From 4950b67afd1be1e10c017aaf5892090509c7048a Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 8 Dec 2023 15:41:11 +0100 Subject: [PATCH] basic ttn parsing --- src/udi/handlers/ttn/emu-example.json | 124 ++++++++++++++++++++++++++ src/udi/handlers/ttn/ttn.go | 70 +++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 src/udi/handlers/ttn/emu-example.json diff --git a/src/udi/handlers/ttn/emu-example.json b/src/udi/handlers/ttn/emu-example.json new file mode 100644 index 0000000..02dc180 --- /dev/null +++ b/src/udi/handlers/ttn/emu-example.json @@ -0,0 +1,124 @@ +{ + "end_device_ids": { + "device_id": "eui-102ceffffe01089c", + "application_ids": { + "application_id": "com-passavant-geiger-poc" + }, + "dev_eui": "102CEFFFFE01089C", + "join_eui": "102CEF0000000000", + "dev_addr": "260B0E1A" + }, + "correlation_ids": [ + "gs:uplink:01HH4TTA29NV2GZXGYQ61R2BVZ" + ], + "received_at": "2023-12-08T13:45:34.236364394Z", + "uplink_message": { + "session_key_id": "AYxJcJyrJgr7XiIUdO3EBA==", + "f_port": 1, + "f_cnt": 64, + "frm_payload": "3B1zZQsAAAAADAAAAAANAAAAAA4AAAAAFwAYABkA8ABm", + "decoded_payload": { + "Active Power L1": { + "cfgphase": 1, + "unit": "W", + "value": 0 + }, + "Active Power L123": { + "unit": "W", + "value": 0 + }, + "Active Power L2": { + "cfgphase": 2, + "unit": "W", + "value": 0 + }, + "Active Power L3": { + "cfgphase": 3, + "unit": "W", + "value": 0 + }, + "Powerfactor L1": { + "cfgphase": 1, + "unit": "Cos", + "value": 0, + "value_raw": 0 + }, + "Powerfactor L2": { + "cfgphase": 2, + "unit": "Cos", + "value": 0, + "value_raw": 0 + }, + "Powerfactor L3": { + "cfgphase": 3, + "unit": "Cos", + "value": 0, + "value_raw": 0 + }, + "errorcode": { + "CTRatioChange": false, + "ImpulseRatioChange": false, + "ImpulseWidthChange": false, + "LogbookFull": false, + "PowerFail": false, + "TimeChanged": false, + "VTRatioChange": false, + "value": 0 + }, + "medium": { + "desc": "Electricity", + "type": 1 + }, + "timeStamp": 1702043100 + }, + "rx_metadata": [ + { + "gateway_ids": { + "gateway_id": "eui-b827ebfffe8b01dd", + "eui": "B827EBFFFE8B01DD" + }, + "time": "2023-12-08T13:45:33.311665058Z", + "timestamp": 3841207982, + "rssi": -86, + "channel_rssi": -86, + "snr": 13.25, + "location": { + "latitude": 51.404164272478724, + "longitude": 7.060088589208832, + "source": "SOURCE_REGISTRY" + }, + "uplink_token": "CiIKIAoUZXVpLWI4MjdlYmZmZmU4YjAxZGQSCLgn6//+iwHdEK7d0KcOGgsI/rvMqwYQn82PDCCwr9nO5eulAg==", + "received_at": "2023-12-08T13:45:34.006723465Z" + } + ], + "settings": { + "data_rate": { + "lora": { + "bandwidth": 125000, + "spreading_factor": 7, + "coding_rate": "4/5" + } + }, + "frequency": "868300000", + "timestamp": 3841207982, + "time": "2023-12-08T13:45:33.311665058Z" + }, + "received_at": "2023-12-08T13:45:34.027717446Z", + "confirmed": true, + "consumed_airtime": "0.092416s", + "version_ids": { + "brand_id": "emu", + "model_id": "emu-prof-ii", + "hardware_version": "1.0", + "firmware_version": "1.0", + "band_id": "EU_863_870" + }, + "network_ids": { + "net_id": "000013", + "ns_id": "EC656E0000000181", + "tenant_id": "ttn", + "cluster_id": "eu1", + "cluster_address": "eu1.cloud.thethings.network" + } + } +} diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index 144ca3d..2b7af39 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -2,6 +2,7 @@ package ttn import "log" import "fmt" +import "encoding/json" import "udi/config" import "udi/handlers/handler" @@ -11,6 +12,54 @@ type TTNHandler struct { id int } +type uplinkMessage struct { + EndDeviceIds struct { + DeviceId string `json:"device_id"` + ApplicationIds struct { + ApplicationId string `json:"application_id"` + } `json:"application_ids"` + DevEui string `json:"dev_eui"` + JoinEui string `json:"join_eui"` + DevAddr string `json:"dev_addr"` + } `json:"end_device_ids"` + ReceivedAt string `json:"received_at"` + UplinkMessage struct { + FCnt int `json:"f_cnt"` + FPort int `json:"f_port"` + FrmPayload string `json:"frm_payload"` + DecodedPayload map[string]interface{} `json:"decoded_payload"` + RxMetadata []struct { + GatewayIds struct { + GatewayId string `json:"gateway_id"` + Eui string `json:"eui"` + } `json:"gateway_ids"` + Time string `json:"time"` + Rssi int `json:"rssi"` + ChannelRssi int `json:"channel_rssi"` + Snr float32 `json:"snr"` + ChannelIndex int `json:"channel_index"` + } `json:"rx_metadata"` + ConsumedAirtime string `json:"consumed_airtime"` + } `json:"uplink_message"` +} + +type gatewayAttributes struct { + GatewayId string `json:"gateway_id"` + Rssi int `json:"rssi"` + Snr float32 `json:"snr"` +} + +type attributes struct { + DeviceId string `json:"device_id"` + ApplicationId string `json:"application_id"` + FCnt int `json:"f_cnt"` + FPort int `json:"f_port"` + FrmPayload string `json:"frm_payload"` + Gateways []gatewayAttributes `json:"gateways"` + ConsumedAirtime string `json:"consumed_airtime"` +} + + func NewTTNHandler(config config.HandlerConfigT) handler.Handler { t := &TTNHandler { @@ -26,6 +75,27 @@ func (self *TTNHandler) GetId() string { func (self *TTNHandler) Handle(message handler.MessageT) { log.Printf("Handler TTN %d processing %s -> %s", self.id, message.Topic, message.Payload) + + var uplinkMessage uplinkMessage + err := json.Unmarshal([]byte(message.Payload), &uplinkMessage) + if err != nil { + log.Printf("Error when unmarshaling message: %s", err) + } + log.Printf("Parsed message: %s", uplinkMessage) + + var attributes attributes + attributes.DeviceId = uplinkMessage.EndDeviceIds.DeviceId + attributes.ApplicationId = uplinkMessage.EndDeviceIds.ApplicationIds.ApplicationId + attributes.FCnt = uplinkMessage.UplinkMessage.FCnt + attributes.FPort = uplinkMessage.UplinkMessage.FPort + attributes.FrmPayload = uplinkMessage.UplinkMessage.FrmPayload + attributes.ConsumedAirtime = uplinkMessage.UplinkMessage.ConsumedAirtime + for _, rxm := range uplinkMessage.UplinkMessage.RxMetadata { + log.Printf("RXM: %s", rxm) + g := gatewayAttributes { GatewayId: rxm.GatewayIds.GatewayId, Rssi: rxm.Rssi, Snr: rxm.Snr } + attributes.Gateways = append(attributes.Gateways, g) + } + log.Printf("Attributes: %s", attributes) }