OH2.x versus OH3.x Rule "postUpdate(item, state)" mqtt behaviour

hello,
In Openhab 2.x, when a Rule issued a postUpdate(item, state) to an item, the item state will be updated in Openhab, and the item will also re-publish it’s state via linked MQTT message.
Subscribed devices external to OH would also receive notification of the state change.

Observed behaviour in OH3.x
In Openhab 3.x… the same Rule, successfully updates the state of the Item in Openhab interfaces, however, no MQTT message is published from the item that has now changed it’s state.

Question
Is there a different approach/command I can use to tell the switch Item to re-publish it’s state via MQTT?

Thing

Thing topic AllKitchenLightsSwitch "AllKitchenLightsSwitch .thing" @ "Group Switches" {
    Channels:
    Type switch : light       "AllKitchenLightsSwitch .thing"[
    commandTopic="myhome/HMI/page0/group/KitchenAllLights/switch/state", transformationPattern="MAP:switchboard.map",
    stateTopic="myhome/group/KitchenAllLights/switch/command",
    postCommand=true]
    }

example
Rule

rule "KitchenAllLightsSwitch state OFF"
when
        Item gAllKitchenLights changed to OFF
then
        logInfo( "RULE KitchenAllLightsSwitch state", "gAllKitchenLights Received state OFF. State=" + gAllKitchenLights.state + ". KitchenAllLightsSwitch status is now OFF");
        //only change the status of the swich when any all group lights are OFF.  Don't send a command this will turn all the lights OFF!
        postUpdate(AllKitchenLightsSwitch, OFF);
end

What do I use this for?
I have bunch of switch Items linked to a group (gAllLightsGswitch)
When any group members are ON, I set the status of a Switch AllKitchenLightsSwitch "All Kitchen Lights switch" (gAllLightsGswitch) to ON.
This allows me to have a switch that can turn on all group members, or turn off all group members from a single switch.

As group members are turned on, the group switch item is correctly updated in OH3 interfaces.

I use the published MQTT state message to update the state of a button on external devices (Arduino touch screen controller) with the status of the switch.

If I Command the group switch manually by triggering the thing switch, or Item, all MQTT messages are published correctly.

Maybe there is a configuration parameter similar to isCommand=True that changes the behaviour of State updates?

Worst case, I guess I can update the Rule to publish the required MQTT state message to the broker. The downside to this approach is the MQTT topic is then maintained in multiple locations. Once in the Thing and Item, and another copy of it manually maintained in the Rule. Not the end of the world.

YAML

UID: mqtt:topic:pi4MqttBroker:AllKitchenLightsSwitch
label: AllKitchenLightsSwitch .thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:pi4MqttBroker
location: Group Switches
channels:
  - id: light
    channelTypeUID: mqtt:switch
    label: AllKitchenLightsSwitch .thing
    description: null
    configuration:
      postCommand: true
      retained: false
      formatBeforePublish: "%s"
      commandTopic: myhome/HMI/page0/group/KitchenAllLights/switch/state
      transformationPattern: MAP:switchboard.map
      stateTopic: myhome/group/KitchenAllLights/switch/command
      off: "0"
      on: "1"

You just want one switch to turn off or on all the devices in the group?
If so this may work.
Create a group.

Then add the direct group members (the devices) to the item group.

You can still turn the lights on indivdually it you want:
image

Or turn the whole group on or off:
image

In the example above the Japanese lamps are offline as they are only turned on at sunset. That is why they are in an off state.

Don’t know if this is exactly what you are after but it may come in handy for someone else later.

Thanks ubeaut. Appreciated.

Similar to your example, I have group switches working fine in OH2.x and in OH3.x. So I’m comfortable with the concept.

In the example you’ve provided;

  1. when any group member switch turns ON, Group All Lights switch will change its STATE to ON. All good.
  2. As you turn group members OFF, when all group members are OFF, then the “Group All Lights” switch will change it’s STATE to OFF.
  3. If you manually switch the item Group All Lights ON, then this will be a COMMAND ON, and COMMAND all group members to be ON.

With the good working use-case above,

  • The COMMAND actions cause Mqtt messages to be Published.
    If only the STATE is changed then a Rule is needed to observe the change, and ask the Group Switch item to re-publish its state. So extends mqtt devices are aware of the state change.

All good. And this works fine for me in OH2 and OH3.

My problem is related to item 1 above, when the STATE of the “Group All Lights” changes (not COMMAND, just STATE), i used a Rule in OH2 to see the Group All Lights had changed and request Group All Lights to re-publish it’s state.
This told the Group All Lights to re-publish its state via MQTT using the postUpdate(item, ON);

Maybe this then? If an item in the group state changes then post and update of the current state of each item in the group?

triggers:
  - id: "2"
    configuration:
      groupName: gAllLights
    type: core.GroupStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript
      script: >
        var logger =
        Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' +
        ctx.ruleUID);


        ir.getItem("gAllLights").members
                           .stream()
                             .forEach(function(batt) {events.postUpdate(batt.name, batt.state)
                                                       logger.info('\r\nGroup list: \r\n' + batt.name +" " + batt.state)
        });
    type: script.ScriptAction

Thanks for the example java code. I’ll have a play and see if it makes any difference.

i note the essence of where the code ends up is the the same postUpdate function called from my rule earlier in the post, but with some elaborate java code providing some additional logic.

I’ll give it a try and see what happens.

I did notice that you have the state topic as the command and the command topic as the state so the javascript may do something totally different.

You can just send the ON postupdate like you have in your original script.
eg events.postUpdate(batt.name, “ON”)

Yes, CommandTopic is outbound from openhab to the mosquito broker. This outbound message drives the state of the button on the touch screen controller which is subscribed to the topic.

If state is ON, button is yellow.

So if the Openhab All Lights switch is ON in Openhab, it will notify external devices.

This is working fine when I COMMAND the switch ON or OFF manually by hand or Mqtt message, or by pressing ON OFF on touch display.

But does not sent the command topic when only the state changes.

The photo of the touch screen is taken from OH2.x setup. Notice the top ON OFF buttons. These are the group control buttons/items. They are auto updated by state topic in OH2, but cannot get the same to work in OH3.

Each button is a thing channel.

What if, because your topics are reversed you have a rule that reacts when the command changes as the way you have it set up is the state topic and then you post the update…just a thought.

:slight_smile: yes. Agreed. That is possible. I have tested with mosquito subscribed to all topics.
when I command the ‘All Group switch’. All group items are turned ON or OFF correctly and the appropriate State message is sent. So messages are correct when commanded. But not on status change.

Sending messages must be form the commandTopic.

OH3 stateTopic is inbound only.

If I use mqtt to change the state of the ‘ All Group switch’, mosquito sub shows no changes. So nothing is being sent to Mqtt broker on state change.
Hence trying to use a Rule todo it for me.

I am going to hard code mqtt publish statement into the Rule later tonight. The Rule already detects the All Group switch State change OK. I just need to develop the mqtt message topics with payload 0 or 1.
This will fix the problem, but I feel like I’m cheating! and it’s just different behaviour to my OH2 setup where I could tell the ‘All Group switch’ to republish its state via mqtt using a Rule ‘postUpdate(item, state)‘

I’ll share what I’ve done when finished.

That’s not an OH2 feature, it’s a feature of the MQTT version 1 binding that you were using.

You can no longer use v1 bindings under OH3, so you must work with whatever features the OH2/3 Things and channels binding provides.

As a fundamental principle, the openHAB workflow is that commands to Items result in bindings sending messages to devices.
Messages arriving from devices are interpreted by bindings as Item state updates.

Command representing “do something” instructions.
State representing “it’s like this” conditions.

A few bindings allow full or partial reversal of this workflow.
There are valid reasons to do that, for instance pressing a button on a control panel is more accurately represented as command in openHAB.
The same panel might have an indicator light, which should follow the state of an openHAB Item, requiring state changes to result in device messages.

MQTT v2 binding only allows re-positioning incoming messages as commands.
MQTT v2 binding does not offer a means to directly map Item state changes to device messages.

So you have to build your own with rules and Actions.

1 Like

Also if you really want to know the state of the item then you can take the force autoupdate off the metadata of the item and the state will only update when the device sends back the state via the state topic. There is a bit of a time lag though.

I have updated the Rule to publish a mqtt state message to the HMI screens to keep them in sync. All working as expected now.
Posting Rule below incase it is useful to someone else.

Logic = if the Openhab switch item changes state… then send a mqtt state message on HMI state topic so the HMI updates the state of the touch screen display button.

// sets the AllLightsSwitch state on HMI touch screens when any gAllLights group member is turned ON
rule "AllLightsSwitch state ON"
when
	Item gAllLights changed to ON
then
        logInfo( "RULE AllLightsSwitch state", "gAllLights Received state ON. State =" + gAllLights.state + ". AllLightsSwitch status is now ON");
        //only change the status of the swich when any item in gAllLights is turned on.  Don't send a command this will turn all the lights on!
	//postUpdate(AllLightsSwitch, ON);
        val mqttval = getActions("mqtt","mqtt:broker:pi4MqttBroker");
        mqttval.publishMQTT("myhome/HMI/page0/group/AllLights/switch/state", "1");
end

// sets the AllLightsSwitch state on HMI touch screens when any gAllLights group member is turned OFF
rule "AllLightsSwitch state OFF"
when
        Item gAllLights changed to OFF
then
        logInfo( "RULE AllLightsSwitch state", "gAllLights Received state OFF. State =" + gAllLights.state + ". AllLightsSwitch status is now OFF");
        //only change the status of the swich when any all group lights are OFF.  Don't send a command this will turn all the lights OFF!
        //postUpdate(AllLightsSwitch, OFF);
        val mqttval = getActions("mqtt","mqtt:broker:pi4MqttBroker");
        mqttval.publishMQTT("myhome/HMI/page0/group/AllLights/switch/state", "0");
end