Merge pull request #59 from schizza/wslink_sensors_add

Adds sensors for WSLink and improves data handling
pull/61/head
Lukas Svoboda 2025-03-10 08:44:11 +01:00 committed by GitHub
commit 7ca4578c0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 116 additions and 57 deletions

View File

@ -97,6 +97,10 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
self.hass, DOMAIN, f"sensor.{t_key}", key="name", category="entity"
)
for t_key in sensors
if await translations(
self.hass, DOMAIN, f"sensor.{t_key}", key="name", category="entity"
)
is not None
]
human_readable = "\n".join(translate_sensors)

View File

@ -60,6 +60,7 @@ BARO_PRESSURE: Final = "baro_pressure"
OUTSIDE_TEMP: Final = "outside_temp"
DEW_POINT: Final = "dew_point"
OUTSIDE_HUMIDITY: Final = "outside_humidity"
OUTSIDE_CONNECTION: Final = "outside_connection"
WIND_SPEED: Final = "wind_speed"
WIND_GUST: Final = "wind_gust"
WIND_DIR: Final = "wind_dir"
@ -72,10 +73,13 @@ INDOOR_HUMIDITY: Final = "indoor_humidity"
UV: Final = "uv"
CH2_TEMP: Final = "ch2_temp"
CH2_HUMIDITY: Final = "ch2_humidity"
CH2_CONNECTION: Final = "ch2_connection"
CH3_TEMP: Final = "ch3_temp"
CH3_HUMIDITY: Final = "ch3_humidity"
CH3_CONNECTION: Final = "ch3_connection"
CH4_TEMP: Final = "ch4_temp"
CH4_HUMIDITY: Final = "ch4_humidity"
CH4_CONNECTION: Final = "ch4_connection"
HEAT_INDEX: Final = "heat_index"
CHILL_INDEX: Final = "chill_index"
@ -105,19 +109,37 @@ REMAP_ITEMS: dict = {
REMAP_WSLINK_ITEMS: dict = {
"intem": INDOOR_TEMP,
"inhum": INDOOR_HUMIDITY,
"t1temp": OUTSIDE_TEMP,
"t1tem": OUTSIDE_TEMP,
"t1hum": OUTSIDE_HUMIDITY,
"t1dew": DEW_POINT,
"t1wdir": WIND_DIR,
"t1ws": WIND_SPEED,
"t1wg": WIND_GUST,
"t1wgust": WIND_GUST,
"t1rainra": RAIN,
"t1raindy": DAILY_RAIN,
"t1solrad": SOLAR_RADIATION,
"rbar": BARO_PRESSURE,
"uvi": UV
"t1uvi": UV,
"t234c1tem": CH2_TEMP,
"t234c1hum": CH2_HUMIDITY,
"t1cn": OUTSIDE_CONNECTION,
"t234c1cn": CH2_CONNECTION,
"t234c2cn": CH3_CONNECTION,
"t1chill": CHILL_INDEX,
"t1heat": HEAT_INDEX,
}
# TODO: Add more sensors
#
# 'inbat' indoor battery level (1 normal, 0 low)
# 't1rainhr' hourly rain rate in mm
# 't1rainwy' weekly rain rate in mm
# 't1rainmth': monthly rain rate in mm
# 't1rainyr': yearly rain rate in mm
# 't1bat': outdoor battery level (1 normal, 0 low)
# 't234c1bat': CH2 battery level (1 normal, 0 low) CH2 in integration is CH1 in WSLink
DISABLED_BY_DEFAULT: Final = [
CH2_TEMP,
CH2_HUMIDITY,
@ -167,4 +189,3 @@ AZIMUT: list[UnitOfDir] = [
UnitOfDir.NNW,
UnitOfDir.N,
]

View File

@ -111,16 +111,26 @@ class WeatherSensor(
def native_value(self) -> str | int | float | None:
"""Return value of entity."""
_wslink = self.coordinator.config.options.get(WSLINK)
if self.coordinator.data and (WIND_AZIMUT in self.entity_description.key):
return self.entity_description.value_fn(self.coordinator.data.get(WIND_DIR))
if self.coordinator.data and (HEAT_INDEX in self.entity_description.key):
if (
self.coordinator.data
and (HEAT_INDEX in self.entity_description.key)
and not _wslink
):
return self.entity_description.value_fn(heat_index(self.coordinator.data))
if self.coordinator.data and (CHILL_INDEX in self.entity_description.key):
if (
self.coordinator.data
and (CHILL_INDEX in self.entity_description.key)
and not _wslink
):
return self.entity_description.value_fn(chill_index(self.coordinator.data))
return self.entity_description.value_fn(self._data)
return None if self._data == "" else self.entity_description.value_fn(self._data)
@property
def suggested_entity_id(self) -> str:

View File

@ -51,7 +51,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=INDOOR_TEMP,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=INDOOR_HUMIDITY,
@ -64,12 +64,12 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
),
WeatherSensorEntityDescription(
key=OUTSIDE_TEMP,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=OUTSIDE_TEMP,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_HUMIDITY,
@ -78,7 +78,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=OUTSIDE_HUMIDITY,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=DEW_POINT,
@ -87,7 +87,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=DEW_POINT,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=BARO_PRESSURE,
@ -97,7 +97,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
suggested_unit_of_measurement=UnitOfPressure.HPA,
translation_key=BARO_PRESSURE,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=WIND_SPEED,
@ -107,7 +107,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:weather-windy",
translation_key=WIND_SPEED,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=WIND_GUST,
@ -117,7 +117,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:windsock",
translation_key=WIND_GUST,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=WIND_DIR,
@ -126,12 +126,12 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_display_precision=None,
icon="mdi:sign-direction",
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)),
value_fn=lambda data: cast("str", wind_dir_to_text(data)),
device_class=SensorDeviceClass.ENUM,
options=list(UnitOfDir),
translation_key=WIND_AZIMUT,
@ -145,7 +145,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=RAIN,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=DAILY_RAIN,
@ -156,7 +156,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=DAILY_RAIN,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=SOLAR_RADIATION,
@ -165,7 +165,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.IRRADIANCE,
icon="mdi:weather-sunny",
translation_key=SOLAR_RADIATION,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=UV,
@ -174,7 +174,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
native_unit_of_measurement=UV_INDEX,
icon="mdi:sunglasses",
translation_key=UV,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=CH2_TEMP,
@ -184,7 +184,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
icon="mdi:weather-sunny",
translation_key=CH2_TEMP,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=CH2_HUMIDITY,
@ -193,7 +193,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH2_HUMIDITY,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=CH3_TEMP,
@ -203,7 +203,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
icon="mdi:weather-sunny",
translation_key=CH3_TEMP,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=CH3_HUMIDITY,
@ -212,7 +212,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH3_HUMIDITY,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=CH4_TEMP,
@ -222,7 +222,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
icon="mdi:weather-sunny",
translation_key=CH4_TEMP,
value_fn=lambda data: cast(float, data),
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=CH4_HUMIDITY,
@ -231,7 +231,7 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH4_HUMIDITY,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=HEAT_INDEX,
@ -239,9 +239,10 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=HEAT_INDEX,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=CHILL_INDEX,
@ -252,6 +253,6 @@ SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=CHILL_INDEX,
value_fn=lambda data: cast(int, data),
value_fn=lambda data: cast("int", data),
),
)

View File

@ -176,25 +176,25 @@ SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
translation_key=UV,
value_fn=lambda data: cast("float", data),
),
# WeatherSensorEntityDescription(
# key=CH2_TEMP,
# native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
# state_class=SensorStateClass.MEASUREMENT,
# device_class=SensorDeviceClass.TEMPERATURE,
# suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
# icon="mdi:weather-sunny",
# translation_key=CH2_TEMP,
# value_fn=lambda data: cast(float, data),
# ),
# WeatherSensorEntityDescription(
# key=CH2_HUMIDITY,
# native_unit_of_measurement=PERCENTAGE,
# state_class=SensorStateClass.MEASUREMENT,
# device_class=SensorDeviceClass.HUMIDITY,
# icon="mdi:weather-sunny",
# translation_key=CH2_HUMIDITY,
# value_fn=lambda data: cast(int, data),
# ),
WeatherSensorEntityDescription(
key=CH2_TEMP,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
icon="mdi:weather-sunny",
translation_key=CH2_TEMP,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=CH2_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH2_HUMIDITY,
value_fn=lambda data: cast("int", data),
),
# WeatherSensorEntityDescription(
# key=CH3_TEMP,
# native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
@ -235,17 +235,18 @@ SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
# ),
WeatherSensorEntityDescription(
key=HEAT_INDEX,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=HEAT_INDEX,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=CHILL_INDEX,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,

View File

@ -131,9 +131,7 @@ def remap_wslink_items(entities):
def loaded_sensors(config_entry: ConfigEntry) -> list | None:
"""Get loaded sensors."""
return (
config_entry.options.get(SENSORS_TO_LOAD) or []
)
return config_entry.options.get(SENSORS_TO_LOAD) or []
def check_disabled(
@ -176,13 +174,30 @@ def wind_dir_to_text(deg: float) -> UnitOfDir | None:
return None
def heat_index(data: Any) -> UnitOfTemperature:
"""Calculate heat index from temperature."""
def fahrenheit_to_celsius(fahrenheit: float) -> float:
"""Convert Fahrenheit to Celsius."""
return (fahrenheit - 32) * 5.0 / 9.0
def celsius_to_fahrenheit(celsius: float) -> float:
"""Convert Celsius to Fahrenheit."""
return celsius * 9.0 / 5.0 + 32
def heat_index(data: Any, convert: bool = False) -> UnitOfTemperature:
"""Calculate heat index from temperature.
data: dict with temperature and humidity
convert: bool, convert recieved data from Celsius to Fahrenheit
"""
temp = float(data[OUTSIDE_TEMP])
rh = float(data[OUTSIDE_HUMIDITY])
adjustment = None
if convert:
temp = celsius_to_fahrenheit(temp)
simple = 0.5 * (temp + 61.0 + ((temp - 68.0) * 1.2) + (rh * 0.094))
if ((simple + temp) / 2) > 80:
full_index = (
@ -207,12 +222,19 @@ def heat_index(data: Any) -> UnitOfTemperature:
return simple
def chill_index(data: Any) -> UnitOfTemperature:
"""Calculate wind chill index."""
def chill_index(data: Any, convert: bool = False) -> UnitOfTemperature:
"""Calculate wind chill index from temperature and wind speed.
data: dict with temperature and wind speed
convert: bool, convert recieved data from Celsius to Fahrenheit
"""
temp = float(data[OUTSIDE_TEMP])
wind = float(data[WIND_SPEED])
if convert:
temp = celsius_to_fahrenheit(temp)
return (
round(
(