Add explicit unit mapping for zwave_js meters and sensors (#59659)
* Add explicit unit mapping for zwave_js meters and sensors * review comment * fix * alternate approach
This commit is contained in:
parent
5ae311b111
commit
edd068d6eb
3 changed files with 261 additions and 66 deletions
|
@ -11,6 +11,13 @@ from zwave_js_server.const.command_class.meter import (
|
||||||
ENERGY_TOTAL_INCREASING_METER_TYPES,
|
ENERGY_TOTAL_INCREASING_METER_TYPES,
|
||||||
POWER_FACTOR_METER_TYPES,
|
POWER_FACTOR_METER_TYPES,
|
||||||
POWER_METER_TYPES,
|
POWER_METER_TYPES,
|
||||||
|
UNIT_AMPERE as METER_UNIT_AMPERE,
|
||||||
|
UNIT_CUBIC_FEET,
|
||||||
|
UNIT_CUBIC_METER as METER_UNIT_CUBIC_METER,
|
||||||
|
UNIT_KILOWATT_HOUR,
|
||||||
|
UNIT_US_GALLON,
|
||||||
|
UNIT_VOLT as METER_UNIT_VOLT,
|
||||||
|
UNIT_WATT as METER_UNIT_WATT,
|
||||||
VOLTAGE_METER_TYPES,
|
VOLTAGE_METER_TYPES,
|
||||||
ElectricScale,
|
ElectricScale,
|
||||||
MeterScaleType,
|
MeterScaleType,
|
||||||
|
@ -26,16 +33,97 @@ from zwave_js_server.const.command_class.multilevel_sensor import (
|
||||||
PRESSURE_SENSORS,
|
PRESSURE_SENSORS,
|
||||||
SIGNAL_STRENGTH_SENSORS,
|
SIGNAL_STRENGTH_SENSORS,
|
||||||
TEMPERATURE_SENSORS,
|
TEMPERATURE_SENSORS,
|
||||||
|
UNIT_AMPERE as SENSOR_UNIT_AMPERE,
|
||||||
|
UNIT_BTU_H,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
UNIT_CENTIMETER,
|
||||||
|
UNIT_CUBIC_FEET_PER_MINUTE,
|
||||||
|
UNIT_CUBIC_METER as SENSOR_UNIT_CUBIC_METER,
|
||||||
|
UNIT_CUBIC_METER_PER_HOUR,
|
||||||
|
UNIT_DECIBEL,
|
||||||
|
UNIT_DEGREES,
|
||||||
|
UNIT_DENSITY,
|
||||||
|
UNIT_FAHRENHEIT,
|
||||||
|
UNIT_FEET,
|
||||||
|
UNIT_GALLONS,
|
||||||
|
UNIT_HERTZ,
|
||||||
|
UNIT_INCHES_OF_MERCURY,
|
||||||
|
UNIT_INCHES_PER_HOUR,
|
||||||
|
UNIT_KILOGRAM,
|
||||||
|
UNIT_KILOHERTZ,
|
||||||
|
UNIT_LITER,
|
||||||
|
UNIT_LUX,
|
||||||
|
UNIT_M_S,
|
||||||
|
UNIT_METER,
|
||||||
|
UNIT_MICROGRAM_PER_CUBIC_METER,
|
||||||
|
UNIT_MILLIAMPERE,
|
||||||
|
UNIT_MILLIMETER_HOUR,
|
||||||
|
UNIT_MILLIVOLT,
|
||||||
|
UNIT_MPH,
|
||||||
|
UNIT_PARTS_MILLION,
|
||||||
|
UNIT_PERCENTAGE_VALUE,
|
||||||
|
UNIT_POUND_PER_SQUARE_INCH,
|
||||||
|
UNIT_POUNDS,
|
||||||
|
UNIT_POWER_LEVEL,
|
||||||
|
UNIT_RSSI,
|
||||||
|
UNIT_SECOND,
|
||||||
|
UNIT_SYSTOLIC,
|
||||||
|
UNIT_VOLT as SENSOR_UNIT_VOLT,
|
||||||
|
UNIT_WATT as SENSOR_UNIT_WATT,
|
||||||
|
UNIT_WATT_PER_SQUARE_METER,
|
||||||
VOLTAGE_SENSORS,
|
VOLTAGE_SENSORS,
|
||||||
|
MultilevelSensorScaleType,
|
||||||
MultilevelSensorType,
|
MultilevelSensorType,
|
||||||
)
|
)
|
||||||
from zwave_js_server.model.node import Node as ZwaveNode
|
from zwave_js_server.model.node import Node as ZwaveNode
|
||||||
from zwave_js_server.model.value import Value as ZwaveValue, get_value_id
|
from zwave_js_server.model.value import Value as ZwaveValue, get_value_id
|
||||||
from zwave_js_server.util.command_class.meter import get_meter_scale_type
|
from zwave_js_server.util.command_class.meter import get_meter_scale_type
|
||||||
from zwave_js_server.util.command_class.multilevel_sensor import (
|
from zwave_js_server.util.command_class.multilevel_sensor import (
|
||||||
|
get_multilevel_sensor_scale_type,
|
||||||
get_multilevel_sensor_type,
|
get_multilevel_sensor_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
|
CONCENTRATION_PARTS_PER_MILLION,
|
||||||
|
DEGREE,
|
||||||
|
ELECTRIC_CURRENT_AMPERE,
|
||||||
|
ELECTRIC_CURRENT_MILLIAMPERE,
|
||||||
|
ELECTRIC_POTENTIAL_MILLIVOLT,
|
||||||
|
ELECTRIC_POTENTIAL_VOLT,
|
||||||
|
ENERGY_KILO_WATT_HOUR,
|
||||||
|
FREQUENCY_HERTZ,
|
||||||
|
FREQUENCY_KILOHERTZ,
|
||||||
|
IRRADIATION_WATTS_PER_SQUARE_METER,
|
||||||
|
LENGTH_CENTIMETERS,
|
||||||
|
LENGTH_FEET,
|
||||||
|
LENGTH_METERS,
|
||||||
|
LIGHT_LUX,
|
||||||
|
MASS_KILOGRAMS,
|
||||||
|
MASS_POUNDS,
|
||||||
|
PERCENTAGE,
|
||||||
|
POWER_BTU_PER_HOUR,
|
||||||
|
POWER_WATT,
|
||||||
|
PRECIPITATION_INCHES_PER_HOUR,
|
||||||
|
PRECIPITATION_MILLIMETERS_PER_HOUR,
|
||||||
|
PRESSURE_INHG,
|
||||||
|
PRESSURE_MMHG,
|
||||||
|
PRESSURE_PSI,
|
||||||
|
SIGNAL_STRENGTH_DECIBELS,
|
||||||
|
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
|
SPEED_MILES_PER_HOUR,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
TEMP_FAHRENHEIT,
|
||||||
|
TIME_SECONDS,
|
||||||
|
VOLUME_CUBIC_FEET,
|
||||||
|
VOLUME_CUBIC_METERS,
|
||||||
|
VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE,
|
||||||
|
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
|
||||||
|
VOLUME_GALLONS,
|
||||||
|
VOLUME_LITERS,
|
||||||
|
)
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ENTITY_DESC_KEY_BATTERY,
|
ENTITY_DESC_KEY_BATTERY,
|
||||||
ENTITY_DESC_KEY_CO,
|
ENTITY_DESC_KEY_CO,
|
||||||
|
@ -78,6 +166,58 @@ MULTILEVEL_SENSOR_DEVICE_CLASS_MAP: dict[str, set[MultilevelSensorType]] = {
|
||||||
ENTITY_DESC_KEY_VOLTAGE: VOLTAGE_SENSORS,
|
ENTITY_DESC_KEY_VOLTAGE: VOLTAGE_SENSORS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METER_UNIT_MAP: dict[str, set[MeterScaleType]] = {
|
||||||
|
ELECTRIC_CURRENT_AMPERE: METER_UNIT_AMPERE,
|
||||||
|
VOLUME_CUBIC_FEET: UNIT_CUBIC_FEET,
|
||||||
|
VOLUME_CUBIC_METERS: METER_UNIT_CUBIC_METER,
|
||||||
|
VOLUME_GALLONS: UNIT_US_GALLON,
|
||||||
|
ENERGY_KILO_WATT_HOUR: UNIT_KILOWATT_HOUR,
|
||||||
|
ELECTRIC_POTENTIAL_VOLT: METER_UNIT_VOLT,
|
||||||
|
POWER_WATT: METER_UNIT_WATT,
|
||||||
|
}
|
||||||
|
|
||||||
|
MULTILEVEL_SENSOR_UNIT_MAP: dict[str, set[MultilevelSensorScaleType]] = {
|
||||||
|
ELECTRIC_CURRENT_AMPERE: SENSOR_UNIT_AMPERE,
|
||||||
|
POWER_BTU_PER_HOUR: UNIT_BTU_H,
|
||||||
|
TEMP_CELSIUS: UNIT_CELSIUS,
|
||||||
|
LENGTH_CENTIMETERS: UNIT_CENTIMETER,
|
||||||
|
VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE: UNIT_CUBIC_FEET_PER_MINUTE,
|
||||||
|
VOLUME_CUBIC_METERS: SENSOR_UNIT_CUBIC_METER,
|
||||||
|
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR: UNIT_CUBIC_METER_PER_HOUR,
|
||||||
|
SIGNAL_STRENGTH_DECIBELS: UNIT_DECIBEL,
|
||||||
|
DEGREE: UNIT_DEGREES,
|
||||||
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: {
|
||||||
|
*UNIT_DENSITY,
|
||||||
|
*UNIT_MICROGRAM_PER_CUBIC_METER,
|
||||||
|
},
|
||||||
|
TEMP_FAHRENHEIT: UNIT_FAHRENHEIT,
|
||||||
|
LENGTH_FEET: UNIT_FEET,
|
||||||
|
VOLUME_GALLONS: UNIT_GALLONS,
|
||||||
|
FREQUENCY_HERTZ: UNIT_HERTZ,
|
||||||
|
PRESSURE_INHG: UNIT_INCHES_OF_MERCURY,
|
||||||
|
PRECIPITATION_INCHES_PER_HOUR: UNIT_INCHES_PER_HOUR,
|
||||||
|
MASS_KILOGRAMS: UNIT_KILOGRAM,
|
||||||
|
FREQUENCY_KILOHERTZ: UNIT_KILOHERTZ,
|
||||||
|
VOLUME_LITERS: UNIT_LITER,
|
||||||
|
LIGHT_LUX: UNIT_LUX,
|
||||||
|
LENGTH_METERS: UNIT_METER,
|
||||||
|
ELECTRIC_CURRENT_MILLIAMPERE: UNIT_MILLIAMPERE,
|
||||||
|
PRECIPITATION_MILLIMETERS_PER_HOUR: UNIT_MILLIMETER_HOUR,
|
||||||
|
ELECTRIC_POTENTIAL_MILLIVOLT: UNIT_MILLIVOLT,
|
||||||
|
SPEED_MILES_PER_HOUR: UNIT_MPH,
|
||||||
|
SPEED_METERS_PER_SECOND: UNIT_M_S,
|
||||||
|
CONCENTRATION_PARTS_PER_MILLION: UNIT_PARTS_MILLION,
|
||||||
|
PERCENTAGE: {*UNIT_PERCENTAGE_VALUE, *UNIT_RSSI},
|
||||||
|
MASS_POUNDS: UNIT_POUNDS,
|
||||||
|
PRESSURE_PSI: UNIT_POUND_PER_SQUARE_INCH,
|
||||||
|
SIGNAL_STRENGTH_DECIBELS_MILLIWATT: UNIT_POWER_LEVEL,
|
||||||
|
TIME_SECONDS: UNIT_SECOND,
|
||||||
|
PRESSURE_MMHG: UNIT_SYSTOLIC,
|
||||||
|
ELECTRIC_POTENTIAL_VOLT: SENSOR_UNIT_VOLT,
|
||||||
|
POWER_WATT: SENSOR_UNIT_WATT,
|
||||||
|
IRRADIATION_WATTS_PER_SQUARE_METER: UNIT_WATT_PER_SQUARE_METER,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ZwaveValueID:
|
class ZwaveValueID:
|
||||||
|
@ -154,10 +294,8 @@ class DynamicCurrentTempClimateDataTemplate(BaseDiscoverySchemaDataTemplate):
|
||||||
value.node, self.dependent_value
|
value.node, self.dependent_value
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
for key in self.lookup_table:
|
for key, value_id in self.lookup_table.items():
|
||||||
data["lookup_table"][key] = self._get_value_from_id(
|
data["lookup_table"][key] = self._get_value_from_id(value.node, value_id)
|
||||||
value.node, self.lookup_table[key]
|
|
||||||
)
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -183,17 +321,45 @@ class DynamicCurrentTempClimateDataTemplate(BaseDiscoverySchemaDataTemplate):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class NumericSensorDataTemplateData:
|
||||||
|
"""Class to represent returned data from NumericSensorDataTemplate."""
|
||||||
|
|
||||||
|
entity_description_key: str | None = None
|
||||||
|
unit_of_measurement: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class NumericSensorDataTemplate(BaseDiscoverySchemaDataTemplate):
|
class NumericSensorDataTemplate(BaseDiscoverySchemaDataTemplate):
|
||||||
"""Data template class for Z-Wave Sensor entities."""
|
"""Data template class for Z-Wave Sensor entities."""
|
||||||
|
|
||||||
def resolve_data(self, value: ZwaveValue) -> str | None:
|
@staticmethod
|
||||||
|
def find_key_from_matching_set(
|
||||||
|
enum_value: MultilevelSensorType | MultilevelSensorScaleType | MeterScaleType,
|
||||||
|
set_map: dict[
|
||||||
|
str, set[MultilevelSensorType | MultilevelSensorScaleType | MeterScaleType]
|
||||||
|
],
|
||||||
|
) -> str | None:
|
||||||
|
"""Find a key in a set map that matches a given enum value."""
|
||||||
|
for key, value_set in set_map.items():
|
||||||
|
for value_in_set in value_set:
|
||||||
|
# Since these are IntEnums and the different classes reuse the same
|
||||||
|
# values, we need to match the class as well
|
||||||
|
if (
|
||||||
|
value_in_set.__class__ == enum_value.__class__
|
||||||
|
and value_in_set == enum_value
|
||||||
|
):
|
||||||
|
return key
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_data(self, value: ZwaveValue) -> NumericSensorDataTemplateData:
|
||||||
"""Resolve helper class data for a discovered value."""
|
"""Resolve helper class data for a discovered value."""
|
||||||
|
|
||||||
if value.command_class == CommandClass.BATTERY:
|
if value.command_class == CommandClass.BATTERY:
|
||||||
return ENTITY_DESC_KEY_BATTERY
|
return NumericSensorDataTemplateData(ENTITY_DESC_KEY_BATTERY, PERCENTAGE)
|
||||||
|
|
||||||
if value.command_class == CommandClass.METER:
|
if value.command_class == CommandClass.METER:
|
||||||
scale_type = get_meter_scale_type(value)
|
scale_type = get_meter_scale_type(value)
|
||||||
|
unit = self.find_key_from_matching_set(scale_type, METER_UNIT_MAP)
|
||||||
# We do this because even though these are energy scales, they don't meet
|
# We do this because even though these are energy scales, they don't meet
|
||||||
# the unit requirements for the energy device class.
|
# the unit requirements for the energy device class.
|
||||||
if scale_type in (
|
if scale_type in (
|
||||||
|
@ -201,28 +367,36 @@ class NumericSensorDataTemplate(BaseDiscoverySchemaDataTemplate):
|
||||||
ElectricScale.KILOVOLT_AMPERE_HOUR,
|
ElectricScale.KILOVOLT_AMPERE_HOUR,
|
||||||
ElectricScale.KILOVOLT_AMPERE_REACTIVE_HOUR,
|
ElectricScale.KILOVOLT_AMPERE_REACTIVE_HOUR,
|
||||||
):
|
):
|
||||||
return ENTITY_DESC_KEY_TOTAL_INCREASING
|
return NumericSensorDataTemplateData(
|
||||||
|
ENTITY_DESC_KEY_TOTAL_INCREASING, unit
|
||||||
|
)
|
||||||
# We do this because even though these are power scales, they don't meet
|
# We do this because even though these are power scales, they don't meet
|
||||||
# the unit requirements for the power device class.
|
# the unit requirements for the power device class.
|
||||||
if scale_type == ElectricScale.KILOVOLT_AMPERE_REACTIVE:
|
if scale_type == ElectricScale.KILOVOLT_AMPERE_REACTIVE:
|
||||||
return ENTITY_DESC_KEY_MEASUREMENT
|
return NumericSensorDataTemplateData(ENTITY_DESC_KEY_MEASUREMENT, unit)
|
||||||
|
|
||||||
for key, scale_type_set in METER_DEVICE_CLASS_MAP.items():
|
return NumericSensorDataTemplateData(
|
||||||
if scale_type in scale_type_set:
|
self.find_key_from_matching_set(scale_type, METER_DEVICE_CLASS_MAP),
|
||||||
return key
|
unit,
|
||||||
|
)
|
||||||
|
|
||||||
if value.command_class == CommandClass.SENSOR_MULTILEVEL:
|
if value.command_class == CommandClass.SENSOR_MULTILEVEL:
|
||||||
sensor_type = get_multilevel_sensor_type(value)
|
sensor_type = get_multilevel_sensor_type(value)
|
||||||
|
scale_type = get_multilevel_sensor_scale_type(value)
|
||||||
|
unit = self.find_key_from_matching_set(
|
||||||
|
scale_type, MULTILEVEL_SENSOR_UNIT_MAP
|
||||||
|
)
|
||||||
if sensor_type == MultilevelSensorType.TARGET_TEMPERATURE:
|
if sensor_type == MultilevelSensorType.TARGET_TEMPERATURE:
|
||||||
return ENTITY_DESC_KEY_TARGET_TEMPERATURE
|
return NumericSensorDataTemplateData(
|
||||||
for (
|
ENTITY_DESC_KEY_TARGET_TEMPERATURE, unit
|
||||||
key,
|
)
|
||||||
sensor_type_set,
|
key = self.find_key_from_matching_set(
|
||||||
) in MULTILEVEL_SENSOR_DEVICE_CLASS_MAP.items():
|
sensor_type, MULTILEVEL_SENSOR_DEVICE_CLASS_MAP
|
||||||
if sensor_type in sensor_type_set:
|
)
|
||||||
return key
|
if key:
|
||||||
|
return NumericSensorDataTemplateData(key, unit)
|
||||||
|
|
||||||
return None
|
return NumericSensorDataTemplateData()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from dataclasses import dataclass
|
|
||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
|
@ -25,6 +24,9 @@ from homeassistant.components.sensor import (
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.zwave_js.discovery_data_template import (
|
||||||
|
NumericSensorDataTemplateData,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
DEVICE_CLASS_BATTERY,
|
DEVICE_CLASS_BATTERY,
|
||||||
|
@ -40,8 +42,6 @@ from homeassistant.const import (
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
DEVICE_CLASS_VOLTAGE,
|
DEVICE_CLASS_VOLTAGE,
|
||||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
TEMP_CELSIUS,
|
|
||||||
TEMP_FAHRENHEIT,
|
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
|
@ -89,98 +89,91 @@ STATUS_ICON: dict[NodeStatus, str] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
ENTITY_DESCRIPTION_KEY_MAP: dict[str, SensorEntityDescription] = {
|
||||||
class ZwaveSensorEntityDescription(SensorEntityDescription):
|
ENTITY_DESC_KEY_BATTERY: SensorEntityDescription(
|
||||||
"""Base description of a Zwave Sensor entity."""
|
|
||||||
|
|
||||||
info: ZwaveDiscoveryInfo | None = None
|
|
||||||
|
|
||||||
|
|
||||||
ENTITY_DESCRIPTION_KEY_MAP: dict[str, ZwaveSensorEntityDescription] = {
|
|
||||||
ENTITY_DESC_KEY_BATTERY: ZwaveSensorEntityDescription(
|
|
||||||
ENTITY_DESC_KEY_BATTERY,
|
ENTITY_DESC_KEY_BATTERY,
|
||||||
device_class=DEVICE_CLASS_BATTERY,
|
device_class=DEVICE_CLASS_BATTERY,
|
||||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_CURRENT: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_CURRENT: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_CURRENT,
|
ENTITY_DESC_KEY_CURRENT,
|
||||||
device_class=DEVICE_CLASS_CURRENT,
|
device_class=DEVICE_CLASS_CURRENT,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_VOLTAGE: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_VOLTAGE: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_VOLTAGE,
|
ENTITY_DESC_KEY_VOLTAGE,
|
||||||
device_class=DEVICE_CLASS_VOLTAGE,
|
device_class=DEVICE_CLASS_VOLTAGE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_ENERGY_MEASUREMENT: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_ENERGY_MEASUREMENT: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_ENERGY_MEASUREMENT,
|
ENTITY_DESC_KEY_ENERGY_MEASUREMENT,
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
device_class=DEVICE_CLASS_ENERGY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_ENERGY_TOTAL_INCREASING: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_ENERGY_TOTAL_INCREASING: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_ENERGY_TOTAL_INCREASING,
|
ENTITY_DESC_KEY_ENERGY_TOTAL_INCREASING,
|
||||||
device_class=DEVICE_CLASS_ENERGY,
|
device_class=DEVICE_CLASS_ENERGY,
|
||||||
state_class=STATE_CLASS_TOTAL_INCREASING,
|
state_class=STATE_CLASS_TOTAL_INCREASING,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_POWER: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_POWER: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_POWER,
|
ENTITY_DESC_KEY_POWER,
|
||||||
device_class=DEVICE_CLASS_POWER,
|
device_class=DEVICE_CLASS_POWER,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_POWER_FACTOR: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_POWER_FACTOR: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_POWER_FACTOR,
|
ENTITY_DESC_KEY_POWER_FACTOR,
|
||||||
device_class=DEVICE_CLASS_POWER_FACTOR,
|
device_class=DEVICE_CLASS_POWER_FACTOR,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_CO: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_CO: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_CO,
|
ENTITY_DESC_KEY_CO,
|
||||||
device_class=DEVICE_CLASS_CO,
|
device_class=DEVICE_CLASS_CO,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_CO2: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_CO2: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_CO2,
|
ENTITY_DESC_KEY_CO2,
|
||||||
device_class=DEVICE_CLASS_CO2,
|
device_class=DEVICE_CLASS_CO2,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_HUMIDITY: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_HUMIDITY: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_HUMIDITY,
|
ENTITY_DESC_KEY_HUMIDITY,
|
||||||
device_class=DEVICE_CLASS_HUMIDITY,
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_ILLUMINANCE: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_ILLUMINANCE: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_ILLUMINANCE,
|
ENTITY_DESC_KEY_ILLUMINANCE,
|
||||||
device_class=DEVICE_CLASS_ILLUMINANCE,
|
device_class=DEVICE_CLASS_ILLUMINANCE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_PRESSURE: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_PRESSURE: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_PRESSURE,
|
ENTITY_DESC_KEY_PRESSURE,
|
||||||
device_class=DEVICE_CLASS_PRESSURE,
|
device_class=DEVICE_CLASS_PRESSURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_SIGNAL_STRENGTH: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_SIGNAL_STRENGTH: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_SIGNAL_STRENGTH,
|
ENTITY_DESC_KEY_SIGNAL_STRENGTH,
|
||||||
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
|
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_TEMPERATURE: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_TEMPERATURE: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_TEMPERATURE,
|
ENTITY_DESC_KEY_TEMPERATURE,
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_TARGET_TEMPERATURE: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_TARGET_TEMPERATURE: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_TARGET_TEMPERATURE,
|
ENTITY_DESC_KEY_TARGET_TEMPERATURE,
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
state_class=None,
|
state_class=None,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_MEASUREMENT: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_MEASUREMENT: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_MEASUREMENT,
|
ENTITY_DESC_KEY_MEASUREMENT,
|
||||||
device_class=None,
|
device_class=None,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
ENTITY_DESC_KEY_TOTAL_INCREASING: ZwaveSensorEntityDescription(
|
ENTITY_DESC_KEY_TOTAL_INCREASING: SensorEntityDescription(
|
||||||
ENTITY_DESC_KEY_TOTAL_INCREASING,
|
ENTITY_DESC_KEY_TOTAL_INCREASING,
|
||||||
device_class=None,
|
device_class=None,
|
||||||
state_class=STATE_CLASS_TOTAL_INCREASING,
|
state_class=STATE_CLASS_TOTAL_INCREASING,
|
||||||
|
@ -201,25 +194,42 @@ async def async_setup_entry(
|
||||||
"""Add Z-Wave Sensor."""
|
"""Add Z-Wave Sensor."""
|
||||||
entities: list[ZWaveBaseEntity] = []
|
entities: list[ZWaveBaseEntity] = []
|
||||||
|
|
||||||
|
if info.platform_data:
|
||||||
|
data: NumericSensorDataTemplateData = info.platform_data
|
||||||
|
else:
|
||||||
|
data = NumericSensorDataTemplateData()
|
||||||
entity_description = ENTITY_DESCRIPTION_KEY_MAP.get(
|
entity_description = ENTITY_DESCRIPTION_KEY_MAP.get(
|
||||||
info.platform_data
|
data.entity_description_key or "", SensorEntityDescription("base_sensor")
|
||||||
) or ZwaveSensorEntityDescription("base_sensor")
|
)
|
||||||
entity_description.info = info
|
|
||||||
|
|
||||||
if info.platform_hint == "string_sensor":
|
if info.platform_hint == "string_sensor":
|
||||||
entities.append(ZWaveStringSensor(config_entry, client, entity_description))
|
entities.append(
|
||||||
|
ZWaveStringSensor(config_entry, client, info, entity_description)
|
||||||
|
)
|
||||||
elif info.platform_hint == "numeric_sensor":
|
elif info.platform_hint == "numeric_sensor":
|
||||||
entities.append(
|
entities.append(
|
||||||
ZWaveNumericSensor(config_entry, client, entity_description)
|
ZWaveNumericSensor(
|
||||||
|
config_entry,
|
||||||
|
client,
|
||||||
|
info,
|
||||||
|
entity_description,
|
||||||
|
data.unit_of_measurement,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
elif info.platform_hint == "list_sensor":
|
elif info.platform_hint == "list_sensor":
|
||||||
entities.append(ZWaveListSensor(config_entry, client, entity_description))
|
entities.append(
|
||||||
|
ZWaveListSensor(config_entry, client, info, entity_description)
|
||||||
|
)
|
||||||
elif info.platform_hint == "config_parameter":
|
elif info.platform_hint == "config_parameter":
|
||||||
entities.append(
|
entities.append(
|
||||||
ZWaveConfigParameterSensor(config_entry, client, entity_description)
|
ZWaveConfigParameterSensor(
|
||||||
|
config_entry, client, info, entity_description
|
||||||
|
)
|
||||||
)
|
)
|
||||||
elif info.platform_hint == "meter":
|
elif info.platform_hint == "meter":
|
||||||
entities.append(ZWaveMeterSensor(config_entry, client, entity_description))
|
entities.append(
|
||||||
|
ZWaveMeterSensor(config_entry, client, info, entity_description)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"Sensor not implemented for %s/%s",
|
"Sensor not implemented for %s/%s",
|
||||||
|
@ -269,12 +279,14 @@ class ZwaveSensorBase(ZWaveBaseEntity, SensorEntity):
|
||||||
self,
|
self,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
client: ZwaveClient,
|
client: ZwaveClient,
|
||||||
entity_description: ZwaveSensorEntityDescription,
|
info: ZwaveDiscoveryInfo,
|
||||||
|
entity_description: SensorEntityDescription,
|
||||||
|
unit_of_measurement: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a ZWaveSensorBase entity."""
|
"""Initialize a ZWaveSensorBase entity."""
|
||||||
assert entity_description.info
|
super().__init__(config_entry, client, info)
|
||||||
super().__init__(config_entry, client, entity_description.info)
|
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
|
self._attr_native_unit_of_measurement = unit_of_measurement
|
||||||
|
|
||||||
# Entity class attributes
|
# Entity class attributes
|
||||||
self._attr_force_update = True
|
self._attr_force_update = True
|
||||||
|
@ -312,12 +324,10 @@ class ZWaveNumericSensor(ZwaveSensorBase):
|
||||||
@property
|
@property
|
||||||
def native_unit_of_measurement(self) -> str | None:
|
def native_unit_of_measurement(self) -> str | None:
|
||||||
"""Return unit of measurement the value is expressed in."""
|
"""Return unit of measurement the value is expressed in."""
|
||||||
|
if self._attr_native_unit_of_measurement is not None:
|
||||||
|
return self._attr_native_unit_of_measurement
|
||||||
if self.info.primary_value.metadata.unit is None:
|
if self.info.primary_value.metadata.unit is None:
|
||||||
return None
|
return None
|
||||||
if self.info.primary_value.metadata.unit == "C":
|
|
||||||
return TEMP_CELSIUS
|
|
||||||
if self.info.primary_value.metadata.unit == "F":
|
|
||||||
return TEMP_FAHRENHEIT
|
|
||||||
|
|
||||||
return str(self.info.primary_value.metadata.unit)
|
return str(self.info.primary_value.metadata.unit)
|
||||||
|
|
||||||
|
@ -365,10 +375,14 @@ class ZWaveListSensor(ZwaveSensorBase):
|
||||||
self,
|
self,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
client: ZwaveClient,
|
client: ZwaveClient,
|
||||||
entity_description: ZwaveSensorEntityDescription,
|
info: ZwaveDiscoveryInfo,
|
||||||
|
entity_description: SensorEntityDescription,
|
||||||
|
unit_of_measurement: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a ZWaveListSensor entity."""
|
"""Initialize a ZWaveListSensor entity."""
|
||||||
super().__init__(config_entry, client, entity_description)
|
super().__init__(
|
||||||
|
config_entry, client, info, entity_description, unit_of_measurement
|
||||||
|
)
|
||||||
|
|
||||||
# Entity class attributes
|
# Entity class attributes
|
||||||
self._attr_name = self.generate_name(
|
self._attr_name = self.generate_name(
|
||||||
|
@ -405,10 +419,14 @@ class ZWaveConfigParameterSensor(ZwaveSensorBase):
|
||||||
self,
|
self,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
client: ZwaveClient,
|
client: ZwaveClient,
|
||||||
entity_description: ZwaveSensorEntityDescription,
|
info: ZwaveDiscoveryInfo,
|
||||||
|
entity_description: SensorEntityDescription,
|
||||||
|
unit_of_measurement: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a ZWaveConfigParameterSensor entity."""
|
"""Initialize a ZWaveConfigParameterSensor entity."""
|
||||||
super().__init__(config_entry, client, entity_description)
|
super().__init__(
|
||||||
|
config_entry, client, info, entity_description, unit_of_measurement
|
||||||
|
)
|
||||||
self._primary_value = cast(ConfigurationValue, self.info.primary_value)
|
self._primary_value = cast(ConfigurationValue, self.info.primary_value)
|
||||||
|
|
||||||
# Entity class attributes
|
# Entity class attributes
|
||||||
|
|
|
@ -421,6 +421,7 @@ ATTR_TEMPERATURE: Final = "temperature"
|
||||||
POWER_WATT: Final = "W"
|
POWER_WATT: Final = "W"
|
||||||
POWER_KILO_WATT: Final = "kW"
|
POWER_KILO_WATT: Final = "kW"
|
||||||
POWER_VOLT_AMPERE: Final = "VA"
|
POWER_VOLT_AMPERE: Final = "VA"
|
||||||
|
POWER_BTU_PER_HOUR: Final = "BTU/h"
|
||||||
|
|
||||||
# Energy units
|
# Energy units
|
||||||
ENERGY_WATT_HOUR: Final = "Wh"
|
ENERGY_WATT_HOUR: Final = "Wh"
|
||||||
|
@ -472,6 +473,7 @@ LENGTH_MILES: Final = "mi"
|
||||||
|
|
||||||
# Frequency units
|
# Frequency units
|
||||||
FREQUENCY_HERTZ: Final = "Hz"
|
FREQUENCY_HERTZ: Final = "Hz"
|
||||||
|
FREQUENCY_KILOHERTZ: Final = "kHz"
|
||||||
FREQUENCY_MEGAHERTZ: Final = "MHz"
|
FREQUENCY_MEGAHERTZ: Final = "MHz"
|
||||||
FREQUENCY_GIGAHERTZ: Final = "GHz"
|
FREQUENCY_GIGAHERTZ: Final = "GHz"
|
||||||
|
|
||||||
|
@ -482,6 +484,7 @@ PRESSURE_KPA: Final = "kPa"
|
||||||
PRESSURE_BAR: Final = "bar"
|
PRESSURE_BAR: Final = "bar"
|
||||||
PRESSURE_CBAR: Final = "cbar"
|
PRESSURE_CBAR: Final = "cbar"
|
||||||
PRESSURE_MBAR: Final = "mbar"
|
PRESSURE_MBAR: Final = "mbar"
|
||||||
|
PRESSURE_MMHG: Final = "mmHg"
|
||||||
PRESSURE_INHG: Final = "inHg"
|
PRESSURE_INHG: Final = "inHg"
|
||||||
PRESSURE_PSI: Final = "psi"
|
PRESSURE_PSI: Final = "psi"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue