Add WIND_DIRECTION to SensorDeviceClass and NumberDeviceClass (#138714)

* Add WIND_DIRECTION to SensorDeviceClass

* Add WIND_DIRECTION to NumberDeviceClass

* Fix tests
pull/138854/head
Robert Resch 2025-02-19 12:24:22 +01:00 committed by GitHub
parent d655c51ef9
commit 97c558b694
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 69 additions and 5 deletions

View File

@ -239,6 +239,7 @@ SENSOR_DESCRIPTIONS = (
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
suggested_display_precision=0, suggested_display_precision=0,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key=TYPE_WINDGUSTMPH, key=TYPE_WINDGUSTMPH,

View File

@ -608,21 +608,25 @@ SENSOR_DESCRIPTIONS = (
key=TYPE_WINDDIR, key=TYPE_WINDDIR,
translation_key="wind_direction", translation_key="wind_direction",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key=TYPE_WINDDIR_AVG10M, key=TYPE_WINDDIR_AVG10M,
translation_key="wind_direction_average_10m", translation_key="wind_direction_average_10m",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key=TYPE_WINDDIR_AVG2M, key=TYPE_WINDDIR_AVG2M,
translation_key="wind_direction_average_2m", translation_key="wind_direction_average_2m",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key=TYPE_WINDGUSTDIR, key=TYPE_WINDGUSTDIR,
translation_key="wind_gust_direction", translation_key="wind_gust_direction",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key=TYPE_WINDGUSTMPH, key=TYPE_WINDGUSTMPH,

View File

@ -92,7 +92,12 @@ def discover_sensors(topic: str, payload: dict[str, Any]) -> list[ArwnSensor] |
device_class=SensorDeviceClass.WIND_SPEED, device_class=SensorDeviceClass.WIND_SPEED,
), ),
ArwnSensor( ArwnSensor(
topic + "/dir", "Wind Direction", "direction", DEGREE, "mdi:compass" topic + "/dir",
"Wind Direction",
"direction",
DEGREE,
"mdi:compass",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
] ]
return None return None

View File

@ -169,6 +169,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
translation_key="windazimuth", translation_key="windazimuth",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="pressure", key="pressure",
@ -530,30 +531,35 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
translation_key="windazimuth_1d", translation_key="windazimuth_1d",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="windazimuth_2d", key="windazimuth_2d",
translation_key="windazimuth_2d", translation_key="windazimuth_2d",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="windazimuth_3d", key="windazimuth_3d",
translation_key="windazimuth_3d", translation_key="windazimuth_3d",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="windazimuth_4d", key="windazimuth_4d",
translation_key="windazimuth_4d", translation_key="windazimuth_4d",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="windazimuth_5d", key="windazimuth_5d",
translation_key="windazimuth_5d", translation_key="windazimuth_5d",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass-outline", icon="mdi:compass-outline",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="condition_1d", key="condition_1d",

View File

@ -65,7 +65,9 @@ ECOWITT_SENSORS_MAPPING: Final = {
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
EcoWittSensorTypes.DEGREE: SensorEntityDescription( EcoWittSensorTypes.DEGREE: SensorEntityDescription(
key="DEGREE", native_unit_of_measurement=DEGREE key="DEGREE",
native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
EcoWittSensorTypes.WATT_METERS_SQUARED: SensorEntityDescription( EcoWittSensorTypes.WATT_METERS_SQUARED: SensorEntityDescription(
key="WATT_METERS_SQUARED", key="WATT_METERS_SQUARED",

View File

@ -167,6 +167,7 @@ SENSOR_TYPES: tuple[ECSensorEntityDescription, ...] = (
translation_key="wind_bearing", translation_key="wind_bearing",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
value_fn=lambda data: data.conditions.get("wind_bearing", {}).get("value"), value_fn=lambda data: data.conditions.get("wind_bearing", {}).get("value"),
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
ECSensorEntityDescription( ECSensorEntityDescription(
key="wind_chill", key="wind_chill",

View File

@ -177,6 +177,7 @@ SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = {
"WIND_DIRECTION": SensorEntityDescription( "WIND_DIRECTION": SensorEntityDescription(
key="WIND_DIRECTION", key="WIND_DIRECTION",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
"WIND_DIRECTION_RANGE": SensorEntityDescription( "WIND_DIRECTION_RANGE": SensorEntityDescription(
key="WIND_DIRECTION_RANGE", key="WIND_DIRECTION_RANGE",

View File

@ -105,6 +105,7 @@ SENSOR_DESCRIPTIONS = {
value_fn=get_value, value_fn=get_value,
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
suggested_display_precision=2, suggested_display_precision=2,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
"WetDry": LaCrosseSensorEntityDescription( "WetDry": LaCrosseSensorEntityDescription(
key="WetDry", key="WetDry",

View File

@ -101,6 +101,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
name="Wind Bearing", name="Wind Bearing",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:weather-windy", icon="mdi:weather-windy",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
SensorEntityDescription( SensorEntityDescription(
key="rain", key="rain",

View File

@ -102,6 +102,7 @@ SENSORS: dict[str, SensorEntityDescription] = {
key="V_DIRECTION", key="V_DIRECTION",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
icon="mdi:compass", icon="mdi:compass",
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
"V_WEIGHT": SensorEntityDescription( "V_WEIGHT": SensorEntityDescription(
key="V_WEIGHT", key="V_WEIGHT",

View File

@ -11,6 +11,7 @@ from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION, CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION, CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX, LIGHT_LUX,
PERCENTAGE, PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS, SIGNAL_STRENGTH_DECIBELS,
@ -424,6 +425,12 @@ class NumberDeviceClass(StrEnum):
- USCS / imperial: `oz`, `lb` - USCS / imperial: `oz`, `lb`
""" """
WIND_DIRECTION = "wind_direction"
"""Wind direction.
Unit of measurement: `°`
"""
WIND_SPEED = "wind_speed" WIND_SPEED = "wind_speed"
"""Wind speed. """Wind speed.
@ -516,6 +523,7 @@ DEVICE_CLASS_UNITS: dict[NumberDeviceClass, set[type[StrEnum] | str | None]] = {
UnitOfVolume.LITERS, UnitOfVolume.LITERS,
}, },
NumberDeviceClass.WEIGHT: set(UnitOfMass), NumberDeviceClass.WEIGHT: set(UnitOfMass),
NumberDeviceClass.WIND_DIRECTION: {DEGREE},
NumberDeviceClass.WIND_SPEED: set(UnitOfSpeed), NumberDeviceClass.WIND_SPEED: set(UnitOfSpeed),
} }

View File

@ -150,6 +150,9 @@
"weight": { "weight": {
"default": "mdi:weight" "default": "mdi:weight"
}, },
"wind_direction": {
"default": "mdi:compass-rose"
},
"wind_speed": { "wind_speed": {
"default": "mdi:weather-windy" "default": "mdi:weather-windy"
} }

View File

@ -169,6 +169,9 @@
"weight": { "weight": {
"name": "[%key:component::sensor::entity_component::weight::name%]" "name": "[%key:component::sensor::entity_component::weight::name%]"
}, },
"wind_direction": {
"name": "[%key:component::sensor::entity_component::wind_direction::name%]"
},
"wind_speed": { "wind_speed": {
"name": "[%key:component::sensor::entity_component::wind_speed::name%]" "name": "[%key:component::sensor::entity_component::wind_speed::name%]"
} }

View File

@ -114,6 +114,7 @@ SENSOR_TYPES: tuple[NWSSensorEntityDescription, ...] = (
icon="mdi:compass-rose", icon="mdi:compass-rose",
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
unit_convert=DEGREE, unit_convert=DEGREE,
device_class=SensorDeviceClass.WIND_DIRECTION,
), ),
NWSSensorEntityDescription( NWSSensorEntityDescription(
key="barometricPressure", key="barometricPressure",

View File

@ -11,6 +11,7 @@ from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION, CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION, CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX, LIGHT_LUX,
PERCENTAGE, PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS, SIGNAL_STRENGTH_DECIBELS,
@ -454,6 +455,12 @@ class SensorDeviceClass(StrEnum):
- USCS / imperial: `oz`, `lb` - USCS / imperial: `oz`, `lb`
""" """
WIND_DIRECTION = "wind_direction"
"""Wind direction.
Unit of measurement: `°`
"""
WIND_SPEED = "wind_speed" WIND_SPEED = "wind_speed"
"""Wind speed. """Wind speed.
@ -612,6 +619,7 @@ DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = {
UnitOfVolume.LITERS, UnitOfVolume.LITERS,
}, },
SensorDeviceClass.WEIGHT: set(UnitOfMass), SensorDeviceClass.WEIGHT: set(UnitOfMass),
SensorDeviceClass.WIND_DIRECTION: {DEGREE},
SensorDeviceClass.WIND_SPEED: set(UnitOfSpeed), SensorDeviceClass.WIND_SPEED: set(UnitOfSpeed),
} }
@ -683,5 +691,6 @@ DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = {
SensorStateClass.TOTAL, SensorStateClass.TOTAL,
SensorStateClass.TOTAL_INCREASING, SensorStateClass.TOTAL_INCREASING,
}, },
SensorDeviceClass.WIND_DIRECTION: set(),
SensorDeviceClass.WIND_SPEED: {SensorStateClass.MEASUREMENT}, SensorDeviceClass.WIND_SPEED: {SensorStateClass.MEASUREMENT},
} }

View File

@ -83,6 +83,7 @@ CONF_IS_VOLUME = "is_volume"
CONF_IS_VOLUME_FLOW_RATE = "is_volume_flow_rate" CONF_IS_VOLUME_FLOW_RATE = "is_volume_flow_rate"
CONF_IS_WATER = "is_water" CONF_IS_WATER = "is_water"
CONF_IS_WEIGHT = "is_weight" CONF_IS_WEIGHT = "is_weight"
CONF_IS_WIND_DIRECTION = "is_wind_direction"
CONF_IS_WIND_SPEED = "is_wind_speed" CONF_IS_WIND_SPEED = "is_wind_speed"
ENTITY_CONDITIONS = { ENTITY_CONDITIONS = {
@ -145,6 +146,7 @@ ENTITY_CONDITIONS = {
SensorDeviceClass.VOLUME_FLOW_RATE: [{CONF_TYPE: CONF_IS_VOLUME_FLOW_RATE}], SensorDeviceClass.VOLUME_FLOW_RATE: [{CONF_TYPE: CONF_IS_VOLUME_FLOW_RATE}],
SensorDeviceClass.WATER: [{CONF_TYPE: CONF_IS_WATER}], SensorDeviceClass.WATER: [{CONF_TYPE: CONF_IS_WATER}],
SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_IS_WEIGHT}], SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_IS_WEIGHT}],
SensorDeviceClass.WIND_DIRECTION: [{CONF_TYPE: CONF_IS_WIND_DIRECTION}],
SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_IS_WIND_SPEED}], SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_IS_WIND_SPEED}],
DEVICE_CLASS_NONE: [{CONF_TYPE: CONF_IS_VALUE}], DEVICE_CLASS_NONE: [{CONF_TYPE: CONF_IS_VALUE}],
} }
@ -204,6 +206,7 @@ CONDITION_SCHEMA = vol.All(
CONF_IS_VOLUME_FLOW_RATE, CONF_IS_VOLUME_FLOW_RATE,
CONF_IS_WATER, CONF_IS_WATER,
CONF_IS_WEIGHT, CONF_IS_WEIGHT,
CONF_IS_WIND_DIRECTION,
CONF_IS_WIND_SPEED, CONF_IS_WIND_SPEED,
CONF_IS_VALUE, CONF_IS_VALUE,
] ]

View File

@ -82,6 +82,7 @@ CONF_VOLUME = "volume"
CONF_VOLUME_FLOW_RATE = "volume_flow_rate" CONF_VOLUME_FLOW_RATE = "volume_flow_rate"
CONF_WATER = "water" CONF_WATER = "water"
CONF_WEIGHT = "weight" CONF_WEIGHT = "weight"
CONF_WIND_DIRECTION = "wind_direction"
CONF_WIND_SPEED = "wind_speed" CONF_WIND_SPEED = "wind_speed"
ENTITY_TRIGGERS = { ENTITY_TRIGGERS = {
@ -144,6 +145,7 @@ ENTITY_TRIGGERS = {
SensorDeviceClass.VOLUME_FLOW_RATE: [{CONF_TYPE: CONF_VOLUME_FLOW_RATE}], SensorDeviceClass.VOLUME_FLOW_RATE: [{CONF_TYPE: CONF_VOLUME_FLOW_RATE}],
SensorDeviceClass.WATER: [{CONF_TYPE: CONF_WATER}], SensorDeviceClass.WATER: [{CONF_TYPE: CONF_WATER}],
SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_WEIGHT}], SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_WEIGHT}],
SensorDeviceClass.WIND_DIRECTION: [{CONF_TYPE: CONF_WIND_DIRECTION}],
SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_WIND_SPEED}], SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_WIND_SPEED}],
DEVICE_CLASS_NONE: [{CONF_TYPE: CONF_VALUE}], DEVICE_CLASS_NONE: [{CONF_TYPE: CONF_VALUE}],
} }
@ -204,6 +206,7 @@ TRIGGER_SCHEMA = vol.All(
CONF_VOLUME_FLOW_RATE, CONF_VOLUME_FLOW_RATE,
CONF_WATER, CONF_WATER,
CONF_WEIGHT, CONF_WEIGHT,
CONF_WIND_DIRECTION,
CONF_WIND_SPEED, CONF_WIND_SPEED,
CONF_VALUE, CONF_VALUE,
] ]

View File

@ -156,6 +156,9 @@
"weight": { "weight": {
"default": "mdi:weight" "default": "mdi:weight"
}, },
"wind_direction": {
"default": "mdi:compass-rose"
},
"wind_speed": { "wind_speed": {
"default": "mdi:weather-windy" "default": "mdi:weather-windy"
} }

View File

@ -52,6 +52,7 @@
"is_volume_flow_rate": "Current {entity_name} volume flow rate", "is_volume_flow_rate": "Current {entity_name} volume flow rate",
"is_water": "Current {entity_name} water", "is_water": "Current {entity_name} water",
"is_weight": "Current {entity_name} weight", "is_weight": "Current {entity_name} weight",
"is_wind_direction": "Current {entity_name} wind direction",
"is_wind_speed": "Current {entity_name} wind speed" "is_wind_speed": "Current {entity_name} wind speed"
}, },
"trigger_type": { "trigger_type": {
@ -105,6 +106,7 @@
"volume_flow_rate": "{entity_name} volume flow rate changes", "volume_flow_rate": "{entity_name} volume flow rate changes",
"water": "{entity_name} water changes", "water": "{entity_name} water changes",
"weight": "{entity_name} weight changes", "weight": "{entity_name} weight changes",
"wind_direction": "{entity_name} wind direction changes",
"wind_speed": "{entity_name} wind speed changes" "wind_speed": "{entity_name} wind speed changes"
}, },
"extra_fields": { "extra_fields": {
@ -299,6 +301,9 @@
"weight": { "weight": {
"name": "Weight" "name": "Weight"
}, },
"wind_direction": {
"name": "Wind direction"
},
"wind_speed": { "wind_speed": {
"name": "Wind speed" "name": "Wind speed"
} }

View File

@ -836,7 +836,7 @@
'suggested_display_precision': 0, 'suggested_display_precision': 0,
}), }),
}), }),
'original_device_class': None, 'original_device_class': <SensorDeviceClass.WIND_DIRECTION: 'wind_direction'>,
'original_icon': None, 'original_icon': None,
'original_name': 'Wind direction', 'original_name': 'Wind direction',
'platform': 'ambient_network', 'platform': 'ambient_network',
@ -851,6 +851,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'attribution': 'Data provided by ambientnetwork.net', 'attribution': 'Data provided by ambientnetwork.net',
'device_class': 'wind_direction',
'friendly_name': 'Station A Wind direction', 'friendly_name': 'Station A Wind direction',
'last_measured': HAFakeDatetime(2023, 11, 8, 12, 12, 0, 914000, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific')), 'last_measured': HAFakeDatetime(2023, 11, 8, 12, 12, 0, 914000, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific')),
'unit_of_measurement': '°', 'unit_of_measurement': '°',
@ -1820,7 +1821,7 @@
'suggested_display_precision': 0, 'suggested_display_precision': 0,
}), }),
}), }),
'original_device_class': None, 'original_device_class': <SensorDeviceClass.WIND_DIRECTION: 'wind_direction'>,
'original_icon': None, 'original_icon': None,
'original_name': 'Wind direction', 'original_name': 'Wind direction',
'platform': 'ambient_network', 'platform': 'ambient_network',
@ -1835,6 +1836,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'attribution': 'Data provided by ambientnetwork.net', 'attribution': 'Data provided by ambientnetwork.net',
'device_class': 'wind_direction',
'friendly_name': 'Station C Wind direction', 'friendly_name': 'Station C Wind direction',
'last_measured': HAFakeDatetime(2024, 6, 6, 8, 28, 3, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific')), 'last_measured': HAFakeDatetime(2024, 6, 6, 8, 28, 3, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific')),
'unit_of_measurement': '°', 'unit_of_measurement': '°',
@ -2741,7 +2743,7 @@
'suggested_display_precision': 0, 'suggested_display_precision': 0,
}), }),
}), }),
'original_device_class': None, 'original_device_class': <SensorDeviceClass.WIND_DIRECTION: 'wind_direction'>,
'original_icon': None, 'original_icon': None,
'original_name': 'Wind direction', 'original_name': 'Wind direction',
'platform': 'ambient_network', 'platform': 'ambient_network',
@ -2756,6 +2758,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'attribution': 'Data provided by ambientnetwork.net', 'attribution': 'Data provided by ambientnetwork.net',
'device_class': 'wind_direction',
'friendly_name': 'Station D Wind direction', 'friendly_name': 'Station D Wind direction',
'unit_of_measurement': '°', 'unit_of_measurement': '°',
}), }),