Recommended approach for bindings that generate events


(Bill Welliver) #1

Hi all,

I’m working on a binding that generates asynchronous events I’m having trouble figuring out the proper approach for modeling this behavior in OpenHAB. I imagine that these events might trigger rules based on an event occurring (precipitation has started), or possibly displaying data or updating a widget in a UI such as HABPanel.

Some background:

The binding is for things (WeatherFlow SmartWeather devices) that generate a set of “event” messages, such as “Precipitation Started” or “Lightning Strike” or “Wind Speed Update”. I’ve got a set of channels to handle sensor values that are reported, but these asynchronous events don’t seem to to represent the sort of data that typical Channels hold (i.e. the state of an item).

I initially thought that Trigger Channels were the appropriate mechanism for introducing these events into OpenHAB. However, Trigger Channels don’t seem to be able to have a payload, and some of the events have data associated with them (such as the lightning strike distance).

I then thought that using an EventPublisher with custom Event types would be the appropriate approach, but I didn’t see any existing examples that were similar to my use case. It also wasn’t clear if these messages would/could be passed to UIs for action.

Does anyone have any thoughts about the best approach for this scenario?

Thanks in advance,

Bill


(Rich Koshak) #2

If the event is the only data (e.g. sunrise, dash button pushed, etc) then use the Trigger Channels.

If the event contains a value, it needs to be a Channel that links to an Item like any other. The fact that it is asynchronous is immaterial. Most Items get updated randomly as events occur…

The only way to persist the data is through Items. The only way to slow the data on the sitemap or HABPanel is through Items. And the only way to trigger a Rule with anything more than “event happened” you need an item.

For the events that you list I would follow the lead of the Astro binding. Use a Trigger Channel to trigger Rules, a DateTime channel to store when the event last occurred in an Item. And if there is any other Piece of data there should be a Channel for that prefer if data so it can be sent to the appropriate item type.

Anything else would be inconsistent with how all other bindings I’m familiar with work.


(Bill Welliver) #3

The event contains data so a trigger channel won’t work.

The event data isn’t intended to be persistent… the data is only valid as of the instant the event occurs, so a standard item isn’t really appropriate, plus the data is complex, and there doesn’t appear to be a way to extend ComplexType outside of the core.

Events appear to be the correct approach based on all of the documentation I have read, though I haven’t found any examples of it in actual use.

I’ve looked at the Astro binding, and that seems to be a different use case: time of an event like sunrise isn’t temporal, it’s a constant given the date and location and is something you might be interested in knowing over the course of a day. Weather events like precipitation beginning or a lightning strike are discontinuous and thus don’t really seem to make sense in terms of an item.


(Rich Koshak) #4

Then there is no reason to send the event data in the first place. If it is only valid in that instant then you can’t use the data in a Rule. It makes no sense to put it on the sitemap, it makes no sense to save it to persistence.

However, if you want to use it in a Rule, you must use an Item. Or, the data is not useful information in which case don’t send the data and use a Trigger Channel.

The amount of time a piece of data is valid is frankly irrelevant as to whether it is appropriate to assign it to an Item. If there is a relevant piece of data that comes with the event, it is up to the user of the binding to decide how long or what they want to do with that piece of information and therefore it belongs in an Item.

But I’m failing to see what data would come with a precipitation started or lightning strike event in the first place so I fail to see why the Trigger Channel won’t work.

Ultimately the coin of the realm is Items. If you bypass the Items you eliminate a huge set of options that I the user has the ability to use with that data. So if there is additional data beyond just the fact that the event occurred, it must be in an Item.


(Bill Welliver) #5

Thanks for your feedback. I originally posted my message because the methods you describe don’t fit the use case I am looking at: Events carrying potentially complex data that represent an instantaneous data point (a changing edge) rather than a level (ie state).

As I mentioned earlier, the lightning strike event, for example, provides a distance to the strike; a rapid wind event may provide direction and speed, and so forth. Having data directly associated with an event is critical to avoiding data loss that can happen if you are storing associated measurements in an item: a lightning strike event that stores a 1km distance in an item may be immediately masked by one at 5km, and that is something that obviously is undesirable, especially if the goal is to permit use of the value as part of a triggered rule.

Another use case might be a HABPanel widget that displays lightning activity based on lightning strike events.

The use of events is described fairly extensively in the documentation (and the canonical example provided is a Sunrise event). It seems to very closely map to the scenario I am speaking of, however I have not seen any obvious uses of this infrastructure and was seeking feedback.

Ref:

https://www.eclipse.org/smarthome/documentation/features/events.html
and
https://www.eclipse.org/smarthome/documentation/features/event-type-definition.html

I am still hoping someone with knowledge of how this was intended to be used will chime in.


(Rich Koshak) #6

When you send a command to an Item, the command is what goes on to trigger the Rule which is stored in the implicit variable receivedCommand. So you would never lose the event nor the data even if two occur on the same Item within milliseconds of each other.

This is in fact a problem that some users encounter because they try to use MyItem.state in a Rule triggered by Item MyItem received command and MyItem.state is still the old value because the Rule starts executing before the Item registry is updated. That is why the receivedCommand implicit variable exists.

tl;dr the Rule runs before the data is stored in the Item so there should be no data loss.

The UIs (sitemaps, HABPanel, etc) only support Items.

These triggering events do not carry any data. These are pretty much just “fact of” events. The fact that Sunrise took place at this instant. The fact that a Dash button was pressed. But there is no data that comes with it. That is the purpose of these sorts of events. Since your events carry data, the only way to preserve that data and make it available to Rules, the UIs, et. al. is by sending command to Items. And as mentioned above, the Rules are already set up to handle the case where events come in really really fast on each other’s tail.

However, there is a problem that might be faced. Since you have some events with multiple pieces of data you will run into trouble if you do the logical thing and split the pieces of data apart into multiple Items. Each command to each Item is handled independently and in parallel so if, for example, you have a Rule that need to know: that a high wind event occurred, the wind speed, and the direction, then you can’t really guarantee that the Items are all updated at the same time so you can’t really rely on the state of the Items to get the data.

So you would really need to assign the data to a single Item and somehow require the User to split out the data in the Rule.

I think one of the big takeaways is OH is not a real time system. There is no guarantee of timing of processing and and no guarantee of order of processing. Adding events that carry data is not going to address these issues. So in your example of the lightning strike 1 km away and another 5km away, you can guarantee that both events will be processed but cannot guarantee how soon after the event processing starts nor can you guarantee that they are processed in order.

@kai, do you have any comments. Bill has momentary events but these events carry data to the triggering Channel approach will not work. He has concerns about using Items to receive the data but I know of no other way. Is there something coming down the line?


(Bill Welliver) #7

An update on what I’ve found:

Custom events generated in OpenHAB do get delivered to PaperUI and HABPanel, but no action is taken on them. I contributed a patch to HABPanel that causes unhandled events to be broadcast via the AngularJS framework so that downstream components like widgets can make use of them.

The new rules engine can trigger from a generic event but the triggers are marked as hidden so they’re not available in the UI. The documentation says that they’re meant to be used as a building block for other triggers but I haven’t actually seen a case of that. Perhaps they could be made visible from an advanced mode?

I was able to create a custom trigger type within my binding, and that seems like a good approach from a usability standpoint. I had some problems using the sample trigger from the automation.sample.moduletype bundle (the OSGI EventHandler was only getting a strange subset of overall events being generated) but using a smarthome level EventListener seems to work properly. There seems to be some flux there so I will wait till 2.4 to see if that settles down.


(Mark Herwege) #8

Trigger channel events to have a string payload. I have used that in the Niko Home Control binding. An example of a rule using it is in the docs:

rule "example trigger rule"
when
    Channel 'nikohomecontrol:bridge:nhc1:alarm' triggered or
    Channel 'nikohomecontrol:bridge:nhc1:notice' triggered
then
    var message = receivedEvent.getEvent()
    logInfo("nhcTriggerExample", "Message: {}", message)
    ...
end

The Neeo binding also uses this and uses a json as the event payload. That could be interpreted in a rule for its content, or easily be shown in Habpanel.


(Bill Welliver) #9

Hi Mark,

Thanks for the note (and sorry for the delay in replying)! I did think about using this approach… I wrote some code and it did work, but I sort of wanted to advocate for a more complete solution to the problem space. Creating custom triggers seems to work well with the next generation rules engine, though it would be nice if the OSGI event trigger were available directly to end-users. Making custom events available to the various clients seems more like a work in progress (and a direction/functionality that not all maintainers seem to be up-to-speed on).

I’m more than happy to have further conversations about this topic and future directions if anyone wants to chat about it!

Bill