View Full Version : how to subscribe to motion detector DM events
mhwlng
December 31st, 2006, 09:58 AM
I want to be notified via a single lua callback whenever any motion detector (i.e. type:Security\Sensor) Condition changes (Ready/Not Ready) in the Device Manager...
What is the best way to do this ?
Do I need to iterate through all my motion detector devices and subscribe to each one with the same callback function, or is there a better way ?
Marcel
Rob H
December 31st, 2006, 10:11 AM
You could use DeviceManager:Subscribe() e.g.
DeviceManager:Subscribe(function (...) self:HandleEvent(unpack(arg)) end)
where HandleEvent would be something like
HandleEvent = function(self, event, path, controlId)
if event == DeviceManager.Devices.Events.Condition then
local device = DeviceManager:GetDeviceUsingPath(path)
assert(device, 'No device for path '..path)
local control = device:GetControl (controlid)
assert (control,'No control for id'..controlid)
if control:IsType('Security\\Sensor') then
-- add code here to handle the sensor
end
end
end
mhwlng
December 31st, 2006, 10:17 AM
I tried this code :
require 'DeviceManager.Devices'
require 'DeviceManager.Controls'
HandleEvent = function( event, path, controlId)
if event == DeviceManager.Devices.Events.Condition then
local device = DeviceManager:GetDeviceUsingPath(path)
assert(device, 'No device for path '..path)
local control = device:GetControl (controlid)
assert (control,'No control for id'..controlid)
if control:IsType('Security\\Sensor') then
print (path);
end
end
end
DeviceManager:Subscribe(function (...) HandleEvent(unpack(arg)) end)
and got this :
Error in subscriber callback
...is\Girder5\luascript\DeviceManager/Devices/Basic.lua:533: attempt to concatenate local `id' (a nil value)
stack traceback:
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:28: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:25>
...is\Girder5\luascript\DeviceManager/Devices/Basic.lua:533: in function `GetControl'
[string "marcel v2.0.gml:\X10\motion detectors"]:8: in function `HandleEvent'
[string "marcel v2.0.gml:\X10\motion detectors"]:16: in function <[string "marcel v2.0.gml:\X10\motion detectors"]:16>
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:37: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:36>
[C]: in function `xpcall'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:40: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:32>
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:151: in function `SendEvent'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:138: in function `Event'
...m Files\Promixis\Girder5\luascript\DeviceManager.lua :644: in function `Event'
...m Files\Promixis\Girder5\luascript\DeviceManager.lua :569: in function <...m Files\Promixis\Girder5\luascript\DeviceManager.lua :550>
...
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:37: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:36>
[C]: in function `xpcall'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:40: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:32>
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:151: in function `SendEvent'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:138: in function `Event'
.\scripts\x10.lua:1406: in function `Event'
.\scripts\x10.lua:1485: in function `SetCondition'
.\scripts\x10.lua:1591: in function `UpdateX10'
.\scripts\x10.lua:939: in function `ReceiveEvent'
.\scripts\x10.lua:861: in function <.\scripts\x10.lua:845>
Error in subscriber callback
...is\Girder5\luascript\DeviceManager/Devices/Basic.lua:533: attempt to concatenate local `id' (a nil value)
stack traceback:
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:28: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:25>
...is\Girder5\luascript\DeviceManager/Devices/Basic.lua:533: in function `GetControl'
[string "marcel v2.0.gml:\X10\motion detectors"]:8: in function `HandleEvent'
[string "marcel v2.0.gml:\X10\motion detectors"]:16: in function <[string "marcel v2.0.gml:\X10\motion detectors"]:16>
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:37: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:36>
[C]: in function `xpcall'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:40: in function <...les\Promixis\Girder5\luascript\Classes/Publisher.lua:32>
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:151: in function `SendEvent'
...les\Promixis\Girder5\luascript\Classes/Publisher.lua:138: in function `Event'
...m Files\Promixis\Girder5\luascript\DeviceManager.lua :644: in function `Event'
...m Files\Promixis\Girder5\luascript\DeviceManager.lua :569: in function <...m Files\Promixis\Girder5\luascript\DeviceManager.lua :550>
...
[C]: in function `xpcall'
...ogram Files\Promixis\Girder5\luascript\Protected.lua:113 : in function `protect'
...ogram Files\Promixis\Girder5\luascript\Protected.lua:117 : in function `Protect'
...Girder5\luascript\DeviceManager/Providers/Simple.lua:56: in function `DeviceCommand'
...is\Girder5\luascript\DeviceManager/Providers/X10.lua:285: in function `DeviceCommand'
...is\Girder5\luascript\DeviceManager/Devices/Basic.lua:588: in function `ControlAction'
...s\Girder5\luascript\DeviceManager/Controls/Basic.lua:335: in function <...s\Girder5\luascript\DeviceManager/Controls/Basic.lua:327>
(tail call): ?
(tail call): ?
...is\Girder5\/plugins/treescript/Device Manager UI.lua:1236: in function <...is\Girder5\/plugins/treescript/Device Manager UI.lua:1184>
Rob H
December 31st, 2006, 10:40 AM
Ah, mea culpa, should be controlid in the parameter list rather than controlId.
mhwlng
December 31st, 2006, 10:54 AM
ah yes, of course...
note that, to make it work, I had to change :
if control:IsType('Security\\Sensor') then
print (path);
end
to
if control:IsType('Sensor') then
print (path);
end
Thanks a lot for your help Rob, I really appreciate it !!!
Marcel
Rob H
December 31st, 2006, 11:07 AM
Ah, so it is - in DeviceManager\Controls\Display.lua - didn't think to check.
mhwlng
January 7th, 2007, 04:13 AM
ok... next variation
the motion detector actually sends an x10 'ON' message every time you move (and only if you don't move for x minutes, it sends an 'OFF' message.)
the DM only sends messages when the state changes, so moving around only results in ONE DM message.
I now want my callback called every time the x10 'ON' message is received ?
I assume that is only possible by handling the raw x10 data and not use the DM for that ?
is this the best way to do this ?
function X10DeviceManagerEvent (event,xdevice)
print (event);
table.print (xdevice);
end
X10:Subscribe (X10DeviceManagerEvent)
xdevice, just contains the location and name
["Location"] = "office",
["Name"] = "motion 10",
I'm not sure how to convert that to the regular DM path
SERVER\X10\B10
Marcel
Rob H
January 7th, 2007, 05:14 AM
That's strange, I would have expected to see HC and UC properties in the xdevice as well
mhwlng
January 7th, 2007, 05:24 AM
ah yes,
I missed that :
["HC"] = "C",
["UC"] = 10,
thanks,
Marcel
mhwlng
January 7th, 2007, 07:07 AM
In case anybody is interested...
Here's my solution for using motion detectors, to switch on/off lights in my flat automatically...
First of all, you can't simply link a few lights to a motion detector!
If you don't move while watching tv or sitting at the computer, then the lights go off after a while and you have to wave your arms every couple of minutes....
I have 4 'real' X10 motion detectors with housecode 'B'
I created another 4 'fake' X10 motion detectors with housecode 'C'
I linked the lights to the 'fake' motion detectors.
If a 'real' motion detector triggers, then I also trigger the 'fake' motion detector, turning the lights on in the relevant room..
If a 'real' motion detector doesn't sense motion, then I only trigger the 'fake' motion detector (and switch off the lights) if the last movement detected was in ANOTHER room.. So the lights stay on if I don't move...
(note that this solution doesn't work properly if you have pets/family members moving around in another room, while you are watching tv, while not moving, in the living room, so it's a solution for bachelors only :-) )
require 'DeviceManager.Devices'
require 'DeviceManager.Controls'
local ActionSource = 'Action'
local function HandleDMEvent( event, path, controlid )
if event == DeviceManager.Devices.Events.Condition then
local device = DeviceManager:GetDeviceUsingPath(path)
local control = device:GetControl (controlid)
if control:IsType('Sensor') then
if path == "SERVER\\X10\\C9" then -- room state bedroom (fake motion detector)
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A2')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A15')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
elseif path == "SERVER\\X10\\C10" then -- room state office (fake motion detector)
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A13')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
elseif path == "SERVER\\X10\\C11" then -- room state hallway (fake motion detector)
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A6')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
elseif path == "SERVER\\X10\\C12" then -- room state living room (fake motion detector)
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A7')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then -- no motion
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A8')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then -- no motion
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
local Device = DeviceManager:GetDeviceUsingPath ('SERVER\\X10\\A5')
local Control = Device:GetControl("Switch")
if (control:GetValue ()=="Ready") then -- no motion
Control:SetValue ('Off',ActionSource)
else
Control:SetValue ('On',ActionSource)
end
end
end
end
end
--force device manager event
X10:ReceiveEvent ("C","9","OFF") -- fake 'room state' motion detector bedroom
X10:ReceiveEvent ("C","10","OFF") -- fake 'room state' motion detector office
X10:ReceiveEvent ("C","11","OFF") -- fake 'room state' motion detector hallway
X10:ReceiveEvent ("C","12","OFF") -- fake 'room state' motion detector living room
HandleDMEvent(DeviceManager.Devices.Events.Conditi on,"SERVER\\X10\\C9","Condition");
HandleDMEvent(DeviceManager.Devices.Events.Conditi on,"SERVER\\X10\\C10","Condition");
HandleDMEvent(DeviceManager.Devices.Events.Conditi on,"SERVER\\X10\\C11","Condition");
HandleDMEvent(DeviceManager.Devices.Events.Conditi on,"SERVER\\X10\\C12","Condition");
X10:ReceiveEvent ("B","9","OFF") -- bedroom
X10:ReceiveEvent ("B","10","OFF") -- office
X10:ReceiveEvent ("B","11","OFF") -- hallway
X10:ReceiveEvent ("B","12","OFF") -- living room
DeviceManager:Subscribe(function (...) HandleDMEvent(unpack(arg)) end)
local switchrequest = {}-- 1 == **must** switch on, 2 == **want** to switch off
local lastmovement = 0
local function X10DeviceManagerEvent (event,xdevice)
if (event =="Condition") and (xdevice ~= nil) then
if (xdevice.HC=="B") then -- any 'real' motion detector (housecode B)
if (xdevice.Level==100) then -- motion detected
switchrequest [xdevice.UC] = 1
lastmovement = xdevice.UC
else
switchrequest [xdevice.UC] = 2
end
end
end
for UC in pairs (switchrequest) do
if (switchrequest[UC] == 1) then
switchrequest[UC] = 0;
X10:ReceiveEvent ("C",tostring(UC),"ON") -- fake 'room state' motion detector
elseif (switchrequest[UC] == 2) and (lastmovement > 0) and (lastmovement ~= UC) then
switchrequest[UC] = 0;
X10:ReceiveEvent ("C",tostring(UC),"OFF")
end
end
end
X10:Subscribe (X10DeviceManagerEvent)
note that this bit in the middle :
X10:ReceiveEvent ("C","9","OFF") -- fake 'room state' motion detector bedroom
...
HandleDMEvent(DeviceManager.Devices.Events.Conditi on,"SERVER\\X10\\C9","Condition");
...
X10:ReceiveEvent ("B","9","OFF") -- bedroom
is because all states are remembered when shutting down girder (also 509)
above code fragment resets everything to a know state when girder is started (and turns all the lights off when girder is started!).
Note that code still needs to be added for the situation when you want to go to bed (disable motion detector in the bedroom) or leave the house (switch off lights in the hallway) !
above X10 stuff is displayed in NR using svg (see picture in this thread http://www.promixis.com/forums/showthread.php?t=15702 )
Marcel
danward79
January 7th, 2007, 07:24 AM
That is a nice solution Marcel. I was wonder how this could be done.
Any ideas on how to modify this for multiple person occupancy?
mhwlng
January 7th, 2007, 07:30 AM
That is a nice solution Marcel. I was wonder how this could be done.
Yeah, I'm trending the output from my rfxcom power meter, (kWh converted to cold-hard-cash), and I see an immediate benefit
Any ideas on how to modify this for multiple person occupancy?
I can't think of a fool-proof way using regular motion detectors....
Marcel
mhwlng
January 14th, 2007, 07:51 AM
Another thing that is easy to add is :
Switch on a different number of lights in the living room, depending on how sunny it is outside.
I use a 1-wire Solar Energy (W/m^2) meter from http://hobby-boards.com that is supported by my 1-wire plugin.
(I suppose that you could make sunlight dependent dimming as well, but I don't use that X10 feature myself)
Marcel
danward79
January 14th, 2007, 09:01 AM
You could use the solar energy board to adjust the ambient light zones.
mhwlng
January 14th, 2007, 09:07 AM
excuse my ignorance..
what's an ambient light zone ?
Marcel
danward79
January 14th, 2007, 09:22 AM
settings > scheduler > Light zones.
Set up your zones.
Then use Actions > Ambient Light Level, to set and adjust your zones with the data from your sensor.
I build a sensor in the summer which interfaces via serial to girder. I am thinking of getting a solar hobby board now thou
mhwlng
January 14th, 2007, 09:43 AM
I'm not sure, how I would use 'light zones' for what I want to accomplish :
i.e.
I enter a room,
* the motion sensor triggers
** if light level > x I switch on light 1,2
** if light level < x I switch on light 1,2,3,4,5
I leave the room,
* the motion sensor changes back to 'ready'
** all lights go off.
also, note that :
I hardly ever use any actions anywhere in my gml file :
-I just define a bunch of timers/threads/callbacks via ScriptEnable/FileLoaded events to handle 'stuff' (1wire/x10/DM/weather/rss/xAP/callerid/trend/etc.)
-I have some communication server events triggered by NR
that's it, I use no x10/DM/etc. events, no conditionals, etc..
And I don't write 'big' lua script files inside the girder editor either...
(most of my lua code is in external lua files)
Marcel
danward79
January 14th, 2007, 10:29 AM
ah, in that case they will probably be no use to you.
If you have standard actions and combine the ambient conditional you would find it useful.
honnt
May 13th, 2007, 07:38 PM
Replying here as this mentions the Ambient conditional...
Can't seem to get the conditional to work properly. I've got everything enabled properly, and see the Ambient events in the logger, etc., but the conditional doesn't seem to block the action if it returns false.
i.e. I have a macro to turn on some lights in the kitchen upon an X10 motion detector triggering, but only want it to actually send the X10 command for the lights if the Ambient light level is darker or equal to Little Dark. With the conditional in place, the macro completes regardless of the Ambient light level. To test the macro itself, I've used a Time of Day conditional, and it blocks/allows the macro as I expect.
Is anyone else using the Ambient light conditional successfully?
Rob H
May 14th, 2007, 01:51 AM
Are you testing this using the motion detector or by using F5 (or the lightning flash button)?
honnt
May 14th, 2007, 03:30 AM
Are you testing this using the motion detector or by using F5 (or the lightning flash button)?
Motion detector
Rob H
May 14th, 2007, 03:39 AM
Can you copy that node (complete with the conditional) to its own GML and upload it here so Mike or I can see what's going on.
honnt
May 14th, 2007, 04:50 AM
You bet... attached. Thanks for looking at this.
Rob H
May 14th, 2007, 08:27 AM
If you edit the conditional, does the 'Current result is' field show what you would expect for a given time of day?
honnt
May 14th, 2007, 10:05 AM
Yes. Also, I have other actions triggered by SunRiseSunSet events, and those are triggered as expected, and I see Ambient lighting events in the logger at appropriate times, the only thing that I can't seem to get right is the conditional itself.
Thanks again, Rob, for looking into this....
Rob H
May 14th, 2007, 10:40 AM
I can confirm that it's not working properly, an action guarded by the Ambient light conditional is always triggered. Not sure why yet, but looking for the problem.
Rob H
May 14th, 2007, 11:24 AM
Here's a replacement for luascript\DUI\ConditionalBase.lua that should fix the problem.
honnt
May 14th, 2007, 05:37 PM
You rock, Rob....works as advertised. Thanks a lot!
Promixis
May 14th, 2007, 07:30 PM
You rock, Rob....works as advertised. Thanks a lot!
Yup, he rocks. I knew that one was out there - just hadn't found it :(
vBulletin® v3.7.4, Copyright ©2000-2008, Jelsoft Enterprises Ltd.