Background story
I once used expire binding to create auto off lamps, but 1 switch in a 2 gang switch is not expiring properly similar with this thread. I also like to know how long my switches will be turned off to save electricity, so I need to know remaining time of timer. After receiving many help on this wonderful forum, I want to share what I do to achieve without learning another language (I have no Java nor Python background).
With fear of expire binding go away in OH 3, and my limited understanding on python to use this python based solution to show timer remaining time, I decided to create my way to show timer remaining time using proxy item using design pattern: associated items.
How I do it
sample of items.items
Group Group_Counters_Triggers <time> (Group_Counters)
Group Group_Counters_Minutes <time> (Group_Counters)
Group Group_Counters_Seconds <time> (Group_Counters)
Switch Kodi1_stop "Stop" (Group_Kodi, Group_Counters_Triggers)
Switch Light_FF_Front "Front Hall" <light> (Group_Counters_Triggers)
Number Kodi1_stop__Counter "TV Shutdown timer [%d]" <clock> (Group_Counters_Minutes) // notice double underscore before "Counter"
Number Light_FF_Front__Counter "Front Hall timer [%d]" <clock> (Group_Counters_Seconds)
timer.rules
import org.eclipse.smarthome.model.script.ScriptServiceUtil
var Timer tKill = null
var Timer tKillSeconds = null
rule "Counter Triggers"
when
Member of Group_Counters_Triggers received command
then
val itemCounter = ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name + "__Counter" )
switch(triggeringItem.name){
case "Kodi1_stop": {
switch triggeringItem.state.toString {
case "ON": { itemCounter.sendCommand(8)
}
case "OFF": { itemCounter.sendCommand(-1) // I use "-1" because I do not know how to stop timer without using value lower than 0
}
}
}
case "Light_FF_Front": {
switch triggeringItem.state.toString {
case "ON": { itemCounter.sendCommand(30)
}
case "OFF": { itemCounter.sendCommand(-1)
}
}
}
}
end
rule "CounterMinutes Commands"
when
Member of Group_Counters_Minutes received command
then
Thread::sleep(10) //required to give rule to receive changed state, without this old state will be used
logWarn("Counter Minutes Action", triggeringItem.state.toString + " = value of " + triggeringItem.name)
tKill = createTimer(now.plusMinutes(1), [|
val stopCounter = Integer::parseInt(triggeringItem.state.toString)
logWarn("CounterMinutes Commands", "Timer " + triggeringItem.name + " runs, value = " + stopCounter)
if(stopCounter == 0){
switch(triggeringItem.name){
case "Kodi1_stop__Counter": {
if(Kodi1_stop.state == ON){ //only shutdown TV when nothing is playing. I didn't know how to get "paused" state yet.
TV_FF_Living_Power.sendCommand(OFF)
logWarn("TV Shutdown Timer", "TV shutted down, Kodi1_stop state = " + Kodi1_stop.state.toString)
}
else logWarn("TV Shutdown Timer", "something wrong, Kodi1_stop status = " + Kodi1_stop.state.toString)
}
default : {
val counterTrigger = ScriptServiceUtil.getItemRegistry.getItem( triggeringItem.name.split('__').get(0) )
counterTrigger.sendCommand(OFF)
}
}
logWarn("CounterMinutes Commands", "Counter is now " + stopCounter + ", Action for " + triggeringItem.name + " is executed. Then timer is deactivated")
tKill = null
}
if(stopCounter > 0){
logWarn("CounterMinutes Commands", "counter is not negative, reducing timer..")
triggeringItem.sendCommand(stopCounter - 1)
}
if(stopCounter === null) tKill = null
])
end
rule "CounterSeconds Commands"
when
Member of Group_Counters_Seconds received command
then
Thread::sleep(10)
logWarn("Counter Seconds Action", triggeringItem.state.toString + " = value of " + triggeringItem.name)
tKillSeconds = createTimer(now.plusSeconds(1), [|
val stopCounter = Integer::parseInt(triggeringItem.state.toString)
if(stopCounter == 0){
switch(triggeringItem.name){
default : {
val counterTrigger = ScriptServiceUtil.getItemRegistry.getItem( triggeringItem.name.split('__').get(0) )
counterTrigger.sendCommand(OFF)
}
}
logWarn("Counter Seconds Commands", "Counter is now " + stopCounter + ", Action for " + triggeringItem.name + " is executed. Then timer is deactivated")
tKillSeconds = null
}
if(stopCounter > 0){
triggeringItem.sendCommand(stopCounter - 1)
}
if(stopCounter === null) tKillSeconds = null
])
end
old.sitemap
sitemap old label="Main Menu old"
{
Switch item=Light_SF_MasterBedRoom_BathroomLightSwitch1
Slider item=Light_SF_MasterBedRoom_BathroomLightSwitch1__Counter
Switch item=TV_FF_Living_Power
Text item=Kodi1_stop__Counter
}
here is what I get on sitemap
Slider to change timer on demand.
That’s all.
Feedback is highly appreciated.