#本片教程介紹了具體如何實現天貓精靈控制一個燈。php
前提:git
HASS平臺json
天貓精靈ubuntu
ESP8266模塊服務器
2 爲了防止關閉遠程訪問,而致使正在運行的程序跟着關閉,開啓一個screen背後運行微信
首先查一下正在運行的screenapp
screen -lside
這裏發現已經有一個背後運行的screen(裏面是我以前開啓的mqtt和hass程序)函數
screen -r 1102 # 查詢指定編號的screen裏運行的程序 oop
而後來到 編號爲1102的screen下面
3運行 mqtt 服務器
上一步,咱們已經來到 編號爲1102的screen下面(或者你新建的screen下面)
進入 emqtt 文件路徑下
cd Dongdong/emqttd
命令行進入路徑,開啓mqtt服務
./bin/emqttd start
4 運行hass
hass
回車開始運行
5 查看hass
打開谷歌遊覽器
輸入 域名:8123
密碼
看到本身的頁面
圖中是我默認添加的兩個測試設備
目的:告訴HASS平臺,如今有一個新的設備---燈要被你控制管理
手動添加模式
0 打開配置文件手動配置HASS要鏈接的MQTT服務器
這裏兩個選擇
一 蹭一下別人的mqtt服務器
二 直接在HASS的服務器上運行一個,這裏我安裝了EMQ版本的MQTT服務器,因此網址是本地的MQTT服務器 127.0.0.1:1883
# configuration.yaml配置樣例 mqtt: # MQTT Broker的IP地址或者域名,這裏蹭的官網測試服務器 #broker: broker.mqtt-dashboard.com
#我在hass同一個服務器上,開了一個MQTT服務器
broker: 127.0.0.1
# MQTT Broker的端口號,缺省爲1883 port: 1883 #client_id: home-assistant-1 # 用戶名 不用設置 #username: homeassistant # 密碼 不用設置 #password: 123456
1 打開配置文件手動增長一個設備
platform: mqtt name: "light_on" state_topic: "hachina/rgb1/light/status" command_topic: "hachina/rgb1/light/switch" brightness_state_topic: "hachina/rgb1/brightness/status" brightness_command_topic: "hachina/rgb1/brightness/set" rgb_state_topic: "hachina/rgb1/rgb/status" rgb_command_topic: "hachina/rgb1/rgb/set" state_value_template: "{{ value_json.state }}" brightness_value_template: "{{ value_json.brightness }}" rgb_value_template: "{{ value_json.rgb | join(',') }}" qos: 0 payload_on: "ON" payload_off: "OFF" optimistic: false
自動添加模式
0 HASS配置要鏈接的MQTT服務器
1 HASS配置文件中開啓自動發現設備。
# configuration.yaml配置樣例 mqtt: # MQTT Broker的IP地址或者域名,這裏蹭的官網測試服務器 #broker: broker.mqtt-dashboard.com #我在hass同一個服務器上,開了一個MQTT服務器 broker: 127.0.0.1 # MQTT Broker的端口號,缺省爲1883 port: 1883 #client_id: home-assistant-1 # 用戶名 不用設置 #username: homeassistant # 密碼 不用設置 #password: 123456
2 ESP8266 WIFI模塊(燈)發送本身的配置信息給HASS的配置話題。
hass配置話題 位置
homeassistant/light/garden/config
garden能夠隨意換--設備ID
發送的配置信息
{"name": "light_on", "command_topic": "hachina/rgb1/light/switch", "state_topic": "hachina/rgb1/light/status","brightness_command_topic": "hachina/rgb1/brightness/set", "brightness_state_topic": "hachina/rgb1/brightness/status","rgb_command_topic": "hachina/rgb1/rgb/set","rgb_state_topic": "hachina/rgb1/rgb/status","state_value_template": "{{ value_json.state }}","brightness_value_template": "{{ value_json.brightness }}","rgb_value_template": "{{ value_json.rgb | join(',') }}","optimistic": false}
而後能夠看到 HASS平臺上多了一個燈 light_on(其餘兩個設備忽略)
light_on是我用esp8266自動註冊的一個只有開關狀態的燈
TestLed2_light_MQTT是我手動在配置文件中添加的燈,具有開關 顏色 亮度
上述兩個燈除了名字不同,其餘接收開關的話題我設置成一摸同樣。
能夠直接用HASS來控制燈
手機HASS app
編輯--添加設備--裏面有個咱們自定義的燈設備 light_on--添加進來
短按開關,長按跳出顏色控制板塊
下一步,接入天貓精靈,使用語音間接控制HASS的設備(HASS自帶語音識別和播放服務,也可以使用)
疑問: 爲什麼貓精不直接控制燈?
世界燈種類千千萬,鬼知道你這是什麼燈,因此具體控制業務由專門開發智能家居的公司來搞,貓精只負責把語音控制解析信息給智能家居平臺公司,由他們本身去控制本身平臺下的燈。
1 登錄hass論壇,註冊帳戶和密碼
https://bbs.hassbian.com
2打開天貓精靈APP,在智能家居---綁定平臺帳號----綁定HASS帳戶和密碼
這樣貓精就和HASS這個具體的智能家居公司對接起來了(然而HASS不是一個公司,是一個開源項目,申請成爲開發合做者)
3將HASS上已有的設備同步到天貓精靈手機APP-智能家居控制列表裏,從而使得貓精間接經過HASS控制咱們的燈
具體過程:
打開HASS論壇架設的配置網址
https://bbs.hassbian.com/tmall/discovery.php
輸入本身的HASS地址和密碼信息,進入本身的HASS設備管理
將第一步HASS發現的ID爲 light_on的燈添加到天貓精靈設備管理中。
選擇增長--真實設備
設置燈的信息
這裏 天貓精靈看到hass上有三個設備
只具有 開關 不具有顏色 亮度支持
只具有 開關 不具有顏色 亮度支持
具有 開關 顏色 亮度
這裏咱們先添加個功能徹底的
完成後,多出一個彩燈設備
打開天貓精靈APP,在智能家居中發現,多出一個彩燈設備(我已經在app裏從新更名字,截圖不是)
爲了提升語音識別準確度,我按照天貓精靈APP的設置從新取了名字 --- 臥室的燈。
就這樣,語音告訴貓精開燈,貓精解析語音後告訴HASS平臺,去開哪盞燈。
-------------------------------------------------------------------------
hass是個智能家居管理平臺,能夠介入各類設備,具體怎麼控制燈,這裏須要藉助MQTT通訊協議和服務。
MQTT服務典型: 我想和女友說「我愛你」,並非我直接告訴她,而是我在 「love」這個話題下,發佈了「我愛你」這個消息,她訂閱「love」話題,這樣每次從「love」這個話題下,接收到「我愛你」的消息
這種服務好在哪: 凡是訂閱這個話題的人,都能收到一樣的消息,反之,也均可以往這個話題發消息。就像QQ和微信討論組同樣。
-------------------------------------------------------------------------
HASS接收到開哪一個燈命令後,找到這個燈的信息,把開關,顏色,亮度控制命令經過MQTT放在指定話題上,等待燈來這個話題上取消息。
這個燈如何取到消息?
1能聯網----這裏選擇ESP8266 wifi模塊
2能使用MQTT-- esp8266 在 aruino ide開發平臺 下有現成的MQTT通訊庫。使用這個庫能夠很輕易從對應話題拿到想要的數據。
3能當單片機控制-- ESP8266能夠當一塊單片機 開發,外接繼電器能夠控制220V的開和關。
燒錄時板型選擇信息(根據本身使用的ESP866 wifi板類型)
兩種控制模式:
1 使用HASS網頁版或者手機APP直接控制
開關
亮度
顏色
2 天貓精靈語音控制hass,間接控制燈
天貓精靈 打開臥室的的燈
天貓精靈 關閉臥室的的燈
天貓精靈 將臥室的的燈顏色調成紅色
天貓精靈 將臥室的的燈亮度調爲60
ESP8266串口打印輸出:
程序功能:
將來擴展:
目前bug
因爲ESP自己內存小,沒法發送太多信息。只能發送簡單的開關
警告:
自動發現設備的時候,必定要改配置話題第三個參數ID,
第一個設備 名字 RGBlight ID garden 存在
homeassistant/light/garden/config
{"name": "RGBlight", "command_topic": "hachina/rgb1/light/switch",
第二個設備 名字light ID garden1 存在
homeassistant/light/garden1/config
{"name": "light", "command_topic": "hachina/rgb1/light/switch",
第三個設備 名字light ID garden2 存在
homeassistant/light/garden2/config
{"name": "light", "command_topic": "hachina/rgb1/light/switch",
第四個設備 名字light ID garden 不存在
homeassistant/light/garden/config
{"name": "light", "command_topic": "hachina/rgb1/light/switch",
ID和第一個配置ID衝突,只能存在一個
esp8266燒錄代碼
/*************************************************** ****************************************************/ #include <ESP8266WiFi.h> #include "Adafruit_MQTT.h" #include "Adafruit_MQTT_Client.h" /*------------------------------------------------------------------------------------------- * 配置WIFI信息 *------------------------------------------------------------------------------------------*/ #define WLAN_SSID "dongdong" #define WLAN_PASS "ldd123456" /*------------------------------------------------------------------------------------------- * 配置MQTT服務器信息 *------------------------------------------------------------------------------------------*/ //#define AIO_SERVER "io.adafruit.com" // 不穩定 //#define AIO_SERVER "broker.mqtt-dashboard.com" // 穩定 #define AIO_SERVER "本身的mqtt服務器地址" #define AIO_SERVERPORT 1883 // use 8883 for SSL #define AIO_USERNAME "" #define AIO_KEY "" /*------------------------------------------------------------------------------------------- * 配置外接設備 *------------------------------------------------------------------------------------------*/ // 燈的接口 D4口-繼電器 int Light_d1 = D4; /*------------------------------------------------------------------------------------------- * 開啓MQTT服務 *------------------------------------------------------------------------------------------*/ // Create an ESP8266 WiFiClient class to connect to the MQTT server. WiFiClient client; // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_USERNAME, AIO_KEY); /*------------------------------------------------------------------------------------------- -因爲MQTT發佈信息有長度限制 130個左右,不能一次性發送太多自身配置信息,所以發雜的設備沒法註冊 */ // 發送自身配置信息 開關 // 名字 String name_s="light_on"; // 接收開關命令話題 String command_topic_s="hachina/rgb1/light/switch"; // 自身開關狀態發佈話題 String state_topic_s = "hachina/rgb1/light/status"; // 接收亮度命令話題 String brightness_command_topic_s="hachina/rgb1/brightness/set"; // 自身亮度發佈話題 String brightness_state_topic_s="hachina/rgb1/brightness/status"; // 接收顏色命令話題 String rgb_command_topic_s="hachina/rgb1/rgb/set"; // 自身顏色狀態發佈話題 String rgb_state_topic_s="hachina/rgb1/rgb/status"; // 話題能夠性 String optimistic_c="false"; // 可用1 註冊一個只有開關的燈 沒有亮度和顏色 String my_config_s= String("{\"name\":\"")+ name_s +String("\",\"command_topic\":\"")+command_topic_s +String("\",\"state_topic\":\"")+state_topic_s //+String("\",\"brightness_command_topic\":\"")+brightness_command_topic_s //+String("\",\"brightness_state_topic\":\"")+brightness_state_topic_s //+String("\",\"rgb_command_topic_topic\":\"")+rgb_command_topic_s //+String("\",\"rgb_state_topic\":\"")+rgb_state_topic_s +String("\",\"optimistic\":\"")+optimistic_c +String("\"}"); String hass_config_s1="homeassistant/light/garden/config"; // 發佈本身的配置信息 Adafruit_MQTT_Publish hass_config = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "homeassistant/light/garden/config"); // 發佈本身的開關信息 Adafruit_MQTT_Publish state_topic = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "hachina/rgb1/light/status"); //發佈本身的亮度信息 Adafruit_MQTT_Publish brightness_state_topic = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "hachina/rgb1/brightness/status"); //發佈本身的顏色信息 Adafruit_MQTT_Publish rgb_state_topic = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "hachina/rgb1/rgb/status"); /*------------------------------------------------------------------------------------------- * 功能:訂閱開關信息 * 輸入:顏色數據 * 輸出:空 *------------------------------------------------------------------------------------------*/ //訂閱開關命令 Adafruit_MQTT_Subscribe command_topic = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "hachina/rgb1/light/switch", MQTT_QOS_1); //訂閱亮度命令 Adafruit_MQTT_Subscribe brightness_command_topic = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "hachina/rgb1/brightness/set", MQTT_QOS_1); //訂閱顏色命令 Adafruit_MQTT_Subscribe rgb_command_topic = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "hachina/rgb1/rgb/set", MQTT_QOS_1); /*************************** 接受信息訂閱函數 ************************************/ /*------------------------------------------------------------------------------------------- * 功能:接收開關命令回掉函數 * on 開燈 off 關燈 * 輸入:接收數據+數據長度 * 輸出:空 *------------------------------------------------------------------------------------------*/ void command_topic_call(char *data, uint16_t len) { Serial.print("the button value is: "); Serial.println(data); String msg=String(data); if(msg=="ON") { Serial.println("light is open"); digitalWrite(Light_d1, HIGH); if (! state_topic.publish("ON")) { Serial.println(F("state_topic.publish Failed")); } else { Serial.println(F("state_topic.publish ON!")); } } if(msg=="OFF") { Serial.println("light is close"); digitalWrite(Light_d1, LOW); if (! state_topic.publish("OFF")) { Serial.println(F("state_topic.publish Failed")); } else { Serial.println(F("state_topic.publish OFF!")); } } } /*------------------------------------------------------------------------------------------- * 功能:接收亮度命令回掉函數 * 向電腦打印輸出亮度值 0-255 * 輸入:亮度數據 * 輸出:空 *------------------------------------------------------------------------------------------*/ void brightness_command_topic_call(double x) { Serial.print("Hey we're in a slider callback, the slider value is: "); Serial.println(x); if (! brightness_state_topic.publish(x)) { Serial.println(F("brightness_state_topic.publish Failed")); } else { Serial.print(F("brightness_state_topic.publish "));Serial.println(x); } } /*------------------------------------------------------------------------------------------- * 功能:接收顏色命令回掉函數 * 向電腦打印輸出亮度值 255,255,255 * 輸入:顏色數據 * 輸出:空 *------------------------------------------------------------------------------------------*/ void rgb_command_topic_call(char *data, uint16_t len) { Serial.print("the button value is: "); Serial.println(data); } void setup() { pinMode(Light_d1, OUTPUT); digitalWrite(Light_d1, LOW); Serial.begin(115200); delay(10); Serial.println(F("Adafruit MQTT demo")); // Connect to WiFi access point. Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(WLAN_SSID); WiFi.begin(WLAN_SSID, WLAN_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // 配置信息轉換 // strcpy( my_config_c, my_config.c_str()); // 回掉函數 command_topic.setCallback(command_topic_call); brightness_command_topic.setCallback(brightness_command_topic_call); rgb_command_topic.setCallback(rgb_command_topic_call); // 訂閱話題註冊 mqtt.subscribe(&command_topic); mqtt.subscribe(&brightness_command_topic); mqtt.subscribe(&rgb_command_topic); } uint32_t x=0; void loop() { MQTT_connect(); // this is our 'wait for incoming subscription packets and callback em' busy subloop // try to spend your time here: mqtt.processPackets(10000); // ping the server to keep the mqtt connection alive // NOT required if you are publishing once every KEEPALIVE seconds if(! mqtt.ping()) { mqtt.disconnect(); } } // Function to connect and reconnect as necessary to the MQTT server. // Should be called in the loop function and it will take care if connecting. void MQTT_connect() { int8_t ret; // Stop if already connected. if (mqtt.connected()) { return; } Serial.print("Connecting to MQTT... "); uint8_t retries = 3; while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected Serial.println(mqtt.connectErrorString(ret)); Serial.println("Retrying MQTT connection in 3 seconds..."); mqtt.disconnect(); delay(3000); // wait 10 seconds retries--; if (retries == 0) { // basically die and wait for WDT to reset me while (1); // ESP.wdtFeed(); } } Serial.println("MQTT Connected!"); hass_config.publish(my_config_s.c_str()); // 內存不夠大 ,一直重啓 只能註冊個簡單的有開關功能 Serial.println(my_config_s); }
程序燒錄後,ESP一直觸發看門狗重啓,是MQTT庫默認容許發送數據最大長度引發的.
打開mqttq庫文件源代碼,修改。
注意修改 esp8266 mqtt庫容許發送最大的 數據長度(默認 150),修改成1024
而後仍是沒什用,報錯 可是最大隻能傳送約 130個char
這意味着經過MQTT自動配置,只能發送 開關的信息,顏色和亮度信息發送不了。需手動添加,後者使用手機MQTT調試助手發過去,長度最大限制1024。