本文旨在帮助已经购买RAK商业网关产品并且使用内置LoRa Server功能的用户,了解如何通过MQTT订阅商业网关内置LoRa Server的数据,使用户了解商业网关的工作原理,方便用户在自己的应用服务器获取节点数据,达到便捷使用应用服务器完成数据展示和数据分析的目的。
本文将以RAK公司的商业网关产品(室内网关RAK7258或室外网关RAK7249)为例,介绍如何配置商业网关使用内置MQTT服务器和私有(外置)MQTT服务器,以及如何订阅节点数据和向节点发送数据等。
本章节介绍LoRaWAN网络和MQTT网络,用于帮助用户对LoRaWAN和MQTT的工作原理有一个简单直观的了解。如果您已经熟悉了LoRaWAN和MQTT的工作原理,可跳过此章节。
从上图可以看出,LoRaWAN网络包括如下3个角色,各个角色的作用如下所示:
RAK简化LoRaWAN实际部署条件,RAK商业网关集成了NS服务器,它配合节点可以轻松搭建LoRaWAN网络。
MQTT代表MQ遥测传输,是一种发布/订阅极其简单和轻量级的消息传递协议,用于受限设备和低带宽、高延迟或不可靠的网络。设计原则是使网络带宽和设备资源要求最小化以及确保可靠性。这些原则使该协议成为物联网世界的理想选择。
Figure 2: MQTT网络角色
如上图所示,MQTT网络角色包括如下3个,各个角色的作用如下所示:
MQTT Broker同比是新闻发布网站,发布者是新闻发布成员,订阅者是浏览、查看新闻的用户。
实际应用1:使用RAK商业网关内置的MQTT Broker功能。
RAK商业网关获取数据并发送给内置NS,内置NS将数据发布至内置的MQTT Broker,用户通过第三方程序订阅数据。这种应用情况下,RAK商业网关既是发布者,又是MQTT Broker。
注意:
实际应用2:使用用户私有的MQTT Broker功能。
RAK商业网关获取数据并发送给内置NS,内置NS将数据发布至第三方MQTT Broker,用户通过第三方程序订阅数据。这种应用情况下,RAK商业网关仅为发布者。
本节以RAK商业网关为例,介绍如何通过MQTT.fx工具订阅节点上报的数据和向节点发送数据。您可以通过单击MQTT.fx下载MQTT.fx工具(MQTT客户端)。
1、在浏览器地址栏中输入商业网关的IP地址192.168.230.1,按"Enter",进入如下界面。
Figure 4: 商业网关登录界面
2、在打开的商业网关登录界面中输入用户名和密码,单击"Login"。
默认用户名和密码都为root。
3、在左侧导航栏中选择“LoRa Network > Network Settings”。
4、在“LoRaWAN Network Settings”界面上,设置"Mode"为"Network Server"模式。
Figure 5: 配置RAK7249使用内置服务器
5、单击“Switch mode”切换模式。
约15秒左右,网关即可切换为Network Server模式。在该模式下,商业网关既是网关,又是NS服务器。
1、在商业网关左侧导航栏中选择“LoRa Network > Application”,进入应用概览页面。
2、输入应用名称,单击“Add”,如下图所示。
注意:
本示例采用"Type1 : Unified Application Key",即同一Application中,所有节点设备使用相同的Application Key。不需要单独为设备设置Application Key。支持通过OTAA自动添加设备。如果您想使用“Type2 : Separate Application Key”,请参考Web 平台配置指南。
Figure 6: 新增应用
在应用配置页面根据页面提示配置应用信息,如下图所示。
Figure 7: 配置应用
注意:您也可以使用Micro USB线连接节点设备到PC,后使用串口工具打开相应端口分别发送AT+APPEUI
和AT+APPKEY
获取Application EUI和Application Key的值后填写到此处,可省去后续配置节点的步骤。本示例采用系统自动生成的方法。
4、单击"Save & Apply"保存配置。
5、在系统自动返回的应用概览页面,单击"Edit"进入应用配置页面添加节点。
Figure 8: 应用概览页面
6、输入节点的Device EUI后,单击“Add”,如下图所示。Device EUI可在节点设备的标签上获取,也可使用Micro USB线连接节点设备到PC,后使用串口工具打开相应端口发送AT+DEVEUI
进行查询。
7、在节点配置页面配置节点设备信息,如下图所示。
Figure 10: 配置节点设备信息
8、单击"Save & Apply"保存配置。
用户可通过商业网关内置的Application Server Integration功能使用MQTT客户端订阅NS Topic消息来获取节点数据,也可以使用MQTT客户端向节点发送数据。
1、在商业网关左侧导航栏中选择"LoRa Network > Global Integration"。
2、在"Application Server Integration"页面上,设置应用服务器集成的相关参数。
如果使用内置的MQTT Broker,则“MQTT Broker Address”和“MQTT Broker Port”参数的值保持默认即可。如果您不了解MQTT协议的topic,建议保持MQTT topic相关参数的默认配置。此处使用内置的MQTT Broker,全部参数保持默认配置,如下图所示。
Figure 11: 配置商业网关使用内置的MQTT Broker
3、单击"Save & Apply"保存配置。
1、打开MQTT.fx工具,主界面如下图所示。
Figure 12: MQTT.fx工具主界面
2、单击左上角的新建图标,如下图所示。
Figure 13: 新建图标
3、在下图中红框处输入网关的IP地址。
Figure 14: 输入网关的IP地址
4、单击“Connect”。最右侧的黑色圆形变成绿色,说明已经成功连接到网关内置的MQTT Broker。
Figure 15: 成功连接到网关内置的MQTT Broker
5、选择“Subscribe”页签。
6、在“Subscribe”页签的输入框中输入待订阅的topic,单击输入框右侧的“Subscribe”。
输入待订阅的topic时,topic的格式应该与商业网关"Application Server Integration"页面上Uplink Topic的格式保持一致,如下图所示,其中,application_ID需要替换成实际的application ID的值,device_EUI需要替换成节点的device_EUI的值。
Figure 16: Uplink Topic参数
application ID的值和device_EUI的值请参考下面两个图来获取。
Figure 17: 获取application IDFigure 18: 获取device_EUI
以上面两个图中获取的application ID和device_EUI的值为例,则需要在输入框中输入的topic为:application/2/device/00d939567c667e1e/rx,如下图所示。
· 如果要订阅一个应用下的所有节点数据,例如:要订阅应用2下的所有节点数据,则需要输入如下topic:
application/2/device/+/rx
· 如果要订阅所有应用下的所有节点数据,则需要输入如下topic:
application/+/device/+/rx
7、使用节点成功join之后发送一条数据。例如:要在节点侧发送一条“HelloRakwireless”,因为节点需要接收16进制的数据,将“Hello Rakwireless”转换为16进制,即“48656c6c6f52616b776972656c657373”,则发送的AT命令如下图所示。
Figure 20: 在节点侧发送数据示例
8、在MQTT.fx界面上查看已订阅的节点数据,如下图所示。
Figure 21: 在MQTT.fx界面上查看已订阅的节点数据
上图中"data"字段的值即为节点发送的数据,只是这些数据进行了base64编码,对"data"字段的值进行base64解码后即可看到原始数据。
9、查看商业网关web管理界面上节点发送的数据是否与MQTT.fx界面上一致。
Figure 22: 查看商业网关web管理界面
1、在MQTT.fx工具的主界面上,选择“Publish”页签。
2、在“Publish”页签的输入框2中输入topic,在输入框3中输入{"confirmed": true,"data": "SGVsbG8=","fPort":10},单击“Publish”。
注意:
{"confirmed": true,"data": "SGVsbG8=","fPort": 10}中字段的说明如下所示:
"confirmed"的取值包括true和false。
"data"的取值即要发送的数据,需要对数据进行base64编码。
"fPort"的取值即要发送的端口号,有效端口号为1~255。
输入topic时,topic的格式应该与商业网关"Application Server Integration"页面上Downlink Topic的格式保持一致,如下图所示,其中,application_ID需要替换成实际的application ID的值,device_EUI需要替换成节点的device_EUI的值。
Figure 23: Downlink Topic参数
application ID的值和device_EUI的值请参考下面两个图来获取。
Figure 24: 获取application IDFigure 25: 获取device_EUI
以上面两个图中获取的application ID和device_EUI的值为例,则需要在输入框2中输入的topic为:application/2/device/00d939567c667e1e/tx,如下图所示。
Figure 26: 通过MQTT.fx向节点发送数据
注意:
通过MQTT.fx客户端向节点发送数据后,Class C模式下节点会立刻收到MQTT.fx下发的数据,Class A模式下节点会在下一次上发数据之后收到MQTT.fx下发的数据。
3、在节点端查看接收到的数据,如下图所示。
Figure 27: 查看节点端接收到的数据
本节介绍在商业网关上配置用户私有的MQTT Broker信息、连接MQTT客户端与用户私有的MQTT Broker、通过MQTT客户端订阅节点数据和通过MQTT客户端向节点发送数据的具体方法。
1、在商业网关左侧导航栏中选择"LoRa Network > Global Integration"。
2、在"Application Server Integration"页面上,设置应用服务器集成的相关参数。
如果要使用用户私有的MQTT Broker,则需要配置如下参数。
如果您不了解MQTT协议的topic,建议保持MQTT topic相关参数的默认配置。
此处使用用户私有的MQTT Broker且保持MQTT topic相关参数的默认配置,如下图所示。
Figure 28: 配置商业网关使用用户私有的MQTT Broker
3、单击"Save & Apply"保存配置。
1、打开MQTT.fx。
2、单击设置图标,如下图所示。
Figure 29: 设置图标
系统弹出“Edit Connection Profiles”对话框。
3、在“Edit Connection Profiles”对话框中,单击左下角的+。
4、设置“Profile Name”、“Broker Address”、"Broker Port",单击“User Credentials”,输入“User Name”和“Password”,如下图所示。
Figure 30: 新建Profile并配置参数
5、单击右下角的“OK”。
6、“Edit Connection Profiles”对话框自动关闭,MQTT.fx主界面中已自动选择了刚创建的Profile。
7、在MQTT.fx主界面中单击“Connect”。最右侧的黑色圆形变成绿色,说明已经成功连接到用户私有的MQTT Broker。
具体方法请参考通过MQTT.fx客户端订阅节点信息。
具体方法请参考通过MQTT.fx客户端向节点发送数据。
前面章节介绍了通过MQTT如何订阅节点的上行数据Uplink以及如何向节点下发数据Downlink,节点还有其他三种类型的数据,分别是Join、Ack和Status。其中Join是节点入网时的信息,Ack是向节点下发数据之后节点回复的确认信息,Status是节点的电池电量信息。
下面将分别介绍这五种数据的具体格式和含义。
{
"applicationID": "1", // 节点所属应用的id
"applicationName": "test-app", // 节点所属应用的名称
"devEUI": "3637343457387e11", // 节点的devEUI
"deviceName": "dev-5205", // 节点名称
"timestamp": 1592730721, // 接收到节点数据的Unix时间戳
"fCnt": 6,
"fPort": 2,
"data": "AQIDBA==", // base64编码后的数据,解码之后就是节点实际上发的数据
"data_encode": "base64", // 数据的编码类型
"adr": true, // 节点是否开启了adr
"rxInfo": [ // 所有接收到节点数据的网关信息
{
"gatewayID": "d896e0fff010611e", // 网关的gateway_id
"loRaSNR": 13.3, // 当前网关的信噪比
"rssi": -71, // 当前网关的RSSI
"location": { // 对应网关的经纬度以及海拔信息
"latitude": 0,
"longitude": 0,
"altitude": 0
}
}
],
"txInfo": {
"frequency": 486300000, // 节点发送数据使用的的频率
"dr": 2 // 节点当前的data rate
}
}
{
"devEUI":"3637343457387e11", // 节点的devEUI信息
"confirmed": true, // This dl pkt need confirm or not.
"fPort": 2, // The port will be used for sending this packet
"data": "AgAAAA==" // 发送给节点的数据,经过base64编码
}
{
"applicationID": "1",
"applicationName": "test-app",
"deviceName": "dev-5205",
"devEUI": "3637343457387e11",
"devAddr": "02000001" // Join成功之后分配给节点的短地址
}
只有服务器给节点下发了confirmed类型的数据后,节点才会回复Ack。
注意:节点不一定立即回复Ack,Ack可能会在节点下一次发送上行数据时携带。
{
"applicationID": "1",
"applicationName": "test-app",
"deviceName": "dev-5205",
"devEUI": "3637343457387e11",
"acknowledged": true,
"fCnt": 7
}
{
"applicationID": "1",
"applicationName": "test-app",
"deviceName": "dev-5205",
"devEUI": "3637343457387e11",
"battery": 254, // 电池剩于电量的分级。254表示电源满电状态,1表示电池电量即将耗尽。
"margin": 8, // 是最近一次成功接收DevStatusReq命令的解调信噪比
"externalPowerSource": false, // 是否使用了额外的电源
"batteryLevelUnavailable": false, // 节点的电量级别是否有效
"batteryLevel": 100 // batteryLevelUnavailabl为true的情况下,batteryLevel表示电量百分比
}
以下是使用python代码调用MQTT订阅节点的上行数据并将对应内容打印出来,每收到一条上行数据,程序会主动向节点发送一个下行数据,内容是“Hello rak”。使用代码前请仔细阅读代码注释。
以下源码基于python3运行环境,在运行代码前,需要使用命令pip3 install paho-mqtt
安装依赖库。
#!/usr/bin/env python
import json
import base64
import paho.mqtt.client as mqtt
from datetime import datetime
\# mqtt服务器IP
mqtt_ip = '111.230.247.253'
\# mqtt服务器端口
mqtt_port = 1883
\# mqtt用户名
mqtt_username = 'rakwireless'
\# mqtt密码
mqtt_password = 'rakwireless.com'
\# mqtt订阅topic。该topic可以订阅所有节点信息
mqtt_rx_topic = 'application/+/device/+/rx'
\# 将字符串转换为16进制
def str_to_hex(s):
return r"\x"+r'\x'.join([hex(ord(c)).replace('0x', '') for c in s])
\# 一旦订阅到消息,回调此方法
def on_message(mqttc, obj, msg):
on_print_rak_node_info(msg.payload)
\# 打印订阅到的节点信息
def on_print_node_rx_info(json_rx):
try:
devEUI = json_rx['devEUI']
applicationID = json_rx['applicationID']
applicationName = json_rx['applicationName']
deviceName = json_rx['deviceName']
timestamp = json_rx['timestamp']
fCnt = json_rx['fCnt']
fPort = json_rx['fPort']
data = json_rx['data']
data_hex = str_to_hex(base64.b64decode(data).decode("utf-8"))
\# 将时间戳转换为本地时间
str_local_time = datetime.fromtimestamp(timestamp)
print('---------------- devEUI:[%s] rxpk info -------------------' % devEUI)
print('+\t applicationName:\t%s' % applicationName)
print('+\t applicationID:\t\t%s' % applicationID)
print('+\t deviceName:\t\t%s' % deviceName)
print('+\t datetime:\t\t%s' % str_local_time)
print('+\t fCnt:\t\t\t%d' % fCnt)
print('+\t fPort:\t\t\t%d' % fPort)
print('+\t data:\t\t\t%s' % data)
print('+\t data_hex:\t\t%s' % data_hex)
print('----------------------------------------------------------')
except Exception as e:
print(e)
finally:
pass
\# 订阅到节点的数据之后,向节点发送“Hello rak”字符串
def on_print_rak_node_info(payload):
json_str = payload.decode()
try:
json_rx = json.loads(json_str)
on_print_node_rx_info(json_rx)
dev_eui = json_rx['devEUI']
app_id = json_rx['applicationID']
\# 商业网关默认的tx topic
tx_topic = 'application/%s/device/%s/tx' % (app_id, dev_eui)
str_hello = "Hello Rak"
tx_msg = '{"confirmed":true,"fPort":10,"data":"%s" }' % str(base64.b64encode(str_hello.encode("utf-8")), "utf-8")
\# 发布消息
mqttc.publish(tx_topic, tx_msg, qos=0, retain=False)
print('Send \'Hello rak\' to node %s' % dev_eui)
except Exception as e:
raise e
finally:
pass
mqttc = mqtt.Client()
mqttc.on_message = on_message
\# 如果没有用户名和密码,请注释改行
mqttc.username_pw_set(mqtt_username, password=mqtt_password)
\# 连接mqtt broker,心跳时间为60s
mqttc.connect(mqtt_ip, mqtt_port, 60)
mqttc.subscribe(mqtt_rx_topic, 0)
mqttc.loop_forever()
全部0条评论
快来发表一下你的评论吧 !