February 12th, 2017

It's time to scrounge around the box of unused X10 devices for anything useful while my home automation setup still supports X10 hardware. I found a motion sensor (ActiveEye model MS16A). There is a good location for it at the bottom of the stairs leading to the landing. If I could get it to work, it could turn on lights to reduce fumbling with the key and lock at the front door when it is dark.

What the sensor will do

The sensor operates as follows. Its address is set to the same address as an X10 switch. While the sensor detects motion, it sends wireless "on" messages. The first of these messages switches the light on, the following do nothing (except clutter the airwave and power line) because the switch is already on. Once the sensor no longer detects motion, it waits for a programmable period of time and then sends a wireless "off" message which will shut the light off.

What the sensor will not do

The mode of operation described above would not work in my house for three reasons:

Of course, Domoticz can resolve this mess by acting as go between. It will read the incoming wireless message from the sensor via the Mochad bridge and it will send out the appropriate power line commands via the Heyu bridge. No need to purchase a phase coupler; which is good because I don't want to spend more money on X10 hardware.

Setting up the sensor

Instructions on setting up the sensor are contained in the product manual. The knowledge base at X10.com has much more information.

It turns out that when you change the batteries, the sensor will return to the default address: A1. After loosing the settings a few times because of this, I gave up and decided to accept the default. Hopefully, neighbours will not be using the A house code soon.

I setup my sensor to report movements day and night and to report dusk and dawn explicitly. By default the latter is done with an on and off message to an address with the same house code as the motion sensor but with a unit code equal to the successor of the motion sensor. This means the sensor will be sending "A2 on" and "A2 off" messages to report on the light level.

I did not change the default behaviour for the off message. I can use the adjustment screw on the sensor itself to dial in the delay. But it does not really matter, the off message will be ignored; the software will take care of turning off the lights.

Summarizing, I have setup the MS16A so that it looks like two sensors:

Adding sensor devices to Domoticz

Adding the motion sensor is as simple as adding a switch. Place it close enough to the CM19A (or CM15A) rf receiver. There is a minimum delay of one minute between messages that the sensor sends out, so wait a minute or so to let the sensor calm down. Click on the Switches tab, and then on the Learn Light/Switch button. When prompted to activate the remote, wave your hand over the sensor. Then fill in the name and change the switch type in the pop up dialogue window:

Adding the dusk sensor is somewhat more complicated because it is harder to trigger it on demand. Perhaps you could try putting the sensor under a blanket and using a flashlight to simulate the sun. What I did was to open an ssh session on the Raspberry Pi, and then I netcat into Mochad (nc localhost 1099) and prepared to send the on command: (rf a2 on). Back on the Switches tab, I clicked on the Learn Light/Switch button and then quickly pressed the Enter key in the ssh terminal make the Mochad bridge send the rf a2 on command to Domoticz. Much as above, you will have to enter a name and change the switch type to Dusk sensor.

A First Dysfunctional Lua Script

Following script naming convention, I saved the following script in the file /home/pi/domoticz/script/lua/script_device_mochad_a1.lua

commandArray = {} MOTION_NAME = 'Stairs' DUSK_NAME = 'Dusk' LAMP1 = 'Floor lamp' LAMP2 = 'Table lamp' ON_TIME = 10 VERBOSE = 2 -- 0 = quiet, 1 = logs commands, 2 = debug if devicechanged[MOTION_NAME] then if (VERBOSE > 1) then print('...in mochad_a1.lua') end change = devicechanged[MOTION_NAME] if otherdevices[DUSK_NAME] == 'On' then is_dark = 1 else is_dark = 0 end if (VERBOSE > 1) then print('Device: ' .. MOTION_NAME) print('Change: ' .. change) print('Dusk: ' .. DUSK_NAME) print('is_dark: ' .. is_dark) print('On time: ' .. ON_TIME) end if (change == 'On') then if (is_dark == 1) then commandArray[LAMP1]='On FOR '..ON_TIME commandArray[LAMP2]='On FOR '..ON_TIME if (VERBOSE > 0) then print('Motion detected, turn lights on for '..ON_TIME..' min.') end elseif (VERBOSE > 1) then print('Motion detected, no action, not dark') end elseif (VERBOSE > 1) and (change == 'Off') then print('Motion detection off') end end return commandArray

The great thing about the On FOR 10 minutes command is that once the 10 minutes are passed, the switch is returned to its original on/off status. If the lamp was already on, it will remain on and will not be switched off.

A Second Dysfunctional Lua Script

I tested the script by manually using netcat to talk to Mochad:

pi@raspberrypi:~ $ nc localhost 1099 rf a2 on To simulate night (if not already) rf a1 on To simulate motion detected ... rf a1 off To simulate no more motion rf a2 off To simulate day (if needed)

The lights went on and off as expected; lights turned before I sent the fake sensor message remained on after the 10 minute delay. I also concluded that 10 minutes is a long time to walk 5 steps and open a door. I wanted to change the ON_TIME but also wanted flexibility to experiment. Rather than editing the script file each time I wanted to try a new value, I decided to create a user variable so that the delay could be adjusted within the Domoticz web interface. This can be done with just a little bit of tweaking.

First create the user variable. Click on the Setup tab, then on the More Options menu, then on the User variables menu item. Continue on to Edit variable by filling in the variable name, variable type and its initial value. Complete the operation by clicking on the Add button.

To change the value of on delay later on, repeat the three steps to get back to the Edit variable screen, but now click on the line corresponding to the variable in the table. The variable name, type and value fields will be filled. Adjust the variable value to the desired number of minutes to wait before turning off the lamps and click on the Update button.

Adjust the script; the constant ON_TIME is no longer set but it is replace with a variable on_time set to equal the value of the user variable Sensor_Delay created in the previous step.

commandArray = {} MOTION_NAME = 'Stairs' DUSK_NAME = 'Dusk' LAMP1 = 'Floor lamp' LAMP2 = 'Table lamp' DELAY_VAR = 'Sensor_Delay' VERBOSE = 2 -- 0 = quiet, 1 = logs commands, 2 = debug if devicechanged[MOTION_NAME] then if (VERBOSE > 1) then print('...in mochad_a1.lua') end change = devicechanged[MOTION_NAME] on_time = uservariables[DELAY_VAR] -- time (min) to turn on LAMP1 and LAMP2 if needed if otherdevices[DUSK_NAME] == 'On' then is_dark = 1 else is_dark = 0 end if (VERBOSE > 1) then print('Device: ' .. MOTION_NAME) print('Change: ' .. change) print('Dusk: ' .. DUSK_NAME) print('is_dark: ' .. is_dark) print('On time: ' .. on_time) end if (change == 'On') then if (is_dark == 1) then commandArray[LAMP1]='On FOR '..on_time commandArray[LAMP2]='On FOR '..on_time if (VERBOSE > 0) then print('Motion detected, turn lights on for '..on_time..' min.') end elseif (VERBOSE > 1) then print('Motion detected, no action, not dark') end elseif (VERBOSE > 1) and (change == 'Off') then print('Motion detection off') end end return commandArray

A Third Working Lua Script

The script worked well when tested manually, but it took only one field test at night to see that it did not work. Typically, the sensor will send more than one on message. That makes the script fire more than once. The second time it fires, the lamps are both on, and when the delay passes, they will remain on no matter what the initial state was before the first on message from the sensor.

One possible solution is to setup a user integer variable, say Motion_Detected with an initial value of 0 (= false). When processing an on message from the sensor, the script would begin with a test: if Motion_Detected is false (= 0) then it sets it true (= 1) and continues as before, turning on the lamps. If Motion_Detected had been found to be true (=1), then the script ends doing noting because signals that the lamps are already on. Then there would be the need to write a time script (script_time_xxx.lua) which is executed once every minute. If it finds Motion_Detected is true, then it calculates the time elapsed since it was last accessed. If that time measured in minutes is longer than the value of the variable DELAY_VAR then it sets Motion_Detected is false.

I chose another approach. I created an invisible virtual sensor (type switch) called $SensorState in a new Dummy Hardware called Virtual. we have already done this in setting up Heyu, so here is a quick outline of the steps.

  1. Click on Setup tab.
  2. Click on on the Hardware menu choice.
  3. Fill in the fields
    Name = Virtual, and
    Type = Dummy (Does nothing...
  4. Click on the Add button.
  5. Click on the Create Virtual Sensors in the Virtual hardware.
  6. Name the sensor $SensorState and change its type to switch. Starting the name with a dollar sign '$' hides that switch which will be visible only in the devices list
  7. Click on the OK button.
The idea is to leave the virtual switch off most of the time and to let the script turn it on for DELAY_VAR minutes at the same time it turns on the other lamps. Domoticz will take care of turning off the switch. And the script can test the switch's state at the beginning and do nothing if it is already on.

commandArray = {} MOTION_NAME = 'Détecteur de mouvement' DUSK_NAME = 'Détecteur crépuscule' LAMP1 = 'Lampe sur pied' LAMP2 = 'Lampe sur table' VIRTUAL = '$SensorState' DELAY_VAR = 'Sensor_Delay' VERBOSE = 2 -- 0 = quiet, 1 = logs os.execute commands, 2 = debug if devicechanged[MOTION_NAME] then if (VERBOSE > 1) then print('...in mochad_a1.lua') end change = devicechanged[MOTION_NAME] on_time = uservariables[DELAY_VAR] -- time (min) to turn on LAMP1 and LAMP2 if needed if otherdevices[DUSK_NAME] == 'On' then is_dark = 1 else is_dark = 0 end if (VERBOSE > 1) then print('Device: ' .. MOTION_NAME) print('Change: ' .. change) print('Dusk: ' .. DUSK_NAME) print('is_dark: ' .. is_dark) print('On time: ' .. on_time) end if (change == 'On') then if (is_dark == 1) then if otherdevices[VIRTUAL] == "On" then if (VERBOSE > 1) then print('Motion detected, ignored, lights already on') end else commandArray[VIRTUAL]='On FOR '..on_time commandArray[LAMP1]='On FOR '..on_time commandArray[LAMP2]='On FOR '..on_time if (VERBOSE > 0) then print('Motion detected, turned lights on for '..on_time..' min.') end end elseif (VERBOSE > 1) then print('Motion detected, no action, not dark') end elseif (VERBOSE > 1) and (change == 'Off') then print('Motion detection off') end end return commandArray

Third time lucky? Hopefully this will work.The script does what I want. Only trouble is that I reach the door before the lights turn on. There is probably a delay in the sensor itself at it "debounces" the signal before sending its first on message. And then X10 hardware is not very fast. Short of learning to walk more slowly, the easiest solution may just be to move the sensor further back from the front door. I will investigate later on when its batteries are weaker, and the temperature has dropped even more. That way conditions will be at their worst and I will be able to see the limits of the rf link.