Virtual Item - String - Default Value

Every Item already has an easily detected default state (NULL).
Outlined above are several ways to work around that, if you want something else.

Not generically, but my Scripted Automation implementation of the Time of Day Design Pattern implements something like this. [Scripted Automation] Multi-day Time of Day Library

I’ve been deciding whether to extract this and make it generic. I’m hesitant to do this though because I fear it will be used in less than ideal ways. NULL and UNDEF are states that should be embraced and used, not avoided at all costs. But I also recognize there are times when you need to boot strap the state of an Item when it’s first created.

EDIT:

I’ve not tested this but it’s simple enough that it should work.

from core.rules import rule
from core.triggers import when
from core.metadata import get_key_value,remove_metadata
from core.utils import postUpdate, post_update_if_different

@rule("Initialize configured Items",
      description="Updates Items with an initialization value",
      tags=["init"])
@when("System started")
def item_init(event):
    """
    Rule that triggers at System started and populates Items with an initial
    value. The initialization value is defined in metadata with three key/values.
        - value: value to send update the Item to
        - override: whether to update to this value even if the Item already
            has a value. It's an optional key and should be either absent,
            "true", or "false"
        - clear: whether to delete the metadata once the Item is updated. It's
            an optional key and should be either absent, "true", or "false"

    For example:
        - { init=""[value="ON", override="true", clear="true"] }: Initialize
            the Switch Item to ON whether or not it already has a value and then
            delete the metadata.
        - { init=""[value="123,45,67"] }: Initialize the Color Item to the value
            only if it is NULL or UNDEF.

    Limitations:
        - The clear option only works for Items not created through .items
            files. For Items defined in .items files, you must manually remove
            the metadata or else it will get reloaded next time the file is
            loaded.
    """

    for item_name in [i for i in items if get_key_value(i, "init", "value")]:
        value = get_key_value(i, "init", "value")

        if get_key_value(i, "init", "override") == "true":
            post_update_if_different(i, value)
        elif isinstance(items[i], UnDefType):
            postUpdate(i, value)

        # only works if Items are not defined in .items files
        if get_key_value(i, "init", "clear") == "true":
            remove_metadata(i, "init")

I’ll probably submit it to the helper library at some point. But I’ve already a bunch awaiting merge so I’m holding off submitting new ones right now.

Hi @rlkoshak
Have you submitted your idea?
thanks

No, not yet. All my PR’s are still awaiting review and merging so I’m waiting for that to happen first.

Hi Rich,

Do you know, how to access the multi-value metadata from JS? The API method (getMetadataValue items/managed.js - Documentation) does not provide a second attribute …

item definition:
Switch Notification_Setting_FrontGate “Front gate is opened for a longer time” (gNotificationSettings) { Static=“meta”[ after=“30”, interval=“30”, channel=“3”, createOHItem=“true” ] }

Script (ECMA 2021):
let it = items.getItem(“Notification_Setting_FrontGate”);
let sett = it.getMetadataValue(“Static”, “”);
console.log("NotificationSettings >> " + sett);

The console logs the “meta” only.

It appears that the library doesn’t support that at this time. It only gets and sets the value. You’ll have to get it the MetadataRegistry and pull that yourself.

It would look something like this:

let MetadataRegistry = osgi.getService("org.openhab.core.items.MetadataRegistry");
let Metadata = Java.type("org.openhab.core.items.Metadata");
let MetadataKey = Java.type("org.openhab.core.items.MetadataKey");

// Get the full metadata object
var meta = MetadataRegistry.get(new MetadataKey("debounce", itemName));
var after = meta['after'];

Rich, excellent! Thank you for the quick help and also for the idea in your post :slight_smile:

instead of meta[‘after’], the following should be used: meta.configuration.after

Just to have all info here, this is how the meta object look like:
[key=Static:Notification_Setting_FrontGate, value=meta, configuration=[createOHItem=true, channel=3, interval=30, after=30]]

For future readers, I’ve opened an issue on the library to add full support for metadata. I’ll submit a PR for it sometime after my current PR is accepted.