(2)用Micropython將ESP32資料上雲

ScottX發表於2022-01-19

之前我們嘗試過直接把LED點亮並且閃爍。
今天嘗試一下將LED的開關狀態上雲,並可以通過雲來進行資料下發。
資料要上雲,首先開發板要聯網。
首先我們會用 Python的network 庫, 在network庫當中,提供STA_IF和AP_IF兩種模式。其中進行連線的是使用STA_IF模式,如果使用AP_IF,則是將ESP32作為一個熱點。後面的文章當中我們會用到。


import network 
import utime
WIFISSID = "Put your ssid here"
WIFIPWD = "Put yuou ssid password"
wlan = None
class ConnectWIFI:
    def connect_wifi(self): 
        # network.STA_IF 站點也稱為客戶端,連線到上游WiFi接入點
        # network.AP_IF 作為熱點,允許其他WiFi客戶端接入。熱點模式允許使用者將自己的裝置配置為熱點,這讓多個裝置之間的無線連線在不借助外部路由器網路的情況下成為可能。
        wlan = network.WLAN(network.STA_IF)  
        wifi_connected = False
        wlan.active(True)                  
        wlan.scan()                         
        wlan.connect(WIFISSID, WIFIPWD)       # 定義好的SSID 和 密碼
        while True:
            # 判斷是否已經連線網路
            wifi_connected = wlan.isconnected()    
            if wifi_connected:                     
                # 若沒有連線成功,則一直連線
                break
            else:
                # 連線成功,進行提示
                utime.sleep_ms(2000)
                print("Wifi connet status :", wifi_connected)
        ifconfig = wlan.ifconfig()       
        # 列印網路情況              
        print(ifconfig)

當WI-FI已經連線成功後,我們的開發板已經有了通訊的能力,下一步我們將我們的開發板和阿里雲物聯網平臺進行連線。
在連線之前需要保證:

  1. 自己擁有阿里雲賬戶
  2. 開通了IOT服務
  3. 已經註冊了對應的產品和裝置。
    如果還沒有設定IOT的請看下面:
    首先建立一個產品
    image
    設定產品的名稱,品類和其他資訊

image

完成產品建立後,進行產品物模型的定義
image

image

阿里雲IOT平臺提供了很多日常常用的一些標準功能,但是我們進行測試的話使用自定義功能。這樣能夠更好的瞭解每個功能裡面會有什麼樣的屬性。
image

image

完成產品新增後,需要新增裝置(即新增我們目前手裡使用的這個開發板)
image

image

image

建立完成,並看到產品的資訊

image

這裡可以記一下三元組的概念,ProductKey, DeviceName, DeviceSecret 這三個東西能用來在資料通訊時進行開發板的唯一性識別。
因為之前已經完成了連線WI-FI的程式碼。所以,在WI-FI連線後,我們就需要將開發板和阿里雲物聯網連線。 我們直接使用HAAS提供的庫。 aliyunIoT

import utime
import ujson
from aliyunIoT import Device
from example.haas_led import HAASLed
 
iot_connected = False
device = None
# 物聯網平臺連線成功的回撥函式 
def on_connect( data):
    print('on_connect')
    global iot_connected
    iot_connected = True
  
def on_props(request): 
    led_entity = HAASLed()
    led_entity.handle_iot_data(request) 
     
    
class HaasIOT(object):
  
    def report_data(self, data):
        global device 
        upload_data = {'params': ujson.dumps(data)
        } 
        device.postProps(upload_data) 
        
      
    def connect_iot(self):
        self.test()
        global device, iot_connected
        key_info = {
            'region': 'cn-shanghai',
            'productKey': 'XXX', 
            'deviceName': 'XXX',
            'deviceSecret': 'XXX',
            'keepaliveSec': 60
        } 
        device = Device()
        # 設定連線到物聯網平臺的回撥函式,如果連線物聯網平臺成功,則呼叫on_connect函式
        device.on(Device.ON_CONNECT, on_connect)
        # 配置收到雲端屬性控制指令的回撥函式,如果收到物聯網平臺傳送的屬性控制訊息,則呼叫on_props函式
        device.on(Device.ON_PROPS, on_props)
        # 啟動連線阿里雲物聯網平臺過程
        device.connect(key_info)
        # 等待裝置成功連線到物聯網平臺
        while(True):
            if iot_connected:
                print('物聯網平臺連線成功')
                break
            else:
                print('sleep for 1 s')
                utime.sleep(1)
        print('sleep for 2s')
        utime.sleep(2)

程式碼中的productKey, deviceName, deviceSecret分別對應到我們剛才在阿里雲IOT平臺上建立的裝置資訊。
main.py裡面的呼叫程式碼

if __name__ == '__main__': 
     
    wifi_entity = ConnectWIFI()
    wifi_connected = wifi_entity.connect_wifi()
    if wifi_connected is True:   
        hass_iot_entity = HaasIOT()
        hass_iot_entity.connect_iot()

將程式碼燒錄到開發板,我們會看到下面的資訊,表示開發板已經完成WI-FI連線並和阿里雲IOT平臺連線成功。

Wifi connet status : False
Wifi connet status : False
('192.168.20.26', '255.255.255.0', '192.168.20.1', '11.11.2.69')
a test function
establish tcp connection with server(host='a1fuLmf5uts.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[443])
sleep for 1 s
tcp_connect: can only connect from state CLOSED
success to establish tcp, fd=54
on_connect
物聯網平臺連線成功

在連線IOT平臺的時候,通過了阿里雲提供的回撥方法 Device.on 註冊了 上報屬性的一個方法。
device.on(Device.ON_PROPS, on_props)
通過該回撥,我們可以接收到IOT平臺下發給裝置的資料,並進行處理。比如在本文當中,我們通過平臺來控制3個LED燈開關。

image

在線上除錯當中,可以對之前設定的3個屬性進行修改。(0表示關燈,1表示開燈)

image

該實現是用剛才的回撥函式實現的。

def on_props(request): 
    led_entity = HAASLed()
    led_entity.handle_iot_data(request)

在回撥函式當中,物聯網平臺下發的資料為request, 在這裡,我用了HAASLed當中的handle_iot_data方法進行處理。
物聯網平臺下發的資料都是以一個dict傳輸過來的資料,形如:

{'code': 0, 'params_len': 20, 'msg_id': 659157818, 'params': '{"led_red_switch":0}'}

我們所需要獲取的資料就在 params當中。

def handle_iot_data(self, rsp): 
        print(type(rsp))
        print(rsp) # {'code': 0, 'params_len': 20, 'msg_id': 659157818, 'params': '{"led_red_switch":0}'}
        if rsp.get('code') == 0:
            data = rsp.get('params') 
            led_switch = ujson.loads(data)  # '{"led_red_switch":1}'
            led_red_switch = led_switch.get('led_red_switch') 
            if led_red_switch is not None:
                self.control_led("led_red_switch", led_red_switch)
            led_green_switch = led_switch.get('led_green_switch') 
            if led_green_switch is not None:
                self.control_led("led_green_switch", led_green_switch)
            led_yellow_switch = led_switch.get('led_yellow_switch') 
            if led_yellow_switch is not None:
                self.control_led("led_yellow_switch", led_yellow_switch)
            
 def control_led(self,led, status):
        r_led_gpio = GPIO()
        y_led_gpio = GPIO()
        g_led_gpio = GPIO()
        r_led_gpio.open("r_led")
        y_led_gpio.open("y_led")
        g_led_gpio.open("g_led")
        if led == "led_red_switch":
            r_led_gpio.write(status)
        elif led == "led_green_switch":
            g_led_gpio.write(status)
        elif led == "led_yellow_switch":
            y_led_gpio.write(status)

可以看到,在程式碼當中,首先將下發資料進行處理,並根據業務邏輯獲取到需要的內容,並呼叫control_led來進行LED燈的判斷。
對於從端上報資料上雲,則可以使用下面的程式碼

def report_data(self, data):
        global device 
        upload_data = {'params': ujson.dumps(data)
        } 
        device.postProps(upload_data)

按照業務需要,將要傳送的資料拼接好後。使用device.postProps進行上報即可。所有的上報或者下發資料,都可以在日誌服務當中檢視。
image

通過以上操作,成功的將ESP32 和 物聯網平臺完成了通訊。

相關文章