I often find myself in the situation where I’m storing JSON objects in openHAB item states.
For example, a dictionary of available Spotify devices, a dictionary of all network devices, a dictionary of iCloud devices, etc.
This is data that is has a dynamic content (e.g. network devices come and go) and I don’t need/want an OH item for each item in my dictionary. I also find it useful to store more complex data in these objects.
These objects work great in HabPanel, because you can fully access them and their structure to display them in very nice ways.
So, I’m wondering … would it make sense to add “JSON” as a formal data type to OH items? And provide some support to access the properties in rules, etc.?
Anyone else would find that useful?
I also understand that there is a long discussion about tagging and meta data on items to support Homekit, etc. Would this maybe help?
Requiring JSON as an item state is a clear sign of a wrong level of modelling - this is simply not how it is intended and it does not fit into the overall design and architecture, where items are fine-grained individual functions. It probably makes sense to think about encapsulating complex logic into a binding or in rules.
Right, but lots of people use OpenHAB items to store random stuff (e.g. credentials, timestamps) for ad-hoc/one-off integrations, because it’s easy. I bet almost every OH installation has items that are not items in the pure definition. You don’t have to worry about another data persistance layer. It can be accessed from anywhere (scripts, rules, HabPanel, etc.).
In my experience almost everyone users local or global var for this sort of thing, not Items. In fact when I recommend to store such data in Items it comes as a revelation. So I question your user of “lots of people”.
Setting a credential in a String or a timestamp or Boolean flag isn’t going against the architecture and is a recognized and approved use of Items. Such items ARE items even in the pure definition. I even wrote a design pattern that covers that use.
What is not is what you propose, creating an item type whose purpose is to store a whole data structure.
Thanks for your response and helping me understand.
Could I give you an example where I struggle to fit in the current model? Maybe you could point me in the right direction for the appropriate design pattern.
I’ve written a python script that uses the Spotify Web Connect API (a rest API). I script is invoked via rule through HabPanel.
The script returns, amongst other things, a list of playlists (with id, name) and a list of connected devices (with id, name, volume, etc.). I need to store these two lists somewhere so that I can access them later via the script and via HabPanel.
I cannot create OH items for each item in the lists, because it changes (playlists get added/removed, etc.). Plus I don’t think it would make sense for me to create an item for “Playlist_1_name”, “Playlist_1_id”, etc.
So what I do is store the dictionary in an OH item called “spotify_playlist”. It gets persistet, restored upon reboot, and most importantly, I can easily access it through HabPanel because it’s just another item.
What would you propose to store these two lists/dictionaries?
As @kai pointed out, I may consider writing a binding instead of a pything script. Fair point, and I intend to give that a try. It’s still not clear where I could store this data so that it is accessible in HabPanel.
Thanks again for your help! It’s much appreciated.
I hope I didn’t offend anyone with my proposal I did not intend to dilute the quality of a great piece of software.
I may be wrong, but it sounds to me like your scenario is mostly “get information from ‘some external system’ and show it on the UI”, meaning you may not need the information to be available to the openHAB rule engine?
The reason I ask is that I have come across a few similar situations myself over the past year. When considering these situations I have often thought that it would be nice to be able to present content from a database (typically MySQL) directly in the UI (without the help of items).
I have only briefly worked with HABpanel so I am not very familiar with this UI, but based on what I read it seems very flexible so I presume access to MySQL is possible.
What is your view on this; a Python script writing to MySQL and HABpanel reading from MySQL and presenting it is a nice list?
There was already some work on a Spotify Connect binding (see here) so maybe it would be more pragmatic to try and improve the current PR (to include things like playlist selection) than hack around storing these structures in an Item.
I have actually just started to use Json for some items from the Z-Wave binding, so this is an interesting discussion. Currently, the item model only allows a single “bit” of information, and if we want to store more information, we need to use multiple items. This has the drawback that the user then needs to correlate this information again, and this requires that the user knows exactly how the binding will send this out (ie the update order of each item).
An example of this is if we open a door - the lock state changes to OFF, but we might also want to provide other information such as the user who opened the door or the way in which it was opened (eg keypad, physical key or remote). Currently I see two ways to handle this - either to encode these three bits of information into a single item (and encode in Json or another format), or we split the information into 3 separate items.
If the information is just for display in the UI, then 3 items is fine. However, often this information is needed in rules, and if the data is split into 3 items (door state, user code, unlock method) then for the user to make use of this, they need to correlate the data with a single event to avoid the situation where the lock state is correlated with an incorrect user (eg from a previous unlock event). This is not straight forward (IMHO) as the update of the 3 items needs to always be in a specific order, and the user needs to know that order - to me that’s not a nice dependency.
I would have liked to have seen items having properties/attributes (maybe this is the wrong name) such that we could have the above item as a Switch to reflect the lock state, but secondary data (such as the user and method) can be added and accessed directly within the item - eg we might have the item LockState, but we access the user information as LockState.user or LockState.property("user").
Maybe there’s alternative ways that this sort of thing can be achieved and someone has some nice suggestion other than encoding in Json .
I wasn’t aware that there was a Spotify binding PR, so yeah, it makes sense to improve it - although what you call “hacking around” is part of exploring and playing, so i’ll keep doing that as long as I have fun with it
Spotify playlists was just one example I was providing to illustrate the need to store more than simple states. Maybe items are the wrong place, so I’m happy to hear about suggestions on where to store this information instead.
@KjetilA - yes, that is true, although sometimes it’s also usefull to access those values in rules etc. What I appreciate about storing JSON in items is that it works out of the box. I don’t need another persistance layer or exposure to HabPanel.
Again, if there’s a better (and equally simple) way to do it, I’m all ears!
Interesting! This reminds me of a question/comment I made in another thread a long time ago, where I asked for some kind of concept of meta-data related to items.
At that time my focus was on time stamp information for “last update” and “last change” of an item state. As this information is clearly available to the core (event bus), I find it a bit strange that we need to go through rules and/or a persistence service to get access to it, e.g. for the purpose of displaying it on the UI.
My reading of the concept of Channels is that the architecture would prefer separate Items in this case.
I completely agree. Can the event bus even guarantee order or is I multithreaded?
This would make the exec 2 binding a lot more intuitive to use, that’s for sure.
I think it is clear that the sitemap based UIs are very inadequate in some areas:
date time entry (e.g alarm clock)
display of multi line data
display of data from multiple items on the same line
multiple controls on the same line
HABpanel has fewer of these problems with it’s templating system, but creating a JSON Item would only be applicable and useful for HABpanel. And I would bet even the majority of HABpanel users still have sitemaps to drive their phone apps.
No matter the solution, if one is attempted, sitemaps should be included. And I would rather see a compressive and well thought out generalized approach than a bandaid approach which a JSON Item feels like to me.
Finally, I love the conversation here and encourage it’s continuation. But everything we are discussing would be implemented in the core so a similar thread should be started on the ESH forums.
That looks like it’s going to take a while before (if at all) any enhancement would be implemented.
So, back to my practical question, if I enhance the Spotify Binding or create another one and would like to store a list-type information (e.g. “Available Playlists”) that I then use in HabPanel to show to the user, what would be the recommended place/way to store it in the current version of OH?
I can’t really say without seeing and getting my hands into the code and whatnot, which I don’t have time for.
You have more flexibility with HABPanel than the sitemaps. Remember that any binding that gets added as an official binding will have to support both.
I’m not sure if it is kosher or not for a binding to create Items on the fly. I know there is the REST API to do that so it is technically possible. Maybe a playlist group and collection of dynamically created and destroyed Items for each song in the list. There are problems with this approach but it might be a start.
Really hope you didn’t take that the wrong way! Exploring and playing is probably what got most of us here , I was just trying to make you aware that you may be reinventing the wheel so-to-speak and trying to guide your effort.
Going on what you’ve described so far I would model a “Playlist” channel as a dynamic channel (I’m assuming you’re talking about user-created playlists and not all playlists on Spotify) that gets populated during run-time. Each playlist found would become an option for that channel.
This would then render like the “Repeat Mode” channel in the screenshot below.
In this case, the binary object IS the state. And while an Image is internally a data structure with a header and pixel information, it still represents only one thing. It isn’t a data structure that OH parses and converts to other Items or something like that. The image is a self-contained whole and therefore is a perfectly reasonable state.
Just to add to this - my Russound binding also has a number of JSON channels (carried in string types) that are used to support HABPANEL implementations. The JSON channels simply carry additional information that UIs would be interested in and are not required to correctly operate the binding. I would have loved to see either a JSON/Dictionary/Collection/List types would be incredibly useful for more advanced UI implementations…