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.
- This function establishes a connection to the database and retrieves class instances from a specific class ("Path").
- If the connection cannot be established, it logs an error and returns an empty array.
- The fetched data is validated to ensure it is an array before being returned.
- If any error occurs during the execution, it is caught, logged, and an empty array is returned.
- 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");
});
});Updated about 3 hours ago

