Blockly Date Time functions generating errors after migrating to 4.0

Since I migrated from OH 3 to 4 I experience some issues with the dates & times blocks.
When I execute the following code sequence:

image

The Error Log shows the the following:


2023-08-07 12:28:46.386 [WARN ] [mation.script.ui.Licht_Toilet_Ouders] - DAYLIGHT
2023-08-07 12:28:46.399 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (sendBroadcastNotification) on org.openhab.io.openhabcloud.NotificationAction failed due to: no applicable overload found (overloads: [Method[public static void org.openhab.io.openhabcloud.NotificationAction.sendBroadcastNotification(java.lang.String)], Method[public static void org.openhab.io.openhabcloud.NotificationAction.sendBroadcastNotification(java.lang.String,java.lang.String,java.lang.String)]], arguments: [false (Boolean), warn (String), high (String)])
	at <js>.:program(<eval>:46) ~[?:?]
	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) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) ~[?:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) ~[?:?]
	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:833) ~[?:?]
2023-08-07 12:28:46.403 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Licht_Toilet_Ouders' failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (sendBroadcastNotification) on org.openhab.io.openhabcloud.NotificationAction failed due to: no applicable overload found (overloads: [Method[public static void org.openhab.io.openhabcloud.NotificationAction.sendBroadcastNotification(java.lang.String)], Method[public static void org.openhab.io.openhabcloud.NotificationAction.sendBroadcastNotification(java.lang.String,java.lang.String,java.lang.String)]], arguments: [false (Boolean), warn (String), high (String)])

Can somebody take a look at this problem? Thanks

Is that your entire Blockly Rule? The error seems to refer to sendBroadcastNotification but that is not in the screenshot you posted?

Also, you will be asked for the generated code by the more qualified posters I am sure.

Thanks Mark,

Hereby the script

There seem to be Nashorn functions to in the script.

var BetwHours;

// Nashorn
function zdtCompare(zdt1, zdt2, compareOp, precision, compDate) {
  switch (precision) {
    case 'years':
     zdt2 = zdt2.withMonth(zdt1.getMonthValue());
    case 'months':
     zdt2 = zdt2.withDayOfMonth(zdt1.getDayOfMonth());
    case 'days':
     zdt2 = zdt2.withHour(zdt1.getHour());
    case 'hours':
     zdt2 = zdt2.withMinute(zdt1.getMinute());
    case 'minutes':
     zdt2 = zdt2.withSecond(zdt1.getSecond());
    case 'seconds':
     zdt2 = zdt2.withNano(zdt1.getNano());
  }
  if (compDate === 'date') {
    zdt1 = zdt1.toLocalDate();
    zdt2 = zdt2.toLocalDate();
  } else if (compDate === 'time') {
    zdt1 = zdt1.toLocalTime();
    zdt2 = zdt2.toLocalTime();
  }
  switch (compareOp) {
    case 'before':
      return zdt1.isBefore(zdt2);
    case 'equal':
      return zdt1.equals(zdt2);
    case 'after':
      return zdt1.isAfter(zdt2);
    case 'beforeEqual':
      return zdt1.isBefore(zdt2) || zdt1.equals(zdt2);
    case 'afterEqual':
      return zdt1.isAfter(zdt2) || zdt1.equals(zdt2);
  }
}


BetwHours = ((time.ZonedDateTime.now()).isBetweenTimes((time.toZDT('16:00:00')), (time.toZDT('20:30:00'))));

I am no Guru, but it still looks to me like the relevant part is missing.

From by experience you would be more likely to get a solution if you post the full script and blockly rule.

Hereby the complete script,

var SunPhase, BetwHours;

// Nashorn
function zdtCompare(zdt1, zdt2, compareOp, precision, compDate) {
  switch (precision) {
    case 'years':
     zdt2 = zdt2.withMonth(zdt1.getMonthValue());
    case 'months':
     zdt2 = zdt2.withDayOfMonth(zdt1.getDayOfMonth());
    case 'days':
     zdt2 = zdt2.withHour(zdt1.getHour());
    case 'hours':
     zdt2 = zdt2.withMinute(zdt1.getMinute());
    case 'minutes':
     zdt2 = zdt2.withSecond(zdt1.getSecond());
    case 'seconds':
     zdt2 = zdt2.withNano(zdt1.getNano());
  }
  if (compDate === 'date') {
    zdt1 = zdt1.toLocalDate();
    zdt2 = zdt2.toLocalDate();
  } else if (compDate === 'time') {
    zdt1 = zdt1.toLocalTime();
    zdt2 = zdt2.toLocalTime();
  }
  switch (compareOp) {
    case 'before':
      return zdt1.isBefore(zdt2);
    case 'equal':
      return zdt1.equals(zdt2);
    case 'after':
      return zdt1.isAfter(zdt2);
    case 'beforeEqual':
      return zdt1.isBefore(zdt2) || zdt1.equals(zdt2);
    case 'afterEqual':
      return zdt1.isAfter(zdt2) || zdt1.equals(zdt2);
  }
}


SunPhase = items.getItem('LocalSun_SunPhaseName').state;
actions.NotificationAction.sendBroadcastNotification('Beweging keuken', 'warn', 'high');
actions.NotificationAction.sendBroadcastNotification(SunPhase, 'warn', 'high');
console.warn(SunPhase);
BetwHours = ((time.ZonedDateTime.now()).isBetweenTimes((time.toZDT('16:00:00')), (time.toZDT('20:30:00'))));
actions.NotificationAction.sendBroadcastNotification(BetwHours, 'warn', 'high');
if ('true' == items.getItem('AqaraBewegingsSens_KelderBeweging').state && (SunPhase == 'CIVIL_DAWN' || SunPhase == 'NAUTIC_DAWN' || SunPhase == 'ASTRO_DAWN' || SunPhase == 'CIVIL_DUSK' || SunPhase == 'NAUTIC_DUSK' || SunPhase == 'ASTRO_DUSK' || SunPhase == 'SUN_SET' || SunPhase == 'SUN_RISE' || SunPhase == 'UNDEF') && BetwHours) {
  actions.NotificationAction.sendBroadcastNotification('3h licht', 'warn', 'high');
  items.getItem('Eilandspots').sendCommand('ON');
  if (cache.private.exists('MyTimer1') === false || cache.private.get('MyTimer1').hasTerminated()) {
    cache.private.put('MyTimer1', actions.ScriptExecution.createTimer('MyTimer1', time.ZonedDateTime.now().plusMinutes(180), function () {
      items.getItem('Eilandspots').sendCommand('OFF');
      cache.private.remove('MyTimer1');
    }));
  } else {
    // do nothing
  };
} else if ('true' == items.getItem('AqaraBewegingsSens_KelderBeweging').state && (SunPhase == 'CIVIL_DUSK' || SunPhase == 'NAUTIC_DUSK' || SunPhase == 'ASTRO_DUSK' || SunPhase == 'SUN_SET' || SunPhase == 'UNDEF') && !BetwHours) {
  console.warn(BetwHours);
  actions.NotificationAction.sendBroadcastNotification('30 min licht', 'warn', 'high');
  items.getItem('Eilandspots').sendCommand('ON');
  if (cache.private.exists('MyTimer2') === false || cache.private.get('MyTimer2').hasTerminated()) {
    cache.private.put('MyTimer2', actions.ScriptExecution.createTimer('MyTimer2', time.ZonedDateTime.now().plusMinutes(20), function () {
      items.getItem('Eilandspots').sendCommand('OFF');
      cache.private.remove('MyTimer2');
    }));
  } else {
    cache.private.get('MyTimer2').reschedule(time.ZonedDateTime.now().plusMinutes(20));
  };
}

Regards Dirk

The problem is this line. Your BetwHours variable is boolean (true/false). This is not a string of “true” or “false” but a single bit indicating a true state or a false state. The sendBroadcastNotification function expects only strings as its inputs. It’s possible that in previous versions there was less rigorous checking of the parameter types or better automatic conversion, but now you have to do the conversion yourself.

I suggest that you use the logic block image. Your test is the boolean value of BetwHours and the true and false values are informative strings. Something like this:
image

Thanks Justin for your reply.
I removed the log messages and notifications to be sure that they are not the reason why the rule doesn’t run. Unfortunately I still have errors while running the rule. Some function called is in Graal unknown. Do you have any idea whats wrong here?

2023-08-07 23:07:39.757 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '24f597c4ff' failed: org.graalvm.polyglot.PolyglotException: TypeError: date1.getSecond is not a function

var SunPhase, BetwHours;

// Nashorn
function zdtCompare(zdt1, zdt2, compareOp, precision, compDate) {
  switch (precision) {
    case 'years':
     zdt2 = zdt2.withMonth(zdt1.getMonthValue());
    case 'months':
     zdt2 = zdt2.withDayOfMonth(zdt1.getDayOfMonth());
    case 'days':
     zdt2 = zdt2.withHour(zdt1.getHour());
    case 'hours':
     zdt2 = zdt2.withMinute(zdt1.getMinute());
    case 'minutes':
     zdt2 = zdt2.withSecond(zdt1.getSecond());
    case 'seconds':
     zdt2 = zdt2.withNano(zdt1.getNano());
  }
  if (compDate === 'date') {
    zdt1 = zdt1.toLocalDate();
    zdt2 = zdt2.toLocalDate();
  } else if (compDate === 'time') {
    zdt1 = zdt1.toLocalTime();
    zdt2 = zdt2.toLocalTime();
  }
  switch (compareOp) {
    case 'before':
      return zdt1.isBefore(zdt2);
    case 'equal':
      return zdt1.equals(zdt2);
    case 'after':
      return zdt1.isAfter(zdt2);
    case 'beforeEqual':
      return zdt1.isBefore(zdt2) || zdt1.equals(zdt2);
    case 'afterEqual':
      return zdt1.isAfter(zdt2) || zdt1.equals(zdt2);
  }
}


SunPhase = items.getItem('LocalSun_SunPhaseName').state;
actions.NotificationAction.sendBroadcastNotification('Beweging keuken', 'warn', 'high');
actions.NotificationAction.sendBroadcastNotification(SunPhase, 'warn', 'high');
console.warn(SunPhase);
BetwHours = ((time.ZonedDateTime.now()).isBetweenTimes((time.toZDT('16:00:00')), (time.toZDT('20:30:00'))));
if ('true' == items.getItem('AqaraBewegingsSens_KelderBeweging').state && (SunPhase == 'CIVIL_DAWN' || SunPhase == 'NAUTIC_DAWN' || SunPhase == 'ASTRO_DAWN' || SunPhase == 'CIVIL_DUSK' || SunPhase == 'NAUTIC_DUSK' || SunPhase == 'ASTRO_DUSK' || SunPhase == 'SUN_SET' || SunPhase == 'SUN_RISE' || SunPhase == 'UNDEF') && BetwHours) {
  actions.NotificationAction.sendBroadcastNotification('3h licht', 'warn', 'high');
  items.getItem('Eilandspots').sendCommand('ON');
  if (cache.private.exists('MyTimer1') === false || cache.private.get('MyTimer1').hasTerminated()) {
    cache.private.put('MyTimer1', actions.ScriptExecution.createTimer('MyTimer1', time.ZonedDateTime.now().plusMinutes(180), function () {
      items.getItem('Eilandspots').sendCommand('OFF');
      cache.private.remove('MyTimer1');
    }));
  } else {
    // do nothing
  };
} else if ('true' == items.getItem('AqaraBewegingsSens_KelderBeweging').state && (SunPhase == 'CIVIL_DUSK' || SunPhase == 'NAUTIC_DUSK' || SunPhase == 'ASTRO_DUSK' || SunPhase == 'SUN_SET' || SunPhase == 'UNDEF') && !BetwHours) {
  actions.NotificationAction.sendBroadcastNotification('30 min licht', 'warn', 'high');
  items.getItem('Eilandspots').sendCommand('ON');
  if (cache.private.exists('MyTimer2') === false || cache.private.get('MyTimer2').hasTerminated()) {
    cache.private.put('MyTimer2', actions.ScriptExecution.createTimer('MyTimer2', time.ZonedDateTime.now().plusMinutes(20), function () {
      items.getItem('Eilandspots').sendCommand('OFF');
      cache.private.remove('MyTimer2');
    }));
  } else {
    cache.private.get('MyTimer2').reschedule(time.ZonedDateTime.now().plusMinutes(20));
  };
}

This error is, as you suggested above, related to the fact that you still have some Nashorn code left over from the OH3 version of the rule. One of the major differences in js versions is the time library used. The time library for the newer JS version extracts date and time values from a datetime variable using calls that do NOT have the get prefix. So, if you see datetime.getSecond() in your script then the conversion to the new JS of OH4 has not been completed.

Most of the conversion should have happened automatically when you opened an old version Blockly rule and saved it again. However, in this case it looks like the problem is that there’s complete change in the block for testing the time. If you look in the date time block group you will see that


looks very different than the block your code still uses to create the BetwHours variable.

Replace the old datetime test block with this new version and see if that replaces the //Nashorn section of code in your rule with a // graalVM section where the call to .getSecond() has been replaced with .second().

Hi Justin,

I recreated the rule now everything works. Thanks for your contribution to find the solution.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.