(二 -3-1) 天貓精靈接入Home Assistant-自動發現Mqtt設備--燈系列 實戰

#本片教程介紹了具體如何實現天貓精靈控制一個燈。php

前提:git

HASS平臺json

  1. 你已經搭建一個能夠在公網IP訪問到的HASS平臺--- 我用的是租了阿里雲服務器,買了個域名,ubuntu1604系統
  2. 你已經搭建一個能夠在公網IP訪問到的MQTT服務器----沒有好的話也可使用官方測試用的服務器湊合下
  3. 在HASS論壇註冊一個帳戶和密碼---- 通常人不給註冊,你須要給管理員發送郵件證實你會基本的HASS搭建(這都不會玩個蛇)

天貓精靈ubuntu

  1. 花60元在鹹魚買個二手的 天貓精靈-方糖  (官網89元新的)
  2. 下載天貓精靈手機APP,綁定本身的 天貓精靈-方糖

ESP8266模塊服務器

  1. 隨便找個可以使用arduino ide 開發的ESP8266(這裏使用的是  esp8266 d1 pro min  14元)
  2. 一個繼電器,控制檯燈開和關

運行服務器

  1. 遠程登陸阿里雲服務器

2 爲了防止關閉遠程訪問,而致使正在運行的程序跟着關閉,開啓一個screen背後運行微信

 首先查一下正在運行的screenapp

screen -lside

 這裏發現已經有一個背後運行的screen(裏面是我以前開啓的mqtt和hass程序)函數

screen -r 1102   # 查詢指定編號的screen裏運行的程序  oop

而後來到 編號爲1102的screen下面

  • 若是想建立一個也能夠
  • screen -r 1102
  • exit    
  • 執行完上面兩句,代號1102的screen就被銷燬了
  • screen -S hass_mqtt    #開啓一個名字爲hass_mqtt   的screen的背後運行
  •  全部在hass_mqtt   下面開啓的程序不會隨着遠程訪問斷開而跟隨關閉,會獨立運行。

3運行 mqtt 服務器

上一步,咱們已經來到 編號爲1102的screen下面(或者你新建的screen下面)

進入 emqtt 文件路徑下

cd Dongdong/emqttd

  

命令行進入路徑,開啓mqtt服務

 

./bin/emqttd start

  

 

  •  ./bin/emqttd stop   關閉命令

4 運行hass

hass

  

回車開始運行

5 查看hass

打開谷歌遊覽器

輸入   域名:8123

密碼

看到本身的頁面

圖中是我默認添加的兩個測試設備

 

一 HASS配置-發現燈設備

目的:告訴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

  手動添加的須要重啓 hass服務。

自動添加模式

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自帶語音識別和播放服務,也可以使用)

 

二 天貓精靈添加燈設備--將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的開和關。

三 對接現實世界------ESP8266程序

 燒錄時板型選擇信息(根據本身使用的ESP866  wifi板類型)

兩種控制模式:

1 使用HASS網頁版或者手機APP直接控制

開關

亮度

顏色

2 天貓精靈語音控制hass,間接控制燈

天貓精靈 打開臥室的的燈

天貓精靈 關閉臥室的的燈

天貓精靈 將臥室的的燈顏色調成紅色

天貓精靈 將臥室的的燈亮度調爲60

ESP8266串口打印輸出:

 

 

 

程序功能:

  1. 鏈接指定MQTT服務器
  2. 在hass約定好的配置話題上發送ESP8266本身的配置信息,從而HASS註冊這個燈設備
  3. HASS註冊設備後,將開燈關閉,顏色,亮度等控制信息發送到對應約定好的話題上,ESP8266wifi模塊到對應話題取出命令,控制繼電器開關臺燈

將來擴展:

  1. 增長一鍵配網,可靈活修改WIFI信息
  2. 增長flash保存WIFI聯網信息,斷後電從新自動鏈接上次記錄的WIFI信息
  3. 增長觸摸開關,從而開關自己+HASS軟件+天貓語音三者都能獨立控制開關,同時彼此更新開關狀態
  4. 完善電路,可控硅代替繼電器,電路微薄化處理,作成玻璃面板,好看美觀

目前bug

 因爲ESP自己內存小,沒法發送太多信息。只能發送簡單的開關

 

警告:

 自動發現設備的時候,必定要改配置話題第三個參數ID,

  • 跟換設備名不要緊。設備名重複,ID不重複,能夠添加。
  • 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。

相關文章
相關標籤/搜索