MicroPython 通过MQTT协议 连接OneNet上云

本文详细介绍了如何使用ESP32通过WiFi连接手机热点,利用MQTT协议将数据上传到中国移动OneNet云平台。首先注册OneNet账号并添加新设备,然后在单片机编程软件中编写Python代码,创建MQTTClient类实现连接、发布数据等功能。最后,通过RTOS定时器周期性地发送数据。
摘要由CSDN通过智能技术生成

1. One Net注册新用户

首先,进入中国移动OneNet平台官方网站(https://open.iot.10086.cn),点击右上角的“注册”,注册一个账号。账号注册完成后点击登录,进入右上角的“控制台”。

 2. 添加新设备

       2.1 进入控制台后,在全部产品服务中选择MQTT物联网套件。

        2.1参数如下

         2.2设备添加成功后,查看设备列表

 

3. ESP32把采集到的数据,通过wifi连接手机热点,上传到OneNet云平台,采用的Mqtt协议,首先导入MQTTClient依赖包,创建client客户端对象连接OneNet服务器,上传数据就是client的客户端向服务器的发布主题$sys/{pid}/{device-name}/dp/post/json发布信息。

        3.1. 打开单片机编程软件mu,新建二个文件,分别为:simple.py、main.py。

 simple.py

#simple.py 的文件
import usocket as socket
import ustruct as struct
from ubinascii import hexlify

class MQTTException(Exception):
    pass

class MQTTClient:

    def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,
                 ssl=False, ssl_params={}):
        if port == 0:
            port = 8883 if ssl else 1883
        self.client_id = client_id
        self.sock = None
        self.server = server
        self.port = port
        self.ssl = ssl
        self.ssl_params = ssl_params
        self.pid = 0
        self.cb = None
        self.user = user
        self.pswd = password
        self.keepalive = keepalive
        self.lw_topic = None
        self.lw_msg = None
        self.lw_qos = 0
        self.lw_retain = False

    def _send_str(self, s):
        self.sock.write(struct.pack("!H", len(s)))
        self.sock.write(s)

    def _recv_len(self):
        n = 0
        sh = 0
        while 1:
            b = self.sock.read(1)[0]
            n |= (b & 0x7f) << sh
            if not b & 0x80:
                return n
            sh += 7

    def set_callback(self, f):
        self.cb = f

    def set_last_will(self, topic, msg, retain=False, qos=0):
        assert 0 <= qos <= 2
        assert topic
        self.lw_topic = topic
        self.lw_msg = msg
        self.lw_qos = qos
        self.lw_retain = retain

    def connect(self, clean_session=True):
        self.sock = socket.socket()
        addr = socket.getaddrinfo(self.server, self.port)[0][-1]
        self.sock.connect(addr)
        if self.ssl:
            import ussl
            self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
        premsg = bytearray(b"\x10\0\0\0\0\0")
        msg = bytearray(b"\x04MQTT\x04\x02\0\0")

        sz = 10 + 2 + len(self.client_id)
        msg[6] = clean_session << 1
        if self.user is not None:
            sz += 2 + len(self.user) + 2 + len(self.pswd)
            msg[6] |= 0xC0
        if self.keepalive:
            assert self.keepalive < 65536
            msg[7] |= self.keepalive >> 8
            msg[8] |= self.keepalive & 0x00FF
        if self.lw_topic:
            sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
            msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
            msg[6] |= self.lw_retain << 5

        i = 1
        while sz > 0x7f:
            premsg[i] = (sz & 0x7f) | 0x80
            sz >>= 7
            i += 1
        premsg[i] = sz

        self.sock.write(premsg, i + 2)
        self.sock.write(msg)
        #print(hex(len(msg)), hexlify(msg, ":"))
        self._send_str(self.client_id)
        if self.lw_topic:
            self._send_str(self.lw_topic)
            self._send_str(self.lw_msg)
        if self.user is not None:
            self._send_str(self.user)
            self._send_str(self.pswd)
        resp = self.sock.read(4)
        assert resp[0] == 0x20 and resp[1] == 0x02
        if resp[3] != 0:
            raise MQTTException(resp[3])
        return resp[2] & 1

    def disconnect(self):
        self.sock.write(b"\xe0\0")
        self.sock.close()

    def ping(self):
        self.sock.write(b"\xc0\0")

    def publish(self, topic, msg, retain=False, qos=0):
        pkt = bytearray(b"\x30\0\0\0")
        pkt[0] |= qos << 1 | retain
        sz = 2 + len(topic) + len(msg)
        if qos > 0:
            sz += 2
        assert sz < 2097152
        i = 1
        while sz > 0x7f:
            pkt[i] = (sz & 0x7f) | 0x80
            sz >>= 7
            i += 1
        pkt[i] = sz
        #print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt, i + 1)
        self._send_str(topic)
        if qos > 0:
            self.pid += 1
            pid = self.pid
            struct.pack_into("!H", pkt, 0, pid)
            self.sock.write(pkt, 2)
        self.sock.write(msg)
        if qos == 1:
            while 1:
                op = self.wait_msg()
                if op == 0x40:
                    sz = self.sock.read(1)
                    assert sz == b"\x02"
                    rcv_pid = self.sock.read(2)
                    rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
                    if pid == rcv_pid:
                        return
        elif qos == 2:
            assert 0

    def subscribe(self, topic, qos=0):
        assert self.cb is not None, "Subscribe callback is not set"
        pkt = bytearray(b"\x82\0\0\0")
        self.pid += 1
        struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
        #print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt)
        self._send_str(topic)
        self.sock.write(qos.to_bytes(1, "little"))
        while 1:
            op = self.wait_msg()
            if op == 0x90:
                resp = self.sock.read(4)
                #print(resp)
                assert resp[1] == pkt[2] and resp[2] == pkt[3]
                if resp[3] == 0x80:
                    raise MQTTException(resp[3])
                return

    # Wait for a single incoming MQTT message and process it.
    # Subscribed messages are delivered to a callback previously
    # set by .set_callback() method. Other (internal) MQTT
    # messages processed internally.
    def wait_msg(self):
        res = self.sock.read(1)
        self.sock.setblocking(True)
        if res is None:
            return None
        if res == b"":
            raise OSError(-1)
        if res == b"\xd0":  # PINGRESP
            sz = self.sock.read(1)[0]
            assert sz == 0
            return None
        op = res[0]
        if op & 0xf0 != 0x30:
            return op
        sz = self._recv_len()
        topic_len = self.sock.read(2)
        topic_len = (topic_len[0] << 8) | topic_len[1]
        topic = self.sock.read(topic_len)
        sz -= topic_len + 2
        if op & 6:
            pid = self.sock.read(2)
            pid = pid[0] << 8 | pid[1]
            sz -= 2
        msg = self.sock.read(sz)
        self.cb(topic, msg)
        if op & 6 == 2:
            pkt = bytearray(b"\x40\x02\0\0")
            struct.pack_into("!H", pkt, 2, pid)
            self.sock.write(pkt)
        elif op & 6 == 4:
            assert 0

    # Checks whether a pending message from server is available.
    # If not, returns immediately with None. Otherwise, does
    # the same processing as wait_msg.
    def check_msg(self):
        self.sock.setblocking(False)
        return self.wait_msg()

 main.py

'''
实验名称:采集数据到onenet云平台
版本:v1.0
日期:2022.10.24
作者:没睡醒的番茄
说明:esp32开发板通过路由器上网,将数据周期性采集上传到onenet云端
'''

from simple import MQTTClient
from machine import I2C, Timer, Pin
import network, time

#初始化相关模块
WIFI_LED=Pin(2,Pin.OUT)
#WIFI连接函数
def WIFI_Connect():
    WIFI_LED = Pin(2, Pin.OUT)  # 初始化WIFI指示灯
    #STA模式
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)                   #激活接口
    start_time=time.time()              #记录时间做超时判断
    if not wlan.isconnected():
        print("connecting to network...")
        wlan.connect("Yangs","1234567890")  # 输入WIFI账号密码
        while not wlan.isconnected():

            #LED闪烁提示
            WIFI_LED.value(1)
            time.sleep_ms(300)
            WIFI_LED.value(0)
            time.sleep_ms(300)

            #超时判断,15秒没连接成功判定为超时
            if time.time()-start_time > 15 :
                print('WIFI Connected Timeout!')
                break

    if wlan.isconnected():
        #LED点亮,指示
        WIFI_LED.value(1)
        print("network information:", wlan.ifconfig())
             return True
    else:
        return False

#执行发送任务
def MQTT_Send(tim):
        print("《里面填入你的数据》")   #串口打印数据
        mymessage='{"id": 123,"dp": {"《填入你的数据名称》": [{ "v": %d,}],"《填入你的数据名称》": [{"v": %d,}]}}'%("《里面填入你的数据》","《里面填入你的数据》")
'''
列如
传入一个温度 和湿度的数据
        print("tem:"+str(d.temperature())+' C  '+"hum:"+str(d.humidity())+' %')   #串口打印温湿度
        mymessage='{"id": 123,"dp": {"Temperature": [{ "v": %d,}],"Humidity": [{"v": %d,}]}}'%(d.temperature(),d.humidity())
 
'''
    
        client.publish(topic=publish_TOPIC,msg= mymessage, retain=False, qos=0)


#执行WIFI连接函数
if WIFI_Connect():
    # TOPIC名称
    #里面的要改成自己的
    publish_TOPIC= '$sys/xxxxxx/xxxxx_xx/dp/post/json'
    #客户端ID:设备名称
    #里面的要改成自己的
    CLIENT_ID = "xxxxx_xx"
    #用户名:产品ID
    #里面的要改成自己的
    user_name = "xxxxxx"
    #用户密码:用token工具计算的,大家也可以直接用程序实现
    #里面的要改成自己的
    user_password = 'version=2018-10-31&res=products%2F543721%2Fdevices%2Fesp32_1&et=1684280992&method=md5&sign=p5MLOtbEweXkfWy05BGtPg%3D%3D'
    #onenet IP和端口 不用改
    SERVER = "183.230.40.96"  #非加密方式
    PORT = 1883
    #连接到onenet平台
    client = MQTTClient(CLIENT_ID, SERVER, 0, user_name, user_password,60)
    client.connect()

    #开启RTOS定时器,编号为-1,周期2000ms,执行MQTT发布任务
    tim = Timer(-1)
    tim.init(period=2000, mode=Timer.PERIODIC,callback=MQTT_Send)


4.如何修改上面的代码

         4.1 

  xxxxxx表示为:

 xxxxx_xx表示为:

  user_password 的 tocken计算:

下载软件和使用方法

 注意时间戳要大于当前时间    当前Unix时间参考链接:https://time.is/Unix

 key为:

 如:

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值