Blockly historic state average ending with type error

Hey guys,

I really struggle to get the average value of a field which is persisted and holds the power delivered to the grid.
It simple always fails with type error, see screenshot. I am not able to figure out what goes wrong here… Get “persisted state” works fine, but as soon as I switch to “historic state average” I end up with shown error.
All I want to achieve is the average value of that measurements logged to influxdb of last 5 minutes. Any idea? Thx in advance!

Blocky looks like (all except the average block works):
image

Leading to this log messages:
2024-09-04 17:25:51.520 [INFO ] [org.openhab.rule.test1 ] - -6.4
2024-09-04 17:25:51.521 [INFO ] [org.openhab.rule.test1 ] - Fronius_Symo_Inverter_Grid_Power (Type=NumberItem, State=-6.4 W, Label=Inverter Grid Power, Category=, Tags=[Measurement, Power], Groups=[Fronius_Symo_Inverter])
2024-09-04 17:25:51.521 [INFO ] [org.openhab.rule.test1 ] - Fronius_Symo_Inverter_Grid_Power
2024-09-04 17:25:51.522 [INFO ] [org.openhab.rule.test1 ] - -6.4 W
2024-09-04 17:25:51.537 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘test1’ failed: TypeError: persistence.averageSince(itemRegistry.getItem(“Fronius_Symo_Inverter_Grid_Power”), zdt.now().minusMinutes(5)).getState is not a function in at line number 61

Which version of OH are you running? There have been some changes recently with persistence so it helps to know.

Also, please show the generated code. There’s an icon at the bottom to show the JS code. Seeing what the blocks render to in JS can be helpful.

I don’t see anything immediately to indicate what might be the problem here. Seeing the full rule might show what’s going wrong (e.g. is zdt declared)?

Hey, thanks for super fast response.
Current version: openHAB 4.2.1

Generated code see:

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);

var persistence = Java.type('org.openhab.core.persistence.extensions.PersistenceExtensions');

var dtf = Java.type("java.time.format.DateTimeFormatter");

var zdt = Java.type("java.time.ZonedDateTime");

function getZonedDateTime(datetime) {
  datetime = String(datetime).replace('T', ' ')
  var regex_time_min =         /^\d{2}:\d{2}$/;
  var regex_time_sec =         /^\d{2}:\d{2}:\d{2}$/;
  var regex_date =             /^\d{4}-\d{2}-\d{2}$/;
  var regex_date_time_min =    /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
  var regex_date_time_sec =    /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
  var regex_date_time_sec_tz = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/;
  var regex_date_time_ms =     /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}$/;
  var regex_date_time_us =     /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{6}$/;
  var regex_date_time_ms_tz =  /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{2}:\d{2}$/;
  var regex_date_time_us_tz =  /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{6}[+-]\d{2}:\d{2}$/;
  var regex_oh =               /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{4}$/;
  var now = zdt.now();
  var now_year = now.getYear();
  var now_month = now.getMonthValue();
  var now_day = now.getDayOfMonth();
  var today = '' + now_year;
  today += '-' + ('0' + now_month).slice(-2);
  today += '-' + ('0' + now_day).slice(-2)+' ';
  switch (true) {
    case regex_time_min.test(datetime): return zdt.parse(today + datetime + ':00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_time_sec.test(datetime): return zdt.parse(today + datetime + '+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_date.test(datetime): return zdt.parse(datetime + ' 00:00:00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_date_time_min.test(datetime): return zdt.parse(datetime + ':00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_date_time_sec.test(datetime): return zdt.parse(datetime + '+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_date_time_sec_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
    case regex_date_time_ms.test(datetime): return zdt.parse(datetime + ' +00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSS z'));
    case regex_date_time_us.test(datetime): return zdt.parse(datetime + ' +00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSSS z'));
    case regex_date_time_ms_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSz'));
    case regex_date_time_us_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSSSSz'));
    case regex_oh.test(datetime): return zdt.parse(datetime.slice(0,26) + ':' + datetime.slice(26,28), dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSz'));
    default: return zdt.parse(datetime);
  }
}

function createZonedDateTime(year, month, day, hour, minute, second, nano, offsetString, timezoneString) {
  stringToParse = '' + year;
  stringToParse += '-' + ('0' + month).slice(-2);
  stringToParse += '-' + ('0' + day).slice(-2);
  stringToParse += 'T' + ('0' + hour).slice(-2);
  stringToParse += ':' + ('0' + minute).slice(-2);
  stringToParse += ':' + ('0' + second).slice(-2);
  stringToParse += '.' + nano + offsetString + '[' + timezoneString + ']';
  return stringToParse;
}


logger.info(parseFloat(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power').getState()));
logger.info(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power'));
logger.info(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power').getName());
logger.info(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power').getState());
logger.info((parseFloat(persistence.averageSince(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power'), zdt.now().minusMinutes(5)).getState())));

Hmmm. I’m on OH 4.3 M1 and I think there have even been some changes between 4.2.1 and 4.3 M1. I’m seeing an extra flag in the block:

The code generated has some important differences too:

items.getItem('HomeEnergyMeter_ElectricmeterkWh').persistence.averageSince(time.ZonedDateTime.now().minusHours(1))?.quantityState;

Your generated code looks odd though. Was this rule created in OH 3.x? If so have you opened and resaved the rule since upgrading to OH 4? All those Java.type stuff at the top of the code looks like the way Blockly used to work when it compiled to Nashorn JS instead of JS Scripting.

Or maybe you don’t have the JS Scripting add-on installed? If you have Nashorn installed instead Blockly will render Nashorn code.

The codegenerated for JS scripting for a similar set of blocks:

console.info(items.getItem('HomeEnergyMeter_ElectricmeterkWh').quantityState);
console.info(items.getItem('HomeEnergyMeter_ElectricmeterkWh'));
console.info(items.getItem('HomeEnergyMeter_ElectricmeterkWh').name);
console.info(items.getItem('HomeEnergyMeter_ElectricmeterkWh').state);
console.info((items.getItem('HomeEnergyMeter_ElectricmeterkWh').persistence.averageSince(time.ZonedDateTime.now().minusHours(1))?.quantityState));

Notice how much less code there is.

If you open the rule and just save it, OH will recreate the generated JS code for you. Try that and see if the code looks closer to the above. If so it should work. If not something else very weird is going on.

This is indeed still code generated for Nashorn. The extra type field is also not available for Nashorn.

Carefully read Rules Blockly | openHAB on what needs to be done to convert these to the current JS scripting addon. Most will not work properly without resaving.

1 Like

Guys thank you so much… All was fine and good after installing the j scrip addon (and removing the nashorn one)…
THANKS!

It looks a little like the code generated for Nashorn isn’t correct also. I don’t see what the problem is but there’s something wrong with that last line of code:

logger.info((parseFloat(persistence.averageSince(itemRegistry.getItem('Fronius_Symo_Inverter_Grid_Power'), zdt.now().minusMinutes(5)).getState())));

Does an issue need to be filed?

Yes, would be good not to forget looking into it. Although I am seriously asking myself if we should not retire support for Blockly Nashorn generated code in 4.3 completely and require the JS Scripting addon. We start having too much that only works with GraalJS.

I thought we already did in 4.0. I was surprised when you told me Nashorn was still supported.

I/We kept the Nashorn support for everything that already existed and where it would be straight forward and easy to support it. In some cases you will even see an error popping up telling you that it is not supported.

In particular with all the new persistence functionality that was added much later and the complexity with that block already, I wouldn’t fix that for Nashorn anymore.

However, there is no intent (at least from my side) to further support any new functionality (and I didn’t). So, @Mherwege, I am open for the next major release to completely drop Nashorn support.

(cc @florian-h05 )

We kept Nashorn for 4.0 because we wanted to be on the safe side — if something does not work with JS Scripting, one could go back to Nashorn.
I think meanwhile both JS Scripting and Blockly on JS Scripting have been proven to be reliable, so from I’m fine with dropping Blockly for Nashorn with 4.3. This will definitely reduce the amount of Blockly code needed :slight_smile:

The only advantage Nashorn HAD IMO was its faster „compilation“ times on 32-bit, but with [rules] Add support for pre-compilation of conditions and actions by florian-h05 · Pull Request #4289 · openhab/openhab-core · GitHub this advantage is gone/the slower compilation times of JS Scripting are mitigated.

1 Like

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