一、为什么把"网关 + 服务器"塞进一块板子
常规 LoRaWAN 组网是这样的:
LoRaWAN 网关 ──▶ 云服务器上的 ChirpStack ──▶ 业务应用
网关负责收无线电,ChirpStack 负责解密和分发,两者通常分处两地,中间依赖公网。
在中小规模工业现场,可以把 ChirpStack 直接部署在网关板子上:
- 无需额外配置独立服务器
- 断网时本地仍能采集、判断、显示,网络恢复后补传
- 调试链路完全在本地,不依赖公网环境
本文的方案就是后者:一块板 = 射频网关 + Gateway Bridge + ChirpStack + MQTT ,搭配配套软件,搭建可落地的LoRaWan网关。
二、硬件与软件清单
硬件
项目 | 说明 |
主机 | SBC2332(全志 T113-i,双核 A7,1GB DDR3,16GB eMMC) |
系统 | Ubuntu 20.04 |
无线模块 | MiniPCIe LoRaWAN 网关模块 |
天线 | 与模块频段匹配(本例 868MHz) |
网络 | 千兆网口(用于 SSH 和 Web 访问) |
节点(可选) | LoRaWAN 节点模块 + 传感器;无节点也能先验证网关 |
软件与端口
组件 | 版本/端口 | 作用 |
ChirpStack | 4.19.x | LoRaWAN 网络服务器(NS)+ 应用服务器(AS) |
ChirpStack Gateway Bridge | UDP1700 | 接收网关的 Semtech UDP 包 |
ChirpStack Web UI | TCP8080 | 管理后台 |
MQTT Broker(mosquitto) | TCP1883 | 网关与平台、平台与应用之间的消息总线 |
PostgreSQL / Redis | — | ChirpStack 的存储与缓存 |
钡铼技术网关程序/LoRaWan网关配置上位机 | — | 负责驱动射频模块/ 获取配置服务器连接参数 |
三、部署 ChirpStack
ChirpStack是一个著名的开源LoRaWAN服务器,官方提供安装方法,Ubuntu 20.04 直接照做即可:
# 参考官方文档:https://www.chirpstack.io/docs/getting-started/debian-ubuntu.html # 1 安装依赖(ChirpStack 本体不带这些) apt install -y mosquitto mosquitto-clients redis-server redis-tools postgresql # 2 建库建角色(psql 内执行) su postgres -c psql create role chirpstack with login password 'chirpstack'; create database chirpstack with owner chirpstack; \c chirpstack create extension pg_trgm; create extension pgcrypto; -- PostgreSQL 12 必加(PG13 起内置),缺它迁移全停 \q # 3 添加软件源(keyring 方式) mkdir -p /etc/apt/keyrings/ wget -q -O - https://artifacts.chirpstack.io/packages/chirpstack.key | gpg --dearmor > /etc/apt/keyrings/chirpstack.gpg echo "deb [signed-by=/etc/apt/keyrings/chirpstack.gpg] https://artifacts.chirpstack.io/packages/4.x/deb stable main" > /etc/apt/sources.list.d/chirpstack.list apt update # 4 安装并启动 apt install -y chirpstack chirpstack-gateway-bridge systemctl enable --now chirpstack chirpstack-gateway-bridge编辑/etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge.toml,把[integration.mqtt]段改成:
[integration.mqtt] event_topic_template="eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }}" command_topic_template="eu868/gateway/{{ .GatewayID }}/command/#" systemctl restart chirpstack-gateway-bridge验证:
systemctl is-active chirpstack chirpstack-gateway-bridge mosquitto postgresql redis-server # 期望全部输出 active ss -tlnp | grep -E ':(8080|1883|1700)'四、 注册网关与设备
1. 给设备安装LoRaWan软件
1. 打开设备后等待系统进入后,使用ssh等工具将安包传输设备
2. 使用解压命令解压缩安装包
tar -zxf install.tar.gz3. 进入解压后的软件目录执行里面的安装脚本
./install.sh2. 使用LoRaWan配置上位机连接
1. 解压缩上位机软件如图出现3个文件
2. 运行LoRaWanConfigurator.exe这个软件即可打开
3. 在配置上位机上输入对应的IP地址进行连接
4. 点击连接
5. 网关注册
浏览器访问 http://localhost:8080,用默认账号 admin / admin 登录。
登录后按顺序配置(以 ABP 激活为例):
Tenants → Gateways → Add gateway
字段 | 值 |
Gateway name | SBC2332-GW |
Gateway ID | 网关模块的 EUI |
6. 设备Profile
Device profiles → Add device profile
字段 | 值 |
Name | env-node-abp |
Region | EU868(与你的模块频段一致) |
MAC version | LoRaWAN 1.0.3 |
Activation | ABP |
7. 应用与设备
Applications → Add application(名字:env-monitor) → 进入应用 →Devices → Add device
字段 | 值 |
Name | env-node-01 |
Device EUI | 0011223344556677 |
Device-profile | env-node-abp |
8.填写ABP密钥
设备页 →Activation标签:
字段 | 值 |
DevAddr | 01D4C2A8 |
NwkSKey | 2B7E151628AED2A6ABF7158809CF4F3C |
AppSKey | 3B7E151628AED2A6ABF7158809CF4F3D |
FCnt Up / Down | 0 / 0 |
DevAddr 相当于节点的"IP",NwkSKey 用于校验帧完整性(MIC),AppSKey 用于解密业务数据。这三个值必须与节点端完全一致,否则数据进不来。
9. 网关上线
1.网关配置软件直接点击读取下位机
2. 请根据实际情况填写下面的内容,例如我使用的开源LoRaWan服务器chirpstack,上行端口是1700,下行端口是1700,服务器请填写自己服务器的地址,EUI请使用识别到的EUI
3. 添加连接的服务器
4. 改完配置后请点击发送配置
看操作日志可以发现配置已经写入成功了,现在只需点击重启网关等待片刻就可以连接到服务器。
五、没有真实节点?先跑一个"模拟节点"
网关调好后,最尴尬的情况是:节点还没到货,无法验证链路到底通不通。
这时可以写一个脚本扮演"无线节点",直接往 Gateway Bridge 注入数据包。从 ChirpStack 的角度看,它和真实节点发来的数据别无二致。我们实测的完整链路就是用这个方法打通的——网关环节是真硬件(模块在线、芯片应答),节点环节由脚本顶替;以后接上真实节点,软件侧一行都不用改。
1. Semtech UDP 协议要点
网关和服务器之间用 Semtech 包转发器协议(UDP),帧结构:
[协议版本 1B] [Token 2B] [类型 1B] [网关 MAC 8B] [JSON]类型值 | 含义 |
0x00 | PUSH_DATA(网关 → 服务器) |
0x01 | PUSH_ACK |
0x02 | PULL_DATA |
0x03 | PULL_RESP |
协议版本号必须是 0x02,PUSH_DATA 是 0x00。写成 0x01 会被当成 PUSH_ACK 拒收。
2. 两类包、两套时间格式
// stat(网关心跳)—— 让平台显示"在线",时间用传统格式 {"stat":{"time":"2026-10-14 08:44:52 GMT","rxnb":0,"rxok":0,"rxfw":0,"ackr":100,"dwnb":0,"txnb":0}} // rxpk(节点上行)—— 真正的业务数据,时间用 RFC3339 {"rxpk":[{"time":"2026-10-14T08:44:52.025Z","freq":868.1,"modu":"LORA", "datr":"SF7BW125","codr":"4/5","rssi":-42,"lsnr":9.8,"size":18,"data":"<base64>"}]}ChirpStack Gateway Bridge 对两种包用两套时间解析器——心跳要YYYY-MM-DD HH:MM:SS GMT,上行要 ISO 8601。
3. 拼装 LoRaWAN 物理帧
rxpk.data里是一整帧 LoRaWAN 物理层数据,需要按协议拼装:
MHDR(1) + FHDR(7) + FPort(1) + FRMPayload(加密) + MIC(4)两个加密环节是最容易写错的地方:
- FRMPayload 加密:用 AppSKey 做 AES-128,构造 A 块(0x01 | 0x00×4 | Dir | DevAddr | FCnt | 0x00 | i)
- MIC 计算:用 NwkSKey 做AES-CMAC,构造 B0 块后取前 4 字节
写 AES-CMAC 时,必须把子密钥 K1/K2 异或进最后一个数据块再加密。
A 块和 B0 块里的DevAddr 和 FCnt 都是小端(LSB first)。用大端写,表现为 MIC 校验失败。
4. 运行效果
此时打开 ChirpStack:
- Gateway 页面显示 Online
- Device 页面 → Events / LoRaWAN frames里能看到每一条上行帧
5. 排障利器:tcpdump
链路不通时先抓包,确认 UDP 层有没有数据进出:
tcpdump -i any port 1700 -vv- 有进有出 → 问题在应用层(密钥/MIC/帧计数器)
- 只有出没有进 → 网关没发或发错地址(检查 server_address)
六、应用侧对接:订阅 MQTT
数据到了 ChirpStack 之后,业务应用不需要调任何 REST 接口,只要订阅 MQTT 主题:
application/+/device/+/event/up在嵌入式端,用 libmosquitto 起一个线程轮询即可(示例为 C):
mosquitto_subscribe(mq, NULL, "application/+/device/+/event/up", 0); /* 收到消息后:从 JSON 提取 data 字段 → base64 解码 → 按约定解析 */ int16_t t = (int16_t)((bin[0] << 8) | bin[1]); /* 温度 ×10 ℃ */ int16_t h = (int16_t)((bin[2] << 8) | bin[3]); /* 湿度 ×10 %RH */ uint8_t b = bin[4]; /* 电量 % */本例约定的应用负载(FPort=2,共 5 字节,大端):
偏移 | 类型 | 含义 |
0–1 | int16 BE | 温度 ×10 ℃ |
2–3 | int16 BE | 湿度 ×10 %RH |
4 | uint8 | 节点电量 % |
解析完写入本地数据模型,既能驱动 HMI 显示,也能通过 MQTT 转发到云平台(如华为云 IoTDA)、或者写数据库都可以——边缘侧闭环采集 + 上云两不误。
七、延伸
- 边缘自闭环:把分析+决策放在网关板上,只把结果上云,能大幅节省流量并降低响应延迟。
- 多节点组网:同一网关可接入数百个节点,“无线环境监测"可以平滑扩展到"无线振动监测”“无线表计抄读”。
- 协议透明:业务层只认 MQTT 主题和 payload 约定,射频方案的升级(SX1302→SX1303、LoRaWAN 1.0.3→1.1)不会波及上层代码。
八、总结
本次实操在 SBC2332 单板上搭建一体化 LoRaWAN 网关,将射频网关与 ChirpStack 网络服务器部署在同一板子,实现断网可用的边缘自治采集。使用 SX1302 网关硬件,搭配脚本模拟 ABP 节点,完成 Semtech UDP 协议、LoRaWAN 帧加密校验、MQTT 业务数据解析全链路验证。为中小工业现场的本地化 LoRaWAN 部署提供工程方案。