rule "doorOpened"
when
Item contactDoor changed from CLOSED to OPEN
then
var timeX = new DateTimeType(now.toString)
lastDoorOpen.sendCommand(timeX)
doorTimer.sendCommand(ON)
end
rule "motioninhouse"
when
Item sensorMotion changed from OFF to ON
then
var timeY = new DateTimeType(now.toString)
lastMotion.sendCommand(timeY)
end
rule "doorTimerExpired"
when
Item doorTimer changed from ON to OFF
then
var Number epoc1 = (lastDoorOpen.state as DateTimeType).calendar.timeInMillis
var Number epoc2 = (lastMotion.state as DateTimeType).calendar.timeInMillis
if (epoc1 < epoc2){
andyIsHome.sendCommand(ON)
}
if (epoc1 > epoc2){
andyIsHome.sendCommand(OFF)
}
end
OK… this works but I feel like there should be a more elegant way to do this.
When the rules file loads, it also throws a warning about .calendar.timeInMillis being depreciated (I understand why and don’t care, it works) but loads the file anyhow
Warnings are just that, warnings. The Rule will still work.
However, a deprecation warning means that while it may work today, there may be some point in the future when it won’t work because that method or data member will be removed.
namraccr points to the more elegant way to do what you are after.
To get the epoch without the warning you would use:
(MyDateTimeItem.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
ok, because learning by trying causes problems in openHAB (repeated file loads et.) let us walk thru this
orig rule
rule "doorTimerExpired"
when
Item doorTimer changed from ON to OFF
then
var Number epoc1 = (lastDoorOpen.state as DateTimeType).calendar.timeInMillis
var Number epoc2 = (lastMotion.state as DateTimeType).calendar.timeInMillis
if (epoc1 < epoc2){
andyIsHome.sendCommand(ON)
}
if (epoc1 > epoc2){
andyIsHome.sendCommand(OFF)
}
end
new version from Rich’s doc
longer but doesn’t throw deprecation warning (untested)
var Number epoc1 = (lastDoorOpen.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
var Number epoc2 = (lastMotion.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
The cool thing here is we can use simple math operations to compare times. Time is expressed in milliseconds since epoch (1st Jan 1970). So if an event occurred earlier in time, the number will be lower. If the number is greater, the event occurred later (after) in time. hence:
if (epoc1 < epoc2){
andyIsHome.sendCommand(ON)
}
if (epoc1 > epoc2){
andyIsHome.sendCommand(OFF)
}
on to the next method.
I’m guessing (sorry openHAB dumb) this is only going to work with joda time so I must covert TimeDate type to joda time type. Link to Rich’s older (8/17) but still awesome type conversion thread points us to joda time conversion methods.
// Convert DateTimeType to Joda DateTime
val joda = new DateTime((MyDateTimeItem.state as DateTimeType).calendar.timeInMillis)
hmm… smells like millis with depreciated calender warning (untested)
newer and even more awesome time conversion thread by @anfaengerfound here suggest 2 methods
val MyJodaFromDateTimeType_VariantA = new DateTime((MyDateTimeItem.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
hmmm… uses zonedDateTime (avoids warning) but still smells like millis
second method
so then I’m hoping this will work
var Number epoc1 = new DateTime(lastDoorOpen.state.toString)
var Number epoc2 = new DateTime(lastMotion.state.toString)
then
if (epoc1.isBefore(epoc2)){
andyIsHome.sendCommand(ON)
}
if (epoc1.isAfter(epoc2)){
andyIsHome.sendCommand(OFF)
}
will work?
edit: additional question… is the
var Number
needed… or even correct, is it a joda time not a number?
how about
var epoc1 = new DateTime(lastDoorOpen.state.toString)
var epoc2 = new DateTime(lastMotion.state.toString)
val MyJodaFromDateTimeType_VariantB = new DateTime(MyDateTimeItem.state.toString)
I think, your code could also look like this
rule "doorOpened"
when
Item contactDoor changed from CLOSED to OPEN
then
lastDoorOpen.postUpdate(new DateTimeType)
doorTimer.sendCommand(ON)
end
rule "motioninhouse"
when
Item sensorMotion changed from OFF to ON
then
lastMotion.postUpdate(new DateTimeType)
end
rule "doorTimerExpired"
when
Item doorTimer changed from ON to OFF
then
val JodaLastDoorOpen = new DateTime(lastDoorOpen.state.toString)
val JodaLastMotion = new DateTime(lastMotion.state.toString)
if ( JodaLastDoorOpen.isBefore(JodaLastMotion) ) {
andyIsHome.sendCommand(ON)
}
if ( JodaLastDoorOpen.isAfter(JodaLastMotion) ) {
andyIsHome.sendCommand(OFF)
}
end
The repeated file loads should not stop you from learning by trying.
That will work except you need to remove the Number.
Joda DateTime is not a Number. It’s a very complicated class that encapsulates most anything one would want to do with date times. Epoch, on-the-other-hand, is a Number because all it is is the number of milliseconds since midnight Jan 1 1970.