物聯網不加密傳輸數據是很危險的一件事!
這裡我用的是單方向驗證,也就是只有服務器端配置了證書,而且是自簽的證書
本來想搞個雙向驗證,但是總是配置不成功,連證書的格式都沒有說明,有說是der,但是沒用,不知道什麼問題,網上資料也很少,最後退而求其次,搞個單向驗證,總比明文傳輸強
硬件基礎: esp8266
編程語言:micropython
開發環境:thonny(這玩意老是出錯誤,不過再打開還能用),或者vscode (RT-Thread插件)(這玩意bug多的一p,出錯了就再也用不了了)
外部依賴:micropython-umqtt.simple (就是micropython中的mqtt庫,好幾年沒更新了,有點落後了,功能也少)
服務端:emqx 自帶自簽證書,也就是說服務器端已經配置好了
至於怎麼刷micropython這裡就不啰嗦了,自己百度去吧
注意:要刷適合大小的固件,小閃存不能刷大閃存型號的固件,不然會報錯,無法保存數據,別問我怎麼知道的
怎麼配置網絡這裡我也不說了,自己百度去吧
順便可以配置一個webrepl
下面的命令都是在esp8266上的micropython命令行上敲的
這裡使用upip
import upip
upip.install('micropython-umqtt.simple')
#可能會安裝失敗,重新安裝幾次,或者直接把這個包下載下來裡面就一個文件,傳到開發板上就行了
#這樣這個庫就被安裝到/lib下面了可以使用os.listdir()查看,或者用開發環境查看
把下載的simple.py文件裡面的第61行(如下)中的函數中的第二個參數給去掉,不然總是報錯
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
改為
self.sock = ussl.wrap_socket(self.sock)
下面是我的示例程序
#這裡使用mqtt協議,用emqx平台做一個遠程開關用的是esp8266-01s relay模塊
from simple import MQTTClient as mqttc
#這裡我直接把simple文件放到了根目錄,可以直接引入,沒有移動位置的按下面這句引入
#from umqtt.simple import MQTTClient as mqttc
from machine import Pin #用於控制繼電器
import time
import webrepl #配置文件為webrepl_cfg.py
webrepl.start()
import network
#配置網絡
#啟動wifi客戶端連接wifi
def apc():
print('啟動wifi客戶端')
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect('要連接的wifi的名稱', 'wifi密碼')
while not sta_if.isconnected():
time.sleep(1)
#檢查連接狀態,有ip地址才離開循環
while 1:
if '0.0.0.0' == sta_if.ifconfig()[0]:
time.sleep(2)
else:
break
print("run end")
print(sta_if.ifconfig())
#啟動熱點
def aps():
print('啟動熱點')
ap_if = network.WLAN(network.AP_IF)
if not ap_if.isconnected():
print('setting ap...')
ap_if.active(True)
ap_if.config(authmode=network.AUTH_WPA_WPA2_PSK,password="設置ap熱點的密碼")
apc()
aps()
#初始化繼電器,繼電器的開閉由gpio 0 控制
pin=Pin(0,Pin.OUT)
pin.on() #默認設為高電平,常關
#設置mqtt參數
#emqx這裡我服務器開啟了用戶名密碼認證,需要填寫這兩項,cid是clientid可以隨便填
#這裡的數據有些要轉為二進制,不然報錯
cid=b'relay-01s-2' #可自己設置
strcid='relay-01s-2' #和上面一樣,格式不一樣而已,用來發信息的
host='你的服務器地址或域名'
port=8883 #emqx的8883有ssl加密的,默認18083沒有加密
user=b'test'
pwd=b'test'
meettopic=b'relay_ctl' #訂閱的topic,從這個topic中接受消息,可自己設置
pushtopic=b'relay_msg' #推送消息到這個topic,可以自己設置
#收到訂閱topic中的消息時處理消息的回調函數
def dealMsg(topic,msg,server=None,port=None,ssl=None):
global pin,cli
print(msg)
#收到0,輸出高電平,切斷被控設備電源,並發送消息
if msg==b'0':
pin.on()
cli.publish(pushtopic,strcid+': normal close!')
#收到1,輸出底電平,連接被控設備電源,並發送消息
if msg==b'1':
pin.off()
cli.publish(pushtopic,strcid+': normal open!')
#初始化一個mqtt客戶端,開啟ssl
cli=mqttc(cid,host,port,user,pwd,keepalive=0,ssl=True)
#設置處理消息的回調函數
cli.set_callback(dealMsg)
#連接
cli.connect()
cli.subscribe(meettopic)
cli.publish(pushtopic,strcid+' is online!')
#阻塞在此等待消息,由於此庫沒有自動重連,這裡只能自己寫一個了
#由於esp8266不支持多線程,這裡只能讓進程阻塞在這裡
#這導致終端和webrepl沒法正常使用
#如果支持多線程可以另起一個線程,在後台運行
while 1:
try:
cli.wait_msg()
except Exception as e:
print(str(e))
time.sleep(2)
print('reconnect!')
cli.connect()
#斷線之後要重新訂閱
cli.subscribe(meettopic)
我測試了一次發現過了一個小時這個設備就收不到信息了,不知道啥問題