Send all switch status as one MQTT String?

Hi

Hardware is Raspberry PI running Openhabian 4.3.1

I’m trying to send the status of 20 switches (on/off) as a string of 0 and 1. So for example if switch 1 and 3 are ON and the others are OFF I want to send:
10100000000000000000
to an MQTT topic.

I know how to create and manage MQTT, I’ve worked with this a lot.

I guess I need a rule that fires each time any switch is updated and gets the status into a string. I don’t understand how to collect the status of all the switches and put in a string (or array) together

I’ve done a lot with Openhab before but this is new to me.

Many thanks for any pointers

I assume that you have a reason not to use a more verbose / descriptive message (e.g. json), so I’m not going to suggest that here.

To do what you want:

  • Put all the switches into a group
  • Make sure you have a way to sort these switches so that their relative position is maintained in that string, e.g. by its naming, Switch1, Switch2, or by some metadata.
  • Use a rule that triggers on member changes
  • Build the string

Example in JRuby using naming sort

rule "Update MQTT string for switches" do
  changed SwitchGroup.members
  run do |event|
    message = event.group.members.sort_by(&:name).map { |switch| switch.on? "1" : "0" }.join
    things["mqtt:broker:BROKERNAME"].publish_mqtt("your/topic/here", message)
  end
end

This rule can be made generic and work for multiple switch groups. Let me know if you need that.

1 Like

In JS, with the same assumptions as @jimtng outlines:

var message = items.SwitchGroup.members.map( i => (i.state == "ON") ? "1" : "0"  ).join();
actions.get('mqtt', 'mqtt:broker:BROKERNAME').publishMQTT("your/topic/here", message, false);

In Blockly you’ll need to use the inline script block or install the MQTT block library from the marketplace.

image

image

In Rules DSL the code would look something like:

val message = SwitchGroup.members.map[ i | if i.state == ON then "1" else "0" ]
                                 .reduce[ result, curr | result + curr ]
getAction('mqtt', 'mqtt:broker:BROKERNAME').publishMQTT('your/topic/here', message)

I mainly post this because hopefully you and future readers can see that overall no matter what you are looking to do it’s going to look fairly similar no matter what language you choose. Consequently, if you see an example that doesn’t match your preferred language, do not give up hope. It’s not too hard to convert from one to the other.

1 Like

@rlkoshak the member list needs to be sorted alphabetically by its name to produce a reliable order.

1 Like

I meant to have the sort in there. But that’s easy enough to just insert the sort after the map and before the reduce. IIRC Blockly had a sort block too but it’s more limited.

...map(...).sort().join()
1 Like

Thanks everyone for your comments! I hadn’t thought of using a group to combine them all together. I would use a numerical item like 01SW_bedroom 02SW_bath to keep them in permanent order.

I’ll give this a try in a week when I get back home and let you know how it goes.

Controlling the end device by CANbus so I have to go via MQTT because that seems the easiest way. There is no CANbus solution in OpenHab that I can find. There is already existing MQTT to CANbus solution which requires the data to be formatted specifically.

It used to be the case that you cannot start an Item name with a number so be careful. I think that might still be the case.