[SOLVED] Persistence: Request state to specific point in time (DateTime item)

All,

I would like to request a state from my mariaDB at a certain time. In this case CarTripStart is a DateTime item:

val Number distDNAStart = CarDistDNA.historicState(CarTripStart.state)

but I get:

2018-07-06 12:05:56.167 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Received car trip data': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.persistence.extensions.PersistenceExtensions.historicState(org.eclipse.smarthome.core.items.Item,org.joda.time.base.AbstractInstant) on instance: null

But neither CarDistDNA is null nor CarTripStart is null

Any suggestion is greatly appreciated.

What item-types are CarDistDNA and CarTripStart?
What value has CarTripStart?

CarDistDNA is a Number item (between 0 and a few thousand)
CarTripStart is a DateTime item (e.g. 2018-07-06 15:37:00.000)

Have you checked, that are values stored in the DB?
CarTripStart.state is not a valid format for historicState().

Yes, I just copied them from my DB.

Have you tried this?

val Number distDNAStart = CarDistDNA.historicState(CarTripStart.state.toDateTime())

Not yet.
Thanks a lot.
I will give it a try!

Is the double bracket a typo or on purpose?

Does not work :frowning:
2018-07-07 08:21:23.829 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule ‘Received car trip data’: ‘toDateTime’ is not a member of ‘org.eclipse.smarthome.core.library.types.DateTimeType’; line 67, column 54, length 31

Ok that was worth a try.
The master of datetime @rlkoshak can help, maybe?

Oh, not Rich again :wink:
I am already feeling guilty to keep him so busy…
:wink:

toDateTime is a method on Joda DateTime objects but not on DateTimeType objects. You need to convert the DateTimeType to a Joda DateTimeType.

I’m usually going in the other direction, but I think this will work:

val Number distDNAStart = CarDistDNA.historicState(new DateTime(CarTripStart.state.toString))

Thanks again Rich. I will try

One question though:
So this would check the value CarDistDNA (Number) at CarTripStart (DateTime) timestamp in my DB?

I don’t get

Why do I need to use a DateTime item as a String and created a new DateTime item out of it?

Joda DateTime is the type of object that is required by calls to get historic states and when creating a Timer. The implicit variable now is a Joda DateTime.

A DateTime Item carries it’s state as a DateTimeType. DateTimeType is not a Joda DateTime object and therefore cannot be used in places that require a Joda DateTime. So you must first convert the DateTimeType to a Joda DateTime. There are lots of ways to do this but I find the easiest is to use the toString from the DateTimeType to create a new DateTime, as illustrated above.

2 Likes

Got it.
Thanks for the explanation.
I use now quite a bit like
now.isAfter(now.withTimeAtStartOfDay.plusHours(8))
or
if(!System_started.changedSince(now.minusMinutes(45),"jdbc")

I always wondered what this “AbstractInstant” e.g. in the persistence documentation supposed to mean :slight_smile:
Now I have a much better clue :slight_smile:

Again, thanks for your support.

Unfortunately this does not work: :frowning:
2018-07-10 18:27:13.243 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Received car trip data': 'state' is not a member of 'org.openhab.core.persistence.internal.QueryablePersistenceServiceDelegate$1'; line 73, column 48, length 18

Try this:

val dt_carStartTime = new DateTime(CarTripStart.state.toString)
val Number distDNAStart = CarDistDNA.historicState(dt_carStartTime)

Thanks - I will try this today.
I finally have time to catch up with this thread again.
Damn travelling :wink:

So to summarize:To get the historic state from my DB I need an AbstractInstant (JodaTime type).
Your suggestion to get this JodaTime is:

val dt_carStartTime = new DateTime(CarTripStart.state.toString)

Question (to better understand):
In another thread I got help to convert a string to a “real” DateTimeItem:

// get string
val String time = transform("JSONPATH", "$.trips[0].tripDetails[0].startTime", json)
// get JodaTime from String
var DateTime JDT_time = parse(time.toString)
// convert Joda to DateTimeType
var DateTimeType DTT_time = new DateTimeType(JDT_time.toString)

So, DateTime in rules is always Joda and DateTimeType is always “real” DateTime?
If that’s true it’s really confusing for me is that DateTime in rules is not the same format like DateTime item and DateTime items are DateTimeType in rules.

Or did I mess it up completely now?

There is no “real” date time time except epoch. Epoch if the number of milliseconds since 1970-01-01T00:00:00Z.

Joda DateTime is a class that provides a lot of useful helper methods for comparing then together, getting parts of the date (e.g. day off the month), etc.

All OH Items carry a State. Joda DateTime is not a State. So OH has the DateTimeType which is a State but it is not a Joda DateTime. And DateTimeType doesn’t have all the nice comparison and date manipulation helper methods on it. So I’m order to get the nice helper methods or to use a DateTimeType to schedule Timers, it must first be converted to a Joda DateTime.

In your example code, I might be possible to just use:

var DateTimeType DTT_time = new DateTimeType(time)

Or just

var DateTime JDT_time = new DateTime(time)

Assuming that the time String is in standard ISO 8601 (I think that’s the number) format.

Just on similar notes, here is how you can get epoch millis from ESH DateTimeType

Number time = dateTimeESH.getZonedDateTime().toInstant().toEpochMilli();

Once you get hold of epoch millis, you can create other date types using their epoch millis based constructors.

To convert back from epoch millis

ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
DateTimeType dateTimeESH2 = new DateTimeType(zdt);

ESH DateTimeType recently got upgraded to use ZonedDateTime, maybe thats why old rule examples may not work.