Sure! I set the metadata on the item via Main UI like this:
value: " "
config:
devicewaittime: 10
deviceoff: 0.1
devicerunning: 3
In the code I used this line to get devicewaittime:
var waitTime = statusConfig.configuration["devicewaittime"];
When I later use this to setup a timer:
var timeoutId = setTimeout(deviceFinished, waitTime, outlet);
This fails miserably (you will find the * 1000 in the complete code below. It wasn’t there when this exception popped up. I added it later, I simply forgot it before):
2024-07-22 19:50:00.699 [ERROR] [omation.script.javascript.d1edc3008c] - Failed to execute script: TypeError: invokeMember (setTimeout) on org.openhab.automation.jsscripting.internal.threading.ThreadsafeTimers@3453db4d failed due to: Cannot convert '10.0'(language: Java, type: java.math.BigDecimal) to Java type 'java.lang.Long': Invalid or lossy primitive coercion.
at <js>.globalThis.setTimeout(@jsscripting-globals.js:167)
at <js>.main(<eval>:70)
at <js>.:program(<eval>:74)
at org.graalvm.polyglot.Context.eval(Context.java:399)
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458)
... 23 more
So I changed it now to:
var waitTime = statusConfig.configuration["devicewaittime"].longValue()
This works but maybe I should just use strings for metadata. It’s more transparent than to deal with a BigDecimal.
Complete code (there still might be other bugs since I changed a few things while migrating from my old to my new OH instance):
function deviceFinished(outlet) {
items[outlet.name + '_status'].sendCommandIfDifferent('FINISHED');
actions.notificationBuilder("Gerät ist fertig").withTitle(outlet.label).withReferenceId(outlet.name).send();
}
function deviceSwitchedOff(outlet) {
items[outlet.name + '_status'].sendCommandIfDifferent('OFF');
actions.notificationBuilder("Gerät wurde ausgeschaltet").withReferenceId(outlet.name).hide().send();
}
function cancelTimer(outlet) {
if (cache.private.exists(outlet.name)) {
var timeoutId = cache.private.get(outlet.name);
console.debug("Removing existing timer for outlet", outlet.name, "(", timeoutId, ")");
// This will also clear a timer added by setInterval
clearTimeout(timeoutId);
cache.private.remove(outlet.name);
}
}
function updateRuntime(outlet) {
var runtimeItem = items[outlet.name + "_runtime"];
var currentRuntime = runtimeItem.numericState;
runtimeItem.sendCommand(currentRuntime + 1 + " min");
}
function main(itemName, newState, oldState) {
var outlet = items[itemName].semantics.equipment;
if (outlet == null) {
console.warn("Trigger item is not part of an equipment");
return;
}
if (outlet.semantics.equipmentType != "PowerOutlet") {
console.warn("Expected Equipment type PowerOutlet. Got" + equipment.semantics.equipmentType + "instead.")
return;
}
var statusConfig = outlet.getMetadata("status");
if (statusConfig == null) {
console.warn("No status configuration found for outlet", outlet.name);
return;
}
var deviceOff = statusConfig.configuration["deviceoff"];
var deviceRunning = statusConfig.configuration["devicerunning"];
var waitTime = statusConfig.configuration["devicewaittime"].longValue() * 1000;
if (deviceOff == null || deviceRunning == null || waitTime == null) {
console.warn("Incomplete status configuration", deviceOff, deviceRunning, waitTime);
return;
}
if (newState <= deviceOff) {
cancelTimer(outlet);
var previousStatus = items[outlet.name + '_status'].state;
items[outlet.name + '_status'].sendCommandIfDifferent('OFF');
if(previousStatus == "RUNNING") {
deviceSwitchedOff(outlet);
}
} else if (newState >= deviceRunning && oldState < deviceRunning) {
cancelTimer(outlet);
items[outlet.name + '_status'].sendCommandIfDifferent('RUNNING');
items[outlet.name + '_runtime'].sendCommandIfDifferent("0 min");
var timeoutId = setInterval(updateRuntime, 60 * 1000, outlet);
cache.private.put(outlet.name, timeoutId);
} else if (newState < deviceRunning && oldState >= deviceRunning) {
var timeoutId = setTimeout(deviceFinished, waitTime, outlet);
cache.private.put(outlet.name, timeoutId);
}
}
main(this.event.itemName, this.event.itemState, this.event.oldItemState);