Add optional bindkey support for CGG1. (#1407)

This commit is contained in:
Diego Elio Pettenò 2021-03-25 18:33:06 +00:00 committed by Jesse Hills
parent 69c78651d5
commit c903eb2d01
No known key found for this signature in database
GPG key ID: BEAAE804EFD8E83A
4 changed files with 27 additions and 4 deletions

View file

@ -103,7 +103,7 @@ bool parse_xiaomi_message(const std::vector<uint8_t> &message, XiaomiParseResult
return false; return false;
} }
while (payload_length > 0) { while (payload_length > 3) {
if (payload[payload_offset + 1] != 0x10) { if (payload[payload_offset + 1] != 0x10) {
ESP_LOGVV(TAG, "parse_xiaomi_message(): fixed byte not found, stop parsing residual data."); ESP_LOGVV(TAG, "parse_xiaomi_message(): fixed byte not found, stop parsing residual data.");
break; break;
@ -171,7 +171,10 @@ optional<XiaomiParseResult> parse_xiaomi_header(const esp32_ble_tracker::Service
result.type = XiaomiParseResult::TYPE_MUE4094RT; result.type = XiaomiParseResult::TYPE_MUE4094RT;
result.name = "MUE4094RT"; result.name = "MUE4094RT";
result.raw_offset -= 6; 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.type = XiaomiParseResult::TYPE_CGG1;
result.name = "CGG1"; result.name = "CGG1";
} else if ((raw[2] == 0xbc) && (raw[3] == 0x03)) { // VegTrug Grow Care Garden } else if ((raw[2] == 0xbc) && (raw[3] == 0x03)) { // VegTrug Grow Care Garden

View file

@ -3,6 +3,7 @@ import esphome.config_validation as cv
from esphome.components import sensor, esp32_ble_tracker from esphome.components import sensor, esp32_ble_tracker
from esphome.const import ( from esphome.const import (
CONF_BATTERY_LEVEL, CONF_BATTERY_LEVEL,
CONF_BINDKEY,
CONF_HUMIDITY, CONF_HUMIDITY,
CONF_MAC_ADDRESS, CONF_MAC_ADDRESS,
CONF_TEMPERATURE, CONF_TEMPERATURE,
@ -27,6 +28,7 @@ CONFIG_SCHEMA = (
cv.Schema( cv.Schema(
{ {
cv.GenerateID(): cv.declare_id(XiaomiCGG1), cv.GenerateID(): cv.declare_id(XiaomiCGG1),
cv.Optional(CONF_BINDKEY): cv.bind_key,
cv.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE 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) yield esp32_ble_tracker.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) 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: if CONF_TEMPERATURE in config:
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])

View file

@ -10,6 +10,7 @@ static const char *TAG = "xiaomi_cgg1";
void XiaomiCGG1::dump_config() { void XiaomiCGG1::dump_config() {
ESP_LOGCONFIG(TAG, "Xiaomi CGG1"); ESP_LOGCONFIG(TAG, "Xiaomi CGG1");
ESP_LOGCONFIG(TAG, " Bindkey: %s", hexencode(this->bindkey_, 16).c_str());
LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Temperature", this->temperature_);
LOG_SENSOR(" ", "Humidity", this->humidity_); LOG_SENSOR(" ", "Humidity", this->humidity_);
LOG_SENSOR(" ", "Battery Level", this->battery_level_); 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) { if (res->is_duplicate) {
continue; continue;
} }
if (res->has_encryption) { if (res->has_encryption &&
ESP_LOGVV(TAG, "parse_device(): payload decryption is currently not supported on this device."); (!(xiaomi_ble::decrypt_xiaomi_payload(const_cast<std::vector<uint8_t> &>(service_data.data), this->bindkey_,
this->address_)))) {
continue; continue;
} }
if (!(xiaomi_ble::parse_xiaomi_message(service_data.data, *res))) { 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; 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 xiaomi_cgg1
} // namespace esphome } // namespace esphome

View file

@ -13,6 +13,7 @@ namespace xiaomi_cgg1 {
class XiaomiCGG1 : public Component, public esp32_ble_tracker::ESPBTDeviceListener { class XiaomiCGG1 : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
public: public:
void set_address(uint64_t address) { address_ = address; } 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; bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
@ -24,6 +25,7 @@ class XiaomiCGG1 : public Component, public esp32_ble_tracker::ESPBTDeviceListen
protected: protected:
uint64_t address_; uint64_t address_;
uint8_t bindkey_[16];
sensor::Sensor *temperature_{nullptr}; sensor::Sensor *temperature_{nullptr};
sensor::Sensor *humidity_{nullptr}; sensor::Sensor *humidity_{nullptr};
sensor::Sensor *battery_level_{nullptr}; sensor::Sensor *battery_level_{nullptr};