button
[svn42.git] / go / r3-eventbroker_zmq / presence.go
index 953af11..3677b27 100644 (file)
@@ -6,67 +6,73 @@ import (
     "time"
     //~ "./brain"
     pubsub "github.com/tuxychandru/pubsub"
+    r3events "svn.spreadspace.org/realraum/go.svn/r3events"
     )
 
-type PresenceUpdate struct {
-    Present bool
-    Ts int64
-}
-
-type doorstate struct {
-    locked bool
-    shut bool
-}
-
-func MetaEventRoutine_Presence(ps *pubsub.PubSub) {
-    //~ var last_door_cmd *DoorCommandEvent
+func MetaEventRoutine_Presence(ps *pubsub.PubSub, movement_timeout, button_timeout int64) {
+    var last_door_cmd *r3events.DoorCommandEvent
     var last_presence bool
-    var last_movement, last_buttonpress int64
-    doorstatemap := make(map[byte]doorstate,1)
+    var last_event_indicating_presence, last_frontlock_use int64
+    var front_locked, front_shut, back_shut bool = true, true, true
 
     events_chan := ps.Sub("door", "doorcmd", "buttons", "movement")
-    
+    defer ps.Unsub(events_chan, "door", "doorcmd", "buttons", "movement")
+
     for event := range(events_chan) {
+        Debug_.Printf("Presence prior: %t : %T %+v", last_presence, event, event)
         new_presence := last_presence
         ts := time.Now().Unix()
         switch evnt := event.(type) {
-            case SomethingReallyIsMoving:
+            case r3events.SomethingReallyIsMoving:
                 if evnt.Movement {
-                    last_movement = evnt.Ts
+                    //ignore movements that happened just after locking door
+                    if (evnt.Ts - last_event_indicating_presence) > movement_timeout {
+                        new_presence = true
+                    }
+                    last_event_indicating_presence = evnt.Ts
                 } else {
-                    last_movement = 0
+                    if last_presence { Syslog_.Printf("Presence: Mhh, SomethingReallyIsMoving{%+v} received but presence still true. Quite still a bunch we have here.", evnt) }
+                    if front_locked && front_shut && back_shut && evnt.Confidence >= 20 && last_event_indicating_presence > 1800 {
+                        new_presence = false
+                    }
                 }
-            case ButtonPressUpdate:
-                last_buttonpress = evnt.Ts
+            case r3events.BoreDoomButtonPressEvent:
                 new_presence = true
-            //~ case DoorCommandEvent:
-                //~ last_door_cmd = &evnt
-            case DoorLockUpdate:
-                doorstatemap[evnt.DoorID]=doorstate{locked:evnt.Locked, shut:doorstatemap[evnt.DoorID].shut}
-            case DoorAjarUpdate:
-                doorstatemap[evnt.DoorID]=doorstate{locked:doorstatemap[evnt.DoorID].locked, shut:evnt.Shut}
-        }
-        
-        any_door_unlocked := false
-        any_door_ajar := false
-        for _, ds := range(doorstatemap) {
-            if ds.locked == false {any_door_unlocked = true }
-            if ds.shut == false {any_door_ajar = true }
+                last_event_indicating_presence = evnt.Ts
+            case r3events.DoorCommandEvent:
+                last_door_cmd = &evnt
+            case r3events.DoorLockUpdate:
+                front_locked = evnt.Locked
+                last_frontlock_use = evnt.Ts
+                last_event_indicating_presence = evnt.Ts
+            case r3events.DoorAjarUpdate:
+                if front_shut == false && evnt.Shut && front_locked && evnt.Ts - last_frontlock_use > 2 {
+                    Syslog_.Print("Presence: ignoring frontdoor ajar event, since obviously someone is fooling around with the microswitch while the door is still open")
+                } else {
+                    front_shut = evnt.Shut
+                }
+                last_event_indicating_presence = evnt.Ts
+            case r3events.BackdoorAjarUpdate:
+                back_shut = evnt.Shut
+                last_event_indicating_presence = evnt.Ts
         }
-        
+
+        any_door_unlocked := (front_locked == false)
+        any_door_ajar := ! (front_shut && back_shut)
+
         if new_presence != last_presence {
             //... skip state check .. we had a definite presence event
         } else if any_door_unlocked || any_door_ajar {
             new_presence = true
-        } else if last_movement != 0 || ts - last_buttonpress < 200 {
+        } else if last_door_cmd.Using == "Button" {
             new_presence = true
         } else {
             new_presence = false
         }
-        
+        //~ Debug_.Printf("Presence: new: %s , last:%s", new_presence, last_presence)
         if new_presence != last_presence {
             last_presence = new_presence
-            ps.Pub(PresenceUpdate{new_presence, ts} , "presence")
+            ps.Pub(r3events.PresenceUpdate{new_presence, ts} , "presence")
         }
     }
 }
\ No newline at end of file