I have created a variation of the “Taking Rules to New Heights” from the wiki. I am quite new so there is some stuff in the wiki that I don’t quite get so I tried to make something similar that I understood fully, and could be used with my wink lights.
The rules seem to work well.
When the light group changes the rule is triggered.
It then checks all the lights from a hashmap that stores the last value update - so that only the updated item gets sent a command.
In the same hashmap there is a timer and timeout stored that is used if set to true.
NOTE - I rooted my wink hub out of the box and do not want to update as my luck with such things is not very good, because of this I cannot use the “blink” app. I also do not want to run any extra php on the wink hub as we do not know for sure what long term consequences such synchronization will cause - like an early failure, instead I run a cron rule that checks the status of the light from the hub and updates the status on openhab if it is different.
The code is below, if you have any suggestion I would greatly appreciate them, I am starting to get the hang of this language and even small suggestions can take me leaps and bounds further.
Thanks in advance.
import org.joda.time.*
import org.eclipse.xtext.xbase.lib.*
import org.openhab.core.persistence.*
import org.openhab.core.library.types.*
import org.openhab.core.library.types.PercentType
import org.openhab.core.library.items.SwitchItem
import org.openhab.core.library.items.NumberItem
import org.openhab.core.library.items.DimmerItem
import org.openhab.model.script.actions.*
import org.openhab.model.script.actions.Timer
import java.util.HashMap
import java.util.LinkedHashMap
import java.util.List
import java.util.ArrayList
import java.util.Map
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
var Timer timer
val HashMap<String, LinkedHashMap<String, Object>> winkLightInfo =
newHashMap(
"bedroom_one_light" -> (newLinkedHashMap(
"id" -> "2",
"at" -> false as Boolean,
"at_time" -> null,
"timer" -> null as Timer,
"last_update" -> 0,
"oh_item" -> bedroom_one_light as NumberItem
) as LinkedHashMap<String, Object>),
"upstairs_kitchen_light" -> (newLinkedHashMap(
"id" -> "1",
"at" -> true as Boolean,
"at_time" -> 30,
"timer" -> null as Timer,
"last_update" -> 0,
"oh_item" -> upstairs_kitchen_light as NumberItem
) as LinkedHashMap<String, Object>),
"upstairs_bathroom_light" -> (newLinkedHashMap(
"id" -> "3",
"at" -> true as Boolean,
"at_time" -> 30,
"timer" -> null as Timer,
"last_update" -> 0,
"oh_item" -> upstairs_bathroom_light as NumberItem
) as LinkedHashMap<String, Object>)
)
// On system start we need to:
// -> Get the status of the WInk lights from the Hub
// -> Set all the wink lights to 0 using postUpdate
rule "Initialize lighting and lighting hardware"
when
System started
then
createTimer(now.plusSeconds(5)) [|
lights_wink.members.forEach[item, i| createTimer(now.plusSeconds(i)) [|
var String name = item.name
var Number value = item.state
executeCommandLine("/home/pi/wink/wink-status.sh " + name + " " + value.toString + " -update")
]]
createTimer(now.plusSeconds(15)) [|
lights_wink.members.forEach[item2, i2| createTimer(now.plusSeconds(i2)) [|
var String name2 = item2.name
var Number value2 = item2.state
winkLightInfo.get(name2).put("last_update", value2)
]]
]
]
end
// WINK LIGHT STATUS'
// This rule runs a check every ten minutes
// -> Gets the real status of the lights from the wink hub
rule "Check wink light status"
when
Time cron "0 0/10 * * * ?"
then
lights_wink.members.forEach[ item, i | createTimer(now.plusSeconds(i)) [|
var String name = item.name
var Number value = item.state
executeCommandLine("/home/pi/wink/wink-status.sh " + name + " " + value.toString + " -update")
]]
createTimer(now.plusSeconds(10)) [|
lights_wink.members.forEach[item2, i2| createTimer(now.plusSeconds(i2)) [|
var String name2 = item2.name
var Number value2 = item2.state
winkLightInfo.get(name2).put("last_update", value2)
]]
]
end
// SOFTWARE LIGHT CONTROLS
// These rules are the software controls for the wink lights
// -> when one of the lights receives a command it updates the state of the light
rule "Upstairs Bathroom main light autoshut off"
when
Item lights changed
then
val HashMap<String, Object> performUpdates = new HashMap<String, Object>()
for (f : winkLightInfo.entrySet()) {
val Number lastUpdatedState = f.getValue().get("last_update")
val DimmerItem currentItem = f.getValue().get("oh_item") as NumberItem
//println("name: " + currentItem.name + " last_state: " + lastUpdatedState + " new_state: " + currentItem.state.toString)
if(lastUpdatedState.toString != (currentItem.state.toString)) {
performUpdates.put(currentItem.name, currentItem.state)
f.getValue().put("last_update", currentItem.state)
}
}
for ( String key : performUpdates.keySet() ) {
val finalValue = performUpdates.get(key)
val fixture = winkLightInfo.get(key)
executeCommandLine("/home/pi/wink/winkhub.sh -m" + fixture.get("id") + " -t 2 -u -v " + finalValue)
if(fixture.get("at") == true) {
var Timer timer = fixture.get("timer") as Timer
if(finalValue.toString != "0") {
val thisLight = fixture.get("oh_item") as NumberItem
timer = createTimer(now.plusSeconds(fixture.get("at_time"))) [|
postUpdate(thisLight, 0)
]
fixture.put("timer", timer)
println("light on timer has been STARTED")
} else {
if(timer!=null) {
timer.cancel
fixture.put("timer", null)
println("light off, timer has been CANCELLED")
}
}
}
}
end