Hi Everyone,
hopefully this is the right way to post a FR. If not, please feel free to point me to the right direction.
Currently, i’ve build a rule which controls a switch item that simply tells me that it is between set and rise:
I Use this rule f.e. to open a rollershutter if that window is opened and this switch is set.
Or, if there is any other simpler way, drop a line how you get this done.
rule "Time between Set and Rise"
when
Time cron "0 */5 16-9 * * ?" or
Item DEBUGSwitch received command ON
then
if (DEBUGSwitch.state == ON) {
logInfo("Rule Start","Time between Set and Rise")
}
var SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
var String SunRiseString = LocalSun_Rise_EndTime.state.toString()
var String SRStr = SunRiseString.replace("T", " ")
var Date SunRiseSDF = sdf.parse(SRStr)
var String SRStrFmt = sdf.format(SunRiseSDF)
var Date SunRiseDate = sdf.parse(SRStrFmt)
var String SunSetString = Sonne_Set_EndTime.state.toString()
var String SSStr = SunSetString.replace("T", " ")
var Date SunSetSDF = sdf.parse(SSStr)
var String SSStrFmt = sdf.format(SunSetSDF)
var Date SunSetDate = sdf.parse(SSStrFmt)
var Date CurrentDateTime = new Date()
var String CurrentDateTimeStr = sdf.format(CurrentDateTime)
var Date CurrentDateTimeSDF = sdf.parse(CurrentDateTimeStr)
if ( ( CurrentDateTimeSDF.getTime() < SunRiseDate.getTime() ) || ( CurrentDateTimeSDF.getTime() > SunSetDate.getTime() ) ) {
sendCommand(TIME_BETWEEN_SET_AND_RISE, ON)
if (DEBUGSwitch.state == ON) {
logInfo("+++ Debug +++","TIME_BETWEEN_SET_AND_RISE.State: " + TIME_BETWEEN_SET_AND_RISE.state)
}
} else {
sendCommand(TIME_BETWEEN_SET_AND_RISE, OFF)
if (DEBUGSwitch.state == ON) {
logInfo("+++ Debug +++","TIME_BETWEEN_SET_AND_RISE.State: " + TIME_BETWEEN_SET_AND_RISE.state)
}
}
if (DEBUGSwitch.state == ON) {
logInfo("Rule Ended","Time between Set and Rise")
}
end
If you have one time period over the day you probably have several. The above shows how to set up a state machine driven by Astro and cron that sets a String Item with the time of day.
You have basically already implemented it but your conditionals can be made much simpler.
For example:
rule "Time between Set and Rise"
when
System started or
Channel 'astro:sun:home:rise#event' triggered START or
Channel 'astro:sun:home:set#event' triggered START
then
if(now.isAfter((LocalSun_Rise_EndTime.state as DateTimeType).calendar.timeInMillis &&
now.isBefore((Sonne_Set_EndTime.state as DateTimeType).calendar.timeInMillis)){
TIME_BETWEEN_SET_AND_RISE.sendCommand(ON)
}
else {
TIME_BETWEEN_SET_AND_RISE.sendCommand(OFF)
}
end
I didn’t include your DEBUGSwitch (note, the typical way one does this is set your log statements to logDebug and put that logger (in this case “+++ Debug +++” into Debug mode). See http://docs.openhab.org/administration/logging.html
Also, if you end up with more than just these two states, a switch statement is easier to read as illustrated in the Time of Day Design Pattern linked above.
Note in the above the rule only triggers when OH restarts or one of the given events occur. You don’t need to poll when you use these events.
Hey,
i just tried your rule but it seems not to be working:
2017-02-09 18:29:43.541 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Time between Set and Rise': An error occured during the script execution: The name '<XFeatureCallImplCustom>.calendar' cannot be resolved to an item or type.
But it seems that i get the correct boolean states:
Well - at least close. As you can see, the state “is before SunRise” is false. thats because the astro binding dont update this until midnight. So i guess i’ll have to add 1 day to this?
I’m not sure what could be wrong. It looks right to me. Are you certain both DateTime Items have a state when this is running? If not what could be happening (if you are not using restoreOnStartup) is the rule is executing before the Astro binding is calculating the date times. You can try changing the triggers to:
Item LocalSun_Rise_EndTime received update or
Item Sonne_Set_Endtime received update or
Channel 'astro:sun:home:rise#event' triggered START or
Channel 'astro:sun:home:set#event' triggered START
Based on timing it might still generate one error in the logs (i.e. one of the Items is updated but the other one hasn’t been updated yes) but the rule will execute again when the second one gets calculated.
Or you can implement restoreOnStartup and it initialize the Items with whatever value they were in before the restart of OH.
You don’t have to wait until midnight. It should work but it appears the System started is not working for you.
no, thats not what i ment. The astro binding is showing the sunrise date for today - not for the next day. this is only updated after midnight. so the if statement will never be true, right?
i did got triggered the rule by the the channel events…
The calculations are done a little after midnight for that day so the if statement will evaluate to true without problem.
The reason to add the two updated triggers is so that TIME_BETWEEN_SET_AND_RISE gets updated when OH reboots or you chage the .items files. Otherwise the switch will be undefined until the next Channel event.
The above example from Rich does work as I tested it to increase my knowledge on channels. I had to change the sunrise and sunset names to match the names as used for Astro in the demo program (Sunrise_Time and Sunset_Time).
There is a however a missing bracket in the example which might be causing your error if you just copied it. There should be a single closing bracket after the ‘timeInMillis’ in the first line after the ‘then’ statement.
if(now.isAfter((LocalSun_Rise_EndTime.state as DateTimeType).calendar.timeInMillis) &&
The only issue I found is that the command is run twice at each event.
Still don’t understand channels
now the rule is working without errors. But the state is wrong Right now it is between Set and Rise but the switch isn’t on (i triggered the rule via a debug switch)
if(now.isAfter((Sonne_Set_EndTime.state as DateTimeType).calendar.timeInMillis) && now.isBefore((LocalSun_Rise_EndTime.state as DateTimeType).calendar.timeInMillis)){
TIME_BETWEEN_SET_AND_RISE.sendCommand(ON)
}
else {
TIME_BETWEEN_SET_AND_RISE.sendCommand(OFF)
}
I cant find the reason why this is not working (well i know why it isn’t working, because now.isBefore((LocalSun_Rise_EndTime.state as DateTimeType).calendar.timeInMillis) is not true) - in my first post the if statement seems to be the same as rlkoshak ones…
Yes, thats what im looking for. I use this f.e. if the rollershutter is closed (because its dark outside) but i want to go outside or just get some air, in case the time frame between set and rise is true, the roller shutter is automaticlly open if i open the window.
But anyways, i just realized that you wrote allready this piece here. I will try to use this to get things going on