8ea269359cf9522f385812daed454ee13365847e
[svn42.git] / go / r3-eventbroker_zmq / presence.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6         "time"
7         //~ "./brain"
8         pubsub "github.com/tuxychandru/pubsub"
9         r3events "svn.spreadspace.org/realraum/go.svn/r3events"
10 )
11
12 func MetaEventRoutine_Presence(ps *pubsub.PubSub, movement_timeout, button_timeout int64) {
13         var last_door_cmd *r3events.DoorCommandEvent
14         var last_presence bool
15         var last_event_indicating_presence, last_frontlock_use, last_manual_lockhandling int64
16         var front_locked, front_shut, back_shut bool = true, true, true
17
18         events_chan := ps.Sub("door", "doorcmd", "buttons", "movement")
19         defer ps.Unsub(events_chan, "door", "doorcmd", "buttons", "movement")
20
21         for event := range events_chan {
22                 Debug_.Printf("Presence prior: %t : %T %+v", last_presence, event, event)
23                 new_presence := last_presence
24                 ts := time.Now().Unix()
25                 evnt_type := r3events.NameOfStruct(event)
26                 switch evnt := event.(type) {
27                 case r3events.SomethingReallyIsMoving:
28                         if evnt.Movement {
29                                 //ignore movements that happened just after locking door
30                                 if (evnt.Ts - last_event_indicating_presence) > movement_timeout {
31                                         new_presence = true
32                                 }
33                                 last_event_indicating_presence = evnt.Ts
34                         } else {
35                                 if last_presence {
36                                         Syslog_.Printf("Presence: Mhh, SomethingReallyIsMoving{%+v} received but presence still true. Quite still a bunch we have here.", evnt)
37                                 }
38                                 if front_locked && front_shut && back_shut && evnt.Confidence >= 90 && last_event_indicating_presence > 1800 && (last_door_cmd == nil || (last_door_cmd.Using != "Button" && last_door_cmd.Ts >= last_manual_lockhandling)) {
39                                         new_presence = false
40                                 }
41                         }
42                 case r3events.BoreDoomButtonPressEvent:
43                         new_presence = true
44                         last_event_indicating_presence = evnt.Ts
45                 case r3events.DoorCommandEvent:
46                         last_door_cmd = &evnt
47                 case r3events.DoorManualMovementEvent:
48                         last_manual_lockhandling = evnt.Ts
49                         last_event_indicating_presence = evnt.Ts
50                 case r3events.DoorLockUpdate:
51                         front_locked = evnt.Locked
52                         last_frontlock_use = evnt.Ts
53                         last_event_indicating_presence = evnt.Ts
54                 case r3events.DoorAjarUpdate:
55                         if front_shut == false && evnt.Shut && front_locked && evnt.Ts-last_frontlock_use > 2 {
56                                 Syslog_.Print("Presence: ignoring frontdoor ajar event, since obviously someone is fooling around with the microswitch while the door is still open")
57                         } else {
58                                 front_shut = evnt.Shut
59                         }
60                         last_event_indicating_presence = evnt.Ts
61                 case r3events.BackdoorAjarUpdate:
62                         back_shut = evnt.Shut
63                         last_event_indicating_presence = evnt.Ts
64                 }
65
66                 any_door_unlocked := (front_locked == false)
67                 any_door_ajar := !(front_shut && back_shut)
68
69                 if new_presence != last_presence {
70                         //... skip state check .. we had a definite presence event
71                 } else if any_door_unlocked || any_door_ajar {
72                         new_presence = true
73                 } else if last_door_cmd != nil && (last_door_cmd.Using == "Button" || last_door_cmd.Ts < last_manual_lockhandling) {
74                         // if last_door_cmd is set then: if either door was closed using Button or if time of manual lock movement is greater (newer) than timestamp of last_door_cmd
75                         new_presence = true
76                 } else if evnt_type == "DoorCommandEvent" {
77                         //don't set presence to false for just a door command, wait until we receive a LockUpdate
78                         //(fixes "door manually locked -> door opened with card from outside -> nobody present status sent since door is locked and we havent received door unloked event yet"-problem)
79                         continue
80                 } else {
81                         new_presence = false
82                 }
83                 //~ Debug_.Printf("Presence: new: %s , last:%s", new_presence, last_presence)
84                 if new_presence != last_presence {
85                         last_presence = new_presence
86                         ps.Pub(r3events.PresenceUpdate{new_presence, ts}, "presence")
87                         Syslog_.Printf("Presence: %t", new_presence)
88                 }
89         }
90 }