|
* 上次搞清楚了ESP8266怎么使用Arduino控制WS2812B灯带,可以参考:https://www.mydigit.cn/forum.php?mod=viewthread&tid=112534
* 这次在此基础上添加天猫精灵智能音箱控制操作,这个原理也可以用到实际灯具中。
* 先看一看最后实现了哪些功能:
1. 无线配网
2. 天猫精灵语音控制:
天猫精灵,开灯。。
天猫精灵,亮度50。。
天猫精灵,灯光绿色。。
天猫精灵,关灯。。
* 最终效果如视频:查看视频效果
* 下面就是一步步来接入,首先再来看看连接图
* 第一步就是配网,配网我用的是Arduino中的WifiManager库:
* 它的原理是用ESP8266开启热点,电脑或手机连接热点后访问192.168.4.1,就可以访问一个网页
* 我们把要连接的路由器Wifi热点名和密码输入,ESP8266会把账号密码保存到Flash
* 下次起机的时候,ESP8266发现有保存了可用的Wifi热点,就会通过热点接入互联网。
* 完成上述的配网操作所需要写的代码仅有两行:
- void setup() {
- // 设置Wifi
- WiFiManager wifiManager;
- wifiManager.autoConnect();
- }
复制代码
* ESP8266能连接互联网还不够,需要和贝壳互联云平台连接,才能推送命令。
访问贝壳互联网站注册账号,再注册设备即可,关键的是得到id和apikey,这是给设备做命令推送的凭据:
* 下一步就是写代码让设备连接贝壳互联的服务器,可参考官方例程:https://github.com/bigiot/bigiotArduino
关键代码如下:
- void loop() {
- // 检测网络是否通畅
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- }
- // 检测是否连接到服务器
- if (!client.connected()) {
- if (!client.connect(host, httpPort)) {
- Serial.println("connection failed");
- delay(5000);
- return;
- }
- }
- // 检测是否需要发送心跳包
- if (millis() - lastCheckInTime > postingInterval || lastCheckInTime == 0) {
- Serial.println("Send HeartBeat!!");
- sendHeartBeat();
- }
- // 检测是否收到服务器推送
- if (client.available()) {
- String inputString = client.readStringUntil('\n');
- onMessageReceive(inputString);
- }
- // 判断是否需要将LED闪烁
- if (ledOn) {
- doLedStep();
- }
- }
复制代码
* 可以看出,在loop里面,关键要做的有两件事,
1. 每隔40秒左右向服务端发送心跳包,告诉服务器这个设备还在线
2. 轮询服务端接口是否有下发命令,有的话需要立即响应,至于收到了一个消息,我们要做什么样的处理,这都是我们自由发挥了。
* 为了扩展性,发送和接收的消息都是要编码成json格式,所以为了方便,我们还是要使用个json解析库才行,官方例程里用的是aJson,但是我在IDE里搜索不到这个,还要单独安装。我便没有用aJson,找了一个比较流行的ArduinoJson,大同小异,也可以用。
* 有了JSON解析库,我们就可以解析消息了,先用串口打印消息看看。现在还没有接天猫精灵,先用贝壳物联后台的面板试试Play和Stop按钮的消息是啥:
* Play和Stop的消息打印出来,其实开灯和关灯用的就是这两个:
- {"M":"say","ID":"U11085","NAME":"hzy3774(web)","C":"play","T":"1577714088"}
- {"M":"say","ID":"U11085","NAME":"hzy3774(web)","C":"stop","T":"1577714088"}
复制代码
* 从消息内容可以看出,我们主要解析消息中的C这个字段,即可判断是什么动作,代码如下
- void onMessageReceive(String msg) {
- msg.trim();
- Serial.println(msg);
- if (msg.startsWith("{") && msg.endsWith("}")) {
- DynamicJsonDocument doc(1024);
- deserializeJson(doc, msg);
- JsonObject obj = doc.as<JsonObject>();
- String M = obj["M"];
- if (M == "say") {
- String C = obj["C"];
- if (C == "play") {
- ledOn = 1;
- } else if (C == "stop") {
- ledOn = 0;
- turnLedColor(0);
- } else if (C.startsWith("{") && C.endsWith("}")) {
- deserializeJson(doc, C);
- obj = doc.as<JsonObject>();
- onExtraCommand(obj);
- }
- }
- }
- }
复制代码
* 只要串口能打印,就说明能收到消息了。下一步来接入天猫精灵。
* 操作很简单,主要有三步,在天猫精灵App中添加设备,搜索贝壳,授权绑定后再登陆贝壳账号,即可看到设备信息。
* 绑定完成后就可以对天猫精灵说“开灯”,在串口打印中看到命令是Play,这说明天猫精灵也对接成功了。
- {"M":"say","ID":"U11085","C":"play","SIGN":"Aligenie","T":"1577716165"}
复制代码
* 这个时候如果还想实现更复杂的灯光控制功能,比如对精灵说“亮度50”,“灯光变绿色”,命令的内容就稍微复杂了:
- {"M":"say","ID":"U11085","C":"{"n":"SetColor","a":"color","v":"Green"}","SIGN":"Aligenie","T":"1577715366"}
- {"M":"say","ID":"U11085","C":"{"n":"SetBrightness","a":"brightness","v":"10"}","SIGN":"Aligenie","T":"1577715412"}
复制代码 * 这时候C变得复杂,不过也没关系,对C再做一次JSON解析即可:
- void onExtraCommand(JsonObject obj) {
- String aa = obj["a"];
- if (aa == "brightness") {
- int vv = obj["v"];
- FastLED.setBrightness(vv * 255 / 100);
- } else if (aa == "color") {
- String color = obj["v"];
- ledOn = 0;
- if (color == "Red") {
- turnLedColor(CRGB::Red);
- } else if (color == "Green") {
- turnLedColor(CRGB::Green);
- } else if (color == "Blue") {
- turnLedColor(CRGB::Blue);
- } else if (color == "White") {
- turnLedColor(CRGB::White);
- }
- }
- }
复制代码
* 一步步调试完成,就可以完美运行了,完整代码如下可做个参考,需要替换自己设备的ID和APIKEY即可。
* 目前实现了天猫精灵开关灯,调灯颜色,调灯亮度,其他功能还有待发现。
* 调试灯光的说明可以参考其他帖子如:https://www.mydigit.cn/forum.php?mod=viewthread&tid=112534
- #include <ESP8266WiFi.h>
- #include <WiFiManager.h>
- #include <ArduinoJson.h>
- //============= 此处必须修该============
- String DEVICEID = "00000"; // 你的设备编号 ==
- String APIKEY = "0000000"; // 设备密码==
- unsigned long lastCheckInTime = 0; //记录上次报到时间
- const unsigned long postingInterval = 40000; // 每隔40秒向服务器报到一次
- const char* host = "www.bigiot.net";
- const int httpPort = 8181;
- WiFiClient client;
- //============ LED 相关 ======================
- int ledOn = 0;
- int hue = 0;
- #include <FastLED.h>
- #define LED_PIN 8 //我的LED信号线IN接在8引脚
- #define NUM_LEDS 12 //我的灯带一共级联了12颗LED
- CRGB leds[NUM_LEDS];
- void setup() {
- Serial.begin(115200);
- // 设置LED
- FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
- FastLED.setBrightness(20); //可以设置全局亮度,调低亮度不刺眼
- turnLedColor(0);
- // 设置Wifi
- WiFiManager wifiManager;
- wifiManager.autoConnect();
- }
- void loop() {
- // 检测网络是否通畅
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- }
- // 检测是否连接到服务器
- if (!client.connected()) {
- if (!client.connect(host, httpPort)) {
- Serial.println("connection failed");
- delay(5000);
- return;
- }
- }
- // 检测是否需要发送心跳包
- if (millis() - lastCheckInTime > postingInterval || lastCheckInTime == 0) {
- Serial.println("Send HeartBeat!!");
- sendHeartBeat();
- }
- // 检测是否收到服务器推送
- if (client.available()) {
- String inputString = client.readStringUntil('\n');
- onMessageReceive(inputString);
- }
- // 判断是否需要将LED闪烁
- if (ledOn) {
- doLedStep();
- }
- }
- void turnLedColor(int c) {
- for (int i = 0; i < NUM_LEDS; i++) {
- leds[i] = c;
- }
- FastLED.show();
- }
- void doLedStep() {
- for (int i = 0; i < NUM_LEDS; i++) {
- leds[i] = CHSV( (hue + (255 / NUM_LEDS) * i), 255, 255); //用HSV色彩空间,不断改变H即可
- }
- FastLED.show();
- delay(5);
- hue = (hue + 3) % 255;
- }
- void onExtraCommand(JsonObject obj) {
- String aa = obj["a"];
- if (aa == "brightness") {
- int vv = obj["v"];
- FastLED.setBrightness(vv * 255 / 100);
- } else if (aa == "color") {
- String color = obj["v"];
- ledOn = 0;
- if (color == "Red") {
- turnLedColor(CRGB::Red);
- } else if (color == "Green") {
- turnLedColor(CRGB::Green);
- } else if (color == "Blue") {
- turnLedColor(CRGB::Blue);
- } else if (color == "White") {
- turnLedColor(CRGB::White);
- }
- }
- }
- void onMessageReceive(String msg) {
- msg.trim();
- Serial.println(msg);
- if (msg.startsWith("{") && msg.endsWith("}")) {
- DynamicJsonDocument doc(1024);
- deserializeJson(doc, msg);
- JsonObject obj = doc.as<JsonObject>();
- String M = obj["M"];
- if (M == "say") {
- String C = obj["C"];
- if (C == "play") {
- ledOn = 1;
- } else if (C == "stop") {
- ledOn = 0;
- turnLedColor(0);
- } else if (C.startsWith("{") && C.endsWith("}")) {
- deserializeJson(doc, C);
- obj = doc.as<JsonObject>();
- onExtraCommand(obj);
- }
- }
- }
- }
- void sendHeartBeat() {
- String msg = "{"M":"checkin","ID":"" + DEVICEID + "","K":"" + APIKEY + ""}\n";
- client.print(msg);
- lastCheckInTime = millis();
- }
复制代码
结束
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|