FORUM CTRLX AUTOMATION
ctrlX World Partner Apps for ctrlX AUTOMATION
11-25-2022 04:08 PM
@webiq-eg Can you please provide an JS example how to read and the attributes (digits, min, max, label,...) of an existing item. I tried to do it, with the help of the documentation (shmi.core.Item & shmi.core.ItemManager), but I failed.
Solved! Go to Solution.
11-28-2022 12:16 PM
Hello HmiGuide,
the attributes are obtained via the callback function when I subscribe to an item:
(function() {
var actions = shmi.pkg("visuals.session.userActions"); //get reference to userActions object
/**
* UI-Action 'get-item-attributes' implementation
*
* @params {any[]} parameters configured ui-action parameters
*
*/
actions["get-item-attributes"] = function(parameters) {
//Place your code here
const item = parameters[0];
if (item) {
const im = shmi.visuals.session.ItemManager,
tok = im.subscribe([item], (name, value, type) => {
console.log(`New value for item '${name}': ${value}`);
}, (name, properties) => {
if (properties.initialized) {
shmi.notify(JSON.stringify(properties, null, 4));
tok.unlisten(); //... when subsription is no longer needed, unsubscribe:
clearTimeout(timeout);
}
console.log(`Properties changed for item '${name}': ${JSON.stringify(properties, null, 4)}`);
}),
timeout = setTimeout(() => {
tok.unlisten();
shmi.notify(`TIMEOUT ERROR: Item ${item} does not respond!`)
}, 1000);
}
};
}());
I have attached a small WebIQ HMI project to try out.
Hope that helps?
Many greetings
webiq eg
11-29-2022 10:20 AM
Thanks for the example. It's working, but only when the item is NOT subscribed (=used on the screen).
I checked to documenation again, and implemented the solution below.
// get properties of item
const im = shmi.visuals.session.ItemManager
let item = im.getItem("SInt")
if (item) {
let prop = item.getProperties()
console.log(JSON.stringify(prop, null, 2))
} else {
console.log("getProperties failed")
}
One question is not answered: Is it possible to write/change the attributes at runtime (with shmi functions, not via API functions).
11-29-2022 02:45 PM
@HmiGuide WebIQ has a subscription-based model, so your implementation will not work every time.
Here is a working version:
/**
* Custom UI-Action 'readItemProps'.
*
* Description:
* [Add description here]
*/
(function() {
const actions = shmi.pkg("visuals.session.userActions"); //get reference to userActions object
/**
* Reads properties of an item.
*
* @param {string} itemAlias Alias of the item to read the properties of.
* @param {?AbortSignal} signal Abort signal to cancel the operation.
* @returns {Promise<object>}
*/
function readItemProperties(itemAlias, signal = null) {
return new Promise((resolve, reject) => {
const { ItemManager } = shmi.visuals.session,
itemAlreadyExists = (ItemManager.getItem(itemAlias)?.type ?? null) !== null;
let token = null,
done = false,
callbackReady = itemAlreadyExists,
/** @type {() => void} */
onAbort;
/**
* @param {string} text
*/
function onError(text) {
if (done) {
// We are already done.
return;
}
token?.unlisten();
token = null;
done = true;
signal?.removeEventListener("abort", onAbort);
reject(new Error(text));
}
/**
* @param {object} result
*/
function onDone(result) {
if (done) {
// We are already done.
return;
}
token?.unlisten();
token = null;
done = true;
signal?.removeEventListener("abort", onAbort);
resolve(result);
}
onAbort = onError.bind(null, "aborted");
signal?.addEventListener("abort", onAbort);
token = ItemManager.subscribe([itemAlias], null, (name, properties) => {
if (done) {
// We are already done.
return;
}
if (properties.type === null && callbackReady) {
// Subscription has been terminated by WebIQ Server and we
// haven't gotten our properties yet. Assume the item has
// failed.
onError(`Item ${itemAlias} not found.`);
return;
} else if (!properties.initialized) {
// Properties are not initialized yet.
return;
} else if (properties.type === -1) {
onError(`Unable to read properties of item ${itemAlias}.`);
return;
}
onDone(properties);
});
// Allow properties callback to fail when type is null.
callbackReady = true;
// Check if the properties callback has already been called. This
// can happen if the item was already subscribed before. We now
// need to cleanup the token because it wasn't available to the
// callback.
if (done) {
token?.unlisten();
token = null;
}
});
}
/**
* UI-Action 'readItemProps' implementation
*
* @params {any[]} parameters configured ui-action parameters
* ---- Initial parameters, needs to be updated manually when changed ----
* @param {string} parameters[0] Item
*
*/
actions["readItemProps"] = async function(parameters) {
//Place your code here
const itemName = parameters[0];
const props = await readItemProperties(itemName);
console.log(props);
};
}());
11-29-2022 02:55 PM
Thanks for your adapted script. I do prefere the solution without subscription. It's much easier than with subscription.
I'm still wait for the statement (and example) if it is possible to adapt the attributes. (See message above)
11-29-2022 03:25 PM
Actually your solution only works when the item is currently subscribed or has already been subscribed before. If you're getting data with the item not being subscribed anymore the data returned will be outdated.
There is no other way than using the asynchronous method simply because the underlying call has to be asynchronous because the data will be retrieved asynchronously from the server via the WebSocket connection.
There simply is no synchronous way of getting the current data of any item.
11-29-2022 03:26 PM
Modification of attributes from the HMI is not possible at runtime.