IoT改變世界之 Arduino+ESP8266+阿裏MQTT+App控制
因為蛋疼的緣故, 接觸了一下MQTT, 從一個大佬那裏聽說了塗鴉這個牛逼平臺, 但是我正玩阿裏的IoT呢, 就拿進行了一半的阿裏IoT練練手吧.
目標是一句話: 用手機控制一個ESP8266的模塊上面的一個燈.
這裏面涉及幾個問題:
1. ESP8266固件
2. App如何訪問雲端? 直接MQTT?
3. 小機端怎麽連接阿裏的IoT? 這個問題是問題1的延續.
挨個來說, 我的模塊是某寶買的, (感覺被坑了, 20塊錢).
https://detail.tmall.com/item.htm?id=524942473974&spm=a1z09.2.0.0.459e2e8dI58meT&_u=b124ig73098
排線居然焊歪了.根據這個賣家的資料, 看得我一頭霧水, 一是所謂官方網站, 也就是這個http://www.nodemcu.com 啥雞毛都沒有, 幾年前我玩這個8266的時候, 依稀記得貌似用的是lua, 但是這個網站沒有提到lua, 反而說可以像arduino一樣編程, 我有點兒糊塗了就.
先是找了一個早就沒有人用的nodemcu studio 2015, 看名字就知道夠老了. 折騰了一番, 終於把init.lua刷進去了, 基本能連到我家的wifi上去.
後來一個偶然的機會聽說了塗鴉, 進去一看文檔, 哎喲, 都是用的esp8266, 這樣我又從他們官網頂了兩個模塊, 後來發現完全沒必要.
然後回到阿裏這邊折騰, 發現了開發文檔裏面說到了, 這裏要先吐槽一下塗鴉的文檔, 壓根沒有寫任何有意義的關於mcu開發的例程, 甚至連固件的編譯都只字不提, 且不提怎麽寫代碼, 我他媽怎把東西刷進去我都不知道, 搞毛線.
我後來記得貌似阿裏的文檔中, 提到了8266的一個快速應用案例, 一看哎呦, 還有源碼, 再一看, 居然是arduino的, 這麽說, esp8266真的如nodemcu.com網站上所說, 可以當作arduino來編程?
後來google了一番, 誠不我欺也, ESP8266上真的可以跑arduino, 連引腳都靠譜.
過程是, 先下一個adruino的ide, for windows版本.
記得前面根據倒黴賣家提供的資料百度盤, 下載安裝一下板子的usb驅動, cp2102, 我買的是廉價的cp2102的版本.
裝好之後, 去arduino的首選項裏面, 加上開發板的管理器地址, 就是一個repo源
https://www.arduino.cn/package_esp8266com_index.json
再在arduino的開發板管理器裏面, 下載NodeMCU 1.0的開發板
接著是兩個庫, 因為阿裏的源碼裏面要引用這兩個庫: PubSubClient ArduinoJson
直接進庫管理裏面搜就行了. 註意版本最好跟阿裏源碼裏面的版本一致.
#include <ESP8266WiFi.h> /* 依賴 PubSubClient 2.4.0 */ #include <PubSubClient.h> /* 依賴 ArduinoJson 5.13.4 */ #include <ArduinoJson.h> #define SENSOR_PIN 13 /* 連接您的WIFI SSID和密碼 */ #define WIFI_SSID "xxid" #define WIFI_PASSWD "password" /* 設備證書信息*/ #define PRODUCT_KEY "a1mBLX1dkbZ" #define DEVICE_NAME "tXQxE2VcYyZrYHubvw2h" #define DEVICE_SECRET "pGL6jQLhjlbQ24x0HbfMsNYp9y9Xe0" #define REGION_ID "cn-shanghai" /* 線上環境域名和端口號,不需要改 */ #define MQTT_SERVER "a1mBLX1dkbZ.iot-as-mqtt.cn-shanghai.aliyuncs.com" #define MQTT_PORT 1883 #define MQTT_USRNAME "tXQxE2VcYyZrYbvw2h&a1mBLX1dkbZ" #define CLIENT_ID "12345|securemode=3,signmethod=hmacsha1|" // 請使用以上說明中的加密工具或參見MQTT-TCP連接通信文檔加密生成password。 // 加密明文是參數和對應的值(clientIdesp8266deviceName${deviceName}productKey${productKey}timestamp1234567890)按字典順序拼接 // 密鑰是設備的DeviceSecret #define MQTT_PASSWD "FCA9741899490E99BE661F504AFBA71099A0C520" #define ALINK_BODY_FORMAT "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"thing.event.property.post\",\"params\":%s}" #define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post" #define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/set" unsigned long lastMs = 0; WiFiClient espClient; PubSubClient client(espClient); void callback(char *topic, byte *payload, unsigned int length) { StaticJsonBuffer<200> jsonBuffer; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); payload[length] = ‘\0‘; Serial.println((char *)payload); JsonObject& root = jsonBuffer.parseObject(payload); if (!root.success()) { Serial.println("parseObject() failed"); return; } const char* status = root["params"]["LightSwitch"]; Serial.println(status); if(status[0] == ‘0‘){ //Serial.println("off"); digitalWrite(LED_BUILTIN, HIGH); }else{ //Serial.println("on"); digitalWrite(LED_BUILTIN, LOW); } } void wifiInit() { WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWD); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("WiFi not Connect"); } Serial.println("Connected to AP"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); Serial.print("espClient ["); client.setServer(MQTT_SERVER, MQTT_PORT); /* 連接WiFi之後,連接MQTT服務器 */ client.setCallback(callback); } void mqttCheckConnect() { while (!client.connected()) { Serial.println("Connecting to MQTT Server ..."); if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD)) { Serial.println("MQTT Connected!"); client.subscribe(ALINK_TOPIC_PROP_SET); } else { Serial.print("MQTT Connect err:"); Serial.println(client.state()); delay(5000); } } } void mqttIntervalPost() { char param[32]; char jsonBuf[128]; //sprintf(param, "{\"idle\":%d}", digitalRead(13)); //sprintf(jsonBuf, ALINK_BODY_FORMAT, param); Serial.println(jsonBuf); boolean d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf); Serial.print("publish:0 失敗;1成功"); Serial.println(d); } void setup() { pinMode(SENSOR_PIN, INPUT); /* initialize serial for debugging */ Serial.begin(115200); Serial.println("Demo Start"); pinMode(LED_BUILTIN, OUTPUT); wifiInit(); } // the loop function runs over and over again forever void loop() { if (millis() - lastMs >= 5000) { lastMs = millis(); mqttCheckConnect(); } client.loop(); }
編譯一下, 發現還行, 能連上MQTT的服務器.
然後就在阿裏的控制臺, 建一個服務, 這裏很奇怪, 我發現了兩個IoT控制臺, 似乎一個新一個舊, 總之相互之間數據還是不通的, 我大概是用舊的控制臺建了一個服務, 所謂服務就是把前端api, 比如app那邊的請求, 向設備端的topic進行了一個發布publish, 如果你的設備正好訂閱了這個topic, 就會執行回調, 就是上面arduino固件裏面callback函數裏面執行的那樣,
畫圖一般做了一個服務出來.
Api輸入為一個接口地址, 比如/switch, 然後傳參數進去, 後來就被這個傳參給攔住了, 把心一橫,直接幹一個app出來.
阿裏估計是學塗鴉的, 或者塗鴉學阿裏, 誰知道去了, 反正都是一個路子(不過感覺塗鴉落地的項目更多, 界面都有很多模板選擇.), 配置好頁面, 直接出sdk
基本過程是傻瓜式的:
IoT的網頁就應該是傻瓜式的嘛, 可復制, 可復用, 有伸縮, 有彈性.
沒別的就做了一個開關, 然後這個開關可以配置:
點幾下鼠標, 搞定了.
然後下載安裝到安卓上, 完成.
最終效果很簡單, 即使按屏幕上的按鈕, 燈可以亮或者滅.
這就是IoT了...我滴天哪...
下一步是pwm...哈哈哈
IoT改變世界之 Arduino+ESP8266+阿裏MQTT+App控制