Acrel IoT Docs Help

LoRaWAN协议

1.协议概述

此文档规范了 LoRaWAN 节点与 NS 服务器之间的通讯协议数据格式。节点可以是采集设备数据的网关,也可以是直连表。设备使用 LoRaWan 无线通讯将设备数据逐层上报到 NS 服务器,同时节点还支持 NS 服务器进行透传下发。数据报文格式是 HEX 十六进制格式(HEX Format)。

┌────────┐ ┌─────────┐ ┌────────────────┐ ┌───────────┐ │ Device │ -- │ Gateway │ -- │ Network Server │ --MQTT-- │ Acrel IoT │ └────────┘ └─────────┘ └────────────────┘ └───────────┘

如上图所示,设备通过LoRaWAN网关(如AWT200-LW)接入NS平台(Network Server),然后需要在NS平台维护JS脚本,将HEX报文解析中台所需JSON格式 ,再由NS平台转发给数据中台进行数据处理。

由于LoRaWAN报文长度受限,报文中仅包含电参量值,而不包含参量名,所以对于中台来说,不同型号、不同版本的报文格式不相同,定制开发的成本太高,所以设备研发完成后,还需要编写解析报文的Javascript脚本

2.解析脚本

以下为解析脚本模板,其中标注了需要修改的用于解析数据内容的主要逻辑部分。

/** * 上行解码器脚本 */ function uplinkDeviceDecode(bytes, input) { var decoded = {}; decoded.devEUI = LoRaObject.devEUI; decoded.rssi = LoRaObject.rxInfo[0].rssi; decoded.snr = LoRaObject.rxInfo[0].loRaSNR; decoded.fPort = LoRaObject.fPort; //原始数据,0x90透传报文需要用到 decoded.data = LoRaObject.data; //中台以此区分报文是否是经过脚本解析,默认置为true // true-未解析过的16进制报文 // false-解析为JSON报文 decoded.original = true; //中台产品型号productKey,联系中台研发获取 decoded.productKey = "ODAzMTU1MDA1ODcyMDc0NzUy"; //中台产品名称,联系中台研发获取 decoded.productName = "ADL200-NK"; var payload = {}; // 命令字91代表实时数据, if (bytes[3] === 0x91) { // 91报文是解析过的,这里修改标识 decoded.original = false; /* === START 需要修改的主要逻辑,依次解析电参量值 START === */ // 仪表地址,中台根据此地址生成拓扑 decoded.addr = bytes[4]; // modbus地址 decoded.MeterAddr = bytes[4]; // 仪表状态,0-offline 1-online decoded.MeterState = bytes[6]; decoded.EPI = bytesToFloat(bytes.slice(7, 11),2); decoded.EPIJ = bytesToFloat(bytes.slice(11, 15),2); decoded.EPIF = bytesToFloat(bytes.slice(15, 19),2); decoded.EPIP = bytesToFloat(bytes.slice(19, 23),2); decoded.EPIG = bytesToFloat(bytes.slice(23, 27),2); decoded.U = bytesToFloat(bytes.slice(27, 31),1); decoded.I = bytesToFloat(bytes.slice(31, 35),1); decoded.P = bytesToFloat(bytes.slice(35, 39),3); decoded.Q = bytesToFloat(bytes.slice(39, 43),1); decoded.S = bytesToFloat(bytes.slice(43, 47),1); decoded.PF = bytesToFloat(bytes.slice(47, 51),1); decoded.EPE = bytesToFloat(bytes.slice(51, 55),2); decoded.AlarmA = bytesToFloat(bytes.slice(55, 59),1); decoded.AlarmB = bytesToFloat(bytes.slice(59, 63),1); decoded.PowerLimit = bytesToFloat(bytes.slice(63, 67),2); decoded.BuyTimes = bytesToFloat(bytes.slice(67, 71),0); decoded.Balance = bytesToFloat(bytes.slice(71, 75),2); decoded.PriceSharp = bytesToFloat(bytes.slice(75, 79),2); decoded.PricePeak = bytesToFloat(bytes.slice(79, 83),2); decoded.PriceFlat = bytesToFloat(bytes.slice(83, 87),2); decoded.PriceVally = bytesToFloat(bytes.slice(87, 91),2); decoded.AlarmPower = bytesToFloat(bytes.slice(91, 95),2); decoded.PRESTATE = bytesToFloat(bytes.slice(95, 99),0); /* === END 需要修改的主要逻辑,依次解析电参量值 END === */ payload.data = decoded; return payload; } } // Chirpstack v4 使用的函数 function decodeUplink(input) { var decoded = uplinkDeviceDecode(input.bytes, input); return { data: decoded }; } // Chirpstack v3 使用的函数 function Decode(fPort, bytes) { return uplinkDeviceDecode(bytes); } // The Things Network 使用的函数 function Decoder(bytes, port) { return uplinkDeviceDecode(bytes); } /* ****************************************** * bytes to number ******************************************* */ function bytesToFloat(bytes, id, scale) { id = (id - 1) * 4; var buff = bytes.slice(7 + id, 7 + id + 4); var bits = (buff[0] << 24) | (buff[1] << 16) | (buff[2] << 8) | buff[3]; var sign = bits >>> 31 === 0 ? 1.0 : -1.0; var e = (bits >>> 23) & 0xff; var m = e === 0 ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; var f = sign * m * Math.pow(2, e - 150); f = parseFloat(f.toFixed(scale)); return f; }

3.报文格式

3.1 实时数据

字段

数值(HEX)

类型

长度

包头

{{

ASCII

2

包长

包头到结束符的包长

uint8

1

功能码

0x91

uint8

1

表地址

仪表modbus地址1~255

uint8

1

数据组号

网关模板内的组号1~255

uint8

1

在线状态

0=离线 1=在线

uint8

1

数据体

根据模板内参数序号依次排列

N<=4*X

CRC

包长~数据体的CRC

uint16

2

结束符

}}

ASCII

2

总包长

11+N

注意:上述字段<数据体>的长度一栏,X 代表上报参数数量,其根据 LoRaWAN 发送速率有所不同 ,见下表:

LoRaWAN 速率

单包上传最大参数数量(个)

自动

10

SF10~SF12

10

SF9

20

SF8/SF7

40

3.2 命令下发

注:下发端口为 FPort:10

  • 服务器下发

字段

数值(HEX)

类型

长度

包头

{{

ASCII

2

包长

包头到结束符的包长

uint8

1

功能码

0x90

uint8

1

数据体

自定义输入(透传内容)

uint8

N<=41

CRC

包长~数据体的CRC

uint16

2

结束符

}}

ASCII

2

总包长

8+N

报文示例:

透传下发:7b 7b 10 90 01 03 00 00 00 10 44 06 9D 9F 7d 7d 包头:7b 7b 包长:10(总字节数,此处为 7b 7b 10 90 01 03 00 00 00 10 44 06 9D 9F 7d 7d 的字节数,共 16 字节,转换为 16 进制为 0x10) 功能码:90 数据体: 01 03 00 00 00 10 44 06(自定义输入,内容是通过 485 发送给电表的实际报文) CRC:9D 9F(10 90 01 03 00 00 00 10 44 06 部分做 CRC 校验,此处结果为 9D 9F) 固定包尾:7d 7d
  • 节点回复

字段

数值(HEX)

类型

长度

包头

{{

ASCII

2

包长

包头到结束符的包长

uint8

1

功能码

0x90

uint8

1

数据体

回包数据体(透传内容)

uint8

N<=41

CRC

包长~数据体的CRC

uint16

2

结束符

}}

ASCII

2

总包长

8+N

25 十二月 2025