mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 10:08:40 +00:00
[zigbee] Add sensor support on esp32 (#16026)
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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<typename T> void set_attr(const T &value);
|
||||
uint8_t attr_type() { return attr_type_; }
|
||||
void set_report(bool force);
|
||||
#ifdef USE_SENSOR
|
||||
template<typename T> void connect(sensor::Sensor *sensor);
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
template<typename T> void connect(binary_sensor::BinarySensor *sensor);
|
||||
#endif
|
||||
@@ -78,6 +84,11 @@ template<typename T> void ZigbeeAttribute::set_attr(const T &value) {
|
||||
this->enable_loop();
|
||||
}
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
template<typename T> 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<typename T> void ZigbeeAttribute::connect(binary_sensor::BinarySensor *sensor) {
|
||||
sensor->add_on_state_callback([this](bool value) { this->set_attr((T) (this->scale_ * value)); });
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user