The question in the title of this post can easily be answered by a person – just speak it out loud enough and listen for an answer. For a Domotica system, providing the answer can be a bit more complicated though.
OK, you’ve got motion sensors, but that doesn’t help much during the night. But there’s also an alarm system, of which the status (Off, Arm Home, Arm Away) can help. But not if someone forgot to arm it. Even monitoring water usage can help – everyone has to go to the toilet some time, right? And even leaving outside doors open may be interpreted as someone being at home, right? Another ‘input’ could be switching to another TV channel or a change in volume level of radio/TV. The same goes for the media player playing a movie. Or a change in Thermostat setpoint. Or pinging a smartphone that succeeds. And … so on. The more ‘input’ your Domotica system has, the more accurate the answer to the question will become.
And that’s what I’m facing right now: the lack of a single indicator that tells me whether there’s somebody at home or not. Based on 1160 different ‘inputs’ I (my system) should be able to produce something reliable enough to use in events, don’t you think?
But how do I do that? For that I would need ‘something’ to monitor a subset of all the available device values that are in my system. The boiler water pressure won’t be useful, but a motion sensor probably will be. And that ‘something’ should be able to have a ‘yes’ or a ‘no’ (or a ‘maybe’) as output: ‘human presence‘ .
Since nearly everything in my Domotica system is based on Interfaces, Devices and Events, a Device sounds like the best choice to me. A virtual one, in this case. I already started using virtual devices 3 years ago, so the concept is not new to me. But until now, it have been the Events that operated as the ‘glue’ between all the Interfaces and Devices. Now it’s time for something different.
I don’t want to create a static Event that takes care of this ‘human presence’ indicator getting the right value. No, somehow that doesn’t feel right, cause that would mean I’d have to change the Event when a new motion sensor is added to the system, or any other device that can help me to detect whether somebody’s at home. No way, I hate to do those kind of ‘internal’ housekeeping tasks, my system should adapt itself to a new motion sensor!
What I really need is inter-device notifications, as in Device A being notified of a value change of Device B. And Device A should be able to Subscribe & Unsubscribe itself from value changes of Device B (and C, D, …) in a dynamic fashion – I don’t want anything hard coded stuff in my system, cause sooner or later this will create an inflexible system and even more work.
Another thing that has to be done is that each device (value) has to get an indicator whether it can be used as ‘presence’ information or not.
For example, I have 3 RFXMeter devices in use (in fact just simple pulse counters) for gas, water and power consumption. Gas and power consumption are more or less independent of human presence, but water usage isn’t. For now that is, cause this can change when I’ve built an automatic irrigation system… But the example shows that a device type doesn’t say anything about it being helpful in determining human presence. Nor can I use all the motion sensors, cause some of them could be outside; so I definitely need a ‘can indicate presence’ attribute for every device value instance.
It may sound like this could take some work to accomplish but it’s not that hard actually.
type TDeviceValueChangeNotification = TNotifyEvent; PDeviceValueChangeNotification = ^TDeviceValueChangeNotification; TDeviceValue=class(TObject) private ... ValueChangeSubscriptions:TList; ... end; procedure TDeviceValue.RegisterToValueChange(NotifyProc:TDeviceValueChangeNotification); var N: PDeviceValueChangeNotification; begin if Assigned(ValueChangeSubscriptions) then begin New(N); N^ := NotifyProc; ValueChangeSubscriptions.Add(N); end; end; procedure TDeviceValue.NotifyValueChangeSubscribers; var i: integer; N: TDeviceValueChangeNotification; begin for i:=0 to pred(ValueChangeSubscriptions.Count) do begin N := TDeviceValueChangeNotification(ValueChangeSubscriptions.Items[i]^); N(Self); end; end; procedure THomeStatus.OnOtherDeviceValueChange(Sender:TObject); var aDeviceValue:TDeviceValue; begin aDeviceValue := TDeviceValue(Sender); Log('Device '+Self.ClassName+':'+Self.Address+ ' was notified of a value change by '+aDeviceValue.ID); Log('Device Value '+aDeviceValue.ID+' hasn''t changed since ' +IntToStr(aDeviceValue.SecondsSinceLastChange)+' seconds.'); Log('The current value is :'+aDeviceValue.AsString); ... end; if DeviceValuesList.Objects[i].canDetectHumanPresence then DeviceValuesList.Objects[i].RegisterToValueChange(OnOtherDeviceValueChange);
Lines 1..10 define a new type for the kind of Notification I need for this and shows how to expand a DeviceValue with a list of Subscriptions.
After that the method to Register a new Subscriber and the method that has to be called whenever a Devicevalue has changed.
The last method shows the beauty of it all – the DeviceValue object where the change took place (A) is completely accessible from the other DeviceValue object (B) that subscribed to that first DeviceValue (A). Simple, very powerful and always available, whether the Devicevalue is used for temperature, a light switch or whatever.