JSON: transformation and triggering of items in a rule

I know, it’s time to have a look at the Next-Gen rules…
But until then, I have a problem with my rule here.

  1. I configured Nuki callback, which presents a JSON (which I relay via a PHP-script on my webserver, because a) the Nuki binding is broken and b) a direct callback doesn’t work)
  2. the JSON is sent to a item
  3. if the JSON gets an update, I like to parse it and update my Nuki items

so, the items:

String 		Nuki_callback		 	"Callback-Meldung [%s]"         

Number		Nuki_doorState			"Nuki State (Status) [%d]"		
Number		Nuki_doorStateName		"Nuki State (Name) [%s]"		
Number		Nuki_doorsensorState	"Nuki Sensor (Status) [%d]"		
String		Nuki_doorsensorName		"Nuki Sensor (Name) [%s]"		
Switch		Nuki_doorBattery		"Nuki Batteriestatus [%s]"		

the item “Nuki_callback” gets updated from Nuki via this JSON:

{"deviceType": 0, "nukiId": 123456789, "mode": 2, "state": 3, "stateName": "unlocked", "batteryCritical": false, "doorsensorState": 3, "doorsensorStateName": "door opened"}

in my rule, I like to update the items like this:

rule "Nuki Update"
when
	Item Nuki_callback received command
then
	logInfo("Nuki doorsensorname", "Name: " + transform("JSONPATH", "$.doorsensorStateName", Nuki_callback.state.toString))

	if (transform("JSONPATH", "$.batteryCritical", Nuki_callback.state).toString === "true") {
		Nuki_doorBattery.sendCommand(ON)
	} else {
		Nuki_doorBattery.sendCommand(OFF)	
	}
	Nuki_doorsensorName.sendCommand(transform("JSONPATH", "$.doorsensorStateName", Nuki_callback.state.toString).toString)
	Nuki_doorsensorState.sendCommand(transform("JSONPATH", "$.doorsensorState", Nuki_callback.state.toString).toString)
	Nuki_doorState.sendCommand(transform("JSONPATH", "$.state", Nuki_callback.state.toString).toString)
	Nuki_doorStateName.sendCommand(transform("JSONPATH", "$.stateName", Nuki_callback.state.toString).toString)
	
end

If the callback gets updated, I get this in the log:

2020-09-29 18:16:58.918 [ome.event.ItemCommandEvent] - Item 'Nuki_callback' received command {"deviceType": 0, "nukiId": 1234567879, "mode": 2, "state": 3, "stateName": "unlocked", "batteryCritical": false, "doorsensorState": 3, "doorsensorStateName": "door opened"}

==> /var/log/openhab2/openhab.log <==

2020-09-29 18:16:58.938 [INFO ] [ome.model.script.Nuki doorsensorname] - Name: door opened
2020-09-29 18:16:58.945 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Nuki Update': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.transform.actions.Transformation.transform(java.lang.String,java.lang.String,java.lang.String) on instance: null

I guess, I’ll never get my head wrapped around the “.toString”, when to use, I tried with and without and it won’t change the ERROR.

What do I miss here? Thanks!

this is how I would troubleshoot:

  1. I would store the transform into a variable with:
    var batteryCritical = transform(“JSONPATH”, “$.batteryCritical”, Nuki_callback.state.toString)

  2. I would compare like this
    if (batteryCritical == “true”) {
    Nuki_doorBattery.sendCommand(ON)
    } else {
    Nuki_doorBattery.sendCommand(OFF)
    }

PS: You used three times the =, not sure this is correct

1 Like

As @StefanH has shown, there are two main issues:

  1. The .toString must be inside your brackets, straight after state.
  2. You need to use == not ===.

I’ve just tested the below, and it seems to work:

if (transform("JSONPATH", "$.batteryCritical", Nuki_callback.state.toString) == "true") {
	logInfo("Nuki_callback", "Battery is critical")
} else {
	logInfo("Nuki_callback", "Battery is not critical")
}

Suggestion … if you want to update your Items, then update them.

someItem.postUpdate("yourData")

commands and state updates are two different things in openHAB

Following that theme …

There’s a trap in there.
Your rule is triggered by a command to an Item.
Then you immediately look at the state of that same Item.
Note that commands may or may not result in a state change, but they certainly do not act instantly. Any resulting update comes later.
So your rule is not looking at the state resulting from the command.
At least, not to begin with. Maybe it will even change while your rule is running.

If you really want to look at the command value in your rule, use the receivedCommand implicit variable.

Items getting commands from external scripts is unusual though. As with a binding, you’d normally get incoming data as state update. Then you would trigger the rule from received update

2 Likes

Thanks all!
It was the missing “.toString” within the JSONPATH transformation within the if-clause, als @hafniumzinc pointed out…
I told ya, I never know, when to use those buggars… :crazy_face:

And @rossko57, you’re absolutely right, if there was a stable binding, I’d prefer to use that also, but it’s unstable und unreliable. and the “Nuki bridge” (the hardware, which offers the API) offers hook-url to send callbacks if states change, but it doesn’t fit the OH2 REST API. So I’m forced to use the plain API and a roundtrip with an external script instead. And yeah, it’s a pain in the a**. But now it works. Thanks.