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

 找回密码
 立即注册
查看: 8909|回复: 10

[基础教程] HA通过MQTT连接esp8266控制电器

[复制链接]

2

主题

65

帖子

383

积分

论坛分享达人

积分
383
金钱
318
HASS币
0
发表于 2018-3-23 22:02:37 | 显示全部楼层 |阅读模式
本帖最后由 jesson 于 2018-3-23 22:05 编辑

Esp8266与homeassistant
很早以前就有想法,可以遥控家里的各种电器,健康家里的环境。然而条件技术有限,没有再进行下去。偶然的机会看到了esp8266,这是个好东西,便宜又强大好还可以用arduino开发,真是我等业余爱好者的福音。然后又有home assistant这个集成环境,可以连接各种设备,作为人机界面接口并且这些又都是开源的。
       要让esp8266与home assistant 合体需要一个中间桥梁,也是一个开源项目MQTT协议,实现这个协议的软件有很多,我选了mosquitto这个款软件。
       我的思路是这样:
框架.png
       Esp8266负责物理层控制硬件,例如灯或者实体开关。
       Homeassistant负责显示状态或者远程控制硬件实体,如显示环境温度,控制灯。
       Mosquito负责连接esp8266和homeassistant,是一个中间桥梁。
后面用hass 代替homeassistan。

后面我主要以esp8266开发为重点,假如hass和mqtt都配置好了,能正常运行了。
Esp8266推荐买nodemcu v3这款,尤其是开发初期直接一根usb线就可以下载程序了,免了很多没必要的硬件接线。
首先配置arduino使其能够兼容esp8266配置好了安装用到的两个库,一个是<PubSubClient.h>负责MQTT通讯,另一个<DHT.H>使用dht11温湿度传感器(选择安装)
Pubsubclient.h 这个库有几个重要的函数先介绍一下
const  char* mqtt_server = "192.168.1.4";  连接一个mqtt服务器
PubSubClientclient(esp8266);  定义一个类
这是几个初始设置放到程序开头定义变量位置
client.connected()   判断是否连接到服务器
client.connect("ESP8266Client")  一个叫ESP8266Client的客户端连接mqtt服务器,没用密码。
client.publish("esp8266", "mqttconnected!");   往服务器推送一个主题esp8266及内容
client.subscribe("light"); 订阅一个主题
这几个可以上面列出的顺序放到一起先判断是否连接到mqtt服务器,否就连接服务器成功发送一个连接成功的主题,然后订阅主题接受信息。
callback(char*intopic, byte* payload, unsigned int length) 接受订阅的主题内容的回调函数
这个函数有client.loop()调用,可以放到任意位置,这里可以写控制灯的程序
client.setServer(mqtt_server,1883);   设置mqtt 服务器
client.setCallback(callback);          设置回调函数名为callback
上面这两个放到setup()中执行一次就可以
client.loop();  一直循环调用回调函数callback,放到loop()中
这就是这个库用到的几个函数更具体全面准确的介绍看官方文档。我也是折腾出来的
第二个是<ESP8266WiFi.h> 这个是esp8266的主要库,这是必须要包含的头文件
再说一说modemcu这个板子,要用gpio的序号,不要看D0D1这类的看图
例如想用D1这个引脚在程序中要用5,digitalRead(5),但是读取模拟量是用A0.
现在用一个例子来说明一下。
现在有一个灯,墙上有一个开关,开关控制灯亮灯灭。现在我们要改造一下,保留原来开关的功能,添加上hass控制并能显示灯的亮灭状态。
1 连接硬件
  Esp8266 D1控制一个继电器模块,继电器一组常开触点控制灯的火线,原来的开关也要改掉接到esp8266D2上示意图如下
连线.png
2 设置hass 添加一个light
灯是否在线 lighta     onlineoffline
灯状态     lights     ON OFF
灯开关     light      ON OFF
这都是默认值可以修改。
3 编写代码,如下
#include<ESP8266WiFi.h>
#include<PubSubClient.h>
#defineLAMP5 5
#defineSW4 4
const  char* mqtt_server = "192.168.1.1";//your mqtt server ip,you can use a domain
const  char* ssid = "hass";              //your wifi  ssid
const  char* password = "";          // your wifi password
long  now;
booleanlight_state, old_key;
WiFiClientesp8266;
PubSubClientclient(esp8266);
voidreconnectwifi() {
  delay(10);
  Serial.print("\nConnecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected\nIPaddress: ");
  Serial.println(WiFi.localIP());
}
voidreconnectmqtt() {
  while (!client.connected()) {
    Serial.print("Attempting MQTTconnection...");
    if(client.connect("ESP8266Client")) {
      Serial.println("\nMQTTconnected");
      // Once connected, publish anannouncement...
      client.publish("esp8266","MQTT connected!");
      client.publish("lighta","online"); //availability
      client.subscribe("light");
    }
    else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 2seconds");
      // Wait 5 seconds before retrying
      delay(2000);
    }
  }
}
voidcallback(char* intopic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(intopic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload); //debuginfo
  }
  if (!strcmp(intopic, "light")) {
    if ((char)payload[0] == 'O' &&(char)payload[1] == 'N')  light_state =1;
    if ((char)payload[0] == 'O' &&(char)payload[1] == 'F')  light_state =0;
  }
  /*if (!strcmp(intopic, "curtain")){   //another topic
    if ((char)payload[0] == 'O' &&(char)payload[1] == 'N') client.publish("curtains", "ON");
    if ((char)payload[0] == 'O' &&(char)payload[1] == 'F') client.publish("curtains", "OFF");
  }*/
}
voidcontral_light() {
  if (digitalRead(SW4) != old_key) {
    delay(20);
    if (digitalRead(SW4) != old_key) {
      old_key = digitalRead(SW4);
      light_state = !light_state;
      }
  }
}
voidsetup() {
  old_key = digitalRead(SW4);
  Serial.begin(115200);
  delay(20);
  reconnectwifi();
  pinMode(SW4, INPUT_PULLUP); //light button
  pinMode(LAMP5, OUTPUT); //LAMP
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}
voidloop() {
  if (WiFi.status() != WL_CONNECTED)reconnectwifi();
  if (!client.connected()) reconnectmqtt();
  client.loop();//callback();
  if (millis() - now > 5000) {
    client.publish("lighta","online");
    now = millis();
  }
  contral_light();
  if (light_state) {
      client.publish("lights","ON");
      digitalWrite(LAMP5,HIGH);
    }
    else {
      client.publish("lights","OFF");
      digitalWrite(LAMP5,LOW);
    }
}
然后下载到esp8266,接好电路就可以了。
快去体验一把吧!
arduino 文件下载 example1.zip (1.17 KB, 下载次数: 71)



回复

使用道具 举报

74

主题

1958

帖子

7959

积分

元老级技术达人

积分
7959
金钱
5951
HASS币
430

活跃会员教程狂人

发表于 2018-3-23 22:15:52 | 显示全部楼层
感觉论坛现在需要一个8266控制DY WIFI窗帘控制器的手把手教程,虽然我没有。
谢谢分享。
所有过往,皆为序章。
回复

使用道具 举报

2

主题

65

帖子

383

积分

论坛分享达人

积分
383
金钱
318
HASS币
0
 楼主| 发表于 2018-3-23 23:28:19 | 显示全部楼层
咸味土豆 发表于 2018-3-23 22:15
感觉论坛现在需要一个8266控制DY WIFI窗帘控制器的手把手教程,虽然我没有。
谢谢分享。 ...

我过年的时候打算自己改造一下家里的窗帘来。在单位找了一个直流减速电机,发现改装太麻烦,就拖下来了,然后就一直出差中。
回复

使用道具 举报

6

主题

741

帖子

5624

积分

论坛元老

Rank: 8Rank: 8

积分
5624
金钱
4878
HASS币
20
发表于 2018-3-23 23:56:15 | 显示全部楼层
只是控制灯的开关或者接入其他一般的传感器,可以直接刷入ESPEasy,或者ESPurna。
回复

使用道具 举报

2

主题

171

帖子

2328

积分

金牌会员

Rank: 6Rank: 6

积分
2328
金钱
2157
HASS币
0
发表于 2018-10-9 15:02:08 | 显示全部楼层
动手能力加软件开发
回复

使用道具 举报

4

主题

150

帖子

592

积分

高级会员

Rank: 4

积分
592
金钱
442
HASS币
0
发表于 2022-3-30 21:45:00 | 显示全部楼层
好东西,终于找到合适的教程了
回复

使用道具 举报

4

主题

150

帖子

592

积分

高级会员

Rank: 4

积分
592
金钱
442
HASS币
0
发表于 2022-3-30 22:16:59 | 显示全部楼层
大佬你的程序我下载了以后编译好像很多问题啊,不知道是不是因为版本的原因 很多函数格式都不对,能麻烦你用新版的编译一下再发一次吗?我很想学习一下
回复

使用道具 举报

0

主题

566

帖子

2214

积分

金牌会员

Rank: 6Rank: 6

积分
2214
金钱
1648
HASS币
0
发表于 2022-7-17 22:54:26 | 显示全部楼层
本帖最后由 Ari 于 2022-7-18 00:33 编辑

大佬,点击编译提示
example1:10:12: error: 'WiFiClient esp8266' redeclared as different kind of entity

   10 | WiFiClient esp8266;

      |            ^~~~~~~

In file included from C:\Users\Ari\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:42,

                 from sketch\example1.ino.cpp:1:

C:\Users\Ari\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/core_esp8266_version.h:121:11: note: previous declaration 'namespace esp8266 { }'

  121 | namespace esp8266 {

      |           ^~~~~~~

example1:11:28: error: expected primary-expression before ')' token

   11 | PubSubClient client(esp8266);

      |                            ^

exit status 1

'WiFiClient esp8266' redeclared as different kind of entity

回复

使用道具 举报

1

主题

11

帖子

48

积分

新手上路

Rank: 1

积分
48
金钱
37
HASS币
0
发表于 2023-9-5 23:19:54 | 显示全部楼层
是不是需要一段HA自动识别的代码,mqtt上面有了,调试发送on和off能做出反应,就是还不会怎么连接上HA
回复

使用道具 举报

21

主题

304

帖子

1138

积分

金牌会员

Rank: 6Rank: 6

积分
1138
金钱
834
HASS币
10
发表于 2023-9-5 23:28:16 来自手机 | 显示全部楼层
看不懂这个开关是如何控制灯的
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-5-12 04:26 , Processed in 0.060551 second(s), 35 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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