package cdp import ( "encoding/hex" "strconv" "strings" "time" ) // EndpointMessage is a generic message type EndpointMessage struct { Reports []EndpointMessageReport `json:"reports"` } // EndpointMessageReportTime for custom time type EndpointMessageReportTime struct { time.Time } // ResourcePathUplinkMsgData is the resource path for uplink messages const ResourcePathUplinkMsgData = "uplinkMsg/0/data" // EndpointMessageReport is a single device report type EndpointMessageReport struct { SerialNumber SerialNumber `json:"serialNumber"` Timestamp EndpointMessageReportTime `json:"timestamp"` SubscriptionID string `json:"subscriptionId"` ResourcePath string `json:"resourcePath"` Value string `json:"value"` } // UnmarshalJSON for converting from UNIX milliseconds to time.Time func (t *EndpointMessageReportTime) UnmarshalJSON(b []byte) error { ms, err := strconv.Atoi(string(b)) if err != nil { return err } s := ms / 1e3 ns := (ms - s*1e3) * 1e6 t.Time = time.Unix(int64(s), int64(ns)) return nil } // SerialNumber attribute from EndpointMessageReport type SerialNumber string // IMEI calculates the IMEI from the SerialNumber it returns an empty string when not valid func (sn SerialNumber) IMEI() string { const imeiPrefix = "IMEI:" if strings.HasPrefix(string(sn), imeiPrefix) { return strings.TrimPrefix(string(sn), imeiPrefix) } return "" } //NewEndpointMessage creates a new endpoint message containing a single report. //The single report wraps the CRM payload given. func NewEndpointMessage(payload []byte, timestamp time.Time) *EndpointMessageReport { hexPayload := hex.EncodeToString(payload) return &EndpointMessageReport{ SerialNumber: "", Timestamp: EndpointMessageReportTime{timestamp}, SubscriptionID: "", ResourcePath: "", Value: hexPayload, } }