Is it possible to combine two transformations?

Happy New Year.

So, I’ve got this generic MQTT Thing for an RGB-Zigbee-Bulb and it almost works fine. The only issue(s) are with the value of ‘brightness’ in the color topic as:

“This channel will publish the color as comma separated list to the MQTT broker, e.g. “112,54,123” for an RGB channel (0-255 per component) and “360,100,100” for a HSB channel (0-359 for hue and 0-100 for saturation and brightness).
The channel expects values on the corresponding MQTT topic to be in this format as well.”

But, the value of brightness I get from the Bulb is between 0 and 255.

This is the channel config:

- id: Nous_01_color
    channelTypeUID: mqtt:color
    label: Nous_01_color
    description: color
    configuration:
      postCommand: false
      retained: false
      formatBeforePublish: '{ "x": %s, "y": %s, "brightness": %s}'
      commandTopic: zigbee2mqtt/nous_01/set/color
      colorMode: XYY
      stateTopic: zigbee2mqtt/nous_01
      transformationPattern: DSL:|transform("JSONPATH", "$.color.x",
        input)+","+transform("JSONPATH", "$.color.y",
        input)+","+transform("JSONPATH", "$.brightness", input)

And I was wondering if there is a way to have an additional transformation for the last value. My attempts to get it running failed so far…

Why don‘t you just chain the transformations with the intersection character (like shown in the documentation)?

I think intersection does not help here, as it’s about giving Value a, b and c.

For incoming messages, a script seems to be the appropriate way (and of course it’s possible to add something like

transformationPattern: DSL:|transform("JSONPATH", "$.color.x",
        input)+","+transform("JSONPATH", "$.color.y",
        input)+","+(Integer.parseInt(transform("JSONPATH", "$.brightness", input))*2.55).toString

(did not verify)

For outgoing messages, there is also the option to use a script transformation, I guess it’s the best option here.

1 Like

You see - I’ve already set up a script (NousDown.js) for this transformation in the transform folder:

(function(i) {
    if(input >= 0)
    {
	return input / 255 * 100;
    }
    else
    {
	return null;
    }
})(input)

But I don’t know how to make use of it as I’m struggling with the syntax in the channel config.

I tried things like:

transformationPattern: DSL:|transform("JSONPATH", "$.color.x",
        input)+","+transform("JSONPATH", "$.color.y",
        input)+","+transform("JS", NousDown.js, (transform("JSONPATH", "$.brightness", input)))

And I now tried your attempt/suggestion, but it isn’t working either.

there is another thread with the same topic :slight_smile:

Well, not the same topic, but another attempt to archive the same goal - which I will have a look at. Thanks again, Udo.

I did test with success (as a *.things definition):

        Type color  : col "Color"      [ colorMode="XYY", commandTopic="test/zigbee2mqtt/p3z/set", stateTopic="test/zigbee2mqtt/p3z", 
        transformationPatternOut="DSL:|val col = input.split(',') var my = '{\"brightness\": ' + (Float.parseFloat(col.get(2))*255/100).toString + ', \"color\": {\"x\": ' + col.get(0)  + ',\"y\": ' + col.get(1) + '}}' my", 
        transformationPattern="DSL:|transform('JSONPATH','$.color.x',input) + ',' + transform('JSONPATH','$.color.y',input) + ',' + (Integer.parseInt(transform('JSONPATH','$.brightness',input))*100/255)" ]

or (the same) as yaml code:

channels:
  - id: col
    channelTypeUID: mqtt:color
    label: Color
    description: null
    configuration:
      retained: false
      postCommand: false
      transformationPatternOut: "DSL:|val col = input.split(',') var my =
        '{\"brightness\": ' + (Float.parseFloat(col.get(2))*255/100).toString +
        ', \"color\": {\"x\": ' + col.get(0)  + ',\"y\": ' + col.get(1) + '}}'
        my"
      formatBeforePublish: "%s"
      commandTopic: test/zigbee2mqtt/p3z/set
      colorMode: XYY
      stateTopic: test/zigbee2mqtt/p3z
      transformationPattern: DSL:|transform('JSONPATH','$.color.x',input) + ',' +
        transform('JSONPATH','$.color.y',input) + ',' +
        (Integer.parseInt(transform('JSONPATH','$.brightness',input))*100/255)

And I ran into another issue:

[WARN ] [t.generic.ChannelStateTransformation] - Transformation service JS for pattern NousOut.js not found!

And it’s correct, there is no such transformation installed - but also not available.

I’ll try your attempt now…uff.

That’s correct, as there is no script transformation service at all.

The thing is, you can now use any script engine which is installed to do a script transformation.
In older openHAB versions you had to install JS Transformation Service and you were bound to JavaScript Scripting for Transformations.
The Log message is a bit vague here :slight_smile: but you’ll simply have to install the JavaScript Scripting engine.

Okay, got it. In order for JS to be functional I had to install the script engine. How ever, I now got it working using your transformation patterns. I only had to change

(Integer.parseInt(transform('JSONPATH','$.brightness',input))*100/255)

to

(Float.parseFloat(transform('JSONPATH','$.brightness',input))*100/255)

Thank you, Udo.

1 Like