mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add Xiaomi Cleargrass Temperature and Humidity Sensor (#735)
* Add Xiaomi Cleargrass Temperature and Humidity Sensor * fix CI Travis * fix CI Travis 2 * Improve device detection (more accurate) Co-authored-by: t151602 <sergio.mayoralmartinez@telefonica.com>
This commit is contained in:
		
				
					committed by
					
						 Otto Winter
						Otto Winter
					
				
			
			
				
	
			
			
			
						parent
						
							e207c6ad84
						
					
				
				
					commit
					e30512931b
				
			| @@ -84,13 +84,14 @@ optional<XiaomiParseResult> parse_xiaomi(const esp32_ble_tracker::ESPBTDevice &d | ||||
|   bool is_mijia = (raw[1] & 0x20) == 0x20 && raw[2] == 0xAA && raw[3] == 0x01; | ||||
|   bool is_miflora = (raw[1] & 0x20) == 0x20 && raw[2] == 0x98 && raw[3] == 0x00; | ||||
|   bool is_lywsd02 = (raw[1] & 0x20) == 0x20 && raw[2] == 0x5b && raw[3] == 0x04; | ||||
|   bool is_cleargrass = (raw[1] & 0x30) == 0x30 && raw[2] == 0x47 && raw[3] == 0x03; | ||||
|  | ||||
|   if (!is_mijia && !is_miflora && !is_lywsd02) { | ||||
|   if (!is_mijia && !is_miflora && !is_lywsd02 && !is_cleargrass) { | ||||
|     // ESP_LOGVV(TAG, "Xiaomi no magic bytes"); | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   uint8_t raw_offset = is_mijia ? 11 : 12; | ||||
|   uint8_t raw_offset = is_mijia || is_cleargrass ? 11 : 12; | ||||
|  | ||||
|   const uint8_t raw_type = raw[raw_offset]; | ||||
|   const uint8_t data_length = raw[raw_offset + 2]; | ||||
| @@ -107,6 +108,8 @@ optional<XiaomiParseResult> parse_xiaomi(const esp32_ble_tracker::ESPBTDevice &d | ||||
|     result.type = XiaomiParseResult::TYPE_MIJIA; | ||||
|   } else if (is_lywsd02) { | ||||
|     result.type = XiaomiParseResult::TYPE_LYWSD02; | ||||
|   } else if (is_cleargrass) { | ||||
|     result.type = XiaomiParseResult::TYPE_CLEARGRASS; | ||||
|   } | ||||
|   bool success = parse_xiaomi_data_byte(raw_type, data, data_length, result); | ||||
|   if (!success) | ||||
| @@ -124,6 +127,8 @@ bool XiaomiListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) | ||||
|     name = "Mi Jia"; | ||||
|   } else if (res->type == XiaomiParseResult::TYPE_LYWSD02) { | ||||
|     name = "LYWSD02"; | ||||
|   } else if (res->type == XiaomiParseResult::TYPE_CLEARGRASS) { | ||||
|     name = "Cleargrass"; | ||||
|   } | ||||
|  | ||||
|   ESP_LOGD(TAG, "Got Xiaomi %s (%s):", name, device.address_str().c_str()); | ||||
|   | ||||
| @@ -9,7 +9,7 @@ namespace esphome { | ||||
| namespace xiaomi_ble { | ||||
|  | ||||
| struct XiaomiParseResult { | ||||
|   enum { TYPE_MIJIA, TYPE_MIFLORA, TYPE_LYWSD02 } type; | ||||
|   enum { TYPE_MIJIA, TYPE_MIFLORA, TYPE_LYWSD02, TYPE_CLEARGRASS } type; | ||||
|   optional<float> temperature; | ||||
|   optional<float> humidity; | ||||
|   optional<float> battery_level; | ||||
|   | ||||
							
								
								
									
										0
									
								
								esphome/components/xiaomi_cleargrass/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/xiaomi_cleargrass/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										38
									
								
								esphome/components/xiaomi_cleargrass/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								esphome/components/xiaomi_cleargrass/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, esp32_ble_tracker | ||||
| from esphome.const import CONF_BATTERY_LEVEL, CONF_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ | ||||
|     UNIT_CELSIUS, ICON_THERMOMETER, UNIT_PERCENT, ICON_WATER_PERCENT, ICON_BATTERY, CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| AUTO_LOAD = ['xiaomi_ble'] | ||||
|  | ||||
| xiaomi_cleargrass_ns = cg.esphome_ns.namespace('xiaomi_cleargrass') | ||||
| XiaomiCleargrass = xiaomi_cleargrass_ns.class_( | ||||
|     'XiaomiCleargrass', esp32_ble_tracker.ESPBTDeviceListener, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(XiaomiCleargrass), | ||||
|     cv.Required(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1), | ||||
|     cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_BATTERY, 0), | ||||
| }).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield esp32_ble_tracker.register_ble_device(var, config) | ||||
|  | ||||
|     cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) | ||||
|  | ||||
|     if CONF_TEMPERATURE in config: | ||||
|         sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) | ||||
|         cg.add(var.set_temperature(sens)) | ||||
|     if CONF_HUMIDITY in config: | ||||
|         sens = yield sensor.new_sensor(config[CONF_HUMIDITY]) | ||||
|         cg.add(var.set_humidity(sens)) | ||||
|     if CONF_BATTERY_LEVEL in config: | ||||
|         sens = yield sensor.new_sensor(config[CONF_BATTERY_LEVEL]) | ||||
|         cg.add(var.set_battery_level(sens)) | ||||
							
								
								
									
										21
									
								
								esphome/components/xiaomi_cleargrass/xiaomi_cleargrass.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								esphome/components/xiaomi_cleargrass/xiaomi_cleargrass.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #include "xiaomi_cleargrass.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|  | ||||
| namespace esphome { | ||||
| namespace xiaomi_cleargrass { | ||||
|  | ||||
| static const char *TAG = "xiaomi_cleargrass"; | ||||
|  | ||||
| void XiaomiCleargrass::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "Xiaomi Cleargrass"); | ||||
|   LOG_SENSOR("  ", "Temperature", this->temperature_); | ||||
|   LOG_SENSOR("  ", "Humidity", this->humidity_); | ||||
|   LOG_SENSOR("  ", "Battery Level", this->battery_level_); | ||||
| } | ||||
|  | ||||
| }  // namespace xiaomi_cleargrass | ||||
| }  // namespace esphome | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										50
									
								
								esphome/components/xiaomi_cleargrass/xiaomi_cleargrass.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								esphome/components/xiaomi_cleargrass/xiaomi_cleargrass.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h" | ||||
| #include "esphome/components/xiaomi_ble/xiaomi_ble.h" | ||||
|  | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|  | ||||
| namespace esphome { | ||||
| namespace xiaomi_cleargrass { | ||||
|  | ||||
| class XiaomiCleargrass : public Component, public esp32_ble_tracker::ESPBTDeviceListener { | ||||
|  public: | ||||
|   void set_address(uint64_t address) { address_ = address; } | ||||
|  | ||||
|   bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { | ||||
|     if (device.address_uint64() != this->address_) | ||||
|       return false; | ||||
|  | ||||
|     auto res = xiaomi_ble::parse_xiaomi(device); | ||||
|     if (!res.has_value()) | ||||
|       return false; | ||||
|  | ||||
|     if (res->temperature.has_value() && this->temperature_ != nullptr) | ||||
|       this->temperature_->publish_state(*res->temperature); | ||||
|     if (res->humidity.has_value() && this->humidity_ != nullptr) | ||||
|       this->humidity_->publish_state(*res->humidity); | ||||
|     if (res->battery_level.has_value() && this->battery_level_ != nullptr) | ||||
|       this->battery_level_->publish_state(*res->battery_level); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override { return setup_priority::DATA; } | ||||
|   void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } | ||||
|   void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; } | ||||
|   void set_battery_level(sensor::Sensor *battery_level) { battery_level_ = battery_level; } | ||||
|  | ||||
|  protected: | ||||
|   uint64_t address_; | ||||
|   sensor::Sensor *temperature_{nullptr}; | ||||
|   sensor::Sensor *humidity_{nullptr}; | ||||
|   sensor::Sensor *battery_level_{nullptr}; | ||||
| }; | ||||
|  | ||||
| }  // namespace xiaomi_cleargrass | ||||
| }  // namespace esphome | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user