JSON Transformation with tuples won't work AND how-to-convert from String-to-Number [solved]

I want to transform a Thing via JSONPATH and get only null as Tranform response.

The Json-String (its from vzlogger, I fetch a s0-meter via a GPIO and want to get the Watt) looks like this:
{ “version”: “0.6.1”, “generator”: “vzlogger”, “data”: [ { “uuid”: “da700390-af1a-11e6-bc58-2d548e76e54c”, “last”: 1507031721882, “interval”: -1, “protocol”: “s0”, “tuples”: [ [ 1507031721882, 2714.9316893122327 ] ] } ] }

The value I want to get is the 2714.9316893122327.

My things-file:
Thing exec:command:stromzaehlertest [command=“curl -G --silent http://192.168.0.60:8081”, interval=5, timeout=1, transform=“JSONPATH($[‘data’].[‘tuples’].[1])”]

I tested the JSONPATH-part via http://jsonpath.com/ and it looks right for me, but in the DEBUG-Log it looks like this:

2017-10-03 18:51:59.010 [DEBUG] [hab.binding.exec.handler.ExecHandler] - Exec [OUTPUT]: '{ “version”: “0.6.1”, “generator”: “vzlogger”, “data”: [ { “uuid”: “da700390-af1a-11e6-bc58-2d548e76e54c”, “last”: 1507049517452, “interval”: -1, “protocol”: “s0”, “tuples”: [ [ 1507049517452, 2714.9316893122327 ] ] } ] }'
2017-10-03 18:51:59.610 [DEBUG] [hab.binding.exec.handler.ExecHandler] - Transformed response is ‘null’

Does anybody can help me? I don’t know what to do now and got a few hours spent on it.

PS: I got the Openhab Snapshotversion from last week (end of september 2017)

Try

JSONPATH($.data[0].tuples[1])

I’m not sure if the library OH uses supports bracket notation. All the examples I’ve ever seen use dot notation.

Thank you for your thought. With that setting it doesn’t work, but I tested in your direction.

With the setting

transform="JSONPATH($.data…tuples.)

I got

2017-10-03 20:34:43.395 [DEBUG] [hab.binding.exec.handler.ExecHandler] - Transformed response is ‘[[[1507031721882,2714.9316893122327]]]’

but then I don’t know how to get to the second value (2714,93…).

If using the [1] with tuples doesn’t work, I’m going to suggest you use a JS transform instead. With the builtin JSON support you can easily parse the JSON and just reference the right value.

I have tried this way you mentioned, but it doesn’t worked - sorry, I’m no developer :frowning:

file getValue.js in directory /transform with this line in:

JSON.parse(input).data[0].tuples.[1];

and my thing - file looks like this:
Thing exec:command:stromzaehlertest [command=“curl -G --silent http://192.168.0.60:8081”, interval=3, timeout=1,transform=“JS(getValue.js)”]

But it doesn’t work - it shows the whole json-string without change - but why?
Maybe I have to do this transformation in the items-file?

items
String stromzaehlertest “stromzaehlertest [%s W]” (All) {channel=“exec:command:stromzaehlertest:output”}

I don’t know how to do this…

See

http://docs.openhab.org/configuration/transform.html

and

http://docs.openhab.org/addons/transformations.html

and

http://docs.openhab.org/addons/transformations/javascript/readme.html

1 Like

I looked at this pages and searched in other places, but I’m no familiar with javascript.
But I’m a step further…

With getValue.js with
JSON.parse(input).data[0].tuples[0];

I got [object Array] in the frontend.

with
JSON.parse(input).data[0].tuples[1];
I get NULL in the frontend.

As a test i do
JSON.parse(input).data[0].protocol;
then I get s0 (which is correct) in the frontend - so it still works, but I can’t get the right value from the tuple.

Is there still a trick to get the right information from the JSON-String?
Maybe JSON.parse(input).data[0].tuples[1] has to be a little bit of other spelling or something?

Is your full .js file just that one line or are you following the instructions and are using something that looks like

(function(i) {
    var array = i.split(" ");
    return array[array.length - 1].length;
})(input)

?

Tuples is a two dimensional array so you need something like:

JSON.parse(input).data[0].tuples[0][0];

or

JSON.parse(input).data[0].tuples[0].[0];
1 Like

That’s the solution!!!

In my js - file is only this one line.
I changed it to
JSON.parse(input).data[0].tuples[0][0];
then it worked!!!

How I mentioned, I’m no developer - so I’m not familiar with JAVA, Arrays and such things - but now it worked like it should.
Thank you!

I’m surprised that worked. The docs say it should be in a function like the above.

I have (maybe) a simple Question at all - I can’t convert from e.g. 2714.93168 to 2714,93168 or 2714 (both variants are ok for my usecase).

So my getvalue.js-file now contains this:

(function(i) {
var newstring = JSON.parse(i).data[0].tuples[0][1];
return newstring;
})(input)

-> This works with this settings:

thing:
Thing exec:command:stromzaehlertest [command=“curl -G --silent http://192.168.0.60:8081”, interval=2, timeout=1, transform=“JS(getValue.js)”]

item:
String stromzaehlertest “stromzaehlertest [%s]” (All) {channel=“exec:command:stromzaehlertest:output”}

sitemap:
Text item=stromzaehlertest
-> it shows e.g. 2714.93168 in the frontend

But I can’t convert it to the mentioned value above.
I’d try to integrate it in the getvalue.js-file:

(function(i) {
var newstring = JSON.parse(i).data[0].tuples[0][1];
var newstring = newstring.replace(".",",");
return newstring ;
})(input)

But then this error occours:
An exception occurred while transforming ‘{ “version”: “0.6.1”, “generator”: “vzlogger”, “data”: [ { “uuid”: “da700390-af1a-11e6-bc58-2d548e76e54c”, “last”: 1507483756317, “interval”: -1, “protocol”: “s0”, “tuples”: [ [ 1507483756000, 2714.93168 ] ] } ] }’ with ‘JS(getValue.js)’ : ‘An error occurred while executing script.’

When I remove the line with the newstring.replace, then it works again, but without conversion from . to ,

Maybe I make something basically wrong with the handling of JAVASCRIPT in this case?

I don’t know JavaScript that well but assuming you define a new variable using car, you can not define another variable of the same name and that is essentially what you after doing on the second line. Get rid of the car in front of the newstring on the second line.

Thank you Rich for your help! Thats one great step to the solution, but it doesn’t worked as well.
But with this code it gets the Number before the . (e.g. 2123.4445 will transform to 2123)

(function(i) {
	var oldstring = JSON.parse(i).data[0].tuples[0][1];
	var newstring = oldstring.toString();
	split = newstring.split(".");
	return split[0];
})(input)

But now I have found the problem, that the exec:command:output (I use it for the thing/item stromzaehlertest )is always a string, that means, I can’t use it for saving in the persistence-database.

Is there a way to convert such strings in numbers and save it e.g. in a new number-item?
I thought about rules, but my test wasn’t working (in SmartHome Designer it shows an error ):

My rules-file:

val Number conversion
 rule "conversion"
when
  Item stromzaehlertest changed
then
  conversion = Integer.valueOf(stromzaehlertest);
  postUpdate(Stromzaehler, conversion)
end

I made a new item called Stromzaehler, which is a Number-item.
As a error I get

“Type mismatch: cannot convert from StringItem to String”

at the conversion = … -line.

Is there another way to convert such a string to a number for the case in saving in the persistence-database?

Thanks a lot for your support!!!

You are on the right track. You do need a Rule. But you need to parse the state of the Item.

Please review the Rules section of the documents, and in particular this section.

To obtain the state of an Item one must call .state, as in stromzaehlertest.state.

Yes! Now it got it.
This is my working rule-file:

var Number conversion
var String get_stromzaehlerteststate 
 rule "conversion"
when
  Item stromzaehlertest changed
then
  get_stromzaehlerteststate = stromzaehlertest.state.toString();
 conversion = Integer.valueOf(get_stromzaehlerteststate);
  Stromzaehler.postUpdate(conversion)
end

And my item look like this:

Number Stromzaehler "Socket [%.0f W]" <energy> (All)

The important thing was the “f” in the [%.0f W] and that I have to get the stromzaehlertest.state.toString() in the rule. Without the last thing the error doesn’t go away in the SmartHome Designer.
Anyway - it works.

Many thanks to you, Rich! :grinning: