OH3 Example ShellyPLUS1pm Things, Items, Rules

I own several Gen1 Shellies and I’m quite fond of how they work. So I ordered a few new ones and thought the software etc. is the same but they changed a lot. MQTT is way different and nothing worked like I wanted. After 2 days of research, I got them working as far as I needed them to. So this should be helpful for anyone using Gen2 Shellies like the ShellyPlus1pm for example.
In my example it is a ShellyPLUS 1pm (with Power Meter) for my air condition unit controlled by MQTT with Mosquitto and Openhab 3.

shellyplus.things

    Thing topic shellyplus1pm_dg_klimaanlage "Shellyplus1pm Klimaanlage" @ "DG" {
    Channels:
        Type switch : PowerSwitch     [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0" , transformationPattern="JSONPATH:$.output", on="true" , off="false" , commandTopic="shellies/shellyplus1pm_DG_Klimaanlage/rpc" , formatBeforePublish="{\"src\":\"openhab\",\"method\":\"Switch.Set\", \"params\":{\"id\":0,\"on\":%s}}" ] 
        Type string : Event0          [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/events/rpc", transformationPattern="REGEX:(.*\"event\":.*)∩JSONPATH:$.params.events[*].event" ] 
        Type string : Source          [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0" , transformationPattern="JSONPATH:$.source" ]
        Type number : Power           [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0" , transformationPattern="JSONPATH:$.apower" ]
        Type number : Voltage         [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0" , transformationPattern="JSONPATH:$.voltage" ]
        Type number : Energy          [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0", transformationPattern="JSONPATH:$.aenergy.total∩JS:shellyplus_energy_kwh.js" ] // From Shelly in Wh
        Type number : Temperature     [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/switch:0", transformationPattern="JSONPATH:$.temperature.tC" ]
        Type string : UpdAvailable    [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/sys",  transformationPattern="REGEX:(.*stable.*)∩JSONPATH:$.available_updates.stable.version"]
        Type string : RestartReq      [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/sys",  transformationPattern="REGEX:(.*restart_required.*)∩JSONPATH:$.restart_required"]
        Type number : Uptime          [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/status/sys",  transformationPattern="REGEX:(.*uptime.*)∩JSONPATH:$.uptime"] // in seconds
        Type string : IP              [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/shellystatus/rpc", transformationPattern="REGEX:(.*sta_ip.*)∩JSONPATH:$.result.wifi.sta_ip"]
        Type string : Devicestate     [ stateTopic="shellies/shellyplus1pm_DG_Klimaanlage/online" ]
      }

(The backslashes are to escape " in the JSON string)

To get all the status informations like in Gen1 you have to do 2 things.

  1. You have to enable MQTT with your Mosquitto settings and ENABLE “Generic status update over MQTT” in the UI.
    Shelly WebUI MQTT configuration
  2. We need a rule to trigger a MQTT message sent to the Shelly, so that it sends more status updates back.

shellyplus_start.rules

val logName = "shellyplus_start.rules"

rule "Get Status"

when
    Member of g_shellyplus_source changed to "init" or
    Member of g_shellyplus_event changed to "scheduled_restart"
then
    val shelly = triggeringItem.name.toString().replace('_source', '')
    logInfo(logName, "Shelly: " + shelly)

    var actionsBroker = getActions("mqtt","mqtt:broker:mosquitto")
    actionsBroker.publishMQTT( "shellies/" + shelly + "/rpc", "{\"id\":1, \"src\":\"shellies/" + shelly + "/shellystatus\", \"method\":\"Shelly.GetStatus\"}" )
end

The rule sends a message to the /rpc commandtopic and the Shelly then sends infos back. The Shelly creates a new subtopic for the answer which you can define with “src”. Yes, really. I didn’t understand that part neither in the beginning but it is not as complicated as you would think.
Here in our example all my Shellies have the overall topic shellies/ and then the Shelly name. You can see that in a program like MQTT explorer.

When we now restart the Shelly the rule is triggered and sends the payload

{"id":1, "src":"shellies/shelly1pmplus_DG_Klimaanlage/shellystatus", "method":"Shelly.GetStatus"}

to the channel

shellies/shelly1pmplus_DG_Klimaanlage/rpc

Some of the methods can be found in the Allterco Shelly documentation. The GetStatus method is described here.
Some methods are not explained for MQTT but it seems to work like the cUrl commands with the same arguments.
Now, because we set our “src” to shellies/shelly1pmplus_DG_Klimaanlage/shellystatus the Shelly will send its answer to this subtopic!!!

All the missing status items from Gen1 Shellies are in this answer.

Now to the different channels in our things file.
The PowerSwitch was a bit tricky because the Gen2 API requests a JSON string back in the command topic. Also it is not on and off as it was but true and false.
In our stateTopic we receive the state for the relay. The topic payload is in JSON so we have to do JSONPATH as transformationPattern to get output from the JSON. The ouput if true or false but because we have a Switch Thing we need on or off. This can be accomplished by using

on="true" , off="false"

The commandTopic is a little bit more complicated because we have to send a JSON payload back. The payload for a command is

{"src":"openhab","method":"Switch.Set", "params":{"id":0,"on":true}

The params part can be true or false and switches the relay on or off. Because of our

on="true" , off="false"

We can use %s in our format string to make on=true and off=false. So we use formatBeforePublish to switch between true and false because the rest of the payload is always the same.

formatBeforePublish="{"src":"openhab","method":"Switch.Set", "params":{"id":0,"on":%s}}"

So, on every toggle from our switch every command will have the command “on” or “off” send which will be substituted on the %s position with “true” or “false”.
So, when switching “ON” normally the command on would be send to shellies/shellyplus1pm_DG_Klimaanlage/rpc but because of the formatBeforePublish the “ON” will be substituted with {“src”:“openhab”,“method”:“Switch.Set”, “params”:{“id”:0,“on”:true}}. “OFF” will be substituted to {“src”:“openhab”,“method”:“Switch.Set”, “params”:{“id”:0,“on”:false}}

If anybody is searching for another purpose to TOGGLE a switch, the new Gen2 payload would be

{"method":"Switch.Toggle","params":{"id":0}}

The next channels are quite self explaining. They’re all different things from the Shelly which we’ll get from different topics. We have to pay attention that not all things are there all the time. An event (pushing a button) is only in the payload if it’s actually pushed and then disappears. So we have to check with a REGEX transformation if the payload actually exists

REGEX:(.*\"event\":.*)

checks if “event” is in the payload. If yes, ∩ sends it to the next transformation which here is JSONPATH and with

JSONPATH:$.params.events[*].event"

Gets the event from the payload. For the Shellies this could be btn_down, btn_up, single_push, long_push, double_push, scheduled_restart.

The only other thing is, energy from the Shelly is in Watthours but I like it in Kilowatthours or kWh. This channel gets the energy number from the Shelly and then sends it to a Javascript file to transform it.

shellyplus_energy_kwh.js

var logger = Java.type("org.slf4j.LoggerFactory").getLogger("shellyplus_energy_kwh.js");

(function(i){
    //logger.warn(i);
    x = (i/1000).toFixed(2);
    //logger.warn(x);
    return x
})(input)

If you comment the logger.warn in it will show in the Openhab logs. But it’s annoying fast. So just for debugging!

Uptime from the Shelly is in seconds! If you want to transform that, just use another .js file and do a little math.

You can get every channel without the rule from the beginning except the IP address. I don’t know why but the IP is in no status topic from the Shelly, except you ask explicitly for it. This was different in Gen1. So if you are not interested in the Shelly IP, you don’t need the shellyplus_start.rules from the beginning!!!

This is all I need for my purposes with the Shelly. So, to use it I created the corresponding
shellyplus.items

Group        g_shellyplus_source
Group        g_shellyplus_event

Switch shellyplus1pm_DG_Klimaanlage_R1                 "DG Klimaanlage"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:PowerSwitch" }
String shellyplus1pm_DG_Klimaanlage_event0             "DG Klimaanlage Tasterevent" (g_shellyplus_event) // btn_down, btn_up, single_push, long_push, double_push, scheduled_restart
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Event0" }
String shellyplus1pm_DG_Klimaanlage_source             "DG Klimaanlage Eingabe" (g_shellyplus_source)
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Source" }
Number shellyplus1pm_DG_Klimaanlage_power              "DG Klimaanlage Power [%s W]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Power" }
Number shellyplus1pm_DG_Klimaanlage_voltage            "DG Klimaanlage Voltage [%s V]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Voltage" }
Number shellyplus1pm_DG_Klimaanlage_energy             "DG Klimaanlage Energy [%s kWh]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Energy" }
Number shellyplus1pm_DG_Klimaanlage_temperature        "DG Klimaanlage Temperatur"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Temperature" }
String shellyplus1pm_DG_Klimaanlage_ip                 "IP Adresse [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:IP" }
String shellyplus1pm_DG_Klimaanlage_updavailable       "FW Update [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:UpdAvailable" }
String shellyplus1pm_DG_Klimaanlage_restartreq         "Neustart notwendig [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:RestartReq" }
Number shellyplus1pm_DG_Klimaanlage_uptime             "Uptime [%s s]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Uptime" }
String shellyplus1pm_DG_Klimaanlage_state              "Status [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus1pm_dg_klimaanlage:Devicestate" [profile="transform:MAP", function="shellyplus.map"] }

The 2 groups are to differentiate for the shellyplus_start.rules file if a restart happened. As said above, if you’re not interested in the IP you don’t need the 2 groups.

The last item is mapped so that the sitemap show the state as “online” or “offline” instead “true” or “false”

shellyplus.map

true=online
false=offline

To test and see all our values I also did a shellyplus.sitemap

shellyplus.sitemap

sitemap shellyplus label="Shelly Plus" { 

	Frame label="Shelly Plus 1PM" {
        Switch item=shellyplus1pm_DG_Klimaanlage_R1
        Text   item=none                         label="" icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_event0 icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_source icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_power icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_voltage icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_energy icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_temperature icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_ip icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_updavailable icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_restartreq icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_uptime icon=none
        Text   item=shellyplus1pm_DG_Klimaanlage_state icon=none
	} 
}

I am not sure if I like the PLUS series. I have a lot of Gen1 devices and they worked flawlessly and the MQTT integration was easy and understandable. This Gen2 seems a little overengeneered and overcomplicated to me. I hope they knew what they were doing…
I hope this answers a lot of questions for people who are trying to get a Shelly PLUS running. This took me 2-3 days to get all the different informations I needed to get the Shelly doing what I wanted it to do!

3 Likes

There is a Shelly binding. It provides auto discovery and local control. If your devices are supported by the binding, it’s definitely the easiest way to go.

I know. Thanks for the info. I did it file based from the beginning and I liked it. I followed the whole development thread for the binding. I just thought it’s enough if one person has to search all the infos to do it by MQTT.

1 Like

I found this thread after a while of searching.
I’m struggling to get my ShellyPlus2PM running with Mqtt. Thanks for your approach schossel.
How to “change” your code to get it run with a ShellyPlus2PM in cover mode to positioning from 0 -100?

BR Peter

There is no easy and straightforward solution. I think this should be available as a config option because it’s a quite common use case.
For my part I’m inverting the percentage in a HABApp rule and directly subscribe/publish to the corresponding topics.

I’m not sure if I got your question right, because the answer from Sebastian is not what I expected. What I can do for you, I can show you one of my 2pms, you have a look and then tell me if you have further questions!?

.things

    Thing topic shellyplus25_Rollladen_WST "Shelly25 Rollladen Werkstatt" @ "Keller" {
    Channels:
        Type rollershutter  : Position            [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0", transformationPattern="JSONPATH:$.current_pos∩JS:shellyplus25_roller_position.js", commandTopic="shellies/shellyplus25_Rollladen_WST/command/cover:0", transformationPatternOut="JS:shellyplus25_roller_position_out.js"]
        Type rollershutter  : Control             [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0", transformationPattern="JSONPATH:$.current_pos∩JS:shellyplus25_roller_position.js", commandTopic="shellies/shellyplus25_Rollladen_WST/command/cover:0", transformationPatternOut="JS:shellyplus25_roller_position_out.js"]
        Type string         : Source              [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0" , transformationPattern="JSONPATH:$.source" ]
        Type number         : Power               [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0" , transformationPattern="JSONPATH:$.apower" ]
        Type number         : Voltage             [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0" , transformationPattern="JSONPATH:$.voltage" ]
        Type number         : Energy              [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0", transformationPattern="JSONPATH:$.aenergy.total∩JS:shellyplus_energy_kwh.js" ] // From Shelly in Wh
        Type number         : Temperature         [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/cover:0", transformationPattern="JSONPATH:$.temperature.tC" ]
        Type string         : FWVersion           [ stateTopic="shellies/shellyplus25_Rollladen_WST/announce",  transformationPattern="JSONPATH:$.ver"]
        Type string         : UpdAvailable        [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/sys",  transformationPattern="REGEX:(.*stable.*)∩JSONPATH:$.available_updates.stable.version"]
        Type string         : RestartReq          [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/sys",  transformationPattern="REGEX:(.*restart_required.*)∩JSONPATH:$.restart_required"]
        Type number         : Uptime              [ stateTopic="shellies/shellyplus25_Rollladen_WST/status/sys",  transformationPattern="REGEX:(.*uptime.*)∩JSONPATH:$.uptime"] // in seconds
        Type string         : IP                  [ stateTopic="shellies/shellyplus25_Rollladen_WST/shellystatus/rpc", transformationPattern="REGEX:(.*sta_ip.*)∩JSONPATH:$.result.wifi.sta_ip"]
        Type string         : Devicestate         [ stateTopic="shellies/shellyplus25_Rollladen_WST/online" ]
    }

The transforms are small Javascripts, so you need the Javascript Transformation installed through the GUI.

image

shellyplus25_roller_position.js

(function(i){
    //console.log('shellyplus25_roller_position.js -> Variable i: ' + i);   
    i = 100 - i;

    //console.log('shellyplus25_roller_position.js -> Variable i: ' + i);               
    return (i);
})(input)

shellyplus25_roller_position_out.js

(function(i){
    //console.log('shellyplus25_roller_position_out.js -> Variable i: ' + i);
    if (i != 'STOP') {
        i = 100 - i;
        i = 'pos,' + i
    } else {
        i = 'stop'
    }

    //console.log('shellyplus25_roller_position_out.js -> Variable i: ' + i);               
    return (i);
})(input)

shelly.items

Rollershutter shellyplus25_Rollladen_WST_position        "Rolladen Werkstatt"    (g_Keller_Rolllaeden_position)
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Position" }
Rollershutter shellyplus25_Rollladen_WST_control         "Status"    (g_Keller_Rolllaeden_ctrl,g_Keller_Rolllaeden_ctrl_ueberanderenRL) 
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Control" }
String shellyplus25_Rollladen_WST_source             "WST Rollladen Eingabe" (g_shellyplus_source)
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Source" }
Number shellyplus25_Rollladen_WST_power              "WST Rollladen Power [%s W]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Power" }
//Number shellyplus25_Rollladen_WST_voltage            "WST Rollladen Voltage [%s V]"
//    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Voltage" }
Number shellyplus25_Rollladen_WST_energy             "WST Rollladen Energy [%s kWh]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Energy" }
//Number shellyplus25_Rollladen_WST_temperature        "WST Rollladen Temperatur"
//    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Temperature" }
String shellyplus25_Rollladen_WST_ip                 "IP Adresse [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:IP" }
String shellyplus25_Rollladen_WST_version       "Firmware [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:FWVersion" }
String shellyplus25_Rollladen_WST_updavailable       "FW Update [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:UpdAvailable" }
String shellyplus25_Rollladen_WST_restartreq         "Neustart notwendig [%s]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:RestartReq" }
Number shellyplus25_Rollladen_WST_uptime             "Uptime [%s s]"
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Uptime" }
String shellyplus25_Rollladen_WST_state              "Status [%s]" (g_shelly_status, g_shellyplus_status)
    { channel="mqtt:topic:mosquitto:shellyplus25_Rollladen_WST:Devicestate" [profile="transform:MAP", function="shelly.map"] }

The map transformations needs the binding installed
image

shelly.map

true=online
false=offline
0=nein
1=ja
NULL=undefiniert

shelly.sitemap

			Frame label="Shelly25 Rollladen Werkstatt"
			{
				Switch  item=shellyplus25_Rollladen_WST_control          
				Switch  item=shellyplus25_Rollladen_WST_position           mappings=[35="25%",65="50%",80="75%"]
				Text    item=shellyplus25_Rollladen_WST_power              label="Verbrauch:" icon="line"
				Slider  item=shellyplus25_Rollladen_WST_position           label="Rollladen (0-100%)"
				Text    item=shellyplus25_Rollladen_WST_temperature        label="Temperatur:" icon=none
				Text    item=shellyplus25_Rollladen_WST_overtemperature    label="Zu warm:" icon=none
				Text    item=shellyplus25_Rollladen_WST_stopreason         label="Haltegrund:" icon=none
				Text    item=shellyplus25_Rollladen_WST_id                 label="Bezeichnung:" icon=none
				Text    item=shellyplus25_Rollladen_WST_ip                 label="IP:" icon=none
				Text    item=shelly25_FW_Available                     label="Verfügbare FW:" icon=none
	        	Text   item=shellyplus25_Rollladen_WST_version             label="Installierte FW:" icon=none
	        	Text   item=shellyplus25_Rollladen_WST_updavailable        label="Update" icon=none
				Text    item=shellyplus25_Rollladen_WST_state              label="Status:" icon=none
				Switch  item=shelly_firmware_update                    mappings=[shellyplus25_Rollladen_WST="Start"]
			}

The command for positioning the blind is:
shellyplus25_Rollladen_WST_position.sendCommand(60)

The blind now goes to position 60.

I hope that leads you the way. If you have further questions please ask.

You answered everything perfectly. Thank you for sharing these examples.


I just stated that it’s not trivial and not easy because to invert a percentage you have to

  1. Install js transformation
  2. Learn about js scripts as transformations
  3. Write an incoming js transformation
  4. Write an outgoing js transformation that also respects possible commands. Your script is also not working with all commands (i.e. REFRESH, MOVE, UP and DOWN should also be handled) but the necessity of that depends how you use the items.

It would be a tremendous help if someone would improve the generic rollershutter mqtt thing to make this a configurable option.

If I’m not mistaken, you can esily use the Javascript transformations and invert your position by doing 100 - your position.

You can do transformation when receiving values or when sending values. I have a few blinds which are running in different directions, so 10 really means 90 etc.

(function(i){
    //console.log('shellyplus25_roller_position_out.js -> Variable i: ' + i);
    if (i != 'STOP') {
        i = 100 - i;
        i = 'pos,' + i
    } else {
        i = 'stop'
    }

    //console.log('shellyplus25_roller_position_out.js -> Variable i: ' + i);               
    return (i);
})(input)

It handles all commands.

UP, DOWN etc are not position elements, they are control elements:

shellyplus25_Rollladen_WST_control.sendCommand(DOWN)

But you are correct, this is no easy thing to do. You need a deep understanding what you are doing and a lot of time.
I think my setup is a bit special because I get all my device info from a Netbox as source of wisdom and all my things, items, sitemaps are created by python scripts. So, I’m not doing all the work by hand but it takes a lot of time to figure out what to do. It also takes a lot of time everytime someone at Shelly has a bright idea and changes EVERYTHING.
I think that somehow is what a hobby is meant to be. If it isn’t your thing you have to pay 40000€ and get Loxone installed by an electrician…

1 Like

You can use any language, even Rules DSL. It’s a long time since JS was the only one supported. That’s not an argument against fixing this in the MQTT binding, just a note for others who may come along and not realize that all rules languages (as of this writing) can be used to create a transformation.

I’ll also note that one can post transformations to the Marketplace now and they can be installed through MainUI → Add-on Store → Transformations. @schossel this looks like something useful enough to enough users you might consider publishing your transformation to the Marketplace.

The process is pretty easy.

  1. Create your transformation script; it should work as a file or a managed transformation
  2. MainUI → Developer Tools → API Explorer → transformations → GET transformations/{uid} where {uid} is the UID of the transformation created in 1
  3. Paste the JSON returned in step 2 as the “resource” on the Marketplace posting, fill out the rest of the post per the template
  4. MainUI → Settings → Community Marketplace → Show unpublished
  5. MainUI → Add-on Store → Transformations and you should now see your post. Try to add your transformation. If it’s successful you are done. I or another moderator will add the published tag after a brief review.

I know you mean well but if I have to rely on a marketplace binding/installation to invert a percentage in a smart home system that deals with percentages all the time something is fundamentally flawed.
Also be aware that depending on the channel linked a different set of commands has to be processed, too. E.g. some would need to invert UP/DOWN, too while others keep UP/DOWN and only invert percentage.
So a generic market place implementation would have to take all that into consideration.

It would have been very nice if there is a profile that could change/modify these values.
But unfortunately (as far as I know) the profiles still neither have a direction nor a defined order.

And as a marketplace post it can take all that into consideration. And do some error checking and more because it only has to be implemented once. And it can have arguments passed to control the behavior is one needs to control things like whether to swap UP/DOWN and such.

And anyone can do that now. No PRs. No arguing. No reviews from maintainers that require argument and compromise.

Again, I’m not saying this shouldn’t be fixed in core or in the binding, but if you want something right now you have an option. If you want something that pretty much anyone can use and give back to the community, you have that option too.

It’s better to say “sorry, this approach isn’t perfect, better to suffer and see when/if someone decides to fix it in core”? Where would HABApp be if you applied that? You’d still be waiting around for Python 3 support to be added to OH.

Script transformation profiles support direction.

Order is fixed. If there is a transformation on the Channel, that happens first for incoming state updates, then profiles, then UoM and finally state description pattern. Going the other direction you have the Profile Item Command to Thing, and then any outgoing transformations implemented by the binding.

For most of the profiles, what they do doesn’t make sense to go in the Item to Thing direction in the first place.

Thank you for your effort.
It works at my test OpenHab 4.x very well.
But on my productive OpenHab wich is still on 2.4 is throws my a
Invalid Jsonpath error.

BR Peter

It’s a wild guess, because I can’t really remember but I think it’s the ∩. If I’m not mistaken what it does is something like “if current_pos exists then do …” I think this functionality was not possible in 2.4.
I can’t test it but this would be where I would start to look.

I think Rich does some expalining here: [SOLVED] Nested REGEX and JSONPATH transformations - #2 by rlkoshak

It concats 2 things and is available since 2.5 M1.

It’s chaining. It lets you extrat a little bit of the String and pass that to another transformation. REGEX is a little different in that if the REGEX doesn’t match anything, it passes nothing on so chaining can and usually is used to filter messages.

For example if you have three different JSON’s that are posted to the same MQTT topic, one can use a REGEX transformation that only matches messages that you want to parse and chain that to a JSONPATH transformation to extract the value you want. Messages that do not match the REGEX get ignored instead of generating an error.

In 4.3 chaining was expanded a bit such that instead of using ∩ which is hard to type, you can chain transformations by putting each on it’s own line. This works for the transform profile at least but I think HTTP and MQTT Channel configs can use that too.

Other uses could be to use one JSONPATH to pull out an element from a JSON and then a Map transformation to convert that value to something that can be used by an OH Item. Stuff like that.