Controlling a Dimmer Item by physical buttons - various questons to achieve clean solution

Running OH 3.2 I plan to control (various) dimmers by a physical “ButtonBox”.

The buttons are connected via MQTT using Homie Convention. The box runs a menu with a hierarchical state machine, so it converts it input directly to command strings.

The whole project is planned as an example in a series of workshops explaining how to build the Button Box (FreeCAD → Laser cutting), programm it (Arduino, PlatformIO, Eclipse, MQTT/Homie, Use of state machines) and using it for home automation (OpenHAB). So I strive for a “cleanest” possible solution and want to avoid any “ugly” workarounds.

For some of my questions the answer probably is “this is how OpenHAB is designed”, but maybe these question then can be an idea for future improvements.

The current setup is:

  • There is a channel and Item of Type Dimmer for the LED strip to control.
  • There is a channel and item of Type String to receive “commands” from the ButtonBox, these include “TOGGLE”, “INCREMENT” or “DECREMENT”.
  • There is a rule (jython) to read the command-string and forward it to the dimmer item. A “TOGGLE” command is changed to “ON” or “OFF” depending on current state of the target item.

This works fine, but there are some issues:

  • The increment/decrement is only 1%
  • There seems to be no toggle command for a Dimmer.
  • It seems unnecessary to use a rule (use profiles instead)
  • Even although the received command could really be a “Command” type, it is a normal “State” for OpenHab.
  • This state needs to be reset to an “NoOp” (or “Idle”) state by a rule to recognize further commands.

So, my questions:

  • Is there a way to increment or decrement an item or channel by more than one, when INCREMENT or DECREMENT command are received?
  • I could change the inc/dec buttons to send their “pressed” state and use the rawrocker-to-dimmer profile. However, INCREMENT or DECREMENT every 500ms is WAY too slow (it would take 50s to reach 100%). So to use this approach: Is there a way to lower this delay?
  • Why there is no TOGGLE command for OnOffType? Is there any elegant workaround other than a rule? (e.g. own profiles using the script engine (preferrably python)).
  • Is it possible to convert incoming MQTT strings directly to an OpenHab Command?
  • What is the most elegant solution to have a rule that handles such “command strings” without unnecessary trigger for the “NoOp” state.

Thing/Channel configuration:

Thing mqtt:topic:kueche_thled "Küche Thermometer & LED" (mqtt:broker:IAmq) @ "Küche" {
	Channels:
		Type dimmer:	LED_w		"Arbeitsplatte weiß"		[ stateTopic="homie/kueche_thled/LED-RGBW/w", commandTopic="homie/kueche_thled/LED-RGBW/w/set" ]
}

Thing mqtt:topic:coffeectrl "Kaffee Controller" (mqtt:broker:IAmq) @ "Küche" {
	Type string:			coffee_white_cmd "CoffeeCtrl Command White" [stateTopic="homie/CoffeeCtrl/RGBWCtrl/w_cmd" ]
}

item-Configuration:

String CoffeeWhiteCmd "Coffee ctrl command white" {channel="mqtt:topic:coffeectrl:coffee_white_cmd"}
Dimmer	kueche_thled_LED_w		"Arbeitsfläche weiß"			(kueche_thled, gAutom_ALL_OFF)	{ channel="mqtt:topic:kueche_thled:LED_w" }

Rules:

from core.rules import rule
from core.triggers import when

@rule("receive command white from OP Box Kueche")
@when("Item CoffeeWhiteCmd changed")
def kuOpBoxWhite(event):
    cmd = event.itemState.toString()
    if cmd == "NoOp": return
    targetItem = "thermo_ian_LED_w"
    events.postUpdate("CoffeeWhiteCmd", "NoOp")     # Reset Item to NoOp
    if cmd == "TOGGLE":
        cmd = "ON" if items[targetItem].as(OnOffType) == OFF else "OFF"
    events.sendCommand(targetItem, cmd)

Teaser: Photo of the box (I hope this will be a reall “cool” project that I can finish soon - including workshop-capable documentation):

So have your jython rule do something different about it?

That’s correct. As you’ve found, you can construct your own by rule.

Really, don’t. for an instructional. Harder to debug and less flexible.

If you are talking about incoming MQTT message, see postCommand option on the channel.

See above, commands are events and this will not be needed.

Since you are teaching this as a series of workshops I would encourage you to use JS Scripting instead of Jython. I think that Jython is not long for this world and will go away at some point. It’s still Python 2.7 with no Python 3 implementation in sight. The upstream Jython project is barely up and running so at some point something is going to break and Jython will stop working.

Better to use something that has a more certain future in OH.

If JavaScript isn’t your thing, jRuby, JRule, even Groovy would probably be better options. I think it’s better to set people up for long term success where possible instead of teaching on something that is likely to go away in the uncertain future.

The Dimmer Item is a PercentType which can only be integer values between 0 and 100. So be careful when trying to change this. But as @rossko57 mentioned, you can change this in a rule to use any integer increase or decrease amount in a rule.

Correct, you’ll need to implement that in a rule. It’s a one liner really so not that big of a deal. If you do switch to JS Scripting it’s built into the sendCommandIfDifferent() though I’m not positive if that will work in this case, I need to try that out.

What seems unnecessary? Profiles only work on the link between a Channel and an Item. It doesn’t work the other way around nor does it work on Items without links.

That’s a side effect of your previous bullet. I don’t know Homie as well as I should so I don’t know if this is behavior that can be changed. With a Generic MQTT Thing the sendCommand option @rossko57 pointed out is what would be used. Explore the Thing’s advanced configs and the Channel’s advanced configs to see if there is a way to force that to be a String.

If you can change the message so it’s interpreted as a command, there is no need to change the state of the Item to trigger the rule. If not, you can use received update as the trigger of the rule to also avoid needing to change the state of the Item back to NULL or UNDEF.

If there is some reason you still want to set the Item back, you can either do so in the rule that triggers on the Item change or use the Expire Item metadata to set it back for you after a configured amount of time. I think Expire might be limited to seconds though so that may be too long.

If an option is not provided by the binding (which appears to be the case here) then you need to use a rule. There might be some “interesting” interactions between the binding and the rule though so be careful. A Proxy Item might be required.

If there isn’t something in the docs saying that’s configurable, you’d have to change the code of that profile. Though you can use anything you want in your own rules.

You can indeed code your own profile in Python. See openhab-rules-tools/multi_press.py at 6cedcc00b648c29c9aca771a9b72f8dfa22710d1 · rkoshak/openhab-rules-tools · GitHub for an example. But I given the limitations of the Profile I’m not entirely certain that a TOGGLE is possible. I’m not certain that the Profile can get at the state of the Item, for example. It looks like you might be able to catch and store Item updates in the Profile which might be good enough.

Honestly, Profiles are super limited. For a certain class of problems they work great. But they can’t solve all problems and they are anything but elegant. There is nothing wrong with using a rule.

In UI rules you have the option to set a condition which will cause the rule to ignore commands or updates or changes based on some condition. In this case you’d change it to look for the NoOp state. In a text based rule you’ll have to just put an if statement at the top of the rule logic.

Ok, I used python only so far and I like it - however I don’t have any more complicated rules (except one for PWM, but as a PWM function integrated in OH3 I need to migrate anyhow). I will see if I find some time to adapt to Groovy.

Well, I like the initial idea of OpenHAB to have various type for commands (and states) as the OnOffType or IncreaseDecreaseType.
So it would be nice to be able to configure the step size for Increase or Decrease.

As far as I understood the documentation, the decision how to handle Decrease/Increase commands is up to the Binding (xml file with Thing description) - so it is a MQTT binding design decision to handle this as a single step only (and don’t offer a configuration possibility per channel)?

Yes - I would find it more useful to do such things directly in item configuration without any need for rule. I just want to say: This item follows commands from this other item.
I don’t want a rule if it is not necessary.

I haven’t used an explicit profile configuration yet, but as I understand them, they can be used to forward a command from one channel to another, so that another Item will receive the state update - and the command will be send out by the binding of this other channel.

Yes, I’ll give the sendCommand option a try. For now, I use the GenericMQTT thing instead of Homie. For configuration by text file its simpler that way.

There are already two items involved, so it should be straightforward. It still feels wrong to use a rule to implement INC/DEC behavior, when OpenHab has implemented these commands in its core.

Thanks for the hint.

That is dependent on the target device. We can pass increase/decrease instructions along to devices that are sophisticated enough to accept them, and they can do whatever they do with them. Not openHABs business.

Yes. Your target device should implement this. If it does not, then you will have to simulate the action within openHAB by conversion to absolute brightness values, and you should expect to do some tailoring, which is what rules are for.

That’s talking about the target device. Not MQTT in your case, where you just passing the inc/dec instruction inwards. (I’m assuming you intend your button box to work with any type of real dimmer device - zwave, KNX, etc.).

You know, you could have your button box sending messages like “Increase:15” and have OH manipulate that into something suitable for your target device.

Why the aversion to rules?

Seems we all get phobias; an aversion to Items is just as common. My personal horror is non-file based configs. :wink:

1 Like

Good lord Ross, don’t tell anybody :laughing:

Well, lots of things would be nice. But we have what we have. Anything like this would need to be implemented in the binding and since you are using MQTT, which is pretty low level, there is only so much that can be configured. What it means to increase and decrease can vary from technology to technology so OH can’t solve it on its own.

But always you have the option to request new features, or even better submit a PR that implements a new feature.

Why is everyone so against rules? If everything that people have suggest would “be more convenient to configure in Items” were implemented, there wouldn’t be Items any more. It would all be rules. The only thing different is we’d call it “item config”.

And don’t get me started on the people who don’t want to use Items.

Commanding or updating Items based on an event is literally the role for Rules in OH. They can be super simple or crazy complex but that is basically what rules are for.

Profiles don’t do this since they only work on the Link. Item configs don’t do this because they don’t define behaviors. This is what rules are for. It’s why they exist.

Yes, but notice the word “channel”. They don’t work Item to Item. Again, a Profile exists only on the link between a Channel and an Item. The Follow Profile let’s you tell that link to also serve a command from the “primary” Channel to the “secondary” Channel, but it doesn’t work both ways.

OH can only make a decision on which use cases it will support. It can’t support them all in the core. If you’re use case doesn’t match the one supported, that’s what rules are for.

I’m not sure you grasp the sheer number of use cases that exist in home automation. OH can’t support them all as a simple configuration. You’re unlucky to have a use case that isn’t directly supported. But you can at least achieve your ends through rules. Many systems would say “too bad, go poud sand.”

I blame Profiles. There mere existence implies that rules should only be used as a last resort for really complicated stuff. Somehow using a rule to do something simple is a failure instead of celebrating the fact that even use cases that the developers didn’t anticipate and implement can still be achieved.

It’s really nice over here on the dark side. :wink: Though at the end of the day it’s all text file based configs. The only thing different is whether you personally write them or let OH write them for you.

(Obviously there is more to it than that, everyone has to find their own path.)

No mater how strongly you feel software should work a certain way, it does not care. You will learn to use the software within it’s capabilities or you will be disappointed. If you learn to use the software the way it was designed to work, you can do amazing things

Right?

EXACTLY!

Thanks for the discussion and sorry for the delay of my answers. I was quite busy with implementation issues for the Box.
There was quite some progress (project page is GitHub - fablabnbg/ZauberBoxOp: A "ZauberBox" with Buttons - Software uses final state machines to send various commands via MQTT) and I now first have some more practical remarks:

Yes, it makes sense to interprete these commands at Binding (channel) level. So, the bindings should support configuration options how to handle commands if the binding-protocol leaves choices. (Like a generic protocol like MQTT).

I’m forwarding the command to another MQTT channel, so from OH perspective, input command is read and forwarded to an output channel. Ideally unchanged, but I need to interprete the TOGGLE command. But INCREASE and DECREASE will be forwarded unchanged.

Oh, actually, the MQTT binding DOES support a “step”-parameter for Dimmer channels. (At time of writing my last post, I already tried this option and it seem to not work. However, after a restart the “step”-parameter was fine).
The binding changes the Number (percentage) value by the defined step size in case of IncreaseDecreaseType commands. But the MQTT binding gives no option to forward the command as it is - what would be useful to allow the devices to handle commands automatically.

So, for now I need a rule to forward the command and interprete the “missing” TOGGLE command.
Also, there seems to be no profile to forward commands between channels?

@rule("receive command white from OP Box Kueche")
@when("Item CoffeeWhiteCmd changed")
def kuOpBoxWhite(event):
    cmd = event.itemState.toString()
    targetItem = "kueche_thled_LED_w"
    events.postUpdate("CoffeeWhiteCmd", "ACK")     # command ACK
    if cmd == "TOGGLE":
        cmd = "ON" if items[targetItem].as(OnOffType) == OFF else "OFF"
    events.sendCommand(targetItem, cmd)

My “ideal solution” would be:

  • 2 channels:
    • Command-Channel (input device, e.g. “ButtonBox” or a simple push-button)
    • State-Channel (output device, e.g. a LED-Strip).
  • 1 Dimmer Item: “LED-Strip”
    • both channels are linked to this item, the input channel with a “command” profile.
  • Command profile
    • the command profile forwards each received command to other linked channels. A channel with default profile will process the command which then leads to a state update.
    • e.g. in case of two MQTT channels:
      1. MQTT message with command is received
      2. Command is forwarded to output channel
      3. Command is interpreted by MQTT binding and send on MQTT topic as configured (e.g. INCREASE could be handled by binding or forwarded as “INCREASE” string).
      4. MQTT device receives the command, process it and sends it back on MQTT as acknowledgment (like foreseen in Homie convetion) or processed new state (e. .g. “INCREASE” leads to new dimmer value)
      5. The binding receives the Acknowledgement and uses it as state-update (“AutoUpdate= false”).
      6. Optionally: The state update is also forwarded to the input channel (“command profile”).

No rules would be needed for this and I could make use of the command types that are foreseen in OH’s core.

As far as I see the following features are missing for this ideal solution:

  • a TOGGLE command for OnOffType
  • a profile that forwards commands
  • MQTT should support sending “raw” commands.
  • MQTT Homie Convention: Support for commands to properties (for now, support is only indirect via extra properties of type String or enum.

I see that it is hard to anticipate all use case, but what I see for this usecase is that the concepts like command types etc. have anticipated such use case - and they still don’t work without rules.

But with this discussion I learned why it is correct to interprete commands like INCREMENT or DECREMENT at the outgoing binding - and that there is an option that solved my issue.
So I’m happy that at least the IncreaseDecreaseType of the DimmerItem is used internally :slight_smile:

I have no aversion in general, I just want to make use of existing OH internas, because somebody added them for a reason.

Exactly, but as said, there are features in OH that have been designed with such use cases in mind, so I want to use them as far as possible.

When I have a look into these forums here I often have the feeling that shown solutions are found because people don’t understand the possibilities of OpenHab.

Well then, since you know more than us and have more insight into what the developers intended, why are you here asking for help and any are you still unable to reach your goal? And why aren’t you more active on the forum because, you’ve just called us incompetent perhaps you can do a better job.

Yes, I think in the case of dimmer type channel the implementation is not complete. Because it does some pre-emptive numeric work on INCREASE/DECREASE, it is not currently possible to pass those as-is to the MQTT payload.

That’s correct. All profiles are associated with channel-Item links. There is no such thing as a channel-channel link, so no profiles either.

Once you give in and use an Item, the ‘follow’ profile may have uses here.

So, apologies that my sentence was misunderstanding - it was already late yesterday so I missed to explain it in more detail.
It was not meant in general and I fully acknowledge that also many very good solutions are shown in the forums.
However, I still see a discrepancy between the potential of OH and the way it is used by its users.

I also want to point out that the I got help here and that now I don’t need to translate the INCREMENT/DECREMENT strings to commands in a rule.
I also intended to start a discussion about possible improvements and so I will create a feature request that OnOffType shall support a TOGGLE command.
Also other improvements like command forwarding may be a good idea, so some feedback here is still welcome.

Well, unfortunately I don’t have the time to participate more in discussions.

Improving an automation system needs more effort than other software because it is hard to have a test environment when real devices are involved.

I admin two instances, one at home, one at the local FabLab. Both are in “production” use and control at least the room heating. So, in case of problems there is usually not that much time to try it and investigate the root cause.
For instance, after upgrade to OH3.2 my home instance had some stability issues (out of heap space after some hours) - after de-installing several bindings and removing some stale retained topics on MQTT (for a valid Homie Thing) the issue seems to be solved.
I tried to investigate but all I found was more confusing so I don’t think thats enough for a a bug report.

That already took several hours effectively - and there is no way to try again, because it involves interaction with real devices.

For the FabLab instance we thought about having an extra test system that receives all real MQTT data but outgoing MQTT messages are not send back to the real network/broker.
This also don’t work because:

  • feedback from devices is necessary to test rules etc.
  • not all devices where connected by MQTT and the other protocols always rely on direct connection.

Not that it cannot be revisited, but be aware of previous discussions

Maybe instead of rule you could rely on profile? There is an option with smarthome/j and trigger profile which does that.