Here is a good tutorial on lambdas: Reusable Functions: A simple lambda example with copious notes.
But I don’t think you need one in this case. To make things just a little easier, change your naming conventions to use some underscores (e.g. gPowerString_1_Port_1).
Next, add each Item as a trigger to a single rule. New in OH 2.2. is a variable called triggeringItem which will contain the Item that triggered the Rule.
Then we can use some string manipulation on the name of the Item that triggered the rule to get the port and state for your URL.
I’ll use a MAP to provide mapping between the strip number and its IP address (not shown, see https://docs.openhab.org/addons/transformations/map/readme.html)
With a few other minor changes your rules could collapse to:
rule "Steckdose"
when
Item gPowerStrip_1_Port_1 received command or
Item gPowerStrip_1_Port_2 received command or
...
Item gPowerStrip_2_Port_1 received command or
Item gPowerStrip_2_Port_2 received command or
...
then
val strip = triggeringItem.name.split("_").get(1)
val ip = transform("MAP", "steckdose.map", strip)
val port = triggeringItem.name.split("_").get(3)
val cmd = if(receivedCommand == ON) "1" else "0"
val encoded = URLEncoder::encode('{"port":'+port+', "state":'+cmd+'}', 'UTF-8')
sendHttpGetRequest("http://"+ip+"/?cmd=200&json="+encoded)
logInfo("Steckdose", "eingeschalet")
end
For the second rule I would use the HTTP binding with the caching config. Then create Items for the status and watt values. And then you just need a couple of simple rules.
rule "Status"
when
Item PowerStrip_1_Port_1_Status changes or
Item PowerStrip_1_Port_2_Status changes or
...
Item PowerStrip_2_Port_1_Status changes or
Item PowerStrip_2_Port_2_Status changes or
...
then
val gItemName = triggeringItem.name.replace("_Status","")
val status = if(triggeringItem.state.toString == "1") "ON" else "OFF"
postUpdate(gItemName, status)
end
rule "Watt"
when
Item PowerStrip_1_Port_1_Watt changes or
Item PowerStrip_1_Port_2_Watt changes or
...
Item PowerStrip_2_Port_1_Watt changes or
Item PowerStrip_2_Port_2_Watt changes or
...
then
val watt = (triggeringItem.state as Number)/1000
postUpdate("g"+triggeringItem.name, watt)
end
When you move to 2.3, you will be able to get rid of all of those triggers on the rules as well. Features for Rules that work with Groups There is a new Member of trigger for Rules so if you put all your Items into a Group you can trigger the rule on that Group and triggeringItem will be the member of the Group that triggered the Rule.
NOTE: the above examples are the only times when it is appropriate to use the postUpdate actions. You should use the method (e.g. gPowerString1Port1.postUpdate(ON)
) in all other cases. See https://docs.openhab.org/configuration/rules-dsl.html#sendcommand-method-vs-action.
Finally, it would be possible to remove the last watts rule above and use the JS transform to extract the value and divide by 1000 in the transform. Or you could keep the value large and use the JS transform to divide by 1000 in the label.
You also might be able to do away with the status change rule as well by adding the HTTP binding config to the gPowerString Item itself. The HTTP binding will update the state of the Item and you can use the rule above to command it.
It also occurs to me that you may be able to do away with the first rule as well using the outgoing config.
powerStrip1.url=http://192.168.22.12/?cmd=511
powerStrip1.updateInterval=10000 # every ten seconds
powerStrip2.url=http://192.168.22.13/?cmd=511
powerStrip2.updateInterval=10000
Switch gPowerStrip1Port1 { http="<[powerStrip1:10000:JSONPATH($.data.switch[0])]
>[ON:GET:http://192.168.22.12/?cmd=200&json=%7B%22port%22%3A1%2C%22state%22%3A1%7D]
>[OFF:GET:http://192.168/22/12?cmd=200&json=%7B%22port%22%3A1%2C%22state%22%3A0%7D]" }
Number gPowerStrip1Port1Watt "Watts [JS(watts.js): %d]" { http="<[powerStrip1:1000:JSONPATH($.data.watt[0])]" }
watt.js
(function(1) {
if(isNaN(i) return -1
return i / 1000
})(input)
In the above the HTTP caching config pulls the data down every ten seconds. The gPowerStrip1Port1 has three HTTP clauses. The first polls the cached data pulled by the binding every ten seconds, extracts the status and updates gPowerStrip1Port1 with the status. NOTE: this might not work if Switch can’t handle converting a “1” to ON and “0” to OFF in which case we would probably need a JS transform or the Rule above. The other two clauses causes the binding to issue a GET command to the supplied URL when it receives the ON or OFF command. Notice there are two clauses, one for ON and one for OFF.
For the Watts Item I use the cached data and I only divide the value by 1000 in the label. So the Item keeps the full value but shows it divided by 1000 on the UI.