View SDK API Examples

This page provides examples for interacting with RTDB with View SDK APIs.

1. How to Fetch Class Data ?

Below example fetches class data from RTBD using view SDK Api, in this example we will try to fetch the properties('DisplayName','ServiceStatus','CPU','MEM_Private') of 'Path_Builtin.SysDiag.Process' class and write this data into a simple HTML table.

import { cWidgetBase, IWidgetBaseConfig } from "widgetbase/widgetbase";
import { Components, IProperty, cPropertyType } from "componentbase/common";
import { AddConnectionSupport, IConnectionAPI } from "componentbase/connectionsupport";
import { TFetchClassDataResult } from "client/servertypes";
import { IDbCacheConnection } from "db/cache";


const dataProperties : string[] = ["DisplayName", "ServiceStatus", "CPU", "MEM_Private"];
class FetchData extends cWidgetBase
{
	private conn: IDbCacheConnection = null;
    private Connection: IConnectionAPI  = AddConnectionSupport(this);

	public readonly Mask : IProperty<string> = this.Properties.Add("Mask", cPropertyType.Text,
	{
		DefaultValue: "DisplayName LIKE 'RTDB*'",
		IsBrowsable: true, IsSerializable: true
	});
	private content : HTMLTableElement;

	public constructor(parentelement : HTMLElement, config : IFetchDataConfig)
	{
		super(parentelement);
		this.content = this.DOM.Create("table", { classes: "cDemo_FetchData" }, parentelement);
		this.Properties.Read(config);
		this.Mask.OnChange(this.fetch);
		this.fetch();
	}

	private fetch = async () =>
	{
		this.conn = this.Connection.Get() as IDbCacheConnection;
		const result = await this.conn.FetchClassData(
			"Path_Builtin.SysDiag.Process", dataProperties, -1, this.Mask.Get(), []
		).catch(this.renderfail);
		if(result) this.render(result as TFetchClassDataResult);
	};

	private render(result : TFetchClassDataResult)
	{
		this.content.innerHTML = "";
		for(let i : number = 0;i < result.Data.length;i += dataProperties.length)
		{
			const row : HTMLTableRowElement = this.content.insertRow();
			for(let j : number = 0;j < dataProperties.length;j++)
			{
				const cell : HTMLTableCellElement = row.insertCell();
				cell.innerHTML = result.Data[i + j] as string;
			}
		}
	}

	private renderfail = (errormessage : string) =>
	{
		this.content.textContent = errormessage;
	}
}

Components.Add(FetchData, "Demo.TS.FetchData");

interface IFetchDataConfig extends IWidgetBaseConfig
{
	Mask ?: string;
}

2. How user can subscribe to change in the current value based on the variable or equipment property ID?

This example demonstrates how a user can subscribe to real-time updates of a Variable or Equipment property based on its IDN value, and dynamically display the updated values in a simple HTML table.

This function in the below code snippet generates an HTML table as a string using a flat array of data and a list of property names (column headers). It is designed for scenarios where the input data is a linear list (not an array of objects), and every N consecutive elements correspond to a single row, where N is the number of properties.

export function ShowTable(data:unknown[], properties:string[]):string
{
	let html:string="<table>";
	html+="<thead><tr>";
	for(let propi = 0; propi < properties.length ; propi++)
	{
		html += "<th>" + properties[propi] + "</th>";
	}
	html+="</thead></tr><tbody>";
	for(let i:number = 0; i < data.length ; i += properties.length)
	{
		html+="<tr>";
		for(let propi = 0; propi < properties.length ; propi++)
		{
			html += "<td>" + data[i + propi] + "</td>";
		}
		html+="</tr>";
	}
	html+="</tbody></table>";
	return html;
}

This code below defines a widget class SubscribeChanges that subscribes to real-time changes in the Current Value of Variables or Equipment Properties, using their IDs as identifiers. The subscription is handled via a connection to RTDB , and the resulting data is dynamically rendered into an HTML table.

In this code the numbers [10009, 10010] specifies the ID of a Variable and Equipment Property available in the RTDB.

The array '["Id", "Status", "Time", "Value", "Parent"]' specifies which properties to be accessed from the CurrentValue class.

import { registerWidget } from "@cpmplus/widget-support/register-widget";
import { cWidgetBase } from "widgetbase/widgetbase";
import { Components } from "componentbase/common";
import { TSubscribeChangesResult } from "client/servertypes";
import { IComponentConfig } from "componentbase/propertyapi";
import { IConnectionAPI, AddConnectionSupport } from "componentbase/connectionsupport";
import { IDbCacheConnection } from "db/cache";

class SubscribeChanges extends cWidgetBase
{
  private conn: IDbCacheConnection = null;
  private Connection: IConnectionAPI  = AddConnectionSupport(this);

	constructor(container:HTMLElement, config:IComponentConfig)
	{
		super(container);
		this.Properties.Read(config);
		this.conn = this.Connection.Get() as IDbCacheConnection;

		const properties:string[] = ["Id", "Status", "Time", "Value", "Parent"];
		this.conn.SubscribeChanges
		(
			"CurrentValue",                    // Class name
			properties,                        // Class properties
			"Id IN ?",                         // Masking & sorting
			[[10009, 10010]],                  // IDNs
			(ret:TSubscribeChangesResult) => {
				container.innerHTML=ShowTable(ret.Values, properties);
			}
		);
	}
}
Components.Add(SubscribeChanges, "Demo.TS.SubscribeChanges");

3. How to use Single Value Accessor to get property of any class ?

The code below explains how a user can access current value of any class.

import { registerWidget } from "@cpmplus/widget-support/register-widget";
import { cWidgetBase } from "widgetbase/widgetbase";
import { Components, cPropertyType } from "componentbase/common";
import { IComponentConfig, IProperty } from "componentbase/propertyapi";
import { cCurrentValueAccessor } from "valueaccessors/currentvalueaccessor";
import { cSingleValueAccessorBase } from "valueaccessors/singlevalueaccessorbase";
import { cValueRecord } from "client/data/valuerecord";

class SingleValueAccessorExample extends cWidgetBase
{
	public readonly Accessor:IProperty<cSingleValueAccessorBase> = this.Properties.Add
	(
		"Accessor", cPropertyType.Component, 
		{
			DefaultValue: new cCurrentValueAccessor(),
			IsSerializable: true, IsBrowsable: true,
			ComponentType: "ABB.Mia.cSingleValueAccessorBase"
		}
	);
	
	constructor(container:HTMLElement, config:IComponentConfig)
	{
		super(container);
		this.Properties.Read(config);
		const accessor:cSingleValueAccessorBase=this.Accessor.Get();
		accessor.Changed.AddListener(()=>{
			const vr:cValueRecord=accessor.ValueRecord.Get();
			container.innerHTML=vr.GetValueString() + " " + accessor.Unit.Get();
		});
	}
}
Components.Add(SingleValueAccessorExample, "Demo.TS.SingleValueAccessorExample");

registerWidget(SingleValueAccessorExample);

4. How to navigate to a dashboard based on Node ID?


const ctxBuilder = new cContextBuilder(this);
			ctxBuilder.AddContext(this.Context.Builder());
			ctxBuilder.AddClassInstanceProperty(this.connection, config.Class, config.Id, config.Property);

const navreq = CreateNavigationRequest(`{` + this.TargetDashboard.Get() + `}`, this.connection.GetUri(), false, ctxBuilder.GetContext(), false, true);

(this.ResolveDashboard() as IGUIDashboard)?.NavigateTo.Fire(navreq);

5. How to Fetch Class Instances ?

The fetchClassInstances method is an asynchronous function that retrieves a list of class instances from a database connection. It ensures proper error handling, validates the response, and logs necessary information.

  1. This function establishes a connection to the database and retrieves class instances from a specific class ("Path").
  2. If the connection cannot be established, it logs an error and returns an empty array.
  3. The fetched data is validated to ensure it is an array before being returned.
  4. If any error occurs during the execution, it is caught, logged, and an empty array is returned.
  5. Returns a Promise that resolves to an array of objects, where each object represents a class instance.
    If an error occurs, an empty array ([]) is returned.
async fetchClassInstances(): Promise<Array<Record<string, any>>> {
    try {
        // Establish a database connection
        this.conn = this.Connection.Get() as IDbCacheConnection;
        if (!this.conn) {
            console.error("Error: Unable to establish connection.");
            return [];
        }

        // Fetch instances asynchronously
        const classInstances = await this.conn.FetchClassInstances("Path", -1);

        console.log("classInstances ::", classInstances);

        // Validate that the returned value is an array
        if (!Array.isArray(classInstances)) {
            console.error("Error: classInstances is not an array!", classInstances);
            return [];
        }

        console.log(`Retrieved ${classInstances.length} class instances.`);
        return classInstances; // Return the fetched instances

    } catch (error) {
        console.error("Error fetching class instances:", error);
        return []; // Return an empty array in case of failure
    }
}

//Usage Example: Using .then() and .catch()

myInstance.fetchClassInstances()
    .then(classInstances => {
        if (classInstances.length > 0) {
            console.log("Fetched class instances:", classInstances);
        } else {
            console.log("No class instances found.");
        }
    })
    .catch(error => console.error("Error occurred while fetching class instances:", error));

//Using await in an Async Function
async function main() {
    const myInstance = new MyClass(someConnectionObject);
    const classInstances = await myInstance.fetchClassInstances();

    if (classInstances.length > 0) {
        console.log("Fetched class instances:", classInstances);
    } else {
        console.log("No class instances found.");
    }
}

// Execute
main().catch(error => console.error("Unexpected error:", error));

6. How to get Dashboard Title ?

The below code snippet will the dashboard title based on the Node ID

private getDashboardTitle(node: unknown) {
		return (JS.API("ABB.Mia.GUI.GetTitleFromDashboardNode") as (node: unknown) => string)(node);
	}

7. How to fetch Equipment Information ?

Below code snippet fetches the equipment info and prints it. Call back function will be executed if successful else exception function will be executed.

const equipment_id: string = "e8996cf4-f1a0-468e-9bb2-5a6a67416d0c";
		this.connection.FetchEquipmentInfo(equipment_id, (x) => {
			console.log("Equipment Properties", x.Properties);
			console.log("Equipment Type", x.Type);
			console.log("Base", x.Base);
			console.log("Is Abstract", x.Abstract);
		}, (exception) => { console.log(exception) });

8. How to update 'UpdateHistory' table ?

this.conn.Classes["UpdateHistory"].Instances.Ready.Then(() => {
				const uh = this.conn.Classes["UpdateHistory"].Instances.Add();
				//18 - is the ID of AVG1Month
				//195 - is ID of Stream History
  			// User can pass the required ID
  			// 10590 is the IDN of a Variable
				const hi = this.conn.Classes["History"].Instances.GetInstanceById(18);
				hi.Ready.Then(() => {
					console.log("Name::", hi.Get('Name'));
					console.log("ID::", hi.Get('Id'));
					uh.Set("History", hi.Get('Id'));
					uh.Set("Variable", 10590);
					uh.Set("StartValue", 230);
					uh.Set("EndValue", 1200);
					uh.Set("CallMode", 1);
					uh.Set("Function", 2);
					uh.Set("ItemType", 9);
					uh.Set("StartTime", startTimestamp);
					uh.Set("EndTime", currentTimestamp);
					uh.Set("Comment", "Update from View simulation");
					uh.Set("AllowOverwriting", true);

					// Committing the changes
					uh.CommitChanges();
					console.log("Commit Done");
				});
			});

Did this page help you?