Dear Community User! We are updating our platform to a new system.
Read more: Important information on the platform change.

cancel
Showing results for 
Search instead for 
Did you mean: 
SOLVED

itemManager Methods and documentation request.

itemManager Methods and documentation request.

MrAdam1983
Long-established Member

I cannot sem to find the documentation that actually list the methods inside the itemManager API, I have run a report out of the API but I am still not able to complete the task i am after. 

I need to read the "Value" of data source assigned to "item2" in my Custom Widget. Since "setValue" allows me to write a value (1 or 0) to a connection through "Item" I assumed "getValue" value would read teh connection on "Item2" but I countine to get errors in the debug that it is not a function. I have tried the following and recieved either the same error or i just get nothing. 

.getValue

.data.

.getItemvalue

.Values

.valueOf

My project in it's current state is attached if that helps, maybe i am using the wrong syntax?  I am trying to assign a tag in WebIQ interface and then use the value of that tag (1 or 0) to set the "state" of my button with differnt svg. files. I know I will need to subscribe to the data in a finale iteration but I just wanted to get it functional first. 

8 REPLIES 8

AndreasL
New Contributor

Hello,

The api documentation is avaiable from here (requires login on the WebIQ - page):

https://www.smart-hmi.com/user/download/deliver/docs/documentation-webiq-visuals-reference-2.14-3d30...

And the readValue method is probably what you want

webiq-sk
Frequent Contributor

readValue only returns the last value read by any widget or script, not the current value, you have to use readDirect for non-virtual items to get the current value.

MrAdam1983
Long-established Member

I need some additional insight into using the im. methods for reading values.  I have "Item" and item2" defined and I have even gone as far as defining their type in my java.  If I inspect the console in my browser I am able to output the methods and properties associated with the datasources that these two items are connected to. 

MrAdam1983_0-1692734285687.png

 

if I look at just "self.config.item" the console output displays the "name" which is the Tag i have the property pointed at in WebIQ.  If i go beyond that at all; .value, .formattedValue, .readDirect, and even .name I get an output of "undefined".  So that means that if i am trying to read the value of the datasource in my js code, nothing comes across unless I am only look at the item directly and then that is not the infomration I want. 

However, I know for a fact that I can use "self.imports.im.setValue(self.config.item, 0);"  to write a value, in this case 0, to the datasource assigned to "item" with code logic.  I am using "item" as my command tag, and "item2" is my status coming back from the PLC (at this moment both properties are pointed at the same tag) and this is a momnetary push button. So, press and release work and I can watch the value of the external datasource ( the tag) change.

BUT, I cannot read that value, in order to trigger a subscription, with my js code.  Everything i see suggest that item.value shoudl get me exactly what I want. So, either there is some configuration on the data source I need to do, there is an alter method for this, or .....????

I am including my project, I would be happy to look at any sample code but I have not found a example of this yet. seems like I have been picking alot up from going through other code though. 

this works

MrAdam1983_2-1692735752294.png

this does not work

MrAdam1983_3-1692735791326.png

 

 

webiq-sk
Frequent Contributor

The easiest solution would probably be to simply download our Scripting Demo right from inside WebIQ Designer and see how it's done.

MrAdam1983
Long-established Member

After spending 2 days on this, looking at the scripting demo, figuring out how to dig into the objects provided in WebIQ designer, and trying a ton of different methods I am condifent when I say the itemManager does not contain a method that will do what I need. 

The function I am after comes down to being able to monitor an external data source for a value change.  I am defining "item2" as a integer, I have gone as far as making sure I can define it as such in the UI properties (learned a lot there, pretty cool how I can manipulate the WebIQ UI), I have defined the type in my JS and I even considered doing it in my json but I don't think that would matter. There is no problem in interacting with external values as Integers at the UI level, my button press and release work exactly how I want them to.  I am not saying I cannot read tag values at all, I just can't seem to do so in inside the js. The issue is that internal to the js code, there is no way to access the .value of an item and read that as an integer.

I can subscribe to "item" in my code, and I can console output the name of "item" with just "self.config.item".  The result of this is the TAG or PLC address I have assinged to this property in WebIQ. If I try to access any other property of that item inside my code the console output is "undefined". it does not matter what I try to access, the value, the name, anything, it's "undefined".  so again, there is not a method in itemManager that allows this interaction. 

But then I go back to the fact that I can use .SetValue to write a value to my external tag based on a press and release action; it seems odd that this is able to get the data to the property of the Item it needs to with no additional information.  And, ok, .setValue works so based on my reading the common opposite of that would be .getValue.  NOPE, not a support function/method. So, there is some magic going on in the background becuase we can infact manipulate the value of an item in some manner. Another example is the iq-input-field, which I pulled some useful code from; this widget updates it's displayed value live, but i cannot find anything in it's js that does this. Magic...

Now, I don't actually need to know the Value inside my code, i just need to know that the value changed.  But again there does not appear to be any methods for this operation.  .onChange, .onValue, .valueChange.  nothing in the common venacular that I can find online works. 

Furthermore, I have scowered the supplied documentation in WebIQ Visual and there is absolutly NO discussion of any such similar behaviors; at least not that i can find. 

I am 3 weeks into this and honeslty, this should have been a functional widget last friday; everything since then has been focused on this one behavior I am after.  Trigger an svg change based of the value of a external tag.  and i cannot sit here and believe that I am the only who has or will want to do.  to be prefectly honest, i don't understand why this does not already exist on the standard widgets. Why?

We use this behavior now as a diagnostic (not to mention that FacotyrTalk View studio has been able to do this since the days it was called RSview), we do not condition our indicators from the HMI itself, we condition them from the PLC and ONLY if the required logic completes. We are an OEM and we have found this to be a huge benefit for anyone trying to diagnose a problem.

"the arm didn't move"

"when you pushed the button, did it light up?"

"Uh, no..."

"then the logic never functioned, there is a condition not met."

SO, Either my lack of knowledge in this area is preventing me from finding the methods I need to complete the task I am after.... not unlikely.

OR.

The itemManager API, supplied by smart-HMI, does not contain common methods that Bing and ChatGTP are both confused about not being present. 

and yes, I am using AI to work through this.  I have accomplished more in the last 3 weeks using AI to check code and provide alternatives than using anything in this forum has.  That is not to say that this forum is not helpful, but the benefit to a non-human interaction is the speed at which it can provide answers. 

Way Faster than any Forum ever could. There is no way i could have accomplished much as a i have with this project without the use of AI. That does not mean I said "write me code for this"  though i have purposed concepts to it to see if the code was helpful in anyway (most wasn't).  No, for the most part i have used it as a validator that I can talk to directly to explain the task i am trying to accomplish.

Anyways.

How do I read the properties of an Item and how can I monitor an item for a value change?

Is there another API I can use?

Can i add to this one? ( that sounds terrifying)

 

I am again including my project.  I am going to take the rest of the week to step away from this as it has consumed me, but i will check responses here.  Line 231 will error when compling becuase the method .onValueChange is invalid.

webiq-sk
Frequent Contributor

"The issue is that internal to the js code, there is no way to access the .value of an item and read that as an integer."
Sure there is - there are two ways available:
1. When you only need a one-shot read: readDirect
2. When you want to react to continuous item changes: subscribeItem

Here is the corresponding code from the scripting demo ("demo-item-subscribe") that illustrates this:

 

        // Define our item names to use - it's best to put them here and not somewhere in the code below
        // for easier changeability and understanding
        const observedItemName = 'ls-observed-item';

        // See below
        let subscriptionToken = null;

        // Get a reference to the ItemManager
        const im = shmi.requires("visuals.session.ItemManager");

        // Create a new instance of an item handler to use and define a function that will be called
        // asynchronously by the framework whenever the item value changes (or is received initially)
        const myItemHandler = im.getItemHandler();
        myItemHandler.setValue = function (value) {
            console.log("[LS demo-item-subscribe] The value of the item has been set to " + value);
        };

        // Obtain a subscription token. You ALWAYS have to store this token and call the appropriate unlisten function
        // when you no longer need it, in this case when the LocalScript will be disabled (see below)
        // If you do not do that this will likely cause memory leaks (https://blog.logrocket.com/escape-memory-leaks-javascript/)
        // leading to more and more RAM used in your HMI until the amount of free RAM will be exhausted and the browser will crash
        // The WebIQ Visuals framework always calls the onDisable function automatically when your LocalScript should not be running anymore,
        // e.g. when it has been included in a screen view and the user switches to another screen.
        subscriptionToken = im.subscribeItem(observedItemName, myItemHandler);

        /* called when this local-script is disabled */
        self.onDisable = function () {
            if (subscriptionToken) {
                subscriptionToken.unlisten(); // Remove the listener and tell WebIQ Server to stop sending us item updates
            }
            self.run = false; /* from original .onDisable function of LocalScript control */
        };

 

And if your item does not have the type integer in your PLC you can of course cast it with JavaScripts parseInt() method into an integer value.

webiq-sk
Frequent Contributor

And tis one is from the same demo's demo-item-readdirect UI Action:

        actions["demo-item-readdirect"] = function(parameters) {

        // Give it a meaningful name for better readability
        // Parameters to UI Actions are made available in the code as an array.
        // Here we only require the first parameter (which is at index 0)
        const itemName = parameters[0];

        // Get a reference to the ItemManager
        const im = shmi.requires("visuals.session.ItemManager");

        // Execute a readDirect - please note that this is an asynchronous call and code
        // that should run after the read has been completed has to run inside the inline (anonymous)
        // callback function shown below.
        // If you'd write another code line after the "im.readDirect" call it would be executed immediately
        // after the asynchronous readDirect has been started but very probably not ended
        im.readDirect([itemName], function(err, result) {
            if (!err) {
                console.log(result[itemName]);

                shmi.notify("readDirect result: " + itemName + "=" + result[itemName], "ReadDirect Result");
            } else {
                shmi.notify("readDirect failed: " + err, "ReadDirect Error");
            }
        });
    };

MrAdam1983
Long-established Member

@webiq-sk wrote:

"The issue is that internal to the js code, there is no way to access the .value of an item and read that as an integer."
Sure there is - there are two ways available:
1. When you only need a one-shot read: readDirect
2. When you want to react to continuous item changes: subscribeItem

Here is the corresponding code from the scripting demo ("demo-item-subscribe") that illustrates this:

 

 

        // Define our item names to use - it's best to put them here and not somewhere in the code below
        // for easier changeability and understanding
        const observedItemName = 'ls-observed-item';

        // See below
        let subscriptionToken = null;

        // Get a reference to the ItemManager
        const im = shmi.requires("visuals.session.ItemManager");

        // Create a new instance of an item handler to use and define a function that will be called
        // asynchronously by the framework whenever the item value changes (or is received initially)
        const myItemHandler = im.getItemHandler();
        myItemHandler.setValue = function (value) {
            console.log("[LS demo-item-subscribe] The value of the item has been set to " + value);
        };

        // Obtain a subscription token. You ALWAYS have to store this token and call the appropriate unlisten function
        // when you no longer need it, in this case when the LocalScript will be disabled (see below)
        // If you do not do that this will likely cause memory leaks (https://blog.logrocket.com/escape-memory-leaks-javascript/)
        // leading to more and more RAM used in your HMI until the amount of free RAM will be exhausted and the browser will crash
        // The WebIQ Visuals framework always calls the onDisable function automatically when your LocalScript should not be running anymore,
        // e.g. when it has been included in a screen view and the user switches to another screen.
        subscriptionToken = im.subscribeItem(observedItemName, myItemHandler);

        /* called when this local-script is disabled */
        self.onDisable = function () {
            if (subscriptionToken) {
                subscriptionToken.unlisten(); // Remove the listener and tell WebIQ Server to stop sending us item updates
            }
            self.run = false; /* from original .onDisable function of LocalScript control */
        };

 

 

And if your item does not have the type integer in your PLC you can of course cast it with JavaScripts parseInt() method into an integer value.


I am sorry for the things I said while i was pretending to be a programmer.

this was certainly the fix for everything i was fighting. i had tried to implement this yesterday but must have really messed it up.  my second attempt today went much better. it works, does exactly what I need it to do.  I am now in the refinement process and will start add additional features.  i appropriate the guidance. 

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist