基于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的实时室温检测

 

 

posted @ 2020-05-03 22:45  dyigstraw  阅读(1081)  评论(0编辑  收藏  举报
foot