[solved] MQTT: Switch json boolean true/false mapping not working - how to debug?

  • Platform information:
    • openHAB version: docker openhab/openhab:3.2.0
  • Issue of the topic: I get a json with a boolean by MQTT. My configuration is failing to convert it to the switch status. I tried to fix this with Javascript transformation and tried with a map. I do not get any error messages in the openhab.log. How can I debug this?
  • Please post configurations (if applicable):
    • MQTT message on topic zigbee2mqtt/xxx
      {
       "battery_low":false
      }
      
    • Things configuration
      Thing mqtt:topic:zigbee:Lidl_HG06335_HG07310 "Silvercrest smart motion sensor" (mqtt:broker:myMQTTBroker) @ "TODO" {
          Channels:
              Type switch : BatteryWarning1            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low∩MAP:truefalse.map", on="ON", off="OFF"]
              Type switch : BatteryWarning2            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low∩JS:js/mapTrueFalse.js", on="ON", off="OFF"]
      }
      
    • Items configuration related to the issue
      Switch    HG06335_HG07310_BatteryWarning1     "BatteryWarning"                (zigbee)    {channel="mqtt:topic:zigbee:Lidl_HG06335_HG07310:BatteryWarning1"}
      Switch    HG06335_HG07310_BatteryWarning2     "BatteryWarning"                (zigbee)    {channel="mqtt:topic:zigbee:Lidl_HG06335_HG07310:BatteryWarning2"}
      
    • Sitemap configuration related to the issue
      sitemap mqtt_zigbee2mqtt_HG06335_HG07310 label="mqtt_zigbee2mqtt_HG06335_HG07310" {
        Switch item=HG06335_HG07310_BatteryWarning1
        Switch item=HG06335_HG07310_BatteryWarning2
      }
      
    • Tansformation
      filename: truefalse.map
      true=ON
      false=OFF
      ON=true
      OFF=false
      
      filename: js/mapTrueFalse.js
      (function(i) {
          if (i == true) {
              return "ON";
          } else {
              return "OFF";
          }
      }) (input)
      
  • If logs where generated please post these here using code fences:
    log does not complain

Thanks for your help :slight_smile:

Try

Thing mqtt:topic:zigbee:Lidl_HG06335_HG07310 "Silvercrest smart motion sensor" (mqtt:broker:myMQTTBroker) @ "TODO" {
    Channels:
        Type switch : BatteryWarning1            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low", on="true", off="false"]
}

The on and off parameters are a shortcut to mapping the incoming (and outgoing) values. In theory, the above configuration will accept true and map it to ON within openHAB, sending ON to your Item. The same with false.

(Of course, this assumes you’re changing zigbee2mqtt/xxx to the actual topic!)

I’ve just recreated your Thing and Items here, and with the change above the Item goes ON and OFF when the incoming values are true and false respectively.

Peek 2022-02-05 22-12

Note that the value here is not the string "false", it is a true boolean false.
I’m not sure quite what you get out of JSONPATH for that; try it on its own in a string type channel, linked to to a String Item, and find out?

Despite the fact that the JSON was a ‘real’ boolean, be aware that transformation outputs and inputs are always strings internally. So the input to a JS transform will never be true or 99.0, but “true” or “99.0” and would need parsing if you want to treat it as something else.

Remember transformations like JSONPATH, JS, and MAP are add-ons, each needs installing individually.

Thanks for the info. Somehow now it started to work on my site with the MAP transformation as well …

Now I would like to get the JS transformation running too.
I upgraded the mapTrueFalse.js to this:

(function(i) {
    switch(i) { 
        case true:
        case "true":
        case "TRUE":
        case 1:
        case "1":
        case "on":
        case "yes":
        case "ON":
        case "YES":
          return "ON"; 
        default: 
          return "OFF"; 
      } 
}) (input)

It does not seem to work. I cannot see any new messages in the log.

I have this in my addons.cfg:

package = standard
binding = mqtt,http
transformation = jsonpath,map,javascript

You can’t just make up the channel configuration syntax ; it does not have any true= false= configuration parameters.

So you know its getting “true”/“false” at the MAP

Note that when you work from xxx.things files, small edits are commonly not “picked up” by the binding, and if in doubt you should restart it once you have your best effort in place…

I restarted again and somehow it works now too with javascript.
Now I feel dumb. Restarting multiple times seems to do the trick.

for reference:

Type switch : BatteryWarning2            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low∩JS:js/mapTrueFalse.js", on="ON", off="OFF"]
(function(i) {
    switch(i) { 
        case true:
        case "true":
        case "TRUE":
        case 1:
        case "1":
        case "on":
        case "yes":
        case "ON":
        case "YES":
          return "ON"; 
        default: 
          return "OFF"; 
      } 
}) (input)

But I don’t get all this. You wanted to map true and false to ON and OFF. Post #2 provides the simplest solution using only JSONPATH. But you’ve ended up chaining an extra transformation, and creating an extra file which also maps a whole bunch of other stuff. Why? Your JSON in your first post only suggested true or false.

1 Like
Type switch : BatteryWarning            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low", on=true, off=false]

results in:

2022-02-06 11:31:23.320 [WARN ] [re.config.core.internal.ConfigMapper] - Could not set field value for field 'off': Can not set java.lang.String field org.openhab.binding.mqtt.generic.ChannelConfig.off to java.lang.Boolean
java.lang.IllegalArgumentException: Can not set java.lang.String field org.openhab.binding.mqtt.generic.ChannelConfig.off to java.lang.Boolean
	at jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[?:?]
	at jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[?:?]
	at jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) ~[?:?]
	at java.lang.reflect.Field.set(Field.java:780) ~[?:?]
	at org.openhab.core.config.core.internal.ConfigMapper.as(ConfigMapper.java:101) [bundleFile:?]
	at org.openhab.core.config.core.Configuration.as(Configuration.java:80) [bundleFile:?]
	at org.openhab.binding.mqtt.generic.internal.handler.GenericMQTTThingHandler.initialize(GenericMQTTThingHandler.java:157) [bundleFile:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.openhab.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:154) [bundleFile:?]
	at org.openhab.core.internal.common.Invocation.call(Invocation.java:52) [bundleFile:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:829) [?:?]

and having this:

Type switch : BatteryWarning            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low"]

results in:

Command 'false' not supported by type 'OnOffValue': No enum constant org.openhab.core.library.types.OnOffType.false

summary:
The two listed error cases combined with the necessity to restart openhab created contradicting results while testing different ways to fix the problem. This is why I ended up trying it with map and javascript.
I think now I understood it: If it “should” work but does not → better safe than sorry and restart your openhab

long story and recommended working solution (because we can avoid the complexity of having a map or using javascript for this transformation as @hafniumzinc explained):

Type switch : BatteryWarning            [stateTopic="zigbee2mqtt/xxx", transformationPattern="JSONPATH:$.battery_low", on="true", off="false"]

Right, because

is not the same as

The second is comparing against the String "true" which is how the MQTT binding handles incoming messages.

I do this as it’s faster. It’s definitely a pain that this is still an issue!!