Issue with configuring item to transform

Hi all,

I have a working item doing some math to recalculate a duration from secons to a more human readable format.

The HTTP item transformation works fine:

Number AutoMowerDuration "Dauer [%s]"                                                                   <clock-on>              {http="<[automowerCache:30000:JS(automower_duration.js)]"}

I am now looking into getting the same conversion with a channel-based item which is currently looking as follows:

Number robonect_duration "Dauer aktueller Modus"        <grass> {channel="robonect:mower:13b76ca8:mowerStatus#duration" }

I had no luck with

Number robonect_duration "Dauer aktueller Modus"        <grass> {channel="<[robonect:mower:13b76ca8:mowerStatus#duration:JS(automower_duration.js)]>}"

Could someone please point me towards the correct syntax?

Thanks,

Ben

Number robonect_duration "Dauer aktueller Modus [%s]"   <grass> {channel="<[robonect:mower:13b76ca8:mowerStatus#duration:JS(automower_duration.js)]>" }

results in

[ERROR] [el.item.internal.GenericItemProvider] - Binding configuration of type 'channel' of item 'robonect_duration' could not be parsed correctly.
org.eclipse.smarthome.model.item.BindingConfigParseException: UID segment '<[robonect' contains invalid characters. Each segment of the UID must match the pattern [A-Za-z0-9_-]*.
        at org.eclipse.smarthome.model.thing.internal.GenericItemChannelLinkProvider.createItemChannelLink(GenericItemChannelLinkProvider.java:77)[136:org.eclipse.smarthome.model.thing:0.9.0.b5]
        at org.eclipse.smarthome.model.thing.internal.GenericItemChannelLinkProvider.processBindingConfiguration(GenericItemChannelLinkProvider.java:67)[136:org.eclipse.smarthome.model.thing:0.9.0.b5]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:325)[126:org.eclipse.smarthome.model.item:0.9.0.b5]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:297)[126:org.eclipse.smarthome.model.item:0.9.0.b5]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.processBindingConfigsFromModel(GenericItemProvider.java:182)[126:org.eclipse.smarthome.model.item:0.9.0.b5]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.modelChanged(GenericItemProvider.java:367)[126:org.eclipse.smarthome.model.item:0.9.0.b5]
        at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.notifyListeners(ModelRepositoryImpl.java:286)[125:org.eclipse.smarthome.model.core:0.9.0.b5]
        at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.addOrRefreshModel(ModelRepositoryImpl.java:136)[125:org.eclipse.smarthome.model.core:0.9.0.b5]
        at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.checkFile(FolderObserver.java:234)[125:org.eclipse.smarthome.model.core:0.9.0.b5]
        at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.processWatchEvent(FolderObserver.java:297)[125:org.eclipse.smarthome.model.core:0.9.0.b5]
        at org.eclipse.smarthome.core.service.WatchQueueReader.run(WatchQueueReader.java:206)[101:org.eclipse.smarthome.core:0.9.0.b5]
        at java.lang.Thread.run(Thread.java:748)[:1.8.0_131]
		
		

Unfortunately, you cannot apply a transform to a channel link. If the binding supports transforms, you would add the transform to the Thing definition and it will be documented in the binding’s readme.

If the binding does not support transforms, you will have to do the transform in a Rule.

1 Like

Thanks Rich. Could you let me know as of how this would need to be done in a rule? Binding unfortunately doesn’t support transform.

This is what’s inside the .js to transform:

(function(i) {
    var ret = "";
    var seconds = JSON.parse(input).status.duration;
    var days = Math.floor(seconds/(24*60*60));
    var restwodays = seconds % (24*60*60);
    var hours = Math.floor(restwodays/(60*60));
    var restwohours = restwodays % (60*60);
    var minutes = Math.floor(restwohours/ 60);
    var seconds = restwohours % 60;

    var minutess = "" + minutes;
    if(minutes<=9) minutess = "0"+minutes;

    var secondss = "" +  seconds;
    if(seconds<=9) secondss = "0"+seconds;

    if ( days  > 0 )   ret = ""  + days    + "T ";
    if ( hours > 0 )   ret = ret + hours   + ":";
    if ( minutes > 0 ) ret = ret + minutess + ":";
    ret = ret + secondss + "";
    return ret;
})(input)

You need two items, one linked to the channel and one unbound to hold the transformed value.

Create a rule that triggers when the linked item changed our updates.

Update the unbound item with the result of

transform("JS", "automower_duration.js", robonect_duration.state.toString)
1 Like

I can’t find an example how to achieve that, could you maybe line out the complete rule?

http://docs.openhab.org/tutorials/beginner/index.html

http://docs.openhab.org/configuration/rules-dsl.html

1 Like

Obviously something is wrong.

Defined a new string item without a linking to the channel:

String robonect_transform "Dauer aktueller Modus [%s]"

Created a new rule:

automowr_duration.rules

rule TransformRobonectDuration
when
        Item robonect_duration received update
then
        robonect_transform = transform("JS", "automower_duration.js", robonect_duration.state.toString)
end

Unfortunately resulting in

[ERROR] [ore.transform.actions.Transformation] - Error executing the transformation 'JS': An error occurred while executing script.
[ERROR] [.script.engine.ScriptExecutionThread] - Rule 'TransformRobonectDuration': An error occurred during the script execution: Cannot assign a value in null context.

Now ending up with

[ERROR] [.script.engine.ScriptExecutionThread] - Rule 'TransformRobonectDuration': An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: automower_duration.rules#|::0.2.0.2.0.1::0::/1)

Current rule:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
import org.openhab.core.transform.actions.Transformation

rule "TransformRobonectDuration"
when
        Item robonect_duration changed
then
        var String robonectduration value = transform("JSONPATH", "automower_duration.js", robonect_duration.state.toString)
        postUpdate("robonect_transform", robonectduration)
end

Current shot:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
import org.openhab.core.transform.actions.Transformation

rule "TransformRobonectDuration"
when
        Item robonect_duration changed
then
        var robonectduration=transform("JSONPATH", "automower_duration.js", robonect_duration.state.toString)
        postUpdate("robonect_transform", robonectduration)
end

Resulting in

[ERROR] [.script.engine.ScriptExecutionThread] - Rule 'TransformRobonectDuration': The argument 'state' must not be null or empty.

Now I am really lost.

Current rule status:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
import org.openhab.core.transform.actions.Transformation

rule "TransformRobonectDuration"
when
        Item robonect_duration changed
then
        var robonectduration=transform("JSONPATH", "automower_duration.js", robonect_duration.state.toString)
        robonect_transform.postUpdate(robonectduration)
        logInfo("test_log","[Test Log]Log entry test...")
end

Item definition

Number robonect_duration "Dauer aktueller Modus [%s]"   <grass> {channel="robonect:mower:13b76ca8:mowerStatus#duration" }
String robonect_transform "Dauer aktueller Modus [%s]"

Current status:

Log entry is being created, tested it to determine whether rule kicks in at all, so obviously yes. However, robonect_transform is not updated at all.

I could imagine this is down to JS being wrong, so also this one again for the records:

(function(i) {
    var ret = "";
    var seconds = JSON.parse(input).status.duration;
    var days = Math.floor(seconds/(24*60*60));
    var restwodays = seconds % (24*60*60);
    var hours = Math.floor(restwodays/(60*60));
    var restwohours = restwodays % (60*60);
    var minutes = Math.floor(restwohours/ 60);
    var seconds = restwohours % 60;

    var minutess = "" + minutes;
    if(minutes<=9) minutess = "0"+minutes;

    var secondss = "" +  seconds;
    if(seconds<=9) secondss = "0"+seconds;

    if ( days  > 0 )   ret = ""  + days    + "T ";
    if ( hours > 0 )   ret = ret + hours   + ":";
    if ( minutes > 0 ) ret = ret + minutess + ":";
    ret = ret + secondss + "";
    return ret;
})(input)

Assuming you are running OH 2, eliminate all of the imports.

Put your log info as the first line of the rule and then log out the value of robonectduration.

You are using the wrong transform. JSONPATH is used to extract values from JSON formatted strings. To execute a JavaScript function you use “JS”.

Make sure you have the JS transform installed.

1 Like

Yepp, am on OH2. Imports eliminated. I tried JS but that returned an error.

transformation-javascript - 2.1.0 is installed according to PaperUI.

Rule currently looking as followed:

rule "TransformRobonectDuration"
when
        Item robonect_duration changed
then
        logInfo("test_log","[Test Log]Log entry test...")
        var robonectduration=transform("JS", "automower_duration.js", robonect_duration.state.toString)
        robonect_transform.postUpdate(robonectduration)
        logInfo("FILE",robonectduration)
end

Resulting in following logfile output when robonect_duration gets updated:

==> /var/log/openhab2/events.log <==
2017-07-20 22:40:05.432 [ItemStateChangedEvent     ] - robonect_duration changed from 44729 to 44752

==> /var/log/openhab2/openhab.log <==
2017-07-20 22:40:05.433 [INFO ] [ipse.smarthome.model.script.test_log] - [Test Log]Log entry test...
2017-07-20 22:40:05.444 [ERROR] [ore.transform.actions.Transformation] - Error executing the transformation 'JS': An error occurred while executing script.

==> /var/log/openhab2/events.log <==
2017-07-20 22:40:05.447 [ItemStateChangedEvent     ] - robonect_transform changed from 44729 to 44752

==> /var/log/openhab2/openhab.log <==
2017-07-20 22:40:05.448 [INFO ] [.eclipse.smarthome.model.script.FILE] - 44752

So I still believe something is wrong with the .js… but it works just fine with the HTTP variant item…

The JavaScript is failing for some reason. I’m no JavaScript expert so all I can suggest is to comment out the bulk of the JS and slowly add back in the lines until you can figure out on what line it is failing.

1 Like

Okay, so you agree the rule itself should be fine now, but the JS part is having errors and I can continue to try to solve that and leave the rule assuming it’s fine for the time being?

The rule looks fine and it triggering and executing up to the transform call. That is all I can say at this point.

1 Like

Thank you so much Rich for your help so far. I’ll try to find someone who can help me with the JS part.