#本片教程介绍了具体如何实现天猫精灵控制一个灯。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。