diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 8605b4fa1a3..a7e9d1096f7 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -36,6 +36,7 @@ from .const_zephyr import ( from .zigbee_esp32 import ( final_validate_esp32, validate_binary_sensor_esp32, + validate_sensor_esp32, zigbee_require_vfs_select, ) from .zigbee_zephyr import ( @@ -49,8 +50,7 @@ _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@luar123", "@tomaszduda23"] - -BINARY_SENSOR_SCHEMA = cv.Schema( +BASE_SCHEMA = cv.Schema( { cv.Optional(CONF_REPORT): cv.All( cv.requires_component("zigbee"), @@ -58,8 +58,9 @@ BINARY_SENSOR_SCHEMA = cv.Schema( cv.enum(REPORT, lower=True), ) } -).extend(zephyr_binary_sensor) -SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_sensor) +) +BINARY_SENSOR_SCHEMA = cv.Schema({}).extend(BASE_SCHEMA).extend(zephyr_binary_sensor) +SENSOR_SCHEMA = cv.Schema({}).extend(BASE_SCHEMA).extend(zephyr_sensor) SWITCH_SCHEMA = cv.Schema({}).extend(zephyr_switch) NUMBER_SCHEMA = cv.Schema({}).extend(zephyr_number) @@ -227,7 +228,7 @@ def validate_sensor(config: ConfigType) -> ConfigType: if "zigbee" not in CORE.loaded_integrations or config.get(CONF_INTERNAL): return config if CORE.is_esp32: - return config + return validate_sensor_esp32(config) return consume_endpoint(config) diff --git a/esphome/components/zigbee/const.py b/esphome/components/zigbee/const.py index 26ae2cc0ec4..7d0e14c67aa 100644 --- a/esphome/components/zigbee/const.py +++ b/esphome/components/zigbee/const.py @@ -1,4 +1,47 @@ +from enum import IntEnum + import esphome.codegen as cg +from esphome.const import ( + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_DURATION, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLUME_FLOW_RATE, + UNIT_AMPERE, + UNIT_CELSIUS, + UNIT_CENTIMETER, + UNIT_DECIBEL, + UNIT_HECTOPASCAL, + UNIT_HERTZ, + UNIT_HOUR, + UNIT_KELVIN, + UNIT_KILOMETER, + UNIT_KILOWATT, + UNIT_KILOWATT_HOURS, + UNIT_LITRE_PER_SECOND, + UNIT_LUX, + UNIT_METER, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_MILLIAMP, + UNIT_MILLIGRAMS_PER_CUBIC_METER, + UNIT_MILLIMETER, + UNIT_MILLISECOND, + UNIT_MILLIVOLT, + UNIT_MINUTE, + UNIT_OHM, + UNIT_PARTS_PER_BILLION, + UNIT_PARTS_PER_MILLION, + UNIT_PASCAL, + UNIT_PERCENT, + UNIT_SECOND, + UNIT_VOLT, + UNIT_WATT, + UNIT_WATT_HOURS, +) zigbee_ns = cg.esphome_ns.namespace("zigbee") ZigbeeComponent = zigbee_ns.class_("ZigbeeComponent", cg.Component) @@ -30,3 +73,73 @@ POWER_SOURCE = { } KEY_ZIGBEE = "zigbee" + +# BACnet engineering units mapping (ZCL uses BACnet unit codes) +# See: https://github.com/zigpy/zha/blob/dev/zha/application/platforms/number/bacnet.py +BACNET_UNITS = { + UNIT_CELSIUS: 62, + UNIT_KELVIN: 63, + UNIT_VOLT: 5, + UNIT_MILLIVOLT: 124, + UNIT_AMPERE: 3, + UNIT_MILLIAMP: 2, + UNIT_OHM: 4, + UNIT_WATT: 47, + UNIT_KILOWATT: 48, + UNIT_WATT_HOURS: 18, + UNIT_KILOWATT_HOURS: 19, + UNIT_PASCAL: 53, + UNIT_HECTOPASCAL: 133, + UNIT_HERTZ: 27, + UNIT_MILLIMETER: 30, + UNIT_CENTIMETER: 118, + UNIT_METER: 31, + UNIT_KILOMETER: 193, + UNIT_MILLISECOND: 159, + UNIT_SECOND: 73, + UNIT_MINUTE: 72, + UNIT_HOUR: 71, + UNIT_PARTS_PER_MILLION: 96, + UNIT_PARTS_PER_BILLION: 97, + UNIT_MICROGRAMS_PER_CUBIC_METER: 219, + UNIT_MILLIGRAMS_PER_CUBIC_METER: 218, + UNIT_LUX: 37, + UNIT_DECIBEL: 199, + UNIT_PERCENT: 98, +} +BACNET_UNIT_NO_UNITS = 95 + + +class AnalogInputType(IntEnum): + TEMP_DEGREES_C = 0x00 + RELATIVE_HUMIDITY_PERCENT = 0x01 + PRESSURE_PASCAL = 0x02 + FLOW_LITERS_PER_SEC = 0x03 + PERCENTAGE = 0x04 + PARTS_PER_MILLION = 0x05 + ROTATIONAL_SPEED_RPM = 0x06 + CURRENT_AMPS = 0x07 + FREQUENCY_HZ = 0x08 + POWER_WATTS = 0x09 + POWER_KILO_WATTS = 0x0A + ENERGY_KILO_WATT_HOURS = 0x0B + COUNT = 0x0C + ENTHALPY_KJOULES_PER_KG = 0x0D + TIME_SECONDS = 0x0E + + +ANALOG_INPUT_APPTYPE = { + (DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS): AnalogInputType.TEMP_DEGREES_C, + (DEVICE_CLASS_HUMIDITY, UNIT_PERCENT): AnalogInputType.RELATIVE_HUMIDITY_PERCENT, + (DEVICE_CLASS_PRESSURE, UNIT_PASCAL): AnalogInputType.PRESSURE_PASCAL, + ( + DEVICE_CLASS_VOLUME_FLOW_RATE, + UNIT_LITRE_PER_SECOND, + ): AnalogInputType.FLOW_LITERS_PER_SEC, + (DEVICE_CLASS_CURRENT, UNIT_AMPERE): AnalogInputType.CURRENT_AMPS, + (DEVICE_CLASS_FREQUENCY, UNIT_HERTZ): AnalogInputType.FREQUENCY_HZ, + (DEVICE_CLASS_POWER, UNIT_WATT): AnalogInputType.POWER_WATTS, + (DEVICE_CLASS_POWER, UNIT_KILOWATT): AnalogInputType.POWER_KILO_WATTS, + (DEVICE_CLASS_ENERGY, UNIT_KILOWATT_HOURS): AnalogInputType.ENERGY_KILO_WATT_HOURS, + (DEVICE_CLASS_DURATION, UNIT_SECOND): AnalogInputType.TIME_SECONDS, +} diff --git a/esphome/components/zigbee/const_esp32.py b/esphome/components/zigbee/const_esp32.py index 682638439e9..bb507320eb0 100644 --- a/esphome/components/zigbee/const_esp32.py +++ b/esphome/components/zigbee/const_esp32.py @@ -11,6 +11,7 @@ CONF_CLUSTER = "cluster" SCALE = "scale" CONF_ATTRIBUTE_ID = "attribute_id" KEY_BS_EP = "binary_sensor_ep" +KEY_SENSOR_EP = "sensor_ep" ha_standard_devices = cg.esphome_ns.enum("zb_ha_standard_devs_e") DEVICE_ID = { @@ -22,6 +23,7 @@ cluster_id = cg.esphome_ns.enum("esp_zb_zcl_cluster_id_t") CLUSTER_ID = { "BASIC": cluster_id.ESP_ZB_ZCL_CLUSTER_ID_BASIC, "BINARY_INPUT": cluster_id.ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, + "ANALOG_INPUT": cluster_id.ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, } cluster_role = cg.esphome_ns.enum("esp_zb_zcl_cluster_role_t") CLUSTER_ROLE = { @@ -32,4 +34,6 @@ ATTR_TYPE = { "BOOL": attr_type.ESP_ZB_ZCL_ATTR_TYPE_BOOL, "8BITMAP": attr_type.ESP_ZB_ZCL_ATTR_TYPE_8BITMAP, "CHAR_STRING": attr_type.ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING, + "SINGLE": attr_type.ESP_ZB_ZCL_ATTR_TYPE_SINGLE, + "DOUBLE": attr_type.ESP_ZB_ZCL_ATTR_TYPE_DOUBLE, } diff --git a/esphome/components/zigbee/zigbee_attribute_esp32.h b/esphome/components/zigbee/zigbee_attribute_esp32.h index 5a0cfc4fbd7..90a5cf8ff9b 100644 --- a/esphome/components/zigbee/zigbee_attribute_esp32.h +++ b/esphome/components/zigbee/zigbee_attribute_esp32.h @@ -12,6 +12,9 @@ #include "esp_zigbee_core.h" #include "zigbee_esp32.h" +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif @@ -42,6 +45,9 @@ class ZigbeeAttribute : public Component { template void set_attr(const T &value); uint8_t attr_type() { return attr_type_; } void set_report(bool force); +#ifdef USE_SENSOR + template void connect(sensor::Sensor *sensor); +#endif #ifdef USE_BINARY_SENSOR template void connect(binary_sensor::BinarySensor *sensor); #endif @@ -78,6 +84,11 @@ template void ZigbeeAttribute::set_attr(const T &value) { this->enable_loop(); } +#ifdef USE_SENSOR +template void ZigbeeAttribute::connect(sensor::Sensor *sensor) { + sensor->add_on_state_callback([this](float value) { this->set_attr((T) (this->scale_ * value)); }); +} +#endif #ifdef USE_BINARY_SENSOR template void ZigbeeAttribute::connect(binary_sensor::BinarySensor *sensor) { sensor->add_on_state_callback([this](bool value) { this->set_attr((T) (this->scale_ * value)); }); diff --git a/esphome/components/zigbee/zigbee_ep_esp32.py b/esphome/components/zigbee/zigbee_ep_esp32.py index 791232d4633..5dd76e99038 100644 --- a/esphome/components/zigbee/zigbee_ep_esp32.py +++ b/esphome/components/zigbee/zigbee_ep_esp32.py @@ -46,6 +46,35 @@ ep_configs: dict[str, dict[str, Any]] = { }, ], }, + "analog_input": { + DEVICE_TYPE: "CUSTOM_ATTR", + CONF_CLUSTERS: [ + { + CONF_ID: "ANALOG_INPUT", + ROLE: CLUSTER_ROLE["SERVER"], + CONF_ATTRIBUTES: [ + { + CONF_ATTRIBUTE_ID: 0x55, + CONF_TYPE: "SINGLE", + CONF_REPORT: REPORT["enable"], + CONF_DEVICE: None, + }, + { + CONF_ATTRIBUTE_ID: 0x51, + CONF_TYPE: "BOOL", + }, + { + CONF_ATTRIBUTE_ID: 0x6F, + CONF_TYPE: "8BITMAP", + }, + { + CONF_ATTRIBUTE_ID: 0x1C, + CONF_TYPE: "CHAR_STRING", + }, + ], + }, + ], + }, } diff --git a/esphome/components/zigbee/zigbee_esp32.py b/esphome/components/zigbee/zigbee_esp32.py index 9081582c7be..99238f758e8 100644 --- a/esphome/components/zigbee/zigbee_esp32.py +++ b/esphome/components/zigbee/zigbee_esp32.py @@ -16,11 +16,13 @@ import esphome.config_validation as cv from esphome.const import ( CONF_AP, CONF_DEVICE, + CONF_DEVICE_CLASS, CONF_ID, CONF_MAX_LENGTH, CONF_MODEL, CONF_NAME, CONF_TYPE, + CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, CONF_WIFI, ) @@ -29,7 +31,16 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.types import ConfigType -from .const import CONF_REPORT, CONF_ROUTER, KEY_ZIGBEE, REPORT, ZigbeeAttribute +from .const import ( + ANALOG_INPUT_APPTYPE, + BACNET_UNIT_NO_UNITS, + BACNET_UNITS, + CONF_REPORT, + CONF_ROUTER, + KEY_ZIGBEE, + REPORT, + ZigbeeAttribute, +) from .const_esp32 import ( ATTR_TYPE, CLUSTER_ID, @@ -40,6 +51,7 @@ from .const_esp32 import ( DEVICE_ID, DEVICE_TYPE, KEY_BS_EP, + KEY_SENSOR_EP, ROLE, SCALE, ) @@ -55,6 +67,10 @@ def get_c_size(bits: str, options: list[int]) -> str: def get_c_type(attr_type: str) -> Any | None: if attr_type == "BOOL": return cg.bool_ + if attr_type == "SINGLE": + return cg.float_ + if attr_type == "DOUBLE": + return cg.double if "STRING" in attr_type: return cg.std_string test = re.match(r"(^U?)(\d{1,2})(BITMAP$|BIT$|BIT_ENUM$|$)", attr_type) @@ -66,19 +82,23 @@ def get_c_type(attr_type: str) -> Any | None: def get_cv_by_type(attr_type: str) -> Any | None: if attr_type == "BOOL": return cv.boolean + if attr_type in ["SINGLE", "DOUBLE"]: + return cv.float_ if "STRING" in attr_type: return cv.string test = re.match(r"(^U?)(\d{1,2})(BITMAP$|BIT$|BIT_ENUM$|$)", attr_type) if test and test.group(2): return cv.positive_int - return None + raise cv.Invalid(f"Zigbee: type {attr_type} not supported or implemented") -def get_default_by_type(attr_type: str) -> str | bool | int: +def get_default_by_type(attr_type: str) -> str | bool | int | float: if attr_type == "CHAR_STRING": return "" if attr_type == "BOOL": return False + if attr_type in ["SINGLE", "DOUBLE"]: + return float("nan") return 0 @@ -134,9 +154,8 @@ def final_validate_esp32(config: ConfigType) -> ConfigType: return config -def validate_binary_sensor_esp32(config: ConfigType) -> ConfigType: - ep = copy.deepcopy(ep_configs["binary_input"]) - for cl in ep.get(CONF_CLUSTERS, []): +def setup_attributes(config: ConfigType, clusters: list[dict[str, Any]]) -> None: + for cl in clusters: for attr in cl[CONF_ATTRIBUTES]: if ( attr[CONF_ATTRIBUTE_ID] == 0x1C @@ -159,6 +178,41 @@ def validate_binary_sensor_esp32(config: ConfigType) -> ConfigType: else: attr[CONF_ID] = None validate_attributes(attr) + + +def validate_sensor_esp32(config: ConfigType) -> ConfigType: + ep = copy.deepcopy(ep_configs["analog_input"]) + # get application type from device class and meas unit + # if none get BACNET unit from meas unit + dev_class = config.get(CONF_DEVICE_CLASS) + unit = config.get(CONF_UNIT_OF_MEASUREMENT) + apptype = ANALOG_INPUT_APPTYPE.get((dev_class, unit)) + bacunit = BACNET_UNITS.get(unit, BACNET_UNIT_NO_UNITS) + if apptype is not None: + ep[CONF_CLUSTERS][0][CONF_ATTRIBUTES].append( + { + CONF_ATTRIBUTE_ID: 0x100, + CONF_VALUE: (apptype << 16) | 0xFFFF, + CONF_TYPE: "U32", + }, + ) + ep[CONF_CLUSTERS][0][CONF_ATTRIBUTES].append( + { + CONF_ATTRIBUTE_ID: 0x75, + CONF_VALUE: bacunit, + CONF_TYPE: "16BIT_ENUM", + }, + ) + setup_attributes(config, ep[CONF_CLUSTERS]) + zb_data = CORE.data.setdefault(KEY_ZIGBEE, {}) + sensor_ep: list[dict] = zb_data.setdefault(KEY_SENSOR_EP, []) + sensor_ep.append(ep) + return config + + +def validate_binary_sensor_esp32(config: ConfigType) -> ConfigType: + ep = copy.deepcopy(ep_configs["binary_input"]) + setup_attributes(config, ep[CONF_CLUSTERS]) zb_data = CORE.data.setdefault(KEY_ZIGBEE, {}) binary_sensor_ep: list[dict] = zb_data.setdefault(KEY_BS_EP, []) binary_sensor_ep.append(ep) @@ -254,8 +308,9 @@ async def esp32_to_code(config: ConfigType) -> None: # create endpoints zb_data = CORE.data.get(KEY_ZIGBEE, {}) + sensor_ep: list[dict] = zb_data.get(KEY_SENSOR_EP, []) binary_sensor_ep: list[dict] = zb_data.get(KEY_BS_EP, []) - ep_list = create_ep(binary_sensor_ep, config.get(CONF_ROUTER)) + ep_list = create_ep(sensor_ep + binary_sensor_ep, config.get(CONF_ROUTER)) # setup zigbee components var = cg.new_Pvariable(config[CONF_ID]) diff --git a/esphome/components/zigbee/zigbee_helpers_esp32.c b/esphome/components/zigbee/zigbee_helpers_esp32.c index 4ba71ec6098..5254818df49 100644 --- a/esphome/components/zigbee/zigbee_helpers_esp32.c +++ b/esphome/components/zigbee/zigbee_helpers_esp32.c @@ -33,6 +33,9 @@ esp_err_t esphome_zb_cluster_list_add_or_update_cluster(uint16_t cluster_id, esp case ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY: ret = esp_zb_cluster_list_add_identify_cluster(cluster_list, attr_list, role_mask); break; + case ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT: + ret = esp_zb_cluster_list_add_analog_input_cluster(cluster_list, attr_list, role_mask); + break; case ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT: ret = esp_zb_cluster_list_add_binary_input_cluster(cluster_list, attr_list, role_mask); break; @@ -49,6 +52,8 @@ esp_zb_attribute_list_t *esphome_zb_default_attr_list_create(uint16_t cluster_id return esp_zb_basic_cluster_create(NULL); case ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY: return esp_zb_identify_cluster_create(NULL); + case ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT: + return esp_zb_analog_input_cluster_create(NULL); case ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT: return esp_zb_binary_input_cluster_create(NULL); default: @@ -63,6 +68,8 @@ esp_err_t esphome_zb_cluster_add_attr(uint16_t cluster_id, esp_zb_attribute_list return esp_zb_basic_cluster_add_attr(attr_list, attr_id, value_p); case ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY: return esp_zb_identify_cluster_add_attr(attr_list, attr_id, value_p); + case ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT: + return esp_zb_analog_input_cluster_add_attr(attr_list, attr_id, value_p); case ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT: return esp_zb_binary_input_cluster_add_attr(attr_list, attr_id, value_p); default: diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index b74074e50f8..033511691cc 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -10,35 +10,6 @@ from esphome.const import ( CONF_MODEL, CONF_NAME, CONF_UNIT_OF_MEASUREMENT, - UNIT_AMPERE, - UNIT_CELSIUS, - UNIT_CENTIMETER, - UNIT_DECIBEL, - UNIT_HECTOPASCAL, - UNIT_HERTZ, - UNIT_HOUR, - UNIT_KELVIN, - UNIT_KILOMETER, - UNIT_KILOWATT, - UNIT_KILOWATT_HOURS, - UNIT_LUX, - UNIT_METER, - UNIT_MICROGRAMS_PER_CUBIC_METER, - UNIT_MILLIAMP, - UNIT_MILLIGRAMS_PER_CUBIC_METER, - UNIT_MILLIMETER, - UNIT_MILLISECOND, - UNIT_MILLIVOLT, - UNIT_MINUTE, - UNIT_OHM, - UNIT_PARTS_PER_BILLION, - UNIT_PARTS_PER_MILLION, - UNIT_PASCAL, - UNIT_PERCENT, - UNIT_SECOND, - UNIT_VOLT, - UNIT_WATT, - UNIT_WATT_HOURS, __version__, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority @@ -50,6 +21,8 @@ from esphome.cpp_generator import ( from esphome.types import ConfigType from .const import ( + BACNET_UNIT_NO_UNITS, + BACNET_UNITS, CONF_ON_JOIN, CONF_POWER_SOURCE, CONF_ROUTER, @@ -86,41 +59,6 @@ ZigbeeSensor = zigbee_ns.class_("ZigbeeSensor", cg.Component) ZigbeeSwitch = zigbee_ns.class_("ZigbeeSwitch", cg.Component) ZigbeeNumber = zigbee_ns.class_("ZigbeeNumber", cg.Component) -# BACnet engineering units mapping (ZCL uses BACnet unit codes) -# See: https://github.com/zigpy/zha/blob/dev/zha/application/platforms/number/bacnet.py -BACNET_UNITS = { - UNIT_CELSIUS: 62, - UNIT_KELVIN: 63, - UNIT_VOLT: 5, - UNIT_MILLIVOLT: 124, - UNIT_AMPERE: 3, - UNIT_MILLIAMP: 2, - UNIT_OHM: 4, - UNIT_WATT: 47, - UNIT_KILOWATT: 48, - UNIT_WATT_HOURS: 18, - UNIT_KILOWATT_HOURS: 19, - UNIT_PASCAL: 53, - UNIT_HECTOPASCAL: 133, - UNIT_HERTZ: 27, - UNIT_MILLIMETER: 30, - UNIT_CENTIMETER: 118, - UNIT_METER: 31, - UNIT_KILOMETER: 193, - UNIT_MILLISECOND: 159, - UNIT_SECOND: 73, - UNIT_MINUTE: 72, - UNIT_HOUR: 71, - UNIT_PARTS_PER_MILLION: 96, - UNIT_PARTS_PER_BILLION: 97, - UNIT_MICROGRAMS_PER_CUBIC_METER: 219, - UNIT_MILLIGRAMS_PER_CUBIC_METER: 218, - UNIT_LUX: 37, - UNIT_DECIBEL: 199, - UNIT_PERCENT: 98, -} -BACNET_UNIT_NO_UNITS = 95 - zephyr_binary_sensor = cv.Schema( { cv.OnlyWith(CONF_ZIGBEE_ID, ["nrf52", "zigbee"]): cv.use_id(ZigbeeComponent), diff --git a/esphome/const.py b/esphome/const.py index c39225fdec0..a256a10e627 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1240,6 +1240,7 @@ UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kvarh" UNIT_KILOWATT = "kW" UNIT_KILOWATT_HOURS = "kWh" UNIT_LITRE = "L" +UNIT_LITRE_PER_SECOND = "L/s" UNIT_LUX = "lx" UNIT_MEGAJOULE = "MJ" UNIT_METER = "m" diff --git a/tests/components/zigbee/common_esp32.yaml b/tests/components/zigbee/common_esp32.yaml index 4494b4081d4..94e3f3c8c04 100644 --- a/tests/components/zigbee/common_esp32.yaml +++ b/tests/components/zigbee/common_esp32.yaml @@ -1,10 +1,10 @@ +packages: + - !include common.yaml + binary_sensor: - platform: template name: "Garage Door Open 10" report: "enable" - - platform: template - name: "Garage Door Open 11" - report: "coordinator" - platform: template name: "Garage Door Open 12" report: "force"