OpenHab reacting to specific message on MQTT

Hi, I’m having a really hard time figuring this out so maybe there’s someone who already did it.

I’m usung Espurna firmware with Sonoff 433 bridge. I want to turn a switch on and off from messages read from an MQTT topic that the bridge publishes to, for example:

Message posted to bridge/rfin with the payload ABC123 should make a switch go ON
Message posted to bridge/rfin with the payload DEF456 should make a switch go OFF

I tried a lot of combination but the only thing I was able to respond in any way was to react to all messages posted on the bridge/rfin topic which is just not good enough.

Can anyone post an example of an item that does respond with a switch on and off upon receiving 2 different, specified payloads on an MQTT topic?

Better yet, imagine there is a 3rd value, XYZ987, that when posted on the bridge/rfin topic should toggle that switch (if it was on update its state to off and the other way around).

What I am trying to implement is as follows:

  • I have a relay that can be switched on and off by 3 codes: a code for toggle, a code for on and a code for off
  • I have a physical switch (mounted on the wall) that shall toggle the relay that in turn turns a light on and off (that happens without the need for OpenHab just simply by toggling the relay). That switch works on the 433MHz band by sending a code (XYZ987) which the relay interprets immediately and toggles the relay.
  • If the code for toggle is sent on 433MHz I need OpenHab to register that message and toggle the state of a switch to reflect the actual state of the light
  • If a user toggles a switch in the UI I need that toggle code to be sent on 433MHz
  • If a user turns the switch ON then the proper code should be sent
  • If a user turns the switch OFF then the proper code should be sent

Thanks for any help you can provide!

DO you have any items already set-up and code to publish?

As far as I read the documentation for ESPurna, You would need to define some Items:

items:

Number myMQTTsend    {mqtt=">[{root topic}/rfout/set:command:*:MAP(rf_sendcodes.map)]"}
Number myMQTTreceive {mqtt="<[{root topic}/rfin:state:MAP(rf_reccodes.map)]"}

Number myRFswitch1 "Switch is [MAP(rf_onoff.map):%s]" {autoupdate="false"}

transform/rf_sendcodes.map:

0=DEF456
1=ABC123
2=XYZ987
NULL=
-=

transform/rf_reccodes.map:

XYZ987=1
NULL=-
-=-

transform/rf_onoff.map:

0=OFF
1=ON
NULL=-
-=-

some rules:

rule "rf switch receive"
when
    Item myMQTTreceive received command                                   // maybe 'received update' here
then
    if ((myMQTTreceive.state as Number) == 1) {                           //received TOGGLE
        if (myRFswitch1.state instanceof Number)                          //can't toggle state if state is uncertain
            myRFswitch1.postUpdate(1 - (myRFswitch1.state as Number))     //Toggle state
        myMQTTreceive.postUpdate(NULL)
    }
end

rule "rf switch send"
when
    Item myRFswitch1 received command
then
    switch (receivedCommand) {
        case 0 : {                                                        //OFF
            myMQTTsend.sendCommand(0)
            myRFswitch1.postUpdate(0)
        }
        case 1 : {                                                        //ON
            myMQTTsend.sendCommand(1)
            myRFswitch1.postUpdate(1)
        }
        case 2 : {                                                        //TOGGLE
            myMQTTsend.sendCommand(2)
            if(myRFswitch1.state instanceof Number)                       //can't toggle state if state is uncertain
                myRFswitch1.postUpdate(1 - (myRFswitch1.state as Number)) //Toggle state
        }
    }
end

finally, in the sitemap:

Switch item=myRFswitch1 mappings=[0="OFF",1="ON",2="TOGGLE"]

Please be aware that the presented state will only be guessing when the switch is toggled, so it can be out of sync until you switched once through the UI.

The first item is to send messages to the bridge. The code to send is set in a .map file, so you can easily provide more codes.
The second item is to receive messages from the bridge. the received code is also transformed through another .map file

When the toggle code is received, the first rule will toggle the state of myRFswitch1 and afterwards will “erase” the received message.
If switching through the UI, the second rule takes care of sending the code and setting the switch to the correct state. Therefor openHAB should not set the state itself (autoupdate="false").

If you don’t need the TOGGLE Button in the UI, you could also use a simple Switch Item for myRFswitch1 and use some other code to toggle the switch in the UI. You won’t need to update the switch state but delete autoupdate="false", as there will be only the two possible states which are sent.

Woow! Thank you! I’ll definitelly check that out! I had no idea this would be so complicated…

I think the main problem that I have had was with Espurna posting messages to one topic with different content. I approached the matter using the transform EIP and created a processor in JavaScript that listens to the {root}/rfin topic, processes the content in such a way that it extracts the last 6 characters of the message (I call it the “code”) and then posts a message to {root}/rfin/{code} with content “1” to signify that the code has been received.

Similarly, for symmetry, I have created a listener for the {root}/rfout/set/{code} that standardizes the preamble and pulse widths and sends a message to {root}/rfout/set with the complete code to be transmitted over 433MHz

With that in place I have created the following items file:

Switch Relay { mqtt=">[mqtt:sonoff-rf-bridge/rfout/set/ABC123:command:ON:1], >[mqtt:sonoff-rf-bridge/rfout/set/DEF456:command:OFF:1], <[mqtt:sonoff-rf-bridge/rfin/ABC123:command:ON:1], <[mqtt:sonoff-rf-bridge/rfin/DEF456:command:OFF:1]" }
Switch RelayToggle { mqtt="<[mqtt:sonoff-rf-bridge/rfin/XYZABC:command:ON:1]" }

This already provided me a way to detect actual ON/OFF when sent over 433MHz and to react to the Toggle switch in some way. For that I created the following simple rules file:

rule "Toggle relay"
when
  Item RelayToggle received command
then
  if (Relay.state == ON) {
    postUpdate(Relay, OFF)
  } else {
    postUpdate(Relay, ON)
  }
end

With that in place everything works as expected!

Please keep in mind, that this setup will allow you to command more than one RF433 Switch, you only have to add the command strings and an unbound Item per Switch (i.e. without a binding other than {autoupdate="false"})
In the two rules only the same set of lines is to be added (and I think it’s possible to do it in a more clever way, by using groups, but let’s keep the rules simple for now :wink: )

The point is, there is no State answer by the actuator, so you have to create an answer within the rules. And you want a toggle option, but that is uncommon in openHAB, as you will have to guess the state (especially if there is no way to get the real state). If using only ON and OFF message, you could do it this way:

Switch myRFswitch1 "Switch" {mqtt=">[{root topic}/rfout/set:command:OFF:DEF456],>[{root topic}/rfout/set:command:ON:ABC123]"}

No rule for send and state update at all! This way the Switch will send the command directly, the state of the switch is set by the sent command. But when the switch is toggled through the light switch, there is no way to get the real state, but you have to guess with the rf receive rule.

That guessing the state is pretty obvious now. Thanks!

Just in case someone wanted to play around with that processor here it is: