From a6255c31feaa511896cbcc00326028080d22b906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Thu, 25 Mar 2021 18:33:06 +0000 Subject: [PATCH] Add optional bindkey support for CGG1. (#1407) --- esphome/components/xiaomi_ble/xiaomi_ble.cpp | 7 +++++-- esphome/components/xiaomi_cgg1/sensor.py | 4 ++++ esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp | 18 ++++++++++++++++-- esphome/components/xiaomi_cgg1/xiaomi_cgg1.h | 2 ++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 033269f66c..29a34be81c 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -103,7 +103,7 @@ bool parse_xiaomi_message(const std::vector &message, XiaomiParseResult return false; } - while (payload_length > 0) { + while (payload_length > 3) { if (payload[payload_offset + 1] != 0x10) { ESP_LOGVV(TAG, "parse_xiaomi_message(): fixed byte not found, stop parsing residual data."); break; @@ -171,7 +171,10 @@ optional parse_xiaomi_header(const esp32_ble_tracker::Service result.type = XiaomiParseResult::TYPE_MUE4094RT; result.name = "MUE4094RT"; result.raw_offset -= 6; - } else if ((raw[2] == 0x47) && (raw[3] == 0x03)) { // round body, e-ink display + } else if ((raw[2] == 0x47) && (raw[3] == 0x03)) { // ClearGrass-branded, round body, e-ink display + result.type = XiaomiParseResult::TYPE_CGG1; + result.name = "CGG1"; + } else if ((raw[2] == 0x48) && (raw[3] == 0x0B)) { // Qingping-branded, round body, e-ink display — with bindkeys result.type = XiaomiParseResult::TYPE_CGG1; result.name = "CGG1"; } else if ((raw[2] == 0xbc) && (raw[3] == 0x03)) { // VegTrug Grow Care Garden diff --git a/esphome/components/xiaomi_cgg1/sensor.py b/esphome/components/xiaomi_cgg1/sensor.py index 6201df61b8..cedf04d8a6 100644 --- a/esphome/components/xiaomi_cgg1/sensor.py +++ b/esphome/components/xiaomi_cgg1/sensor.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker from esphome.const import ( CONF_BATTERY_LEVEL, + CONF_BINDKEY, CONF_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, @@ -27,6 +28,7 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(XiaomiCGG1), + cv.Optional(CONF_BINDKEY): cv.bind_key, cv.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE @@ -50,6 +52,8 @@ def to_code(config): yield esp32_ble_tracker.register_ble_device(var, config) cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) + if CONF_BINDKEY in config: + cg.add(var.set_bindkey(config[CONF_BINDKEY])) if CONF_TEMPERATURE in config: sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) diff --git a/esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp b/esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp index a7c94fafad..86725956e0 100644 --- a/esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp +++ b/esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp @@ -10,6 +10,7 @@ static const char *TAG = "xiaomi_cgg1"; void XiaomiCGG1::dump_config() { ESP_LOGCONFIG(TAG, "Xiaomi CGG1"); + ESP_LOGCONFIG(TAG, " Bindkey: %s", hexencode(this->bindkey_, 16).c_str()); LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Humidity", this->humidity_); LOG_SENSOR(" ", "Battery Level", this->battery_level_); @@ -31,8 +32,9 @@ bool XiaomiCGG1::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { if (res->is_duplicate) { continue; } - if (res->has_encryption) { - ESP_LOGVV(TAG, "parse_device(): payload decryption is currently not supported on this device."); + if (res->has_encryption && + (!(xiaomi_ble::decrypt_xiaomi_payload(const_cast &>(service_data.data), this->bindkey_, + this->address_)))) { continue; } if (!(xiaomi_ble::parse_xiaomi_message(service_data.data, *res))) { @@ -57,6 +59,18 @@ bool XiaomiCGG1::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { return true; } +void XiaomiCGG1::set_bindkey(const std::string &bindkey) { + memset(bindkey_, 0, 16); + if (bindkey.size() != 32) { + return; + } + char temp[3] = {0}; + for (int i = 0; i < 16; i++) { + strncpy(temp, &(bindkey.c_str()[i * 2]), 2); + bindkey_[i] = std::strtoul(temp, NULL, 16); + } +} + } // namespace xiaomi_cgg1 } // namespace esphome diff --git a/esphome/components/xiaomi_cgg1/xiaomi_cgg1.h b/esphome/components/xiaomi_cgg1/xiaomi_cgg1.h index 57f883405c..e1d812e929 100644 --- a/esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +++ b/esphome/components/xiaomi_cgg1/xiaomi_cgg1.h @@ -13,6 +13,7 @@ namespace xiaomi_cgg1 { class XiaomiCGG1 : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: void set_address(uint64_t address) { address_ = address; } + void set_bindkey(const std::string &bindkey); bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override; @@ -24,6 +25,7 @@ class XiaomiCGG1 : public Component, public esp32_ble_tracker::ESPBTDeviceListen protected: uint64_t address_; + uint8_t bindkey_[16]; sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; sensor::Sensor *battery_level_{nullptr};