0%

HomeAssistant自带的数据库是SQLite
可能我加入的十几个传感器采样速度过快,没几天home-assistant_v2.db就400多M了
回看历史数据的速度惨不忍睹,经过一番调研决定更换时序型的数据库InfluxDB
同时自带的图表实在太简陋,也更换了Grafana

InfluxDB

在群晖Docker的注册表里搜索并下载influxdb
高级设置里勾选启动自动重新启动
里设置/docker/influxdb映射装载路径/var/lib/influxdb
网络里勾选使用与Docker Host相同的网络
在控制台启动bash,运行influxdb
创建数据库

1
CREATE DATABASE home_assistant

修改configuration.yaml增加如下内容

1
2
influxdb:
host: 127.0.0.1

重启服务
至此,HomeAssistant数据库切换成功

Grafana

在群晖Docker的注册表里搜索并下载grafana/grafana
高级设置里勾选启动自动重新启动
里设置/docker/grafana映射装载路径/var/lib/grafana
网络里勾选使用与Docker Host相同的网络
注意如果启动失败,可以为文件夹添加权限
访问http://群晖IP:3000,用户名密码均为admin
添加数据源,类型选择InfluxDB
设置里URL填写http://127.0.0.1:8086
数据库名称home_assistant
点击Save & Test,出现Data source is working即可
在Dashboard里
选择Query的数据库,修改第一行为

1
From ppm WHERE entity_id = mb_co2

即可连接数据库,绘制出而二氧化碳的数值曲线
可添加多条Query语句
最后保存Dashboard

引用
https://registry.hub.docker.com/_/influxdb/
https://registry.hub.docker.com/r/grafana/grafana
https://bbs.hassbian.com/thread-4185-1-1.html
https://blog.yxwang.me/2017/10/smart-home-2/

硬件

看了HBO的《切尔诺贝利》之后,觉得是时候重新填坑了
把前两年买的盖格计数器翻出来Geiger-Counter-RadiationD-v1.1-CAJOE
它和NodeMCU连接如下

NodeMCU geiger(p3)
Vin(5V) 5V
GND GND
D2(IO4) VIN

加了块OLED显示器,连接如下

NodeMCU OLED
3V3 3V3
GND GND
D4(IO2) SCL
D3(IO0) SDA

软件

程序如下

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
#include <ESP8266WiFi.h>
#include <Thread.h>
#include <SoftwareSerial.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>

#define OLED_RESET 5
Adafruit_SSD1306 display(OLED_RESET);

// Update these with values suitable for your network.
const char* ssid = "xxxxx";
const char* password = "xxxxx";
const char* mqtt_server = "192.168.1.110";

const char* clientID = "espgeiger";
const char* mqtt_topic = "Home/Global";

WiFiClient espClient;
PubSubClient client(espClient);

Thread geigerThread = Thread();

//geiger
volatile unsigned long counts = 0; // Tube events
unsigned long cpm = 0; // CPM
unsigned long previousMillis; // Time measurement
const int geigerPin = 4;
unsigned long currentMillis = millis();

#define LOG_PERIOD 30000 //Logging period in milliseconds
#define MINUTE_PERIOD 60000

void ICACHE_RAM_ATTR ISR_impulse ();
void ISR_impulse() { // Captures count of events from Geiger counter board
counts++;
}

void geigerCallback(){
currentMillis = millis();
if (currentMillis - previousMillis > LOG_PERIOD) {

previousMillis = currentMillis;
cpm = counts * MINUTE_PERIOD / LOG_PERIOD;
counts = 0;
}
}

void setup() {
Wire.begin(0, 2);
Serial.begin(115200);
pinMode(geigerPin, INPUT); // Set pin for capturing Tube events
interrupts(); // Enable interrupts
attachInterrupt(digitalPinToInterrupt(geigerPin), ISR_impulse, FALLING); // Define interrupt on falling edge
unsigned long clock1 = millis();

geigerThread.onRun(geigerCallback);
geigerThread.setInterval(1000);

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("booting");
display.display();

Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

client.setServer(mqtt_server, 1883);
}

void reconnect() {
while (!client.connected()) {
Serial.print("AtDHTting MQTT connection...");
if (client.connect(clientID)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

void loop(){

if(geigerThread.shouldRun())
geigerThread.run();
delay(30000);

if (!client.connected()) {
reconnect();
}
client.loop();
if (cpm==0) {
Serial.println("try to read sensor again!");
return;
}

StaticJsonBuffer<300> JSONbuffer;
JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["cpm"] = cpm;
float usvh = cpm/151.0;
JSONencoder["usvh"] = usvh;

char JSONmessageBuffer[300];
JSONencoder.prettyPrintTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
Serial.println(JSONmessageBuffer);

boolean isOK = client.publish(mqtt_topic, JSONmessageBuffer, true);
Serial.println(isOK);
display.clearDisplay();

char str[100];
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
snprintf(str,16, "cpm=%d", cpm);
display.println(str);
snprintf(str,16, "usvh=%.3f", usvh);
display.println(str);
display.display();
}

修改homeassistantconfiguration.yaml

编辑/docker/homeassistantconfiguration.yaml在末尾加入

1
2
3
4
5
6
7
8
9
10
11
sensor:
- platform: mqtt
state_topic: "Home/Global"
name: 'cpm'
unit_of_measurement: 'cpm'
value_template: '{{ value_json.cpm }}'
- platform: mqtt
state_topic: "Home/Global"
name: 'usvh'
unit_of_measurement: 'usv/h'
value_template: '{{ value_json.usvh }}'

重启服务即可

引用

https://github.com/SensorsIot/Geiger-Counter-RadiationD-v1.1-CAJOE-/
https://www.youtube.com/watch?v=K28Az3-gV7E&feature=youtu.be
https://zh.wikipedia.org/wiki/%E8%A5%BF%E5%BC%97
https://github.com/SensorsIot/Geiger-Counter-RadiationD-v1.1-CAJOE-/blob/master/Geiger_Counter.ino

准备工作

在群晖的Virtual Machine Manager里创建新的虚拟机
在Debian官网下载镜像(https://www.debian.org/distrib/)
建议内存4GB/硬盘40GB

服务器安装

最好先安装lnmp

之前的工作看这里

  • LNMP安装笔记 接着做环境准备
    1
    2
    3
    4
    $ sudo apt-get update
    $ sudo apt-get install git clang cmake make gcc g++ libmariadbclient-dev libssl-dev libbz2-dev libreadline-dev libncurses-dev libboost-all-dev p7zip-full
    $ sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
    $ sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang 100
    下载3.3.5源码
    1
    2
    $ cd ~/
    $ git clone -b 3.3.5 git://github.com/TrinityCore/TrinityCore.git
    配置
    1
    $ sudo cmake ../ -DCMAKE_INSTALL_PREFIX=/home/wow/server
  • DTOOLS=0 是不编译地图提取工具的选项
    编译
    1
    2
    $ sudo make
    $ sudo make install
    后续可以拉取git代码更新
    1
    2
    $ cd ~/TrinityCore/
    $ git pull origin 3.3.5

    服务器设置

    上传客户端到~/wow_client
    提取DBC和Maps
    1
    2
    3
    4
    $ cd ~/wow_client/
    $ /home/wow/server/bin/mapextractor
    $ mkdir /home/wow/server/data
    $ cp -r dbc maps /home/wow/server/data
    提取vmaps(可选)
    1
    2
    3
    4
    5
    $ cd ~/wow_client/
    $ /home/wow/server/bin/vmap4extractor
    $ mkdir vmaps
    $ /home/wow/server/bin/vmap4assembler Buildings vmaps
    $ cp -r vmaps /home/wow/server/data
    提取mmaps(可选,我用了6个多小时)
    1
    2
    3
    4
    $ cd ~/wow_client/
    $ mkdir mmaps
    $ /home/wow/server/bin/mmaps_generator
    $ cp -r mmaps /home/wow/server/data
    拷贝配置文件
    1
    2
    3
    $ cd ~/server/etc/
    $ cp worldserver.conf.dist worldserver.conf
    $ cp authserver.conf.dist authserver.conf
    编辑worldserver.conf
    1
    DataDir = "../data"
    还有数据库配置(帐号wow,密码trinity)
    1
    2
    3
    LoginDatabaseInfo = "127.0.0.1;3306;wow;trinity;auth" #worldserver.conf
    WorldDatabaseInfo = "127.0.0.1;3306;wow;trinity;world" #worldserver.conf
    CharacterDatabaseInfo = "127.0.0.1;3306;wow;trinity;characters" #worldserver.conf
    编辑authserver.conf
    1
    LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"

    安装数据库

    1
    2
    3
    4
    5
    6
    CREATE DATABASE `world` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    CREATE DATABASE `characters` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    CREATE DATABASE `auth` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    GRANT ALL PRIVILEGES ON `world` . * TO 'wow'@'localhost' WITH GRANT OPTION;
    GRANT ALL PRIVILEGES ON `characters` . * TO 'wow'@'localhost' WITH GRANT OPTION;
    GRANT ALL PRIVILEGES ON `auth` . * TO 'wow'@'localhost' WITH GRANT OPTION;
    这三个数据库的说明如下

    auth - holds account data - usernames, passwords, GM access, realm information, etc.
    characters - holds character data - created characters, inventory, bank items, auction house, tickets, etc.
    world - holds game-experience content such as NPCs, quests, objects, etc
    hotfixes (master only) - holds fixes not already added to the core or other official databases.

下载最新的数据库文件(https://github.com/TrinityCore/TrinityCore/releases)
把它放在server/bin目录下

1
2
3
4
5
$ cd ~/server/bin/
$ wget https://github.com/TrinityCore/TrinityCore/releases/download/TDB335.20021/TDB_full_world_335.20021_2020_02_15.7z
$ 7z x TDB_full_world_335.20021_2020_02_15.7z
$ rm TDB_full_world_335.20021_2020_02_15.7z
$ ./worldserver

执行结束,数据库导入完成

配置修改

修改本机客户端文件\Data\zhCN\realmlist.wtf,改为服务器地址

1
set realmlist xxx.xxx.xxx.xxx

修改数据库authrealmlist

  • name是服务器名称
  • address是服务器地址
  • gamebuild是客户端版本号(客户端启动时左下角可见)

测试

启动服务器

1
2
3
$ cd ~/server/bin/
$ ./authserver &
$ ./worldserver

创建帐号并设置为gm(3级权限)

1
2
account create user password
account set gmlevel userid 3 1

如果要和朋友一起玩,就映射一个域名上去
frp映射好本地服务器的37248085端口
frp服务器开对应的防火墙端口即可

gm指令请惠存
(https://trinitycore.atlassian.net/wiki/spaces/tc/pages/2130065/GM+Commands)

优秀插件
(https://rochet2.github.io/downloads/)

引用
https://trinitycore.atlassian.net/wiki/spaces/tc/pages/2130077/Installation+Guide

安装Nginx

1
2
# apt update 
# apt install nginx

控制服务状态

1
2
3
4
5
# systemctl start nginx
# systemctl restart nginx
# systemctl stop nginx
# systemctl reload nginx
# systemctl status nginx

安装MariaDB

1
# apt install mariadb-server

安全配置全部Yes

1
# mysql_secure_installation

安装PHP-FPM (Fast Process Manager)

1
# apt install php-fpm php-mysqli

查看启动状态

1
# systemctl status php7.3-fpm

修改PHP-FPM配置文件/etc/php/7.3/fpm/php.ini
取消如下内容的注释,并改为0

1
cgi.fix_pathinfo=0

修改Nginx配置文件/etc/nginx/sites-available/default
取消如下内容的注释

1
2
3
4
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}

同时添加主页index.php
重启服务

1
2
# systemctl restart php7.3-fpm
# systemctl restart nginx

/var/www/html/下编写测试页

1
<?php phpinfo(); ?>

测试正常后继续
下载phpMyAdmin,并解压到/var/www/html/目录下
进入mysql命令行创建phpmyadmin用户

1
2
3
CREATE USER 'phpmyadmin'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

使用phpmyadmin登录成功即可

引用
https://www.tecmint.com/install-lemp-on-debian-10-server/
https://www.centos.bz/2017/07/mysql5-7-phpmyadmin-access-denied-for-user-rootlocalhost/

升级了新版的KiCad5,感觉好用很多
我布线多用FreeRouter因为人工智能终究会取代我们
新版的FreeRouting打包在LayoutEditor这款软件里
下载程序压缩包后,提取其中的freeRouting.jar

我是在Ubuntu上运行Kicad的
所以还需要安装OpenJava的运行环境

1
$ sudo apt install default-jre

只要在pcbnew里面导出.DSN文件
File → Export → Specctra DSN
导入到FreeRouting中,布好线之后再导出.SES文件
再次导入到pcbnew程序里即可
File → Import → Spectra Session

介绍

这是一款攀藤科技的二氧化碳传感器 链接 图片

DS-CO2-20 是一款基于非分光红外吸收原理的数字式二氧化碳浓度传感器,可连续采集并计算单位体积内空气中的二氧化碳浓度,并以通用数字接口形式输出。
本传感器可嵌入各种与二氧化碳浓度相关的仪器仪表或环境改善设备,为其提供及时准确的浓度数据。

硬件部分

它的针脚是2mm间距,接口朝下俯视角从左到右分别是pin1到pin7,需要注意的是5V供电

管脚 标号 说明
pin1 VCC 5V
pin2 GND
pin3 RXD TTL_3.3V
pin4 TXD TTL_3.3V
pin5 RESET TTL_3.3V
pin6 NC
pin7 NC

把NodeMCU和它连接使用,接法如下

NodeMCU DS-CO2-20
Vin(5V) VCC
GND GND
D5(IO14) RXD
D6(IO12) TXD

软件部分

通讯方式是串口通讯,默认波特率:9600bps,校验位:无,停止位:1 位
通讯协议是应答式,主机发送0x42, 0x4d, 0xe3, 0x00, 0x00, 0x01, 0x72
其中前两位是特征字节,第三位是指令字节,最后两位是校验字节

从机应答格式协议长度为12字节,从0x42, 0x4d开始二氧化碳数值的高低八位分别在第5、6位
最后两位是校验字节

程序如下

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
#include <ESP8266WiFi.h>
#include <Thread.h>
#include <SPI.h>
#include <Wire.h>
#include <SoftwareSerial.h>

Thread CO2Thread = Thread();
SoftwareSerial CO2sensor(14, 12, false, 128);

//CO2
static unsigned int CO2ppm = 0;
const unsigned char CO2AskData[7] = {0x42, 0x4d, 0xe3, 0x00, 0x00, 0x01, 0x72};

struct _panteng {
unsigned char len[2];
unsigned char co2_cf[2];
unsigned char d[4];
unsigned char crc_cf[2];
} panteng;
char crc1,crc2;

void CO2Callback(){
unsigned char c;
static int state = 0;
static int count = 0;
CO2sensor.write(CO2AskData, 7);

while (CO2sensor.available()) {
c = CO2sensor.read();
//Serial.print(c,HEX);
switch (state) {
case 0:
if (0x42 == c)
state = 1;
break;
case 1:
if (0x4d == c) {
state = 2;
count = 0;
}
break;
case 2:

((unsigned char *) &panteng)[count++] = c;
if (count > 12) {
state = 0;

crc1 = panteng.crc_cf[0] * 256 + panteng.crc_cf[1];
crc2 = 0x42 + 0x4d + panteng.len[0]+ panteng.len[1]+panteng.co2_cf[0]+panteng.co2_cf[1]+panteng.d[0]+panteng.d[1]+panteng.d[2]+panteng.d[3];

//Serial.print("crc1 = ");Serial.println(crc1,HEX);
//Serial.print("crc2 = ");Serial.println(crc2,HEX);

if (crc1 == crc2){
CO2ppm = panteng.co2_cf[0] * 256 + panteng.co2_cf[1];
Serial.print("co2 = ");Serial.print(CO2ppm);Serial.println(" ppm");
}
}
break;
default:
break;
}
}
delay(1000);
}

void setup(){
CO2Thread.onRun(CO2Callback);
CO2Thread.setInterval(1000);

Serial.begin(115200);
CO2sensor.begin(9600);
}

void loop(){
if(CO2Thread.shouldRun())
CO2Thread.run();
}

之前的工作看这里

修改homeassistantconfiguration.yaml

编辑/docker/homeassistantconfiguration.yaml在末尾加入

1
2
3
4
5
6
7
8
9
10
11
12
sensor:
- platform: mqtt
state_topic: "esp/sensor1"
name: 'Temperature'
unit_of_measurement: '°C'
value_template: '{{ value_json.Temperature }}'
- platform: mqtt
state_topic: "esp/sensor1"
name: 'Humidity'
unit_of_measurement: '%'
value_template: '{{ value_json.Humidity }}'
device_class: humidity

esp8266程序

将DHT22连接到NodeMCU的D2口也就是IO4
烧写程序如下

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
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#include <ArduinoJson.h>

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

// Update these with values suitable for your network.
const char* ssid = "xxx";
const char* password = "xxx";
const char* mqtt_server = "xxx.xxx.xxx.xxx";
const char* mqtt_topic = "esp/sensor1";


WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
Serial.begin(9600);
setup_wifi();
client.setServer(mqtt_server, 1883);
dht.begin();
}

void setup_wifi() {

delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
//if (client.connect("arduinoClient", mqtt_user, mqtt_password)) {
Serial.println("connected");
// Once connected, publish an announcement...
client.subscribe("esp/#");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();

// Wait a few seconds between measurements.
delay(2000);
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
//Serial.print("Humidity: ");
//Serial.print(h);
//Serial.print(" %\t");
//Serial.print("Temperature: ");
//Serial.print(t);
//Serial.print(" *C ");

StaticJsonBuffer<300> JSONbuffer; //Declaring static JSON buffer
JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["Humidity"] = h;
JSONencoder["Temperature"] = t;
//JsonObject& data = JSONencoder.createNestedObject("data");
//data.set("Humidity", h);
//data.set("Temperature", t);

char JSONmessageBuffer[300];
JSONencoder.prettyPrintTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
Serial.println(JSONmessageBuffer);

boolean isOK = client.publish(mqtt_topic, JSONmessageBuffer, true);
Serial.println(isOK);
}

测试

开发者工具/MQTT
订阅主题Topicesp/sensor1
注意监听

在主页面中右上角选择配置UI
在右下角选择添加卡片
实体里选择sensor.temperaturesensor.humidity
完成添加到主页

在iPhone的家庭APP里可以看到

注意

湿度传感器需要在修改homeassistantconfiguration.yaml的时候加入device_class: humidity
Device Class支持的传感器类型有

None: Generic sensor. This is the default and doesn’t need to be set.
battery: Percentage of battery that is left.
humidity: Percentage of humidity in the air.
illuminance: The current light level in lx or lm.
signal_strength: Signal strength in dB or dBm.
temperature: Temperature in °C or °F.
power: Power in W or kW.
pressure: Pressure in hPa or mbar.
timestamp: Datetime object or timestamp string.

安装bash-completion

1
apt-get install bash-completion

编辑~/.bashrc 文件,添加如下内容:

1
2
3
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi

重新登录

安装HomeAssistant

在群晖Docker的注册表里搜索并下载homeassistant/home-assistant
高级设置里勾选启动自动重新启动
里设置/docker/homeassistant映射装载路径/config
网络里勾选使用与Docker Host相同的网络
环境里设置TZ数值为Asia/Shanghai
浏览器访问http://群晖的ip:8123即可完成剩下的设置

添加HomeKit支持
编辑/docker/homeassistantconfiguration.yaml在末尾加入

1
homekit: 

末尾有空格

返回HomeAssistant页面,会收到HomeKit的配置代码
如果忘记了此代码,可以删除.homekit.state文件

安装MQTT服务器

在群晖Docker的注册表里搜索并下载ncarlier/mqtt
高级设置里勾选启动自动重新启动
网络里勾选使用与Docker Host相同的网络
完成设置
编辑/docker/homeassistantconfiguration.yaml在末尾加入

1
2
3
4
mqtt:
broker: 192.168.1.110
discovery: true
discovery_prefix: homeassistant

烧写esp8266程序

基础设置参考这里
(https://randomnerdtutorials.com/how-to-install-esp8266-board-arduino-ide/)
此外安装库PubSubClient
烧写程序如下

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
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
const char* ssid = "xxx";
const char* password = "xxx";
const char* mqtt_server = "xxx.xxx.xxx.xxx";

WiFiClient espClient;
PubSubClient client(espClient);
String switch1;
String strTopic;
String strPayload;

void setup_wifi() {

delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
strTopic = String((char*)topic);
if(strTopic == "esp/switch1")
{
switch1 = String((char*)payload);
if(switch1 == "ON")
{
Serial.println("ON");
digitalWrite(LED_BUILTIN, LOW);
}
else
{
Serial.println("OFF");
digitalWrite(LED_BUILTIN, HIGH);
}
}
}


void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.subscribe("esp/#");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void setup()
{
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);

pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
}

void loop()
{
if (!client.connected()) {
reconnect();
}
client.loop();
}

测试

编辑/docker/homeassistantconfiguration.yaml在末尾加入

1
2
3
4
5
6
7
switch:
- platform: mqtt
name: "light"
state_topic: "esp/switch1"
command_topic: "esp/switch1"
payload_on: "ON"
payload_off: "OFF"

开发者工具/MQTT
填写主题Topicesp/switch1
分别发送有效负载为ONOFF进行测试
注意在客户端监听

在主页面中右上角选择配置UI
在右下角选择添加卡片
实体里选择switch.light
完成添加到主页

最后在iPhone的家庭APP里添加配件,简单配置后即可使用Siri控制开关

引用

(https://www.instructables.com/id/Using-an-Esp8266-Arduino-to-Control-a-Relay-Using-/)