I’ve seen a few old posts asking this question, sort of. But no relevant solutions.
I am creating a widget that populates various fields based on a single item.
This is a light widget that can control a number of different light types: on/off only, CCT, RGBWW, some have illuminance threshold and motion on/off controls, some have auto off timers etc etc.
“Lamp” is the only prop that is set.
Then various list-items and sliders etc use an expression similar to
=props.lightItem + "_Brightness"
This is working well and everything is doing the right thing.
The problem I have is that there are various parts that will only sometimes have an item to refer to.
I think this is slowing down the page load where I have 14 of these widgets. Feels like it is fully searching everything before erroring, and my log is filled with all the items that cannot be referred to. Everything is snappy and functional once loaded.
When you create a new widget, the default code has an example that checks if a prop is present,
If I were doing something like this in a rule, I might define each “multi purpose Item” as a Group, which could have more or less members of different function.
A rule can then work on the Group, examine if it has a “X” type member and only do X type things if so. It’s getting the member list to examine, rather than inducing a “failure” by trying to retrieve Item “X” which may not exist.
I’ve no idea if such an idea is useful in widget work.
It uses a real pure object underneath along with a “tracking list” so when you require the state of an item that isn’t currently on the tracking list, it will involve an API call that will update said tracking list for the associated SSE connection. This happens automatically and in batches within the same “tick” (like when upon a page change requests several items’ states are requested at once).
This allows to keep the network traffic for state updates to a minimum - only the state update events for the items in the tracking list that are actually needed are sent.
So in short, you can’t really check whether an item exists by examining the keys in that object because it’s not a real dictionary and doesn’t contain keys for every item, rather it builds itself dynamically depending on the keys that are accessed.
Null and Undef items do return 'NULL' and 'UNDEF' strings, so it appears that '-' is reserved for the times when the widget just plain cannot get a state (which now makes sense thanks to Yannick’s explanation), and for most cases that situation is because the item doesn’t exist.
There’s a lot that can be done with Proxy objects, but it can be a two-edged sword since every operation could be more costly than expected. But in some cases this can be a good solution since these costly operations would only be carried out if they are actually requested. The “does it exist?” operation could be one the these, but it would be one of these costlier operations since it would involve an API call.
For example I pretty much buried Expose full item info to widgets by asmigala · Pull Request #1180 · openhab/openhab-webui · GitHub because while it’s a good (and often requested) idea, its suggested implementation involves calling the API for every item that is being included in the tracking list. I suggested the author to consider using Proxy objects for the item states objects themselves, so that when you request item.MyItem.category or items.MyItem.label it will gather the info from the API - but as needed, not as a general principle. I have learned from making HABPanel and HABot that when you request too much info (like a blanket /rest/events SSE connection) this will potentially kill your battery in 2 hours if you happen to be on a phone or tablet.
I admit I’m naive on a lot of aspects of this but it seems to be that it would only involve one API call sometimes.
If the Item has already been cached in the tracking list by the proxy because it’s already in use somewhere else on the page no API call would be needed.
If the Item truly doesn’t exist, the first time an API call would be used and then the fact that the Item doesn’t exist could be cached in the tracking list as well. So there’s only be the one API call for each non-existing Item (until the page is reloaded again).
That doesn’t seem like too much of an impact over the long term, though I could see it slowing down the page when it’s first loaded which could be too much. It would also require a page refresh to pick up changes (e.g. a non-existant Item is created after the page was loaded). But I don’t know what I don’t know.-
Since the non-existing Item isn’t in the tracking list, would not this approach have the same problem with causing an API call each time the widget refreshes?