import org.joda.time.DateTime
rule "Test"
when
Time cron "0 */1 * * * ?"
then
var DateTime dt1 = now
var DateTime dt2 = Weather_LastUpdate.state // any DateTime item
logInfo("Test", ""+dt1)
logInfo("Test", ""+dt2)
end
As you may notice the timezone notation is different.
I have found that comparing these with (dt1 == dt2) will NEVER return true. Although they are equal, I guess.
Is this a bug or should I use some additional statement?
In the rule above, now is a org.joda.time.DateTime, but Weather_LastUpdate.state is an openHAB/ESH DateTimeType. That’s why they print differently and why they will never be equal. Time comparisons when using classes of different sources is complicated unfortunately, but there are many examples of successful approaches.
Once ESH is using Java 8 as a minimum version, effort can be made to harmonize the situation and obsolete org.joda.time.
This used to work in OH1. This is the use case. My gas meter sends a reading every hour at the full hour. I capture this with the DSMR binding.
Once a day, at midnight, I publish the reading to www.mindergas.nl.
A rule compares the gas meter time stamp (00:00) with the current time converted to start of day. If true it is published.
This code has been working flawlessly for about a year with OH1 and doesn’t in OH2:
/* utilities.rules */
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
rule Gas_Midnight
when
Item P1_Gas_Timestamp changed
then
logDebug("gas.midnight", "Gas Timestamp changed")
var dt = parse(P1_Gas_Timestamp.state.toString)
if (dt == now.toLocalDate.toDateTimeAtStartOfDay) {
logDebug("gas.midnight", "Received gas meter reading for midnight.")
callScript("mindergas")
} else {
logDebug("gas.midnight", "Received gas meter reading during the day.")
}
end
Still no change in results. I have applied the suggestion from @rlkoshak to use equals and will see what happened tomorrow morning (I will be asleep at midnight ).
/* mindergas.rules */
import org.joda.time.DateTime
/*
* De slimme meter geeft 1x per uur een nieuwe stand van de gasmeter door.
* Een paar minuten na het hele uur ontvang je de stand per het hele uur.
* Publiceer deze stand naar mindergas als de stand eind vorige dag.
*/
rule GasMeterChanged
when
// Time cron "*/10 * * * * ?" or
Item P1_Gas_Timestamp changed
then
logInfo("GasMeterChanged", "Gas meter reading changed")
var DateTime dtRun = parse(P1_Gas_Timestamp.state.toString)
var DateTime dtSOD = now.toLocalDate.toDateTimeAtStartOfDay
logInfo("GasMeterChanged", "Timestamp : " + dtRun)
logInfo("GasMeterChanged", "Start of day: " + dtSOD)
if (dtRun.equals(dtSOD)) {
logInfo("GasMeterChanged", "Gas meter reading changed at midnight.")
callScript("mindergas")
} else {
logInfo("GasMeterChanged", "Gas meter reading changed during the day.")
}
end
Logging:
2017-01-24 23:05:32.165 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-24 23:05:32.184 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp : 2017-01-24T23:00:00.000+01:00
2017-01-24 23:05:32.192 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-24T00:00:00.000+01:00
2017-01-24 23:05:32.200 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
...
2017-01-25 00:05:28.544 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-25 00:05:28.563 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp : 2017-01-25T00:00:00.000+01:00
2017-01-25 00:05:28.571 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-25T00:00:00.000+01:00
2017-01-25 00:05:28.580 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
...
2017-01-25 01:05:26.830 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-25 01:05:26.847 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp : 2017-01-25T01:00:00.000+01:00
2017-01-25 01:05:26.856 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-25T00:00:00.000+01:00
2017-01-25 01:05:26.862 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
Added these lines to the rule for further debugging:
To check a time is equal to, greater than, less than or within a range I use string comparisons, it is so much simpler.
In a datetime string, the time is located at positions 11-15 (10:45), in an Item declared as a string, it is located at positions 0-4. A range example would be:
var hw1on = Hot_Water_1_On.state.toString // time at position 0-4 (String Item set to "07:00" in startup rule)
var hw1off = Hot_Water_1_Off.state.toString
var time1 = CurrentTime.state.toString // time at position 11-15
if ( time1.substring(11,16) >= hw1on.substring(0,5) && time1.substring(11,16) <= hw1off.substring(0,5)){
WITHIN TIMEBAND
}
or
var time1 = CurrentTime.state.toString // time at position 11-15
if (time1.substring(11,16) >= "07:00" && time1.substring(11,16) <= "09:30"){
WITHIN TIMEBAND
}
You example where you need to check the time is “00:00” would be:
rule Gas_Midnight
when
Item P1_Gas_Timestamp changed
then
logDebug("gas.midnight", "Gas Timestamp changed")
var dt = P1_Gas_Timestamp.state.toString
if (dt.substring(11,16)=="00:00") {
logDebug("gas.midnight", "Received gas meter reading for midnight.")
callScript("mindergas")
} else {
logDebug("gas.midnight", "Received gas meter reading during the day.")
}
end
It also has the advantage that you can change the time to say “18:00” to test the rule rather than wait until midnight.
Thanks for your suggestion. I will try this if everything else fails. If so, I would use the whole string e.g. (dtRun.toString == dtSOD.toString) and not just the time part.
This is what happened last night with my additional tests:
Last night the rule triggered the script. So the isEqual is working. I will simplify the rule code and post a working example for later reference by the community.