mirror of https://github.com/tidwall/tile38.git
Added faraway roam notification
This commit is contained in:
parent
b3d3be7e76
commit
0e1ae7b4bc
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue