第四章 LoRaWAN网络服务器:ChirpStack开源平台搭建

聊到LoRaWAN,很多人第一反应是硬件——网关、节点、模块。但说实话,真正让整个系统跑起来的灵魂,是网络服务器。我最早接触LoRa时也犯过这个错:花大价钱买了网关,结果发现数据收上来不知道怎么处理。后来才明白,网络服务器才是那个「承上启下」的关键角色。

今天咱们就聊聊ChirpStack,这个目前最主流的开源LoRaWAN网络服务器。我个人习惯用它来做原型验证,甚至一些小规模商用量产也完全扛得住。

4.1 ChirpStack是什么?

ChirpStack,原名LoRaServer,是一个开源的LoRaWAN网络服务器实现。它负责管理网关、处理设备入网、解析数据包、转发应用数据。说白了,它就是LoRaWAN网络的大脑。

它的架构分三层:

  • ChirpStack Gateway Bridge:负责把网关的UDP数据转成MQTT,说白了就是翻译官
  • ChirpStack Network Server:核心服务,处理MAC层协议、设备激活、数据加解密
  • ChirpStack Application Server:应用层接口,提供REST API和Web界面

我在项目中遇到过有人想自己写网络服务器,结果折腾了三个月连设备入网都没搞定。嗯,专业的事交给专业的工具,ChirpStack就是那个工具。

4.2 环境准备

搭建之前,先把环境准备好。我建议用Ubuntu 20.04 LTS,稳定、社区支持好。硬件方面,一台2核4G的云服务器或者树莓派4B都行。

需要安装的依赖:

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装Docker和Docker Compose
sudo apt install docker.io docker-compose -y

# 启动Docker服务
sudo systemctl enable docker
sudo systemctl start docker

# 把当前用户加入docker组(避免每次sudo)
sudo usermod -aG docker $USER

这里有个坑:加入docker组后要重新登录才能生效。我曾经忘了这一步,结果折腾了半小时才发现是权限问题。

4.3 使用Docker Compose一键部署

ChirpStack官方提供了Docker Compose文件,这是最省事的部署方式。我个人习惯用这种方式,升级维护都方便。

创建一个项目目录:

mkdir ~/chirpstack && cd ~/chirpstack

下载官方docker-compose.yml:

wget https://raw.githubusercontent.com/brocaar/chirpstack-docker/master/docker-compose.yml
wget https://raw.githubusercontent.com/brocaar/chirpstack-docker/master/configuration/chirpstack-network-server/chirpstack-network-server.toml
wget https://raw.githubusercontent.com/brocaar/chirpstack-docker/master/configuration/chirpstack-application-server/chirpstack-application-server.toml

启动服务:

docker-compose up -d

等几分钟,访问 http://你的服务器IP:8080,就能看到ChirpStack的Web界面了。默认账号密码是 admin / admin

小提示:第一次登录后记得改密码。我在客户现场见过有人用默认密码跑了半年,想想都后怕。

4.4 网络服务器配置

登录进去后,第一件事是配置网络服务器。点左侧菜单的「Network-servers」,然后「Add」。这里要填的是Network Server的内部地址。

关键配置项:

配置项 说明 推荐值
Name 网络服务器名称 随便起,比如「MyNS」
Server Network Server地址 chirpstack-network-server:8000
Gateway Discovery 是否开启网关发现 建议开启

你想想看,如果这里填错了,网关连不上,后面所有工作都白费。我建议填完后先保存,然后去「Gateways」页面看看有没有网关连上来。

4.5 网关接入

网关接入是另一个容易出问题的地方。ChirpStack默认使用Semtech UDP协议,网关需要把数据发到Network Server的1700端口。

以常见的RAK7249网关为例,配置如下:

# 在网关的配置文件中
server_address: "你的服务器IP"
server_port_up: 1700
server_port_down: 1700

配置完重启网关,然后在ChirpStack的「Gateways」页面应该能看到网关上线。如果看不到,八成是防火墙没开1700端口。我曾经被这个问题卡了一整天,最后发现是云服务商的安全组规则没配。

注意:UDP协议没有重传机制,网络不稳定时容易丢包。建议网关和服务器之间用有线网络,或者至少保证WiFi信号稳定。

4.6 应用服务器集成

网络服务器搞定了,接下来要把数据送到你的业务系统里。ChirpStack提供了两种方式:

  • HTTP集成:数据通过POST请求发送到你的API
  • MQTT集成:数据发布到MQTT Broker,你的应用订阅即可

我个人更推荐MQTT方式,实时性好,而且解耦。配置方法:

  1. 在ChirpStack的「Applications」页面创建一个应用
  2. 添加一个设备(Device),填入DevEUI、AppKey等信息
  3. 在「Integrations」里选择MQTT
  4. 配置MQTT Broker地址(默认就是本机的Mosquitto)

然后你的应用就可以订阅 application/你的应用ID/device/设备EUI/event/up 这个主题来接收上行数据了。

4.7 数据流解析

数据到了MQTT,但它是Base64编码的,需要解码才能用。举个例子:

{
  "applicationID": "1",
  "deviceName": "temp-sensor-01",
  "devEUI": "a84041aabbccddee",
  "rxInfo": [{
    "gatewayID": "a84041ffffffffff",
    "rssi": -85,
    "loRaSNR": 9.5
  }],
  "txInfo": {
    "frequency": 868100000,
    "dr": 5
  },
  "adr": true,
  "fCnt": 10,
  "fPort": 1,
  "data": "AQIDBA=="
}

这里的 data 字段是Base64编码的。用Python解码:

import base64
import json

# 假设这是从MQTT收到的消息
payload = '{"data": "AQIDBA=="}'
msg = json.loads(payload)
raw_data = base64.b64decode(msg["data"])
print(raw_data)  # 输出: b'\x01\x02\x03\x04'

解码后的字节数据怎么解析?这取决于你的设备上报格式。我习惯在设备端用简单的字节协议,比如第一个字节是温度高8位,第二个是低8位。这样解析起来快,而且省流量。

核心要点:ChirpStack只负责传输和转发,不关心你的数据格式。数据怎么编码、怎么解析,完全由你的应用决定。这就是「网络服务器」和「应用服务器」的分界线。

4.8 避坑指南

最后分享几个我踩过的坑:

  • 时间同步问题:ChirpStack依赖系统时间,如果服务器时间不准,设备入网会失败。建议装个NTP服务。
  • 数据库备份:ChirpStack默认用PostgreSQL,数据都在里面。我建议每天备份一次,不然设备配置丢了重建很痛苦。
  • 日志查看:出问题先看日志。命令是 docker-compose logs -f chirpstack-network-server,大部分问题日志里都有提示。

嗯,这一章的内容差不多就这些。ChirpStack的搭建其实不难,难的是理解整个数据流转的过程。下一章咱们聊聊设备入网的那些事,包括OTAA和ABP两种激活方式的区别,以及我在实际项目中踩过的坑。