dd2b5f6b6976e67d001a7a090305c3f1a485ec1d
[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         switch evnt := event.(type) {
26             case r3events.SomethingReallyIsMoving:
27                 if evnt.Movement {
28                     //ignore movements that happened just after locking door
29                     if (evnt.Ts - last_event_indicating_presence) > movement_timeout {
30                         new_presence = true
31                     }
32                     last_event_indicating_presence = evnt.Ts
33                 } else {
34                     if last_presence { Syslog_.Printf("Presence: Mhh, SomethingReallyIsMoving{%+v} received but presence still true. Quite still a bunch we have here.", evnt) }
35                     if front_locked && front_shut && back_shut && evnt.Confidence >= 20 && last_event_indicating_presence > 1800 {
36                         new_presence = false
37                     }
38                 }
39             case r3events.BoreDoomButtonPressEvent:
40                 new_presence = true
41                 last_event_indicating_presence = evnt.Ts
42             case r3events.DoorCommandEvent:
43                 last_door_cmd = &evnt
44             case r3events.DoorManualMovementEvent:
45                 last_manual_lockhandling = evnt.Ts
46             case r3events.DoorLockUpdate:
47                 front_locked = evnt.Locked
48                 last_frontlock_use = evnt.Ts
49                 last_event_indicating_presence = evnt.Ts
50             case r3events.DoorAjarUpdate:
51                 if front_shut == false && evnt.Shut && front_locked && evnt.Ts - last_frontlock_use > 2 {
52                     Syslog_.Print("Presence: ignoring frontdoor ajar event, since obviously someone is fooling around with the microswitch while the door is still open")
53                 } else {
54                     front_shut = evnt.Shut
55                 }
56                 last_event_indicating_presence = evnt.Ts
57             case r3events.BackdoorAjarUpdate:
58                 back_shut = evnt.Shut
59                 last_event_indicating_presence = evnt.Ts
60         }
61
62         any_door_unlocked := (front_locked == false)
63         any_door_ajar := ! (front_shut && back_shut)
64
65         if new_presence != last_presence {
66             //... skip state check .. we had a definite presence event
67         } else if any_door_unlocked || any_door_ajar {
68             new_presence = true
69         } else if last_door_cmd.Using == "Button"  || last_door_cmd.Ts < last_manual_lockhandling {
70             new_presence = true
71         } else {
72             new_presence = false
73         }
74         //~ Debug_.Printf("Presence: new: %s , last:%s", new_presence, last_presence)
75         if new_presence != last_presence {
76             last_presence = new_presence
77             ps.Pub(r3events.PresenceUpdate{new_presence, ts} , "presence")
78         }
79     }
80 }