I have more RF controlled lights then I have RF switches and I dont want to expand my system with more switches because of limited space for wall-switches; both aethetics and cost wise.
Now I imagined that it would be great to program more functionality to one single switch… Therefore my question:
How to write a (timer/loop-based) rule to add functionality to one single ON-push/OFF-push switch to individually control two (or even more) separate ligths?
this is how far i get with my limited knowledge:
rule “Single switch multiple control of individual ligths”
when
Item SwitchA received update
then
var i = 1
var n = 1 // n is the ligth number
if (SwitchA.state = ON ) // this being the first received ON update
{
// create a timer for 0.1 second that itterates 20 times,
while ((i=i+1) < 21) {
Thread::sleep(100)
if ( SwitchA.state = ON “Again” ) // if received a second ON command then {
n = n + 1
}
}
if (n = 1) { sendCommand(Light1,ON) }
if (n = 2) { sendCommand(Light2,ON) }
end
Why don’t you use a group?
You can create a group item an then put your lights in the group: when the switch is triggered use the rule to send only one command to the group, and OH will send automatically the command to all the members of the group.
PS. In the when statement it’s better to use received command Instead of update.
Do not use a reserved word for Item names. You cannot have an Item named “Switch”
As Alessio indicates, if you want the switch to control more than one light you don’t need any complicated loops or timing. Just put the lights into a Group and write a simple Rule that forwards the command sent to the light switch Item to the Group.
Hi Alexxio,
I don’t use a group because I want to switch two lights seperatly (individually). Thus I want to be able too switch on Light1 while leaving Ligth2 off, also I want to be abble to switch both on, also Ligth1 off and Light2 on, and of course individually put each light off.
HI Rossko57,
Exactly your explanation is wat I am looking for in other words.
Press once to switch Ligth1, press twice (in a short period of thime lets say 2 seconds) to switch on Light2.
The same goes for switching of the lights, press once, press twice.
A less thread consuming way would be to use a Timer:
// Always define global vars on top of the rules file
var Timer tStep = null
var Number nStep = 1
rule "step through the lights"
when
Item SwitchA received update
then
if(tStep === null) { // Timer not yet started
tStep = createTimer(now.plusSeconds(2),[| // so create the timer
switch nStep { // eimer expired, so choose
case 1: Light1.sendCommand(if(Light1.state != ON) ON else OFF) // Light1 for one pulse
case 2: Light2.sendCommand(if(Light2.state != ON) ON else OFF) // Light2 for two pulses
default: // any other amount of pulses...
}
nStep=0
tStep=null
])
} else { // Timer already started
tStep.reschedule(now.plusSeconds(2)) // so reschedule
nStep = nStep+1 // anc count up
}
end
The rule will switch ON and OFF the lights individually. Maybe 2 seconds is a bit long for timeout, a typical double click is less than 0.5 Seconds, but you can check it out…
If choosing the Item names wisely you can use a group Item but switch only one item, by using another code snippet in the timer:
tStep = createTimer(now.plusSeconds(2),[| // so create the timer
val myItem = gLightGroup.members.filter[i|i.name.endsWith(if(nstep<10) "0" else ""+ nStep.toString)].head
myItem.sendCommand(if(myItem.state != ON) ON else OFF)
nStep=0
tStep=null
])
Now all Items have to be member of the Group gLightGroup, all Item names have to end with a two digit number (which is the count of clicks, needed to switch the light (Light01, Light02, Light03 and so on, each two digit number has to be unique in the group)
Thank you for your effort; your solution seems promissing. Although while testing it I ran into three issues:
This line:
nStep = nStep+1
should not be in the “else” {… } caption but after
the Number type in “var Number nStep =1” did not work for me I changed it to Integer
var Integer nStep = 1
The default: should not be empty, in an iteration it was resolved by adding these "{}"brackets thus:
default: {} // any ohter amount of pulses…
I checked the double-click time required for my system KlikaanKlikuit; it required more than one second, at least two but for reliable recievement 2.5 up to 3 seconds. I chose/accepted 3seconds.
I have upgrade the script a little bit (based on Udo’s concept) because my SwitchA has an On-push and an Off-push. After debugging using logInfo and some alternations, the rule below works for me now.
// Always define global vars on top of the rules file
var Timer tStep = null
var Integer pOn = 0 // count the received amount of powerOn-signals
var Integer pOff = 0 // count the received amount of powerOff-signals
var Integer nStep = 1
rule “Single/Double click pOn pOff counter”
when
Item SwitchA received update
then
if(tStep === null) { // Timer not yet started
tStep = createTimer(now.plusSeconds(3),[| // so create the timer
switch nStep { // timer expired, so choose
case 1: Ligth1.sendCommand(if(pOn >= 1 ) ON else OFF) // Light1; powerOn for a single pOn, else powerOff Light1
case 2: Ligth2.sendCommand(if(pOn >= 2 ) ON else OFF) // Light2; powerOn for two pOn total, else powerOff Light2
default: if(pOff >= 3 ){ gLights.sendCommand(OFF) } // Switch of all Lights in group: gLights for 3 or more pOff pulses
}
nStep=0
pOn=0
pOff=0
tStep=null
])
} else { // Timer already started
tStep.reschedule(now.plusSeconds(2)) // so reschedule
}
if(SwitchA.state == ON ) { pOn = pOn+1 }
if(SwitchA.state == OFF) { pOff = pOff+1 }
nStep = nStep+1
//While debugging this logInfo gave insight in the actual counter values
logInfo("single_double_click.rules", "End of rule. Current values of variables; nStep = " + nStep + " pOn = " + pOn + " pOff = " + pOff)
end
Again Udo, thank you for your effort, it made my day 2019-11-12T23:00:00Z
Little bit of advice. Change your Integer declarations to Number
The compile time will be greatly reduced
var Timer tStep = null
var Number pOn = 0 // count the received amount of powerOn-signals
var Number pOff = 0 // count the received amount of powerOff-signals
var Number nStep = 1