Read and Write attributes of item

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.

Best reply by webiq-sk

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);

    };
}());
View original
6 replies