who
[svn42.git] / go / r3-eventbroker_zmq / metamovement.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6     "time"
7     pubsub "github.com/tuxychandru/pubsub"
8     "container/ring"
9     r3events "svn.spreadspace.org/realraum/go.svn/r3events"
10     )
11
12
13 /// Movement Meta Event Injector:
14 ///     threshold number of movements within gran_duration*granularity seconds -> SomethingReallyIsMoving{True}
15 ///     No movement within 3 hours but movement within the last 6 hours -> SomethingReallyIsMoving{False}
16 ///
17 /// Thus SomethingReallyIsMoving{True} fires regularly, but at most every gran_duration seconds
18 /// While SomethingReallyIsMoving{False} fires only once to assure us that everybody might really be gone
19
20
21 func MetaEventRoutine_Movement(ps *pubsub.PubSub, granularity, gran_duration int , threshold uint32) {
22     var last_movement,last_movement1,last_movement2,last_movement3 int64
23     var confidence uint8
24     movement_window := ring.New(granularity+1)
25     events_chan := ps.Sub("movement")
26     defer ps.Unsub(events_chan, "movement")
27     myticker := time.NewTicker(time.Duration(gran_duration) * time.Second)
28
29     for { select {
30         case event := <- events_chan:
31             switch event.(type) {
32                 case r3events.MovementSensorUpdate:
33                     if movement_window.Value == nil {
34                         movement_window.Value = uint32(1)
35                     } else {
36                         movement_window.Value = uint32(movement_window.Value.(uint32)  + 1)
37                     }
38             }
39         case gots := <- myticker.C:
40             ts := gots.Unix()
41             movement_window.Prev().Value = (uint32) (0)
42             movement_window = movement_window.Next()
43             var movsum uint32 = 0
44             movement_window.Do(func(v interface{}){if v != nil {movsum += v.(uint32)}})
45             if movsum > threshold {
46                 confidence = uint8(movsum)
47                 ps.Pub( r3events.SomethingReallyIsMoving{true, confidence ,ts}, "movement")
48                 last_movement = ts
49                 last_movement1 = ts
50                 last_movement2 = ts
51                 last_movement3 = ts
52             }
53             // this sucks.....
54             if last_movement > 0 && ts - last_movement < 3600*6 {
55                 if ts - last_movement > 3600*3 {
56                     last_movement = 0
57                     ps.Pub( r3events.SomethingReallyIsMoving{false,99,ts}, "movement")
58                 } else if ts - last_movement > 3600 && last_movement3 > 0 {
59                     last_movement3 = 0
60                     ps.Pub( r3events.SomethingReallyIsMoving{false,50,ts}, "movement")
61                 } else if ts - last_movement > 1800 && last_movement2 > 0 {
62                     last_movement2 = 0
63                     ps.Pub( r3events.SomethingReallyIsMoving{false,20,ts}, "movement")
64                 } else if ts - last_movement > 120 && last_movement1 > 0 {
65                     last_movement1 = 0
66                     ps.Pub( r3events.SomethingReallyIsMoving{false,5,ts}, "movement")
67                 }
68             }
69     } }
70 }