前篇文章实现了下雨自动报警,今天尝试将ESP8266接入HA,实现苹果HomeKit接入。ESP8266通过MQTT协议将传感器信息发送到指定话题上,HA通过订阅话题获取信息,并通过其插件HomeBridge实现与HomeKit的连接。
MQTT Sever可以使用HA自带的插件实现,或者用第三方的服务实现。这里我选择的是国人制作的EMQX,界面非常的友好,功能丰富。当然,实现本文的功能是绰绰有余的。
部署 Home Assistant&EMQX
这里选择docker-compose来部署服务
version: '3'
services:
HomeAssistant:
image: homeassistant/home-assistant
restart: always
ports:
- 8123:8123
volumes:
- './HomeAssistant:/config'
network_mode: "host"
emq:
image: emqx/emqx
container_name: emqx
ports:
- "18083:18083"
- "1883:1883"
- "8084:8084"
- "8883:8883"
- "8083:8083"
restart: always
network_mode: "host"
这里的network_mode必须选择host,否则会导致HomeKit无法连接。EMQX的配置文件也建议挂载出来,由于实现的功能比较简单,这里就不操作了。
配置Home Assistant
添加插件
点击集成,添加HomeKit插件,完成后在通知中会出现二维码和PIN码,打开HomeKit可联接。接着添加MQTT插件,输入IP地址直接提交即可。
添加传感器
打开上面你映射的HA文件夹路径,修改configuration.yaml。
注意:文件需要使用UTF-8保存,否则会报错
# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:
# Text to speech
tts:
- platform: google_translate
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
sensor: !include sensors.yaml
mobile_app:
添加了sensor和mobile_app
Mobile_app是因为接入三星ST非常的麻烦,干脆用他官方的APP更方便。
然后再在目录下新建sensors.yaml
- platform: mqtt
state_topic: "ha/tmp"
name: "温度"
unit_of_measurement: '°C'
icon: mdi:thermometer
value_template: '{{ value }}'
device_class: temperature
expire_after: 5
- platform: mqtt
state_topic: "ha/hum"
name: "湿度"
unit_of_measurement: "%"
icon: mdi:thermometer
value_template: '{{ value }}'
device_class: humidity
expire_after: 5
变量说明:
- name (可选): 名称,英文。默认
MQTT Binary Sensor
. - state_topic (必填): 获取设备值的MQTT topic
- qos (可选): 最大 QoS 值,默认
0
- value_template (可选): 定制数据生成的模板
- unit_of_measurement (可选): 单位
- expire_after (可选): 数据有效时间,以秒为单位,默认 0
- force_update (可选): 强制更新数据,默认 false
- icon(可选):图标
- device_class(可选):设备类型,不添加HomeKit可能无法正常识别
记住上面设置的topic,等会往上面发消息就完事了。
重启HA以保存修改。
添加卡片-传感器-实体里应该能看到你添加的传感器,否则请确认配置文件是否正确。
ESP8266代码编写
在Arduino库管理器中安装Pubsubclient以支持MQTT。DHT11已安装过依赖,详情请看上一篇。
完整代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHTesp.h"
// Update these with values suitable for your network.
#define LED 2
const char* ssid = "WIFI名";
const char* password = "密码";
const char* mqtt_server = "mqtt服务器地址";
char *buffer=new char[30];
char *buffern=new char[30];
DHTesp dht;
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;
void setup_wifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(LED, 1);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is active low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("ha/tmp", "0");
client.publish("ha/hum", "0");
// ... and resubscribe
client.subscribe("homeassistant/in");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void push()
{
if(client.connected())
{
delay(dht.getMinimumSamplingPeriod());
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
sprintf( buffer , "%.1f", temperature );//将float转换为char
sprintf( buffern , "%.1f", humidity);
client.publish("ha/tmp", buffer);//发布的话题在这里修改,内容用逗号分割
client.publish("ha/hum", buffern);
Serial.println(buffer);
Serial.println(buffern);
delay(2000);
}
else
{
reconnect();
}
}
void setup() {
pinMode(LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
digitalWrite(LED, 0);
dht.setup(14, DHTesp::DHT11); // Connect DHT sensor to GPIO 17
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
push();
}
输入ESP8266表现为,开机LED常亮,连接上WIFI LED熄灭,接收到订阅话题的消息闪烁。此时,HA面板里应该有你的传感器数据了。
在集成界面点击HomeKit的选项,加入sensor配置
提交保存,你的苹果设备上应该就出现传感器了!
发表评论