Channel state persistence in a binding

Hi,

I’m currently migrating a OH1 binding to OH2 and also have resolved some shortcomings within the plugin.
During development it turned out that we have two different architectures that needed to be connected by the binding, and especially during OH restart that causes some issues.
I’ll try to keep it short:

  • In OH we have a thing that has channels. Within OH each channel is individual, has it’s state and can be updated without any relation to other channels.
  • On the other end I have a device where I update a bunch of channel’s with one message. Depending on the setup this means that we have to update the values of 4 or up to 16 channels at once.

Okay, when the system is up and running the binding is aware of the state of the ‘neighboring’ channels. When one channel gets updated, the message sends out the ‘last known values’ for all other channels. That’s fine.

The trouble begins with the restart of OH or the binding (i.e. if more channels are added): After restart I don’t have any known state of the neighboring channels. When a channel gets updated, I have the state for the updated channel - and no known state for all others. And there is no ‘no op’ state that I cloud transmit. Depending on the channel type, everything I send is a valid value. So the receiving system will accept this value and work with it as it would be a real value. This is why I have to find a way to persist/restore the channel states somehow.

To make it round:

Currently I have implemented an own persistence mechanism within the binding. We are wondering if somebody is aware of a similar situation and if there is a solution providing us the states during startup?

One idea might be the item persistence - https://www.openhab.org/docs/configuration/persistence.html#restoring-item-states-on-restart - but is there a way the plugin could fetch the states of the item’s and transfer it to the channel’s?

Any hints are welcome :wink:

Thanks & Bye,
Chris

I think the general design philosophy is that channels are stateless (just update events).

I’m not entirely clear what you need.
I think you have a device that accepts parameters like X,Y,Z but with a restriction that you must update all at once.
So to change X, you must know Y,Z as well.
In startup circumstances, you might not know Y,Z yet.

I’d point out that whatever solution you might come up with that uses openHAB’s persistence framework, or your own binding mechanism - it’s going to be a guess. Could be a good or bad guess, but you’d be relying on historic data which might be stale. (something changed between reboots etc.)

Is it possible to extend “write to X” so that when it looks for Y,Z and discovers they are not yet known, it does a read cycle to fetch Y,Z realtime values before proceeding with X,Y,Z write?
The binding must still hold an image of “live” X.Y,Z but you avoid any of the pitfalls of long term persistence.

Is there some reason that you don’t simply ‘refresh’ your X,Y,Z image immediately upon binding startup, as normal Thing initialization?

Yes, it makes perfectly sense out of OH’s perspective. The channel only trigger state changes - inbound or outbound. Only the linked item seems to be aware of a current state.

Yes, that’s right. We could continue with this sample.

The X,Y,Z values cannot be fetched from the TA device. These are values OH is collecting from other sources and delivers them to TA.
In my sample this are temperatures and some other state information OH is aware due to other bindings. OH provides the data to the TA equipment so it could work with it. Currently I have a boiler and some external sensors connected to OH through different bindings and TA needs to know the values / states to work with it.

As already stated OH is the only source for these values. So, as long as OH is not UP and running there is nothing else that cloud provide updates on the states. So OH’s last known state is the state it is. And as X,Y,Z might not be related, they could be from different sources. And from my work with the system I made the experience a persisted, old value is much better than a ‘0’ initial value :wink:

This is what I would do - but how can I refresh something that OH is providing to the binding? Is there anything like an an ‘outgoing RefreshType’ command that the binding could fire to have a channel updated?

If you need to persist data, you could use thing properties. This is how I persist last known trip in Volvo On Call binding to preserve the information between OH restarts

That’s wildly different to what I was thinking.
So this function of your binding is totally dependent on being supplied data from external devices or services.

I really don’t know what you should be doing instead, but this does not sound like appropriate business for a binding. The binding should be managing the flow of data in-or-out for just its own associated service, device or technology.
It shouldn’t be interfering in other bindings business, such as fetching or persisting data from other bindings.

It’s something you could manage with your own rules and configuration conventions of course - what Items to link to where, how to persist or group, how to orchestrate functions.
I’m not sure how you can package that up as an add-on service - it’s not a binding, though.

Yes. For example, if you need channels X, Y, and Z to be set to valid values before you can send a command, I would initialize all three to UNDEF, and simply not send the command if any are still set to UNDEF.

Rules and/or a persistence service can then be used to make sure items linked to those channels are set to “good” values at startup.

In the meantime I also already was playing with the idea to use this. But it also depends on how often states changes. How often is the value updated in your use case? People have OH running on RPI’s with SD-Cards so we have to try to limit the writes :wink:

Simple but it could work. keep it simple is always good ;). Setting all values initially to UNDEF or maybe to an on the channel configurable initial value for non-critical values could do the job. And sending updates is blocked as long as there are UNDEF values within a message.

TA also has some options to define valid ranges for analog inputs. I have to play around with this feature, maybe I could configure some setup that says when a ‘out of range value’ is received it should continue with the old value… :thinking:
I have to dig into this, maybe combining both concepts allows us circumventing the persistence on OH side…

Using the X,Y,Z model, it seems to me you just want three data channels.
Y and Z listen for state updates, and hold an internal image of those values. No persistence needed - that’s the users problem.
(In practice, you would probably do a read-refresh on those channels at binding startup, and afterwards look for updates)
When a command comes along on X, do your thing if Y and Z image are valid. That’s it really.

Users can manage Y and Z however they see fit - different data sources, modifications or simulations, persist or ensure live data, their choice. Just link an Item and populate it how you like.

In practice, a separate results channel would probably be useful - “Command X ignored because current Y value out of range” - but just a WARN log would do.

In my case it can change at any refresh done toward the webservice (lets say every 5 mn).

Hi @rossko57

Do you have something special in mind for this ‘read-refresh’?

I’m currently thinking of a event channel that can configured with a fixed delay. This channel will be triggered with the given delay after the binding is started. This allows the user to run a rule by this trigger and initialize all channels to some useful value. So it’s up to the user how to initialize - maybe even from the item persistence…

A results channel… :thinking:… Maybe just a Switch/Contact showing that there are uninitialized values so the user could trigger an alert/warning on this?
AFAIK there are no channel states, only thing states… Or is there any thing state that could be used to indicate this?
Or a string channel showing all uninitialized channels? And this string is empty when everything is fine… :thinking: I think i would prefer the string channel so I easily see what’s wrong / missing… What do you think?

Also some warnings in the logs are also fine. But maybe not for each channel update, but during the ‘periodic refresh’ - The binding has to periodically resend the values otherwise it would be flagged as offline by TA. This would ensure the logs won’t get flooded by these warnings…

Nope, out of my league. Bindings can listen for Item state updates. I do not know if you can, from a binding, retrieve a linked Item state on demand. But on reflection there’s probably not much need for that …

I don’t see any point in that. If the user needs to supply values before issuing a command, he knows that. If the system has just booted or he hasn’t yet supplied any, he knows that. Your binding cannot know when the user’s uhhh “arrangements” will be ready with that data, if ever.

You just tell them “you must post state (or command, if you wish) to this channel and that channel before you can command the other channel.” Them’s the rules, there are many ways a user can manage this task.

That’s right. Your binding offers the “results” channel, maybe a string type. If the user’s interested, he links it to an Item. If he doesn’t, then he doesn’t. See exec binding for an example.

But as earlier, since this was only to indicate a command-time error it’s simpler just to log it out.


Have you considered a really simple approach?
In order to transmit a command, you need data Items X,Y,Z all at once.
So, bundle them into one Item. A string as comma separated list or whatever, your rules.
User populates that however he likes.

I like this idea, but I can’t say if it’s practical for the user. Can you give us an insight for what these temperature values are used and where are they sourced from?

Hi. I’ve discussed the ‘single channel’ approach with an other user (offline) and he also would prefer having a 1:1 matching between the channels on OH side and the matching counterpart on TA side. The TA stuff is nearly as flexible as OH and each ‘channel’ could be configured and used individually so the values carried in the message could not be related at all - maybe the there is a temperature next to a liquid flow rate next to a power rate to a pressure. This all depends on the individual configuration…

And also to the combining the values - for a bunch of 4 values it might be manageable, but when it comes to 16 values it could be very confusing and fault-prone to build up the string values properly…

So from my feeling it would be better and clearer for a user to continue with the separate channel approach and block sending till we have all needed values.

In this use case, I agree with keeping the values separated and block any command until all values are known.

The framework will not send any commands to ThingHandlers as long as they are uninitialized (see ProfileCallbackImpl).
It considers them uninitialzed if they haven’t updated the ThingStatus to online/offline/unknown.
So you could use that and only update the ThingStatus once it has obtained all required state from the device.

Hi @wborn
thank you for your input. But either I didn’t understand it or you mixed up the direction of the data flow: The data in question is collected by OH and sent to the device. So my understanding is the binding has to set a proper ThingStatus to be able to receive commands on it’s channels. So it can build up it’s value cache and start transferring data to the device as soon as the required values for a message is complete. What I understand from your post is you expect these values are coming / obtainable from the device. We can only obtain values it has (outputs from the Device’s perspective) - but not the values it expects from OH to be delivered to the device (inputs). And the direction OH -> Device is causing the trouble…