Reactor Expressions/Variables Not Updating

I have a reactor sensor configured which changes the state of occupancy/vacancy via luup.call_action based upon the time of the day. I am also using an exported variable/expression to set a variable to ‘occupancy’ or ‘vacancy’ for reference by other reactor sensors. HOWEVER, I am seeing that this variable doesnt update automatically. Why? Is there a way I can trigger an evaluation in one of the reactor actions? The issue is… I have a virtual switch to disable the motion component of the lights (individually) and set to manual mode. When I toggle the switch, I have lua code which tests to see if the exported variable is set to ‘occupancy’ or ‘vacancy’ and set the correct command. However, since the variable never updates… whenever this is triggered, things are set to ‘occupancy’ during the day, which I dont want!

Thoughts?

Offhand, I’d guess you’re not setting the variable correctly. Can you show us the action you are using?

Here is the expression:

dimmer_vacancy_mode

if ( getstate( null, "urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped" ) == "1", "vacancy", "occupancy" )

"occupancy"

So, right now the sensor is indeed tripped, and running the expression manually gets “The expression result is: vacancy (string)”.

Then, on the other reactor sensor, I have the following expression:

dimmer_mode
getstate( 52, "urn:toggledbits-com:serviceId:ReactorValues", "dimmer_vacancy_mode" )
"occupancy"

With the following action:

-- Device: MBR Motion [GE ZW3008], device #241, altid 17
if (Reactor.variables.dimmer_mode == "vacancy") then
    -- Action: Set device option variable 3 to value 2 (Vacancy Mode)
	luup.call_action('urn:micasaverde-com:serviceId:ZWaveNetwork1','SendData',{Node='17',Data='112 4 3 1 2'},1)
else
    -- Action: Set device option variable 3 to value 3 (Occupancy Mode)
	luup.call_action('urn:micasaverde-com:serviceId:ZWaveNetwork1','SendData',{Node='17',Data='112 4 3 1 3'},1)
end

Since the sensor is tripped, this should all be evaluating against ‘vacancy’ as the set variable, but this is not the case.

OK. This seems to be a rather hard way of going about it.

First off, why do you have two ReactorSensors? Is there something else the first one is doing other than being a container for the expression?

Second, you cannot set Tripped state on a ReactorSensor. Reactor owns that variable/state and gets to determine it. The only way you can influence its value is by the logic result of the root group. Anything you do to try to manipulate it from outside of Reactor won’t work, and isn’t supported.

Also, you don’t need to export a Reactor expression/variable and then use Lua to read it, or use another expression even. It’s a lot of plumbing. You can test the value of an expression/variable directly using an Expression Value condition. In your activity, you don’t need Lua, you can access the SendData action on the ZWave controller (device #1).

Here’s what I think your setup should look like (one ReactorSensor). First, the expression. Just an expressionless-variable, so you can set it from outside:

Then, the condition to check the variable value:

Then, the activities:

Done! Now, to set the occupied mode from outside using call_action(), use Reactor’s SetVariable action to set the value of occupied to 0 or 1:

luup.call_action( "urn:toggledbits-com:serviceId:ReactorSensor", "SetVariable", 
    { VariableName="occupied", NewValue="1" }, reactorsensor_dev_num )

or via HTTP request:

http://vera-ip:3480/data_request?id=action&DeviceNum=RSDEVNUM&serviceId=urn:toggledbits-com:serviceId:ReactorSensor&action=SetVariable&VariableName=occupied&NewValue=1

Additional reading/reference:

FWIW: Version 3.9 currently in development will let you control the value of the Tripped variable on a ReactorSensor provided that the root group operator is NUL (otherwise, Reactor continues setting Tripped to the logic state of the root group as it does now).

Holy cow! There is a send data action built into reactor? Well, started rebuilding the sensor which modifies occupancy/vacancy based upon time of day. I have 7 devices for which I am toggling this setting.

Additionally, I have separate sensors for each of the 7 devices to toggle manual mode. Currently, I have been trying to do this my having a virtual switch corresponding to each device, for keeping the motion detection enabled (ie, vacancy or occupancy mode) or turning it off (manual). The only way I was able to tie things together, was to have a separate reactor sensor for each device as well. Depending on the state of the virtual switch (and I am also checking to see if its between 2300 and sunrise for the bedrooms) I am setting the device option variable to manual. However, when and if manual mode is turned off, I want to revert to either occupancy or vacancy, based upon the setting of the main reactor sensor controlling this. Hence why I was trying to see if I can read the variable.

Not sure if there is a more elegant way of doing this.

The SendData action is a defined action of the urn:micasaverde-com:serviceId:ZWaveNetwork1 service, so Reactor naturally supports it. All devices in the system name the services they support, and Reactor just uses that information. This minimizes the need to use Lua, so you should always look for (as ask for) a function/action before heading to the RunLua action. My home has a ton of automations, and not one RunLua anywhere.

You can read and act on a variable/expression from one ReactorSensor in another by using a Expression Value condition. Make sure the “source” ReactorSensor has the variable exported (but it only needs to be exported if you are going to read it from a ReactorSensor other than the one in which the variable/expression is defined).

Other things to consider that may help smooth out your logic:

  • You can use a Group State condition to read and react to the status of any group in any ReactorSensor.
  • You can have as many groups as you want in a ReactorSensor. Anyplace you are using N ReactorSensors, you can probably just as easily use N groups in 1 ReactorSensor. This can take a little getting used to, but it’s really useful. And I’m not saying that’s what you should do, I’m just saying that if you think you need a separate ReactorSensor to do something, that’s probably incorrect. But, you should use as many RS’s as make sense and keep you sane. I keep all of the logic for each room in a single ReactorSensor in that room. Global things like deciding whether it’s day or night, we’re on vacation or not, etc. go into a ReactorSensor in the “Virtual Devices” room, and the per-room ReactorSensors use Group State commands to look at the logic elements there for the per-room decisions on what happens when time phase changes.
  • Likewise, you can have as many variables as you want, so a little attention to naming things more like occupied_familyrm and occupied_livingrm will help you keep things separated within a single RS.

Looks like when I test the Device Action ‘SendData’, I get the following error popup:

urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="12", Data="112 4 3 1 3" )

400 Bad Request undefined

Previously this worked fine with straight ‘run lua’:

luup.call_action(‘urn:micasaverde-com:serviceId:ZWaveNetwork1’,‘SendData’,{Node=‘12’,Data=‘112 4 3 1 3’},1)

Am I missing something obvious?

I do it all the time. Works for me. Are you on remote access, perhaps?

Try saving the activity and using the “Run Activity” button (also a running man) next to the activity name.

Locally accessing… Mozilla Firefox, and Microsoft Edge as well. New sessions each time, so full reload of the DOM. The activities were also scheduled to execute, but failed, as the mode didnt change from vacancy to occupancy at night. Definitely attempted to run with the ‘running man’ button, a few times, same error. Really strange. On the newest version of Vera Edge firmware, latest Reactor, and even updated the device database.

Please post a Logic Summary.

*************************************************** REACTOR LOGIC SUMMARY REPORT ***************************************************
   Version: 3.8-20262 config 20190 cdata 20045 ui 20190 pluginDevice 39 LuaXP 1.0.2enh
    System: Vera version 1.7.5186 (7.31) on Sercomm G450 ID 36 (Vera Plus); loadtime 1606799797/1606799811; systemReady 1606799816
       Env: Lua 5.1; JSON dkjson 1.2; UnsafeLua=nil/true
Local time: 2020-12-01T10:13:26-0500; DST=0; [REDACTED] United States; formats %Y/%m/%d %H:%M:%S
House mode: plugin 1; system 1; tracking on
  Sun data: { "source": "int", "civdawn": 1606822163, "nautdawn": 1606820015, "sunset": 1606857080, "nautdusk": 1606861164, "stamp": 2020336, "latitude": 43.749677, "astrodusk": 1606863240, "longitude": -71.764801, "civdusk": 1606859016, "astrodawn": 1606817939, "sunrise": 1606824099 }
  Geofence: not running
        RS: 1600826834,1600826949,1600977666,1601072313,1601586566,1601586666,1601586775,1601730091,1601766272,1602011100,1602011169,1602011215,1602012763,1602015221,1602016414,1602040011,1602170771,1602262537,1602262642,1602262764,1602280585,1602542752,1602857271,1603677187,1603810427,1605382321,1606241013,1606253338,1606777751,1606786266,1606799463,1606799811
        NS: 1595090400:D,1595092680:U,1596608880:D,1596614400:U,1596630900:D,1596631020:U,1599595265:D,1599595320:U,1599625440:D,1599625800:U
************************************************************************************************************************************
GEN Dimmer Vacancy Mode [Vera] (#52) tripped
    Version 19082.38 11/30/20 15:56:37
    Message/status: Tripped
    Variable/expressions
       0: dimmer_vacancy_mode      if ( getstate( null, "urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped" ) == "1", "vacancy", "occupancy" ) [last "occupancy"(string)] (exported)
       1: dimmer_mode               [last "vacancy"(string)] (exported)
    Condition group "Dimmer Daytime Home Mode" (AND)  TRUE as of 06:46:00 <root>
      &-T-sun bet sunrise-15,sunset+15 [1606799812 => 1606823160 at 06:46:00; T/T as of 06:46:00/06:46:00] <condng42d5y>
      &-T-housemode in 1,3 [2 => 1 at 11-27.17:28:38; T/T as of 11-27.17:28:38/11-27.17:28:38] <condng42uk1>
    Activity root.false
        Comment: Occupany Mode (Device option variable 3 to value 3)
        Device GBR Motion [GE ZW3008] (202) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="12", Data="112 4 3 1 3" )
        Device HALL Motion [GE ZW3008] (12) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="2", Data="112 4 3 1 3" )
        Device KIT Motion [GE ZW3008] (18) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="6", Data="112 4 3 1 3" )
        Device LOFT Motion [GE ZW3008] (207) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="13", Data="112 4 3 1 3" )
        Device LVR Motion [GE ZW3008] (15) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="5", Data="112 4 3 1 3" )
        Device MBR Motion [GE ZW3008] (241) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="17", Data="112 4 3 1 3" )
        Device OFC Motion [GE ZW3008] (238) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="16", Data="112 4 3 1 3" )
        Set Variable dimmer_mode="occupany"
    Activity root.true
        Comment: Vacancy Mode (Device option variable 3 to value 2)
        Device GBR Motion [GE ZW3008] (202) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="12", Data="112 4 3 1 2" )
        Device HALL Motion [GE ZW3008] (12) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="2", Data="112 4 3 1 2" )
        Device KIT Motion [GE ZW3008] (18) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="6", Data="112 4 3 1 2" )
        Device LOFT Motion [GE ZW3008] (207) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="13", Data="112 4 3 1 2" )
        Device LVR Motion [GE ZW3008] (15) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="5", Data="112 4 3 1 2" )
        Device MBR Motion [GE ZW3008] (241) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="17", Data="112 4 3 1 2" )
        Device OFC Motion [GE ZW3008] (238) action urn:micasaverde-com:serviceId:ZWaveNetwork1/SendData( Node="16", Data="112 4 3 1 2" )
        Set Variable dimmer_mode="vacancy"
    Events
        2020-12-01 00:16:51: Reactor startup (Luup reload)
        2020-12-01 00:16:51: Starting (Luup Startup/Reload)
        2020-12-01 00:16:52: Sensor update starting
        2020-12-01 00:16:52: Sensor update completed; 0.026s
        2020-12-01 06:46:00: Sensor update starting
        2020-12-01 06:46:00: Condition condng42d5y test state changed from false to true
        2020-12-01 06:46:00: Condition condng42d5y evaluation state changed from false to true
        2020-12-01 06:46:00: Group Dimmer Daytime Home Mode test state changed from false to true
        2020-12-01 06:46:00: Group Dimmer Daytime Home Mode evaluation state changed from false to true
        2020-12-01 06:46:00: Preparing Dimmer Daytime Home Mode.true (root.true) activity
        2020-12-01 06:46:00: Launching scene/activity root.true
        2020-12-01 06:46:00: Starting "root.true" group 1
        2020-12-01 06:46:00: Variable "dimmer_mode" set to "vacancy"; was "occupany"
        2020-12-01 06:46:00: Activity "root.true" finished
        2020-12-01 06:46:00: Stopping activity "root.true"
        2020-12-01 06:46:00: Changing RS tripped state to true
        2020-12-01 06:46:00: Sensor update completed; 0.124s
    Devices
        ZWave (1) urn:schemas-micasaverde-com:device:ZWaveNetwork:1 (19/0); parent 0; plugin -; mfg  model ; dev D_ZWaveNetwork.xml impl 
        LVR Motion [GE ZW3008] (15) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        OFC Motion [GE ZW3008] (238) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        LOFT Motion [GE ZW3008] (207) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        MBR Motion [GE ZW3008] (241) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        KIT Motion [GE ZW3008] (18) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        GBR Motion [GE ZW3008] (202) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
        HALL Motion [GE ZW3008] (12) urn:schemas-micasaverde-com:device:MotionSensor:1 (4/3); parent 1; plugin -; mfg GE/Jasco model ; dev D_MotionSensor1.xml impl 
    Watches
        Device #52 GEN Dimmer Vacancy Mode [Vera] service urn:toggledbits-com:serviceId:ReactorSensor variable cdata
        Device #39 GEN Reactor [Vera] service urn:toggledbits-com:serviceId:Reactor variable HouseMode
        Device #52 GEN Dimmer Vacancy Mode [Vera] service urn:toggledbits-com:serviceId:ReactorSensor variable TestHouseMode
        Device #52 GEN Dimmer Vacancy Mode [Vera] service urn:toggledbits-com:serviceId:ReactorSensor variable TestTime
    Special Configuration
        UseReactorScenes = 1
        Retrigger = 0
        FailOnTrouble = 0
        ContinuousTimer = 0

I’m… a bit lost. The variables don’t appear to be used anywhere? And you don’t need to create dimmer_vacancy_mode if you are using it externally because any other logic can just check Tripped on this RS directly. And dimmer_mode isn’t doing anything for you either. This logic doesn’t really coincide with the discussion; it’s simpler, for sure. As it’s set up right now, this RS will set the devices in “vacancy” mode between a bit before sunrise and a bit after sunset when you’re in house mode “Home” or “Night”, which seems OK. But there’s nothing here that makes any use of the variables/expressions and they have no effect on the logic of this sensor, they are just busy work here.

As for the 400 errors, I have no idea. This works perfectly for me where I use it. You might check and make sure your node numbers are correct, and your data string has the right parameter length and number of bytes for what it’s setting.

Use the variable in another reactor sensor. I was tinkering with both of the variables. The main issue is the later part of why the 400 error.

Previously, this all worked using the following Lua code:

luup.call_action('urn:micasaverde-com:serviceId:ZWaveNetwork1','SendData',{Node='17',Data='112 4 3 1 2'},1)

When converting it to the built-in functionality of the reactor sensor, used my comment notes where I had already mapped the device IDs, ie #241 to the corresponding altid, ie 17. Will double check these again, but yeah, not sure why its not liking it.

How does the reactor sensor format this against the API? I can try this directly and see if it gives me any errors.

This is what the output looks like for me when I do it:

image

from this…

1 Like

So, yeah, like the first device, checking the settings it is indeed #202, with altid 12. The send string is correct ‘112 4 3 1 2’ as I have been doing this before with luup.cal_action. I test this via the running man, and receive the 400 error.

Ohhh, think I see what the issue was. I was sending the data directly to the device, instead of the Zwave network. Ie, #202 instead of #1. Doh.

I see. You were doing something sensible. You clearly have not been around Vera long enough. :slight_smile:

Good catch by the way. I totally missed it.

Now I can move onto cleaning up the logic with the other reactor sensor(s), and consider your recommendations on simplifying things. Suppose I didnt realize that zwave uses the altids to reference nodes and execute changes, versus the ID # provided by Vera itself for a configured device. Well, learned quite a bit through this exercise and with the help of your assistance (sometimes have a thick skull).

An idea does come to mind though, is there any way to support in the action when using senddata the ability for the GUI to show the device name and/or ID as it exists in Vera when you put in the altid? When looking at this, its difficult to keep in mind or track which altid corresponds to which device. Previously I used commends in my luup code, but just thinking how to provide some additional user feedback on input provided.

Hah, I will not argue there. Work with various network/security device APIs all the time and have developed code in the past, so no stranger to those items. But learning ‘language syntax’ and ‘constructs’, that is what changes.

Needed a good solid double brown ale, but believe I see how you use your creation. Re-did the reactor sensor for the Master Bedroom as a general ‘Lighting Control’ as per the function, and set it up as NULL… merely a container. Nested previous logic in there for setting manual mode on light dimmer via the native reactor senddata, based upon time and/or the status of a Dimmer Motion control ‘virtual switch’ (have this in here for integration with Alexa to tell her to disable the motion detection via the Ecobee). Then I used separate groups w/ both Group State Logic and looking at the tripped state on the General dimmer mode (occupancy/vacancy) to have two state options for sending different sets of senddata controls.

This should work. If it does, have a few bedrooms to rework, and then its off to setting up similar logic for HVAC controls (ie, when to use liquid propane versus minisplit).