[SOLVED] Single switch individually controlling multiple ligths

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

and for OFF command vice versa.

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.

Edit: ah and welcome!

Please How to use code fences.

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.

I don’t understand the timer stuff. Are you trying to achieve something like press-once-for light X, press-twice-for light Y ?

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.

rlkoshak, I have updated the switchname to SwitchA. Thanks for the tip, I am new in posting, this is my first.

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 :wink: 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)

Hi Udo_Hartmann,

Thank you for your effort; your solution seems promissing. Although while testing it I ran into three issues:

  1. This line:

nStep = nStep+1

should not be in the “else” {… } caption but after

  1. the Number type in “var Number nStep =1” did not work for me I changed it to Integer

var Integer nStep = 1

  1. The default: should not be empty, in an iteration it was resolved by adding these "{}"brackets thus:

default: {} // any ohter amount of pulses…

  1. 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 :slight_smile:
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

Hi :slight_smile:

  1. nStep = nStep +1 should only happen, if the timer is already started and still running, so yes, it should remain within the else part.
  2. Integer… Well, yes, this is a typical issue for me… You have to change the type for switch:
switch (nStep.intValue) {    
  1. default: Jepp, maybe my comment was misleading here.
  2. As the button does send two updates per action (ON and OFF), just change the trigger for the rule to
Item SwitchA received update ON

Maybe received command would also work:

Item SwitchA received command ON