EDIT: Added more content to the editing the JSONDB section
EDIT: Added the “Don’t Wait, Try it Out” section
EDIT: Added autoupdate and persistence sections
This is going to be a relatively sparse set of notes, tips and tricks, and other advice for setting up openHAB 3 through the UI. It will eventually be turned into a full tutorial and perhaps added as an addendum to the Getting Started Tutorial. But I don’t want to wait before getting some of these out in the open. It’s mostly just notes right now but I hope to flesh them out with screen shots and such as time passes.
NOTE: This is not an opportunity to discuss the merits and deficiencies of UI based verses text based configs. If you prefer text based configs, this tutorial is not for you and you probably don’t need one like this anyway. This tutorial is intended to be a resource for UI users who encounter weirdness or are looking for more efficient ways to do things through the UI.
Also, I do not intend this thread to be a place to discuss opinions about whether or not it should be this way. I’ll happily discuss that in other threads or even better issues on GitHub.
I want this thread to focus on OH 3.0 release as it is and how to work with it through MainUI as it is.
If you’ve any tips and tricks please respond in the comments and I’ll add them to the top post.
Don’t Wait, Try it Out!
This one is a pet peeve of mine which I do my best not to drive my replies. But I encounter so many questions here on the forum that could be so easily answered if the users will just try it out. Don’t be afraid to click on stuff. Don’t be afraid to experiment. You will learn way more that way than by coming to the forum and asking a question you can answer just by trying it out.
Buying in Bulk (Items Part 1)
There are times, particularly when migrating to OH 3 when one wants to create or update a whole bunch Items all at once. That’s what the “add Items from textual config” is for. You can define or copy .items file Items definitions into the form and submit and it will add all those Items and Links and Metadata defined therein.
However, you can’t change the name of an Item so if you want to do that, delete the old Item prior to submitting the new one.
Buying in Bulk (Items Part 2)
I imported roughly half of my Items using the above. However, as I started to really work with and understand the model I discovered that it’s actually less work not to try to import my old Items this way. Instead what I do is:
- discover the Things
- from the Model choose “Create Equipment from Thing” and recreate all my Items that way
I’ve found this is faster and easier even than importing all my Items from .items files. And I end up with all the Items properly situated in the Model right out of the gate.
Buying in Bulk (everything else)
One of the big complaints about the UI is all the repetitious clicking around to produce a lot of similar things. For example, creating a lot of similar MQTT Things, applying Expire to a bunch of Items, creating a bunch of similar rules, etc. But you don’t have to do that.
- Create an exemplar using the UI
- Open the API Explorer from the Developer Tools
- Query for your exemplar and copy the JSON
- Navigate to the “create” end point and paste in the JSON
- Edit the JSON for your new instance
- Click submit to create the new instance
- Repeat steps 5 and 6 for all the other similar stuff.
I’ve created a dozen similar MQTT Things in about five minutes with this approach.
You may have to search around a bit. For example, the metadata end points are buried in the Item section of the API.
A Script Error Occurred but the Rule doesn’t tell me what Rule!
The error will include the line of code that caused the problem. Navigate to /var/lib/openhab/jsondb and view the automation_rules.json file. Search for your line of code and you should find the JSON entry for that Rule. From there you can get the UID and Label for the rule which will tell you where to find it in the UI.
Fix the problem in the UI.
[WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: <item name>
This seems to occur mostly when you have a Widget on your Pages that references an Item that doesn’t exist. It might also occur if there is stuff left over after a delete (e.g. an orphaned Link).
Again, navigate to the JSONDB folder. This time run
grep <item name> and it will tell you what files that missing Item occurs in. If the line that is returned isn’t enough to tell you what entity references it, open the file and search. Once you identify the entity, navigate in the UI to find it and correct it.
If deletion operations are not done in the right order Links might become orphaned. If you have some sort of error related to a Link that should not be there any more (see previous section), go to the REST API docs Links section and you can delete the Link from there. You will need both the Item name and the Thing ID. If you don’t have them, grep for the Item name in org.openhab.core.thing.link.ItemChannelLink.json and the line that is returned will include both.
How did I do that last week?
We all end up spending a bit of time figuring out how to do something in a Scripting language, finally get it working, and then a few months later we need to do it again. Only enough time has passed now that we have no idea how we did it nor do we even remember which Rule we did it in.
When you figure something out like that (e.g. creating a Timer, importing a library, calling another rule, etc.), create a Script and paste the example into that. Name the Script something meaningful (e.g. “calling another rule with arguments example”). Then if you need to remember later, you have this nice library of examples built in that you can browse, copy and paste from.
I find it very useful to have these references right there in the UI.
How do I give an Item it’s first value?
Sometimes we have Items whose main job is to hold a constant, or at least a rarely changing value. There needs to be a way to boot strap that state. The approaches are as follows:
events.sendCommand("MyItem", "NewState")or (Rules DSL)
MyItem.sendCommand("NewState"). I think you can even use Blockly but once you type in text Blockly is unavailable. This is a good approach if you have restoreOnStartup and don’t expect to need to change the value again.
Create a System started triggered Rule that updates the Item to it’s first state. Manually run the rule once it’s created to set the Item for the current instance. This is a good approach for when you want to reset the Item’s state on every reload of OH.
Often an Item’s default widgets will allow it to be modified based on it’s type. Open the Developer Sidebar and search for and pin the Item. Click on the Item and if it’s editable with the default widgets you can modify it there.
If the default widgets don’t work, you can create your own default widget that allows it to be edited in the Item’s metadata. The stand alone card is what is shown on the Item’s page itself. The list widget is often how it appears in the automatically generated pages widgets. The cell widget is what appears in the Developer Sidebar. The Input card can be customized to accept date times and free text. See OH 3 Examples: How to boot strap the state of an Item. This is a great approach if this is a value you may want to update again from the UI.
Often it makes sense to represent a given piece of Equipment with a single unified widget. For example a garage door opener that shows the current state of the door and triggers the opener when clicked.
If you are using the model (you really should be) create the unified widget as the default in the Equipment Group Item. Then you can select the widget using “add from model” to your pages and it will drop in the unified widget.
If you’ve more than one of the same type of Equipment, save the widget as a custom personal widget (under the developers tools). Be sure to make use of properties. You can select the custom personal widget when setting the metadata on the Group Item.
Customizing the automatically generated pages
You can change how Items appear on the automatically generate pages by setting their custom widgets. Most of the time it’s the list widget that is used in the cards on the automatically generated pages.
Question: What happens when I set a custom list widget for an Equipment? Need to try that.
Developing Rules Workflow
- open the Developer Sidebar and pin all the relevant Items the the Rule will deal with
- in another tab bring up the -Scratchpad- Script
- in a third tab bring up my Scripts list for reference
- start a tail on openhab.log (some may use Frontail in another tab, I use a terminal and multitail)
- when necessary, instead of pinning the Items I’ll start streaming the events after having set filters so I only see those events I care about; sometimes I’ll bring up the stream on the -Scratchpad- tab
Note that this is not fixed. It depends on the nature of the Items and the rule to be developed. I may not need the Scripts reference. I may want a Page open of a specific Item’s page open.
As I build the logic of the rule I’ll switch over to the -Scratchpad- when I need to experiment or figure something out. When I figure something out, I’ll copy it to a new Script for later reference.
Make liberal use of logging.
If the rule doesn’t depend on
triggeringItemName (Rules DSL), test the rule by clicking on the play button. If you do need the Item that triggered the rule do one of the following:
- create a test Item to trigger the rule with
- from the developer sidebar, Item page, or -Scratchpad- update or command one of the “real” Items that triggers the rule
Always watch the openhab.log for errors and the output from your own log statements.
After I’m satisfied, I’ll check back with openhab.log over time and verify that it’s still working long term and there isn’t some sort of time based error or the like. It’s also a good idea to restart openHAB and verify the rule works correctly after coming back online.
How do I find everywhere X is used?
A typical config will have dozens of Things and hundreds of Items. And these may be referenced from Widgets, UI created Sitemaps, Rules, Links, Metadata, etc. When you delete something that doesn’t go through everything in OH and remove all references to it. So how does one tell where it’s used? Hopefully you remember most of the places it’s used already, but how do you tell it’s really gone?
As with the above, you can grep through all the JSONDB files for the UID of the entity (e.g. the Item name) and find all the files it appears in. From there you may need to open the file and search to figure out more about which specific entity it’s referenced in (e.g. rule UID/Label). But often just seeing which file it exists in is enough to remind you where it’s used. If it’s an orphaned link, see above.
Frankly, unless you are looking to do something like Design Pattern: Associated Items, the names don’t matter. It’s the label that really matters. The label is what will be used to sort alphabetically, it’s the first thing searched for, and it’s going to be more human rememberable anyway. So do focus on coming up with good labels for all your Items and do make sure all your labels are unique and descriptive. But do not worry much about the names beyond that. You hardly ever have to deal with the Item names themselves when working through the UI.
Deleting In Bulk
On any page that shows a list there is a Select option in the upper right. Click on that and then start searching for the ones you want to delete. Check them as you find them. When done the “Remove” option will be at the bottom. It will show you how many of whatever it is you have selected.
However, be careful with deleting Things. You may want to do those individually and to first open the Thing and opening the Channels tab and selecting “unlink all Items” or “unlink and delete all Items” first before deleting the Thing. This gives you the opportunity to delete the Items and Link. Theoretically the Links should be removed when deleting the Things but I’ve found that doesn’t always happen.
Editing the JSONDB, a last resort
You may encounter a situation where the only way to get around it is to edit the JSONDB manually. This should be only considered as a last resort. I just recently had to do this myself.
I have a few “dumb” humidifiers around the house, mostly there to protect my wife’s musical instruments (woodwinds don’t like 15% humidity). So I make them “smart” with a smart plug. Each humidifier is represented by three Items: switch, setpoint, and sensor reading. The Items are named following Design Pattern: Associated Items. But it was not until I had everything set up that I discovered I had a typo in the names for the sensor and the setpoint which made my rule not work.
At this point these Items all have a rule, metadata, links, and UI widgets built around them with the misspellings. Correcting the problem through the UI would not only be a lot of work, but error prone work. My first thought would be to use the REST API (see above) to make these changes but the REST API endpoints for the Metadata makes duplicating the Item with all it’s metadata challenging. Therefore I opted to edit the JSONDB by hand to rename the Item in place.
- stop openHAB
- open a terminal where you can search through the JSONDB files
- I found it works best if you can open the JSONDB files in a tabbed editor where the find and replace dialog can be reused for multiple files. This helps to avoid introducing typos from one file to the next. I used VSCode.
- Search for one of the misnamed Items in the org.openhab.core.items.Item.json file. Adjust your search string to include the full Item name.
- On the terminal search through the other .json files for that Item name to see everywhere it’s referenced. Open all of those files. In my case I had to open the Metadata, automation, Links, and ui_components_widgets files.
- Open every file where the Item is referenced in a separate tab in the editor.
- Now open the editor’s find and replace and put in the Items full current name in the find and what you want to change it to in the replace field. Execute the replace in the Items file. You should do the replace one at a time instead of “Replace all” to make sure you are not accidentally changing Item names that may just happen to include your find string.
- Move to one of the other tabs and repeate the find and replace. In VSCode I just change tab and click the replace icon again and it will start doing the find and replace with the stuff I already entered on the new tab. This helps avoid introducing typos.
- When done, start openHAB and watch the logs and test everywhere the Item was used to verify it all works as expected.
It’s really easy to mess this up so it should only be used as a last resort. Also, don’t try to do too much at once without testing and save incremental backups after each test so when (not if) you make a mistake you won’t have to start all over again.
Also note that you will lose all your historic data that had been saved on the renamed Items. For rrd4j it might be possible to rename the file in $OH_USERDATA/persistence/rrdj4 to recover the persisted data for rrd4j at least. I didn’t try it though as it didn’t really matter for these Items.
This is a tip from @Spaceman_Spiff .
First a couple of facts. First, when a command is sent to an Item, that command often will go out to a device through a binding. This round trip can take some time. Usually the device will change it’s state and report that changed state back to openHAB where the Item is updated. Second, often a command bears little resemblance to the Item’s state. For example, you can send a command INCREASE to a Dimmer, but the Dimmer carries a PercentType as it’s state so the INCREASE will presumably add something to the current Dimmer’s state.
Given the above openHAB has a feature called autoupdate that helps deal with both of these facts. Autoupdate - a primer is a great resource to learn more about Autoupdate. The tl;dr is that when autoupdate is enabled, it will attempt to guess what state an Item will become in response to a command.
Why would someone want to guess like that? Some technologies never report back that it changed state in response to the command. Others might take an extended amount of time before reporting back. The Item might not be linked to a Thing so there is no device to change state. In all of these cases, leaving autoupdate in the default configuration or set to true will be desired or else the UI and the Item state may never change state in response to the command, or do so too late to be useful (e.g. the UI will look like you never sent the command and users might reclick on the control).
But, if you have a technology and device that does report back changes in state in a timely manner, autoupdate should be set to false. This will keep the Item from changing state in response to a command until the device/binding reports that the device has reacted to the command.
You can set the autoupdate metadata by navigating to the Item and adding it as metadata.
But a question arises, how does one tell if the technology supports timely reporting when the device changes state? If you can’t tell based on the docs for the binding and doing a little bit of reading about the technology, perform an experiment! Turn off autoupdate, command the Item and watch the event stream or events.log to see when/if the Item changes in response to the command. If it does leave autoupdate off. If it doesn’t, turn autoupdate back on.
Persistence can be used for a number of things and the best Persistence configuration is different depending on how you want to use it.
This is a profile that will set an Item’s state at openHAB startup to the most recent state saved in the database. This can be great to preserve the state of parameter Items (e.g. setpoints). By default, openHAB ships with rrd4j with a profile to restoreOnStartup for all supported Items.
One problem with a blind restoreOnStartup like that is that it can hide potential problems. For example, if you’ve a temperature sensor with restoreOnStartup and your house loses power and the temp sensor doesn’t come back online when power is restored. openHAB will restore the last temp reading and that restore will not trigger the Expire config. So opemnHAB will chug along with an old and stale reading without knowing there is a problem. Without restoreOnStartup that Item will remain NULL which can be tested for to report problems.
Therefore, instead of blindly using restoreOnStartup on all Items, pick and choose which Items get restored deliberately.
Another problem is rrd54j doesn’t support all Item types. So if you need to restoreOnStartup String Items and other notn-supported Item types, you should use MapDB for restoreOnStartup instead.
Sometimes in a rule it is important to find out when an Item was last updated. Ideally the lastUpdate should be the time when the Item became it’s current state, or when it was most recently updated to it’s current state. But, calling the lastUpdate method will return the timestamp of the most recently saved value in the database. I emphasized that last bit because the lastUpdate may or may not return the timestamp of the actual last update because it depends on when values are configured to be saved to the database. For example, with rrd4j it saves every minute. This is required by the database. But that means you will never get a value returned from lastUpdate older than a minute. If you have the Item configured to be saved on every change instead of every update, you will get the time when the Item changed to it’s current state, even if it has been updated to the same state since then.
So when calling the Persistence methods in a rule, you must have a basic understanding of under what circumstances the Item is saved.
rrd4j is generally a bad choice in cases where you need to call lastUpdate. MapDB using an everyUpdate strategy would be more appropriate. Or if you want to use lastUpdate as lastChange, use an everyChange strategy.
This method will search through the entries starting from the time passed in to present and return true if an Item state was saved in a different state from the current state at any point during that time period. Knowing that MapDB only saves one value per Item should tell you that changedSince will always return true when using MapDB. There are no other entries in the database to show that the Item was different at some point in the past.
Sometimes you may want to get the state of an Item at a given point in time and knowing when it changed to that state is important. In that case you may not want to use a periodic strategy (e.g. everyMinute) because the timestamp will be the most recent record before the time you passed in, not the timestamp for when the Item changed to that given state.
And again, MapDB is not going to be useful for this use case.
Unlike with lastupdate and historic state, with charting you may want to save a value periodically. This is because depending on the graphing package and the time period chosen, if an Item doesn’t have a state saved during the time period shown, or the first value saved is near the end of the time period shown, that Item may not appear on the chart at all or it may sppear half way through the chart time from nowhere. To have a nice line graphed no matter the time period and how often the Item changes state, use a periodic strategy (e.g. everyMinute).
Sometimes one wants even more control over when a state gets saved to the database. In this case you can omit the Item from the .persist file and create a rule. You can then call the
persist method to cause the Item’s current state to be saved to persistence.
Multiple Persistence Engines
Depending on what you want to achieve, you may need to run more than one persistence add-on with a different strategy for each. For example, one might use rrd4j with a custom .persist file (so it doesn’t do restoreOnStartup which it does by default) for charting and MapDB for lastUpdate and restoreOnStartup.
See Design Pattern: Group Based Persistence for one way to make setting this up easier.