Reactor passing a parameter to a lua function

Hi Patrick

Can you point me in the right direction for a reactor sensor. Attached is a screenshot of what I have so far. The idea behind the sensor is to detect when a given virtual Switchboard v-switch is on and then turn off any v-switches that are also on as represented in the sensor. The individual v-switches conform to the various sub-groups you see in the attachment and will be primarily activated through the Alexa service. I want only one switchboard v-switch (in the sensor subgroup) to be active at any one time. I’m hoping to be able to change various real switch lights and security settings per virtual switch change.

What I “believe” I should do is to use the Lua code activity for the “Modes” group to send the name of the active sub group mode (ie v-switch) to a function that uses this variable as a parameter. The function will hold a table of mode v-switch names that correspond to the passed variable. From there, the function will turn off all of the other mode/v-switch names in the table that do not match the passed variable. In this, the function will act as a kind of forced radio button.

Is there a way to capture which sub group has turned on, and then send this name to the function, or do I need to eliminate the parameter and do all the detecting for on-status within the function. If so, this leads me to suspect that I will have timing issues and difficulty discerning one “on” v-switch from another.

One other thing I’m not clear about is will the reactor sensor re-trip when a given v-switch is turned on and then immediately, the previously on v-switch is turned off, as for a brief moment there will be two switches that are turned on in the xor condition. So perhaps this needs to be an “or” condition instead of xor…

Hope all that makes sense.

“Or” seems like a better bet than “Xor”, but that alone won’t do it.

First, there is a way in Reactor activity Lua to detect which groups going true have triggered the activity–in the activity Lua is a global table called Reactor, and within it is another table called trip that has as its keys the ID of every group that is tripped. But I don’t think this is going to be as useful as it might be in this instance.

The problem you are going to run into is that if “Office” mode is on and it switches to “Garage” mode, the “Modes” group is still true, and since the “Modes is TRUE” activity will have already run once, it will not run again unless/until “Modes” goes false between.

You’d really be better off having activities for each mode that turn off the switches for the other modes. Or, use a plugin that actually implements a “choose one of several” switch–I’ve considered adding this to Switchboard. If you want to be my crash test mannequin for that, I’ll be happy to code it up. I’ve actually found use for this myself, I just haven’t gotten around to doing it yet.

I thought xor might work because it would set the sensor false as soon as the second v-light turned on and tripped the sensor. Or does it not work that way…

I thought of using multiswitch, which does have radio button functionality, but that would not get me the Alexa functionality of a single v-switch.

Hmmm… you may be right about this, and it’s darned clever. It makes sense; it seems like it should work. You should try it, and report back here.

The thing is, though, you still have more than one group true for a moment, so in that moment, the Reactor.trip table is going to tell you that both groups are true, so you won’t be able to determine from that which “radio button” is the new master. You could probably work this out with some gyrations, but I think it would be simpler to just have activities for each mode group to turn off the other modes. The last one to fire is the most recent group//vswitch that gets turned on.

Or perhaps a reactor state variable that stores the last condition/group that tripped true…

I could access such a variable in the expression builder, and then send the expression variable to my function when the modes group switched from true to false (last true v-switch/group is sent to a stored state variable, xor senses two v-switches on/true, which sets the sensor false, then activity on modes group going false calls function with stored variable parameter, function turns off “original v-light that was on” as part of the function off loop, making the sensor true again. Then the sensor runs unique true activities specific to the one true group.

I could probably use a call delay in the function to make sure enough time has passed with successive set device firing to ensure accurate v-switch on/off as the device loop increments.

I suppose I’m trying to get away from all the screen input (and associated maintenance) that would go into crafting individual activities that will, for the most part, be redundant calls to individual v-switches. It seems like that kind of hard coded approach is where things typically break. But I can certainly give that way a try if the variable approach is too difficult or has unforeseen problems.

This is one of the reasons that the Reactor.trip table may or may not be useful for this purpose… it’s possible for more than one group to go true (or more generally, change) at a time. It all depends on the logic. So there really isn’t a definition of “last” that works here, at least not with adequate resolution.

Acitivities-per-group is the way to go for this scenario, I think. Another opportunity may present itself, but I’d start there.

OK, will give it a try. BTW the xor statement does function in the inverse sense described above. The sensor untrips when two xor groups go true, and then if one of the two goes false, the sensor trips again.

One last note (I hope!) Attached is a screenshot of some variables I’ve created in an attempt to parametrize the basic activities. The modeStatus variable reads one way on screen (shows the group mode as on “1”), but is not working in an if condition statement immediately below it in the “garage” variable.

I just did a rudimentary test of this structure and it works fine for me. I suggest you disable the ReactorSensor and re-enable it, just to give it a starting kick. If that’s not getting it right, then a Logic Summary is really what’s needed here.

OK that worked. I did notice that, in this particular screen, if I toggle the sensor tripped state by turning on v-switches (using another window), that the condition/status indicators change, but the “IF” expression values do not change until I restart the sensor. I’m guessing this only true for the UI and that the variable values change with the change of state.

The expressions are evaluated in the order displayed. So if you have a variable X that is the result of a getstate(), it should be the case that any and all if() expressions that use X follow it.

OK thanks. I thought I could compare variable stored states of vswitches before modes group and after modes group going true (via XOR), to get the last switch on (my desired current mode). But the logic turned out to be too complex to handle all the various situations, at least as far as my addled self could think through… So I threw in the towel for now. Maybe with some percolation I’ll think of a way to do this without writing out nearly 100 activity commands…

I just cobbled together this arrangement of four switches that act like “radio buttons”.

    Condition group "Test RS" (AND)  TRUE as of 17:57:13 <root>
      &-T-group "Radio VSwitches" (XOR)  TRUE as of 17:57:13 <grpjil8q0r>
      |     ^-F-group "VS1 On" (AND)  false as of 17:56:48 <grpjil92h4>
      |     |     &-F-service Door Control 1 (12) urn:upnp-org:serviceId:SwitchPower1/Status istrue  [1 => 0 at 17:56:48; F/F as of 17:56:48/17:56:48] <condjil97uw>
      |     ^-T-group "VS2 On" (AND)  TRUE as of 17:57:13 <grpjil9ehl>
      |     |     &-T-service Door Control 2 (50) urn:upnp-org:serviceId:SwitchPower1/Status istrue  [0 => 1 at 17:57:13; T/T as of 17:57:13/17:57:13] <condjil9jp4>
      |     ^-F-group "VS3 On" (AND)  false as of 17:56:59 <grpjil9vdy>
      |     |     &-F-service Garage Lights (8) urn:upnp-org:serviceId:SwitchPower1/Status istrue  [1 => 0 at 17:56:59; F/F as of 17:56:59/17:56:59] <condjila0kb>
      |     ^-F-group "VS4 On" (AND)  false as of 17:57:08 <grpjilaohw>
      |     |     &-F-service Motion Control Switch (9) urn:upnp-org:serviceId:SwitchPower1/Status istrue  [1 => 0 at 17:57:08; F/F as of 17:57:08/17:57:08] <condjilapud>
    Activity grpjil9ehl.true (VS1 On is TRUE)
        Comment "Switch 1 turned on; make sure 2-4 are turned off"
        Device Door Control 1 (12) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Garage Lights (8) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Motion Control Switch (9) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Comment "Insert additional actions here for when Switch 1 is turned on"
    Activity grpjil92h4.true (VS2 On is TRUE)
        Comment "Switch 2 turned on; make sure 1, 3, 4 are turned off"
        Device Door Control 2 (50) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Garage Lights (8) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Motion Control Switch (9) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Comment "Insert additional actions here for when Switch 2 is turned on"
    Activity grpjil9vdy.true (VS3 On is TRUE)
        Comment "Switch 3 turned on; make sure 1, 2, 4 are turned off"
        Device Door Control 1 (12) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Door Control 2 (50) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Motion Control Switch (9) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Comment "Insert additional actions here for when Switch 3 is turned on"
    Activity grpjilaohw.true (VS4 On is TRUE)
        Comment "Switch 4 turned on; make sure 1-3 are turned off"
        Device Door Control 1 (12) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Door Control 2 (50) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Device Garage Lights (8) action urn:upnp-org:serviceId:SwitchPower1/SetTarget( newTargetValue="0" )
        Comment "Insert additional actions here for when Switch 4 is turned on"

Yeah, unless I’m misunderstanding what you need, you’re overcomplicating this. You really don’t need special logic, or expressions/variables, to know the last switch turned on and gyrate around that, just put the actions in the activities for each switch, because the last switch to go true is the last one that is turned on. The activities shown here turn off the other switches, so only one will remain on (largely for visual effect for you/the user). If these were “Morning”, “Day”, “Evening” and “Night” switches/groups, then you would just add the appropriate activities for each after the switch actions provided.

No, you’re correct here. Where I was hesitant in going this way was is in the number of actions in each activity that I would need to run with 9 modes … 9*8= 72 + some misc actions. The activity side of the sensor started to blur my vision, so I stopped… But this way definitely works.