From 3a483e55ff57a592d35523a07cefaa380df14f20 Mon Sep 17 00:00:00 2001 From: Josh Baker Date: Tue, 6 Dec 2016 10:30:48 -0700 Subject: [PATCH] Group geofence events Feature request by @huangpeizhi #87 --- controller/bson.go | 45 ++++++++++++++++++++++++++++++++++++++++++++ controller/dev.go | 8 ++++---- controller/fence.go | 27 +++++++++++++++++++++++--- controller/search.go | 1 + 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 controller/bson.go diff --git a/controller/bson.go b/controller/bson.go new file mode 100644 index 00000000..d5a89b76 --- /dev/null +++ b/controller/bson.go @@ -0,0 +1,45 @@ +package controller + +import ( + "crypto/md5" + "crypto/rand" + "encoding/binary" + "encoding/hex" + "io" + "os" + "sync/atomic" + "time" +) + +func bsonID() string { + b := make([]byte, 12) + binary.BigEndian.PutUint32(b, uint32(time.Now().Unix())) + copy(b[4:], bsonMachine) + binary.BigEndian.PutUint32(b[8:], atomic.AddUint32(&bsonCounter, 1)) + binary.BigEndian.PutUint16(b[7:], bsonProcess) + return hex.EncodeToString(b) +} + +var ( + bsonProcess = uint16(os.Getpid()) + bsonMachine = func() []byte { + host, err := os.Hostname() + if err != nil { + b := make([]byte, 3) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + panic("random error: " + err.Error()) + } + return b + } + hw := md5.New() + hw.Write([]byte(host)) + return hw.Sum(nil)[:3] + }() + bsonCounter = func() uint32 { + b := make([]byte, 4) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + panic("random error: " + err.Error()) + } + return binary.BigEndian.Uint32(b) + }() +) diff --git a/controller/dev.go b/controller/dev.go index 6743eac2..c19a860e 100644 --- a/controller/dev.go +++ b/controller/dev.go @@ -104,6 +104,10 @@ func (c *Controller) cmdMassInsert(msg *server.Message) (res string, err error) id := strconv.FormatInt(int64(j), 10) var values []resp.Value if j%8 == 0 { + values = append(values, resp.StringValue("set"), + resp.StringValue(key), resp.StringValue(id), + resp.StringValue("STRING"), resp.StringValue(fmt.Sprintf("str%v", j))) + } else { lat, lon := randMassInsertPosition(minLat, minLon, maxLat, maxLon) values = make([]resp.Value, 0, 16) values = append(values, resp.StringValue("set"), resp.StringValue(key), resp.StringValue(id)) @@ -111,10 +115,6 @@ func (c *Controller) cmdMassInsert(msg *server.Message) (res string, err error) values = append(values, resp.StringValue("FIELD"), resp.StringValue("fname"), resp.FloatValue(rand.Float64()*10)) } values = append(values, resp.StringValue("POINT"), resp.FloatValue(lat), resp.FloatValue(lon)) - } else { - values = append(values, resp.StringValue("set"), - resp.StringValue(key), resp.StringValue(id), - resp.StringValue("STRING"), resp.StringValue(fmt.Sprintf("str%v", j))) } if err := docmd(values); err != nil { log.Fatal(err) diff --git a/controller/fence.go b/controller/fence.go index dc1cad7f..cd05b605 100644 --- a/controller/fence.go +++ b/controller/fence.go @@ -127,25 +127,46 @@ func FenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, detai } sw.mu.Unlock() + if fence.groups == nil { + fence.groups = make(map[string]string) + } + groupkey := details.key + ":" + details.id + var group string + var ok bool + if detect == "enter" { + group = bsonID() + fence.groups[groupkey] = group + } else if detect == "cross" { + group = bsonID() + delete(fence.groups, groupkey) + } else { + group, ok = fence.groups[groupkey] + if !ok { + group = bsonID() + fence.groups[groupkey] = group + } + } + jskey := jsonString(details.key) ores := res msgs := make([]string, 0, 2) if fence.detect == nil || fence.detect[detect] { if strings.HasPrefix(ores, "{") { - res = `{"command":"` + details.command + `","detect":"` + detect + `","hook":` + jshookName + `,"key":` + jskey + `,"time":` + jstime + `,` + ores[1:] + res = `{"command":"` + details.command + `","group":"` + group + `","detect":"` + detect + `","hook":` + jshookName + `,"key":` + jskey + `,"time":` + jstime + `,` + ores[1:] } msgs = append(msgs, res) } switch detect { case "enter": if fence.detect == nil || fence.detect["inside"] { - msgs = append(msgs, `{"command":"`+details.command+`","detect":"inside","hook":`+jshookName+`,"key":`+jskey+`,"time":`+jstime+`,`+ores[1:]) + msgs = append(msgs, `{"command":"`+details.command+`","group":"`+group+`","detect":"inside","hook":`+jshookName+`,"key":`+jskey+`,"time":`+jstime+`,`+ores[1:]) } case "exit", "cross": if fence.detect == nil || fence.detect["outside"] { - msgs = append(msgs, `{"command":"`+details.command+`","detect":"outside","hook":`+jshookName+`,"key":`+jskey+`,"time":`+jstime+`,`+ores[1:]) + msgs = append(msgs, `{"command":"`+details.command+`","group":"`+group+`","detect":"outside","hook":`+jshookName+`,"key":`+jskey+`,"time":`+jstime+`,`+ores[1:]) } + case "roam": if len(msgs) > 0 { var nmsgs []string diff --git a/controller/search.go b/controller/search.go index b339b897..1c809068 100644 --- a/controller/search.go +++ b/controller/search.go @@ -22,6 +22,7 @@ type liveFenceSwitches struct { maxLat, maxLon float64 cmd string roam roamSwitches + groups map[string]string } type roamSwitches struct {