我之前發(fā)布了一篇關(guān)于如果用手機(jī)APP控制LED燈的文章,是基于Blink APP和它的服務(wù)器實(shí)現(xiàn)的,這一講我們?cè)谥暗幕A(chǔ)上做一些擴(kuò)展,通過(guò)手機(jī)的小愛(ài)同學(xué),使用語(yǔ)音控制燈光。沒(méi)有看過(guò)上一篇博客的同學(xué)可以先看一下。
Arduino應(yīng)用開(kāi)發(fā)——手機(jī)APP控制LED
1 工作原理
Blinker APP控?zé)粼恚?/strong>
Blinker廠(chǎng)家有自己的一個(gè)服務(wù)器,我們的設(shè)備(esp8266、esp32、手機(jī)等)都可以通過(guò)網(wǎng)絡(luò)接入到這個(gè)服務(wù)器,手機(jī)app我們看不到源碼不確定是以什么樣的方式接入的,我主要講一下MCU(esp8266、esp32等)這邊,MCU是通過(guò)WIFI連接到互聯(lián)網(wǎng)的,然后通過(guò)MQTT協(xié)議接入到Blinker的服務(wù)器,MCU作為客戶(hù)端,服務(wù)器作為服務(wù)端。具體MQTT的實(shí)現(xiàn)原理這里不多說(shuō)了,光是MQTT這一個(gè)話(huà)題都可以寫(xiě)好多文章了,想深入了解的同學(xué)可以自行查閱資料。
當(dāng)MQTT連成功之后,MCU會(huì)一直偵聽(tīng),等待服務(wù)器下發(fā)數(shù)據(jù)。這個(gè)時(shí)候我們可以通過(guò)手機(jī)app操作,比如點(diǎn)一下開(kāi)燈,服務(wù)器收到這個(gè)開(kāi)燈命令后會(huì)通過(guò)MQTT發(fā)送命令到MCU,MCU接收到數(shù)據(jù)并解析命令后執(zhí)行點(diǎn)燈的操作。服務(wù)器在這里相當(dāng)于一個(gè)中轉(zhuǎn)站,把手機(jī)的操作轉(zhuǎn)發(fā)到設(shè)備端,實(shí)現(xiàn)了手機(jī)和設(shè)備之間的互動(dòng)。不過(guò)有一點(diǎn)要說(shuō)明的是,設(shè)備和服務(wù)器是通過(guò)MQTT連接的,而手機(jī)app和服務(wù)器則不一定是用MQTT,個(gè)人覺(jué)得用http的可能性更大,但是看不到源碼,所以實(shí)際上是怎么通訊的就不清楚了,這個(gè)也不是很重要,并不影響實(shí)際的使用。
小愛(ài)同學(xué)控?zé)粼?/strong>:
說(shuō)明:這里的小愛(ài)同學(xué)可以是小米手機(jī)里面的小愛(ài),也可以是小米的智能音箱。
前面我們已經(jīng)把我們的設(shè)備(esp8266、esp32等)連接到了Blinker的服務(wù)器,實(shí)現(xiàn)了數(shù)據(jù)的上傳下發(fā)。而B(niǎo)linker本身是有對(duì)接小愛(ài)同學(xué)的,并且設(shè)定好了一些固定的語(yǔ)音指令。我們只通過(guò)米家APP關(guān)聯(lián)Blinker的賬號(hào)就能實(shí)現(xiàn)小愛(ài)同學(xué)和Blinker服務(wù)器的聯(lián)動(dòng),再結(jié)合之前Blinker服務(wù)器和我們的硬件設(shè)備的連接,就可以間接的實(shí)現(xiàn)小愛(ài)同學(xué)和硬件設(shè)備的交互。
簡(jiǎn)單來(lái)說(shuō)就是我們的語(yǔ)音指令通過(guò)小愛(ài)同學(xué)發(fā)送到Blinker的服務(wù)器,再由Blinker的服務(wù)器轉(zhuǎn)發(fā)到我們的硬件設(shè)備。Blinker服務(wù)器在這里起到一個(gè)數(shù)據(jù)解析、中轉(zhuǎn)的作用。
2 硬件準(zhǔn)備
我這里以ESP8266和ESP32為例講解,其他MCU方法和原理都是一樣的,所以根據(jù)自己的MCU選擇其中一種即可。
硬件配置如下:
模塊 | 型號(hào) | 說(shuō)明 |
---|---|---|
ESP8266 | ESP-12F | 這是安信可的一款模組,內(nèi)部主要是用樂(lè)鑫的ESP8266EX再加上一個(gè)片外FLASH組成,開(kāi)發(fā)板型號(hào)是NodeMCU-12F(CH340版本) |
ESP32 | ESP-WROOM-32 | MCU是樂(lè)鑫的一款芯片,開(kāi)發(fā)板型號(hào)ESP32 DEVKITV1 |
具體的硬件參數(shù)和電路原理圖這里就不發(fā)出來(lái)了,不同廠(chǎng)家做的開(kāi)發(fā)板引腳可能會(huì)有點(diǎn)差別。
3 軟件準(zhǔn)備
版本說(shuō)明:
本文測(cè)試時(shí)各軟件使用的版本如下:
軟件 | 版本 | 備注 |
---|---|---|
Arduino IDE | 1.8.16 | Blinker需要配合1.8.x及以上版本的Arduino IDE |
ESP8266 package | 3.0.2 | Blinker需配合使用3.0.0或以上release版本的ESP8266 package |
ESP32 package | 3.0.2 | Blinker需配合使用2.0.0或以上版本的ESP32 package |
Blinker arduino package | 0.3.9 | 當(dāng)前最新版本,以后可能會(huì)有更新 |
Blinker APP | 2.5.2(安卓版) | 當(dāng)前最新版本,以后可能會(huì)有更新 |
米家APP | 7.5.705.5319(安卓版) | 當(dāng)前最新版本,以后可能會(huì)有更新 |
3.1 Arduino IDE環(huán)境搭建
這個(gè)在我的博客里面講過(guò)很多次了,這里就不再說(shuō)了,不懂的同學(xué)先按上一講把環(huán)境搭好(根據(jù)自己的MCU選擇對(duì)應(yīng)的教程)。
Arduino應(yīng)用開(kāi)發(fā)——手機(jī)APP控制LED
esp8266開(kāi)發(fā)入門(mén)教程(基于Arduino)——環(huán)境安裝
ESP32 Arduino開(kāi)發(fā)環(huán)境搭建
3.2 Blinker APP賬號(hào)注冊(cè)和使用
這個(gè)內(nèi)容比較多,這里不再贅述了,不懂的同學(xué)先看下上一講的第4點(diǎn)。
Arduino應(yīng)用開(kāi)發(fā)——手機(jī)APP控制LED
4 編寫(xiě)程序
上一講的教程講了怎么用Blinker APP創(chuàng)建設(shè)備并實(shí)現(xiàn)遠(yuǎn)程控制。
這一講在這基礎(chǔ)上增加小愛(ài)同學(xué)的語(yǔ)音控制。我們保留上一講的功能,然后增加電源控制和設(shè)備查詢(xún)這兩個(gè)回調(diào)函數(shù),這兩個(gè)函數(shù)的接口在Blinker的庫(kù)源碼中已經(jīng)定義好了,我們直接使用即可。我們通過(guò)電源控制回調(diào)函數(shù)實(shí)現(xiàn)LED燈的開(kāi)關(guān)控制。
示例代碼:
提示:代碼中的WIFI的賬號(hào)和密碼根據(jù)實(shí)際情況修改。
#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT // 燈設(shè)備
// #define BLINKER_MIOT_OUTLET // 插座設(shè)備
// #define BLINKER_MIOT_MULTI_OUTLET // 多個(gè)插座設(shè)備
// #define BLINKER_MIOT_SENSOR // 傳感器設(shè)備
// #define BLINKER_MIOT_FAN // 風(fēng)扇設(shè)備
// #define BLINKER_MIOT_AIR_CONDITION // 空調(diào)設(shè)備
#include
char auth[] = "e6fce38e525a"; // 設(shè)備密鑰
char ssid[] = "test"; // WIFI賬號(hào)
char pswd[] = "123456789"; // WIFI密碼
#define LED_PIN 2 // LED引腳
// 新建組件對(duì)象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");
int counter = 0;
bool oState = false;
// 電源控制回調(diào)函數(shù)
void miotPowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON)
{// 打開(kāi)開(kāi)關(guān)
digitalWrite(LED_PIN, HIGH); // 開(kāi)燈
BlinkerMIOT.powerState("on");
BlinkerMIOT.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF)
{// 關(guān)閉開(kāi)關(guān)
digitalWrite(LED_PIN, LOW); // 關(guān)燈
BlinkerMIOT.("off");
BlinkerMIOT.print();
oState = false;
}
}
// 查詢(xún)?cè)O(shè)備狀態(tài)回調(diào)函數(shù)
void miotQuery(int32_t queryCode)
{
BLINKER_LOG("MIOT Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER : // 查詢(xún)所有設(shè)備
BLINKER_LOG("MIOT Query All");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER : // 查詢(xún)電源類(lèi)設(shè)備
BLINKER_LOG("MIOT Query Power State");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
default : // 查詢(xún)其他設(shè)備
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
}
}
// 按下按鍵即會(huì)執(zhí)行該函數(shù)
void button1_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // 翻轉(zhuǎn)LED燈狀態(tài)
}
// 如果未綁定的組件被觸發(fā),則會(huì)執(zhí)行其中內(nèi)容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
Number1.print(counter);
}
void setup()
{
// 初始化串口
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
// 初始化LED的IO
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
// 初始化blinker
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead); // 未綁定設(shè)備回調(diào)
Button1.attach(button1_callback); // 按鍵回調(diào)
BlinkerMIOT.attachPowerState(miotPowerState); // 電源控制回調(diào)
BlinkerMIOT.attachQuery(miotQuery); // 查詢(xún)?cè)O(shè)備狀態(tài)回調(diào)
}
void loop() {
Blinker.run();
}
5 關(guān)聯(lián)米家APP和Blinker設(shè)備
打開(kāi) 米家APP
,點(diǎn)擊我的
,點(diǎn)擊其他平臺(tái)設(shè)備
,點(diǎn)擊添加
,在列表中找到點(diǎn)燈科技
,點(diǎn)擊綁定賬號(hào)
,登錄你的Blinker賬號(hào),最后點(diǎn)擊同步設(shè)備
即可。設(shè)備同步成功之后就可以看到你在Blinker APP上創(chuàng)建的所有設(shè)備。
提示1:Blinker賬號(hào)的注冊(cè)以及APP的使用請(qǐng)?zhí)D(zhuǎn)到3.2查看。我在上一篇博客有詳細(xì)的教程。
提示2:同步設(shè)備可能會(huì)出現(xiàn)失敗的情況,我一開(kāi)始同步的時(shí)候一直失敗,過(guò)了一段時(shí)間之后再?lài)L試又沒(méi)出現(xiàn)了,不知道是不是APP的bug。
6 語(yǔ)音控制測(cè)試
特別說(shuō)明:我沒(méi)有小愛(ài)同學(xué)的智能音箱,我這里是直接用小米的手機(jī)來(lái)測(cè)試的。
注:其他品牌的手機(jī)可以下載米家APP,但是沒(méi)法使用小愛(ài)同學(xué)。
把燒錄好代碼的設(shè)備通上電,通過(guò)串口打印的一些信息,我們可以看到設(shè)備正常連上網(wǎng)絡(luò)之后會(huì)連接到Blinker的服務(wù)器,連接成功之后可以在Blinker的APP上看到設(shè)備的狀態(tài)由 ‘離線(xiàn)’ 變成 ‘在線(xiàn)’。
小愛(ài)同學(xué)支持的開(kāi)關(guān)類(lèi)控制語(yǔ)音如下:
打開(kāi)/關(guān)閉{門(mén)口}的{燈}
提示1:{}里面的內(nèi)容是通配多種關(guān)鍵詞的,你可以在Blinker APP修改設(shè)備的名稱(chēng),然后語(yǔ)音對(duì)應(yīng)的命令也要跟著改變,保持一致才能正確的控制設(shè)備。
對(duì)著小米手機(jī)呼叫小愛(ài)同學(xué)
,收到回應(yīng)之后再說(shuō)打開(kāi)燈
,就能看到設(shè)備的LED燈被打開(kāi)了。同理,關(guān)閉燈的指令也是一樣的操作。
通過(guò)串口打印的信息也可以看到開(kāi)燈和關(guān)燈相關(guān)的指令。
至此,從小愛(ài)同學(xué)到硬件設(shè)備的整個(gè)流程就走通了。流程走通了之后我們就可以在這個(gè)基礎(chǔ)上增加更多的功能,比如控制燈的亮度,設(shè)備工作模式等等,也可以修改設(shè)備的名稱(chēng),或者控制更多其他類(lèi)型的設(shè)備。
7 進(jìn)階用法
通過(guò)Blinker關(guān)聯(lián)小愛(ài)同學(xué)控制設(shè)備其實(shí)有很大的局限性,因?yàn)樾?ài)同學(xué)所有的語(yǔ)音指令都是Blinker定義好的,不支持做過(guò)多的修改,而且目前支持的語(yǔ)音指令實(shí)在是有點(diǎn)少,當(dāng)我們需要自定義一些指令時(shí)并不能通過(guò)這套代碼實(shí)現(xiàn)。不過(guò)如果只是玩一下或者學(xué)習(xí)的話(huà),還是可以去研究一下的。
關(guān)于Blinker以及小愛(ài)同學(xué)所支持的設(shè)備和語(yǔ)音指令在點(diǎn)燈科技的官網(wǎng)上其實(shí)有比較詳細(xì)的介紹。
點(diǎn)燈科技小米小愛(ài)技術(shù)文檔:https://diandeng.tech/doc/xiaoai
我們這里也基于這些給定的語(yǔ)音指令做一些進(jìn)階的操作。
前面的示例我們通過(guò)小愛(ài)同學(xué)控制了燈的亮滅,然后現(xiàn)在我們?cè)黾覮ED燈亮度、色溫以及模式的控制。
特別說(shuō)明:要實(shí)際控制燈的亮度和色溫的話(huà)我們需要用到RGB燈,而且有些比較簡(jiǎn)單的GRB燈只能調(diào)節(jié)三色燈的亮滅,最多也只能調(diào)出8種顏色,如果需要調(diào)節(jié)出多種色溫,還需要調(diào)節(jié)三色燈里面每一個(gè)燈的亮度。每個(gè)燈的亮度階梯越多,能跳出來(lái)的色彩就越多。如果是單色LED的話(huà)最多只能調(diào)亮度,是沒(méi)辦法改變顏色的,亮度調(diào)節(jié)可以通過(guò)PWM實(shí)現(xiàn)。
我這里因?yàn)楝F(xiàn)在手頭上也沒(méi)有合適的燈,這里就不做具體的演示了,我這里只講一下怎么把小愛(ài)語(yǔ)音和LED燈的控制代碼關(guān)聯(lián)起來(lái),至于實(shí)際的一些操作,感興趣的同學(xué)可以自己再補(bǔ)充。
7.1 亮度控制
小愛(ài)同學(xué)支持的亮度控制語(yǔ)音如下:
把{臥室}的{燈}的{亮度調(diào)高一點(diǎn)}
亮度范圍為1-100
注:括號(hào)里面的的關(guān)鍵字是可以用戶(hù)自己修改定義的。比如:燈可以換成其他關(guān)鍵字,如氛圍燈、大燈等,這個(gè)是跟你在Blinker APP里面修改的設(shè)備名稱(chēng)保持一致的。
示例代碼:
提示:我這里只把新增的函數(shù)列出來(lái),等后面把亮度、色溫以及模式的控制全部講完之后再列一個(gè)完整的代碼。
// 燈光亮度控制回調(diào)函數(shù)
void miotBright(const String & bright)
{
BLINKER_LOG("need set brightness: ", bright); // 打印需要設(shè)置的亮度
uint8_t colorW = bright.toInt();
BLINKER_LOG("now set brightness: ", colorW);
// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改PWM占空比的值,從而達(dá)到調(diào)節(jié)燈亮度的目的
BlinkerMIOT.brightness(colorW);
BlinkerMIOT.print();
}
// 燈光亮度控制初始化
BlinkerMIOT.attachBrightness(miotBright);
測(cè)試結(jié)果:
特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。
對(duì)著小愛(ài)同學(xué)說(shuō):把燈的亮度調(diào)到60
。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了這個(gè)命令,并且把要調(diào)節(jié)的亮度值60解析出來(lái)了,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮?,因此,LED燈是沒(méi)有變化的。
7.2 色溫控制
小愛(ài)同學(xué)支持的色溫控制語(yǔ)音如下:
把{臥室}的{燈}調(diào)為{紅色}
顏色范圍為0-16777215(0xFFFFFF)
示例代碼:
提示:我這里只把新增的函數(shù)列出來(lái),等后面把亮度、色溫以及模式的控制全部講完之后再列一個(gè)完整的代碼。
// 燈光色溫控制回調(diào)函數(shù)
void miotColor(int32_t color)
{
BLINKER_LOG("need set color: ", color);
// 從接收到的數(shù)據(jù)中解析得到需要配置的R G B三色光的亮度值
uint8_t colorR = color >> 16 & 0xFF;
uint8_t colorG = color >> 8 & 0xFF;
uint8_t colorB = color & 0xFF;
BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB);
// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改R G B三個(gè)燈的亮度從而達(dá)到修改燈顏色的目的
BlinkerMIOT.color(color);
BlinkerMIOT.print();
}
// 燈光色溫控制初始化
BlinkerMIOT.attachColor(miotColor);
測(cè)試結(jié)果:
特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。
對(duì)著小愛(ài)同學(xué)說(shuō):把燈調(diào)為紫色
。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了改命令,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮?,因此,LED燈是沒(méi)有變化的。
提示:這里RGB三元光的亮度范圍是0-255,把三種亮度不同的光混合在一起就能產(chǎn)生多種多樣的顏色。
7.3 模式控制
小愛(ài)同學(xué)支持的色溫控制語(yǔ)音如下:
把{臥室}的{燈}設(shè)置為{xx模式}
示例代碼:
提示:我這里只把新增的函數(shù)列出來(lái),后面有完整的代碼。
// 模式控制回調(diào)函數(shù)
void miotMode(uint8_t mode)
{
BLINKER_LOG("need set mode: ", mode); // 打印接收到需要設(shè)置的模式,數(shù)值是(0-6),對(duì)應(yīng)7種模式
if (mode == BLINKER_CMD_MIOT_DAY) {
// 日光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_NIGHT) {
// 夜光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_COLOR) {
// 彩光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_WARMTH) {
// 溫馨模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_TV) {
// 電視模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_READING) {
// 閱讀模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_COMPUTER) {
// 電腦模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
BlinkerMIOT.mode(mode);
BlinkerMIOT.print();
}
// 模式控制初始化
BlinkerMIOT.attachMode(miotMode);
測(cè)試結(jié)果:
特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。
對(duì)著小愛(ài)同學(xué)說(shuō):把燈調(diào)為夜光模式
。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了改命令,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮?,因此,LED燈是沒(méi)有變化的。
前面我也講過(guò),Blinker這套方案有比較大的局限性,就比如這里的模式,雖然支持多種模式,但是每一個(gè)模式都只能通過(guò)固定的關(guān)鍵字(日光、夜光、彩光等)來(lái)觸發(fā),不能自定義,如果是控?zé)暨€好,很多都可以用上,但是如果控制的是其他設(shè)備,這些模式的關(guān)鍵字就牛頭不對(duì)馬嘴了。
我也沒(méi)有找到改指令關(guān)鍵字的接口,應(yīng)該是Blinker沒(méi)有開(kāi)放這個(gè)接口或者不支持這個(gè)功能。這一點(diǎn)是不太友好的,不過(guò)Blinker畢竟是一個(gè)公司,目的還是盈利,而且維護(hù)服務(wù)器也是需要成本的,白嫖黨也不能要求太多。
完整的進(jìn)階示例代碼:
#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT // 燈設(shè)備
// #define BLINKER_MIOT_OUTLET // 插座設(shè)備
// #define BLINKER_MIOT_MULTI_OUTLET // 多個(gè)插座設(shè)備
// #define BLINKER_MIOT_SENSOR // 傳感器設(shè)備
// #define BLINKER_MIOT_FAN // 風(fēng)扇設(shè)備
// #define BLINKER_MIOT_AIR_CONDITION // 空調(diào)設(shè)備
#include <Blinker.h>
char auth[] = "e6fce38e525a"; // 設(shè)備密鑰
char ssid[] = "tst"; // WIFI賬號(hào)
char pswd[] = "123456789"; // WIFI密碼
#define LED_PIN 2 // LED引腳
// 新建組件對(duì)象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");
int counter = 0;
bool oState = false;
// 電源控制回調(diào)函數(shù)
void miotPowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON)
{// 打開(kāi)開(kāi)關(guān)
digitalWrite(LED_PIN, HIGH); // 開(kāi)燈
BlinkerMIOT.powerState("on");
BlinkerMIOT.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF)
{// 關(guān)閉開(kāi)關(guān)
digitalWrite(LED_PIN, LOW); // 關(guān)燈
BlinkerMIOT.powerState("off");
BlinkerMIOT.print();
oState = false;
}
}
// 查詢(xún)?cè)O(shè)備狀態(tài)回調(diào)函數(shù)
void miotQuery(int32_t queryCode)
{
BLINKER_LOG("MIOT Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER : // 查詢(xún)所有設(shè)備
BLINKER_LOG("MIOT Query All");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER : // 查詢(xún)電源類(lèi)設(shè)備
BLINKER_LOG("MIOT Query Power State");
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
default : // 查詢(xún)其他設(shè)備
BlinkerMIOT.powerState(oState ? "on" : "off");
BlinkerMIOT.print();
break;
}
}
// 燈光亮度控制回調(diào)函數(shù)
void miotBright(const String & bright)
{
BLINKER_LOG("need set brightness: ", bright);
uint8_t colorW = bright.toInt();
BLINKER_LOG("now set brightness: ", colorW);
// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改PWM占空比的值從而達(dá)到調(diào)節(jié)燈亮度的目的
BlinkerMIOT.brightness(colorW);
BlinkerMIOT.print();
}
// 燈光色溫控制回調(diào)函數(shù)
void miotColor(int32_t color)
{
BLINKER_LOG("need set color: ", color);
// 從接收到的數(shù)據(jù)中解析得到需要配置的R G B三色光的亮度值
uint8_t colorR = color >> 16 & 0xFF;
uint8_t colorG = color >> 8 & 0xFF;
uint8_t colorB = color & 0xFF;
BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB);
// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改R G B三個(gè)燈的亮度從而達(dá)到修改燈顏色的目的
BlinkerMIOT.color(color);
BlinkerMIOT.print();
}
// 模式控制回調(diào)函數(shù)
void miotMode(uint8_t mode)
{
BLINKER_LOG("need set mode: ", mode); // 打印接收到需要設(shè)置的模式,數(shù)值是(0-6),對(duì)應(yīng)7種模式
if (mode == BLINKER_CMD_MIOT_DAY) {
// 日光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_NIGHT) {
// 夜光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_COLOR) {
// 彩光模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_WARMTH) {
// 溫馨模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_TV) {
// 電視模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_READING) {
// 閱讀模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
else if (mode == BLINKER_CMD_MIOT_COMPUTER) {
// 電腦模式,在這里面可以添加自己實(shí)際需要控制的代碼
}
BlinkerMIOT.mode(mode);
BlinkerMIOT.print();
}
// 按下按鍵即會(huì)執(zhí)行該函數(shù)
void button1_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // 翻轉(zhuǎn)LED燈狀態(tài)
}
// 如果未綁定的組件被觸發(fā),則會(huì)執(zhí)行其中內(nèi)容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
Number1.print(counter);
}
void setup()
{
// 初始化串口
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
// 初始化LED的IO
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
// 初始化blinker
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead); // 未綁定設(shè)備回調(diào)
Button1.attach(button1_callback); // 按鍵回調(diào)
BlinkerMIOT.attachPowerState(miotPowerState); // 電源控制回調(diào)
BlinkerMIOT.attachQuery(miotQuery); // 查詢(xún)?cè)O(shè)備狀態(tài)回調(diào)
BlinkerMIOT.attachBrightness(miotBright); // 燈光亮度控制回調(diào)
BlinkerMIOT.attachColor(miotColor); // 燈光色溫控制回調(diào)
BlinkerMIOT.attachMode(miotMode); // 模式控制回調(diào)
}
void loop() {
Blinker.run();
}
結(jié)束語(yǔ)
好了,關(guān)于如何在Arduino上通過(guò)小愛(ài)同學(xué)控制燈光就到這里。Blinker的這套框架局限性比較大,只適用于某些設(shè)備,也只能使用比較固定的命令,不能做過(guò)多的修改,這一點(diǎn)是不太好的,但好處是比較省事,不需要我們做語(yǔ)音這部分的開(kāi)發(fā),有利有弊吧,對(duì)于學(xué)生黨或者剛?cè)腴T(mén)的初學(xué)者來(lái)說(shuō)是可以去玩一下的,而且Blinker維護(hù)服務(wù)器本身也是需要成本的,能免費(fèi)提供這個(gè)平臺(tái)給大家用就算不錯(cuò)了,白嫖黨要求也不能太過(guò)分是吧。如果有條件的話(huà)就自己搭服務(wù)器,這樣可操作性會(huì)大大的增加。
想了解更多Arduino的內(nèi)容,可以關(guān)注一下博主,后續(xù)我還會(huì)繼續(xù)分享更多的經(jīng)驗(yàn)給大家。
還有什么問(wèn)題的話(huà),歡迎在評(píng)論區(qū)留言。
如果這篇文章能夠幫到你,就…你懂得。