參考文章
NodeMCU 通過MQTT 連接阿里云物聯網 https://blog.csdn.net/weixin_43368807/article/details/82984796
謝謝驾孔。
概要
本文與參考文章有一點的重復张肾,但有幾點會不同,一,更加具體的添加了一個實際功能框舔,本文監(jiān)控了溫度與濕度信息;二,對代碼進行了重新的組織,更加清晰簡單蒂胞。
阿里云平臺方面的準備工作
創(chuàng)建產品、創(chuàng)建設備
可以參考最前邊列出的參考文章条篷。另外骗随,阿里云平臺也有很好的引導蛤织,按著引導下一步下一步就可以了。
添加功能
這個是與參考文章不同的地方鸿染。對了讓讀者更容易理解為什么要添加功能指蚜,我把產品、設備牡昆、功能的關系簡單描述下姚炕。產品就像一個抽象的概念摊欠,例如電視機丢烘,只有把電視機變成具體的東西,我們才能具體觸摸感知些椒,這個就是設備播瞳,很類似于類與對象的概念。而一個產品對普通人來說免糕,主要就是關注與它能做什么赢乓,也就是它的功能。功能是在產品中定義的石窑,每個設備都會具備這個功能牌芋,這個就類似與類方法。
首先松逊,選擇產品躺屁,進入產品查看頁面
然后,選擇功能定義经宏,在功能定義中選擇自定義功能的添加
最后犀暑,進行自定義功能的設置
信息復制
后期設備端連接阿里云服務器時有幾個信息需要設置,所以現在就要把對應的信息準備好:
- 在產品查看頁面獲取ProductKey與ProductSecret兩個信息烁兰;
-
在功能定義頁面獲取溫度耐亏、濕度的標識名,例如:
功能標識選擇
上圖中沪斟,溫度標識符:CurrentTemperature广辰,濕度標識符:humidity,這兩個是讀者在前邊自己設置主之。
- 在設備查看頁面獲取DeviceName信息轨域;
- 在設備查看頁面獲取Topic鏈接信息,是一個類似/sys/*********/DeviceA/thing/event/property/post的字符串杀餐。
到此為止干发,阿里云端的設置就已經完成了。
設備端操作
固件燒寫
請參考本文最前的參考文章的說明史翘,以及本人其他關于NodeMCU操作的文章枉长。但需要注意的是冀续,固件注意選擇溫度傳感器模塊,例如我使用了DHT溫度傳感器模塊必峰。
我的固件包含了如下模塊:This was built against the master branch and includes the following modules: crypto, dht, encoder, enduser_setup, file, gpio, http, i2c, mqtt, net, node, pwm, sntp, spi, tmr, uart, wifi, wifi_monitor.
代碼編寫邏輯
在代碼設計上洪唐,分為了五個文件,一個是初始化wifi邏輯文件吼蚁,init.lua,另一個是mqtt的連接處理文件凭需,再一個就是配置文件,用來記錄不同使用者信息的文件肝匆,config.lua粒蜈,再一個是mqtt的邏輯處理文件,這個是針對一個物聯網項目需要編寫的邏輯旗国,mqtt_app.lua枯怖。最后一個文件是應用模塊管理文件application.lua。未來能曾,可能會有其他功能添加度硝,例如添加一個HTTP服務器支持,那么很可能會需要添加新的模塊實現寿冕,那么就在application.lua中加載新的模塊實現蕊程。
配置文件config.lua
-- WIFI 設置
SSID = "HiWiFi_**********"
PASSWORD = "**********"
-- MQTT設置
ProductKey ="************"
DeviceName ="*******"
DeviceSecret="*********************************************"
RegionId="cn-shanghai" --華東2
-- MQTT發(fā)送消息的topic
publish_topic = "/sys/"..ProductKey.."/"..DeviceName.."/thing/event/property/post"
Wifi初始化邏輯文件init.lua
dofile("config.lua")
function startup()
if file.open("init.lua") == nil then
print("init.lua deleted or renamed")
else
print("Running")
file.close("init.lua")
-- the actual application is stored in 'application.lua'
dofile("application.lua")
end
end
-- Define WiFi station event callbacks
wifi_connect_event = function(T)
print("Connection to AP("..T.SSID..") established!")
print("Waiting for IP address...")
if disconnect_ct ~= nil then disconnect_ct = nil end
end
wifi_got_ip_event = function(T)
-- Note: Having an IP address does not mean there is internet access!
-- Internet connectivity can be determined with net.dns.resolve().
print("Wifi connection is ready! IP address is: "..T.IP)
print("Startup will resume momentarily, you have 3 seconds to abort.")
print("Waiting...")
tmr.create():alarm(3000, tmr.ALARM_SINGLE, startup)
end
wifi_disconnect_event = function(T)
if T.reason == wifi.eventmon.reason.ASSOC_LEAVE then
--the station has disassociated from a previously connected AP
return
end
-- total_tries: how many times the station will attempt to connect to the AP. Should consider AP reboot duration.
local total_tries = 75
print("\nWiFi connection to AP("..T.SSID..") has failed!")
--There are many possible disconnect reasons, the following iterates through
--the list and returns the string corresponding to the disconnect reason.
for key,val in pairs(wifi.eventmon.reason) do
if val == T.reason then
print("Disconnect reason: "..val.."("..key..")")
break
end
end
if disconnect_ct == nil then
disconnect_ct = 1
else
disconnect_ct = disconnect_ct + 1
end
if disconnect_ct < total_tries then
print("Retrying connection...(attempt "..(disconnect_ct+1).." of "..total_tries..")")
else
wifi.sta.disconnect()
print("Aborting connection to AP!")
disconnect_ct = nil
end
end
-- Register WiFi Station event callbacks
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, wifi_connect_event)
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, wifi_got_ip_event)
wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, wifi_disconnect_event)
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config({ssid=SSID, pwd=PASSWORD})
-- wifi.sta.connect() not necessary because config() uses auto-connect=true by default
應用模塊管理文件application.lua
-- MQTT 模塊 ----
dofile("mqtt.lua")
--print("Hello ...")
mqtt的連接處理模塊mqtt.lua
-- 加載配置信息
dofile("config.lua")
-- 加載MQTT應用邏輯
mqtt_app = require("mqtt_app")
-- 連接阿里云
ClientId =wifi.sta.getmac()
myMQTTport=1883
myMQTT=nil
myMQTThost=ProductKey..".iot-as-mqtt."..RegionId..".aliyuncs.com"
myMQTTusername=DeviceName.."&"..ProductKey
myMQTTtimes='1234567890'
hmacdata="clientId"..ClientId.."deviceName"..DeviceName.."productKey"..ProductKey.."timestamp"..myMQTTtimes
myMQTTpassword=crypto.toHex(crypto.hmac("sha1",hmacdata,DeviceSecret))
myMQTTClientId=ClientId.."|securemode=3,signmethod=hmacsha1,timestamp="..myMQTTtimes.."|"
myMQTT=mqtt.Client(myMQTTClientId, 120,myMQTTusername,myMQTTpassword)
mqtt_app.MQTT_Init(myMQTT)
print("Attempting client connect...")
local re = myMQTT:connect(myMQTThost, myMQTTport,0, mqtt_app.MQTTSuccess,mqtt_app.MQTTFailed)
mqtt的應用邏輯實現模塊mqtt_app.lua
dofile("config.lua")
local myqq_app = {};
MQTTconnectFlag = 0;
mClient = nil;
function myqq_app.MQTT_Init(client)
--[設備offline 事件]-----
myMQTT:on("offline", function(client)
print ("offline")
--tmr.start(0)
end)
--[注冊 設備接收到訂閱的topic 事件]-----
myMQTT:on("message", function(client, topic, data)
print(topic ..":")
if data ~= nil then
print(data)
end
end)
end
---[連接成功]---
function myqq_app.MQTTSuccess(client)
print("MQTT connected")
-- 注冊通道
--client:subscribe(topic0,0, function(conn) --注冊topic0
-- print("subscribe success")
--end)
mClient = client;
MQTTconnectFlag=1
--tmr.stop(0) --關閉定時連接
--[topic 定時上傳數據]
tmr.create():alarm(5000, 1, function() --等待連接上
if MQTTconnectFlag==1 and mClient~=nil then
re,t,s,x = dht.read11(1);
msg = "{\"id\":\"bc:dd:c2:30:cb:dc\", \"params\":{\"CurrentTemperature\":"..tostring(t)..",\"humidity\":"..tostring(s).."},\"method\":\"thing.event.property.post\"}"
mClient:publish(publish_topic,msg,0,0,function(client)
print("send ok" )
end)
end
end)
end
---[連接失敗]---
function myqq_app.MQTTFailed(client,reson)
print("Fail reson:"..reson)
MQTTconnectFlag=0
--tmr.start(0) --重新啟動連接
end
return myqq_app;