Hi there, just wanted to give some feedback on what happened to this:
-
I ended up not using a date & time-picker (out of lack of knowledge on how to do it). Instead, I’m using a slider in HAB Panel to define in how many hours I have planned my departure and an “OK”-button to commit the slider selection.
-
The countdown timers are based on Design Pattern : Expire Binding based Countdown timer and I have made some dirty fixes just to get it working for my purposes.
-
The OK-button sends the slider value through a rule that converts the hours to minutes and then sends the result to the item that triggers the rule below.
-
The formula that calculates heating time is an approximation of recommended heating times issued by heater makers and the national energy council. The resulting value and makes most sense between -30 and +10 degrees C.
-
Once the heating time is calculated, the results are sent into a rule based on the expire binding timer.
-
Current status on the involved timers are converted into hours and minutes and sent to string items that are shown in HAB Panel.
-
The solution is not as nice as I had planned for but it’s a good start that works flawless and have changed my wife’s view on home automation “silly toys” to “useful stuff”.
-
In case anyone wants to use the solution, here it is. It’s not beatiful, but it works. Improvement suggestions are welcome. (and in case you find names of items and text in screen dumps confusing, it’s because it’s in Swedish.)
Items:
Group gCounters
Group gDelayCounters
Number motorvarmare3fas_counter "Tid kvar 3 fas: [%s]" <clock> (gCounters) {expire="1m,command=-1", autoupdate="false"}
Number delaymotorvarmare3fas_counter "Min till aktivering av 3-fas : [%s]" <clock> (gDelayCounters) {expire="1m,command=-1", autoupdate="false"}
Number delaymotorvarmare3fash_counter "H till aktivering av 3-fas : [%s]" <clock>
String commitdelay "Skicka" <wallswitch>
String delaymotorvarmare3fas_status "Tid till aktivering: [%s]" <clock>
String motorvarmare3fas_status "Tid kvar av pågående värmning: [%s]" <clock>
String motorvarmare3fas_tempruntime_status "Tempanpassad värmartid: [%s]" <clock>
Number motorvarmare3fas_tempruntime "Tempanpassad värmartid: [%s]" <clock>
Number motorvarmare3fas_timetodeparture "Sätt tid till avresa (mins): [%s]" <clock>
Number motorvarmare3fash_timetodeparture "Sätt tid till avresa (hrs): [%s]" <clock>
Rules:
//Receive departure time in hours from HAB Panel
rule "1. Delay activation"
when
Item commitdelay received command "DELAY"
then
var cmmd = (motorvarmare3fash_timetodeparture.state as Number).intValue
logWarn("timer.rules", "Delay activation: Received value " + cmmd + " h")
motorvarmare3fas_timetodeparture.sendCommand(cmmd * 60) //convert hours to minutes
logWarn("timer.rules", "Delay activation: Converted to " + 60*cmmd + " min and sent to motorvarmare3fas_timetodeparture")
motorvarmare3fash_timetodeparture.sendCommand(0)
logWarn("timer.rules", "Delay activation: Cleared slider item in HAB Panel (motorvarmare3fash_timetodeparture)")
commitdelay.sendCommand("DELAY CONFIRMED")
end
//Adjusts heating time to the current temperature
rule "2. Countdown by temp"
when
Item motorvarmare3fas_timetodeparture received command
then
val DepTime = (receivedCommand as Number).intValue // integers only
if (DepTime==0){
motorvarmare3fas_tempruntime.sendCommand(0)
commitdelay.sendCommand("CANCEL")
} else {
logWarn("timer.rules", "Countdown by temp: DepTime set to " + DepTime + " minuter")
val OutdoorTemp = (Netatmo_Outdoor_Temperature.state as Number)
logWarn("timer.rules", "Countdown by temp: OutdoorTemp set to " + OutdoorTemp + " degrees")
val RunTime = (60*(-0.075*OutdoorTemp+1.25)).intValue
logWarn("timer.rules", "Countdown by temp: RunTime set to " + RunTime + " minuter")
var DelayTime = (DepTime-RunTime).intValue
if(DelayTime < 0) {
DelayTime = 1 //Force 1 minute countdown in case DepTime minus RunTime is less than 0. Otherwise timer won't trigger.
}
logWarn("timer.rules", "Countdown by temp: DelayTime set to " + DelayTime + " minuter")
motorvarmare3fas_tempruntime.sendCommand(RunTime)
delaymotorvarmare3fas_counter.sendCommand(DelayTime)
}
end
// Countdown before activating the heater for a given amount of time
rule "3. Countdown delay"
when
Member of gDelayCounters received command
then
var cmmd = (receivedCommand as Number).intValue // integers only
var count = 0
val RunTime = (motorvarmare3fas_tempruntime.state as Number).intValue
//logWarn("timer.rules", "Countdown delay: Runtime will be set to " + RunTime + " minutes")
// logWarn("timer.rules", "Delay av 3-fastimer mottog värde " + cmmd + " h")
//cmmd = cmmd * 60
if (triggeringItem.state != NULL) { // avoid 1st time run error
count = (triggeringItem.state as Number).intValue
}
//val lightname = triggeringItem.name.split("_").get(0) // derive light
//val myLight = gTimedDevices.members.filter[ i | i.name == lightname ].head // get light item
if (cmmd == -1 && count > 0) { // decrement counter, do not go below zero
if (count == 1) {
// do actions for counter expiry, as we about to zero it now
motorvarmare3fas_counter.sendCommand(RunTime)
logWarn("timer.rules", "Countdown delay: Runtime activated for " + RunTime + " minutes")
}
triggeringItem.postUpdate(count - 1)
} else if (cmmd == 0) { // cancel countdown
triggeringItem.postUpdate(0)
logWarn("timer.rules", "Countdown delay: Countdown cancelled")
// do optional cancel actions
//myLight.sendCommand(OFF)
} else if (cmmd >= count || cmmd < -1) { // new or refreshed target
if (cmmd < -1) { // force override
cmmd = 0 - cmmd // make it positive
}
triggeringItem.postUpdate(cmmd) // nb we still update even if equal value - resets expire binding
// do startup/continue actions
//if (myLight.state != ON) {
// myLight.sendCommand(ON)
//}
}
end
//Updates status items to show timer values in hours and minutes rather than just minutes or decimmal hours
rule "4. Update counter status"
when
Item delaymotorvarmare3fas_counter changed
or
Item motorvarmare3fas_counter changed
or
Item motorvarmare3fas_tempruntime changed
then
val int totalMinsDelay = (delaymotorvarmare3fas_counter.state as Number).intValue
val mind = totalMinsDelay % 60
val hrsd = (totalMinsDelay / 60) % 24
val String delayhrsmins = hrsd.toString + "h " + mind.toString + "m"
delaymotorvarmare3fas_status.sendCommand(delayhrsmins)
val int totalMinsVarmare = (motorvarmare3fas_counter.state as Number).intValue
val minv = totalMinsVarmare % 60
val hrsv = (totalMinsVarmare / 60) % 24
val zerocheck = minv+hrsv
if(zerocheck == 0){
motorvarmare3fas_status.sendCommand("N/A")
} else {
val String heathrsmins = hrsv.toString + "h " + minv.toString + "m"
motorvarmare3fas_status.sendCommand(heathrsmins)
}
val int totalMinsTemprun = (motorvarmare3fas_tempruntime.state as Number).intValue
val mint = totalMinsTemprun % 60
val hrst = (totalMinsTemprun / 60) % 24
val String temprunmins = hrst.toString + "h " + mint.toString + "m"
motorvarmare3fas_tempruntime_status.sendCommand(temprunmins)
end
//Cancel timers. It can also be done without this rule by sending 0 as timer values.
rule "5. Cancel timers"
when
Item commitdelay received command "CANCEL"
then
delaymotorvarmare3fas_counter.sendCommand(0)
motorvarmare3fas_counter.sendCommand(0)
motorvarmare3fas_tempruntime.sendCommand(0)
end
The looks of it in HAB Panel
![image](//community-openhab-org.s3.dualstack.eu-central-1.amazonaws.com/original/3X/e/c/eca608acb1f931dc5cb5e2c922042205f78dc6fe.png)
And to use it in a sitemap, this is the code I’m using:
Text item=motorvarmare3fas label="Heater [%s]" icon="poweroutlet" labelcolor=[delaymotorvarmare3fas_counter >0 = "orange"]{
Frame label="Heater/3-phase outlet" {
Selection item=motorvarmare3fas_timetodeparture label="Time to departure: []" mappings=[
0="Cancel",60="1h",120="2h",180="3h",240="4h",300="5h",360="6h",420="7h",480="8h",
540="9h",600="10h",660="11h",720="12h",780="13h",840="14h",900="15h",960="16h",
1020="17h",1080="18h",1140="20h",1200="21h",1260="22h",1320="23h",1380="24h"]
Text item=motorvarmare3fas_tempruntime_status icon="time"
Text item=delaymotorvarmare3fas_status icon="time"
Text item=motorvarmare3fas_status icon="time"
Switch item=motorvarmare3fas label="Outlet status [%s]" icon="poweroutlet"
}
}
…which looks like this (although label text is translated in the sitemap code above):
![image](//community-openhab-org.s3.dualstack.eu-central-1.amazonaws.com/original/3X/b/e/be9b1b7b149ac512a64b95ebccff2e03dc423279.png)