Skip to content

Commit 2f0d5b7

Browse files
committed
Parse optional 'meta' in RXPK.
The 'meta' field is not specified in PROTOCOL.TXT, but can be used by custom packet-forwarder implementations to expose additional metadata.
1 parent 24a8656 commit 2f0d5b7

File tree

2 files changed

+83
-19
lines changed

2 files changed

+83
-19
lines changed

internal/backend/semtechudp/packets/push_data.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ func getUplinkFrame(gatewayID lorawan.EUI64, rxpk RXPK, FakeRxInfoTime bool) (*g
140140
Channel: uint32(rxpk.Chan),
141141
Board: uint32(rxpk.Brd),
142142
Context: make([]byte, 4),
143+
Metadata: rxpk.Meta,
143144
},
144145
}
145146

@@ -344,25 +345,26 @@ type Stat struct {
344345

345346
// RXPK contain a RF packet and associated metadata.
346347
type RXPK struct {
347-
Time *CompactTime `json:"time"` // UTC time of pkt RX, us precision, ISO 8601 'compact' format (e.g. 2013-03-31T16:21:17.528002Z)
348-
Tmms *int64 `json:"tmms"` // GPS time of pkt RX, number of milliseconds since 06.Jan.1980
349-
Tmst uint32 `json:"tmst"` // Internal timestamp of "RX finished" event (32b unsigned)
350-
FTime *uint32 `json:"ftime"` // Fine timestamp, number of nanoseconds since last PPS [0..999999999] (Optional)
351-
AESK uint8 `json:"aesk"` // AES key index used for encrypting fine timestamps
352-
Chan uint8 `json:"chan"` // Concentrator "IF" channel used for RX (unsigned integer)
353-
RFCh uint8 `json:"rfch"` // Concentrator "RF chain" used for RX (unsigned integer)
354-
Stat int8 `json:"stat"` // CRC status: 1 = OK, -1 = fail, 0 = no CRC
355-
Freq float64 `json:"freq"` // RX central frequency in MHz (unsigned float, Hz precision)
356-
Brd uint32 `json:"brd"` // Concentrator board used for RX (unsigned integer)
357-
RSSI int16 `json:"rssi"` // RSSI in dBm (signed integer, 1 dB precision)
358-
Size uint16 `json:"size"` // RF packet payload size in bytes (unsigned integer)
359-
DatR DatR `json:"datr"` // LoRa datarate identifier (eg. SF12BW500) || FSK datarate (unsigned, in bits per second)
360-
Modu string `json:"modu"` // Modulation identifier "LORA" or "FSK"
361-
CodR string `json:"codr"` // LoRa ECC coding rate identifier
362-
LSNR float64 `json:"lsnr"` // Lora SNR ratio in dB (signed float, 0.1 dB precision)
363-
HPW uint8 `json:"hpw"` // LR-FHSS hopping grid number of steps.
364-
Data []byte `json:"data"` // Base64 encoded RF packet payload, padded
365-
RSig []RSig `json:"rsig"` // Received signal information, per antenna (Optional)
348+
Time *CompactTime `json:"time"` // UTC time of pkt RX, us precision, ISO 8601 'compact' format (e.g. 2013-03-31T16:21:17.528002Z)
349+
Tmms *int64 `json:"tmms"` // GPS time of pkt RX, number of milliseconds since 06.Jan.1980
350+
Tmst uint32 `json:"tmst"` // Internal timestamp of "RX finished" event (32b unsigned)
351+
FTime *uint32 `json:"ftime"` // Fine timestamp, number of nanoseconds since last PPS [0..999999999] (Optional)
352+
AESK uint8 `json:"aesk"` // AES key index used for encrypting fine timestamps
353+
Chan uint8 `json:"chan"` // Concentrator "IF" channel used for RX (unsigned integer)
354+
RFCh uint8 `json:"rfch"` // Concentrator "RF chain" used for RX (unsigned integer)
355+
Stat int8 `json:"stat"` // CRC status: 1 = OK, -1 = fail, 0 = no CRC
356+
Freq float64 `json:"freq"` // RX central frequency in MHz (unsigned float, Hz precision)
357+
Brd uint32 `json:"brd"` // Concentrator board used for RX (unsigned integer)
358+
RSSI int16 `json:"rssi"` // RSSI in dBm (signed integer, 1 dB precision)
359+
Size uint16 `json:"size"` // RF packet payload size in bytes (unsigned integer)
360+
DatR DatR `json:"datr"` // LoRa datarate identifier (eg. SF12BW500) || FSK datarate (unsigned, in bits per second)
361+
Modu string `json:"modu"` // Modulation identifier "LORA" or "FSK"
362+
CodR string `json:"codr"` // LoRa ECC coding rate identifier
363+
LSNR float64 `json:"lsnr"` // Lora SNR ratio in dB (signed float, 0.1 dB precision)
364+
HPW uint8 `json:"hpw"` // LR-FHSS hopping grid number of steps.
365+
Data []byte `json:"data"` // Base64 encoded RF packet payload, padded
366+
RSig []RSig `json:"rsig"` // Received signal information, per antenna (Optional)
367+
Meta map[string]string `json:"meta"` // Custom meta-data (Optional, not part of PROTOCOL.TXT)
366368
}
367369

368370
// RSig contains the received signal information per antenna.

internal/backend/semtechudp/packets/push_data_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,68 @@ func TestGetUplinkFrame(t *testing.T) {
455455
},
456456
},
457457
},
458+
{
459+
Name: "uplink with meta",
460+
PushDataPacket: PushDataPacket{
461+
GatewayMAC: lorawan.EUI64{1, 2, 3, 4, 5, 6, 7, 8},
462+
ProtocolVersion: ProtocolVersion2,
463+
Payload: PushDataPayload{
464+
RXPK: []RXPK{
465+
{
466+
Time: &ctNow,
467+
Tmst: 1000000,
468+
Freq: 868.3,
469+
Brd: 2,
470+
Chan: 1,
471+
RFCh: 3,
472+
Stat: 1,
473+
Modu: "LORA",
474+
DatR: DatR{LoRa: "SF12BW500"},
475+
CodR: "4/5",
476+
RSSI: -60,
477+
LSNR: 5.5,
478+
Size: 5,
479+
Data: []byte{1, 2, 3, 4, 5},
480+
Meta: map[string]string{
481+
"gateway_name": "test-gateway",
482+
},
483+
},
484+
},
485+
},
486+
},
487+
UplinkFrames: []*gw.UplinkFrame{
488+
{
489+
PhyPayload: []byte{1, 2, 3, 4, 5},
490+
TxInfo: &gw.UplinkTxInfo{
491+
Frequency: 868300000,
492+
Modulation: &gw.Modulation{
493+
Parameters: &gw.Modulation_Lora{
494+
Lora: &gw.LoraModulationInfo{
495+
Bandwidth: 500000,
496+
SpreadingFactor: 12,
497+
CodeRate: gw.CodeRate_CR_4_5,
498+
PolarizationInversion: false,
499+
},
500+
},
501+
},
502+
},
503+
RxInfo: &gw.UplinkRxInfo{
504+
GatewayId: "0102030405060708",
505+
Time: pbTime,
506+
Rssi: -60,
507+
Snr: 5.5,
508+
Channel: 1,
509+
RfChain: 3,
510+
Board: 2,
511+
Antenna: 0,
512+
Context: []byte{0x00, 0x0f, 0x42, 0x40},
513+
Metadata: map[string]string{
514+
"gateway_name": "test-gateway",
515+
},
516+
},
517+
},
518+
},
519+
},
458520
}
459521

460522
for _, test := range testTable {

0 commit comments

Comments
 (0)