Profile types and their separation

I have a question from development and user point of view and I would like to understand it a little bit more. As I don’t find it necessary to go over github yet and there are no code changes I think it will be easier to go over here. Please correct me if my though process is wrong.

Ultimately we have two kinds of channels in openHAB - a trigger and state one. Main difference is how they work and what they can do. The trigger channels works on event basis and its state can not be read directly from backing device (let say a sunrise, it just happens). State channels retain its own situation and they allow to get back to device and refresh state based on the physical system. We could dive a little bit more into philosophical aspects of this fine separation when devices come into the play, however this separation is there and makes a lot of sense.

Since 2.4 release we have support for profiles which can affect how the trigger and state channel works. Thanks to that framework has additional layer between things and items where it can retain state in case of events and also affect the way how state is processed.
Now, based on review I did there is whole set of trigger profiles which can be used to control the sate (RawButtonOnOffSwitchProfile, RawButtonToggleSwitchProfile) of linked item but we have no such thing for state profiles. This forces use of rules for something which is quite basic and available out of the box for simpler (stateless) channels.

While the difference between trigger and state profile from conceptual point of view is clear and quite big I see a big shortage of “toggle” profile (for OnOffType) for state channels. Same applies to rollershutter (UpDownType).

Shouldn’t we have it?

Put another way, a triger channel has no state. It’s a way for OH to receive ephemeral events: a button was pressed, sunset just happened, etc.

That’s a feature of some Channels for those technologies that support it. But in general a Thing exposes a State to openHAB. But it’s important to realize that we used the name “Channel” for a reason. The Thing has Channels and Channels provide a path to update and/or command Items. It’s the Items that actually have the state.

There is a special command, REFRESH, you can send to an Item that some bindings will go out and poll the devices for their current state. But in general, new states for devices get pushed to openHAB. openHAB is not going out and polling the devices for their current state.

What would a “toggle” state profile do that rawbutton-toggle-switch (for example) doesn’t do?

Rawbutton profile is currently permitted for trigger channels while most of bindings uses rather state channels.
My proposal is to allow toggle functionality on state channels too - simply by providing necessary profile implementation.

But the state associated with a channel/Item that deals with UpDownType commands … is a percentage.

When using “toggle” type features in practice, they invariably become a nuisance because they don’t directly give you any clue as to what the result might be. Of course you can work round that with rules of some type … but you can just as easily create the toggle feature with rules.
I suppose I’m not understanding the aversion to rules.

1 Like

UpDownType handles Up and Down commands. It might happen that for some reason these needs to work in other dirrection than initially designed because of some wiring error.
Pulling rules for slighest thing might be fun, same for writing inline transformation but for many cases it might be overwhelming and more complex than user needs. Sure, if whole set of inputs needs to be reversed then group should be first choice. On other hand when one or two switches out of 20 needs to work in reverse direction it is just matter of two clicks to get these. Also removal of these is straight forward.
It makes no point to

Okay, we’ll need to come up with better use case, but …

An obvious omission from current profiles is that only operate on “incoming” state channels.
This use case would need it to operate on “outgoing” command channel.
You’d probably want to have separate state and command profiles, because you would most likely want completely different operations, even if did want to profile both state and command.
That could be achieved by either
Separately specifying stateprofile and commandprofile on the channel
Allowing multiple profiles, but profiles having a type as to state or command.

Need to decide what to do about those bindings that support generating OH commands off incoming data e.g. MQTT. Should a command profile apply to that or not?

Still seems to me it’s not much saving in typing. But - the selling point is that this would be usable with any things/channels binding. Whereas the existing transforms and inversion features of a binding are dependent on the binding developer.

While we are on the topic, is seems that if the transform profile were able to handle more than just String Types this all could be handled using a transform. Given @splatch’s example, he could just to a MAP to swap the directions for those few Items that need it.

In my case, I’d love to be able to change the Item types, for example change all my Network binding Switches to Contacts.

Not sure what you mean by incoming and outgoing channels, as StateProfile allows to mediate from item to handler and vice versa, so it is fine as is to handle situations where we have single channel which can provide state updates as well as accept commands.

interface StateProfile {
  void onStateUpdateFromItem(State state); // inherited from Profile
  void onStateUpdateFromHandler(State state);
  void onCommandFromItem(Command command);
  void onCommandFromHandler(Command command);

From above definitions I read that StateProfile handles both states and commands. I am not sure if both have to be diverged as separation of commands and states is currently purely artificial to me. The UpDownType is both State and Command, same applies to OnOffType and other primitives. For me, when I take these two into account, it is really unclear what is a command and what is a state especially that they seem to be handled separately at API level. When I made my first attempt towards binding development I initially thought that it is all about directions of communication. I was expecting that states are received from devices in binding and commands are issued from binding to devices but it didn’t hold long. The description in the user docs does not answer that clear enough to me.
I believe there is reason for this separation but it is currently well hidden. :slight_smile:

I believe it still applies as it works after channel is defined and covers link alone. If you have a complex script a profile on top of it might be used to quickly inverse the logic. This will work regardless of what MQTT does. Framework layer will hid this up.
MQTT binding is a master piece in terms of functionality, configuration and aligning with OH way of doing things in as many aspects as possible, yet I still seek answer for a basic question.
Why we don’t have, and should we even have a “toggle” and other profile kinds for state channels as part of standard distribution?

I am speaking from a user viewpoint, not privy to channel-binding constructions.

In the most general case, “we” send commands to an Item and expect them to be passed to binding. In eventual response, an incoming communication via binding passes to an Item state update.
Command and state can be of quite different natures e.g. INCREASE and 80%.

So I would expect any realistically usable profile would need to run rather different processes on the “ins” and “outs”. One obvious way to do that is by specifying two simpler profiles.

There are of course exceptions of bindings that create “incoming” commands and export state changes … but I think that only goes to prove there are two separate pathways through a channel, whether we distinguish them as “in” and “out”, or as “state” and “command”.

You’d run into the same kind of thing when, say, exchanging data with thermostat. You might need to scale an “incoming” number with divide-by-100, but the “outgoing” by multiply-by-100. This is routine in usage of transforms, we’d need to replicate it somehow in profiles.

A command may or may not be stored in an Item as it’s new State. For example, if you send INCREASE to a Dimmer Item as a command, the Dimmer Item doesn’t take on the State INCREASE. Instead, the dimmer value will increase by some amount and the new State will be, let’s say 75. Some commands like INCREASE cannot become a state in and of themselves.

In other cases, like OnOffType, if you send an ON command to a Color Item, the Color Item won’t become ON, it will become some HSB value in response to the ON command. But if you send an ON command to a Switch, the Switch may become the ON State.

That’s why there is a difference between a State and a Command. A Command is an event that signals an intent. I want X to happen. A State is an indication of the current condition of the device. So if I sendCommand(ON) to a Dimmer that signals to the binding that I want to turn on the light linked to that Item. In response to the ON command, the binding will send something to the device and then postUpdate to the Item that the device is now at 100% (or what ever dimmer level it turns to on an ON command). In events.log you will see “Item Foo received command ON” followed by “Item Foo changed to 100”. A Dimmer Item can never take on the state of ON. It can only have a state of a PercentType.

Let’s ignore autoupdate for now as we don’t need to muddy the waters. When you see the “predicted to become” log in events.log, that autoupdate. But in short, autoupdate is a feature in OH that will predict what state the device will become in response to the command in those cases where the binding does not get positive feedback from the device what it’s new state after the command.

Anyway, all States can be sent as a Command but not all Command can be a State.

Your explanation makes tons of sense and without doubt can be placed in developer docs. Combining both State and Command in sources under Type tree is not that obvious.
Based on your comment “all States can be sent as a Command but not all Command can be a State” suggests to me that Command is higher in hierarchy than a State, but lets leave the philosophical aspects of that here. :slight_smile:

Given this example I see that State have a variable value inside (or values if we talk about HSB or Point) whereas Command is fixed by its nature and it is unlikely to get intermediate representation. When I took a look on commands we currently have I see all of them are basically pairs:

  • on-off
  • open-closed
  • up-down
  • increase-decrease
  • stop-move
  • next-previous
  • play-pause
  • rewind-fastforward

yet we have no support for Toggle command (or operation if you see it this way) in core despite of having only pair commands! I found few occurrences of a “toggle”, one of them in To me this place looks like an additional Command kind which got implemented in wrong place. :slight_smile:
We have a Refresh command which plays with multiple bindings, why there is no toggle command?

Sounds like a very good candidate to re-evaluate in 3.0 roadmap! :slight_smile:

Personally I see no benefit for a real TOGGLE command, with its indeterminate outcome and adding a new opportunity for race conditions.

Some hardware support it already - ie. LCN has such functionality embedded in its core. It is clear for me that such kind of command can be supported by some, but not all bindings. For these who do not support it directly, framework can emulate. OH is aware of item states and already does it in partial form.

Some hardware support things like “change to channel 5” or “add more water” but we don’t have specific commands for that. We adapt from the basic OH internal command set.

I’m not suggesting that there may not be a place for a “toggle” profile. Or more likely, a family of profiles, as there are different cases. Turning an OH command into something that the binding can be passed as “toggle” in some external command set. Or converting an incoming button event into OH state change.
But I do not think it appropriate for an internal OH command.

I agree that having a command embedded in core supported only by one kind of binding makes no point. However we talk about toggle functionality which is already showing up here and there under profiles and hardcoded in rest api layer.
I would see no problem if there would be a way to contribute new command types. Sadly OH does not support non-core ones. I made a small experiment few months ago if it is possible to contribute completely new kind of state/command to system. It turned into quite big hack. This means that any command which is not already supported yet needed at the binding or ui level will promote use of strings instead of valid data structures.

But it makes no sense to toggle between increase/decrease, rewind/fast forward, up/down, next/previous. open/closed is only supported by Contact Items which cannot receive a command in the first place.Of the list, only on-off, play-pause, and move-stop make sense to have a toggle. For the rest, intermediate commands would be expected. For example, fastforward would go to play or pause or stop next, not to rewind.

Is this even possible though? How much does the Profile know about the current state of the Item. From what I’ve seen, without looking deeply at the code, all it appears to know about is the information coming from the Channel. To implement a TOGGLE, the Profile would need to know the current state of the Item. Someone also has to figure out how to handle the NULL/UNDEF cases.

It is worth noting here that the IFTTT openHAB Channel used to support a TOGGLE command. I’ve no idea what it did to convert that to something OH understands. But the point is there is some precedent, if not a strong one.