javascriptmqttgraalvmopenhab

ECMAScript shows error after 1 successfull run of script in Openhab


Platform information:

Hardware: Synology with docker
OS: Linux/4.4.302+ (amd64)
Java Runtime Environment: debian 17.0.12
openHAB version: openHAB 4.2.2

Issue of the topic: I have a rule that triggers when a widget (heating) changes the setpoint of a thermostat (evohome). The script of the rule is build on ecmascript (v11). It converts some variables + item value into a stringified JSON message on the command topic of the mqtt broker . When triggered a first time, the script runs and publishes a message on the broker, and changes te setpoint. After that, the script is ‘broken’. It takes a while, and a reinitialize of the scriptengine makes it work again 1 time. I cannot get my head around why this is happening

Tried different things, depending on the various forums i checked on topics Javascript/JSON/MQTT/Graalvm/Openhab etc, but there isn't a specific forum that discusses mqtt with evohome on Openhab 4. Understand that the code works, and fires successfull, but only one time.

Code build up (complete rule):

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Thermostaat_zone_temperature_setpoint
    type: core.ItemStateUpdateTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: >-
        var item = items.Thermostaat_zone_temperature_setpoint;

        var obj = new Object();

        obj.command = "set_zone_setpoint";

        obj.setpoint = item.state;

        obj.zone_idx = 1;

        obj.ctl_id = "ID";

        var val = parseFloat (obj.setpoint);

        obj.setpoint = val;

        var message = JSON.stringify(obj);

        var actions = actions.get("mqtt", "mqtt:broker:master");

        actions.publishMQTT("evohome/evogateway/_zone_independent/command",
        message);

        console.log(message);
    type: script.ScriptAction

Logging gives the following (Log when succesfull):

2024-10-17 20:17:02.354 [DEBUG] [.internal.OpenhabGraalJSScriptEngine] - Initializing GraalJS script engine...
2024-10-17 20:17:02.360 [DEBUG] [.internal.OpenhabGraalJSScriptEngine] - Injecting ThreadsafeTimers into the JS runtime...
2024-10-17 20:17:02.361 [DEBUG] [.internal.OpenhabGraalJSScriptEngine] - Evaluating cached global script...
2024-10-17 20:17:02.362 [DEBUG] [.internal.OpenhabGraalJSScriptEngine] - Evaluating cached openhab-js injection...
2024-10-17 20:17:02.417 [DEBUG] [.internal.OpenhabGraalJSScriptEngine] - Successfully initialized GraalJS script engine.
2024-10-17 20:17:02.420 [INFO ] [ab.automation.script.ui.evo_zone] - {"command":"set_zone_setpoint","setpoint":20.5,"zone_idx":1,"ctl_id":"id code"}
2024-10-17 20:17:02.420 [DEBUG] [ing.mqtt.internal.action.MQTTActions] - MQTT publish to evohome/evogateway/_zone_independent/command performed

Logging gives the following (Log when failed):

2024-10-18 06:51:42.850 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'evo_zone' failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (get) on org.openhab.binding.mqtt.internal.action.MQTTActions@27c6d6d2 failed due to: Unknown identifier: get
2024-10-18 06:54:44.350 [ERROR] [ation.script.javascript.evo_eetkamer] - Failed to execute script: TypeError: invokeMember (get) on org.openhab.binding.mqtt.internal.action.MQTTActions@27c6d6d2 failed due to: Unknown identifier: get
        at <js>.:program(<eval>:10)
        at org.graalvm.polyglot.Context.eval(Context.java:399)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426)
        at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262)

Solution

  • Writing this up as a full answer.

    As determined from the comments, the problem is that you are overwriting the actions object at the end of the first run, which means there is no get function when it runs the second time.

    A couple of extra things

    The stack trace does actually contain something useful

    2024-10-18 06:54:44.350 [ERROR] [ation.script.javascript.evo_eetkamer] - Failed to execute script: TypeError: invokeMember (get) on org.openhab.binding.mqtt.internal.action.MQTTActions@27c6d6d2 failed due to: Unknown identifier: get
            at <js>.:program(<eval>:10)
            at org.graalvm.polyglot.Context.eval(Context.java:399)
    

    The second line is actually the place in the script it's failing, <js> means it's in the JavaScript, <eval>:10 is the 10th line.

    Which if you take all the blank lines out of the script: >- sections get's you to:

    var item = items.Thermostaat_zone_temperature_setpoint;
    var obj = new Object();
    obj.command = "set_zone_setpoint";
    obj.setpoint = item.state;
    obj.zone_idx = 1;
    obj.ctl_id = "ID";
    var val = parseFloat (obj.setpoint);
    obj.setpoint = val;
    var message = JSON.stringify(obj);
    var actions = actions.get("mqtt", "mqtt:broker:master");  // << line 10
    actions.publishMQTT("evohome/evogateway/_zone_independent/command", message);
    console.log(message);
    

    The quickest fix is to not reuse actions as a variable name inside the script so line 10 and 11 become

    var action = actions.get("mqtt", "mqtt:broker:master");  
    action.publishMQTT("evohome/evogateway/_zone_independent/command", message);