OH 3 Examples: How to boot strap the state of an Item

Tags: #<Tag:0x00007fe74006e2d8>

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.

5 Likes

Not really :slight_smile: You can specify “date”, “time” (native controls) or even “datepicker” (Framework7 calendar) as the type in the input widget’s parameters (need a list of options for those), but I don’t think they will output dates in a format accepted by DateTime items by default…

image

image

image

1 Like

Turns out, it doesn’t work too bad, except the time picker doesn’t parse the full date properly - but setting the time works.

If you use datepicker as the type, you have a calendarParams (or calendar-params, see Input Vue f7 docs) and then you can set the calendar options) as you like. Not easy, but it works.

Here’s an example with:

component: oh-input-card
config:
  title: Date/Time Picker
  type: datepicker
  sendButton: true
  item: TestDate
  calendarParams:
    timePicker: true
    dateFormat:
      month: short
      day: numeric
      hour: numeric
      minute: numeric
slots: null

(tip: use the topic filter feature of the event monitor with for instance openhab/items/TestDate to see only those events related to this item).

1 Like

This is the UI that openhab needed!! (the whole UI, not just this widget)

Thank you @ysc for the amazing work on it and @rlkoshak for your endlessly helpful documentation

2 Likes

Clearly I was looking in the wrong place for the list of input types. I never say date or time as options nor did I see datepicker. Given that the set of possible input types is predefined and fixed is it possible to choose from a list instead of needing to look it up and type it in?

Where I seem to have run into trouble is what to put into the “Input Mode”. For example, I tried to experiment with “time” as the input type and I left the mode blank but I didn’t get the UI element to pop up as you show there. I just had --:-- -- which I would click on and type in the hour minute meridian.

Your example with the datepicker with params though works really well.

That heavily depends on your browser and OS. Mozilla has a comprehensive page on that: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input/time
So it could be bare bones or way fancier, for instance here’s how it should look on Android:

Definitely. That’s what I tried to say with:

1 Like