『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 4809|回复: 4

[进阶教程] (二) 天猫精灵+Home Assistant+MQTT+ esp8266+彩灯控制 程序

[复制链接]

13

主题

62

帖子

209

积分

中级会员

Rank: 3Rank: 3

积分
209
金钱
147
HASS币
0
发表于 2018-8-31 12:24:51 | 显示全部楼层 |阅读模式
本帖最后由 1051196347 于 2018-8-31 12:28 编辑

三 对接现实世界------ESP8266程序 烧录时板型选择信息(根据自己使用的ESP866  wifi板类型)

                               
登录/注册后可看大图

两种控制模式:
1 使用HASS网页版或者手机APP直接控制
开关
亮度
颜色
2 天猫精灵语音控制hass,间接控制灯
天猫精灵 打开卧室的的灯
天猫精灵 关闭卧室的的灯
天猫精灵 将卧室的的灯颜色调成红色
天猫精灵 将卧室的的灯亮度调为60
ESP8266串口打印输出:

                               
登录/注册后可看大图



程序功能:
  • 连接指定MQTT服务器
  • 在hass约定好的配置话题上发送ESP8266自己的配置信息,从而HASS注册这个灯设备
  • HASS注册设备后,将开灯关闭,颜色,亮度等控制信息发送到对应约定好的话题上,ESP8266wifi模块到对应话题取出命令,控制继电器开关台灯
未来扩展:
  • 增加一键配网,可灵活修改WIFI信息
  • 增加flash保存WIFI联网信息,断后电重新自动连接上次记录的WIFI信息
  • 增加触摸开关,从而开关本身+HASS软件+天猫语音三者都能独立控制开关,同时彼此更新开关状态
  • 完善电路,可控硅代替继电器,电路微薄化处理,做成玻璃面板,好看美观
目前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烧录代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/***************************************************

****************************************************/
#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。


回复

使用道具 举报

0

主题

13

帖子

70

积分

注册会员

Rank: 2

积分
70
金钱
57
HASS币
0
发表于 2018-8-31 14:58:01 | 显示全部楼层
坐沙发,慢慢研究。还是先谢谢分享
回复

使用道具 举报

0

主题

257

帖子

913

积分

高级会员

Rank: 4

积分
913
金钱
656
HASS币
0
发表于 2018-10-5 21:23:11 来自手机 | 显示全部楼层
慢慢研究
回复

使用道具 举报

1

主题

25

帖子

185

积分

注册会员

Rank: 2

积分
185
金钱
160
HASS币
0
发表于 2018-10-21 22:12:36 | 显示全部楼层
先码
回复

使用道具 举报

1

主题

25

帖子

185

积分

注册会员

Rank: 2

积分
185
金钱
160
HASS币
0
发表于 2018-10-22 08:58:24 | 显示全部楼层
收到mqtt指令,esp8266就重启是咋回事?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-5-19 08:44 , Processed in 0.052946 second(s), 26 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表