Context for triggering items

This issue comes up often in my rules that there is no context of where the change originates from.

How difficult would it be to have the equivalent of a stack trace attached to an item that begins from the binding?

For example, I would like to know if a thermostat setting was changed from the actual thermostat, or if it was changed from the Openhab App.

I know there is a disconnect, in some instances, like zwave2mqtt. An MQTT command is sent, then retransmitted over zwave. The tstat replies with the changed updated setpoint, which is then sent back over MQTT. So, the incoming message was caused by an outgoing MQTT message, but that information is lost. I would have to track the timing between the two to fix it, which I do that sort of works, but its a hack. Then, the other case is RX of an MQTT message that wasn’t caused by an outgoing command, which indicates the change happened at the thermostat.

It’s been asked for before as far back as OH 1.x and it comes up periodically since then. No one has volunteered to implement something like this so I surmise it’s not something easy to implement.

Ultimately the event bus does not preserve and has no knowledge of where an event comes from, just that the event occurred.

In the mean time see Design Pattern: Manual Trigger Detection for approaches to determine where a command or change comes from. The proxy Item approach is the most generic and most relaible.

It seems like most of the information is already in the persistence layer.

If a person such as myself were to pick this up, would this be a binding? Take the expire binding as a template, and implement methods that interrogate the persistence for the given item and return a stack trace of the changes made to the item? The information of the class making updates would also need to be added to persistence, which may make this a bad idea.

It seems to me that a change to the base Item class would be required for tracking updates.

This stack would be bounded by a time limit. Any events at the bottom are removed if the now-eventTime exceeds the limit. Let the user specify the length of time.

When used, I would imagine that the user could say something to the effect of

if stack[3].className.contains("ruleEngine"){
   do something

Which would mean that three events prior to now, the thing that modified the item was the ruleEngine. It would probably get one pretty close to being able to figure out how the event chain was initiated.

A less brittle method call would be something like

if stack.originatingClass.contains("MQTT") {
   do something

No, persistence doesn’t get anything until after it hits the event bus and that’s too late to carry any information.

No, you’d have to:

  • change the event bus in openhab-core to supply the additional information to the events that get published to track the origins

  • change everything that publishes events to the event bus to supply this new origin data. This might only impact openhab-core if there is a way to supply the origin information generically for all the different ways an event can be published (karaf console, REST API, rules, bindings). However, if the API changes then it might require a change to all the bindings as well which might be a breaking change and therefore have to wait until OH 5 unless you take it upon yourself to update all 350+ add-ons yourself

  • changes to the Item to pass through origin information when the Item itself generates an event (updated and changed events come from the Item)

Some tasks which might need to be done:

  • changes/updates to the SSE and Websocket stream

  • changes to the REST API

  • changes to the UIs

Expire is no longer a binding and has been built into core since OH 3.0. But no, this cannot be used as a template. You need to modify the event bus to include information in the events that is not currently present and you need to modify all the stuff that publishes events to the event bus to supply that information that is not currently supplied. You will not find a nice concise example to use as a template to do this. The event bus is core to how OH works, it’s what everything else hangs off of.

But agin, persistence is not going to be involved in any of this. Persistence takes place way to late to be of any use here.

I would focus just on trying to get originating information into the event put on the bus to start. Worry about keeping track of history and suff like that later in a separate PR.

Also keep in mind that 99% of the time a rule (which is going to be the only consumer of this information) is going to care about where the event that triggered it came from, it’s not going to care what changed the rule 4 events ago. And if it does, the rule can keep track of that itself.