OpenHAB2 JavaScript Transform

Hey guys,

I’ve been racking my brain around getting JavaScript transforms to work. I’m hoping someone here may be able to tell me what I’m doing wrong…

I have the Javascript transform installed via. PaperUI. I’m using the Nest binding and have it successfully linked to my Nest account and Thermostat. I’m able to pull the temperature, however, the Nest binding currently only exposes the temperature in Celsius.

I have the following CtoF.js file in my transform folder. I currently just have it returning a hard 99 just to ensure that the function is even being called. Once showing that this works, I would replace with the C to F conversion function.

(function(i) {
    return 99;
})(input)

In my .items file I have the following:

Number diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%.1f °F]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

When I view the sitemap I get the following error:

[.core.transform.TransformationHelper] - Cannot format state '20.0' to format '%.1f °F': f != java.lang.String

I’ve tried multiple different permutations and plenty of searching and I’m not getting anywhere. I have updated the format to convert it to a string, to get rid of the error… But it doesn’t appear the javascript is being hit and if so, that it’s not returning a proper value.

Thank you in advance.

~Greg

1 Like

I think what is going on is that the JS transform returns a String and a String value is incompatible with %.1f for formatting. what happens when you use just %s?

Hi Rich,

I tried converting to a string as a test and only get a NULL result. For instance:

.items

String diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%s °F]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

CtoF.js

(function(i) {
    return "TEST";
})(input)

Now when I view it, there is no error but the value is NULL.

The literal String “NULL” or “-” indicating the state of the Item is NULL, or the literal String “null”?

And what I meant by using %s was to leave the function alone with a return of 99, leave the Item as a Number Item. Just change the label.

Oops, sorry about that. I’ve set it back and only updated it %s.

.items

Number diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%s °F]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

CtoF.js

(function(i) {
    return 99;
})(input)

With this I do not get an error, but the temperature does not report as 99, it reports as 20 (which is the real temperature).

Very odd. You have the transform install but perhaps there is something wrong with the install. Do you see it in PaperUI still as installed after restarting OH? Does it show as enabled in the Karaf console? Any errors in the log from the transformation service?

It is acting like the JS transform is not installed.

Hi Rich,

The PaperUI shows that it’s installed. The Karaf console shows the below and I don’t see anything in the logs from the transform service.

199 │ Active   │  75 │ 0.9.0.201710180819     │ Eclipse SmartHome JavaScript Transformation Service

One thing I did notice, is when I the output I’m getting doesn’t reflect the format I’m requesting… For instance, if I enter the following into the .items file:

Number diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%s TEST]" { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

My output is “21”, not “21 TEST” as I would expect.

Have you defined the label in your sitemap too? That one takes precedence over the label defined in your .items file.

Hi Rich,

No I haven’t. I’m trying to define my transforms in the .items for consistency. So in my .sitemap it is defined as follows:

Text item=diningRoomThermostat_Temperature

So to recap, this works as expected:

Number diningRoomThermostat_Temperature  "Temperature [%.1f °C]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

However, once I throw the JS() transform in it this is logged in the error log:

Number diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%.1f °F]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

[WARN ] [.core.transform.TransformationHelper] - Cannot format state '21.0' to format '%.1f °F': f != java.lang.String

Changing the %.1f in the .items to %s get’s rid of the error in the log, but then it appears the transform is not applied and I get an output of just 21.

Number diningRoomThermostat_Temperature  "Temperature [JS(CtoF.js):%s °F]"          { channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

I appreciate the time. Thank you.

Greg

I’m fresh out of ideas. At this point all I can think of is to file an issue. I think all the transformations are maintained on the ESH repo.

Thank you Rich. It’s good to know that I’m at least on the right track and that you didn’t see anything very obvious.

Hi Rich,

If I may add one more piece to this puzzle. I was using the OpenHAB Android app and I noticed that the thermostat was showing 99! So it looks like the transform is being called and working, but, PaperUI and HABmin still do not show the transformed value, they still only show 20.5. Any ideas why it would work in the Android app and not the web interfaces?

Also, none of the interfaces are show the °F label when using the transform. I’m using this for the item:
“Temperature [JS(CtoF.js):%s °F]”

Thanks again.

Greg

I don’t think PaperUI will work properly with .items file defined Items. PaperUI is intended to be an admin UI, not a day-to-day user’s interface. I’m not surprised that it doesn’t show the label properly. I’ve less experience with Habmin and I do know that others are using it as an user’s interface but it too is kind of intended to be more of an admin UI.

What does it look like with BasicUI, ClassicUI, or HABpanel? Those are your user’s interfaces (in addition to the phone apps).

I assumed you were using one of these UIs and having problems.

Hi Rich,

Thank you for that explanation. You are correct. It’s showing up fine in the Basic UI and the Android app. So I think I’m good! Thank you for the assistance!

For anyone else that may come across this searching I’d like to just leave my final solution.

.items

Number diningRoomThermostat_Temperature  "Temperature [JS(tempConvert.js):%s F]"{ channel="nest:thermostat:nest_account:diningRoomThermostat:temperature" }

I updated my javaScript to allow both temperature conversions C to F as well as F to C. To use it just pass the degrees and desired scale as shown in the .items file above.

transform/tempConvert.js

(function(i) {
	//The following script converts °C to °F or °F to °C.
	//Example: Passing "21 F" (Case sensitive) will convert 21 °C to °F.
	//Example: Passing "40 C" (Case sensitive) will convert 40 °F to °C.
	var res = i.split(" ");
	
	//Check requested scale
	if(res[1] == "F"){
		var degrees = (res[0] * (9/5)) + 32;
		var scale = " °F";
	} else if (res[1] == "C") {
		var degrees = (res[0] - 32) * (5/9);		
		var scale = " °C";
	} else {
		//No scale passed
		var degrees = 1000;
		var scale = " ERROR";
	}
	
	//Return result with one decimal accuracy
	return +degrees.toFixed(1) + scale;
})(input)

Greg

5 Likes