DateTimeItem could not be cast to DateTimeType

Hey there,

I receive a mqtt topic and parse / transform it via jsonpathmap.
As result I get a timestamp-value:

2022-11-06T18:09:53+01:00

The item looks like this:

I want to calculate the diff-time from this timestamp with the following part of a script:

var lastChangeMilli = (Stromzahler_ZahlerstandTimestamp as DateTimeType).zonedDateTime.toInstant.toEpochMilli
  
//  var elapsedTime = now.millis - lastChangeMilli

  logInfo("kWhPower", "now.millis: " + now.millis + " lastChangeMilli: " + lastChangeMilli)

But this throws the following error:

Cannot cast from DateTimeItem to DateTimeType

and

The method or field millis is undefined for the type ZonedDateTime;

Could you give me a hint, what I am doing wrong? I am just new to the scripting stuff… ;-(

You need to cast the state of the item, not the item itself.

Hi @J-N-K

Perhaps I am just to new to this stuff - could you please explain a bit further what you mean?
if I understand you right, xxx.state is the item and not the state of the item?

EDIT: ahhh, got you. Will try it later this evening. Thank you!

No, exactly the other way round. You use Stromzahler_ZahlerstandTimestamp which is the item (the class is DateTimeItem) and try to cast it to DateTimeType. This is not possible. Stromzahler_ZahlerstandTimestamp.state is the state of the item and can be cast to DateTimeType.

Hey @J-N-K

Thank you - problem 1 is solved :+1:

Could you give me a hint for problem 2, too?

Did you try now.toInstant.toEpochMilli like you do for the other one. You could also try using the ZonedDateTime directly (instead of .toInstant.toEpochMilli) and use elapsedTime = Duration.MILLIS.between(now, lastChanged) (not sure if this works).

… this throws a new error :wink: …

rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested

… and this throws three errors ;-(

I tried to use your suggestion as following:

var lastChangeMilli = (Stromzahler_ZahlerstandTimestamp.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
elapsedTime = Duration.MILLIS.between(now, Stromzahler_ZahlerstandTimestamp.state)  
  logInfo("kWhPower", "elapsedTime: " + elapsedTime)

and this results in

   1. The method elapsedTime(Object) is undefined; line 35, column 1456, length 11
   2. The method or field MILLIS is undefined for the type Class<Duration>; line 35, column 1479, length 6
   3. The method or field elapsedTime is undefined; line 36, column 1581, length 11

Declares a new variable

If that is a new variable, you have failed to declare it.

.ofMillis looks useful
https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

1 Like
var lastUpdate = (NewItem.state as DateTimeType).zonedDateTime
var elapsed = Duration.between(lastUpdate, now).toMillis
logInfo("test", "elapsed=" + elapsed)

Thank you - but it produces a new error

This code

var lastUpdate = (Stromzahler_ZahlerstandTimestamp.state as DateTimeType).zonedDateTime
var elapsed = Duration.between(lastUpdate, now).toMillis
logInfo("test", "elapsed=" + elapsed) 

leads to this

2022-11-07 08:00:39.893 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'rulAggregationenStrom' failed: rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested

Thank you for helping me :wink:

That rrd4j error is related to persistence, it’s coming from somewhere else. Time to show the whole rule.

Hi @rossko57,

here comes the actual version of the script:

//variables...
var lastChangeMilli = (Stromzahler_ZahlerstandTimestamp.state as DateTimeType).zonedDateTime
var elapsedTime = Duration.between(lastChangeMilli, now).toMillis
logInfo("test", "elapsed=" + elapsedTime) 
logInfo("test", "lastchange=" + lastChangeMilli) 
logInfo("kWhPower", "now.millis: " + now.millis + " lastChangeMilli: " + lastChangeMilli)

  // Calculate time base
 var duration = (now.millis - lastChangeMilli)
 var duration2 = Math::round(duration.floatValue())
logInfo("kWhPower", "duration in ms: " + elapsedTime)

  // Calculate energy base
var Number energyDiff = ((Stromzahler_Zahlerstand.state as DecimalType) - (Stromzahler_Zahlerstand.previousState(true) as DecimalType)) * 1000
var energyDiff2 = Math::round(energyDiff.floatValue())
logInfo("kWhPower", "energyDiff in Wh: " + energyDiff2)

 //Calculate power
 var Number powerCalc = energyDiff2 * 3600 * 1000 / elapsedTime
 postUpdate(kWhPower, powerCalc)
 postUpdate(kWhPowerDT, new DateTimeType())

I changed so much this morning that the error I reported is gone - but there are 5 new errors :wink:

   1. The method or field millis is undefined for the type ZonedDateTime; line 6, column 294, length 6
   2. The method or field millis is undefined for the type ZonedDateTime; line 9, column 390, length 6
   ==> fixed 3. The method or field power is undefined; line 18, column 816, length 5
   ==> fixed 4. The method or field kWhPower is undefined; line 20, column 898, length 8
   ==> fixed 5. The method or field kWhPowerDT is undefined; line 21, column 931, length 10

… so now I have the rdd4j Error again :wink:

//
var lastChangeMilli = (Stromzahler_ZahlerstandTimestamp.state as DateTimeType).zonedDateTime
var elapsedTime = Duration.between(lastChangeMilli, now).toMillis
logInfo("test", "elapsed=" + elapsedTime) 
logInfo("test", "lastchange=" + lastChangeMilli) 
//logInfo("kWhPower", "now.millis: " + now.millis + " lastChangeMilli: " + lastChangeMilli)

  // Calculate time base
 var duration = elapsedTime
 var duration2 = Math::round(duration.floatValue())
logInfo("kWhPower", "duration in ms: " + elapsedTime)

  // Calculate energy base
var Number energyDiff = ((Stromzahler_Zahlerstand.state as DecimalType) - (Stromzahler_Zahlerstand.previousState(true) as DecimalType)) * 1000
var energyDiff2 = Math::round(energyDiff.floatValue())
logInfo("kWhPower", "energyDiff in Wh: " + energyDiff2)

 //Calculate power
 var Number powerCalc = energyDiff2 * 3600 * 1000 / elapsedTime
 //postUpdate(kWhPower, powerCalc)
// logInfo(powerCalc)
// logInfo(new DateTimeType())
 //postUpdate(kWhPowerDT, new DateTimeType())

This seems to be the only persistence call in your current rule.

What type of Item is Stromzahler_Zahlerstand, is it being persisted?
Is rrd4j installed?

Note that returns a historic Item, with timestamp etc. So

is an error, you cannot cast a historic Item to decimal.
You’d be interested in the state, as opposed to timestamp etc.

(Stromzahler_Zahlerstand.previousState(true).state as DecimalType)

hmmm…

I simplified again:

logInfo("default.rules", "Previous-State: " + Stromzahler_Zahlerstand.previousState.toString)  
logInfo("default.rules", "Actual-State: " + Stromzahler_Zahlerstand.state.toString)

produces this:

2022-11-07 14:28:49.273 [INFO ] [nhab.core.model.script.default.rules] - Previous-State: 11/7/22, 2:28 PM: Stromzahler_Zahlerstand -> 30126.0

2022-11-07 14:28:49.276 [INFO ] [nhab.core.model.script.default.rules] - Actual-State: 30126.0

Seems the persistence runs…

But if I try to fetch the latest changed value (Stromzahler_Zahlerstand.previousState(true).state.toString)

logInfo("default.rules", "Previous-State: " + Stromzahler_Zahlerstand.previousState(true).state.toString)  

I got there rrd4j error:

rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested

So that works

and that doesn’t work.

If I recall, the (true) part just doesn’t work with rrd4j, because of the nature of the archived storage. Go without that.

Thank you - I now use InfluxDB - works without any problem :wink: