formatBeforePublish strange behaviour

working with eurotronic spirit thermostat controlled via zigbe2mqtt I need to control some of the parameters via MQTT messages. thats when I stumbled upon a strange behaviour of “formatBeforePublish” as it works fine with number items, but is completely ignored with switch number,

i.e.

Thing

    Type number : current_heating_setpoint    "current_heating_setpoint"    [ stateTopic="zigbee2mqtt/thermostat4", transformationPattern="JSONPATH:$.current_heating_setpoint",
                                                                            commandTopic="zigbee2mqtt/thermostat4/set", formatBeforePublish="{ \"current_heating_setpoint\": %s }"]

results in the correct mqtt message being formed and sent out

zigbee2mqtt/thermostat4/set { “current_heating_setpoint”: 17 }

However, if I apply the same logic to the switch item, the format is completely ignored and

   Type switch : mirror_display              "Mirror Display"              [ stateTopic="zigbee2mqtt/thermostat4",transformationPattern="JSONPATH:$.eurotronic_host_flags.mirror_display",on="true",off="false",
                                                                           commandTopic="zigbee2mqtt/thermostat4/set", formatBeforeTransform="{ testtest %s }" ,on="true",off="false"]

and the following message is formed and sent out

zigbee2mqtt/thermostat4/set true
zigbee2mqtt/thermostat4/set false

I have also tried using the transformationPatternOut i.e.

    Type switch : mirror_display              "Mirror Display"              [ stateTopic="zigbee2mqtt/thermostat4",transformationPattern="JSONPATH:$.eurotronic_host_flags.mirror_display",on="true",off="false",
                                                                           commandTopic="zigbee2mqtt/thermostat4/set", transformationPatternOut="JSONPATH:$.eurotronic_host_flags.mirror_display",on="true",off="false"]

But that results in an error

[WARN ] [t.generic.ChannelStateTransformation] - Executing the JSONPATH-transformation failed: Invalid path ‘$.eurotronic_host_flags.mirror_display’ in ‘true’

So the question is there a way forming a message using the JSONPATH in the outgoing transformation or formatbeforePublish, or it can only be done via JS script?

I just did a quick look, bit wouldn’t using the official Zigbee binding be easier? Why add the complexity of MQTT?

Well, I have plenty of other things controlled via MQTT, like sonoff/shelly devices, Bradlink wifi thermostats. So Zigbee2mqtt seemes like an easy way of controlling a plethora of different ZB devices.

1 Like

Have you looked at this post/topic?

1 Like

it works partially, i guess.

I can set the channel current_heating_setpoint using two ways
either as

commandTopic=“zigbee2mqtt/thermostat4/set”, formatBeforePublish="{ “current_heating_setpoint”: %s }"]

or as

commandTopic=“zigbee2mqtt/thermostat4/set/current_heating_setpoint”

However, the same logic does not apply when setting the more complex channels, i.e.

‘{“eurotronic_host_flags”: {“boost”: true}}’

So for now, for each of the four “complex” channels i have to maually format and return JSON calling the "transformationPattern=“JSONPATH:$.eurotronic_host_flags.boost”

(function(flag) {
if (flag == ‘true’) {
var data = ‘{“eurotronic_host_flags”: {“boost”: true}}’;
} else if (flag == ‘false’) {
var data = ‘{“eurotronic_host_flags”: {“boost”: false}}’;
}
return data;
})(input)

Hi! In latest versions, formatBeforePublish does not work for switch types, seems as this was done on purpose, already opened a ticket a couple of days back if we can re-add this - see here.

1 Like

Thanks for the hint Boris jan :slight_smile:
the worst is that it is simply silently ignored, without generating any error or warning in the logs.

As a workaround, I’m currently using string instead of switch since formatBeforePublish works there, example:

Type string:acPower [ stateTopic="FF_Child_Room/ac/settings", transformationPattern="JSONPATH:$.power", commandTopic="FF_Child_Room/ac/settings/cmd", formatBeforePublish="power,%s" ]

.items:

String FF_Child_Room_ac_power "Power []" { channel="mqtt:topic:rasnas:ffChildRoom:acPower" }

.sitemap:

Switch item=FF_Child_Room_ac_power mappings=[OFF="Off", ON="On"]

It’s rendered a bit different but does its job :wink:

Comment:
In the failing example, there is formatBeforeTransform= which I expect is a typo?

Assuming formatBeforePublish= , there is also on= off= which are another kind of mini-transform.
Do you know which order these transforms are applied in? Seems important.

I’m guessing the output of formatBeforePublish is passed to on/off,which finds no match as that isn’t on or off

formatBeforePublish for switches won’t work, please check source code:

@Override
    public String getMQTTpublishValue(@Nullable String pattern) {
        return (state == OnOffType.ON) ? onCommand : offCommand;
    }

As one can see, pattern is ignored. It’s also documented in latest doc

switch String – No pattern supported. Always on and off strings

It’s not very clear meaning. What is a “pattern”? (The problem here is with a “format”)
Would that mean you can’t use on/off together with an incoming transformationPattern ?

on/off does apply to both in and out messages. So, transformationPatternOut is also unused when on/off is used?
And also of course the subject here, formatBeforePublish ?

The final piece of the topic would be how formatBeforePublish and transformationPattern interact.

I have no point to make,just trying to understand the interplay. It would be great to have clarity, this comes up here lots.

1 Like

I’m saying that formatBeforePublish won’t work for switch type, that is all - so no point trying and loosing time - that parameter is simply ignored by the binding for switch type. Nothing to do with transformationPattern or transformationPatternOut.

I understand. Leaves lots of questions open.

I’m no expert, but my understanding is:

transformationPattern is used for incoming messages and incoming messages only - has nothing to do with transformationPatternOut and formatBeforePublish. transformationPattern transforms incoming message’s value to an OH state - i.e. if we have payload {"temperature": 22} and transformationPattern="JSONPATH:$.temperature", it will extract the temperature from json and set state’s value to 22. But does not effect outgoing messages in any way.

formatBeforePublish and transformationPatternOut are used for outgoing messages and outgoing only. transformationPatternOut is more or less the same as transformationPattern, just that it is used for outgoing messages only. The result of the transformation in transformationPatternOut will be then passed to formatBeforePublish and then send to the wire.

I guess more details on format and pattern can be found here but generally it’s about how specific placeholders in text/string are replaced with other values - i.e. having a (number) item with value (state) = 22 and formatBeforePublish = "Temperature is %d", the %d placeholder will be replaced with the state’s value, more specifically The result is formatted as a decimal integer so well end up with Temperature is 22 being send.

Makes sense?

2 Likes

Excellent summary!

I really think it would be worth while to incorporate an overview like that into the MQTT thing/channel docs. As these features have been added on one by one over time, the overview is missing.

There is still a bit of a gap about how these generic features interact with the uhh “specialist simple transforms” like on=/off= for switches, dimmers, min=/max=/step= for numbers, etc.
It’s complicated by these applying to both in and out.

I’m making the assumption that switch channel currently ignoring format etc.is a binding bug, rather than intended behaviour.

1 Like

I am also reporting that formatBeforePublish stopped working for switch type with last 2.5 snapshot - it simply publish value without any formatting applied.
I am currently downgrading to stable release because this small issue paralyzed our house :joy:.

Just reporting that downgrading to 2.5.0-1 & openhab2-addons 2.5.0-1 fixed the issue with switch.

formatBeforePublish should be working now for switch and contact types, thx to this PR, FYI …

1 Like