基于Home Assistant 和ESP8266 arduino的实时室温检测
前言
最近是真的热!
写完论文宅在家,想要做点什么缓解一些焦虑的心情。从之前大学寄回家至今没有拆开过的元件箱中找到了一个ESP8266 的arduino D1的板子以及一个s17021温湿度传感器,遂萌发做一个实时记录自己卧室温湿度的小作品,来记录家里是究竟多热~。
实验准备
ESP8266 arduino D1
s17021温湿度传感器
ubuntu一台(树莓派低功耗更好)
步骤
硬件连接
D15----SCL
D14---SDA
软件安装
ubuntu1604 + Homeassistant + mqtt
Homeassistant 安装
https://www.hachina.io/docs/355.html
注:安装Homeassistant的时候提示缺少什么就去sudo apt install 什么~
mqtt安装
https://www.jianshu.com/p/a13e888c93fb
代码与脚本
arduino 代码
/**
* 订阅mqtt/cmd可以从hass获取指令控制板子上的led灯
* 向mqtt/state发布on、off上传led等的状态
* 向mqtt/temp发布环境温度
* 向mqtt/humi发布环境湿度
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#define ADDRESS_SI7021 0x40
#define MEASURE_RH_HOLD 0xE5
#define READ_T_FROM_PRE_RH_MEASUREMENT 0xE0
byte buffer[] = {0, 0, 0};
byte crcHumi;
word outHumi = 0;
word outTemp = 0;
float valueHumi = 0;
float valueTemp = 0;
const char* ssid = "SSID";//你要让板子链接的WiFi的名字
const char* password = "..XXXXX..";//该WiFi的密码
const char* mqtt_server = "192.168.31.175";//mqtt服务器地址
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
Wire.begin();
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());
}//链接WiFi
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();
// 如果收到1作为第一个字符,则打开LED
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // 这里他说接受的‘1’就打开灯 但是我在用的时候 接收到0才会打开 这一行的‘LOW’和下面的‘HIGH’应该换下位置,下面也说了 ESP-01是这样的
client.publish("mqtt/state", "1");//链接成功后 会发布这个主题和语句
// 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
client.publish("mqtt/state", "0");//链接成功后 会发布这个主题和语句
}
}
// 重新连接mqtt server
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);//产生一个随机数字 以免多块板子重名
//尝试连接
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// 连接后,发布公告......
client.publish("mqtt/temp", "100");//链接成功后 会发布这个主题和语句
// ......并订阅
client.subscribe("mqtt/cmd");//这个是你让板子订阅的主题(接受该主题的消息)
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// 如果链接失败 等待五分钟重新链接
delay(5000);
}
}
}
//设置
void setup() {
pinMode(BUILTIN_LED, OUTPUT); // 将BUILTIN_LED引脚初始化为输出
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);//MQTT默认端口是1883
client.setCallback(callback);
client.publish("mqtt/state", "1");//链接成功后 会发布这个主题和语句
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 1000*60*10) {
lastMsg = now;
++value;
getTemp();
snprintf (msg, 50, "%f", valueTemp);
Serial.print("Publish message: ");
Serial.println(msg);//串口打印,串口调试器可以看到的
client.publish("mqtt/temp", msg);//接收该主题消息
snprintf (msg, 50, "%f", valueHumi);
client.publish("mqtt/humi", msg);//接收该主题消息
}
}
/**
* 获取温湿度
*/
float getTemp(){
//perform a RH measurement and read back the RH value
Wire.beginTransmission(ADDRESS_SI7021);
Wire.write(MEASURE_RH_HOLD);
Wire.endTransmission();
Wire.requestFrom(ADDRESS_SI7021, 3);
if(Wire.available() >= 3)
{
buffer[0] = Wire.read(); //high byte
buffer[1] = Wire.read(); //low byte
buffer[2] = Wire.read(); //crc
}
outHumi = (buffer[0]<<8) | buffer[1];
crcHumi = CRC8(buffer, 3);
//read temperature from previous RH measurement
Wire.beginTransmission(ADDRESS_SI7021);
Wire.write(READ_T_FROM_PRE_RH_MEASUREMENT);
Wire.endTransmission();
Wire.requestFrom(ADDRESS_SI7021, 2);
if(Wire.available() >= 2)
{
buffer[0] = Wire.read(); //high byte
buffer[1] = Wire.read(); //low byte; no crc
}
outTemp = (buffer[0]<<8) | buffer[1];
valueHumi = 125.0*outHumi/65536 - 6;
valueTemp = 175.72*outTemp/65536 - 46.85;
Serial.print(valueHumi); Serial.print(" \%RH\t");
Serial.print(valueTemp); Serial.println(" `C");
if (crcHumi == 0 && outHumi != 0 && outTemp != 0)
{
Serial.println("CRC checked.");
}
else
{
Serial.println("Error!");
}
}
/**
* CRC校验
*/
byte CRC8(byte *data, byte len)
{
byte crc[8];
byte result = 0;
byte i;
byte doInvert;
String bitString = MakeString(data, len);
for (i = 0; i < 8; i++)
{
crc[i] = 0;
}
for (i = 0; i < bitString.length(); i ++)
{
doInvert = (byte(bitString[i] == '1')) ^ crc[7];
crc[7] = crc[6];
crc[6] = crc[5];
crc[5] = crc[4] ^ doInvert;
crc[4] = crc[3] ^ doInvert;
crc[3] = crc[2];
crc[2] = crc[1];
crc[1] = crc[0];
crc[0] = doInvert;
}
for (i = 0; i < 8; i++)
{
bitWrite(result, i, crc[i]);
}
return result;
}
String MakeString(byte *data, byte len)
{
int i, j;
String tempString[len];
String bitString = "";
for (i = 0; i < len; i++)
{
tempString[i] = String(data[i], BIN);
int zeros = 8 - tempString[i].length();
for (j = 0; j < zeros; j++)
{
tempString[i] = '0' + tempString[i];
}
}
for (i = 0; i < len; i++)
{
bitString = bitString + tempString[i];
}
return bitString;
}
向hassiatant的configuration.yaml配置文件配置域
# weather
sensor:
- platform: yr
name: Weather
forecast: 24 #未来24小时天气,可有手工按需修改
monitored_conditions:
- temperature #气温
- precipitation #雨量
- windSpeed #风速
- pressure #气压
- windDirection #风向
- humidity #湿度
# 环境接收温湿度
- platform: mqtt
name: temp
"unit_of_measurement": "摄氏度"
state_topic: "mqtt/temp"
- platform: mqtt
name: humi
"unit_of_measurement": "%"
state_topic: "mqtt/humi"
# 控制led
light:
- platform: mqtt
name: "bedroom"
state_topic: "mqtt/state"
payload_on: "1"
payload_off: "0"
command_topic: "mqtt/cmd"
效果图
视频
https://www.bilibili.com/video/BV1sp4y197sz
基于Home Assistant 和ESP8266 arduino的实时室温检测