Intro
There is a perennial problem that has been with us since the beginning. Sometimes an Item will have a state that is relatively static and is essentially hard coded. There are multiple ways you can deal with this problem including:
- create a System started rule to populate the Item with it’s state; if you use restoreOnStartup you can even remove the System started rule after the first run
- update the Item using the Karaf Console with smarthome:update
- update the Item from the REST API Docs
- I even wrote a script that would initialize Items based on metadata
All of these options are OK, but now in OH 3 there is a new way which is way more powerful and flexible.
NOTE: I’m going to show how to do this through MainUI. MainUI will create some metadata on the Item to tell it how to render the widget for the Item. If you want to stick to .items files, you will have to look at the code that is generated to figure out how to apply it in your .items files.
Example Problem
I’m porting my Time of Day rule from Python to JavaScript using the MainUI to create the rules. This rule relies upon a series of DateTime Items to define the start times for the various times of day as well as Item metadata to define what type of day it applies to (e.g. morning time could start later on weekends and holidays).
The rule doesn’t know nor does it care how the Item gets its states. In a typical configuration some of the DateTimes will be driven by the Astro binding. Others might be hard coded. We need a way to set the hard coded times.
The Default Widgets
MainUI tries to create a lot of the UI for you automatically based on your Items, the Model, and Item metadata. You can influence how the Item is automatically rendered by setting default widgets on the Item. One of the places where the default widgets are used, and the place we care about here, is on the Item’s page itself.
In the above you will see I have a DateTime Item named Holiday_Night. It doesn’t have a state yet (notice the NULL). So where does that “NULL” come from anyway? Can I change how that widget is rendered? The answer is “yes!” That is the “Default Standalone Widget” which you will find near the middle of the list of predefined metadata entries.
Click on that and you will be presented with a preview of the widget and a menu Item to select what sort of widget you want to use as the default.
Click on “Widget” and select “Input Widget.” If the Item were of another type you can choose the appropriate widget for that type (e.g. a knob for a thermostat setting).
This opens up a form where you can start to customize the widget. In our case we will set:
- title: Holiday Night
- footer: =items.Holiday_Night.state
- input type: datetime-local
- input mode: text
- placeholder: hh:mm:ss
- send button: toggled on
- outline: toggled on
- validate: toggled on
NOTE: input mode defaults to text so that isn’t really needed. The placeholder is a reminder of what to enter. For time of day we don’t care about the date so only the time needs to be entered using 24 hour time. Starting any field with =
starts a formula where you can calculate the state based on Item’s state. In this case we just use the state. The javascript ternary operator (condition) ? true value : false value
comes in handy here.
The code itself is:
value: oh-input-card
config:
outline: true
inputmode: text
footer: =items.Holiday_Night.state
placeholder: hh:mm:ss
title: Holiday Night
type: datetime-local
sendButton: true
validate: true
You will see you changes rendered in the preview at the top. Click save and you will see a live view.
Enter the time you want to initialize the Item with and click the checkmark to the right and the Item will be updated to that time. You will then see the Item’s new state in the footer of the card.
Because we didn’t specify a year/month/day it defaults to epoch. That’s fine as the rule deals with updating it to today when it runs.
Now what?
That seems like a lot of work just to initialize the Item. And that’s true. But now if you want to change it to something else in the future you can just return to the Item’s page, enter the new time and click the check to apply it. If this Item is part of the Model, you can add the Item to a Page using the “add from model” option and the widget you just defined will be used by default (if it isn’t you will have to redefine the widget as shown above).
One of the really nice features is if the Item is part of the Model, *it has already been added to your Pages." But it might have been added as a part of the List in which case you would need to define the default List widget similar to the above using the Input List Widget.
Conclusion
Not only do we now have a way to enter DateTime and text (I think Yannick is even working on a DateTime picker widget) now but if we spend a little bit of time building the model, we won’t even need to build the UI itself. Though much of that work that is saved building a sitemap will be spent creating default widgets for the relevant Items.