Hi Rene,
i use Openhab 4.1.0 Release Build
This is the error log:
2024-03-07 20:27:34.723 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ff5ee7ceb7' failed: org.graalvm.polyglot.PolyglotException: ReferenceError: "contextValues" is not defined
2024-03-07 20:27:40.571 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: ReferenceError: "contextValues" is not defined
at <js>.absorb_it_nspanel_callback(<eval>:174) ~[?:?]
at <js>.:program(<eval>:276) ~[?:?]
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 javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262) ~[java.scripting:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
at java.util.Optional.ifPresent(Optional.java:178) [?:?]
at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
at java.lang.Thread.run(Thread.java:840) [?:?]
This is the code from the blocky callback script:
function absorb_it_nspanel_callback_checkParam(param, noOfItems) {
let result = String(param);
if (result.charAt(0) != '~')
result = '~' + result;
while ((result.match(/~/g) || []).length < noOfItems)
result += '~'
while ((result.match(/~/g) || []).length > noOfItems)
result = result.replace(/~/, '');
return result;
}
function getTimerName() {
return 'absorb_it_nspanel_refreshTimer_' + ctx.ruleUID;
}
function absorb_it_nspanel_callback_startScript(scriptName, context, updateCacheLink) {
const RuleManager = osgi.getService('org.openhab.core.automation.RuleManager');
var thread = Java.type('java.lang.Thread');
if (!scriptName || scriptName === "Script Id")
return 0;
context["timerName"] = getTimerName();
try {
let timer = 10;
while (RuleManager.getStatus(scriptName) && RuleManager.getStatus(scriptName).toString() === "RUNNING") {
if (!timer--) {
console.log("finished waiting for rule " + scriptName);
break;
}
console.log("waiting 1 sec. for running rule " + scriptName);
thread.sleep(1000);
}
rules.runRule(scriptName, context);
cache.private.put('lastPage', scriptName); // any last page
if (updateCacheLink)
cache.private.put('currentCard', scriptName); // only some last pages (excluding popupNotify, Screensaver)
return 1;
}
catch (e) {
console.error("Error", e.stack);
console.log("Error", e.toString());
console.log("can't start/find rule with id '" + scriptName + "'");
}
return 0;
}
function absorb_it_nspanel_callback_safeEval(command, returnValue = '') {
// evaluate command, use returnValue as context
let result = "";
if (command) {
try { result = eval(command); }
catch (e) {
console.error("Error", e.stack);
console.log("Error", e.toString());
console.log("eval failed: '" + command + "'");
}
}
return result;
}
function absorb_it_nspanel_callback_killRefreshTimer() {
if (cache.shared.exists(getTimerName())) {
console.debug("remove existing refresh timer " + getTimerName());
cache.shared.remove(getTimerName()).cancel();
}
}
function absorb_it_nspanel_callback(target, timeout, screenSaverBrightness, activeBrightness, screensaver2, screensaverStartupScript, startupScript, startupAction, startupRedo) {
// on first run only...
if (!cache.private.exists('initialized')) {
// allow refreshing of dimming and timeout when saving configured callback
items.getItem(target).sendCommand(
"timeout" +
absorb_it_nspanel_callback_checkParam(timeout, 1)
);
items.getItem(target).sendCommand(
"dimmode" +
absorb_it_nspanel_callback_checkParam(screenSaverBrightness, 1) +
absorb_it_nspanel_callback_checkParam(activeBrightness, 1)
);
// store settings from blockly interface to be able to change them on-the-fly
cache.private.put('complexScreenSaver', screensaver2);
cache.private.put('enterScriptName', screensaverStartupScript);
cache.private.put('leaveScriptName', startupScript);
cache.private.put('startupRedo', startupRedo);
// done
cache.private.put('initialized', 1);
};
try {
contextValues = (JSON.parse(event.itemState))["CustomRecv"].split(',');
} catch {
if (event.itemState) {
// if callback received non-JSON string check for local requests
let callbackParam = event.itemState.toString().split('?');
switch (callbackParam[0]) {
case "refresh":
case "ON": // triggered by Hardware Button press (if rule configured to fire)
case "OFF": // triggered by Hardware Button press (if rule configured to fire)
if (cache.private.get('currentCard')) {
let context = {
"previousPage": cache.private.get('lastPage'),
"target": target
};
if (cache.private.exists('DetailPage')) {
context["request"] = "pageOpenDetail";
context["item"] = cache.private.get('DetailPage');
};
absorb_it_nspanel_callback_startScript(
cache.private.get('currentCard'),
context,
0
);
}
return;
case "refreshTimer":
if (cache.private.get('currentCard') && (cache.private.get('lastPage') !== "screensaver"))
absorb_it_nspanel_callback_startScript(
cache.private.get('currentCard'),
{
"previousPage": cache.private.get('lastPage'),
"target": target
},
0
);
return;
case "loadPage":
if (callbackParam[1])
contextValues = [ , "buttonPress2", callbackParam[1] ];
break;
case "loadScreensaver":
contextValues = [ , "sleepReached" ];
break;
case "newTimeout":
if (callbackParam[1])
items.getItem(target).sendCommand(
"timeout" +
absorb_it_nspanel_callback_checkParam(callbackParam[1], 1)
);
return;
case "newBrightness":
case "newBrigthness": // keep old value, type of parameter was fixed in 0.6
if (callbackParam[1] && callbackParam[2])
items.getItem(target).sendCommand(
"dimmode" +
absorb_it_nspanel_callback_checkParam(callbackParam[1], 1) +
absorb_it_nspanel_callback_checkParam(callbackParam[2], 1)
);
return;
case "complexScreenSaver":
{
cache.private.put('complexScreenSaver', callbackParam[1]);
return;
}
case "enterScriptName":
{
cache.private.put('enterScriptName', callbackParam[1]);
return;
}
case "leaveScriptName":
{
cache.private.put('leaveScriptName', callbackParam[1]);
if (callbackParam[1])
cache.private.put('startupRedo', "TRUE");
else
cache.private.put('startupRedo', "FALSE");
return;
}
default:
return;
}
}
}
switch(contextValues[1]) {
case "startup":
cache.private.put('screensaverActive', "FALSE");
items.getItem(target).sendCommand(
"timeout" +
absorb_it_nspanel_callback_checkParam(timeout, 1)
);
items.getItem(target).sendCommand(
"dimmode" +
absorb_it_nspanel_callback_checkParam(screenSaverBrightness, 1) +
absorb_it_nspanel_callback_checkParam(activeBrightness, 1)
);
let success = absorb_it_nspanel_callback_startScript(
cache.private.get('leaveScriptName'), { "target": target }, 1
);
absorb_it_nspanel_callback_safeEval(startupAction);
if (success || startupAction != '')
break;
case "sleepReached":
absorb_it_nspanel_callback_killRefreshTimer;
cache.private.put('screensaverActive', "TRUE");
if (cache.private.get('complexScreenSaver') == "TRUE")
items.getItem(target).sendCommand("pageType~screensaver2");
else
items.getItem(target).sendCommand("pageType~screensaver");
absorb_it_nspanel_callback_startScript(
cache.private.get('enterScriptName'), { "target": target }, 0
);
cache.private.put('lastPage', 'screensaver'); // therefore ignore timer updates during screensaver
break;
case "buttonPress2":
if (cache.private.get('screensaverActive') == "TRUE") {
cache.private.put('screensaverActive', "FALSE");
if (cache.private.get('startupRedo') == "TRUE")
cache.private.remove('currentCard');
}
switch(contextValues[3]) {
case "bExit":
cache.private.remove('DetailPage');
if (cache.private.get('currentCard'))
absorb_it_nspanel_callback_startScript(
cache.private.get('currentCard'), { "target": target }, 0
);
else
absorb_it_nspanel_callback_startScript(
cache.private.get('leaveScriptName'), { "target": target }, 1
);
break;
default:
if (contextValues[2].split('?')[0] !== cache.private.get('lastPage')) {
// new page called, probably clicked on navigation buttons
absorb_it_nspanel_callback_startScript(
contextValues[2].split('?')[0], { "target": target },
(contextValues[2] !== "popupNotify" && contextValues[3] !== "notifyAction")
);
}
// find the clicked item, if there hade been multiple on the page
let item = "";
// alarmButtons: third context field contains 'cb' and item id, reparated by '?'
// {"CustomRecv":"event,buttonPress2,*cardAlarmScriptName*,item?1,1"}
if (contextValues[3] && contextValues[3].split('?')[0] === "item")
item = contextValues[3].split('?')[1];
// HVACButtons: third context field contains script name and item id, reparated by '?'
// {"CustomRecv":"event,buttonPress2,*cardThermoScriptName*,hvac_action,item?1"}
if (contextValues[4] && contextValues[4].split('?')[0] === "item")
item = contextValues[4].split('?')[1];
// entities: third context field contains both script name and item id, reparated by '?'
// {"CustomRecv":"event,buttonPress2,*cardEntitiesScriptName*?2,OnOff,0"}
else item = contextValues[2].split('?')[1];
absorb_it_nspanel_callback_startScript(
contextValues[2].split('?')[0],
{
"request": cache.private.exists('DetailPage')?"pageOpenDetail":"pageUpdate",
"item": item,
"trigger": contextValues[3],
"newState": contextValues[4],
"previousPage": cache.private.get('lastPage'),
"target": target
},
(contextValues[2] !== "popupNotify" && contextValues[3] !== "notifyAction")
);
}
break;
case "pageOpenDetail":
let item = contextValues[3].split('?')[1];
cache.private.put('DetailPage', item?item:0);
absorb_it_nspanel_callback_startScript(
contextValues[3].split('?')[0],
{
"request": "pageOpenDetail",
"item": item,
"trigger": contextValues[2],
"target": target
},
1
);
break;
default:
}
}
absorb_it_nspanel_callback('nxpanel_command', 20, 50, 100, 'FALSE', '', 'nxpanel_card_grid', `items.getItem('nxpanel_command').sendCommand('loadScreensaver');`, 'TRUE');
The mqtt items work, because i tried nxpanel before.
Regards B-Tronic