简介
在物联网环境搭建-香橙派Zero3安装docker,HomeAssistant和MQTT服务文章中, 我已经对docker和Home Assistant以及MQTT的安装和部署进行了说明,并且测试了MQTT的通讯. 那么在本章节中我们将AHT10湿温度传感器集成到Home Assistant中, 使其可以在HA中被发现和读取详细的参数. 这样我们通过手机端和WEB端就都可以访问它了.
本次所使用物料如下
1. ESP32-C3 开发板
2. AHT10
3. 香橙派Zero3 (部署了MQTT和Home assistant)
AHT10 驱动
由于我们之前在其他文章中已经使用过ESP-IDF驱动过AHT20了, 这次换成了AHT10. 虽然驱动不同,但是也只是更换了一些命令参数或者I2C地址, 因此如何驱动AHT10,我这里就不多做赘述了. 直接放上来对应的驱动文件
AHT10.c
#include "aht10.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" static const char *TAG = "AHT10"; i2c_master_dev_handle_t aht10_handle = NULL; // AHT10 设备句柄 // AHT10 初始化 esp_err_t aht10_init(i2c_master_bus_handle_t i2c_bus) { esp_err_t err; // 注册 AHT10 设备 i2c_device_config_t dev_cfg = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = AHT10_I2C_ADDRESS, .scl_speed_hz = 100000 // 100kHz }; err = i2c_master_bus_add_device(i2c_bus, &dev_cfg, &aht10_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to add AHT10 to I2C bus"); return err; } // 发送初始化命令 uint8_t init_cmd[3] = {AHT10_CMD_INIT, 0x08, 0x00}; err = i2c_master_transmit(aht10_handle, init_cmd, sizeof(init_cmd), 1000); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize AHT10"); return err; } vTaskDelay(pdMS_TO_TICKS(300)); // 等待传感器稳定 ESP_LOGI(TAG, "AHT10 initialized successfully"); return ESP_OK; } // 读取 AHT10 温湿度数据 esp_err_t aht10_read(float *temperature, float *humidity) { esp_err_t err; uint8_t command[3] = {AHT10_CMD_TRIGGER, 0x33, 0x00}; uint8_t data[6]; // 发送测量命令 err = i2c_master_transmit(aht10_handle, command, sizeof(command), 1000); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to send trigger command to AHT10"); return err; } vTaskDelay(pdMS_TO_TICKS(80)); // 等待数据采集 // 读取 6 字节数据 err = i2c_master_receive(aht10_handle, data, sizeof(data), 1000); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read data from AHT10"); return err; } // 检查状态位(最高位应该为 0) if ((data[0] & 0x80) != 0) { ESP_LOGE(TAG, "AHT10 is busy, try again later"); return ESP_ERR_INVALID_STATE; } // 解析湿度数据 uint32_t raw_humidity = ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | data[3]; *humidity = ((float)(raw_humidity >> 4) / 1048576.0) * 100.0; // 解析温度数据 uint32_t raw_temperature = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5]; *temperature = ((float)raw_temperature / 1048576.0) * 200.0 - 50.0; ESP_LOGI(TAG, "Temperature: %.2f°C, Humidity: %.2f%%", *temperature, *humidity); return ESP_OK; }
Aht10.h
#ifndef AHT10_H #define AHT10_H #include "esp_err.h" #include "driver/i2c_master.h" // AHT10 I2C 地址 #define AHT10_I2C_ADDRESS 0x38 // AHT10 命令 #define AHT10_CMD_INIT 0xE1 #define AHT10_CMD_TRIGGER 0xAC #define AHT10_CMD_RESET 0xBA // I2C 端口 #define I2C_MASTER_PORT 0 // AHT10 设备句柄 extern i2c_master_dev_handle_t aht10_handle; // 初始化 AHT10 传感器 esp_err_t aht10_init(i2c_master_bus_handle_t i2c_bus); // 读取温湿度数据 esp_err_t aht10_read(float *temperature, float *humidity); #endif
上述代码适用于ESPIDF框架, 将上述的代码复制到工程中进行编译即可正常使用. 其程序输出如下所示
MQTT数据上报和HA集成传感器
在上篇文章[物联网系列][ESP-IDF系列]使用ESP32-S3通过MQTT协议对数据进行上报中我对MQTT数据上报的流程也进行了阐述, 因此在这里也不多做阐述. 我们这次的重点在于如何将上报的数据能让HA识别到,并且作为一个实体被展示在界面上.
在这里之前我们需要将传感器读取的数据做一点处理, 使其包装成JSON格式然后上传到MQTT的特定主题里. 首先我们需要先引入cJson来序列化JSON数据
#include "cJSON.h"
然后对读取湿温度数据做一下封装, 使其保留两位小数然后序列化成json (如果不处理小数的话,会有很多位小数点)
while (1) { float temperature, humidity; if (aht10_read(&temperature, &humidity) == ESP_OK) { // 创建 cJSON 对象 cJSON *root = cJSON_CreateObject(); // 格式化浮点数保留两位小数 char temp_str[10], hum_str[10]; sprintf(temp_str, "%.2f", temperature); sprintf(hum_str, "%.2f", humidity); cJSON_AddStringToObject(root, "temperature", temp_str); cJSON_AddStringToObject(root, "humidity", hum_str); // 序列化 JSON char *json_string = cJSON_PrintUnformatted(root); if (json_string) { printf("JSON Data: %s\n", json_string); free(json_string); // 释放 JSON 字符串内存 } // 释放 cJSON 对象 cJSON_Delete(root); } else { printf("Failed to read AHT10 data\n"); } vTaskDelay(pdMS_TO_TICKS(2000)); // 每 2 秒读取一次 }
目前读取到的数据如下所示
然后需要把这个传感器的数据发送到MQTT, 我们将定义一个主题, 然后在创建MQTT连接的时候订阅它.并且在主程序中循环将数据发送到这个主题里.
定义主题
static const char *TOPIC = "bedroom/temperature";
订阅主题: 在MQTT连接事件处理回掉的 MQTT_EVENT_CONNCTED 中修改成以下代码
case MQTT_EVENT_CONNECTED: esp_mqtt_client_subscribe(client, TOPIC, 0); ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); break;
发布数据: 在主程序循环中把JSON数据发送到上述主题
while (1) { float temperature, humidity; if (aht10_read(&temperature, &humidity) == ESP_OK) { // 创建 cJSON 对象 cJSON *root = cJSON_CreateObject(); // 格式化浮点数保留两位小数 char temp_str[10], hum_str[10]; sprintf(temp_str, "%.2f", temperature); sprintf(hum_str, "%.2f", humidity); cJSON_AddStringToObject(root, "temperature", temp_str); cJSON_AddStringToObject(root, "humidity", hum_str); // 序列化 JSON char *json_string = cJSON_PrintUnformatted(root); if (json_string) { printf("JSON Data: %s\n", json_string); esp_mqtt_client_publish(client, TOPIC, json_string, 0, 1, 0); // 发布数据到 MQTT 主题 free(json_string); // 释放 JSON 字符串内存 } // 释放 cJSON 对象 cJSON_Delete(root); } else { printf("Failed to read AHT10 data\n"); } vTaskDelay(pdMS_TO_TICKS(2000)); // 每 2 秒读取一次 }
此时如果打开MQTT客户端,将会看到效果如下所示.
从上图中可以看到已经成功的读取到了湿温度传感器的数据并且发布到了MQTT对应的主题. 接下来我们就是要使其Home Assistant识别到这个实体.
1- 首先登录到香橙派
2- 使用命令进入到容器中
docker exec -it[你的容器ID] /bin/bash
3- 编辑configuration.yaml
mqtt: sensor: - name: "Bedroom Temperature" state_topic: "bedroom/temperature" unit_of_measurement: "..C" value_template: "{{ value_json.temperature }}" - name: "Bedroom Humidity" state_topic: "bedroom/temperature" unit_of_measurement: "%" value_template: "{{ value_json.humidity }}"
注意: 这里配置的JSON的key需要和你发送的保持一致.
4、重载Home Assistant配置
5 -查找实体: 如果配置正确的话, 它会被直接集成在仪表盘
6-手机端展示
总结
在本文中我们详细阐述了如何使用ESP32-C3通过MQTT协议将传感器数据接入到HA, 对智能家居感兴趣的朋友可以动手尝试将更多的传感器接到到HA里. 一起动手玩起来吧!