Sending string over MQTT for ON/OFF control

  • Platform information:
    • Hardware: Raspberry Pi 3 Model B
    • OS: openHABian
    • Java Runtime Environment: openjdk version “1.8.0_152”
    • openHAB version: 2.4.0-1
    • MQTT Binding 1.13.0
    • mosquitto version 1.4.10

Firstly I humbly apologise as this is a redundant topic. I’ve searched the openHAB forum and have found several similar problems but unfortunately for me (being a noob with openHAB, MQTT etc.) I am still not able to figure out how to resolve this issue.

What I am trying to achieve is very simple, make an on/off button in sitemap and control the LED on my development board.

I’ve installed mosquitto, and the MQTT broker works fine. I’m using MQTT.fx 1.7.1 on my MacOS to check the topics.

Here’s the problem:

To turn on/off the LED on the development board:
Topic = iot-2/cmd/leds/fmt/json
String = {\”led\”:\”red\”,\”value\”:1} (turning ON the red LED)
String = {\”led\”:\”red\”,\”value\”:0} (turning OFF the red LED)

Using MQTT.fx, I am able to publish the string to the topic, turning the LED on/off works.
52%20PM

Here’s the content (with screenshot of the actual file for better clarification) of my Items file:

String  S1_LED_RED  "S1 LED Red"  {mqtt=">[<broker>:iot-2/cmd/leds/fmt/json:command:*:default]"}

Here’s the content of my Rules file:

    rule "Update 6LoWPAN Module Switch Items"
    when
        Item S1_LED_RED received command TOGGLE
    then
        if(S1_LED_RED == OFF) {
            S1_LED_RED.sendCommand("{\”led\”:\”red\”,\”value\”:0}")
        }
        else {
            S1_LED_RED.sendCommand("{\”led\”:\”red\”,\”value\”:1}")
        }
    end

Here’s the content of my Sitemap file:

Switch item=S1_LED_RED label="S1 Red LED" mappings=[,{\”led\”:\”red\”,\”value\”:1}=ON]

And this is what my sitemap looks like:

Can someone please help point the mistake/s I’ve done.

Thanks

Do you have the MQTT1 or MQTT2 binding installed? That Item syntax is an old MQTT1 binding syntax and will not work with the MQTT2 binding.

Please don’t post screenshots of code. It’s impossible to read from a phone and impossible to copy and edit.

Thank you for your reply.

Do you have the MQTT1 or MQTT2 binding installed?

I have the MQTT Binding 1.13.0

Please don’t post screenshots of code

I’ve posted the related line of codes above each screenshots. The screenshots display the whole content of the files (so others who may have similar questions can better understand the problem and possible solution to this issue)

OK MQTT1. Did you properly populate mqtt.cfg with the connection information for your broker?

<broker> is incorrect. This needs to be replaced with whatever you configured your broker name to be in mqtt.cfg. See the comments in mqtt.cfg for details.

You have eagle eyes.

I’ve changed <broker> to broker (as configured in mqtt.cfg)

Here’s the error i get when I turn the switch on and off in sitemap.

==> /var/log/openhab2/openhab.log <==

2019-04-03 01:12:54.502 [ERROR] [org.influxdb.impl.BatchProcessor    ] - Batch could not be sent. Data will be lost

java.lang.RuntimeException: {"error":"partial write: field type conflict: input field \"value\" on measurement \"S1_LED_RED\" is type string, already exists as type float dropped=1"}
	at org.influxdb.impl.InfluxDBErrorHandler.handleError(InfluxDBErrorHandler.java:19) ~[206:org.openhab.persistence.influxdb:1.13.0]
	at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:242) ~[206:org.openhab.persistence.influxdb:1.13.0]
	at org.influxdb.impl.$Proxy134.writePoints(Unknown Source) ~[206:org.openhab.persistence.influxdb:1.13.0]
	at org.influxdb.impl.InfluxDBImpl.write(InfluxDBImpl.java:151) ~[206:org.openhab.persistence.influxdb:1.13.0]
	at org.influxdb.impl.BatchProcessor.write(BatchProcessor.java:171) [206:org.openhab.persistence.influxdb:1.13.0]
	at org.influxdb.impl.BatchProcessor$1.run(BatchProcessor.java:144) [206:org.openhab.persistence.influxdb:1.13.0]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]

That’s an error from InfluxDB and will have nothing to do with the MQTT problems.

It’s complaining that S1_LED_RED is a String Item but at some point it was a Number Item perhaps. It usually requires some cleanup of the database when you change the type of an Item after it is being saved to a database.

1 Like

I’m a bit confused here.

In the .items file, S1_LED_RED is defined as a String.

In the .rules file, this is what i have: Item S1_LED_RED received command TOGGLE…

In the .sitemap file, Switch item=S1_LED_RED…

Can this work? Being a ‘string’ in another file, and a ‘switch’ in another? Is the item S1_LED_RED in each file is not related to the other?

They are most definitely related to each other. Was S1_LED_RED a Switch at some point and you changed it to a String? That would be the source of your error. But again, this error has nothing to do with MQTT.

If S1_LED_RED is a String, it will never receive a TOGGLE command, unless you are sending the String “TOGGLE” to it.

You can use any Item type as a Switch on the sitemap. In that case it is just controlling how it appears. Though if you don’t provide a mappings the sitemap will only send ON and OFF commands. And I’ve no idea how it would treat a “TOGGLE” state in the Item.

Based on a reply in this posting: Sent string commands via MQTT

I should have this in the .items file:

String S1_LED_RED "S1 LED Red" {mqtt=">[broker:iot-2/cmd/leds/fmt/json:command:*:default]"}

And a mapping in my .sitemap file, so I’ve entered the following line:

Switch item=S1_LED_RED label="S1 Red LED" mappings=[{\”led\”:\”red\”,\”value\”:1}=ON,{\”led\”:\”red\”,\”value\”:1}=OFF]

I’ve got the following error:

2019-04-03 01:37:00.211 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model '6LoWPAN.sitemap' has errors, therefore ignoring it: [7,65]: no viable alternative at input '{'
[7,81]: mismatched input ',' expecting '='
[7,82]: no viable alternative at input '\'
[7,93]: extraneous input '}' expecting '='
[7,98]: no viable alternative at input '{'
[7,114]: mismatched input ',' expecting '='
[7,115]: no viable alternative at input '\'
[7,126]: extraneous input '}' expecting '='

Allow me to simplify the question.

Using MQTT.fx, publishing the following string to the topic turns the Red LED ON:
32%20AM
While publishing this string, turns it OFF:
50%20AM

What are the required codes in the:

  • .items
  • .rules
  • .sitemap

I’m in no position to write this for you right now.

Look in your logs to see if the MQTT binding is generating any connection errors.

You need a Switch Item. You need to configure the MQTT binding as an outgoing connection as documented in https://www.openhab.org/addons/bindings/mqtt1/.

Use “*” for the Trigger and create a map transformation to transform ON to that full JSON string and OFF to the other full JSON string.

Assuming you have control over the end point, why make this hard on yourself. Just use a separate topic for each color and let it accept ON and OFF as commands.

I managed to get it to work by adding the following codes to my rules:

1st rule to turn on the led

rule "Turn Red LED ON"
when
    Item S1_LED_RED received command ON
then
    var jsonString = "{\"led\":\"red\",\"value\":1}"
    S1_LED_RED_CMD.sendCommand(jsonString)
end

2nd rule to turn off the led

rule "Turn Red LED OFF"
when
    Item S1_LED_RED received command OFF
then
    var jsonString = "{\"led\":\"red\",\"value\":0}"
    S1_LED_RED_CMD.sendCommand(jsonString)
end

I have tried to code a single rule for both ON/OFF state, but unfortunately it doesn’t work.

rule "Turn LEDs ON/OFF"
when
Item S1_LED_RED received command
then
if(S1_LED_RED == OFF) {
    var jsonString = "{\"led\":\"red\",\"value\":0}"
    S1_LED_RED_CMD.sendCommand(jsonString)
}
else {
    var jsonString = '{\"led\":\"red\",\"value\":1}'
    S1_LED_RED_CMD.sendCommand(jsonString)
}
end

On every switch toggle, only the ‘{“led”:“red”,“value”:0}’ string gets published, is there anything wrong with the single rule?

You need to use the state of the Item.

if(S1_LED_RED.state == OFF)
1 Like

Thanks, that go it to work.

Final question, there are 4 LEDs to control and I created a group called ‘LEDs’ in items. I tried using the following code but only the first and the last string gets published when all 4 buttons are toggled ON.

rule "Turn LEDs ON"
when
    Member of LEDs received command ON
then
if( S1_LED_RED.state == ON ) {
    var jsonString = "{\"led\":\"red\",\"value\":1}"
    S1_CMD.sendCommand(jsonString)  
}else if( S1_LED_YELLOW.state == ON ) {
    var jsonString = "{\"led\":\"yellow\",\"value\":1}"
    S1_CMD.sendCommand(jsonString) 
}else if( S1_LED_GREEN.state == ON ) {
    var jsonString = "{\"led\":\"green\",\"value\":1}"
    S1_CMD.sendCommand(jsonString) 
}else ( S1_LED_BLUE.state == ON ) {
    var jsonString = "{\"led\":\"blue\",\"value\":1}"
    S1_CMD.sendCommand(jsonString) 
}
end

Is it possible to have this "If > else if > else" statement?

Yep; only one of the cases is executed. But -

is a nonsense. Either its just else or its else if (condition)

Have you looked in openhab.log? I would imagine that sets jsonString to "{" (a string) and generates an error for the unexpected led”:“red”,“value”:1}” stuff.

@rossko57, you are right. The if, else if and else is buggy when used. So I had to create an ON/OFF rule for every LED.

Here’s how I finally got it to work (thanks to @rlkoshak’s input).

PROBLEM SUMMARY: Turning the LEDs ON/OFF (Red, Yellow, Green & Blue) on my development board by sending JSON strings over MQTT.

The topic to publish to: iot-2/cmd/leds/fmt/json
The JSON string to publish:

  • to turn OFF the Red LED: {\”led\”:\”red\”,\”value\”:0}
  • to turn on the Red LED: {\”led\”:\”red\”,\”value\”:1}
  • to turn OFF the Yellow LED: {\”led\”:\”yellow\”,\”value\”:0}
  • to turn on the Yellow LED: {\”led\”:\”yellow\”,\”value\”:1}
  • to turn OFF the Green LED: {\”led\”:\”green\”,\”value\”:0}
  • to turn on the Green LED: {\”led\”:\”green\”,\”value\”:1}
  • to turn OFF the Blue LED: {\”led\”:\”blue\”,\”value\”:0}
  • to turn on the Blue LED: {\”led\”:\”blue\”,\”value\”:1}

SOLUTION:

Codes in the ‘.items’ file. (/etc/openhab2/items/MyDevBoard.items)

//String variable to send commands:
String S1_CMD {mqtt=">[broker:iot-2/cmd/leds/fmt/json:command:*:default]"}

// 4 switches (1 for each LED colour):
Switch   S1_LED_RED     "S1 LED Red" 
Switch   S1_LED_YELLOW  "S1 LED Yellow"
Switch   S1_LED_GREEN   "S1 LED Green"
Switch   S1_LED_BLUE    "S1 LED Blue"

Codes in the ‘.rules’ file (/etc/openhab2/rules/MyDevBoard.rules)

//Rule for controlling the red LED (On/Off)
rule "Turn Red LEDs ON/OFF"
when
Item S1_LED_RED received command
then
if(S1_LED_RED.state == ON) {
    var jsonString = "{\"led\":\"red\",\"value\":1}"
    S1_CMD.sendCommand(jsonString)
}
else {
    var jsonString = '{\"led\":\"red\",\"value\":0}'
    S1_CMD.sendCommand(jsonString)
}
end

//Rule for controlling the yellow LED
rule "Turn Yellow LEDs ON/OFF"
when
Item S1_LED_YELLOW received command
then
if(S1_LED_YELLOW.state == ON) {
    var jsonString = "{\"led\":\"yellow\",\"value\":1}"
    S1_CMD.sendCommand(jsonString)
}
else {
    var jsonString = '{\"led\":\"yellow\",\"value\":0}'
    S1_CMD.sendCommand(jsonString)
}
end

//Rules for controlling the blue LED
rule "Turn Blue LEDs ON/OFF"
when
Item S1_LED_BLUE received command
then
if(S1_LED_BLUE.state == ON) {
    var jsonString = "{\"led\":\"blue\",\"value\":1}"
    S1_CMD.sendCommand(jsonString)
}
else {
    var jsonString = '{\"led\":\"blue\",\"value\":0}'
    S1_CMD.sendCommand(jsonString)
}
end

//Rules for controlling the green LED
rule "Turn Green LEDs ON/OFF"
when
Item S1_LED_GREEN received command
then
if(S1_LED_GREEN.state == ON) {
    var jsonString = "{\"led\":\"green\",\"value\":1}"
    S1_CMD.sendCommand(jsonString)
}
else {
    var jsonString = '{\"led\":\"green\",\"value\":0}'
    S1_CMD.sendCommand(jsonString)
}
end

Codes in the ‘.sitemap’ file. (/etc/openhab2/sitemaps/MyDevBoard.sitemap)

sitemap MyDevBoard label="My Dev. Board LEDs" {
    Frame  {
            Switch item=S1_LED_RED    label="S1 Red LED"
            Switch item=S1_LED_YELLOW label="S1 Yellow LED"
            Switch item=S1_LED_GREEN  label="S1 Green LED"
            Switch item=S1_LED_BLUE   label="S1 Blue LED"
    }
}

This is the input in the log file (/var/log/openhab2/openhab.log) every time I toggle the switches. In this case, I toggled the switch ON for my red LED.

2019-04-03 11:04:49.828 [ome.event.ItemCommandEvent] - Item 'S1_LED_RED' received command ON
2019-04-03 11:04:49.851 [vent.ItemStateChangedEvent] - S1_LED_RED changed from OFF to ON
2019-04-03 11:04:49.879 [ome.event.ItemCommandEvent] - Item 'S1_CMD' received command {"led":"red","value":1}
2019-04-03 11:04:49.893 [vent.ItemStateChangedEvent] - S1_CMD changed from {"led":"blue","value":0} to {"led":"red","value":1}

Finally some pictures. This is how my sitemap looks like.


This is the development board with all the LEDs turned ON. More info about this module Sanmulink’s CC2538 module.

And this is when all the LEDs are turned OFF


Hope this helps. Cheers

This should shorten the rules a bit:

//Rules for controlling the green LED
rule "Turn LEDs ON/OFF"
when
    Member of LEDS received command
then
    val ledName = triggeringItem.name.split("_").get(2).toLowerCase()  // S1_LED_GREEN to green
    val payload = if (recievedCommand == ON) "1" else "0"
    var jsonString = "{\"led\":\"" + ledName + "\",\"value\":" + payload + "}"
    S1_CMD.sendCommand(jsonString)
end
2 Likes

Thanks @vzorglub. I will try that rule and report back :slight_smile: