Trigger fails due to wrong type / coming from persistence

  • Platform information:
    • Hardware: Raspberry Pi 4 / 8GB
    • OS: OpenHABian / OH 4.3.5

I have just experienced an interesting issue.

I am using a Number type item as storage for the overall status of my underfloor heating and heatpump system. It can have several states which I store as numbers, which represent e.g. if all heating is off (item = 0), all is on (item = 2), or mixed status (item = 1).

The item is used to trigger several actions on change. Therefore, I have rule triggers like:

when
  Item Status_alle_Heizungen changed from 2 or  // von alleHeizungenStatusOn
  Item Status_alle_Heizungen changed from 1 or  // von alleHeizungenStatusMixed
  Item Status_alle_Heizungen changed from 0     // von alleHeizungenStatusOff
then ...

Tonight, the system switched heating off due to the very warm period of days as expected, and I was wondering why some triggers were missing. I found the explanation in the logs:

2025-05-02 03:00:18.471 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Status_alle_Heizungen' changed from 2.0 to 0

→ it changed from 2.0 [float] to 0 [int]. Which does not trigger the above rule - I could reproduce that manually, if it changes from 2 to 0 it triggers, if it’s from 2.0 to 0 the trigger is missed.

The interesting part is that there is no action which ever sets the item to 2.0. Only int values are used for setting the item. It comes from the reload from persistence on any reboot / restart, which correctly restores the value as such, but changes its type from int to float. As the item changes only about twice per year, this reload is nearly inevitable.

The reason why I use these explicite “changed from” is also due to persistence reload. I only want to trigger the rule when the item changed from a valid value, using just “changed” or “changed to” gives me undesired triggers on reload from persistence (as it changes from uninitialized to the recent value).

I would like to avoid something like switching it to float values and using “changed from 2.0”, as comparing float values to exact equality is bad programming practice.

What would be an elegant while stable solution for this issue? Or is it a bug?

Do you have to use a number for this? This seems like a simple state instead of something you need to do math with. A String often works better for those cases and is more self documenting.

You can also address this using the following:

    if(previousState == NULL || previousState == UNDEF) return;

That will exit the rule if the state changed from NULL or UNDEF. Since Items are initialized to NULL it should avoid the rstoreOnStartup triggers (note those should only happen if you reload a .items file after OH has already started, during startup, unless your database is external and really slow, the Items will be restored long before the rule engine is started).

In UI rules and some of the other rules languages (e.g. rule builder from JS) this can be set as a rule condition.

I don’t think it’s a bug. OH doesn’t really have a concept of int when it comes to Item states and persistence stores and restores floats always I think. It might be different from one DB to the next but you definitely cannot count on it always being an int.

Thanks for the quick reply!

In a way yes. I do not do maths with it, true, but I needed a state type which can have more than two discrete values, and which has an easy possibility to be graphically displayed, and which has persistence also for restoring after restart. Only “Number” fulfilled all of them :wink:

I had that idea as well, after some hours of thinking about it - happy to see it makes sense :smiley: So I went for that solution, and explicitely casted the item by “as Number.intValue” inside the rule. From what I tested manually, this works and does not care about int or float anymore. :+1:

That’s what confused me most, honestly. I am using rrd4j with its default config, only thing is that I have 1099 items in my config :sweat_smile:. I would have expected what you described, anyway - restore is done before the rules are loaded.
Nevertheless, on each reboot / restart, my home went crazy for some minutes, triggering actions allover, and at some point I realized that these actions were the last ones, each repeated, which triggered the item before the reboot, even if that original trigger was days ago.
So I changed the triggers that they expect a change from a valid value to another valid value, and all the ghostly behavior disappeared.

At least for rrd4j this actually makes perfect sense, as it internally averages.

Understandable, but anyway, if really triggering on a change to a certain value (and not by triggering on a general change and checking the value inside the rule in an if-condition), the observable behavior is somewhat confusing. All rules set int values, all triggers are to int, and by restart and reload-from-database, the functionality breaks.

Just thinking… having an item type which stores multiple discrete states (like a state machine) would be nice, or by setting a property / metadata of the item which allows int only and implicitely casts any updates / commands / restores to int (and vice-versa, force to float if needed). :slight_smile:

String fits all those criteria too unless you are relying on rrd4j for restoreOnStartup, which I didn’t recommend. MapDB for that.

That’s a String Item.