MQTT mapping outgoing command to value

Tags: #<Tag:0x00007f433cd596d0>

Hi all,

This is my setup (openhab 2.5 stable):

things:

Bridge mqtt:broker:openhabian [host="localhost", secure=false, clientID="OpenHAB2"]
{
        Thing topic smallBedroomDimmer "Dimmer" @ "Small bedroom" {
        Channels:
                Type dimmer : dimmer "Light dimmer" [stateTopic="mySensorsout/34/0/1/0/3", commandTopic="mySensorsin/34/0/1/0/3", min=0, max=100, step=1]
                Type number : scene "Scene" [stateTopic="mySensorsout/34/4/1/0/19"]
        }
}

items:

Dimmer bedroom2_light_dimmer "Small bedroom [%d %%]" <light> {channel="mqtt:topic:openhabian:smallBedroomDimmer:dimmer", autoupdate="false"}
Number bedroom2_light_scene "Small bedroom" {channel="mqtt:topic:openhabian:smallBedroomDimmer:scene"}

sitemap:

Switch item=bedroom2_light_dimmer icon="switch"
Setpoint item=bedroom2_light_dimmer minValue=0 maxValue=100 step=5

And that setup works. But I would like to change it so when I use Switch on the sitemap the value 255 would be send to mqtt broker. Now it is sending value 100. The value 255 is recognised by the device as last set value.

I don’t know if it works for dimmer type channels, but have you tried the on= off= simple transformations?

from documentation:
on: An optional string (like “ON”/“Open”) that is recognized as minimum.

For me it sounds like it converts command sent to dimmer into min/max value. So for example command ON to 100 (if max=100). This is not what want to achieve.

Yes. So perhaps you want on=“255”.

this is not how I uderstand the documentation. I tryied Your suggestion but it is not working

This is mqtt bindimg code for version 2.5 for dimmer channel (bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java:109

if (command instanceof StringType) {
            if (onValue != null && command.toString().equals(onValue)) {
                state = new PercentType(new BigDecimal(max));
            } else if (offValue != null && command.toString().equals(offValue)) {
                state = new PercentType(new BigDecimal(min));
            } else {
                throw new IllegalStateException("Unknown String!");
            }
        }

onValue and offValue are values You specify as on/off channel configuration parameters.
You can see that this is working as I suspected.

All I can offer is it’s possible and super simple to do in PaperUI.

However, be aware that if you use the Absolute Minimum and Absolute Maximum the 0-100 will be converted to a decimal and not rounded.

I couldn’t tell you how to do it with .things files. I don’t use them and don’t recommend their use. But at least you now know it’s definitely possible.

This will not work as expected. I still want to have 0 as minimum and 100 as maximum. But I want to have also the special value to be send to the mqtt broker when I send ON command to the mqtt things channel. With mqtt1 binding I could simply do it with transformation expresion or explicitly configure special case for ON command in item definition.
This is how I did it in mqtt1:

item:

Dimmer bedroom2_light_dimmer "Small bedroom [%d %%]" <light> {mqtt=">[local:mySensorsin/34/0/1/0/3:command:*:JS(mysensors_dimmer.js)], <[local:mySensorsout/34/0/1/0/3:state:default]", autoupdate="false"}

mysensors_dimmer.js:

(function(input){
    if (input == "ON") {
        return 255;
    }
    else if (input == "OFF") {
        return 0;
    }
    else {
        return input;
    }
})(input)

I looked through mqtt2 bindig source code and unfortunetly do not see such possibility …
So maybe I could use another approach. The special value is interpreted by my device as “restore last set value”, maybe there is such functionality in OH already and can be done in the item/thing definition ?

This works with zigbee for turning a light on and off using js transformation. Give it a try with your device and see if it helps.

Things file:

Thing topic zigbee "Bedroom Light" @ "Bedroom" {
    Channels:
        Type switch : power  "Power"               [ stateTopic="zigbee/Light/state", transformationPattern="JSONPATH:$.state",
                                                    commandTopic="zigbee/Light/set/state", on="ON", off="OFF" ]

setZigbeeState.js file:

(function(x){

    var result = new Object();
    result.state = x;
 
    return JSON.stringify(result);
    
})(input)

Notice I also circled “Custom On/Open Value” and “Custom OFF/CLOSED Value”. Fill out those and it should convert an ON command to what ever you put there and OFF to the other field. I believe that is what you are looking for.

I see Marek’s point.
The custom on=“blah” setting for dimmer type channel does not work like switches.
Incoming “blah” should get transformed to Item 100.
But outgoing command ON gets converted to max, and ignores “blah”.

Than that field is all but useless and a PR should be filed to either make it work or remove the field I think. I’ve not a lot of experience with Percent MQTT Channels but so far I’ve not been impressed with how it works.

Well, I thought about suggesting an enhancement. The trouble with it is that this on=/off= business is bidirectional; incoming payload to OH state, outgoing command to payload.
Changing behaviour would suit Marek and ruin someone else’s day.
It works fine until you want some magic special case.

I’m inclined to think the most flexible solution is to bypass on/off and min/max “easy” transforming where you have specified a full blown outbound transform. In a JS or whatever you can manage your own scaling and special cases.

The problem with mqtt2 binding is that it is very restrictive when it comes to values that goes out to the mqtt broker. MQTT is very generic protocol that does not put any restrictions to the payload. So the binging should also allow for that.

I looked through the code and this is what happens when the command is sent to the dimmer channel:

  1. PercentValue.update(command) is called. This converts Command to PercentType applying min, max restrictions, so resulting value is between 0 and 100 -> first fail because the information about the command is already lost (no way to know if it was ON command or 100 percent command). And only in case that the command is of type String the on/off config values are applied and if that wasn’t enough those on/off values are converted to PercentType(max)/PercentType(min) giving result between 0 and 100 evenf if min/max are outside of that range (at least this is how I understand that PercentType works) -> second fail.
  2. then PercentValue.getMQTTPublishValue() is called whch converts State to String applying min/max in reverse to the PercentValue.update -> third fail because this is totally unnecesarry to makes those convertions to 0 - 100 range and back to min - max range.
  3. then transformations are applied on String type
  4. and lastly the formatter is applied

fourth fail is that this is way to complicated for the users. There is no way that someone could understand how to use this binding without reading the code …

Good design would be to make default conversions between commands and Strings sent to mqtt, and possibility to override them with transformations. The code would be simpler, and users would understand how to use the binding.

Bear in mind it all works fine for other people.
You have an oddball requirement; “treat it as a dimmer except sometimes”.
That’s fine, openHAB has the flexibility - we’ve concentrated on binding here but you can workaround this with proxy Items.

Meantime as I see MQTT binding issues - there are a lot of transformation possibilities, which have been added one by one over time. Most of them are intended to make things easier - when used alone. Like the on/off matching.
Once you try to apply more complex transforms, you are rather at the mercy of what order this little train of events comes in.

For example, I agree with you that changing Dimmer-ON to Dimmer-100 is done too early in this process, and ruins any chance of making special behaviour.

The missing feature so far as I can see is a “master” scripted transform - or rather, two, for in and out.
That would allow you to do what you liked with raw OH commands and raw MQTT payloads, and not have the little “helpers” contribute.

Anyway, to address your immediate problem -
Link a number MQTT channel to a Number OH Item.
Use a Dimmer Item linked to nothing on your UI.
Use rule listening for commands to Dimmer Item to create commands for Number Item (and so MQTT)
Use rule listening to Number Item to update Dimmer Item state.

This oddball requirement is how all zwave dimmers I know work and zwave binding handles that.

anyway, thanks for help. I will propably modify my dimmers software to provide another topic for restoring last set state.

Did you ever find a suitable solution for this? I’m running into the same issue with openhab 3. I was hoping the “Custom On/Open Value” would allow me to send 255 or just simply ON to my mqtt broker, but that doesn’t seem to be the case. I’ve been in the process of trying to migrate over to zwavejs2mqtt and so far this is my biggest holdup.

There are a number of solutions outlined above. Maybe you could outline exactly what you want to happen?
At a guess -
Pass commands to an openHAB Dimmer Item to MQTT-
In the case of 0 to 100, scale to 0 to 255?
In the case of ON or OFF, send what? (if anything)
In the case of INCREASE or DECREASE, send what? (if anything)

Is there any incoming payload you want something to happen with?

Basically the same situation as the original post. I have a dimmer switch controllable through mqtt. The dimmer value goes between 0-99, with 255 or ON set to turn it back to the previous state. When I saw the “Custom On/Open Value” section when defining the Channel in OpenHAB I was hoping that would actually send that value, but I guess that isn’t what that is for.

Edit: A bit more info.

My Switch Thing

UID: mqtt:topic:bf74bb3dd9:13a39b5d56
label: EntryWay_Dimmer_1
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:bf74bb3dd9
location: Entry Way
channels:
  - id: Dimmer
    channelTypeUID: mqtt:dimmer
    label: Dimmer
    description: ""
    configuration:
      commandTopic: zwave/ew_dimmer_1/38/0/targetValue/set
      min: 0
      formatBeforePublish: "%.0f"
      stateTopic: zwave/ew_dimmer_1/38/0/currentValue
      max: 99
      on: on

I don’t know how “helpful” the binding dimmer channel is at converting commands to numeric; it really ought not to interfere for a basic transformation like

ohdimmer.js

(function(x){
    var out = 0 ;
    if (x == "ON") {
        out = "255 or ON" ;
    } else if (x == "OFF") {
        out = 0 ;
    } else if (x == 100) {
        out = 99 ;
    } else {
        out = x ;
    }
    return out ;
    
})(input)

without using the mini-transform on/off parameters at all.

How does your dimmer know the difference between turned to zero and being turned off but remember last brightness?