NodeMCU阿里云平臺的遠程溫度查看實現

參考文章

NodeMCU 通過MQTT 連接阿里云物聯網 https://blog.csdn.net/weixin_43368807/article/details/82984796
謝謝。

概要

本文與參考文章有一點的重復,但有幾點會不同,一,更加具體的添加了一個實際功能,本文監控了溫度與濕度信息;二,對代碼進行了重新的組織,更加清晰簡單。

阿里云平臺方面的準備工作

創建產品、創建設備

可以參考最前邊列出的參考文章。另外,阿里云平臺也有很好的引導,按著引導下一步下一步就可以了。

添加功能

這個是與參考文章不同的地方。對了讓讀者更容易理解為什么要添加功能,我把產品、設備、功能的關系簡單描述下。產品就像一個抽象的概念,例如電視機,只有把電視機變成具體的東西,我們才能具體觸摸感知,這個就是設備,很類似于類與對象的概念。而一個產品對普通人來說,主要就是關注與它能做什么,也就是它的功能。功能是在產品中定義的,每個設備都會具備這個功能,這個就類似與類方法。

首先,選擇產品,進入產品查看頁面


選擇產品
進入產品查看信息頁面

然后,選擇功能定義,在功能定義中選擇自定義功能的添加


添加自定義功能

最后,進行自定義功能的設置


自定義功能設置

信息復制

后期設備端連接阿里云服務器時有幾個信息需要設置,所以現在就要把對應的信息準備好:

  1. 在產品查看頁面獲取ProductKey與ProductSecret兩個信息;
  2. 在功能定義頁面獲取溫度、濕度的標識名,例如:


    功能標識選擇

    上圖中,溫度標識符:CurrentTemperature,濕度標識符:humidity,這兩個是讀者在前邊自己設置。

  3. 在設備查看頁面獲取DeviceName信息;
  4. 在設備查看頁面獲取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發送消息的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;
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容