Added faraway roam notification

This commit is contained in:
tidwall 2018-08-14 10:48:28 -07:00
parent b3d3be7e76
commit 0e1ae7b4bc
2 changed files with 130 additions and 59 deletions

View File

@ -47,7 +47,10 @@ func appendHookDetails(b []byte, hookName string, metas []FenceMeta) []byte {
func hookJSONString(hookName string, metas []FenceMeta) string { func hookJSONString(hookName string, metas []FenceMeta) string {
return string(appendHookDetails(nil, hookName, metas)) return string(appendHookDetails(nil, hookName, metas))
} }
func fenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, metas []FenceMeta, details *commandDetailsT) []string { func fenceMatch(
hookName string, sw *scanWriter, fence *liveFenceSwitches,
metas []FenceMeta, details *commandDetailsT,
) []string {
if details.command == "drop" { if details.command == "drop" {
return []string{ return []string{
`{"command":"drop"` + hookJSONString(hookName, metas) + `{"command":"drop"` + hookJSONString(hookName, metas) +
@ -72,23 +75,30 @@ func fenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, metas
} }
} }
if details.command == "del" { if details.command == "del" {
if fence.roam.on {
if fence.roam.nearbys != nil {
delete(fence.roam.nearbys, details.id)
if len(fence.roam.nearbys) == 0 {
fence.roam.nearbys = nil
}
}
}
return []string{ return []string{
`{"command":"del"` + hookJSONString(hookName, metas) + `,"id":` + jsonString(details.id) + `{"command":"del"` + hookJSONString(hookName, metas) +
`,"id":` + jsonString(details.id) +
`,"time":` + jsonTimeFormat(details.timestamp) + `}`, `,"time":` + jsonTimeFormat(details.timestamp) + `}`,
} }
} }
var roamkeys, roamids []string var roamNearbys, roamFaraways []roamMatch
var roammeters []float64
var roamobjs []geojson.Object
var detect = "outside" var detect = "outside"
if fence != nil { if fence != nil {
if fence.roam.on { if fence.roam.on {
if details.command == "set" { if details.command == "set" {
roamkeys, roamids, roammeters, roamobjs = roamNearbys, roamFaraways =
fenceMatchRoam(sw.c, fence, details.key, fenceMatchRoam(sw.c, fence, details.key,
details.id, details.obj) details.id, details.obj)
} }
if len(roamids) == 0 || len(roamids) != len(roamkeys) { if len(roamNearbys) == 0 && len(roamFaraways) == 0 {
return nil return nil
} }
detect = "roam" detect = "roam"
@ -202,7 +212,6 @@ func fenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, metas
fence.groups[groupkey] = group fence.groups[groupkey] = group
} }
} }
var msgs []string var msgs []string
if fence.detect == nil || fence.detect[detect] { if fence.detect == nil || fence.detect[detect] {
if len(res) > 0 && res[0] == '{' { if len(res) > 0 && res[0] == '{' {
@ -224,48 +233,14 @@ func fenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, metas
case "roam": case "roam":
if len(msgs) > 0 { if len(msgs) > 0 {
var nmsgs []string var nmsgs []string
msg := msgs[0][:len(msgs[0])-1] for i := range roamNearbys {
for i, id := range roamids { nmsg := extendRoamMessage(sw, fence,
var nmsg []byte "nearby", msgs[0], roamNearbys[i])
nmsg = append(nmsg, msg...) nmsgs = append(nmsgs, string(nmsg))
nmsg = append(nmsg, `,"nearby":{"key":`...) }
nmsg = appendJSONString(nmsg, roamkeys[i]) for i := range roamFaraways {
nmsg = append(nmsg, `,"id":`...) nmsg := extendRoamMessage(sw, fence,
nmsg = appendJSONString(nmsg, id) "faraway", msgs[0], roamFaraways[i])
nmsg = append(nmsg, `,"object":`...)
nmsg = append(nmsg, roamobjs[i].JSON()...)
nmsg = append(nmsg, `,"meters":`...)
nmsg = append(nmsg, strconv.FormatFloat(roammeters[i], 'f', -1, 64)...)
if fence.roam.scan != "" {
nmsg = append(nmsg, `,"scan":[`...)
col := sw.c.getCol(roamkeys[i])
if col != nil {
obj, _, ok := col.Get(id)
if ok {
nmsg = append(nmsg, `{"id":`+jsonString(id)+`,"self":true,"object":`+obj.JSON()+`}`...)
}
pattern := id + fence.roam.scan
iterator := func(oid string, o geojson.Object, fields []float64) bool {
if oid == id {
return true
}
if matched, _ := glob.Match(pattern, oid); matched {
nmsg = append(nmsg, `,{"id":`+jsonString(oid)+`,"object":`+o.JSON()+`}`...)
}
return true
}
g := glob.Parse(pattern, false)
if g.Limits[0] == "" && g.Limits[1] == "" {
col.Scan(false, iterator)
} else {
col.ScanRange(g.Limits[0], g.Limits[1], false, iterator)
}
}
nmsg = append(nmsg, ']')
}
nmsg = append(nmsg, '}')
nmsg = append(nmsg, '}')
nmsgs = append(nmsgs, string(nmsg)) nmsgs = append(nmsgs, string(nmsg))
} }
msgs = nmsgs msgs = nmsgs
@ -274,6 +249,63 @@ func fenceMatch(hookName string, sw *scanWriter, fence *liveFenceSwitches, metas
return msgs return msgs
} }
func extendRoamMessage(
sw *scanWriter, fence *liveFenceSwitches,
kind string, baseMsg string, match roamMatch,
) string {
// hack off the last '}'
nmsg := []byte(baseMsg[:len(baseMsg)-1])
nmsg = append(nmsg, `,"`+kind+`":{"key":`...)
nmsg = appendJSONString(nmsg, fence.roam.key)
nmsg = append(nmsg, `,"id":`...)
nmsg = appendJSONString(nmsg, match.id)
nmsg = append(nmsg, `,"object":`...)
nmsg = append(nmsg, match.obj.JSON()...)
nmsg = append(nmsg, `,"meters":`...)
nmsg = strconv.AppendFloat(nmsg,
math.Floor(match.meters*1000)/1000, 'f', -1, 64)
if fence.roam.scan != "" {
nmsg = append(nmsg, `,"scan":[`...)
col := sw.c.getCol(fence.roam.key)
if col != nil {
obj, _, ok := col.Get(match.id)
if ok {
nmsg = append(nmsg,
`{"id":`+jsonString(match.id)+
`,"self":true,"object":`+obj.JSON()+`}`...)
}
pattern := match.id + fence.roam.scan
iterator := func(
oid string, o geojson.Object, fields []float64,
) bool {
if oid == match.id {
return true
}
if matched, _ := glob.Match(pattern, oid); matched {
nmsg = append(nmsg,
`,{"id":`+jsonString(oid)+
`,"object":`+o.JSON()+`}`...)
}
return true
}
g := glob.Parse(pattern, false)
if g.Limits[0] == "" && g.Limits[1] == "" {
col.Scan(false, iterator)
} else {
col.ScanRange(g.Limits[0], g.Limits[1],
false, iterator)
}
}
nmsg = append(nmsg, ']')
}
nmsg = append(nmsg, '}')
// re-add the last '}'
nmsg = append(nmsg, '}')
return string(nmsg)
}
func makemsg( func makemsg(
command, group, detect, hookName string, command, group, detect, hookName string,
metas []FenceMeta, key string, t time.Time, tail string, metas []FenceMeta, key string, t time.Time, tail string,
@ -326,31 +358,63 @@ func fenceMatchObject(fence *liveFenceSwitches, obj geojson.Object) bool {
func fenceMatchRoam( func fenceMatchRoam(
c *Controller, fence *liveFenceSwitches, c *Controller, fence *liveFenceSwitches,
tkey, tid string, obj geojson.Object, tkey, tid string, obj geojson.Object,
) (keys, ids []string, meterss []float64, objs []geojson.Object) { ) (nearbys, faraways []roamMatch) {
col := c.getCol(fence.roam.key) col := c.getCol(fence.roam.key)
if col == nil { if col == nil {
return return
} }
p := obj.CalculatedPoint() p := obj.CalculatedPoint()
var prevNearbys []roamMatch
if fence.roam.nearbys != nil {
prevNearbys = fence.roam.nearbys[tid]
}
col.Nearby(0, p.Y, p.X, fence.roam.meters, math.Inf(-1), math.Inf(+1), col.Nearby(0, p.Y, p.X, fence.roam.meters, math.Inf(-1), math.Inf(+1),
func(id string, obj geojson.Object, fields []float64) bool { func(id string, obj geojson.Object, fields []float64) bool {
var match bool var idMatch bool
if id == tid { if id == tid {
return true // skip self return true // skip self
} }
if fence.roam.pattern { if fence.roam.pattern {
match, _ = glob.Match(fence.roam.id, id) idMatch, _ = glob.Match(fence.roam.id, id)
} else { } else {
match = fence.roam.id == id idMatch = fence.roam.id == id
} }
if match { if !idMatch {
keys = append(keys, fence.roam.key) return true
ids = append(ids, id)
meterss = append(meterss, obj.CalculatedPoint().DistanceTo(p))
objs = append(objs, obj)
} }
match := roamMatch{
id: id,
obj: obj,
meters: obj.CalculatedPoint().DistanceTo(p),
}
for i := 0; i < len(prevNearbys); i++ {
if prevNearbys[i].id == match.id {
prevNearbys[i] = prevNearbys[len(prevNearbys)-1]
prevNearbys = prevNearbys[:len(prevNearbys)-1]
i--
break
}
}
nearbys = append(nearbys, match)
return true return true
}, },
) )
faraways = prevNearbys
for i := 0; i < len(faraways); i++ {
faraways[i].meters = faraways[i].obj.CalculatedPoint().DistanceTo(p)
}
if len(nearbys) == 0 {
if fence.roam.nearbys != nil {
delete(fence.roam.nearbys, tid)
if len(fence.roam.nearbys) == 0 {
fence.roam.nearbys = nil
}
}
} else {
if fence.roam.nearbys == nil {
fence.roam.nearbys = make(map[string][]roamMatch)
}
fence.roam.nearbys[tid] = nearbys
}
return return
} }

View File

@ -35,6 +35,13 @@ type roamSwitches struct {
pattern bool pattern bool
meters float64 meters float64
scan string scan string
nearbys map[string][]roamMatch
}
type roamMatch struct {
id string
obj geojson.Object
meters float64
} }
func (s liveFenceSwitches) Error() string { func (s liveFenceSwitches) Error() string {