[SOLVED] [MQTT] How to send integer value to a dimmer?

I want to control the brightness of a device through MQTT. The device brightness varies from 0 to 255.

I have created the device thing with PaperUI as below


with the following item:
Dimmer Tableau “[%d %%]” {channel=“mqtt:topic:d2cfb0fd:Tableau”, alexa=“Lighting”}

But the brightness value received by the dimmer is not an integer which creates side effects.

I have read extensively the different related posts and tried different options like %d for the “Outgoing value format” but nothing worked.

How could I force the output value to be an integer?

What side effect does it create?

What get’s published when you try to use the outgoing value format? Is it just a value from 0-100 or does it appear to have no effect?

I don’t know in what order the various fields that modify the outgoing message are evaluated.

You might need to use the JS transformation to perform the calculation and then round it to an int.

The device receives non integer values between 0 and 255.

Only the integer values (corresponding to 0%, 20% and 100%) are processed, the other ones are ignored

There is a MORE button that provides more :smile: options:
And you are looking for this option: Outgoing Value format:
Set it as %d

image

OP indicated they tried that.

You didn’t answer all of my questions. I need to know what is actually being published when you have the %d set in the Outgoing Value Format field. If you set the Dimmer Item to 50, does it publish 50 or 127.5?

We are trying to figure out if the Outgoing Value Format field is just being ignored or if the min value/max value is being ignored.

Oups, didn’t see that

Point to note - Dimmer type Items work exclusively on 0-100 % values.

So you will need to transform the outgoing 0-100 value into 0-255 as part of your channel configuration.
You’ll need transformationPatternOut which is only available in binding versions 2.5

When you choose a “Percentage value” as the Channel Type it gives you the option to supply an Absolute minimum and Absolute maximum value. The binding will then do the math to convert the 0-100% Item state to a range between the min and max entered.

The root problem here is that the calculation is generating a floating point number, not an integer and the destination requires an integer.

I have no idea when this was added to the binding and frankly I think it’s really cool, but only if we can figure out how to get it to spit out an integer instead of a float.

I had a couple of minutes so ran the test myself.

When the %d is supplied to Outgoing Value Format along with the min and max values. It publishes the floating point value. But if you supply the following JS outgoing transformation it will round the value to the nearest int.

// Wrap everything in a function
(function(i) {
    if(isNaN(i)) return -1;
    return Math.round(i)
})(input)
// input variable contains data passed by openhab

I’ll file an issue on this as I would have expected the outgoing value format to work. I don’t know it it just doesn’t work at all or it doesn’t work with this specific channel type.

1 Like

If I recall, “outgoing format” applies to the string fed into “outgoing transformation”. I presume that is the case whether you have your own transformationPatternOut or this implied transform with min/max. i.e. it does not affect final output unless not transformed.

Based on my experiment that isn’t happening here either. If I change that JS transformation to just return i instead of rounding it, it publishes 127.5. And if it only supports %s, it’s a pretty useless field.

But the description of Outgoing Value Format says:

Format a value before it is published to the MQTT broker.

And at the end of the description it says:

If you want to adjust the precision of a number to for example 4 digits, you would use “%.4f”.

So %d should be supported. But it looks like Outgoing Value Format only applies when there is nothing else modifying the outgoing message. If that’s the case, I argue it’s a huge missed opportunity. It’s also inconsistent as the Absolute minimum/maximum is applied before the Outgoing Value Transformation is called. It is inconsistant for Outgoing Value Format to not be called at all. It is ambiguous given the current docs as to whether one should expect Outgoing Value Format or Transformation to apply first, but the intuitive expectation is that either or both should be executed if supplied. Not have one just silently skipped.

No matter how you look at it, this needs more documentation.

That description needs substantial revision if it only transforms the value before the outgoing transformation or else it does nothing at all.

NOTE: I also tested with %.2f to see if I could get an extra 0 tacked on to the end and there isn’t. The OVF is not being applied at all.

Description of Outgoing Value Format may have become ambiguous now because it pre-dates the addition of “real” outwards transformation.

I just ran a test with only the OVF defined to %.2f and nothing happened (i.e. “50” was published when I commanded the Item to 50). OVF appears to be completely broken, at least for Percent type Channels.

Another test. “Foo %s” does work. So the description is way way wrong. It looks like it only works with %s which is definitely counter to what the description says.

Thank you all for your interest in that problem even though I am not totally sure to understand if there is a solution.

To answer your question the Min, Max work well and the published value is 127.5 for a brightness of 50% even with %d in OVF

To make the problem even harder, one of the dimmer device I am trying to control requires a more complex output in the form {“dps”: 2, “set”: %s} where %s is the brightness integer value between 0 and 255.

When adding {“dps”: 2, “set”: %s} in the Outgoing value format I have the proper output payload except that the dimmer value is not an integer (for example {“dps”: 2, “set”: 127.5} for a brightness value of 50%) but when I tried to use {“dps”: 2, “set”: %d}, as recommended by zorglub, I only got 127.5 as an output, the rest of the string got lost.

So it seems that there is 2 problems to sort out with %d in Outgoing value format

You’ll need a javascript outwards transformation as you want to both do some maths and some JSON encoding.
An example

I will do as rossko57 recommend but am I correct to say that if OVF was working as expected the simplest answer to my problem will be to set OVF to {“dps”: 2, “set”: %d} rather than to go the javascript outwards transformation?

I don’t know. It is not clear what order they are supposed to be evaluated. Maybe, maybe not.

I do not think so. There is a design choice about doing it before or after other transforms. Logically, if you are performing other transforms then you don’t need to to format it further afterwards. I would expect the choice to be - format first, transform after. It would be equally sensible to ignore format if applying a transform.

I would expect the following order:

  1. custom on/open off/closed absolute min/max etc
  2. outgoing transformations
  3. outgoing formatting

This would provide the most flexibility over all. It also feels more consistent with how transformations and formatting works with Items. When you look at Items, the raw data comes from the binding, flows to a transformation, and then can be formatted in the label. Here the raw value comes from the command, flows to a transformation, and finally get’s formatted.

Is there overlap between the transformation and the formatting? Of course. But having access to both lets you simplify the transformations, sometimes significantly, for several use cases I can think of. In this particular case, it lets you do the math and round it to an int without the need for a transform at all.

I agree with Rich.

Anyhow the following Javascript transform does work for my specific setup

(function(brightness) {
    var tuyaobj = {"dps": 2, "set": Math.floor(brightness)};
    var data = JSON.stringify(tuyaobj);
    return data;
})(input)

Thank you all for your help