From 2cc088739d78c1916b426802bf0937458928b119 Mon Sep 17 00:00:00 2001 From: Honceriu Tudor Date: Tue, 8 Nov 2022 18:21:56 +0200 Subject: [PATCH 01/11] add Antratek and g62 parser --- receiver/LoraToGPSServer/device/device.go | 193 ++++++++++++++++++-- receiver/LoraToGPSServer/traccar/traccar.go | 8 +- 2 files changed, 177 insertions(+), 24 deletions(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 790dfdc..65f7479 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -63,7 +63,7 @@ func (self *Manager) Parse(r *http.Request) ([]*Data, error) { if os.Getenv("DEBUG") == "1" { log.Printf("incoming request body:%v RemoteAddr:%v headers:%+v \n", string(c), r.RemoteAddr, r.Header) } - + fmt.Println(string(c)) data := &DataUpPayload{} err = json.Unmarshal(c, data) if err != nil { @@ -74,14 +74,18 @@ func (self *Manager) Parse(r *http.Request) ([]*Data, error) { if !ok { return nil, fmt.Errorf("request payload doesn't include device type tags:%+v", data.Tags) } - + var _ *Data var points []*Data switch devType { case "rpi": points, err = Rpi(string(data.Data)) + case "antratek": + points, err = antratekParse(data) case "irnas": points, err = Irnas(data) + case "Second": + points, err = G62Parse(data) default: return nil, fmt.Errorf("unsuported device type:%v", devType) } @@ -143,6 +147,12 @@ func (self *Manager) update(data *Data) error { } else { // Distance from each gateway that received this data. for _, gwMeta := range data.Payload.RXInfo { + if gwMeta.Location == nil { + if os.Getenv("DEBUG") == "1" { + log.Println("recieved meta gateway without location") + } + continue + } if data.Valid { dist, err := Distance(data.Lat, data.Lon, gwMeta.Location.Latitude, gwMeta.Location.Longitude, "K") if err != nil { @@ -322,31 +332,174 @@ func irnasParseSingle(data dataInterface) (*Data, error) { return dataParsed, nil } + + + +func G62Parse(data *DataUpPayload) ([]*Data, error) { + + dataParsed := &Data{ + Valid: true, + Attr: map[string]string{}, + } + + // Non GPS data. + if data.FPort != 1 { + dataParsed.Valid = false + if os.Getenv("DEBUG") == "1" { + log.Printf("skipping non gps data, fport:%+v", data.FPort) + } + return []*Data{dataParsed}, nil + } + + lat, ok := data.Object["latitudeDeg"] + if !ok { + return nil, errors.New("data doesn't contain lat") + } + lon, ok := data.Object["longitudeDeg"] + + if !ok { + return nil, errors.New("data object doesn't contain lon") + } + //data.DevEUI=data.DeviceInfo.DevEui + + dataParsed.Time = int64( data.Time.Unix()) + + + // Port 12 status messages contain only lat/lon. + hdop, ok := data.Object["hdop"] + if !ok { + log.Printf("data object doesn't contain hdop so setting to 0") + hdop = 0.0 + } + dataParsed.Hdop = hdop.(float64) + + dataParsed.Lat = lat.(float64) + dataParsed.Lon = lon.(float64) + if dataParsed.Lat == 0.0 || dataParsed.Lon == 0.0 { + dataParsed.Valid = false + } + /*if val, ok := data["gps_time"]; ok { // From system updates. + dataParsed.Time = int64(val.(float64)) + } + if val, ok := data["time"]; ok { // From periodic or motion triggered updates. + dataParsed.Time = int64(val.(float64)) + }*/ + + if val, ok := data.Object["speedKmph"]; ok { + dataParsed.Attr["speedKmph"] = fmt.Sprintf("%v", val.(float64)) + } + if val, ok := data.Object["tempC"]; ok && int64(val.(float64)) > 0 { + dataParsed.Attr["temperature"] = fmt.Sprintf("%v", val.(float64)) + } + + return []*Data{dataParsed}, nil +} + +func antratekParse(data *DataUpPayload) ([]*Data, error) { + + dataParsed := &Data{ + Valid: true, + Attr: map[string]string{}, + } + + // Non GPS data. + if data.FPort != 136 { + dataParsed.Valid = false + if os.Getenv("DEBUG") == "1" { + log.Printf("skipping non gps data, fport:%+v", data.FPort) + } + return []*Data{dataParsed}, nil + } + + lat, ok := data.Object["positionLatitude"] + if !ok { + return nil, errors.New("data doesn't contain lat") + } + lon, ok := data.Object["positionLongitude"] + + if !ok { + return nil, errors.New("data object doesn't contain lon") + } + //data.DevEUI=data.DeviceInfo.DevEui + + dataParsed.Time = int64( data.Time.Unix()) + + + // Port 12 status messages contain only lat/lon. + hdop, ok := data.Object["hdop"] + if !ok { + log.Printf("data object doesn't contain hdop so setting to 0") + hdop = 0.0 + } + dataParsed.Hdop = hdop.(float64) + + dataParsed.Lat = lat.(float64) + dataParsed.Lon = lon.(float64) + if dataParsed.Lat == 0.0 || dataParsed.Lon == 0.0 { + dataParsed.Valid = false + } + /*if val, ok := data["gps_time"]; ok { // From system updates. + dataParsed.Time = int64(val.(float64)) + } + if val, ok := data["time"]; ok { // From periodic or motion triggered updates. + dataParsed.Time = int64(val.(float64)) + }*/ + + if val, ok := data.Object["battery"]; ok { + dataParsed.Attr["battery"] = fmt.Sprintf("%v", val.(float64)) + } + if val, ok := data.Object["temperature"]; ok && int64(val.(float64)) > 0 { + dataParsed.Attr["temperature"] = fmt.Sprintf("%v", val.(float64)) + } + + return []*Data{dataParsed}, nil +} + // DataUpPayload represents a data-up payload. type DataUpPayload struct { - ApplicationID int64 `json:"applicationID,string"` - ApplicationName string `json:"applicationName"` - DeviceName string `json:"deviceName"` - DevEUI lorawan.EUI64 `json:"devEUI"` - RXInfo []RXInfo `json:"rxInfo,omitempty"` - TXInfo TXInfo `json:"txInfo"` - ADR bool `json:"adr"` - FCnt uint32 `json:"fCnt"` - FPort uint8 `json:"fPort"` - Data []byte `json:"data"` - Object map[string]interface{} `json:"object,omitempty"` - Tags map[string]string `json:"tags,omitempty"` - Variables map[string]string `json:"-"` + Time *time.Time `json:"time"` + TXInfo TXInfo `json:"txInfo"` + ADR bool `json:"adr"` + FCnt uint32 `json:"fCnt"` + FPort uint8 `json:"fPort"` + Data []byte `json:"data"` + Object map[string]interface{} `json:"object,omitempty"` + Variables map[string]string `json:"-"` + DeviceInfo `json:"deviceInfo"` +} + +// DataUpPayload represents a data-up payload. +type DataUpPayloadAntratek struct { + DeduplicationId string `json:"deduplicationId"` + + DeviceInfo []DeviceInfo `json:"deviceInfo"` +} + +type DeviceInfo struct { + TenantId string `json:"tenantId"` + TenantName string `json:"tenantName"` + ApplicationName string `json:"applicationName"` + ApplicationId string `json:"applicationId"` + DeviceProfileId string `json:"deviceProfileId"` + DeviceProfileName string `json:"deviceProfileName"` + DeviceName string `json:"deviceName"` + DevEui lorawan.EUI64 `json:"devEui"` + RXInfo []RXInfo `json:"rxInfo,omitempty"` + Tags map[string]string `json:"tags"` +} + +type Tags struct { + Type string `json:"type"` } // RXInfo contains the RX information. type RXInfo struct { GatewayID lorawan.EUI64 `json:"gatewayID"` Name string `json:"name"` - Time *time.Time `json:"time,omitempty"` - RSSI int `json:"rssi"` - LoRaSNR float64 `json:"loRaSNR"` - Location *Location `json:"location"` + + RSSI int `json:"rssi"` + LoRaSNR float64 `json:"loRaSNR"` + Location *Location `json:"location"` } // TXInfo contains the TX information. @@ -456,5 +609,5 @@ func Speed(point1 *Data, point2 *Data) (float64, error) { } func GenID(data *DataUpPayload) string { - return data.DeviceName + "-" + data.DevEUI.String() + return data.DeviceName + "-" + data.DeviceInfo.DevEui.String() } diff --git a/receiver/LoraToGPSServer/traccar/traccar.go b/receiver/LoraToGPSServer/traccar/traccar.go index 6e9d660..a758bd6 100644 --- a/receiver/LoraToGPSServer/traccar/traccar.go +++ b/receiver/LoraToGPSServer/traccar/traccar.go @@ -63,8 +63,8 @@ func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer log.SetPrefix("") for n, v := range point.Attr { - s.lastAttrs[point.Payload.DevEUI] = make(map[string]string) - s.lastAttrs[point.Payload.DevEUI][n] = v + s.lastAttrs[point.Payload.DevEui] = make(map[string]string) + s.lastAttrs[point.Payload.DevEui][n] = v } if !point.Valid { @@ -98,7 +98,7 @@ func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } q := req.URL.Query() - q.Add("id", point.Payload.DevEUI.String()) + q.Add("id", point.Payload.DevEui.String()) q.Add("lat", fmt.Sprintf("%g", point.Lat)) q.Add("timestamp", strconv.Itoa(int(point.Time))) q.Add("lon", fmt.Sprintf("%g", point.Lon)) @@ -108,7 +108,7 @@ func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Add last reocorded attributes in case they are missing in the new request // and they will be overrided by the new value if the attr exists. - for n, v := range s.lastAttrs[point.Payload.DevEUI] { + for n, v := range s.lastAttrs[point.Payload.DevEui] { q.Set(n, fmt.Sprintf("%v", v)) } // Override the attr with the new values. From a05c8e5c2afc892544eca54714abce2067f9f623 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:36:59 +0200 Subject: [PATCH 02/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 65f7479..3a27d82 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -81,7 +81,7 @@ func (self *Manager) Parse(r *http.Request) ([]*Data, error) { case "rpi": points, err = Rpi(string(data.Data)) case "antratek": - points, err = antratekParse(data) + points, err = Antratek(data) case "irnas": points, err = Irnas(data) case "Second": From d21e0c1c7899c3a70dc0bf14dac65a47cf0da67f Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:04 +0200 Subject: [PATCH 03/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 3a27d82..1a49f3e 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -468,12 +468,6 @@ type DataUpPayload struct { DeviceInfo `json:"deviceInfo"` } -// DataUpPayload represents a data-up payload. -type DataUpPayloadAntratek struct { - DeduplicationId string `json:"deduplicationId"` - - DeviceInfo []DeviceInfo `json:"deviceInfo"` -} type DeviceInfo struct { TenantId string `json:"tenantId"` From 0caf557e16f3f25c0df5bf08641c329b60f147c6 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:09 +0200 Subject: [PATCH 04/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 1 - 1 file changed, 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 1a49f3e..61d9b2c 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -63,7 +63,6 @@ func (self *Manager) Parse(r *http.Request) ([]*Data, error) { if os.Getenv("DEBUG") == "1" { log.Printf("incoming request body:%v RemoteAddr:%v headers:%+v \n", string(c), r.RemoteAddr, r.Header) } - fmt.Println(string(c)) data := &DataUpPayload{} err = json.Unmarshal(c, data) if err != nil { From f78e9ec5937abe0979d49309c859815a530ce636 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:15 +0200 Subject: [PATCH 05/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 1 - 1 file changed, 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 61d9b2c..d69ce7a 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -73,7 +73,6 @@ func (self *Manager) Parse(r *http.Request) ([]*Data, error) { if !ok { return nil, fmt.Errorf("request payload doesn't include device type tags:%+v", data.Tags) } - var _ *Data var points []*Data switch devType { From 291a0f2ec88a35321bf8d85844e13efc59e8e66b Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:21 +0200 Subject: [PATCH 06/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 1 - 1 file changed, 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index d69ce7a..e36de92 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -358,7 +358,6 @@ func G62Parse(data *DataUpPayload) ([]*Data, error) { if !ok { return nil, errors.New("data object doesn't contain lon") } - //data.DevEUI=data.DeviceInfo.DevEui dataParsed.Time = int64( data.Time.Unix()) From 414d68c49118c2647dceeed8594cf77c9a1ca580 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:26 +0200 Subject: [PATCH 07/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index e36de92..e6aaff1 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -375,12 +375,6 @@ func G62Parse(data *DataUpPayload) ([]*Data, error) { if dataParsed.Lat == 0.0 || dataParsed.Lon == 0.0 { dataParsed.Valid = false } - /*if val, ok := data["gps_time"]; ok { // From system updates. - dataParsed.Time = int64(val.(float64)) - } - if val, ok := data["time"]; ok { // From periodic or motion triggered updates. - dataParsed.Time = int64(val.(float64)) - }*/ if val, ok := data.Object["speedKmph"]; ok { dataParsed.Attr["speedKmph"] = fmt.Sprintf("%v", val.(float64)) From 03690e15951bc363adab3b6f144975bf40abda3c Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:31 +0200 Subject: [PATCH 08/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index e6aaff1..c367776 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -377,7 +377,8 @@ func G62Parse(data *DataUpPayload) ([]*Data, error) { } if val, ok := data.Object["speedKmph"]; ok { - dataParsed.Attr["speedKmph"] = fmt.Sprintf("%v", val.(float64)) + dataParsed.Speed = fmt.Sprintf("%v", val.(float64)) + dataParsed.Motion = true } if val, ok := data.Object["tempC"]; ok && int64(val.(float64)) > 0 { dataParsed.Attr["temperature"] = fmt.Sprintf("%v", val.(float64)) From 906cd2167e391522076f1c8708870c093f1b925c Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:37 +0200 Subject: [PATCH 09/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 1 - 1 file changed, 1 deletion(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index c367776..19d656f 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -412,7 +412,6 @@ func antratekParse(data *DataUpPayload) ([]*Data, error) { if !ok { return nil, errors.New("data object doesn't contain lon") } - //data.DevEUI=data.DeviceInfo.DevEui dataParsed.Time = int64( data.Time.Unix()) From 2251516279d26e3a99172cae57866e530abe6396 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 14 Nov 2022 22:37:43 +0200 Subject: [PATCH 10/11] Update receiver/LoraToGPSServer/device/device.go Co-authored-by: Krasimir Georgiev <8903888+krasi-georgiev@users.noreply.github.com> --- receiver/LoraToGPSServer/device/device.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 19d656f..2d5fb06 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -429,12 +429,6 @@ func antratekParse(data *DataUpPayload) ([]*Data, error) { if dataParsed.Lat == 0.0 || dataParsed.Lon == 0.0 { dataParsed.Valid = false } - /*if val, ok := data["gps_time"]; ok { // From system updates. - dataParsed.Time = int64(val.(float64)) - } - if val, ok := data["time"]; ok { // From periodic or motion triggered updates. - dataParsed.Time = int64(val.(float64)) - }*/ if val, ok := data.Object["battery"]; ok { dataParsed.Attr["battery"] = fmt.Sprintf("%v", val.(float64)) From 6232256449730341d4deb0a9e151a9627e2e4f6f Mon Sep 17 00:00:00 2001 From: Honceriu Tudor Date: Mon, 14 Nov 2022 22:42:36 +0200 Subject: [PATCH 11/11] remove hdop --- receiver/LoraToGPSServer/device/device.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/receiver/LoraToGPSServer/device/device.go b/receiver/LoraToGPSServer/device/device.go index 2d5fb06..7f44d20 100644 --- a/receiver/LoraToGPSServer/device/device.go +++ b/receiver/LoraToGPSServer/device/device.go @@ -362,13 +362,7 @@ func G62Parse(data *DataUpPayload) ([]*Data, error) { dataParsed.Time = int64( data.Time.Unix()) - // Port 12 status messages contain only lat/lon. - hdop, ok := data.Object["hdop"] - if !ok { - log.Printf("data object doesn't contain hdop so setting to 0") - hdop = 0.0 - } - dataParsed.Hdop = hdop.(float64) + dataParsed.Lat = lat.(float64) dataParsed.Lon = lon.(float64)