Skip to content
166 changes: 146 additions & 20 deletions receiver/LoraToGPSServer/device/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

data := &DataUpPayload{}
err = json.Unmarshal(c, data)
if err != nil {
Expand All @@ -74,14 +73,17 @@ 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 points []*Data

switch devType {
case "rpi":
points, err = Rpi(string(data.Data))
case "antratek":
points, err = Antratek(data)
case "irnas":
points, err = Irnas(data)
case "Second":
points, err = G62Parse(data)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
points, err = G62Parse(data)
points, err = G62(data)

default:
return nil, fmt.Errorf("unsuported device type:%v", devType)
}
Expand Down Expand Up @@ -143,6 +145,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 {
Expand Down Expand Up @@ -322,31 +330,149 @@ 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")
}

dataParsed.Time = int64( data.Time.Unix())




dataParsed.Lat = lat.(float64)
dataParsed.Lon = lon.(float64)
if dataParsed.Lat == 0.0 || dataParsed.Lon == 0.0 {
dataParsed.Valid = false
}

if val, ok := data.Object["speedKmph"]; ok {
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))
}

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")
}

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.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"`
}


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.
Expand Down Expand Up @@ -456,5 +582,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()
}
8 changes: 4 additions & 4 deletions receiver/LoraToGPSServer/traccar/traccar.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
Expand All @@ -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.
Expand Down