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...哈哈哈