micropython连接onenet实现从应用端调用api到设备端执行-汇总-优快云博客
↑汇总
目录
micropython通过umqtt连接至onenet-下发命令-优快云博客
上一步↑
建议直接用文末的代码,一步一步的对照着看
下一步↓
这一步我们主要通过get直接向设备请求信息,这里要区别设备post到平台的数据,该get方法是客户app或者其他应用直接向设备请求当前的信息,不知道大家有没有看第一篇应用篇的api。↓
python调用onenet平台api读取和下发命令(应用端的尝试)-优快云博客
这里面有三个方法
(1).Get_Platform_DiveceData
这个是直接读取平台的数据,就是我们micropython调用umqtt的public指令上传数据到平台-优快云博客
这一步的post上传到平台的数据,这一过程直接向平台请求
(2).Set_DiveceData
这个好分辨,直接设置设备的属性,即下发的命令,对应:
micropython通过umqtt连接至onenet-下发命令-优快云博客
这一步设置的属性到设备里面可以控制开关,3d打印机仓温设定,操控其他设备通讯等等
(3).Get_DiveceData
不同1,直接是应用端直接向设备单独发送一次获取信息的请求,平台这时候只是中间商代理传递我们的请求和回复请求.这一步设备会接受一个需要上传的信息,我们把相应的信息上传即可.这一步对应本篇文章.
1我们订阅topic用来接收设备发来的请求信息
topic:
"$sys/{Productid}/{DeviceName}/thing/property/get"
代码
client.Subscribe_topic(get_topic = "$sys/xsH8t9odKK/stm32/thing/property/get")
如果成功我们可以在平台调试工具下发指令
2在回调函数里面分辨是哪个topic的消息
def on_message(topic, msg):
topic = topic.decode('utf-8')
msg = json.loads(msg.decode('utf-8'))
global replay_msg
global replay_state_code
topic = topic.split("/")[-1]
if topic == "reply":
if msg["msg"] == "success":
replay_state_code = topic
if topic == "set":
replay_state_code = topic
replay_msg = msg
if topic == "get":
replay_state_code = topic
replay_msg = msg
print(msg)
传回topic的主题和msg信息
同时设备打印出消息
{
"id": "106",
"version": "1.0",
"params": ["led", "brightness"]
}
这里我们要提取id用于回复,提取出para里面的属性名用于回复
3处理信息并返回数据
我们先写俩个随机数函数用来伪装为数据
def get_sensor_data():
data = random.randint(0,100)
return data
def get_led_state():
data = random.randint(0,1)
if data == 1:
return True
else:
return False
然后再主函数里面
try:
while True:
client.client.check_msg() # 检查是否有新的消息
# 你可以在这里执行其他操作,例如读取传感器数据等
print("Performing other tasks...")
# if replay_state_code == "reply":
# print("Post success")
# replay_state_code = None
# # break
# if replay_state_code =="set":
# wait_handle_msg = replay_msg
# replay_id = wait_handle_msg["id"]
# print(replay_id)
# client.Set_replay(replay_id)
# params = wait_handle_msg.get("params", {})
# for key,value in params.items():
# if key =="led":
# print(value)
# print(type(value))
# replay_msg = None
# replay_state_code = None
# break
if replay_state_code == "get":
wait_replay_msg = replay_msg
get_replay_id = wait_replay_msg["id"]
data={}
for params in wait_replay_msg["params"]:
if params=="brightness":
data[params] = get_sensor_data()
if params=="led":
data[params] = get_led_state()
# print(data)
client.Get_replay(get_replay_id,data)
print("Data has post to client")
# print(data)
replay_msg = None
replay_state_code = None
time.sleep(1)
except KeyboardInterrupt:
print("MQTT subscription stopped.")
finally:
client.client.disconnect()
每次循环check一下是否有新消息,有就进入中断回调函数即3中的函数中判断是哪个topic,判断完后回到主函数,再 处理数据。我们遍历字典的params里面的列表得到参数属性,将参数属性用随机数生成的数据赋值再上传给平台,平台转发给用户。
这个上传用的类的方法函数如下
用的topic为"$sys/{Productid}/{DeviceName}/thing/property/get_reply"
self.get_replay_topic = f"$sys/{user}/{client_id}/thing/property/get_reply"
def Get_replay(self,msg_id,replay_data):
data = self.get_replay
data["id"]=msg_id
data["data"]=replay_data
data = json.dumps(data)
self.client.publish(self.get_replay_topic,data)
print(data)
pass
这时候我们就可以上传数据了运行程序,平台的调试工具下发指令
设备收到
设备回应
平台侧看到回应
总结,这个topic主要在应用端开始时应用,如app打开后读取一下设备各个状态的属性,比较占用设备的处理。
至此我们实现了常用的三个功能,下一步我们把第一步的应用端加进来,复合三个功能做一次物联网的简单通讯。
改进建议,可以把上传和收到消息做异步处理挂起,其他像单片机读取传感器信息也挂起做协程。micropython是基于rtos的,有uasyncio的函数可以实现,本文不过多赘述。
到这一步的代码
import onenet_device_token
from umqtt.robust import MQTTClient
from wifi_connect import wifi
import time
import random
import json
replay_msg = None
replay_state_code = None
token = None
ssid = "-"
password = ""
url = "mqtts.heclouds.com"
port = 1883
DeviceName = "" # 设备ID
Productid = "" # 产品ID
access_key = "=" # 秘钥
# post_topic = "$sys/xsH8t9odKK/stm32/thing/property/post"
# set_topic = "$sys/xsH8t9odKK/stm32/thing/property/set"
# set_replay_topic = "$sys/xsH8t9odKK/stm32/thing/property/set_reply"
def main():
global replay_msg
global replay_state_code
token = onenet_device_token.get_token(Productid,DeviceName,access_key,time=1735971695)
print(token)
wlan = wifi(ssid = ssid,password = password)
client = ONENET(client_id=DeviceName,server=url,port=port,user=Productid,keepalive=100,password=token)
#设置回调函数(必须要)
client.client.set_callback(on_message)
# client.Subscribe_topic(post_replay_topic="$sys/xsH8t9odKK/stm32/thing/property/post/reply")
# client.Post_Data(brightness=25,led=False)
#
# client.Subscribe_topic(set_topic = "$sys/xsH8t9odKK/stm32/thing/property/set")
client.Subscribe_topic(get_topic = "$sys/xsH8t9odKK/stm32/thing/property/get")
try:
while True:
client.client.check_msg() # 检查是否有新的消息
# 你可以在这里执行其他操作,例如读取传感器数据等
print("Performing other tasks...")
# if replay_state_code == "reply":
# print("Post success")
# replay_state_code = None
# # break
# if replay_state_code =="set":
# wait_handle_msg = replay_msg
# replay_id = wait_handle_msg["id"]
# print(replay_id)
# client.Set_replay(replay_id)
# params = wait_handle_msg.get("params", {})
# for key,value in params.items():
# if key =="led":
# print(value)
# print(type(value))
# replay_msg = None
# replay_state_code = None
# break
if replay_state_code == "get":
wait_replay_msg = replay_msg
get_replay_id = wait_replay_msg["id"]
data={}
for params in wait_replay_msg["params"]:
if params=="brightness":
data[params] = get_sensor_data()
if params=="led":
data[params] = get_led_state()
# print(data)
client.Get_replay(get_replay_id,data)
print("Data has post to client")
# print(data)
replay_msg = None
replay_state_code = None
time.sleep(1)
except KeyboardInterrupt:
print("MQTT subscription stopped.")
finally:
client.client.disconnect()
class ONENET():
posts_data ={
"id": "123",
"version": "1.0",
"params": {}
}
set_replay ={
"id": "30",
"code": 200,
"msg": "succ"
}
get_replay = {
"id":"102",
"code":200,
"msg":"succ",
"data":{
}
}
# post_topic = f"$sys/{Productid}/{DeviceName}/thing/property/post"
# post_replay_topic =f"$sys/{Productid}/{DeviceName}/thing/property/post/reply"
# set_replay_topic = f"$sys/{Productid}/{DeviceName}/thing/property/set_reply"
# get_replay_topic = f"$sys/{Productid}/{DeviceName}/thing/property/get_reply"
#======================================================================================
#作者:trashedmaker
#开源文件,未注明请勿转载
#原文链接:https://blog.youkuaiyun.com/m0_73949172/article/details/144929662?spm=1001.2014.3001.5501
#======================================================================================
def __init__(self,client_id,server,port,user,keepalive,password):
self.client_id = client_id
self.server = server
self.port = port
self.user = user
self.keepalive = keepalive
self.password = password
self.client =self.connect_mqtt(self.password)
self.id = None
self.post_topic = f"$sys/{user}/{client_id}/thing/property/post"
self.set_replay_topic = f"$sys/{user}/{client_id}/thing/property/set_reply"
self.get_replay_topic = f"$sys/{user}/{client_id}/thing/property/get_reply"
def connect_mqtt(self,token):
client = MQTTClient(client_id=self.client_id,server=self.server,port=self.port,user=self.user,keepalive=self.keepalive,password=self.password)
while 1:
try:
client.connect()
print('Has Connected to OneNET')
break
# 0 CONNECTION_ACCEPTED - 连接成功
# 1 CONNECTION_REFUSED_PROTOCOL_VERSION - 版本号错误
# 2 CONNECTION_REFUSED_IDENTIFIER_REJECTED - 连接标识符被拒绝
# 3 CONNECTION_REFUSED_SERVER_UNAVAILABLE - 服务器不可用
# 4 CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD - 错误的用户名或密码
# 5 CONNECTION_REFUSED_NOT_AUTHORIZED - 没有权限
except Exception as e: # 捕获所有异常
print(f"Something went wrong: Wrong code is {e}") # 打印错误信息
print("We are trying again...")
time.sleep(1) # 等待 1 秒后重新尝试连接
return client
def Post_Data(self,**kwargs):
data = self.posts_data
data["id"] = str(random.randint(1,1000))
self.id = data["id"]
for key,value in kwargs.items():
data["params"][key] = {"value":value}
self.client.publish(self.post_topic,json.dumps(data))
print(data)
def Subscribe_topic(self,**kwargs):
for sub_topic,sub_topic_value in kwargs.items():
try:
self.client.subscribe(sub_topic_value)
print(f"Subscribed to {sub_topic}")
except:
print(f"Faile Subscribed to {sub_topic}!!!!")
pass
def Set_replay(self,msg_id):
data = self.set_replay
data["id"] = msg_id
data = json.dumps(data)
self.client.publish(self.set_replay_topic,data)
print(data)
def Get_replay(self,msg_id,replay_data):
data = self.get_replay
data["id"]=msg_id
data["data"]=replay_data
data = json.dumps(data)
self.client.publish(self.get_replay_topic,data)
print(data)
pass
#回复的消息topic和msg都是b""需要decode一下
def on_message(topic, msg):
topic = topic.decode('utf-8')
msg = json.loads(msg.decode('utf-8'))
global replay_msg
global replay_state_code
topic = topic.split("/")[-1]
if topic == "reply":
if msg["msg"] == "success":
replay_state_code = topic
if topic == "set":
replay_state_code = topic
replay_msg = msg
if topic == "get":
replay_state_code = topic
replay_msg = msg
print(msg)
def get_sensor_data():
data = random.randint(0,100)
return data
def get_led_state():
data = random.randint(0,1)
if data == 1:
return True
else:
return False
if __name__ == '__main__':
main()
pass