Display/Convert Epoch as DateTime

I’m trying to add PlantLink support into OpenHAB via their API, and need to display epoch time as a DateTime string. Currently the item gets populated (via the HTTP binding & JSONPATH) as: 1466886884
I’d like to either display it as DateTime, or use a rule to convert it to a DateTime string, then display it via another item. Either option would work.

Thanks in advance.

Create a Number Item which gets populated with the epoch.

Create another DateTime Item which will get the displayable version.

rule "Parse DateTime"
when
    Number Epoch changed
then
    ReadableDate.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Epoch.state as DecimalType).longValue)
end

Thanks for the rule @rlkoshak
I’ve created an item which receives the epoch number, and another item which will display it. I’ve also created rules for the conversion. But it’s not working right as of yet. Also, looking at the rule above, it looks like there’s 2 missing “)”'s

Here’s what I’ve got so far, is this correct?

rule Plant0 epoch
when
    Number Plant0_Updated_Raw changed
then
    Plant0_Updated.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Epoch.state as DecimalType).longValue)))
end

Thanks again for the help.

I just typed in the above, there is bound to be errors.

Are you seeing errors in the log?

Are you using Designer? It will point out syntax errors.

Make sure you have the right imports.

You need to get the value from Plant0_Updated_Raw.

Plant0_Updated.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Plant0_Updated_Raw.state as DecimalType).longValue)))

@rlkoshak I’m not seeing any errors in the log files. Also I’m using vi, but with the openhab syntax highlighting. The rule seems to look ok to me. Do you know what imports I should be using? I’m assuming DecimalType, would I also need an import for Time?

Here’s the rule currently:

rule Plant0 epoch
when
    Number Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Updating Epoch Time")
    Plant0_Updated.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Plant0_Updated_Raw.state as DecimalType).longValue)))
end

I’ll open it up in designer and make sure it looks ok.

Vi does syntax highlighting but not syntax checking. Designer does a lot more thorough checking. For example, if you hve a typo in an Item name, vi will happly let it stand but Designer will point out the error.

You do need to import the following:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType

Thanks, I’ve used the Designer quite a bit.

So I’ve added the imports you listed, but the rule hasn’t triggered yet (it’s been a few hours). Here’s the rule, with imports:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType
rule "Plant0 epoch"
when
    Number Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Updating Epoch Time")
    Plant0_Updated.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Plant0_Updated_Raw.state as DecimalType).longValue)))
end

I’m wondering, shouldn’t Number (above) be Item instead?

Indeed it should be Item. I’m surprised it didn’t throw an error in the log or designer like that.

Alright, I’ve changed the Number to Item, in the rule. It’s not working but I am getting an error this time. Here’s the rule:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType

rule "Plant0 epoch"
when
    Item Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Updating Epoch Time")
    Plant0_Updated.sendCommand(new DateTimeType(Calendar::getInstance.setTimeMillis((Plant0_Updated_Raw.state as DecimalType).longValue)))
end

And the error:

2016-07-13 18:12:14.885 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'plant_epoch_conv.rules'
2016-07-13 18:16:01.953 [INFO ] [openhab.model.script.Plantlink] - Plant0: Updating Epoch Time
2016-07-13 18:16:02.184 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Plant0 epoch'
java.lang.NullPointerException: null
	at org.eclipse.xtext.common.types.util.JavaReflectAccess.getRawType(JavaReflectAccess.java:107) ~[na:na]
	at org.eclipse.xtext.common.types.util.JavaReflectAccess.getConstructor(JavaReflectAccess.java:90) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateConstructorCall(XbaseInterpreter.java:511) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor501.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:751) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._featureCallOperation(XbaseInterpreter.java:712) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor478.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.openhab.model.script.interpreter.ScriptInterpreter.internalFeatureCallDispatch(ScriptInterpreter.java:69) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateMemberFeatureCall(XbaseInterpreter.java:549) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor483.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._evaluateBlockExpression(XbaseInterpreter.java:321) ~[na:na]
	at sun.reflect.GeneratedMethodAccessor482.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
	at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
	at org.eclipse.xtext.util.PolymorphicDispatcher.invoke(PolymorphicDispatcher.java:291) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:218) ~[na:na]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:204) ~[na:na]
	at org.openhab.model.script.internal.engine.ScriptImpl.execute(ScriptImpl.java:59) ~[na:na]
	at org.openhab.core.scriptengine.ScriptExecutionThread.run(ScriptExecutionThread.java:44) ~[na:na]

Any idea? Thanks again for the help.

When the Rules DSL is unable to convert something into a valid state it throws a NullPointerException. I wish they had created a separate and more descriptive exception for this case because NullPointer is misleading.

I think it doesn’t like the longValue. I suspect it can’t handle the raw DateTimeType and it needs a String. Or one of the other conversions isn’t working.

Try (the line is getting long so I’ll break it up some):

val Number epoch = Plant0_Updated_Raw.state as DecimalType // Note, DecimalType is a Number
val Calendar cal = Calendar::getInstance.setTimeMillis(epoch.longValue)
val DateTimeType dtt = new DateTimeType(cal)
Plant0_Updated.sendCommand(dtt.toString)

If it still doesn’t work, intersperse each of the above lines with logInfo statements so you can see which specific line it fails on.

I would have to agree, I wish it wasn’t so deceptive, makes issues like these hard to troubleshoot.

I’ve updated the rule as above, but added in some logInfo statements to help determine where the problem is. Here’s the rule:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType

rule "Plant0 epoch"
when
    Item Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Epoch Convert Start")
    logInfo("Plantlink", "Plant0: Step 1")
    val Number epoch = Plant0_Updated_Raw.state as DecimalType
    logInfo("Plantlink", "Plant0: Step 2")
    val Calendar cal = Calendar::getInstance.setTimeMillis(epoch.longValue)
    logInfo("Plantlink", "Plant0: Step 3")
    val DateTimeType dtt = new DateTimeType(cal)
    logInfo("Plantlink", "Plant0: Sending update to Plant0_Updated")
    Plant0_Updated.sendCommand(dtt.toString)
end

and the error:

2016-07-14 10:46:53.496 [INFO ] [openhab.model.script.Plantlink] - Plant0: Epoch Convert Start
2016-07-14 10:46:53.614 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 1
2016-07-14 10:46:53.865 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 2
2016-07-14 10:46:54.014 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Plant0 epoch': The name '<XFeatureCallImplCustom>.setTimeMillis(<XMemberFeatureCallImplCustom>)' cannot be resolved to an item or type.

Looks like you were right, it doesn’t like the longValue (line).

DOH!

I totally messed up the Calendar line.

val Calendar cal = Calendar::getInstance
cal.setTimeMillis(epoch.longValue)

setTimeMillis doesn’t return anything so I can’t do it all on one line like that.

No worries, but I am still getting the same error.
Here’s the rule:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType

rule "Plant0 epoch"
when
    Item Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Epoch Convert Start")
    logInfo("Plantlink", "Plant0: Step 1")
    val Number epoch = Plant0_Updated_Raw.state as DecimalType
    logInfo("Plantlink", "Plant0: Step 2")
    val Calendar cal = Calendar::getInstance
    logInfo("Plantlink", "Plant0: Step 3")
    cal.setTimeMillis(epoch.longValue)
    logInfo("Plantlink", "Plant0: Step 4")
    val DateTimeType dtt = new DateTimeType(cal)
    logInfo("Plantlink", "Plant0: Sending update to Plant0_Updated")
    Plant0_Updated.sendCommand(dtt.toString)
end

and the error:

2016-07-14 13:17:03.964 [INFO ] [openhab.model.script.Plantlink] - Plant0: Epoch Convert Start
2016-07-14 13:17:03.967 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 1
2016-07-14 13:17:03.978 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 2
2016-07-14 13:17:03.985 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 3
2016-07-14 13:17:04.033 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Plant0 epoch': The name '<XFeatureCallImplCustom>.setTimeMillis(<XMemberFeatureCallImplCustom>)' cannot be resolved to an item or type.

Thanks.

Its setTimeInMillis. Missing the In.

In Designer, this sort of error should have been highlighted in red. And if one types cal.<ctrl><space> it will bring up a list of valid completions, one of which would be setTimeInMillis.

I can’t always do this, about 80% of my replies are from my phone. Lots of errors like this get past me as a result.

So I fixed the ‘In’ in the statement, didn’t help much. I also tried adding in 2 more imports, and got a different result. Here’s the rule:

import java.util.Calendar
import org.openhab.core.library.types.DecimalType
import org.joda.time.*
import org.openhab.core.library.types.*

rule "Plant0 epoch"
when
    Item Plant0_Updated_Raw changed
then
    logInfo("Plantlink", "Plant0: Epoch Convert Start")
    logInfo("Plantlink", "Plant0: Step 1")
    val Number epoch = Plant0_Updated_Raw.state as DecimalType
    logInfo("Plantlink", "Plant0: Step 2")
    val Calendar cal = Calendar::getInstance
    logInfo("Plantlink", "Plant0: Step 3")
    cal.setTimeInMillis(epoch.longValue)
    logInfo("Plantlink", "Plant0: Step 4")
    val DateTimeType dtt = new DateTimeType(cal)
    logInfo("Plantlink", "Plant0: Sending update to Plant0_Updated")
    Plant0_Updated.sendCommand(dtt.toString)
end

Not really sure if I need them or not, but here was a log of the output:

2016-07-14 17:47:12.950 [INFO ] [openhab.model.script.Plantlink] - Plant0: Epoch Convert Start
2016-07-14 17:47:13.068 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 1
2016-07-14 17:47:13.364 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 2
2016-07-14 17:47:13.663 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 3
2016-07-14 17:47:14.074 [INFO ] [openhab.model.script.Plantlink] - Plant0: Step 4
2016-07-14 17:47:14.299 [INFO ] [openhab.model.script.Plantlink] - Plant0: Sending update to Plant0_Updated
2016-07-14 17:47:14.555 [WARN ] [.c.i.events.EventPublisherImpl] - given command is NULL, couldn't send command to 'Plant0_Updated'

It’s still not successful, but at least it isn’t spewing java errors… Ideas?

Log out dtt.toString. I think this error is that it can’t convert that to a format Plant0_Updated understands. It doesn’t make sense but that is what the error implies.

Try this:

String Plant0_Updated "Plant Updated [%s]" (Plant0)
Number Plant0_Updated_Raw "[%d]" { http="<[http://dashboard.myplantlink.com/api/v1/plants/XXXX{authorization=Basic XXX=}:1800000:JSONPATH($..last_measurements.updated[0])]" }
import java.util.Calendar
import org.openhab.core.library.types.DecimalType
import org.joda.time.*
import org.openhab.core.library.types.*

rule "Plant0 epoch"
when
	System started or
    Item Plant0_Updated_Raw changed
then
	var String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new java.util.Date(((Plant0_Updated_Raw.state as DecimalType) * 1000).longValue))
	Plant0_Updated.postUpdate(date)
end
1 Like