MQTT switch help

Hello, I’m a newbie here and jump to OH2 directly.
Recently I follow @rlkoshak code to setup one Switch by the code at the end of demo.items:

Switch LED02 				{mqtt=">[mosquibroker:/ESP_Easy_01/GPIO/2:COMMAND:ON:0],>[mosquibroker:/ESP_Easy_01/GPIO/2:COMMAND:OFF:1],<[mosquibroker:/ESP_Easy_01/GPIO/2:state:default]"}
Number LED02_Status			{mqtt="<[mosquibroker:/ESP_Easy_01/GPIO/2:state:default]"}
Switch proxyLED02 

and the code at the end of demo.rules:

rule "proxyLED02 changed"
    when
        Item proxyLED02 received command
    then
        LED02.sendCommand(proxyLED02.state)
    end

rule "LED02_Status updated"
    when
        Item LED02_Status received update
    then
        if(LED02_Status.state == 0) proxyLED02.postUpdate(ON)
        else proxyLED02.postUpdate(OFF)
    end

and the code at the end of demo.sitemaps:

Frame  label="MQTT Test"{
    Switch item=proxyLED02 label="LED 02"
}

and my addons.cfg is:

# The base installation package of this openHAB instance
# Valid options:
#   - minimal  : Installation only with dashboard, but no UIs or other addons
#   - standard : Typical installation with all standards UIs
#   - demo     : A demo setup which includes UIs, a few bindings, config files etc.
package = demo

# A comma-separated list of bindings to install (e.g. "sonos,knx,zwave")
binding = mqtt

# A comma-separated list of UIs to install (e.g. "basic,paper")
ui = basic

# A comma-separated list of persistence services to install (e.g. "rrd4j,jpa")
persistence = mqtt

# A comma-separated list of actions to install (e.g. "mail,pushover")
action = mqtt

# A comma-separated list of transformation services to install (e.g. "map,jsonpath")
transformation = 

# A comma-separated list of text-to-speech engines to install (e.g. "marytts,freetts")
tts = 

# A comma-separated list of miscellaneous services to install (e.g. "myopenhab")
misc = 

In the bigining, I got no responcse from ESP8266-12 LED when toggle the Switch, but got the logs in openhab.log:

2016-02-19 22:37:11.351 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'proxyLED02' received command OFF
2016-02-19 22:37:11.357 [ERROR] [.script.engine.ScriptExecutionThread] - Error during the execution of rule 'proxyLED02 changed': Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.Number) on instance: null
2016-02-19 22:37:11.377 [INFO ] [marthome.event.ItemStateChangedEvent] - proxyLED02 changed from ON to OFF

After reboot openHAB server (Raspberry Pi 2), it did work! And with the following log data:

2016-02-20 10:41:51.021 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'LED02' received command OFF
2016-02-20 10:41:51.023 [DEBUG] [inding.mqtt.internal.MqttItemBinding] - Publishing command OFF to /ESP_Easy_01/GPIO/2
2016-02-20 10:41:51.025 [INFO ] [marthome.event.ItemStateChangedEvent] - proxyLED02 changed from OFF to ON
2016-02-20 10:41:51.026 [DEBUG] [t.mqtt.internal.MqttBrokerConnection] - Publishing message 34 to topic '/ESP_Easy_01/GPIO/2'
2016-02-20 10:41:51.027 [ERROR] [.mqtt.internal.MqttMessageSubscriber] - Error processing MQTT message.
java.lang.NullPointerException
	at org.openhab.core.events.EventPublisherDelegate.postUpdate(EventPublisherDelegate.java:60)[163:org.openhab.core.compat1x:2.0.0.201602120202]
	at org.openhab.binding.mqtt.internal.MqttMessageSubscriber.processMessage(MqttMessageSubscriber.java:150)[11:org.openhab.binding.mqtt:1.9.0.201602140217]
	at org.openhab.io.transport.mqtt.internal.MqttBrokerConnection.messageArrived(MqttBrokerConnection.java:552)[13:org.openhab.io.transport.mqtt:1.9.0.201602140217]
	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.handleMessage(CommsCallback.java:354)[15:org.eclipse.paho.client.mqttv3:1.0.2]
	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.run(CommsCallback.java:162)[15:org.eclipse.paho.client.mqttv3:1.0.2]
	at java.lang.Thread.run(Thread.java:745)[:1.8.0_65]
2016-02-20 10:41:51.046 [INFO ] [marthome.event.ItemStateChangedEvent] - proxyLED02 changed from ON to OFF

Although sometimes Switch no response (can’t turn on or can’t turn off by first tap, but after 2nd or 3rd tap it will OK), after short period, finally the LED work properly. But the ERROR message still remain in log file.

Can anyone help me to resolve this issue?

And my question is : Should I need “Import” in OH2? Because from the topic OH2 Documentation, Kai seems say no need import anymore in OH2, am I right?

Other question is : I put all the related MQTT bindings to addons directory, including “binding, action, io.transport, persistence, eclipse.smarthome.io.transport, eclipse.paho.client.mqttv3”. Is it OK?

Thanks for the help in advance!

I’ve opened this issue regarding the NullPointerException you see in the OH2 log. The root cause, however, is that the message published to the MQTT topic is not in a format that is acceptable for that kind of item, and so an attempt to convert it into an acceptable state fails. This ought to result in a WARN message in the log, but under OH2, produces a NullPointerException instead.

Once you change what is published to the MQTT broker, or you change the item type so it can accept the message, you will get past this issue!

Thanks @watou, your reply ease my nervous about this error log.
So you mean I can modify item definition on the topic of published message or even item style, isn’t it? I’ll try!

If you openHAB were instead a String item, for example, then any message you publish from your device to the topic, which the item subscribes to, will successfully be delivered, because the message does not have to conform to a specific format. If, on the other hand, you have a Switch item, then the MQTT message either has to be “ON” or “OFF”, or you have to use a transform (instead of default) in the item’s binding string, so that the MQTT message is transformed into either ON or OFF. Only then can the update be posted successfully to the Switch item.

Do you mean change “Switch LED02 {mqtt…” to “String LED02 {mqtt…”, or “Number LED02_Satus …” to “String LED02_Status …”? I try a bit but lost in fog ><
Can you give me much detail advice? Thanks!

It helps more to describe the path from your device -> MQTT broker -> MQTT binding -> transform -> item -> sitemap.

  1. Your device publishes the string “ON” to the topic “/switch” on the broker “broker” when it turns on, and “OFF” when it turns off.
  2. You have a Switch item defined in your items file like this: Switch mySwitch { mqtt="<[broker:/switch:state:default]" }.
  3. You have the item appear in your sitemap with Text item=mySwitch
  4. At this point, you can see the switch turn off and on in the openHAB Classic UI.

Problem is, your device publishes “1” for on and “0” for off. So instead of Switch mySwitch { mqtt="<[broker:/switch:state:default]" }, you have replace default with a transform to turn the MQTT message into the “ON” or “OFF” that openHAB needs for switches. So you would have your item be Switch mySwitch { mqtt="<[broker:/switch:state:MAP(onoff.map)]" } and you would have a file transform/onoff.map with

0=OFF
1=ON

in it. Does this make sense so far?

1 Like

FTR: This has been fixed in the latest build.

Thank you for the fix, Kai!

Hmm, I use ESP8266-12E NodeMCU on board LED (GPIO2) for test. This GPIO2 pin should be pull-down to turn on the LED, so I use “0” to turn “ON” and “1” to turn “OFF” in items file and rules file, then I can have the same state behavior between ESP8266 and openHAB UI. But I didn’t notice that this change maybe conflict with Switch mySwitch { mqtt="<[broker:/switch:state:default]" } statement.
I’ll try to use another pin with external LED to test normal map configuration. Thanks!

Recent build of 2.0.0-SNAPSHOT has remove the NullPointerException issue, thanks.
I test 2 LED in ESP8266-12E NodeMCU board, one is via GPIO2 to sent “0” to turn on the on board LED, other one is via GPIO12 to sent “1” to turn on external LED. I modified the item file:

Switch LED02 	        {mqtt=">[mosquibroker:/ESP_Easy_01/GPIO/2:COMMAND:ON:MAP(onoff_inverse.map)],>[mosquibroker:/ESP_Easy_01/GPIO/2:COMMAND:OFF:MAP(onoff_inverse.map)],<[mosquibroker:/ESP_Easy_01/GPIO/2:state:MAP(onoff_inverse.map)]", autoupdate="false"}
Number LED02_Status	{mqtt="<[mosquibroker:/ESP_Easy_01/GPIO/2:state:MAP(onoff_inverse.map)]"}

Switch LED12 		{mqtt=">[mosquibroker:/ESP_Easy_01/GPIO/12:COMMAND:ON:MAP(onoff.map)],>[mosquibroker:/ESP_Easy_01/GPIO/12:COMMAND:OFF:MAP(onoff.map)],<[mosquibroker:/ESP_Easy_01/GPIO/12:state:MAP(onoff.map)]", autoupdate="false"}
Number LED12_Status	{mqtt="<[mosquibroker:/ESP_Easy_01/GPIO/12:state:MAP(onoff.map)]"}

and the rule file (I use function to unify switch rule):

//Function 1: Switch State Update

val org.eclipse.xtext.xbase.lib.Functions$Function SwitchLogic = [
org.openhab.core.library.items.SwitchItem SwitchItem,
    org.openhab.core.library.items.SwitchItem SwitchState |

    if (SwitchState.state == ON) SwitchItem.postUpdate(ON)
    else SwitchItem.postUpdate(OFF)
]

//Function End

rule "LED02 State Update"

when
	Item LED02_State received update 
then
	SwitchLogic.apply(LED02, LED02_State)
end

rule "LED12 State Update"

when
	Item LED12_State received update 
then
	SwitchLogic.apply(LED12, LED12_State)
end

and the transform map:
onoff_inverse.map :

1=OFF
0=ON
1.00=OFF
0.00=ON
OFF=1
ON=0
OFF=1.00
ON=0.00

onoff.map :

0=OFF
1=ON
0.00=OFF
1.00=ON
OFF=0
ON=1
OFF=0.00
ON=1.00

and the sitemap:

Frame  label="MQTT Test"{
    Switch item=LED02 label="LED 02"
    Switch item=LED12 label="LED 12"
}

When I turn on/off LED 02, the log shows:

14:04:36.065 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'LED02' received command ON
14:04:36.080 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'
14:04:36.089 [INFO ] [marthome.event.ItemStateChangedEvent] - LED02 changed from OFF to ON
14:04:38.278 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'LED02' received command OFF
14:04:38.286 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'
14:04:38.289 [INFO ] [marthome.event.ItemStateChangedEvent] - LED02 changed from ON to OFF
14:04:38.380 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'

LED 02 works properly, even I manual change GPIO pin status from ESP8266, the LED status on my mobile openhab app change immediately and correctly.

But for example, if I change onoff_inverse.map to:

1=OFF
0=ON

the log is:

14:02:23.292 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'LED02' received command ON
14:02:23.300 [WARN ] [rm.AbstractFileTransformationService] - Could not transform 'ON' with the file 'onoff_inverse.map' : Target value not found in map for 'ON'
14:02:23.306 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '' with the file 'onoff_inverse.map' : Target value not found in map for ''
14:02:23.309 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02'
14:02:23.310 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '' with the file 'onoff_inverse.map' : Target value not found in map for ''
14:02:23.313 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'
14:02:23.443 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '0.00' with the file 'onoff_inverse.map' : Target value not found in map for '0.00'
14:02:23.445 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02'
14:02:23.447 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '0.00' with the file 'onoff_inverse.map' : Target value not found in map for '0.00'
14:02:23.450 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'

and if I change onoff_inverse.map to:

1=OFF
0=ON
1.00=OFF
0.00=ON

then the log is:

14:02:30.168 [INFO ] [smarthome.event.ItemCommandEvent    ] - Item 'LED02' received command OFF
14:02:30.174 [WARN ] [rm.AbstractFileTransformationService] - Could not transform 'OFF' with the file 'onoff_inverse.map' : Target value not found in map for 'OFF'
14:02:30.192 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '' with the file 'onoff_inverse.map' : Target value not found in map for ''
14:02:30.196 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02'
14:02:30.199 [WARN ] [rm.AbstractFileTransformationService] - Could not transform '' with the file 'onoff_inverse.map' : Target value not found in map for ''
14:02:30.204 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'LED02_Status'

My question is: Dose the format of MAP file is OK? and, Can you give me some advice on ‘Function’? Like: How to fully qualify each and every reference with the complete package name?

Thank a lot!

No, the map files have duplicate ON and OFF keys. The keys to the left of the = must be unique.

With your MQTT out bindings, I recommend simply specifying the literal value you want to send, instead of using a map, like:

Switch LED02 {mqtt=">[mosquibroker:/ESP_Easy_01/GPIO/2:command:ON:0],>[mosquibroker:/ESP_Easy_01/GPIO/2:command:OFF:1],<[mosquibroker:/ESP_Easy_01/GPIO/2:state:MAP(onoff_inverse.map)]", autoupdate="false"}
Switch LED12 {mqtt=">[mosquibroker:/ESP_Easy_01/GPIO/12:command:ON:1],>[mosquibroker:/ESP_Easy_01/GPIO/12:command:OFF:0],<[mosquibroker:/ESP_Easy_01/GPIO/12:state:MAP(onoff.map)]", autoupdate="false"}

I also suggest using

import org.openhab.core.library.types.*

and other imports at the top of your rules file to simplify, and also writing the code directly in the body of the rule if the function is behaving strangely.

All the best!

Thank you @watou, it works! I use map for inbound message only and modify map file like:

0=OFF
1=ON
0.00=OFF
1.00=ON

There is only one warn log “[b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for ‘LED02_Status’” remain, but I think this maybe issue from ESP8266 because switch state update correctly.

Other question is: Should I need the import section for rules in OH2?

Glad you got it working! The imports aren’t needed for the state types in openHAB 2.

Hi,

I am having a similar problem with the “given new state is NULL, couldn’t post update” message in my logs.

I am using OH2 beta (version from the shell tells me 4.0.4).

I have a switch that I build myself and it it publishes the following messages via MQTT. Topic “name/state” Message “ON” or Message “OFF”.

So I would expect it work find updating a switch without any transformation. I have tested it with a String and thats fine.

Switch TestSwitch {mqtt=“<[mosquitto:name/state:state:default]”}
String TestString {mqtt=“<[mosquitto:name/state:state:default]”}

This is the log output

16:25:49.462 [INFO ] [marthome.event.ItemStateChangedEvent] - TestString changed from ON to OFF
16:25:50.369 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for ‘TestSwitch’
16:25:50.371 [INFO ] [marthome.event.ItemStateChangedEvent] - TestString changed from OFF to ON
16:25:50.988 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for ‘TestSwitch’

Based on what you have said it looks like it should work. Do you have any idea why the switch is always seeing the state change as NULL, when the string sees the update correctly and contains ON and OFF which is what the switch would expect?

Or have I missed something? Thats quiet possible as I have only been trying out OH2 for a day (and never tried OH1)

Regards

Ben

Hi Ben, I agree it ought to work. Try turning on debug logging for the binding in the console:

openhab> log:set DEBUG org.openhab.binding.mqtt

Turning DEBUG on like that did not work, but I just did DEBUG and it turned on for everything. Here is what it gave me :

17:00:59.508 [DEBUG] [o.client.mqttv3.internal.ClientState] - paho70904578979633: received bytes count=1
17:00:59.508 [DEBUG] [o.client.mqttv3.internal.ClientState] - paho70904578979633: received bytes count=27
17:00:59.509 [DEBUG] [mqttv3.internal.wire.MqttInputStream] - null: 501
17:00:59.509 [DEBUG] [o.client.mqttv3.internal.ClientState] - paho70904578979633: received key=0 message=PUBLISH qos:0 retained:false dup:false topic:“VBMC/0100000B-01/state” payload:[hex:4f4e00 utf8:“ON” length:3]
17:00:59.509 [DEBUG] [client.mqttv3.internal.CommsCallback] - paho70904578979633: new msg avail, notify workAvailable
17:00:59.509 [DEBUG] [client.mqttv3.internal.CommsReceiver] - paho70904578979633: network read message
17:00:59.510 [DEBUG] [client.mqttv3.internal.CommsCallback] - paho70904578979633: call messageArrived key=0 topic=VBMC/0100000B-01/state
17:00:59.510 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for ‘TestSwitch’
17:00:59.511 [DEBUG] [client.mqttv3.internal.CommsCallback] - paho70904578979633: notify spaceAvailable
17:00:59.511 [DEBUG] [client.mqttv3.internal.CommsCallback] - paho70904578979633: wait for workAvailable

Does that give you any clues?

Regards

Ben

Hi Watou,

Any thoughts on my situation?

Ben

Hi Ben,

If the MQTT item binding binds a Switch item to “<[broker:topic:state:default]”, then any message published to broker:topic must be a string ON or OFF, no spaces or padding. This ought to resolve to an OnOffType state which is then posted to the item (binding code). But it’s not working, or the strings aren’t exactly ON or OFF.

I don’t know how to interpret the Paho log message “paho70904578979633: call messageArrived key=0 topic=VBMC/0100000B-01/state”, but if “key” meant the message and it is “0”, then you would need to replace “default” in the item binding string with MAP(onoff.map), and the file transform/onoff.map would have to contain:

0=OFF
1=ON

so the binding would try to parse the ON or OFF that it needs. But like I said, “key=0” might not refer to the message itself.

If the above doesn’t help, please post your complete configuration (mqtt lines from openhab.cfg and your items file contents at least, and relavent log lines). Surround the snippets with new lines only containing three backtick marks (```), so it’s easier to spot whitespace padding.

Hi Watou

I would suggest the debug message of interest is this one :

17:00:59.509 [DEBUG] [o.client.mqttv3.internal.ClientState] - paho70904578979633: received key=0 message=PUBLISH qos:0 retained:false dup:false topic:“VBMC/0100000B-01/state” payload:[hex:4f4e00 utf8:“ON” length:3]

From that it would be the payload we are looking at which is 0x4F 0x4E 0x00, a Null terminated string “ON” So I think thats as it should be.

Here is the config I am using:

From mqtt.cfg in conf/services

‘’’
mosquitto.url=tcp://10.20.31.186:1883
mosquitto.qos=1
‘’’

From demo.items in conf/items

‘’’
Switch TestSwitch {mqtt=“<[mosquitto:VBMC/0100000B-01/state:state:default]”}
String TestString {mqtt=“<[mosquitto:VBMC/0100000B-01/state:state:default]”}
‘’’

Hi Ben,

Maybe the NUL termination of the string is unintentionally being considered? Could you use mosquitto_pub at a command line to try to publish just ON and OFF to the topic, and see if the Switch item updates?

mosquitto_pub -t VBMC/0100000B-01/state -m ON
mosquitto_pub -t VBMC/0100000B-01/state -m OFF

(you may need other flags, depending on your configuration)

If using mosquitto_pub causes the Switch item to update and there is no “given new state is NULL, couldn’t post update for ‘TestSwitch’” log message, then you can either change the code that publishes the ON or OFF to not include the NUL termination, or—and this may not work—you might be able to use a MAP file like:

ON\u0000=ON
OFF\u0000=OFF

(kind of a stab in the dark, but try mosquitto_pub anyway to see what happens)