From 95a6715b2b3ebc30d31430b24beb888583a1f913 Mon Sep 17 00:00:00 2001 From: rbaron Date: Sat, 25 Sep 2021 13:16:27 +0200 Subject: [PATCH] Adds light sensor support for b-parasites (#2391) --- esphome/components/b_parasite/b_parasite.cpp | 20 ++++++++++++++++++++ esphome/components/b_parasite/b_parasite.h | 2 ++ esphome/components/b_parasite/sensor.py | 10 ++++++++++ tests/test2.yaml | 2 ++ 4 files changed, 34 insertions(+) diff --git a/esphome/components/b_parasite/b_parasite.cpp b/esphome/components/b_parasite/b_parasite.cpp index bc1463fd1c..ee12226977 100644 --- a/esphome/components/b_parasite/b_parasite.cpp +++ b/esphome/components/b_parasite/b_parasite.cpp @@ -14,6 +14,7 @@ void BParasite::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Humidity", this->humidity_); LOG_SENSOR(" ", "Soil Moisture", this->soil_moisture_); + LOG_SENSOR(" ", "Illuminance", this->illuminance_); } bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { @@ -36,6 +37,15 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { const auto &data = service_data.data; + const uint8_t protocol_version = data[0] >> 4; + if (protocol_version != 1) { + ESP_LOGE(TAG, "Unsupported protocol version: %u", protocol_version); + return false; + } + + // Some b-parasite versions have an (optional) illuminance sensor. + bool has_illuminance = data[0] & 0x1; + // Counter for deduplicating messages. uint8_t counter = data[1] & 0x0f; if (last_processed_counter_ == counter) { @@ -59,6 +69,9 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { uint16_t soil_moisture = data[8] << 8 | data[9]; float moisture_percent = (100.0f * soil_moisture) / (1 << 16); + // Ambient light in lux. + float illuminance = has_illuminance ? data[16] << 8 | data[17] : 0.0f; + if (battery_voltage_ != nullptr) { battery_voltage_->publish_state(battery_voltage); } @@ -71,6 +84,13 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { if (soil_moisture_ != nullptr) { soil_moisture_->publish_state(moisture_percent); } + if (illuminance_ != nullptr) { + if (has_illuminance) { + illuminance_->publish_state(illuminance); + } else { + ESP_LOGE(TAG, "No lux information is present in the BLE packet"); + } + } last_processed_counter_ = counter; return true; diff --git a/esphome/components/b_parasite/b_parasite.h b/esphome/components/b_parasite/b_parasite.h index bdd9a01b83..70ee4ab23c 100644 --- a/esphome/components/b_parasite/b_parasite.h +++ b/esphome/components/b_parasite/b_parasite.h @@ -22,6 +22,7 @@ class BParasite : public Component, public esp32_ble_tracker::ESPBTDeviceListene void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; } void set_soil_moisture(sensor::Sensor *soil_moisture) { soil_moisture_ = soil_moisture; } + void set_illuminance(sensor::Sensor *illuminance) { illuminance_ = illuminance; } protected: // The received advertisement packet contains an unsigned 4 bits wrap-around counter @@ -32,6 +33,7 @@ class BParasite : public Component, public esp32_ble_tracker::ESPBTDeviceListene sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; sensor::Sensor *soil_moisture_{nullptr}; + sensor::Sensor *illuminance_{nullptr}; }; } // namespace b_parasite diff --git a/esphome/components/b_parasite/sensor.py b/esphome/components/b_parasite/sensor.py index 46ed64337f..d51c48c602 100644 --- a/esphome/components/b_parasite/sensor.py +++ b/esphome/components/b_parasite/sensor.py @@ -5,14 +5,17 @@ from esphome.const import ( CONF_BATTERY_VOLTAGE, CONF_HUMIDITY, CONF_ID, + CONF_ILLUMINANCE, CONF_MOISTURE, CONF_MAC_ADDRESS, CONF_TEMPERATURE, DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, + UNIT_LUX, UNIT_PERCENT, UNIT_VOLT, ) @@ -55,6 +58,12 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_HUMIDITY, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( + unit_of_measurement=UNIT_LUX, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), } ) .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) @@ -74,6 +83,7 @@ async def to_code(config): (CONF_HUMIDITY, var.set_humidity), (CONF_BATTERY_VOLTAGE, var.set_battery_voltage), (CONF_MOISTURE, var.set_soil_moisture), + (CONF_ILLUMINANCE, var.set_illuminance), ]: if config_key in config: sens = await sensor.new_sensor(config[config_key]) diff --git a/tests/test2.yaml b/tests/test2.yaml index d0634e0f7b..4541fba616 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -91,6 +91,8 @@ sensor: name: 'b-parasite Soil Moisture' battery_voltage: name: 'b-parasite Battery Voltage' + illuminance: + name: 'b-parasite Illuminance' - platform: senseair id: senseair0 co2: