我们在上一节《【ODYSSEY-STM32MP157C】驱动 UART 读取传感器数据》 已经成功读取到 PMS5003ST 传感器的数据,本节我们将学习如何将设备接入阿里云 IoT 平台,并上报数据到云端。
准备材料
- 阿里云:阿里云物联网平台账号
- Seeed:ODYSSEY-STM32MP157C 开发板
- 攀藤:PMS5003ST 传感器
创建产品与设备
登录阿里云物联网平台,进入“控制台”,选择“设备管理” -> “产品”页面,创建产品。
添加自定义功能,我在这里共添加了 6 个属性,分别是 PM1.0、PM2.5、PM10、甲醛浓度、温度、湿度。具体标识符、数据类型和范围如下所示。
在“设备管理” -> “设备”页面,点击“添加设备”,为该产品增加一个测试设备。
设备创建成功后,我们将得到设备三元组信息(ProductKey、DeviceName、DeviceSecret),这就是设备连接阿里云 IoT 平台的凭证。保存起来,我们一会儿就会用到。
连接测试
同样,我们使用 Python 来完成本次任务。首先安装 paho-mqtt 库:
pip3 install paho-mqtt
进入 Python3 交互环境,导入相关软件库
import paho.mqtt.client as mqtt
import time
import hashlib
import hmac
import random
import json
将前面创建的设备三元组信息填入 options 对象(记得替换成你自己的三元组哦):
options = {
'productKey':'a16CxOWWTpI',
'deviceName':'D001',
'deviceSecret':'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'regionId':'cn-shanghai'
}
创建 HOST 和 PORT 变量:
HOST = options['productKey'] + '.iot-as-mqtt.'+options['regionId']+'.aliyuncs.com'
PORT = 1883
因为连接阿里云 IoT 平台是需要构建 Client ID、User name 和 Password 等参数,因此添加一个 hmacsha1 函数:
def hmacsha1(key, msg):
return hmac.new(key.encode(), msg.encode(), hashlib.sha1).hexdigest()
添加 client 构建函数:
def getAliyunIoTClient():
timestamp = str(int(time.time()))
CLIENT_ID = "paho.py|securemode=3,signmethod=hmacsha1,timestamp="+timestamp+"|"
CONTENT_STR_FORMAT = "clientIdpaho.pydeviceName"+options['deviceName']+"productKey"+options['productKey']+"timestamp"+timestamp
# set username/password.
USER_NAME = options['deviceName']+"&"+options['productKey']
PWD = hmacsha1(options['deviceSecret'],CONTENT_STR_FORMAT)
client = mqtt.Client(client_id=CLIENT_ID, clean_session=False)
client.username_pw_set(USER_NAME, PWD)
return client
好啦,接下来可以创建一个 client 对象,并尝试连接阿里云 IoT 平台啦~
>>> client = getAliyunIoTClient()
>>> client.connect(HOST, PORT, 300)
0
切换到阿里云物联网平台的控制台,刷新一下,看看 D001 设备是不是由“离线”状态变成“在线”状态。
上报数据
连接成功,意味着我们的 ODYSSEY-STM32MP157C 开发板已经成为该产品的一个设备了。为了完成传感器数据采集、上报任务,我们新建一个 upload_pms5003st.py 文件。
融合上一节的 show_pms5003st.py 和连接阿里云 IoT 平台的代码,整体框架如下:
import paho.mqtt.client as mqtt
import time
import hashlib
import hmac
import random
import json
import sys
import glob
import serial
options = {
'productKey':'',
'deviceName':'',
'deviceSecret':'',
'regionId':'cn-shanghai'
}
HOST = options['productKey'] + '.iot-as-mqtt.'+options['regionId']+'.aliyuncs.com'
PORT = 1883
PUB_TOPIC = "/sys/" + options['productKey'] + "/" + options['deviceName'] + "/thing/event/property/post"
dev_name = '/dev/ttySTM2'
baudrate = 9600
CMD_READ = bytearray([0x42, 0x4d, 0xe2, 0x00, 0x00, 0x01, 0x71])
CMD_PASS = bytearray([0x42, 0x4d, 0xe1, 0x00, 0x00, 0x01, 0x70])
CMD_ACTI = bytearray([0x42, 0x4d, 0xe1, 0x00, 0x01, 0x01, 0x71])
CMD_STAN = bytearray([0x42, 0x4d, 0xe4, 0x00, 0x00, 0x01, 0x73])
CMD_NORM = bytearray([0x42, 0x4d, 0xe4, 0x00, 0x01, 0x01, 0x74])
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# client.subscribe("the/topic")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
def hmacsha1(key, msg):
return hmac.new(key.encode(), msg.encode(), hashlib.sha1).hexdigest()
def getAliyunIoTClient():
# 忽略
def pms_value(hByte, lByte):
return (hByte << 8 | lByte)
def loop(serial):
while True:
# 忽略
time.sleep(5)
def main():
print("Run ODYSSEY-uart demo")
s = serial.Serial(dev_name, baudrate)
try:
s.write(CMD_PASS)
except Exception as err:
print(err)
finally:
time.sleep(1)
loop(s)
s.close()
if __name__ == '__main__':
client = getAliyunIoTClient()
client.on_connect = on_connect
client.on_message = on_message
client.connect(HOST, 1883, 300)
main()
client.loop_forever()
上报数据在 loop 函数中处理,当获取到传感器数据后,将对应的 6 个属性值封装成 JSON 格式的数据,然后通过发布消息即可。
payload_json = {
'id': int(time.time()),
'params': {
'PM1_0' : PM1_0_atm,
'PM2_5' : PM2_5_atm,
'PM10_0': PM10_0_atm,
'HCHO' : hcho/1000,
'TEMP' : temp,
'HUMI' : humi
},
'method': "thing.event.property.post"
}
print('upload data to iot server: ' + str(payload_json))
client.publish(PUB_TOPIC, payload=str(payload_json), qos=1)
完整代码请看 https://github.com/luhuadong/ODYSSEY-STM32MP157C 。
运行 python3 upload_pms5003st.py
,每次上报数据会打印出 JSON 消息。
upload data to iot server: {
'id': 1601621228, 'params': {
'PM1_0': 24, 'PM2_5': 39, 'PM10_0': 45, 'HCHO': 0.0, 'TEMP': 27.6, 'HUMI': 52.1}, 'method': 'thing.event.property.post'}
在阿里云 IoT 平台页面,打开设备的物模型数据,可以看到周期上报的数据。
好啦,到这里,我们已经完成了从串口获取传感器数据,再将数据上报到云端的工程,实现了一个物联网应用雏形。真棒!休息一下吧~