New sensor fo Azimut now supported.
- A new constant `WIND_AZIMUT` is added to allow creating a wind direction sensor that returns a text value from `UnitOfDir` instead of just a numeric degree value. - The wind direction sensor entity now optionally creates both a numeric wind direction sensor using `WIND_DIR` and a text-based azimuth sensor using `WIND_AZIMUT`. If the numeric one is enabled, the text one will also be added. So in summary, these changes improve the usability of wind data by adding a more human-readable text version alongside the existing numeric version.pull/13/head
parent
5fdd594bae
commit
ac7284770a
|
|
@ -1,5 +1,6 @@
|
||||||
"""Constants."""
|
"""Constants."""
|
||||||
|
|
||||||
|
from enum import StrEnum
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
DOMAIN = "sws12500"
|
DOMAIN = "sws12500"
|
||||||
|
|
@ -59,6 +60,7 @@ OUTSIDE_HUMIDITY: Final = "outside_humidity"
|
||||||
WIND_SPEED: Final = "wind_speed"
|
WIND_SPEED: Final = "wind_speed"
|
||||||
WIND_GUST: Final = "wind_gust"
|
WIND_GUST: Final = "wind_gust"
|
||||||
WIND_DIR: Final = "wind_dir"
|
WIND_DIR: Final = "wind_dir"
|
||||||
|
WIND_AZIMUT: Final = "wind_azimut"
|
||||||
RAIN: Final = "rain"
|
RAIN: Final = "rain"
|
||||||
DAILY_RAIN: Final = "daily_rain"
|
DAILY_RAIN: Final = "daily_rain"
|
||||||
SOLAR_RADIATION: Final = "solar_radiation"
|
SOLAR_RADIATION: Final = "solar_radiation"
|
||||||
|
|
@ -89,3 +91,41 @@ REMAP_ITEMS: dict = {
|
||||||
|
|
||||||
DISABLED_BY_DEFAULT: Final = [CH2_TEMP, CH2_HUMIDITY]
|
DISABLED_BY_DEFAULT: Final = [CH2_TEMP, CH2_HUMIDITY]
|
||||||
|
|
||||||
|
class UnitOfDir(StrEnum):
|
||||||
|
"""Wind direrction azimut."""
|
||||||
|
|
||||||
|
NNE = "NNE"
|
||||||
|
NE = "NE"
|
||||||
|
ENE = "ENE"
|
||||||
|
E = "E"
|
||||||
|
ESE = "ESE"
|
||||||
|
SE = "SE"
|
||||||
|
SSE = "SSE"
|
||||||
|
S = "S"
|
||||||
|
SSW = "SSW"
|
||||||
|
SW = "SW"
|
||||||
|
WSW = "WSW"
|
||||||
|
W = "W"
|
||||||
|
WNW = "WNW"
|
||||||
|
NW = "NW"
|
||||||
|
NNW = "NNW"
|
||||||
|
N = "N"
|
||||||
|
|
||||||
|
AZIMUT: list[UnitOfDir] = [
|
||||||
|
UnitOfDir.NNE,
|
||||||
|
UnitOfDir.NE,
|
||||||
|
UnitOfDir.ENE,
|
||||||
|
UnitOfDir.E,
|
||||||
|
UnitOfDir.ESE,
|
||||||
|
UnitOfDir.SE,
|
||||||
|
UnitOfDir.SSE,
|
||||||
|
UnitOfDir.S,
|
||||||
|
UnitOfDir.SSW,
|
||||||
|
UnitOfDir.SW,
|
||||||
|
UnitOfDir.WSW,
|
||||||
|
UnitOfDir.W,
|
||||||
|
UnitOfDir.WNW,
|
||||||
|
UnitOfDir.NW,
|
||||||
|
UnitOfDir.NNW,
|
||||||
|
UnitOfDir.N,
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,13 @@ from .const import (
|
||||||
SENSORS_TO_LOAD,
|
SENSORS_TO_LOAD,
|
||||||
SOLAR_RADIATION,
|
SOLAR_RADIATION,
|
||||||
UV,
|
UV,
|
||||||
|
WIND_AZIMUT,
|
||||||
WIND_DIR,
|
WIND_DIR,
|
||||||
WIND_GUST,
|
WIND_GUST,
|
||||||
WIND_SPEED,
|
WIND_SPEED,
|
||||||
|
UnitOfDir,
|
||||||
)
|
)
|
||||||
|
from .utils import wind_dir_to_text
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -145,6 +148,14 @@ SENSOR_TYPES: tuple[WeatherSensorEntityDescription, ...] = (
|
||||||
translation_key=WIND_DIR,
|
translation_key=WIND_DIR,
|
||||||
value_fn=lambda data: cast(int, data),
|
value_fn=lambda data: cast(int, data),
|
||||||
),
|
),
|
||||||
|
WeatherSensorEntityDescription(
|
||||||
|
key=WIND_AZIMUT,
|
||||||
|
icon="mdi:sign-direction",
|
||||||
|
value_fn=lambda data: cast(str, wind_dir_to_text(data)),
|
||||||
|
device_class=SensorDeviceClass.ENUM,
|
||||||
|
options=list(UnitOfDir),
|
||||||
|
translation_key=WIND_AZIMUT,
|
||||||
|
),
|
||||||
WeatherSensorEntityDescription(
|
WeatherSensorEntityDescription(
|
||||||
key=RAIN,
|
key=RAIN,
|
||||||
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
|
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
|
||||||
|
|
@ -221,6 +232,8 @@ async def async_setup_entry(
|
||||||
|
|
||||||
# Check if we have some sensors to load.
|
# Check if we have some sensors to load.
|
||||||
if sensors_to_load := config_entry.options.get(SENSORS_TO_LOAD):
|
if sensors_to_load := config_entry.options.get(SENSORS_TO_LOAD):
|
||||||
|
if WIND_DIR in sensors_to_load:
|
||||||
|
sensors_to_load.append(WIND_AZIMUT)
|
||||||
sensors = [
|
sensors = [
|
||||||
WeatherSensor(hass, description, coordinator)
|
WeatherSensor(hass, description, coordinator)
|
||||||
for description in SENSOR_TYPES
|
for description in SENSOR_TYPES
|
||||||
|
|
@ -276,6 +289,10 @@ class WeatherSensor(
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> str | int | float | None:
|
def native_value(self) -> str | int | float | None:
|
||||||
"""Return value of entity."""
|
"""Return value of entity."""
|
||||||
|
|
||||||
|
if self.coordinator.data and (WIND_AZIMUT in self.entity_description.key):
|
||||||
|
return self.entity_description.value_fn(self.coordinator.data.get(WIND_DIR))
|
||||||
|
|
||||||
return self.entity_description.value_fn(self._data)
|
return self.entity_description.value_fn(self._data)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,28 @@
|
||||||
"daily_rain": { "name": "Daily precipitation" },
|
"daily_rain": { "name": "Daily precipitation" },
|
||||||
"solar_radiation": { "name": "Solar irradiance" },
|
"solar_radiation": { "name": "Solar irradiance" },
|
||||||
"ch2_temp": { "name": "Channel 2 temperature" },
|
"ch2_temp": { "name": "Channel 2 temperature" },
|
||||||
"ch2_humidity": { "name": "Channel 2 humidity" }
|
"ch2_humidity": { "name": "Channel 2 humidity" },
|
||||||
|
"wind_azimut": {
|
||||||
|
"name": "Bearing",
|
||||||
|
"state": {
|
||||||
|
"N": "N",
|
||||||
|
"NNE": "NNE",
|
||||||
|
"NE": "NE",
|
||||||
|
"ENE": "ENE",
|
||||||
|
"E": "E",
|
||||||
|
"ESE": "ESE",
|
||||||
|
"SE": "SE",
|
||||||
|
"SSE": "SSE",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SSW",
|
||||||
|
"SW": "SW",
|
||||||
|
"WSW": "WSW",
|
||||||
|
"W": "W",
|
||||||
|
"WNW": "WNW",
|
||||||
|
"NW": "NW",
|
||||||
|
"NNW": "NNW"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notify": {
|
"notify": {
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,28 @@
|
||||||
"daily_rain": { "name": "Denní úhrn srážek" },
|
"daily_rain": { "name": "Denní úhrn srážek" },
|
||||||
"solar_radiation": { "name": "Sluneční osvit" },
|
"solar_radiation": { "name": "Sluneční osvit" },
|
||||||
"ch2_temp": { "name": "Teplota senzoru 2" },
|
"ch2_temp": { "name": "Teplota senzoru 2" },
|
||||||
"ch2_humidity": { "name": "Vlhkost sensoru 2" }
|
"ch2_humidity": { "name": "Vlhkost sensoru 2" },
|
||||||
|
"wind_azimut": {
|
||||||
|
"name": "Azimut",
|
||||||
|
"state": {
|
||||||
|
"N": "S",
|
||||||
|
"NNE": "SSV",
|
||||||
|
"NE": "SV",
|
||||||
|
"ENE": "VVS",
|
||||||
|
"E": "V",
|
||||||
|
"ESE": "VVJ",
|
||||||
|
"SE": "JV",
|
||||||
|
"SSE": "JJV",
|
||||||
|
"S": "J",
|
||||||
|
"SSW": "JJZ",
|
||||||
|
"SW": "JZ",
|
||||||
|
"WSW": "JZZ",
|
||||||
|
"W": "Z",
|
||||||
|
"WNW": "ZZS",
|
||||||
|
"NW": "SZ",
|
||||||
|
"NNW": "SSZ"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notify": {
|
"notify": {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,28 @@
|
||||||
"daily_rain": { "name": "Daily precipitation" },
|
"daily_rain": { "name": "Daily precipitation" },
|
||||||
"solar_radiation": { "name": "Solar irradiance" },
|
"solar_radiation": { "name": "Solar irradiance" },
|
||||||
"ch2_temp": { "name": "Channel 2 temperature" },
|
"ch2_temp": { "name": "Channel 2 temperature" },
|
||||||
"ch2_humidity": { "name": "Channel 2 humidity" }
|
"ch2_humidity": { "name": "Channel 2 humidity" },
|
||||||
|
"wind_azimut": {
|
||||||
|
"name": "Bearing",
|
||||||
|
"state": {
|
||||||
|
"N": "N",
|
||||||
|
"NNE": "NNE",
|
||||||
|
"NE": "NE",
|
||||||
|
"ENE": "ENE",
|
||||||
|
"E": "E",
|
||||||
|
"ESE": "ESE",
|
||||||
|
"SE": "SE",
|
||||||
|
"SSE": "SSE",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SSW",
|
||||||
|
"SW": "SW",
|
||||||
|
"WSW": "WSW",
|
||||||
|
"W": "W",
|
||||||
|
"WNW": "WNW",
|
||||||
|
"NW": "NW",
|
||||||
|
"NNW": "NNW"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notify": {
|
"notify": {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.translation import async_get_translations
|
from homeassistant.helpers.translation import async_get_translations
|
||||||
|
|
||||||
from .const import DEV_DBG, REMAP_ITEMS, SENSORS_TO_LOAD
|
from .const import AZIMUT, DEV_DBG, REMAP_ITEMS, SENSORS_TO_LOAD, UnitOfDir
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -128,3 +128,16 @@ def check_disabled(
|
||||||
_LOGGER.info("Add sensor (%s) to loading queue", item)
|
_LOGGER.info("Add sensor (%s) to loading queue", item)
|
||||||
|
|
||||||
return missing_sensors if entityFound else None
|
return missing_sensors if entityFound else None
|
||||||
|
|
||||||
|
def wind_dir_to_text(deg: float) -> UnitOfDir | None:
|
||||||
|
"""Return wind direction in text representation.
|
||||||
|
|
||||||
|
Returns UnitOfDir or None
|
||||||
|
"""
|
||||||
|
|
||||||
|
if deg:
|
||||||
|
return AZIMUT[int(abs((float(deg) - 11.25) % 360) / 22.5)]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue