WSLink support in beta

Support for firmware 3.0 and WSLink connections.
As for now the 3.0 firmware sending data only on SSL connections.
pull/45/head
schizza 2025-02-12 13:13:46 +01:00
parent a6707b849b
commit 25bb26bb4d
11 changed files with 647 additions and 291 deletions

View File

@ -19,12 +19,15 @@ from .const import (
DOMAIN, DOMAIN,
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
WINDY_ENABLED, WINDY_ENABLED,
WSLINK,
WSLINK_URL,
) )
from .utils import ( from .utils import (
anonymize, anonymize,
check_disabled, check_disabled,
loaded_sensors, loaded_sensors,
remap_items, remap_items,
remap_wslink_items,
translated_notification, translated_notification,
translations, translations,
update_options, update_options,
@ -51,15 +54,25 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
async def recieved_data(self, webdata): async def recieved_data(self, webdata):
"""Handle incoming data query.""" """Handle incoming data query."""
_wslink = self.config_entry.data.get(WSLINK)
data = webdata.query data = webdata.query
response = None response = None
if "ID" not in data or "PASSWORD" not in data: if not _wslink and ("ID" not in data or "PASSWORD" not in data):
_LOGGER.error("Invalid request. No security data provided!") _LOGGER.error("Invalid request. No security data provided!")
raise HTTPUnauthorized raise HTTPUnauthorized
id_data = data["ID"] if _wslink and ("wsid" not in data or "wspw" not in data):
key_data = data["PASSWORD"] _LOGGER.error("Invalid request. No security data provided!")
raise HTTPUnauthorized
if _wslink:
id_data = data["wsid"]
key_data = data["wspw"]
else:
id_data = data["ID"]
key_data = data["PASSWORD"]
_id = self.config_entry.options.get(API_ID) _id = self.config_entry.options.get(API_ID)
_key = self.config_entry.options.get(API_KEY) _key = self.config_entry.options.get(API_KEY)
@ -71,7 +84,11 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
if self.config_entry.options.get(WINDY_ENABLED): if self.config_entry.options.get(WINDY_ENABLED):
response = await self.windy.push_data_to_windy(data) response = await self.windy.push_data_to_windy(data)
remaped_items = remap_items(data) remaped_items = (
remap_wslink_items(data)
if self.config_entry.options.get(WSLINK)
else remap_items(data)
)
if sensors := check_disabled(self.hass, remaped_items, self.config): if sensors := check_disabled(self.hass, remaped_items, self.config):
translate_sensors = [ translate_sensors = [
@ -98,18 +115,22 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
if self.config_entry.options.get(DEV_DBG): if self.config_entry.options.get(DEV_DBG):
_LOGGER.info("Dev log: %s", anonymize(data)) _LOGGER.info("Dev log: %s", anonymize(data))
response = response if response else "OK" response = response or "OK"
return aiohttp.web.Response(body=f"{response}", status=200) return aiohttp.web.Response(body=f"{response or 'OK'}", status=200)
def register_path( def register_path(
hass: HomeAssistant, url_path: str, coordinator: WeatherDataUpdateCoordinator hass: HomeAssistant, url_path: str, coordinator: WeatherDataUpdateCoordinator
): ):
"""Register path to handle incoming data.""" """Register path to handle incoming data."""
_wslink = hass.config_entries.async_get_entry(WSLINK)
try: try:
route = hass.http.app.router.add_route( route = hass.http.app.router.add_route(
"GET", url_path, coordinator.recieved_data "GET", url_path, coordinator.recieved_data
) )
except RuntimeError as Ex: # pylint: disable=(broad-except) except RuntimeError as Ex: # pylint: disable=(broad-except)
if ( if (
"Added route will never be executed, method GET is already registered" "Added route will never be executed, method GET is already registered"
@ -144,7 +165,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
if not register_path(hass, DEFAULT_URL, coordinator): _wslink = entry.data.get(WSLINK)
_LOGGER.info("WS Link is %s", "enbled" if _wslink else "disabled")
if not register_path(hass, DEFAULT_URL if not _wslink else WSLINK_URL, coordinator):
_LOGGER.error("Fatal: path not registered!") _LOGGER.error("Fatal: path not registered!")
raise PlatformNotReady raise PlatformNotReady

View File

@ -1,4 +1,5 @@
"""Config flow for Sencor SWS 12500 Weather Station integration.""" """Config flow for Sencor SWS 12500 Weather Station integration."""
from typing import Any from typing import Any
import voluptuous as vol import voluptuous as vol
@ -17,6 +18,7 @@ from .const import (
WINDY_API_KEY, WINDY_API_KEY,
WINDY_ENABLED, WINDY_ENABLED,
WINDY_LOGGER_ENABLED, WINDY_LOGGER_ENABLED,
WSLINK,
) )
@ -38,22 +40,30 @@ class ConfigOptionsFlowHandler(config_entries.OptionsFlow):
self.user_data: dict[str, str] = { self.user_data: dict[str, str] = {
API_ID: self.config_entry.options.get(API_ID), API_ID: self.config_entry.options.get(API_ID),
API_KEY: self.config_entry.options.get(API_KEY), API_KEY: self.config_entry.options.get(API_KEY),
WSLINK: self.config_entry.options.get(WSLINK),
DEV_DBG: self.config_entry.options.get(DEV_DBG), DEV_DBG: self.config_entry.options.get(DEV_DBG),
} }
self.windy_data: dict[str, Any] = { self.windy_data: dict[str, Any] = {
WINDY_API_KEY: self.config_entry.options.get(WINDY_API_KEY), WINDY_API_KEY: self.config_entry.options.get(WINDY_API_KEY),
WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED) if isinstance(self.config_entry.options.get(WINDY_ENABLED), bool) else False, WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED)
WINDY_LOGGER_ENABLED: self.config_entry.options.get(WINDY_LOGGER_ENABLED) if isinstance(self.config_entry.options.get(WINDY_LOGGER_ENABLED), bool) else False, if isinstance(self.config_entry.options.get(WINDY_ENABLED), bool)
else False,
WINDY_LOGGER_ENABLED: self.config_entry.options.get(WINDY_LOGGER_ENABLED)
if isinstance(self.config_entry.options.get(WINDY_LOGGER_ENABLED), bool)
else False,
} }
self.sensors: dict[str, Any] = { self.sensors: dict[str, Any] = {
SENSORS_TO_LOAD: self.config_entry.options.get(SENSORS_TO_LOAD) if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list) else [] SENSORS_TO_LOAD: self.config_entry.options.get(SENSORS_TO_LOAD)
if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list)
else []
} }
self.user_data_schema = { self.user_data_schema = {
vol.Required(API_ID, default=self.user_data[API_ID] or ""): str, vol.Required(API_ID, default=self.user_data[API_ID] or ""): str,
vol.Required(API_KEY, default=self.user_data[API_KEY] or ""): str, vol.Required(API_KEY, default=self.user_data[API_KEY] or ""): str,
vol.Optional(WSLINK, default=self.user_data[WSLINK]): bool,
vol.Optional(DEV_DBG, default=self.user_data[DEV_DBG]): bool, vol.Optional(DEV_DBG, default=self.user_data[DEV_DBG]): bool,
} }
@ -93,7 +103,7 @@ class ConfigOptionsFlowHandler(config_entries.OptionsFlow):
# retain windy data # retain windy data
user_input.update(self.windy_data) user_input.update(self.windy_data)
#retain sensors # retain sensors
user_input.update(self.sensors) user_input.update(self.sensors)
return self.async_create_entry(title=DOMAIN, data=user_input) return self.async_create_entry(title=DOMAIN, data=user_input)
@ -133,7 +143,7 @@ class ConfigOptionsFlowHandler(config_entries.OptionsFlow):
# retain user_data # retain user_data
user_input.update(self.user_data) user_input.update(self.user_data)
#retain senors # retain senors
user_input.update(self.sensors) user_input.update(self.sensors)
return self.async_create_entry(title=DOMAIN, data=user_input) return self.async_create_entry(title=DOMAIN, data=user_input)
@ -145,6 +155,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
data_schema = { data_schema = {
vol.Required(API_ID): str, vol.Required(API_ID): str,
vol.Required(API_KEY): str, vol.Required(API_KEY): str,
vol.Optional(WSLINK): bool,
vol.Optional(DEV_DBG): bool, vol.Optional(DEV_DBG): bool,
} }
@ -170,7 +181,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
elif user_input[API_KEY] == user_input[API_ID]: elif user_input[API_KEY] == user_input[API_ID]:
errors["base"] = "valid_credentials_match" errors["base"] = "valid_credentials_match"
else: else:
return self.async_create_entry(title=DOMAIN, data=user_input, options=user_input) return self.async_create_entry(
title=DOMAIN, data=user_input, options=user_input
)
return self.async_show_form( return self.async_show_form(
step_id="user", step_id="user",

View File

@ -5,6 +5,7 @@ from typing import Final
DOMAIN = "sws12500" DOMAIN = "sws12500"
DEFAULT_URL = "/weatherstation/updateweatherstation.php" DEFAULT_URL = "/weatherstation/updateweatherstation.php"
WSLINK_URL = "/data/upload.php"
WINDY_URL = "https://stations.windy.com/pws/update/" WINDY_URL = "https://stations.windy.com/pws/update/"
ICON = "mdi:weather" ICON = "mdi:weather"
@ -15,6 +16,7 @@ API_ID = "API_ID"
SENSORS_TO_LOAD: Final = "sensors_to_load" SENSORS_TO_LOAD: Final = "sensors_to_load"
DEV_DBG: Final = "dev_debug_checkbox" DEV_DBG: Final = "dev_debug_checkbox"
WSLINK: Final = "wslink"
WINDY_API_KEY = "WINDY_API_KEY" WINDY_API_KEY = "WINDY_API_KEY"
WINDY_ENABLED: Final = "windy_enabled_checkbox" WINDY_ENABLED: Final = "windy_enabled_checkbox"
@ -53,6 +55,7 @@ PURGE_DATA: Final = [
"dailyrainin", "dailyrainin",
] ]
BARO_PRESSURE: Final = "baro_pressure" BARO_PRESSURE: Final = "baro_pressure"
OUTSIDE_TEMP: Final = "outside_temp" OUTSIDE_TEMP: Final = "outside_temp"
DEW_POINT: Final = "dew_point" DEW_POINT: Final = "dew_point"
@ -99,6 +102,22 @@ REMAP_ITEMS: dict = {
"soilmoisture3": CH4_HUMIDITY, "soilmoisture3": CH4_HUMIDITY,
} }
REMAP_WSLINK_ITEMS: dict = {
"intem": INDOOR_TEMP,
"inhum": INDOOR_HUMIDITY,
"t1temp": OUTSIDE_TEMP,
"t1hum": OUTSIDE_HUMIDITY,
"t1dew": DEW_POINT,
"t1wdir": WIND_DIR,
"t1ws": WIND_SPEED,
"t1wg": WIND_GUST,
"t1rainra": RAIN,
"t1raindy": DAILY_RAIN,
"t1solrad": SOLAR_RADIATION,
"rbar": BARO_PRESSURE,
"uvi": UV
}
DISABLED_BY_DEFAULT: Final = [ DISABLED_BY_DEFAULT: Final = [
CH2_TEMP, CH2_TEMP,
CH2_HUMIDITY, CH2_HUMIDITY,
@ -148,3 +167,4 @@ AZIMUT: list[UnitOfDir] = [
UnitOfDir.NNW, UnitOfDir.NNW,
UnitOfDir.N, UnitOfDir.N,
] ]

View File

@ -10,6 +10,6 @@
"issue_tracker": "https://github.com/schizza/SWS-12500-custom-component/issues", "issue_tracker": "https://github.com/schizza/SWS-12500-custom-component/issues",
"requirements": [], "requirements": [],
"ssdp": [], "ssdp": [],
"version": "0.1.3.5", "version": "0.1.4.0",
"zeroconf": [] "zeroconf": []
} }

View File

@ -1,29 +1,9 @@
"""Sensors definition for SWS12500.""" """Sensors definition for SWS12500."""
from collections.abc import Callable
from dataclasses import dataclass
import logging import logging
from typing import Any, cast
from homeassistant.components.sensor import ( from homeassistant.components.sensor import RestoreSensor, SensorEntity
RestoreSensor,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
DEGREE,
PERCENTAGE,
UV_INDEX,
UnitOfIrradiance,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolumetricFlux,
)
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceEntryType from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, generate_entity_id from homeassistant.helpers.entity import DeviceInfo, generate_entity_id
@ -32,258 +12,25 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import WeatherDataUpdateCoordinator from . import WeatherDataUpdateCoordinator
from .const import ( from .const import (
BARO_PRESSURE,
CH2_HUMIDITY,
CH2_TEMP,
CH3_TEMP,
CH3_HUMIDITY,
CH4_TEMP,
CH4_HUMIDITY,
CHILL_INDEX, CHILL_INDEX,
DAILY_RAIN,
DEW_POINT,
DOMAIN, DOMAIN,
HEAT_INDEX, HEAT_INDEX,
INDOOR_HUMIDITY,
INDOOR_TEMP,
OUTSIDE_HUMIDITY, OUTSIDE_HUMIDITY,
OUTSIDE_TEMP, OUTSIDE_TEMP,
RAIN,
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
SOLAR_RADIATION,
UV,
WIND_AZIMUT, WIND_AZIMUT,
WIND_DIR, WIND_DIR,
WIND_GUST,
WIND_SPEED, WIND_SPEED,
UnitOfDir, WSLINK,
) )
from .utils import heat_index, wind_dir_to_text, chill_index from .sensors_common import WeatherSensorEntityDescription
from .sensors_weather import SENSOR_TYPES_WEATHER_API
from .sensors_wslink import SENSOR_TYPES_WSLINK
from .utils import chill_index, heat_index
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class WeatherSensorEntityDescription(SensorEntityDescription):
"""Describe Weather Sensor entities."""
value_fn: Callable[[Any], int | float | str | None]
SENSOR_TYPES: tuple[WeatherSensorEntityDescription, ...] = (
WeatherSensorEntityDescription(
key=INDOOR_TEMP,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=INDOOR_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=INDOOR_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=INDOOR_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_TEMP,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=OUTSIDE_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=OUTSIDE_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=DEW_POINT,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=DEW_POINT,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=BARO_PRESSURE,
native_unit_of_measurement=UnitOfPressure.INHG,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
suggested_unit_of_measurement=UnitOfPressure.HPA,
translation_key=BARO_PRESSURE,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=WIND_SPEED,
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:weather-windy",
translation_key=WIND_SPEED,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=WIND_GUST,
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:windsock",
translation_key=WIND_GUST,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=WIND_DIR,
native_unit_of_measurement=DEGREE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=None,
icon="mdi:sign-direction",
translation_key=WIND_DIR,
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(
key=RAIN,
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.TOTAL,
suggested_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=RAIN,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=DAILY_RAIN,
native_unit_of_measurement=UnitOfVolumetricFlux.INCHES_PER_DAY,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
suggested_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_DAY,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=DAILY_RAIN,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=SOLAR_RADIATION,
native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.IRRADIANCE,
icon="mdi:weather-sunny",
translation_key=SOLAR_RADIATION,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=UV,
name=UV,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UV_INDEX,
icon="mdi:sunglasses",
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=CH3_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=CH3_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=CH3_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH3_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=CH4_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=CH4_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=CH4_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH4_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=HEAT_INDEX,
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=HEAT_INDEX,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=CHILL_INDEX,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=CHILL_INDEX,
value_fn=lambda data: cast(int, data),
),
)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: ConfigEntry,
@ -295,6 +42,9 @@ async def async_setup_entry(
sensors_to_load: list = [] sensors_to_load: list = []
sensors: list = [] sensors: list = []
_wslink = config_entry.data.get(WSLINK)
SENSOR_TYPES = SENSOR_TYPES_WSLINK if _wslink else SENSOR_TYPES_WEATHER_API
# 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):

View File

@ -0,0 +1,14 @@
"""Common classes for sensors."""
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from homeassistant.components.sensor import SensorEntityDescription
@dataclass(frozen=True, kw_only=True)
class WeatherSensorEntityDescription(SensorEntityDescription):
"""Describe Weather Sensor entities."""
value_fn: Callable[[Any], int | float | str | None]

View File

@ -0,0 +1,257 @@
"""Sensor entities for the SWS12500 integration for old endpoint."""
from typing import cast
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
from homeassistant.const import (
DEGREE,
PERCENTAGE,
UV_INDEX,
UnitOfIrradiance,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolumetricFlux,
)
from .const import (
BARO_PRESSURE,
CH2_HUMIDITY,
CH2_TEMP,
CH3_HUMIDITY,
CH3_TEMP,
CH4_HUMIDITY,
CH4_TEMP,
CHILL_INDEX,
DAILY_RAIN,
DEW_POINT,
HEAT_INDEX,
INDOOR_HUMIDITY,
INDOOR_TEMP,
OUTSIDE_HUMIDITY,
OUTSIDE_TEMP,
RAIN,
SOLAR_RADIATION,
UV,
WIND_AZIMUT,
WIND_DIR,
WIND_GUST,
WIND_SPEED,
UnitOfDir,
)
from .sensors_common import WeatherSensorEntityDescription
from .utils import wind_dir_to_text
SENSOR_TYPES_WEATHER_API: tuple[WeatherSensorEntityDescription, ...] = (
WeatherSensorEntityDescription(
key=INDOOR_TEMP,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=INDOOR_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=INDOOR_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=INDOOR_HUMIDITY,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_TEMP,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=OUTSIDE_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=OUTSIDE_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=DEW_POINT,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=DEW_POINT,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=BARO_PRESSURE,
native_unit_of_measurement=UnitOfPressure.INHG,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
suggested_unit_of_measurement=UnitOfPressure.HPA,
translation_key=BARO_PRESSURE,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=WIND_SPEED,
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:weather-windy",
translation_key=WIND_SPEED,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=WIND_GUST,
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:windsock",
translation_key=WIND_GUST,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=WIND_DIR,
native_unit_of_measurement=DEGREE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=None,
icon="mdi:sign-direction",
translation_key=WIND_DIR,
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(
key=RAIN,
native_unit_of_measurement=UnitOfPrecipitationDepth.INCHES,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.TOTAL,
suggested_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=RAIN,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=DAILY_RAIN,
native_unit_of_measurement=UnitOfVolumetricFlux.INCHES_PER_DAY,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
suggested_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_DAY,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=DAILY_RAIN,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=SOLAR_RADIATION,
native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.IRRADIANCE,
icon="mdi:weather-sunny",
translation_key=SOLAR_RADIATION,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=UV,
name=UV,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UV_INDEX,
icon="mdi:sunglasses",
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=CH3_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=CH3_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=CH3_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH3_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=CH4_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=CH4_TEMP,
value_fn=lambda data: cast(float, data),
),
WeatherSensorEntityDescription(
key=CH4_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
icon="mdi:weather-sunny",
translation_key=CH4_HUMIDITY,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=HEAT_INDEX,
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=HEAT_INDEX,
value_fn=lambda data: cast(int, data),
),
WeatherSensorEntityDescription(
key=CHILL_INDEX,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=CHILL_INDEX,
value_fn=lambda data: cast(int, data),
),
)

View File

@ -0,0 +1,257 @@
"""Sensor entities for the SWS12500 integration for old endpoint."""
from typing import cast
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
from homeassistant.const import (
DEGREE,
PERCENTAGE,
UV_INDEX,
UnitOfIrradiance,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolumetricFlux,
)
from .const import (
BARO_PRESSURE,
CH2_HUMIDITY,
CH2_TEMP,
CH3_HUMIDITY,
CH3_TEMP,
CH4_HUMIDITY,
CH4_TEMP,
CHILL_INDEX,
DAILY_RAIN,
DEW_POINT,
HEAT_INDEX,
INDOOR_HUMIDITY,
INDOOR_TEMP,
OUTSIDE_HUMIDITY,
OUTSIDE_TEMP,
RAIN,
SOLAR_RADIATION,
UV,
WIND_AZIMUT,
WIND_DIR,
WIND_GUST,
WIND_SPEED,
UnitOfDir,
)
from .sensors_common import WeatherSensorEntityDescription
from .utils import wind_dir_to_text
SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
WeatherSensorEntityDescription(
key=INDOOR_TEMP,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=INDOOR_TEMP,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=INDOOR_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=INDOOR_HUMIDITY,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=OUTSIDE_TEMP,
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),
),
WeatherSensorEntityDescription(
key=OUTSIDE_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer",
device_class=SensorDeviceClass.HUMIDITY,
translation_key=OUTSIDE_HUMIDITY,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=DEW_POINT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.TEMPERATURE,
translation_key=DEW_POINT,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=BARO_PRESSURE,
native_unit_of_measurement=UnitOfPressure.HPA,
state_class=SensorStateClass.MEASUREMENT,
icon="mdi:thermometer-lines",
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
suggested_unit_of_measurement=UnitOfPressure.HPA,
translation_key=BARO_PRESSURE,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=WIND_SPEED,
native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:weather-windy",
translation_key=WIND_SPEED,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=WIND_GUST,
native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_SPEED,
suggested_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
icon="mdi:windsock",
translation_key=WIND_GUST,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=WIND_DIR,
native_unit_of_measurement=DEGREE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=None,
icon="mdi:sign-direction",
translation_key=WIND_DIR,
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(
key=RAIN,
native_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.TOTAL,
suggested_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=RAIN,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=DAILY_RAIN,
native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
suggested_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_DAY,
suggested_display_precision=2,
icon="mdi:weather-pouring",
translation_key=DAILY_RAIN,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=SOLAR_RADIATION,
native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.IRRADIANCE,
icon="mdi:weather-sunny",
translation_key=SOLAR_RADIATION,
value_fn=lambda data: cast("float", data),
),
WeatherSensorEntityDescription(
key=UV,
name=UV,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UV_INDEX,
icon="mdi:sunglasses",
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=CH3_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=CH3_TEMP,
# value_fn=lambda data: cast(float, data),
# ),
# WeatherSensorEntityDescription(
# key=CH3_HUMIDITY,
# native_unit_of_measurement=PERCENTAGE,
# state_class=SensorStateClass.MEASUREMENT,
# device_class=SensorDeviceClass.HUMIDITY,
# icon="mdi:weather-sunny",
# translation_key=CH3_HUMIDITY,
# value_fn=lambda data: cast(int, data),
# ),
# WeatherSensorEntityDescription(
# key=CH4_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=CH4_TEMP,
# value_fn=lambda data: cast(float, data),
# ),
# WeatherSensorEntityDescription(
# key=CH4_HUMIDITY,
# native_unit_of_measurement=PERCENTAGE,
# state_class=SensorStateClass.MEASUREMENT,
# device_class=SensorDeviceClass.HUMIDITY,
# icon="mdi:weather-sunny",
# translation_key=CH4_HUMIDITY,
# value_fn=lambda data: cast(int, data),
# ),
WeatherSensorEntityDescription(
key=HEAT_INDEX,
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=HEAT_INDEX,
value_fn=lambda data: cast("int", data),
),
WeatherSensorEntityDescription(
key=CHILL_INDEX,
native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_unit_of_measurement=UnitOfTemperature.CELSIUS,
suggested_display_precision=2,
icon="mdi:weather-sunny",
translation_key=CHILL_INDEX,
value_fn=lambda data: cast("int", data),
),
)

View File

@ -10,6 +10,7 @@
"data": { "data": {
"API_ID": "API ID / ID stanice", "API_ID": "API ID / ID stanice",
"API_KEY": "API KEY / Heslo", "API_KEY": "API KEY / Heslo",
"wslink": "WSLink API",
"dev_debug_checkbox": "Developer log" "dev_debug_checkbox": "Developer log"
}, },
"description": "Zadejte API ID a API KEY, aby meteostanice mohla komunikovat s HomeAssistantem", "description": "Zadejte API ID a API KEY, aby meteostanice mohla komunikovat s HomeAssistantem",
@ -32,6 +33,7 @@
"data": { "data": {
"API_ID": "API ID / ID Stanice", "API_ID": "API ID / ID Stanice",
"API_KEY": "API KEY / Heslo", "API_KEY": "API KEY / Heslo",
"wslink": "WSLink API",
"dev_debug_checkbox": "Developer log" "dev_debug_checkbox": "Developer log"
}, },
"description": "Zadejte API ID a API KEY, aby meteostanice mohla komunikovat s HomeAssistantem", "description": "Zadejte API ID a API KEY, aby meteostanice mohla komunikovat s HomeAssistantem",

View File

@ -10,6 +10,7 @@
"data": { "data": {
"API_ID": "API ID / Station ID", "API_ID": "API ID / Station ID",
"API_KEY": "API KEY / Password", "API_KEY": "API KEY / Password",
"WSLINK": "WSLink API",
"dev_debug_checkbox": "Developer log" "dev_debug_checkbox": "Developer log"
}, },
"description": "Provide API ID and API KEY so the Weather Station can access HomeAssistant", "description": "Provide API ID and API KEY so the Weather Station can access HomeAssistant",
@ -32,6 +33,7 @@
"data": { "data": {
"API_ID": "API ID / Station ID", "API_ID": "API ID / Station ID",
"API_KEY": "API KEY / Password", "API_KEY": "API KEY / Password",
"WSLINK": "WSLink API",
"dev_debug_checkbox": "Developer log" "dev_debug_checkbox": "Developer log"
}, },
"description": "Provide API ID and API KEY so the Weather Station can access HomeAssistant", "description": "Provide API ID and API KEY so the Weather Station can access HomeAssistant",

View File

@ -1,25 +1,27 @@
"""Utils for SWS12500.""" """Utils for SWS12500."""
import logging import logging
import math
from typing import Any
import numpy as np
from homeassistant.components import persistent_notification from homeassistant.components import persistent_notification
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTemperature
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 homeassistant.const import UnitOfTemperature
from typing import Any
import math
import numpy as np
from .const import ( from .const import (
AZIMUT, AZIMUT,
DEV_DBG, DEV_DBG,
REMAP_ITEMS,
SENSORS_TO_LOAD,
UnitOfDir,
OUTSIDE_TEMP,
OUTSIDE_HUMIDITY, OUTSIDE_HUMIDITY,
OUTSIDE_TEMP,
REMAP_ITEMS,
REMAP_WSLINK_ITEMS,
SENSORS_TO_LOAD,
WIND_SPEED, WIND_SPEED,
UnitOfDir,
) )
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -99,7 +101,7 @@ def anonymize(data):
anonym = {} anonym = {}
for k in data: for k in data:
if k not in ("ID", "PASSWORD"): if k not in ("ID", "PASSWORD", "wsid", "wspw"):
anonym[k] = data[k] anonym[k] = data[k]
return anonym return anonym
@ -115,6 +117,16 @@ def remap_items(entities):
return items return items
def remap_wslink_items(entities):
"""Remap items in query for WSLink API."""
items = {}
for item in entities:
if item in REMAP_WSLINK_ITEMS:
items[REMAP_WSLINK_ITEMS[item]] = entities[item]
return items
def loaded_sensors(config_entry: ConfigEntry) -> list | None: def loaded_sensors(config_entry: ConfigEntry) -> list | None:
"""Get loaded sensors.""" """Get loaded sensors."""
@ -202,11 +214,15 @@ def chill_index(data: Any) -> UnitOfTemperature:
temp = float(data[OUTSIDE_TEMP]) temp = float(data[OUTSIDE_TEMP])
wind = float(data[WIND_SPEED]) wind = float(data[WIND_SPEED])
return round( return (
( round(
(35.7 + (0.6215 * temp)) (
- (35.75 * (wind**0.16)) (35.7 + (0.6215 * temp))
+ (0.4275 * (temp * (wind**0.16))) - (35.75 * (wind**0.16))
), + (0.4275 * (temp * (wind**0.16)))
2, ),
) if temp < 50 and wind > 3 else temp 2,
)
if temp < 50 and wind > 3
else temp
)