Merge branch 'esp32-tracker-parser-cleanup' into esp32-tracker-retire-scanner-listener

This commit is contained in:
J. Nick Koston
2026-08-08 09:52:24 -05:00
116 changed files with 1282 additions and 350 deletions
+16 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import logging
from typing import Literal
from typing import Any, Literal
from esphome import pins
import esphome.codegen as cg
@@ -99,15 +99,28 @@ async def to_code(config):
cg.add(var.set_turnaround_time(config[CONF_TURNAROUND_TIME]))
def _validate_server_address(value: Any) -> int:
address = cv.hex_uint8_t(value)
# The broadcast address (0) is delivered to every device and is never answered (Modbus 4.1),
# so it cannot identify an individual server device.
if address == 0:
raise cv.Invalid(
"Address 0 is the Modbus broadcast address and cannot be used as a "
"server device address. Assign a unique unit address instead."
)
return address
def modbus_device_schema(default_address, role: Literal["client", "server"] = "client"):
hub_type = ModbusClient if role == "client" else ModbusServer
address_validator = _validate_server_address if role == "server" else cv.hex_uint8_t
schema = {
cv.GenerateID(CONF_MODBUS_ID): cv.use_id(hub_type),
}
if default_address is None:
schema[cv.Required(CONF_ADDRESS)] = cv.hex_uint8_t
schema[cv.Required(CONF_ADDRESS)] = address_validator
else:
schema[cv.Optional(CONF_ADDRESS, default=default_address)] = cv.hex_uint8_t
schema[cv.Optional(CONF_ADDRESS, default=default_address)] = address_validator
return cv.Schema(schema)
+136 -49
View File
@@ -15,6 +15,9 @@ static constexpr uint32_t MODBUS_BITS_PER_CHAR = 11;
// Milliseconds per second
static constexpr uint32_t MS_PER_SEC = 1000;
// Shortest gap between two "no device accepted broadcast" warnings
static constexpr uint32_t UNACCEPTED_BROADCAST_WARN_INTERVAL_MS = 60 * MS_PER_SEC;
void Modbus::setup() {
if (this->flow_control_pin_ != nullptr) {
this->flow_control_pin_->setup();
@@ -183,6 +186,10 @@ void ModbusServerHub::parse_modbus_frames() {
size_t size = this->rx_buffer_.size();
ESP_LOGVV(TAG, "Parsing frames buffer size = %" PRIu32, size);
bool retry_as_client = false;
// A broadcast is a client request, never a peer response; clear any stale expectation (RTU is half-duplex).
const bool is_broadcast = this->rx_buffer_[0] == BROADCAST_ADDRESS;
if (is_broadcast)
this->expecting_peer_response_ = 0;
if (this->expecting_peer_response_ != 0) {
if (!this->parse_modbus_server_frame_()) {
ESP_LOGV(TAG, "Stop expecting peer response from %" PRIu8 " due to parse failure, and retry parse",
@@ -277,11 +284,17 @@ bool ModbusServerHub::parse_modbus_client_frame_() {
// This requires copying the frame data to a local buffer beforehand.
uint8_t data_offset = helpers::client_frame_data_offset(this->rx_buffer_.data(), this->rx_buffer_.size());
uint16_t data_len = frame_length - 2 - data_offset;
uint8_t data[MAX_FRAME_SIZE] = {};
std::memcpy(data, this->rx_buffer_.data() + data_offset, data_len);
uint8_t data_buffer[MAX_FRAME_SIZE] = {};
std::memcpy(data_buffer, this->rx_buffer_.data() + data_offset, data_len);
std::span<const uint8_t> data(data_buffer, data_len);
this->clear_rx_buffer_(LOG_STR("parse succeeded"), false, frame_length);
this->process_modbus_client_frame_(address, function_code, data);
if (address == BROADCAST_ADDRESS) {
// Keep the unicast response buffers out of the broadcast call chain.
this->process_broadcast_frame_(function_code, data);
} else {
this->process_modbus_client_frame_(address, function_code, data);
}
return true;
}
@@ -365,15 +378,100 @@ ModbusServerDevice *ModbusServerHub::find_device_(uint8_t address) {
return nullptr;
}
bool ModbusServerHub::check_register_range_(uint8_t address, uint8_t function_code, uint16_t start_address,
uint16_t number_of_registers) {
ResponseStatus ModbusServerHub::check_register_range_(uint16_t start_address, uint16_t number_of_registers) {
if ((uint32_t) start_address + number_of_registers > 0x10000u) {
ESP_LOGW(TAG, "Register address out of range - start: %" PRIu16 " num: %" PRIu16, start_address,
number_of_registers);
this->send_exception_(address, function_code, ExceptionCode::ILLEGAL_DATA_ADDRESS);
return false;
return ExceptionCode::ILLEGAL_DATA_ADDRESS;
}
return std::nullopt;
}
// Write PDU layout after the function code: start address(2) [+ quantity(2) + byte count(1)] + register values.
// The value subspans taken at these offsets stay in range because client_pdu_length() clamps the byte count to the
// same maximum the callers' number_of_registers * 2 == number_of_bytes guard enforces.
static constexpr size_t WRITE_SINGLE_VALUES_OFFSET = 2;
static constexpr size_t WRITE_MULTIPLE_VALUES_OFFSET = 5;
// FC 0x17 writes follow read start(2) + read quantity(2) + write start(2) + write quantity(2) + byte count(1).
static constexpr size_t READ_WRITE_VALUES_OFFSET = 9;
ResponseStatus ModbusServerHub::parse_write_single_(std::span<const uint8_t> data, uint16_t &start_address,
RegisterValues &registers) {
start_address = helpers::get_data<uint16_t>(data.data(), 0);
// No range check needed: one register can never push start_address + 1 past the address space.
this->assemble_registers_(data.subspan(WRITE_SINGLE_VALUES_OFFSET, sizeof(uint16_t)), registers);
return std::nullopt;
}
ResponseStatus ModbusServerHub::parse_write_multiple_(std::span<const uint8_t> data, uint16_t &start_address,
RegisterValues &registers) {
start_address = helpers::get_data<uint16_t>(data.data(), 0);
uint16_t number_of_registers = helpers::get_data<uint16_t>(data.data(), 2);
uint8_t number_of_bytes = helpers::get_data<uint8_t>(data.data(), 4);
if (number_of_registers == 0 || number_of_registers > MAX_NUM_OF_REGISTERS_TO_WRITE ||
number_of_registers * 2 != number_of_bytes) {
ESP_LOGW(TAG, "Invalid number of registers %" PRIu16 " or bytes %" PRIu8, number_of_registers, number_of_bytes);
return ExceptionCode::ILLEGAL_DATA_VALUE;
}
if (ResponseStatus status = this->check_register_range_(start_address, number_of_registers); status.has_value()) {
return status;
}
this->assemble_registers_(data.subspan(WRITE_MULTIPLE_VALUES_OFFSET, number_of_bytes), registers);
return std::nullopt;
}
void ModbusServerHub::assemble_registers_(std::span<const uint8_t> values, RegisterValues &registers) {
for (size_t offset = 0; offset + 1 < values.size(); offset += 2) {
registers.push_back(helpers::get_data<uint16_t>(values.data(), offset));
}
}
void ModbusServerHub::process_broadcast_frame_(uint8_t function_code, std::span<const uint8_t> data) {
// Broadcasts are only meaningful for register writes and are never answered (Modbus 4.1 / 6.12), so an
// unsupported function code or a validation failure is silently dropped instead of replying with an exception.
// Coil writes (FC 0x05/0x0F) are also broadcastable by spec, but server coil handlers are not implemented yet.
uint16_t start_address;
RegisterValues registers;
ResponseStatus status;
switch (static_cast<FunctionCode>(function_code)) {
case FunctionCode::WRITE_SINGLE_REGISTER:
status = this->parse_write_single_(data, start_address, registers);
break;
case FunctionCode::WRITE_MULTIPLE_REGISTERS:
status = this->parse_write_multiple_(data, start_address, registers);
break;
default:
// Reads and read/write require a reply, so they are not valid as broadcasts.
ESP_LOGV(TAG, "Ignoring broadcast with unsupported function code %" PRIu8, function_code);
return;
}
if (status.has_value()) {
return;
}
// A broadcast is never answered, so a rejecting device has no other feedback channel: report the
// per-device outcome at V, and warn if the write reached nobody at all.
bool accepted = false;
for (auto *device : this->devices_) {
if (ResponseStatus device_status = device->on_broadcast_write_registers(start_address, registers);
device_status.has_value()) {
ESP_LOGV(TAG, "Device %" PRIu8 " rejected broadcast write with exception %" PRIu8, device->get_address(),
static_cast<uint8_t>(device_status.value()));
} else {
accepted = true;
}
}
if (!accepted && !this->devices_.empty()) {
// Warn at most once per interval, then drop to VERBOSE: on a shared bus a broadcast aimed at other nodes
// repeats forever, so warning per frame would flood the log.
const uint32_t now = millis();
if (this->last_unaccepted_broadcast_warn_ == 0 ||
now - this->last_unaccepted_broadcast_warn_ > UNACCEPTED_BROADCAST_WARN_INTERVAL_MS) {
this->last_unaccepted_broadcast_warn_ = now;
ESP_LOGW(TAG, "No device accepted broadcast write of %zu registers at 0x%04X", registers.size(), start_address);
} else {
ESP_LOGV(TAG, "No device accepted broadcast write of %zu registers at 0x%04X", registers.size(), start_address);
}
}
return true;
}
bool ModbusServerHub::build_or_reject_read_response_(uint8_t address, uint8_t function_code, ResponseStatus status,
@@ -420,7 +518,8 @@ bool ModbusServerHub::build_or_reject_read_response_(uint8_t address, uint8_t fu
return true;
}
void ModbusServerHub::process_modbus_client_frame_(uint8_t address, uint8_t function_code, const uint8_t *data) {
void ModbusServerHub::process_modbus_client_frame_(uint8_t address, uint8_t function_code,
std::span<const uint8_t> data) {
ModbusServerDevice *device = this->find_device_(address);
if (device == nullptr) {
this->expecting_peer_response_ = address;
@@ -437,14 +536,16 @@ void ModbusServerHub::process_modbus_client_frame_(uint8_t address, uint8_t func
case FunctionCode::READ_HOLDING_REGISTERS:
case FunctionCode::READ_INPUT_REGISTERS: {
// PDU data: start address(2) + quantity(2).
uint16_t start_address = helpers::get_data<uint16_t>(data, 0);
uint16_t number_of_registers = helpers::get_data<uint16_t>(data, 2);
uint16_t start_address = helpers::get_data<uint16_t>(data.data(), 0);
uint16_t number_of_registers = helpers::get_data<uint16_t>(data.data(), 2);
if (number_of_registers == 0 || number_of_registers > MAX_NUM_OF_REGISTERS_TO_READ) {
ESP_LOGW(TAG, "Invalid number of registers %" PRIu16, number_of_registers);
this->send_exception_(address, function_code, ExceptionCode::ILLEGAL_DATA_VALUE);
return;
}
if (!this->check_register_range_(address, function_code, start_address, number_of_registers)) {
status = this->check_register_range_(start_address, number_of_registers);
if (status.has_value()) {
this->send_exception_(address, function_code, status.value());
return;
}
RegisterValues registers;
@@ -462,46 +563,31 @@ void ModbusServerHub::process_modbus_client_frame_(uint8_t address, uint8_t func
}
case FunctionCode::WRITE_SINGLE_REGISTER:
case FunctionCode::WRITE_MULTIPLE_REGISTERS: {
// PDU data: start address(2) [+ quantity(2) + byte count(1)] + register values.
// A single-register write always targets one register; for a multiple-register write the
// quantity is in the frame and its byte count must equal quantity * 2. The register values are
// assembled into registers below so the handler doesn't have to know the request framing.
uint16_t start_address = helpers::get_data<uint16_t>(data, 0);
uint16_t number_of_registers = 1;
uint16_t values_offset = 2; // single write: values follow the 2-byte start address
if (static_cast<FunctionCode>(function_code) == FunctionCode::WRITE_MULTIPLE_REGISTERS) {
number_of_registers = helpers::get_data<uint16_t>(data, 2);
uint8_t number_of_bytes = helpers::get_data<uint8_t>(data, 4);
values_offset = 5; // multiple write: values follow start address(2) + quantity(2) + byte count(1)
if (number_of_registers == 0 || number_of_registers > MAX_NUM_OF_REGISTERS_TO_WRITE ||
number_of_registers * 2 != number_of_bytes) {
ESP_LOGW(TAG, "Invalid number of registers %" PRIu16 " or bytes %" PRIu8, number_of_registers,
number_of_bytes);
this->send_exception_(address, function_code, ExceptionCode::ILLEGAL_DATA_VALUE);
return;
}
if (!this->check_register_range_(address, function_code, start_address, number_of_registers)) {
return;
}
}
// Assemble the register values (host byte order) so the handler never sees wire framing.
// Parse and validate the write PDU into host-order register values; reply with an exception on failure.
uint16_t start_address;
RegisterValues registers;
for (uint16_t i = 0; i < number_of_registers; i++) {
registers.push_back(helpers::get_data<uint16_t>(data, values_offset + i * 2));
if (static_cast<FunctionCode>(function_code) == FunctionCode::WRITE_SINGLE_REGISTER) {
status = this->parse_write_single_(data, start_address, registers);
} else {
status = this->parse_write_multiple_(data, start_address, registers);
}
if (status.has_value()) {
this->send_exception_(address, function_code, status.value());
return;
}
status = device->on_write_registers(start_address, registers);
response_data = data; // echo the request header per Modbus 6.6, 6.12
response_data = data.data(); // echo the request header per Modbus 6.6, 6.12
response_len = 4;
break;
}
case FunctionCode::READ_WRITE_MULTIPLE_REGISTERS: {
// PDU data: read start address(2) + read quantity(2) + write start address(2) + write quantity(2) +
// write byte count(1) + write register values. Per Modbus 6.17 the write is performed before the read.
uint16_t read_start_address = helpers::get_data<uint16_t>(data, 0);
uint16_t number_of_registers = helpers::get_data<uint16_t>(data, 2);
uint16_t write_start_address = helpers::get_data<uint16_t>(data, 4);
uint16_t number_of_write_registers = helpers::get_data<uint16_t>(data, 6);
uint8_t number_of_bytes = helpers::get_data<uint8_t>(data, 8);
uint16_t read_start_address = helpers::get_data<uint16_t>(data.data(), 0);
uint16_t number_of_registers = helpers::get_data<uint16_t>(data.data(), 2);
uint16_t write_start_address = helpers::get_data<uint16_t>(data.data(), 4);
uint16_t number_of_write_registers = helpers::get_data<uint16_t>(data.data(), 6);
uint8_t number_of_bytes = helpers::get_data<uint8_t>(data.data(), 8);
if (number_of_registers == 0 || number_of_registers > MAX_NUM_OF_REGISTERS_TO_READ ||
number_of_write_registers == 0 || number_of_write_registers > MAX_NUM_OF_REGISTERS_TO_WRITE_RW ||
number_of_write_registers * 2 != number_of_bytes) {
@@ -510,18 +596,19 @@ void ModbusServerHub::process_modbus_client_frame_(uint8_t address, uint8_t func
this->send_exception_(address, function_code, ExceptionCode::ILLEGAL_DATA_VALUE);
return;
}
if (!this->check_register_range_(address, function_code, read_start_address, number_of_registers) ||
!this->check_register_range_(address, function_code, write_start_address, number_of_write_registers)) {
status = this->check_register_range_(read_start_address, number_of_registers);
if (!status.has_value()) {
status = this->check_register_range_(write_start_address, number_of_write_registers);
}
if (status.has_value()) {
this->send_exception_(address, function_code, status.value());
return;
}
// Perform the write first (Modbus 6.17). Scoped so the write values are off the stack before the read
// values are allocated, keeping only one RegisterValues buffer live at a time.
{
// Assemble the written register values (host byte order); they follow the 9-byte request header.
RegisterValues write_registers;
for (uint16_t i = 0; i < number_of_write_registers; i++) {
write_registers.push_back(helpers::get_data<uint16_t>(data, 9 + i * 2));
}
this->assemble_registers_(data.subspan(READ_WRITE_VALUES_OFFSET, number_of_bytes), write_registers);
// Dispatch to the standalone write and read handlers so any device implementing those supports 0x17
// without a dedicated handler; a device that maps registers by address reconstructs the read response
// from the values it just stored.
+28 -5
View File
@@ -330,12 +330,22 @@ class ModbusServerHub : public Modbus {
void parse_modbus_frames() override;
bool parse_modbus_client_frame_();
void process_modbus_server_frame(uint8_t address, std::span<const uint8_t> pdu) override;
void process_modbus_client_frame_(uint8_t address, uint8_t function_code, const uint8_t *data);
void process_modbus_client_frame_(uint8_t address, uint8_t function_code, std::span<const uint8_t> data);
// Dispatches a broadcast (address 0) write to every registered device; broadcasts are never answered.
void process_broadcast_frame_(uint8_t function_code, std::span<const uint8_t> data);
// Parses a WRITE_SINGLE_REGISTER / WRITE_MULTIPLE_REGISTERS PDU into start_address and the host-order register
// values, validating the register count and address range. Returns std::nullopt on success, otherwise the Modbus
// exception code describing the failure. Shared by unicast writes (which reply with the exception) and broadcast
// writes (which silently drop invalid frames).
ResponseStatus parse_write_single_(std::span<const uint8_t> data, uint16_t &start_address, RegisterValues &registers);
ResponseStatus parse_write_multiple_(std::span<const uint8_t> data, uint16_t &start_address,
RegisterValues &registers);
// Appends the big-endian register values in values to registers, in host byte order.
void assemble_registers_(std::span<const uint8_t> values, RegisterValues &registers);
ModbusServerDevice *find_device_(uint8_t address);
// Returns true if [start_address, start_address + number_of_registers) fits in the 16-bit address space.
// On failure, logs and sends an ILLEGAL_DATA_ADDRESS exception to the client.
bool check_register_range_(uint8_t address, uint8_t function_code, uint16_t start_address,
uint16_t number_of_registers);
// Returns std::nullopt if [start_address, start_address + number_of_registers) fits in the 16-bit address space,
// otherwise ILLEGAL_DATA_ADDRESS. The caller sends the exception reply if one is required.
ResponseStatus check_register_range_(uint16_t start_address, uint16_t number_of_registers);
// Builds the body of a register read response (byte count followed by the big-endian register values) into
// response_buffer. Shared by every function code that answers with register values, so the read reply stays
@@ -351,6 +361,10 @@ class ModbusServerHub : public Modbus {
uint8_t expecting_peer_response_{0};
std::vector<ModbusServerDevice *> devices_;
// Stamp of the last "broadcast reached no device" warning, 0 until the first one is logged. Rate limiting
// on time rather than on address keeps the log bounded no matter how many addresses a shared bus carries.
uint32_t last_unaccepted_broadcast_warn_{0};
// Holds the raw payload of a single reply deferred for sending when tx was blocked at send time.
// Only one server reply can be waiting at once, so a single fixed buffer avoids heap allocation.
std::array<uint8_t, MAX_RAW_SIZE> deferred_payload_;
@@ -603,9 +617,18 @@ class ModbusServerDevice {
virtual ResponseStatus on_write_registers(uint16_t start_address, const RegisterValues &registers) {
return ExceptionCode::ILLEGAL_FUNCTION;
};
// Hub entry point for broadcast (address 0) writes, which are never answered.
ResponseStatus on_broadcast_write_registers(uint16_t start_address, const RegisterValues &registers) {
this->broadcast_write_ = true;
ResponseStatus status = this->on_write_registers(start_address, registers);
this->broadcast_write_ = false;
return status;
}
protected:
uint8_t address_{0};
// Set while handling a broadcast write: the caller sends no reply, so a rejection has no wire consequence.
bool broadcast_write_{false};
};
} // namespace esphome::modbus
@@ -116,6 +116,10 @@ static constexpr uint16_t READ_PDU_SIZE = 5;
// A single-write PDU is always function code(1) + address(2) + value(2)
static constexpr uint16_t WRITE_SINGLE_PDU_SIZE = 5;
static constexpr uint16_t MAX_FRAME_SIZE = 256;
// 4.1 Address 0 is the broadcast address: the request is processed by every device and never answered.
static constexpr uint8_t BROADCAST_ADDRESS = 0;
// Both send paths bound their payload so the framed result lands exactly on the RTU limit: a client
// PDU gains an address byte and a CRC, a raw server frame gains a CRC. send_frame_() therefore never
// has to check the framed size - it cannot be exceeded.
@@ -145,7 +145,12 @@ modbus::ResponseStatus ModbusServer::on_write_registers(uint16_t start_address,
}
return true;
})) {
ESP_LOGW(TAG, "Write request rejected before applying any register. Sending exception response.");
// On a broadcast every device that does not map these registers rejects them, which is the normal case.
if (this->broadcast_write_) {
ESP_LOGV(TAG, "Write request rejected before applying any register.");
} else {
ESP_LOGW(TAG, "Write request rejected before applying any register.");
}
return precheck;
}
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -22,14 +22,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["ble_device_base"]
xiaomi_hhccjcy10_ns = cg.esphome_ns.namespace("xiaomi_hhccjcy10")
XiaomiHHCCJCY10 = xiaomi_hhccjcy10_ns.class_(
"XiaomiHHCCJCY10", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiHHCCJCY10", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_hhccjcy10"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiHHCCJCY10),
@@ -67,15 +68,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_hhccjcy10 {
static const char *const TAG = "xiaomi_hhccjcy10";
@@ -17,7 +15,7 @@ void XiaomiHHCCJCY10::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiHHCCJCY10::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiHHCCJCY10::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -63,5 +61,3 @@ bool XiaomiHHCCJCY10::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
}
} // namespace esphome::xiaomi_hhccjcy10
#endif
@@ -2,17 +2,15 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#ifdef USE_ESP32
#include "esphome/components/ble_device_base/ble_device.h"
namespace esphome::xiaomi_hhccjcy10 {
class XiaomiHHCCJCY10 final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiHHCCJCY10 final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { this->address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; }
@@ -31,5 +29,3 @@ class XiaomiHHCCJCY10 final : public Component, public esp32_ble_tracker::ESPBTD
};
} // namespace esphome::xiaomi_hhccjcy10
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_CONDUCTIVITY,
@@ -13,15 +13,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_hhccpot002_ns = cg.esphome_ns.namespace("xiaomi_hhccpot002")
XiaomiHHCCPOT002 = xiaomi_hhccpot002_ns.class_(
"XiaomiHHCCPOT002", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiHHCCPOT002", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_hhccpot002"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiHHCCPOT002),
@@ -40,15 +40,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_hhccpot002.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_hhccpot002 {
static const char *const TAG = "xiaomi_hhccpot002";
@@ -13,7 +11,7 @@ void XiaomiHHCCPOT002 ::dump_config() {
LOG_SENSOR(" ", "Conductivity", this->conductivity_);
}
bool XiaomiHHCCPOT002::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiHHCCPOT002::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -52,5 +50,3 @@ bool XiaomiHHCCPOT002::parse_device(const esp32_ble_tracker::ESPBTDevice &device
}
} // namespace esphome::xiaomi_hhccpot002
#endif
@@ -2,18 +2,16 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_hhccpot002 {
class XiaomiHHCCPOT002 final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiHHCCPOT002 final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_moisture(sensor::Sensor *moisture) { moisture_ = moisture; }
@@ -26,5 +24,3 @@ class XiaomiHHCCPOT002 final : public Component, public esp32_ble_tracker::ESPBT
};
} // namespace esphome::xiaomi_hhccpot002
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -19,15 +19,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_jqjcy01ym_ns = cg.esphome_ns.namespace("xiaomi_jqjcy01ym")
XiaomiJQJCY01YM = xiaomi_jqjcy01ym_ns.class_(
"XiaomiJQJCY01YM", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiJQJCY01YM", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_jqjcy01ym"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiJQJCY01YM),
@@ -59,15 +59,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_jqjcy01ym.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_jqjcy01ym {
static const char *const TAG = "xiaomi_jqjcy01ym";
@@ -15,7 +13,7 @@ void XiaomiJQJCY01YM::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiJQJCY01YM::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiJQJCY01YM::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -58,5 +56,3 @@ bool XiaomiJQJCY01YM::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
}
} // namespace esphome::xiaomi_jqjcy01ym
#endif
@@ -2,18 +2,16 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_jqjcy01ym {
class XiaomiJQJCY01YM final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiJQJCY01YM final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -30,5 +28,3 @@ class XiaomiJQJCY01YM final : public Component, public esp32_ble_tracker::ESPBTD
};
} // namespace esphome::xiaomi_jqjcy01ym
#endif
+7 -7
View File
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -16,15 +16,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_lywsd02_ns = cg.esphome_ns.namespace("xiaomi_lywsd02")
XiaomiLYWSD02 = xiaomi_lywsd02_ns.class_(
"XiaomiLYWSD02", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiLYWSD02", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_lywsd02"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiLYWSD02),
@@ -50,15 +50,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_lywsd02.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd02 {
static const char *const TAG = "xiaomi_lywsd02";
@@ -14,7 +12,7 @@ void XiaomiLYWSD02::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiLYWSD02::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiLYWSD02::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -55,5 +53,3 @@ bool XiaomiLYWSD02::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
}
} // namespace esphome::xiaomi_lywsd02
#endif
@@ -2,18 +2,16 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd02 {
class XiaomiLYWSD02 final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiLYWSD02 final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -28,5 +26,3 @@ class XiaomiLYWSD02 final : public Component, public esp32_ble_tracker::ESPBTDev
};
} // namespace esphome::xiaomi_lywsd02
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -17,16 +17,16 @@ from esphome.const import (
UNIT_PERCENT,
)
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
CODEOWNERS = ["@juanluss31"]
DEPENDENCIES = ["esp32_ble_tracker"]
xiaomi_lywsd02mmc_ns = cg.esphome_ns.namespace("xiaomi_lywsd02mmc")
XiaomiLYWSD02MMC = xiaomi_lywsd02mmc_ns.class_(
"XiaomiLYWSD02MMC", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiLYWSD02MMC", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_lywsd02mmc"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiLYWSD02MMC),
@@ -53,15 +53,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd02mmc {
static const char *const TAG = "xiaomi_lywsd02mmc";
@@ -21,7 +19,7 @@ void XiaomiLYWSD02MMC::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiLYWSD02MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiLYWSD02MMC::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -65,5 +63,3 @@ bool XiaomiLYWSD02MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device
void XiaomiLYWSD02MMC::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_lywsd02mmc
#endif
@@ -2,19 +2,17 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd02mmc {
class XiaomiLYWSD02MMC final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiLYWSD02MMC final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { this->address_ = address; }
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; }
@@ -30,5 +28,3 @@ class XiaomiLYWSD02MMC final : public Component, public esp32_ble_tracker::ESPBT
};
} // namespace esphome::xiaomi_lywsd02mmc
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -19,15 +19,15 @@ from esphome.const import (
CODEOWNERS = ["@ahpohl"]
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_lywsd03mmc_ns = cg.esphome_ns.namespace("xiaomi_lywsd03mmc")
XiaomiLYWSD03MMC = xiaomi_lywsd03mmc_ns.class_(
"XiaomiLYWSD03MMC", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiLYWSD03MMC", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_lywsd03mmc"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiLYWSD03MMC),
@@ -54,15 +54,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd03mmc {
static const char *const TAG = "xiaomi_lywsd03mmc";
@@ -21,7 +19,7 @@ void XiaomiLYWSD03MMC::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiLYWSD03MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiLYWSD03MMC::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -69,5 +67,3 @@ bool XiaomiLYWSD03MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device
void XiaomiLYWSD03MMC::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_lywsd03mmc
#endif
@@ -2,19 +2,17 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsd03mmc {
class XiaomiLYWSD03MMC final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiLYWSD03MMC final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; };
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
@@ -29,5 +27,3 @@ class XiaomiLYWSD03MMC final : public Component, public esp32_ble_tracker::ESPBT
};
} // namespace esphome::xiaomi_lywsd03mmc
#endif
+7 -7
View File
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -16,15 +16,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_lywsdcgq_ns = cg.esphome_ns.namespace("xiaomi_lywsdcgq")
XiaomiLYWSDCGQ = xiaomi_lywsdcgq_ns.class_(
"XiaomiLYWSDCGQ", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiLYWSDCGQ", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_lywsdcgq"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiLYWSDCGQ),
@@ -50,15 +50,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_lywsdcgq.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsdcgq {
static const char *const TAG = "xiaomi_lywsdcgq";
@@ -14,7 +12,7 @@ void XiaomiLYWSDCGQ::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiLYWSDCGQ::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiLYWSDCGQ::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -55,5 +53,3 @@ bool XiaomiLYWSDCGQ::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
}
} // namespace esphome::xiaomi_lywsdcgq
#endif
@@ -2,18 +2,16 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_lywsdcgq {
class XiaomiLYWSDCGQ final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiLYWSDCGQ final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -28,5 +26,3 @@ class XiaomiLYWSDCGQ final : public Component, public esp32_ble_tracker::ESPBTDe
};
} // namespace esphome::xiaomi_lywsdcgq
#endif
+7 -7
View File
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -16,15 +16,15 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_mhoc303_ns = cg.esphome_ns.namespace("xiaomi_mhoc303")
XiaomiMHOC303 = xiaomi_mhoc303_ns.class_(
"XiaomiMHOC303", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiMHOC303", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_mhoc303"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiMHOC303),
@@ -50,15 +50,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_mhoc303.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mhoc303 {
static const char *const TAG = "xiaomi_mhoc303";
@@ -14,7 +12,7 @@ void XiaomiMHOC303::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiMHOC303::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiMHOC303::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -55,5 +53,3 @@ bool XiaomiMHOC303::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
}
} // namespace esphome::xiaomi_mhoc303
#endif
@@ -2,18 +2,16 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mhoc303 {
class XiaomiMHOC303 final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiMHOC303 final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
@@ -28,5 +26,3 @@ class XiaomiMHOC303 final : public Component, public esp32_ble_tracker::ESPBTDev
};
} // namespace esphome::xiaomi_mhoc303
#endif
+7 -7
View File
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -18,15 +18,15 @@ from esphome.const import (
)
CODEOWNERS = ["@vevsvevs"]
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_mhoc401_ns = cg.esphome_ns.namespace("xiaomi_mhoc401")
XiaomiMHOC401 = xiaomi_mhoc401_ns.class_(
"XiaomiMHOC401", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiMHOC401", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_mhoc401"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiMHOC401),
@@ -53,15 +53,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mhoc401 {
static const char *const TAG = "xiaomi_mhoc401";
@@ -21,7 +19,7 @@ void XiaomiMHOC401::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiMHOC401::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiMHOC401::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -69,5 +67,3 @@ bool XiaomiMHOC401::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
void XiaomiMHOC401::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_mhoc401
#endif
@@ -2,19 +2,17 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mhoc401 {
class XiaomiMHOC401 final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiMHOC401 final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; };
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
@@ -29,5 +27,3 @@ class XiaomiMHOC401 final : public Component, public esp32_ble_tracker::ESPBTDev
};
} // namespace esphome::xiaomi_mhoc401
#endif
+7 -6
View File
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_CLEAR_IMPEDANCE,
@@ -15,14 +15,15 @@ from esphome.const import (
UNIT_OHM,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["ble_device_base"]
xiaomi_miscale_ns = cg.esphome_ns.namespace("xiaomi_miscale")
XiaomiMiscale = xiaomi_miscale_ns.class_(
"XiaomiMiscale", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiMiscale", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_miscale"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiMiscale),
@@ -43,15 +44,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_clear_impedance(config[CONF_CLEAR_IMPEDANCE]))
@@ -1,9 +1,7 @@
#include "xiaomi_miscale.h"
#include "esphome/components/esp32_ble/ble_uuid.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_miscale {
static const char *const TAG = "xiaomi_miscale";
@@ -14,7 +12,7 @@ void XiaomiMiscale::dump_config() {
LOG_SENSOR(" ", "Impedance", this->impedance_);
}
bool XiaomiMiscale::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiMiscale::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -56,14 +54,14 @@ bool XiaomiMiscale::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
return success;
}
optional<ParseResult> XiaomiMiscale::parse_header_(const esp32_ble_tracker::ServiceData &service_data) {
optional<ParseResult> XiaomiMiscale::parse_header_(const ble_device_base::ServiceData &service_data) {
ParseResult result;
if (service_data.uuid == esp32_ble_tracker::ESPBTUUID::from_uint16(0x181D) && service_data.data.size() == 10) {
if (service_data.uuid == ble_device_base::ESPBTUUID::from_uint16(0x181D) && service_data.data.size() == 10) {
result.version = 1;
} else if (service_data.uuid == esp32_ble_tracker::ESPBTUUID::from_uint16(0x181B) && service_data.data.size() == 13) {
} else if (service_data.uuid == ble_device_base::ESPBTUUID::from_uint16(0x181B) && service_data.data.size() == 13) {
result.version = 2;
} else {
char uuid_buf[esp32_ble::UUID_STR_LEN];
char uuid_buf[ble_device_base::UUID_STR_LEN];
ESP_LOGVV(TAG,
"parse_header(): Couldn't identify scale version or data size was not correct. UUID: %s, data_size: %d",
service_data.uuid.to_str(uuid_buf), service_data.data.size());
@@ -167,5 +165,3 @@ bool XiaomiMiscale::report_results_(const optional<ParseResult> &result, const c
}
} // namespace esphome::xiaomi_miscale
#endif
@@ -2,12 +2,10 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include <vector>
#ifdef USE_ESP32
namespace esphome::xiaomi_miscale {
struct ParseResult {
@@ -16,11 +14,11 @@ struct ParseResult {
optional<float> impedance;
};
class XiaomiMiscale final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiMiscale final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; };
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_weight(sensor::Sensor *weight) { weight_ = weight; }
void set_impedance(sensor::Sensor *impedance) { impedance_ = impedance; }
@@ -32,7 +30,7 @@ class XiaomiMiscale final : public Component, public esp32_ble_tracker::ESPBTDev
sensor::Sensor *impedance_{nullptr};
bool clear_impedance_{false};
optional<ParseResult> parse_header_(const esp32_ble_tracker::ServiceData &service_data);
optional<ParseResult> parse_header_(const ble_device_base::ServiceData &service_data);
bool parse_message_(const std::vector<uint8_t> &message, ParseResult &result);
bool parse_message_v1_(const std::vector<uint8_t> &message, ParseResult &result);
bool parse_message_v2_(const std::vector<uint8_t> &message, ParseResult &result);
@@ -40,5 +38,3 @@ class XiaomiMiscale final : public Component, public esp32_ble_tracker::ESPBTDev
};
} // namespace esphome::xiaomi_miscale
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import binary_sensor, esp32_ble_tracker, sensor
from esphome.components import binary_sensor, ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -20,18 +20,18 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble", "sensor"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble", "sensor"]
xiaomi_mjyd02yla_ns = cg.esphome_ns.namespace("xiaomi_mjyd02yla")
XiaomiMJYD02YLA = xiaomi_mjyd02yla_ns.class_(
"XiaomiMJYD02YLA",
binary_sensor.BinarySensor,
cg.Component,
esp32_ble_tracker.ESPBTDeviceListener,
ble_device_base.ESPBTDeviceListener,
)
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_mjyd02yla"),
binary_sensor.binary_sensor_schema(
XiaomiMJYD02YLA, device_class=DEVICE_CLASS_MOTION
)
@@ -63,15 +63,15 @@ CONFIG_SCHEMA = cv.All(
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mjyd02yla {
static const char *const TAG = "xiaomi_mjyd02yla";
@@ -17,7 +15,7 @@ void XiaomiMJYD02YLA::dump_config() {
LOG_SENSOR(" ", "Illuminance", this->illuminance_);
}
bool XiaomiMJYD02YLA::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiMJYD02YLA::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -65,5 +63,3 @@ bool XiaomiMJYD02YLA::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
void XiaomiMJYD02YLA::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_mjyd02yla
#endif
@@ -3,21 +3,19 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mjyd02yla {
class XiaomiMJYD02YLA final : public Component,
public binary_sensor::BinarySensorInitiallyOff,
public esp32_ble_tracker::ESPBTDeviceListener {
public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_idle_time(sensor::Sensor *idle_time) { idle_time_ = idle_time; }
@@ -35,5 +33,3 @@ class XiaomiMJYD02YLA final : public Component,
};
} // namespace esphome::xiaomi_mjyd02yla
#endif
@@ -1,21 +1,21 @@
from esphome import core
import esphome.codegen as cg
from esphome.components import binary_sensor, esp32_ble_tracker
from esphome.components import binary_sensor, ble_device_base
import esphome.config_validation as cv
from esphome.const import CONF_MAC_ADDRESS, CONF_TIMEOUT, DEVICE_CLASS_MOTION
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
xiaomi_mue4094rt_ns = cg.esphome_ns.namespace("xiaomi_mue4094rt")
XiaomiMUE4094RT = xiaomi_mue4094rt_ns.class_(
"XiaomiMUE4094RT",
binary_sensor.BinarySensor,
cg.Component,
esp32_ble_tracker.ESPBTDeviceListener,
ble_device_base.ESPBTDeviceListener,
)
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_mue4094rt"),
binary_sensor.binary_sensor_schema(
XiaomiMUE4094RT, device_class=DEVICE_CLASS_MOTION
)
@@ -28,15 +28,15 @@ CONFIG_SCHEMA = cv.All(
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_time(config[CONF_TIMEOUT]))
@@ -1,8 +1,6 @@
#include "xiaomi_mue4094rt.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mue4094rt {
static const char *const TAG = "xiaomi_mue4094rt";
@@ -12,7 +10,7 @@ void XiaomiMUE4094RT::dump_config() {
LOG_BINARY_SENSOR(" ", "Motion", this);
}
bool XiaomiMUE4094RT::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiMUE4094RT::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -51,5 +49,3 @@ bool XiaomiMUE4094RT::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
}
} // namespace esphome::xiaomi_mue4094rt
#endif
@@ -2,20 +2,18 @@
#include "esphome/core/component.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_mue4094rt {
class XiaomiMUE4094RT final : public Component,
public binary_sensor::BinarySensorInitiallyOff,
public esp32_ble_tracker::ESPBTDeviceListener {
public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_time(uint16_t timeout) { timeout_ = timeout; }
@@ -26,5 +24,3 @@ class XiaomiMUE4094RT final : public Component,
};
} // namespace esphome::xiaomi_mue4094rt
#endif
@@ -1,19 +1,19 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker
from esphome.components import ble_device_base
import esphome.config_validation as cv
from esphome.const import CONF_BINDKEY, CONF_ID, CONF_MAC_ADDRESS
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
CODEOWNERS = ["@jesserockz"]
DEPENDENCIES = ["esp32_ble_tracker"]
MULTI_CONF = True
xiaomi_rtcgq02lm_ns = cg.esphome_ns.namespace("xiaomi_rtcgq02lm")
XiaomiRTCGQ02LM = xiaomi_rtcgq02lm_ns.class_(
"XiaomiRTCGQ02LM", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiRTCGQ02LM", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_rtcgq02lm"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiRTCGQ02LM),
@@ -21,15 +21,15 @@ CONFIG_SCHEMA = (
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_rtcgq02lm {
static const char *const TAG = "xiaomi_rtcgq02lm";
@@ -24,7 +22,7 @@ void XiaomiRTCGQ02LM::dump_config() {
#endif
}
bool XiaomiRTCGQ02LM::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiRTCGQ02LM::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -79,5 +77,3 @@ bool XiaomiRTCGQ02LM::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
void XiaomiRTCGQ02LM::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_rtcgq02lm
#endif
@@ -1,6 +1,6 @@
#pragma once
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/core/defines.h"
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
@@ -11,16 +11,14 @@
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#include "esphome/core/component.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_rtcgq02lm {
class XiaomiRTCGQ02LM final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiRTCGQ02LM final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; };
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
#ifdef USE_BINARY_SENSOR
@@ -54,5 +52,3 @@ class XiaomiRTCGQ02LM final : public Component, public esp32_ble_tracker::ESPBTD
};
} // namespace esphome::xiaomi_rtcgq02lm
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import binary_sensor, esp32_ble_tracker, sensor
from esphome.components import binary_sensor, ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -12,18 +12,18 @@ from esphome.const import (
UNIT_PERCENT,
)
DEPENDENCIES = ["esp32_ble_tracker"]
AUTO_LOAD = ["xiaomi_ble", "sensor"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble", "sensor"]
xiaomi_wx08zm_ns = cg.esphome_ns.namespace("xiaomi_wx08zm")
XiaomiWX08ZM = xiaomi_wx08zm_ns.class_(
"XiaomiWX08ZM",
binary_sensor.BinarySensor,
esp32_ble_tracker.ESPBTDeviceListener,
ble_device_base.ESPBTDeviceListener,
cg.Component,
)
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_wx08zm"),
binary_sensor.binary_sensor_schema(XiaomiWX08ZM)
.extend(
{
@@ -43,15 +43,15 @@ CONFIG_SCHEMA = cv.All(
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
@@ -1,8 +1,6 @@
#include "xiaomi_wx08zm.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_wx08zm {
static const char *const TAG = "xiaomi_wx08zm";
@@ -14,7 +12,7 @@ void XiaomiWX08ZM::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiWX08ZM::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiWX08ZM::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -56,5 +54,3 @@ bool XiaomiWX08ZM::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
}
} // namespace esphome::xiaomi_wx08zm
#endif
@@ -3,20 +3,18 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_wx08zm {
class XiaomiWX08ZM final : public Component,
public binary_sensor::BinarySensorInitiallyOff,
public esp32_ble_tracker::ESPBTDeviceListener {
public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { address_ = address; }
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_tablet(sensor::Sensor *tablet) { tablet_ = tablet; }
@@ -29,5 +27,3 @@ class XiaomiWX08ZM final : public Component,
};
} // namespace esphome::xiaomi_wx08zm
#endif
@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
from esphome.components import ble_device_base, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -17,16 +17,16 @@ from esphome.const import (
UNIT_PERCENT,
)
AUTO_LOAD = ["xiaomi_ble"]
AUTO_LOAD = ["ble_device_base", "xiaomi_ble"]
CODEOWNERS = ["@medusalix"]
DEPENDENCIES = ["esp32_ble_tracker"]
xiaomi_xmwsdj04mmc_ns = cg.esphome_ns.namespace("xiaomi_xmwsdj04mmc")
XiaomiXMWSDJ04MMC = xiaomi_xmwsdj04mmc_ns.class_(
"XiaomiXMWSDJ04MMC", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
"XiaomiXMWSDJ04MMC", ble_device_base.ESPBTDeviceListener, cg.Component
)
CONFIG_SCHEMA = (
CONFIG_SCHEMA = cv.All(
ble_device_base.rename_legacy_hub_id("xiaomi_xmwsdj04mmc"),
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XiaomiXMWSDJ04MMC),
@@ -53,15 +53,15 @@ CONFIG_SCHEMA = (
),
}
)
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA)
.extend(ble_device_base.BLE_DEVICE_SCHEMA),
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await esp32_ble_tracker.register_ble_device(var, config)
await ble_device_base.register_ble_device(var, config)
cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex))
cg.add(var.set_bindkey(config[CONF_BINDKEY]))
@@ -2,8 +2,6 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_xmwsdj04mmc {
static const char *const TAG = "xiaomi_xmwsdj04mmc";
@@ -21,7 +19,7 @@ void XiaomiXMWSDJ04MMC::dump_config() {
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
}
bool XiaomiXMWSDJ04MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
bool XiaomiXMWSDJ04MMC::parse_device(const ble_device_base::ESPBTDevice &device) {
if (device.address_uint64() != this->address_) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
@@ -69,5 +67,3 @@ bool XiaomiXMWSDJ04MMC::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
void XiaomiXMWSDJ04MMC::set_bindkey(const char *bindkey) { parse_hex(bindkey, this->bindkey_, sizeof(this->bindkey_)); }
} // namespace esphome::xiaomi_xmwsdj04mmc
#endif
@@ -2,19 +2,17 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/components/ble_device_base/ble_device.h"
#include "esphome/components/xiaomi_ble/xiaomi_ble.h"
#ifdef USE_ESP32
namespace esphome::xiaomi_xmwsdj04mmc {
class XiaomiXMWSDJ04MMC final : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
class XiaomiXMWSDJ04MMC final : public Component, public ble_device_base::ESPBTDeviceListener {
public:
void set_address(uint64_t address) { this->address_ = address; }
void set_bindkey(const char *bindkey);
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_device(const ble_device_base::ESPBTDevice &device) override;
void dump_config() override;
void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; }
@@ -30,5 +28,3 @@ class XiaomiXMWSDJ04MMC final : public Component, public esp32_ble_tracker::ESPB
};
} // namespace esphome::xiaomi_xmwsdj04mmc
#endif
@@ -0,0 +1,39 @@
"""Tests for modbus configuration validation."""
import pytest
from esphome import config_validation as cv
from esphome.components import modbus
from esphome.components.modbus import CONF_MODBUS_ID, _validate_server_address
from esphome.const import CONF_ADDRESS
def test_server_address_accepts_valid_unit_address() -> None:
# A normal unit address (1-247) is accepted and returned as an int.
assert _validate_server_address(1) == 1
assert _validate_server_address(247) == 247
def test_server_address_accepts_hex_string() -> None:
# hex_uint8_t parses hex strings, and the validator returns the parsed int.
assert _validate_server_address("0x10") == 0x10
def test_server_address_zero_rejected() -> None:
# Address 0 is the Modbus broadcast address and cannot identify a server device.
with pytest.raises(cv.Invalid, match="broadcast address"):
_validate_server_address(0)
def test_server_schema_rejects_address_zero() -> None:
# The server-role schema wires in _validate_server_address, so address 0 is rejected there too.
schema = modbus.modbus_device_schema(0x01, role="server")
with pytest.raises(cv.Invalid, match="broadcast address"):
schema({CONF_MODBUS_ID: "hub", CONF_ADDRESS: 0})
def test_client_schema_still_accepts_address_zero() -> None:
# Not rejected for clients today, but not supported either: a client broadcast gets no reply and
# stalls the hub for the full send-wait.
schema = modbus.modbus_device_schema(0x01)
assert schema({CONF_MODBUS_ID: "hub", CONF_ADDRESS: 0})[CONF_ADDRESS] == 0
@@ -0,0 +1,276 @@
#include <gtest/gtest.h>
#include <cstdint>
#include <optional>
#include <vector>
#include "common.h"
#include "esphome/components/modbus/modbus.h"
namespace esphome::modbus {
namespace {
// A server device that records the writes the hub routes to it.
class RecordingDevice : public ModbusServerDevice {
public:
explicit RecordingDevice(uint8_t address) { this->set_address(address); }
ResponseStatus on_write_registers(uint16_t start_address, const RegisterValues &registers) override {
this->write_count++;
this->last_start_address = start_address;
this->last_values.assign(registers.begin(), registers.end());
return std::nullopt; // return value is ignored for broadcasts, which are never answered
}
int write_count{0};
uint16_t last_start_address{0};
std::vector<uint16_t> last_values;
};
// A server device that rejects every write, to exercise the broadcast dispatch loop's rejection branch.
class RejectingDevice : public ModbusServerDevice {
public:
explicit RejectingDevice(uint8_t address) { this->set_address(address); }
ResponseStatus on_write_registers(uint16_t start_address, const RegisterValues &registers) override {
this->write_count++;
return ExceptionCode::ILLEGAL_DATA_ADDRESS;
}
int write_count{0};
};
// A UART that records every byte written so the test can assert the hub sends no reply.
class RecordingUART : public testing::NullUART {
public:
void write_array(const uint8_t *data, size_t len) override {
this->written.insert(this->written.end(), data, data + len);
}
std::vector<uint8_t> written;
};
// Drives full frames through the server hub's receive path in tests.
class TestServerHub : public ModbusServerHub {
public:
bool tx_blocked() override { return false; }
// Builds a complete client frame (address + FC + pdu + CRC) and runs the full receive-side parser
// (parse_modbus_frames), so the expecting-peer-response routing is exercised, not just the frame parser
// below it. Returns true once the buffer has fully drained.
bool run_receive_parser_for_test(uint8_t address, uint8_t function_code, const uint8_t *pdu_data,
size_t pdu_data_len) {
this->rx_buffer_.clear();
this->rx_buffer_.reserve(pdu_data_len + 4);
this->rx_buffer_.push_back(address);
this->rx_buffer_.push_back(function_code);
this->rx_buffer_.insert(this->rx_buffer_.end(), pdu_data, pdu_data + pdu_data_len);
uint16_t crc = crc16(this->rx_buffer_.data(), this->rx_buffer_.size());
this->rx_buffer_.push_back(crc & 0xFF);
this->rx_buffer_.push_back(crc >> 8);
this->parse_modbus_frames();
return this->rx_buffer_.empty();
}
};
} // namespace
// A broadcast (address 0) single-register write reaches every registered device and is not answered.
// Driven through the full receive parser (parse_modbus_frames) so the address-0 routing -- frame length,
// CRC, and client-vs-broadcast dispatch -- is exercised, not just the handler below it.
TEST(ModbusBroadcast, SingleRegisterWriteReachesAllDevicesWithoutReply) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device_a(0x02);
RecordingDevice device_b(0x03);
hub.register_device(&device_a);
hub.register_device(&device_b);
// FC 0x06 payload: start address 0x9D31, value 0x00A5 (big-endian, no address/CRC).
const uint8_t pdu_data[] = {0x9D, 0x31, 0x00, 0xA5};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data, sizeof(pdu_data)));
for (RecordingDevice *device : {&device_a, &device_b}) {
EXPECT_EQ(device->write_count, 1);
EXPECT_EQ(device->last_start_address, 0x9D31);
ASSERT_EQ(device->last_values.size(), 1u);
EXPECT_EQ(device->last_values[0], 0x00A5);
}
EXPECT_TRUE(uart.written.empty()); // broadcasts are never answered
}
// A single-register broadcast (FC 0x06) must still reach every device when the hub is mid-way through
// waiting for a peer's response. Its frame length matches a response frame, so without the address-0 guard
// in parse_modbus_frames() it would be swallowed by the response parser instead of being dispatched.
TEST(ModbusBroadcast, SingleRegisterBroadcastDispatchedWhileExpectingPeerResponse) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device_a(0x02);
RecordingDevice device_b(0x03);
hub.register_device(&device_a);
hub.register_device(&device_b);
// A unicast write addressed to an unregistered peer (0x09) leaves the hub expecting that peer's response.
const uint8_t peer_pdu[] = {0x00, 0x10, 0x00, 0x2A};
ASSERT_TRUE(hub.run_receive_parser_for_test(0x09, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), peer_pdu,
sizeof(peer_pdu)));
ASSERT_EQ(device_a.write_count, 0); // the peer request is not for our devices
ASSERT_EQ(device_b.write_count, 0);
// The broadcast that follows must still be delivered to every device, and still without a reply.
const uint8_t pdu_data[] = {0x9D, 0x31, 0x00, 0xA5};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data, sizeof(pdu_data)));
for (RecordingDevice *device : {&device_a, &device_b}) {
EXPECT_EQ(device->write_count, 1);
EXPECT_EQ(device->last_start_address, 0x9D31);
ASSERT_EQ(device->last_values.size(), 1u);
EXPECT_EQ(device->last_values[0], 0x00A5);
}
EXPECT_TRUE(uart.written.empty()); // broadcasts are never answered
}
// After dispatching a broadcast, the hub must not still expect a peer response: a following unicast FC 0x06
// to one of our own devices must be handled, not misparsed as that peer's response and dropped.
TEST(ModbusBroadcast, BroadcastClearsStalePeerExpectation) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device(0x02);
hub.register_device(&device);
// A unicast write to an unregistered peer (0x09) leaves the hub expecting that peer's response.
const uint8_t pdu_data[] = {0x00, 0x10, 0x00, 0x2A};
ASSERT_TRUE(hub.run_receive_parser_for_test(0x09, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data,
sizeof(pdu_data)));
// The broadcast that follows clears that expectation as it is dispatched.
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data, sizeof(pdu_data)));
ASSERT_EQ(device.write_count, 1);
// The next unicast FC 0x06 to our own device is handled, not swallowed by the stale expectation.
ASSERT_TRUE(hub.run_receive_parser_for_test(0x02, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data,
sizeof(pdu_data)));
EXPECT_EQ(device.write_count, 2);
}
// A broadcast multi-register write is decoded and delivered to every device, still without a reply.
TEST(ModbusBroadcast, MultipleRegisterWriteReachesAllDevicesWithoutReply) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device_a(0x02);
RecordingDevice device_b(0x03);
hub.register_device(&device_a);
hub.register_device(&device_b);
// FC 0x10 payload: start 0x9D31, quantity 2, byte count 4, values 0x0102 and 0x0304.
const uint8_t pdu_data[] = {0x9D, 0x31, 0x00, 0x02, 0x04, 0x01, 0x02, 0x03, 0x04};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_MULTIPLE_REGISTERS), pdu_data, sizeof(pdu_data)));
for (RecordingDevice *device : {&device_a, &device_b}) {
EXPECT_EQ(device->write_count, 1);
EXPECT_EQ(device->last_start_address, 0x9D31);
ASSERT_EQ(device->last_values.size(), 2u);
EXPECT_EQ(device->last_values[0], 0x0102);
EXPECT_EQ(device->last_values[1], 0x0304);
}
EXPECT_TRUE(uart.written.empty());
}
// A read broadcast is meaningless (it would need a reply), so nothing is dispatched and nothing is sent.
TEST(ModbusBroadcast, ReadFunctionCodeIsIgnoredAndProducesNoReply) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device(0x02);
hub.register_device(&device);
// FC 0x03 payload: start 0x0000, quantity 2. Reads cannot be broadcast.
const uint8_t pdu_data[] = {0x00, 0x00, 0x00, 0x02};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::READ_HOLDING_REGISTERS), pdu_data, sizeof(pdu_data)));
EXPECT_EQ(device.write_count, 0); // no device was written
EXPECT_TRUE(uart.written.empty()); // and the broadcast address is never answered
}
// An invalid broadcast write is silently dropped: no writes dispatched and no exception reply sent.
TEST(ModbusBroadcast, InvalidMultipleWriteBroadcastProducesNoWriteAndNoReply) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device_a(0x02);
RecordingDevice device_b(0x03);
hub.register_device(&device_a);
hub.register_device(&device_b);
// FC 0x10 payload: quantity 2 but byte count 2 (should be 4), so parsing fails.
const uint8_t pdu_data[] = {0x9D, 0x31, 0x00, 0x02, 0x02, 0x01, 0x02};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_MULTIPLE_REGISTERS), pdu_data, sizeof(pdu_data)));
EXPECT_EQ(device_a.write_count, 0);
EXPECT_EQ(device_b.write_count, 0);
EXPECT_TRUE(uart.written.empty());
}
// A device that rejects a broadcast write must not stop dispatch to devices registered after it, and the
// broadcast is still never answered.
TEST(ModbusBroadcast, RejectingDeviceDoesNotStopBroadcastDispatch) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RejectingDevice rejecter(0x02);
RecordingDevice device(0x03);
hub.register_device(&rejecter); // registered first, so a rejection happens before the normal device
hub.register_device(&device);
// FC 0x06 payload: start address 0x9D31, value 0x00A5 (big-endian, no address/CRC).
const uint8_t pdu_data[] = {0x9D, 0x31, 0x00, 0xA5};
ASSERT_TRUE(hub.run_receive_parser_for_test(
BROADCAST_ADDRESS, static_cast<uint8_t>(FunctionCode::WRITE_SINGLE_REGISTER), pdu_data, sizeof(pdu_data)));
EXPECT_EQ(rejecter.write_count, 1); // the rejecting device was still invoked
EXPECT_EQ(device.write_count, 1); // and dispatch continued to the device registered after it
EXPECT_EQ(device.last_start_address, 0x9D31);
ASSERT_EQ(device.last_values.size(), 1u);
EXPECT_EQ(device.last_values[0], 0x00A5);
EXPECT_TRUE(uart.written.empty()); // a broadcast is never answered, even when a device rejects
}
// A unicast out-of-range write sends exactly one exception frame on the wire.
TEST(ModbusBroadcast, UnicastOutOfRangeWriteSendsSingleExceptionFrame) {
TestServerHub hub;
RecordingUART uart;
hub.set_uart_parent(&uart);
RecordingDevice device(0x02);
hub.register_device(&device);
// FC 0x10 payload: start 0xFFFF, quantity 2, byte count 4, values valid but address range overflows.
const uint8_t pdu_data[] = {0xFF, 0xFF, 0x00, 0x02, 0x04, 0x01, 0x02, 0x03, 0x04};
ASSERT_TRUE(hub.run_receive_parser_for_test(0x02, static_cast<uint8_t>(FunctionCode::WRITE_MULTIPLE_REGISTERS),
pdu_data, sizeof(pdu_data)));
EXPECT_EQ(device.write_count, 0);
ASSERT_EQ(uart.written.size(), 5u);
EXPECT_EQ(uart.written[0], 0x02); // server address
EXPECT_EQ(uart.written[1], static_cast<uint8_t>(FunctionCode::WRITE_MULTIPLE_REGISTERS) | 0x80);
EXPECT_EQ(uart.written[2], static_cast<uint8_t>(ExceptionCode::ILLEGAL_DATA_ADDRESS));
}
} // namespace esphome::modbus
+1 -1
View File
@@ -4,7 +4,7 @@ binary_sensor:
mac_address: "12:34:56:12:34:56"
bindkey: 48403ebe2d385db8d0c187f81e62cb64
battery_level:
name: CGPR1 battery Level
name: CGPR1 Battery Level
idle_time:
name: CGPR1 Idle Time
illuminance:
+1 -1
View File
@@ -9,7 +9,7 @@ binary_sensor:
mac_address: "12:34:56:12:34:56"
bindkey: 48403ebe2d385db8d0c187f81e62cb64
battery_level:
name: CGPR1 battery Level
name: CGPR1 Battery Level
idle_time:
name: CGPR1 Idle Time
illuminance:
@@ -12,7 +12,7 @@ binary_sensor:
mac_address: "12:34:56:12:34:56"
bindkey: 48403ebe2d385db8d0c187f81e62cb64
battery_level:
name: CGPR1 battery Level
name: CGPR1 Battery Level
idle_time:
name: CGPR1 Idle Time
illuminance:
@@ -0,0 +1,13 @@
sensor:
- platform: xiaomi_hhccjcy10
mac_address: 94:2B:FF:5C:91:61
temperature:
name: Xiaomi HHCCJCY10 Temperature
moisture:
name: Xiaomi HHCCJCY10 Moisture
illuminance:
name: Xiaomi HHCCJCY10 Illuminance
conductivity:
name: Xiaomi HHCCJCY10 Conductivity
battery_level:
name: Xiaomi HHCCJCY10 Battery Level
@@ -0,0 +1,18 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_hhccjcy10
ble_hub_id: ble_tracker_hub
mac_address: 94:2B:FF:5C:91:61
temperature:
name: Xiaomi HHCCJCY10 Temperature
moisture:
name: Xiaomi HHCCJCY10 Moisture
illuminance:
name: Xiaomi HHCCJCY10 Illuminance
conductivity:
name: Xiaomi HHCCJCY10 Conductivity
battery_level:
name: Xiaomi HHCCJCY10 Battery Level
@@ -0,0 +1,3 @@
packages:
ble: !include ../../test_build_components/common/ble/esp32-idf.yaml
xiaomi_hhccjcy10: !include common.yaml
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_hhccjcy10: !include common-ln.yaml
@@ -0,0 +1,26 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_hhccjcy10
ble_hub_id: ble_tracker_hub
mac_address: 94:2B:FF:5C:91:61
temperature:
name: Xiaomi HHCCJCY10 Temperature
moisture:
name: Xiaomi HHCCJCY10 Moisture
illuminance:
name: Xiaomi HHCCJCY10 Illuminance
conductivity:
name: Xiaomi HHCCJCY10 Conductivity
battery_level:
name: Xiaomi HHCCJCY10 Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_hhccjcy10
mac_address: 94:2B:FF:5C:91:62
temperature:
name: BK Xiaomi HHCCJCY10 Implicit Temperature
@@ -0,0 +1,7 @@
sensor:
- platform: xiaomi_hhccpot002
mac_address: 94:2B:FF:5C:91:61
moisture:
name: HHCCPOT002 Moisture
conductivity:
name: HHCCPOT002 Soil Conductivity
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_hhccpot002
ble_hub_id: ble_tracker_hub
mac_address: 94:2B:FF:5C:91:61
moisture:
name: HHCCPOT002 Moisture
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_hhccpot002: !include common-ln.yaml
@@ -0,0 +1,20 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_hhccpot002
ble_hub_id: ble_tracker_hub
mac_address: 94:2B:FF:5C:91:61
moisture:
name: HHCCPOT002 Moisture
conductivity:
name: HHCCPOT002 Soil Conductivity
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_hhccpot002
mac_address: 94:2B:FF:5C:91:62
moisture:
name: BK HHCCPOT002 Implicit Moisture
@@ -0,0 +1,11 @@
sensor:
- platform: xiaomi_jqjcy01ym
mac_address: 7A:80:8E:19:36:BA
temperature:
name: JQJCY01YM Temperature
humidity:
name: JQJCY01YM Humidity
formaldehyde:
name: JQJCY01YM Formaldehyde
battery_level:
name: JQJCY01YM Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_jqjcy01ym
ble_hub_id: ble_tracker_hub
mac_address: 7A:80:8E:19:36:BA
temperature:
name: JQJCY01YM Temperature
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_jqjcy01ym: !include common-ln.yaml
@@ -0,0 +1,24 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_jqjcy01ym
ble_hub_id: ble_tracker_hub
mac_address: 7A:80:8E:19:36:BA
temperature:
name: JQJCY01YM Temperature
humidity:
name: JQJCY01YM Humidity
formaldehyde:
name: JQJCY01YM Formaldehyde
battery_level:
name: JQJCY01YM Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_jqjcy01ym
mac_address: 7A:80:8E:19:36:BB
temperature:
name: BK JQJCY01YM Implicit Temperature
@@ -0,0 +1,9 @@
sensor:
- platform: xiaomi_lywsd02
mac_address: 3F:5B:7D:82:58:4E
temperature:
name: Xiaomi LYWSD02 Temperature
humidity:
name: Xiaomi LYWSD02 Humidity
battery_level:
name: Xiaomi LYWSD02 Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd02
ble_hub_id: ble_tracker_hub
mac_address: 3F:5B:7D:82:58:4E
temperature:
name: Xiaomi LYWSD02 Temperature
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_lywsd02: !include common-ln.yaml
@@ -0,0 +1,22 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd02
ble_hub_id: ble_tracker_hub
mac_address: 3F:5B:7D:82:58:4E
temperature:
name: Xiaomi LYWSD02 Temperature
humidity:
name: Xiaomi LYWSD02 Humidity
battery_level:
name: Xiaomi LYWSD02 Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_lywsd02
mac_address: 3F:5B:7D:82:58:4F
temperature:
name: BK Xiaomi LYWSD02 Implicit Temperature
@@ -0,0 +1,10 @@
sensor:
- platform: xiaomi_lywsd02mmc
mac_address: A4:C1:38:54:5E:18
bindkey: 2529d8e0d23150a588675cc54ad48400
temperature:
name: Xiaomi LYWSD02MMC Temperature
humidity:
name: Xiaomi LYWSD02MMC Humidity
battery_level:
name: Xiaomi LYWSD02MMC Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd02mmc
ble_hub_id: ble_tracker_hub
mac_address: A4:C1:38:54:5E:18
bindkey: 2529d8e0d23150a588675cc54ad48400
temperature:
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_lywsd02mmc: !include common-ln.yaml
@@ -0,0 +1,24 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd02mmc
ble_hub_id: ble_tracker_hub
mac_address: A4:C1:38:54:5E:18
bindkey: 2529d8e0d23150a588675cc54ad48400
temperature:
name: Xiaomi LYWSD02MMC Temperature
humidity:
name: Xiaomi LYWSD02MMC Humidity
battery_level:
name: Xiaomi LYWSD02MMC Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_lywsd02mmc
mac_address: A4:C1:38:54:5E:19
bindkey: 2529d8e0d23150a588675cc54ad48400
temperature:
name: BK Xiaomi LYWSD02MMC Implicit Temperature
@@ -0,0 +1,10 @@
sensor:
- platform: xiaomi_lywsd03mmc
mac_address: A4:C1:38:4E:16:78
bindkey: e9efaa6873f9f9c87a5e75a5f814801c
temperature:
name: Xiaomi LYWSD03MMC Temperature
humidity:
name: Xiaomi LYWSD03MMC Humidity
battery_level:
name: Xiaomi LYWSD03MMC Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd03mmc
ble_hub_id: ble_tracker_hub
mac_address: A4:C1:38:4E:16:78
bindkey: e9efaa6873f9f9c87a5e75a5f814801c
temperature:
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_lywsd03mmc: !include common-ln.yaml
@@ -0,0 +1,24 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsd03mmc
ble_hub_id: ble_tracker_hub
mac_address: A4:C1:38:4E:16:78
bindkey: e9efaa6873f9f9c87a5e75a5f814801c
temperature:
name: Xiaomi LYWSD03MMC Temperature
humidity:
name: Xiaomi LYWSD03MMC Humidity
battery_level:
name: Xiaomi LYWSD03MMC Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_lywsd03mmc
mac_address: A4:C1:38:4E:16:79
bindkey: e9efaa6873f9f9c87a5e75a5f814801c
temperature:
name: BK Xiaomi LYWSD03MMC Implicit Temperature
@@ -0,0 +1,9 @@
sensor:
- platform: xiaomi_lywsdcgq
mac_address: 7A:80:8E:19:36:BA
temperature:
name: Xiaomi LYWSDCGQ Temperature
humidity:
name: Xiaomi LYWSDCGQ Humidity
battery_level:
name: Xiaomi LYWSDCGQ Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsdcgq
ble_hub_id: ble_tracker_hub
mac_address: 7A:80:8E:19:36:BA
temperature:
name: Xiaomi LYWSDCGQ Temperature
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_lywsdcgq: !include common-ln.yaml
@@ -0,0 +1,22 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_lywsdcgq
ble_hub_id: ble_tracker_hub
mac_address: 7A:80:8E:19:36:BA
temperature:
name: Xiaomi LYWSDCGQ Temperature
humidity:
name: Xiaomi LYWSDCGQ Humidity
battery_level:
name: Xiaomi LYWSDCGQ Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_lywsdcgq
mac_address: 7A:80:8E:19:36:BB
temperature:
name: BK Xiaomi LYWSDCGQ Implicit Temperature
@@ -0,0 +1,9 @@
sensor:
- platform: xiaomi_mhoc303
mac_address: E7:50:59:32:A0:1C
temperature:
name: MHO-C303 Temperature
humidity:
name: MHO-C303 Humidity
battery_level:
name: MHO-C303 Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mhoc303
ble_hub_id: ble_tracker_hub
mac_address: E7:50:59:32:A0:1C
temperature:
name: MHO-C303 Temperature
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_mhoc303: !include common-ln.yaml
@@ -0,0 +1,22 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mhoc303
ble_hub_id: ble_tracker_hub
mac_address: E7:50:59:32:A0:1C
temperature:
name: MHO-C303 Temperature
humidity:
name: MHO-C303 Humidity
battery_level:
name: MHO-C303 Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_mhoc303
mac_address: E7:50:59:32:A0:1D
temperature:
name: BK MHO-C303 Implicit Temperature
@@ -0,0 +1,10 @@
sensor:
- platform: xiaomi_mhoc401
mac_address: E7:50:59:32:A0:1C
bindkey: eef418daf699a0c188f3bfd17e4565d9
temperature:
name: MHO-C401 Temperature
humidity:
name: MHO-C401 Humidity
battery_level:
name: MHO-C401 Battery Level
+6 -3
View File
@@ -1,12 +1,15 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mhoc401
ble_hub_id: ble_tracker_hub
mac_address: E7:50:59:32:A0:1C
bindkey: "eef418daf699a0c188f3bfd17e4565d9"
temperature:
name: MHO-C303 Temperature
name: MHO-C401 Temperature
humidity:
name: MHO-C303 Humidity
name: MHO-C401 Humidity
battery_level:
name: MHO-C303 Battery Level
name: MHO-C401 Battery Level
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_mhoc401: !include common-ln.yaml
@@ -0,0 +1,24 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mhoc401
ble_hub_id: ble_tracker_hub
mac_address: E7:50:59:32:A0:1C
bindkey: "eef418daf699a0c188f3bfd17e4565d9"
temperature:
name: MHO-C401 Temperature
humidity:
name: MHO-C401 Humidity
battery_level:
name: MHO-C401 Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_mhoc401
mac_address: E7:50:59:32:A0:1D
bindkey: eef418daf699a0c188f3bfd17e4565d9
temperature:
name: BK MHO-C401 Implicit Temperature
@@ -0,0 +1,7 @@
sensor:
- platform: xiaomi_miscale
mac_address: '5C:CA:D3:70:D4:A2'
weight:
name: "Xiaomi Mi Scale Weight"
impedance:
name: "Xiaomi Mi Scale Impedance"
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_miscale
ble_hub_id: ble_tracker_hub
mac_address: '5C:CA:D3:70:D4:A2'
weight:
name: "Xiaomi Mi Scale Weight"
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_miscale: !include common-ln.yaml
@@ -0,0 +1,20 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_miscale
ble_hub_id: ble_tracker_hub
mac_address: '5C:CA:D3:70:D4:A2'
weight:
name: "Xiaomi Mi Scale Weight"
impedance:
name: "Xiaomi Mi Scale Impedance"
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_miscale
mac_address: '5C:CA:D3:70:D4:A3'
weight:
name: "BK Xiaomi Mi Scale Implicit Weight"
@@ -0,0 +1,11 @@
binary_sensor:
- platform: xiaomi_mjyd02yla
name: MJYD02YL-A Motion
mac_address: 50:EC:50:CD:32:02
bindkey: 48403ebe2d385db8d0c187f81e62cb64
idle_time:
name: MJYD02YL-A Idle Time
light:
name: MJYD02YL-A Light Status
battery_level:
name: MJYD02YL-A Battery Level
@@ -1,7 +1,10 @@
esp32_ble_tracker:
id: ble_tracker_hub
binary_sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mjyd02yla
ble_hub_id: ble_tracker_hub
name: MJYD02YL-A Motion
mac_address: 50:EC:50:CD:32:02
bindkey: 48403ebe2d385db8d0c187f81e62cb64
@@ -0,0 +1,3 @@
packages:
ln882h_ble_tracker: !include ../ln882h_ble_tracker/common.yaml
xiaomi_mjyd02yla: !include common-ln.yaml
@@ -0,0 +1,24 @@
# Config-only: the CI base board (generic-bk7252, BLE 4.2) cannot compile the
# BLE 5.x tracker, so this fixture proves validation (schema + neutral binding)
# on a non-esp32 platform; codegen and compilation are not exercised here.
bk72xx_ble_tracker:
id: ble_tracker_hub
binary_sensor:
# Explicit ble_hub_id: pins the neutral binding as a declared key.
- platform: xiaomi_mjyd02yla
ble_hub_id: ble_tracker_hub
name: MJYD02YL-A Motion
mac_address: 50:EC:50:CD:32:02
bindkey: 48403ebe2d385db8d0c187f81e62cb64
idle_time:
name: MJYD02YL-A Idle Time
light:
name: MJYD02YL-A Light Status
battery_level:
name: MJYD02YL-A Battery Level
# No ble_hub_id: exercises the generated binding real configs use.
- platform: xiaomi_mjyd02yla
name: BK MJYD02YL-A Implicit Motion
mac_address: 50:EC:50:CD:32:03
bindkey: 48403ebe2d385db8d0c187f81e62cb64

Some files were not shown because too many files have changed in this diff Show More