Compare commits

..

38 Commits

Author SHA1 Message Date
Lukas Svoboda 5022cb7767
Merge pull request #65 from convicte/patch-1
Implement SensorDeviceClass.WIND_DIRECTION
2025-08-28 21:58:28 +02:00
Lukas Svoboda f7cea43722
Merge branch 'stable' into patch-1 2025-08-28 21:58:15 +02:00
Lukas Svoboda 7ff8bb7f92
Merge branch 'main' into patch-1 2025-08-28 21:57:38 +02:00
Lukas Svoboda dbebc501e3
Bump version from 1.6.5 to 1.6.6 2025-08-28 21:55:01 +02:00
Lukas Svoboda 8247f2b854
Merge pull request #72 from FerronN/ft-add-wslink-battery-level
Add outside battery sensor and related translations
2025-08-28 21:53:27 +02:00
Ferron Nijland d48f0fda6e Merge branch 'ft-add-wslink-battery-level' of https://github.com/FerronN/SWS-12500-custom-component into ft-add-wslink-battery-level 2025-08-28 10:42:03 +02:00
schizza 99fd6d266c Adds outside battery sensor
Adds an outside battery sensor to the integration, providing information about the battery level of the outdoor sensor.

This includes:
- Mapping the `t1bat` WSLink item to the `OUTSIDE_BATTERY` sensor.
- Implementing logic to convert the battery level to a human-readable text representation and a corresponding icon.
- Updates precipitation to intensity and fixes data type of battery level
2025-08-28 10:41:44 +02:00
schizza 64dd47a3e9 Option flow configuration
Removes the "migration" step from the option flow menu.
This step will be used in next release.
2025-08-28 10:41:44 +02:00
schizza 720c2148e6 Removes unused import from config_flow
Removes the unused import of `utils` to improve code cleanliness and avoid potential namespace conflicts.
Removed 'migration' from menu as it is intended to use in later version.
2025-08-28 10:41:44 +02:00
schizza b858f648b9 config_flow migrated to stable version.
Config flow was migrated to stable version.

Removes the unit migration flow, which is intended to introduce later.
2025-08-28 10:41:44 +02:00
schizza 07ca4a6833 Reorders constants for better readability
Reorders the import of constants to improve readability and maintain consistency within the module.

Final touches.
2025-08-28 10:41:44 +02:00
schizza de013891c0 Adds missing constant and improves readability
Adds OUTSIDE_BATTERY to the DISABLED_BY_DEFAULT list.
Improves readability by formatting long strings with parenthesis.
2025-08-28 10:41:44 +02:00
schizza 0d0922a494 Improves battery sensor display
Updates the outside battery sensor to display an icon
reflecting the battery level, enhancing the user experience
by providing a visual indication of the battery status.
2025-08-28 10:41:44 +02:00
schizza af19358ac7 Adds battery state translations
Adds translations for the battery state of the outside sensor to both the English and Czech language files.

This change provides more descriptive and user-friendly information about the battery status.
2025-08-28 10:41:44 +02:00
schizza 3dbf8b8a7a Improves battery level representation
Refactors battery level representation by using enum instead of string.

Improves battery level display by adding an icon representation.

Changes const BATLEVEL to BATTERY_LEVEL.
2025-08-28 10:41:44 +02:00
schizza a68a4c929a Update const.py 2025-08-28 10:41:44 +02:00
FerronN af286648e9 fix data parsing in sensors_wslink.py 2025-08-28 10:41:44 +02:00
FerronN b6080fe9fd Fix structure en.json 2025-08-28 10:41:44 +02:00
Ferron Nijland a07af5a4fd Add outside battery sensor and related translations 2025-08-28 10:41:44 +02:00
schizza f14e6500d4 Adds unit migration functionality to options flow
Implements a user interface to migrate units for rain sensors including migration of historic data via statistics.
This provides the user with the ability to correct rain units, if they have been set incorrectly.
Includes UI to select sensor and units, as well as trigger migration.
2025-08-28 10:40:03 +02:00
Lukas Svoboda a1f2bf10ea
Merge branch 'stable' into ft-add-wslink-battery-level 2025-08-22 18:15:11 +02:00
schizza e10ea9901c
Adds outside battery sensor
Adds an outside battery sensor to the integration, providing information about the battery level of the outdoor sensor.

This includes:
- Mapping the `t1bat` WSLink item to the `OUTSIDE_BATTERY` sensor.
- Implementing logic to convert the battery level to a human-readable text representation and a corresponding icon.
- Updates precipitation to intensity and fixes data type of battery level
2025-08-22 18:06:35 +02:00
schizza fc8349c06e
Option flow configuration
Removes the "migration" step from the option flow menu.
This step will be used in next release.
2025-08-21 16:46:13 +02:00
schizza d4d2440ae8
Removes unused import from config_flow
Removes the unused import of `utils` to improve code cleanliness and avoid potential namespace conflicts.
Removed 'migration' from menu as it is intended to use in later version.
2025-08-21 16:45:29 +02:00
schizza 827fb71e25
sensors_wslink updated to stable version
Updating to stable version, retaining CH3 sensors.
Left outside battery unchanged. Will work on bug in next commit.
2025-08-21 16:39:05 +02:00
schizza 2d758835dc
config_flow migrated to stable version.
Config flow was migrated to stable version.

Removes the unit migration flow, which is intended to introduce later.
2025-08-21 16:30:10 +02:00
schizza 0027a80968
Update const to stable version
Update constants to stable version.
2025-08-21 16:08:08 +02:00
schizza e11e068c0f Reorders constants for better readability
Reorders the import of constants to improve readability and maintain consistency within the module.

Final touches.
2025-08-18 13:29:00 +02:00
schizza 1ecd88269d Adds missing constant and improves readability
Adds OUTSIDE_BATTERY to the DISABLED_BY_DEFAULT list.
Improves readability by formatting long strings with parenthesis.
2025-08-18 12:53:40 +02:00
schizza 09d79e2032 Improves battery sensor display
Updates the outside battery sensor to display an icon
reflecting the battery level, enhancing the user experience
by providing a visual indication of the battery status.
2025-08-18 12:50:31 +02:00
schizza bbe31da4c5 Adds battery state translations
Adds translations for the battery state of the outside sensor to both the English and Czech language files.

This change provides more descriptive and user-friendly information about the battery status.
2025-08-18 10:55:37 +02:00
schizza 68da7aad98 Improves battery level representation
Refactors battery level representation by using enum instead of string.

Improves battery level display by adding an icon representation.

Changes const BATLEVEL to BATTERY_LEVEL.
2025-08-17 18:34:14 +02:00
schizza de8d2a7b0c
Update const.py 2025-08-16 17:29:22 +02:00
FerronN cf0938a6fd
fix data parsing in sensors_wslink.py 2025-07-11 10:16:59 +02:00
FerronN 4d2dedbb11
Fix structure en.json 2025-07-11 10:15:44 +02:00
Ferron Nijland feed730818 Add outside battery sensor and related translations 2025-07-09 16:26:18 +02:00
schizza 99d25bfd56 Adds unit migration functionality to options flow
Implements a user interface to migrate units for rain sensors including migration of historic data via statistics.
This provides the user with the ability to correct rain units, if they have been set incorrectly.
Includes UI to select sensor and units, as well as trigger migration.
2025-04-24 17:56:47 +02:00
convicte 6eceee1f4e
Implement SensorDeviceClass.WIND_DIRECTION
This commit adds the latest SensorDeviceClass.WIND_DIRECTION to facilitate correct long term statistics collection for the wind direction sensor.
2025-03-15 23:13:21 +01:00
9 changed files with 133 additions and 86 deletions

View File

@ -7,7 +7,6 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, OptionsFlow from homeassistant.config_entries import ConfigFlow, OptionsFlow
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from .utils import long_term_units_in_statistics_meta, migrate_data
from .const import ( from .const import (
API_ID, API_ID,
@ -16,7 +15,6 @@ from .const import (
DOMAIN, DOMAIN,
INVALID_CREDENTIALS, INVALID_CREDENTIALS,
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
SENSOR_TO_MIGRATE,
WINDY_API_KEY, WINDY_API_KEY,
WINDY_ENABLED, WINDY_ENABLED,
WINDY_LOGGER_ENABLED, WINDY_LOGGER_ENABLED,
@ -41,7 +39,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.windy_data: dict[str, Any] = {} self.windy_data: dict[str, Any] = {}
self.windy_data_schema = {} self.windy_data_schema = {}
self.user_data: dict[str, str] = {} self.user_data: dict[str, Any] = {}
self.user_data_schema = {} self.user_data_schema = {}
self.sensors: dict[str, Any] = {} self.sensors: dict[str, Any] = {}
self.migrate_schema = {} self.migrate_schema = {}
@ -50,7 +48,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
def config_entry(self): def config_entry(self):
return self.hass.config_entries.async_get_entry(self.handler) return self.hass.config_entries.async_get_entry(self.handler)
def _get_entry_data(self): async def _get_entry_data(self):
"""Get entry data.""" """Get entry data."""
self.user_data: dict[str, Any] = { self.user_data: dict[str, Any] = {
@ -61,16 +59,18 @@ class ConfigOptionsFlowHandler(OptionsFlow):
} }
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.get(API_ID, "")): str,
vol.Required(API_KEY, default=self.user_data[API_KEY] or ""): str, vol.Required(API_KEY, default=self.user_data.get(API_KEY, "")): str,
vol.Optional(WSLINK, default=self.user_data[WSLINK]): bool or False, vol.Optional(WSLINK, default=self.user_data.get(WSLINK, False)): bool,
vol.Optional(DEV_DBG, default=self.user_data[DEV_DBG]): bool or False, vol.Optional(DEV_DBG, default=self.user_data.get(DEV_DBG, False)): bool,
} }
self.sensors: dict[str, Any] = { self.sensors: dict[str, Any] = {
SENSORS_TO_LOAD: self.config_entry.options.get(SENSORS_TO_LOAD) SENSORS_TO_LOAD: (
self.config_entry.options.get(SENSORS_TO_LOAD)
if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list) if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list)
else [] else []
)
} }
self.windy_data: dict[str, Any] = { self.windy_data: dict[str, Any] = {
@ -83,34 +83,26 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.windy_data_schema = { self.windy_data_schema = {
vol.Optional( vol.Optional(
WINDY_API_KEY, default=self.windy_data[WINDY_API_KEY] or "" WINDY_API_KEY, default=self.windy_data.get(WINDY_API_KEY, "")
): str, ): str,
vol.Optional(WINDY_ENABLED, default=self.windy_data[WINDY_ENABLED]): bool vol.Optional(WINDY_ENABLED, default=self.windy_data[WINDY_ENABLED]): bool
or False, or False,
vol.Optional( vol.Optional(
WINDY_LOGGER_ENABLED, WINDY_LOGGER_ENABLED,
default=self.windy_data[WINDY_LOGGER_ENABLED], default=self.windy_data[WINDY_LOGGER_ENABLED],
): bool or False, ): bool
} or False,
self.migrate_schema = {
vol.Required(SENSOR_TO_MIGRATE): vol.In(
long_term_units_in_statistics_meta() or {}
),
vol.Optional("trigger_action", default=False): bool,
} }
async def async_step_init(self, user_input=None): async def async_step_init(self, user_input=None):
"""Manage the options - show menu first.""" """Manage the options - show menu first."""
return self.async_show_menu( return self.async_show_menu(step_id="init", menu_options=["basic", "windy"])
step_id="init", menu_options=["basic", "windy", "migration"]
)
async def async_step_basic(self, user_input=None): async def async_step_basic(self, user_input=None):
"""Manage basic options - credentials.""" """Manage basic options - credentials."""
errors = {} errors = {}
self._get_entry_data() await self._get_entry_data()
if user_input is None: if user_input is None:
return self.async_show_form( return self.async_show_form(
@ -147,7 +139,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
"""Manage windy options.""" """Manage windy options."""
errors = {} errors = {}
self._get_entry_data() await self._get_entry_data()
if user_input is None: if user_input is None:
return self.async_show_form( return self.async_show_form(
@ -160,7 +152,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
errors[WINDY_API_KEY] = "windy_key_required" errors[WINDY_API_KEY] = "windy_key_required"
return self.async_show_form( return self.async_show_form(
step_id="windy", step_id="windy",
data_schema=self.windy_data_schema, data_schema=vol.Schema(self.windy_data_schema),
errors=errors, errors=errors,
) )
@ -172,51 +164,6 @@ class ConfigOptionsFlowHandler(OptionsFlow):
return self.async_create_entry(title=DOMAIN, data=user_input) return self.async_create_entry(title=DOMAIN, data=user_input)
async def async_step_migration(self, user_input=None):
"""Migrate sensors."""
# hj
errors = {}
self._get_entry_data()
if user_input is None:
return self.async_show_form(
step_id="migration",
data_schema=vol.Schema(self.migrate_schema),
errors=errors,
description_placeholders={
"migration_status": "-",
"migration_count": "-",
},
)
if user_input.get("trigger_action"):
# Akce se vykoná po zaškrtnutí
count = await self.hass.async_add_executor_job(
migrate_data, user_input.get(SENSOR_TO_MIGRATE)
)
return self.async_show_form(
step_id="migration",
data_schema=vol.Schema(self.migrate_schema),
errors=errors,
description_placeholders={
"migration_status": user_input.get(SENSOR_TO_MIGRATE),
"migration_count": count,
},
)
# retain windy data
user_input.update(self.windy_data)
# retain user_data
user_input.update(self.user_data)
# retain senors
user_input.update(self.sensors)
return self.async_create_entry(title=DOMAIN, data=user_input)
class ConfigFlow(ConfigFlow, domain=DOMAIN): class ConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Sencor SWS 12500 Weather Station.""" """Handle a config flow for Sencor SWS 12500 Weather Station."""

View File

@ -23,8 +23,12 @@ 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"
WINDY_LOGGER_ENABLED: Final = "windy_logger_checkbox" WINDY_LOGGER_ENABLED: Final = "windy_logger_checkbox"
WINDY_NOT_INSERTED: Final = "Data was succefuly sent to Windy, but not inserted by Windy API. Does anyone else sent data to Windy?" WINDY_NOT_INSERTED: Final = (
WINDY_INVALID_KEY: Final = "Windy API KEY is invalid. Send data to Windy is now disabled. Check your API KEY and try again." "Data was succefuly sent to Windy, but not inserted by Windy API. Does anyone else sent data to Windy?"
)
WINDY_INVALID_KEY: Final = (
"Windy API KEY is invalid. Send data to Windy is now disabled. Check your API KEY and try again."
)
WINDY_SUCCESS: Final = ( WINDY_SUCCESS: Final = (
"Windy successfully sent data and data was successfully inserted by Windy API" "Windy successfully sent data and data was successfully inserted by Windy API"
) )
@ -63,6 +67,7 @@ OUTSIDE_TEMP: Final = "outside_temp"
DEW_POINT: Final = "dew_point" DEW_POINT: Final = "dew_point"
OUTSIDE_HUMIDITY: Final = "outside_humidity" OUTSIDE_HUMIDITY: Final = "outside_humidity"
OUTSIDE_CONNECTION: Final = "outside_connection" OUTSIDE_CONNECTION: Final = "outside_connection"
OUTSIDE_BATTERY: Final = "outside_battery"
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"
@ -139,6 +144,7 @@ REMAP_WSLINK_ITEMS: dict = {
"t1rainyr": YEARLY_RAIN, "t1rainyr": YEARLY_RAIN,
"t234c2tem": CH3_TEMP, "t234c2tem": CH3_TEMP,
"t234c2hum": CH3_HUMIDITY, "t234c2hum": CH3_HUMIDITY,
"t1bat": OUTSIDE_BATTERY,
} }
# TODO: Add more sensors # TODO: Add more sensors
@ -155,6 +161,7 @@ DISABLED_BY_DEFAULT: Final = [
CH3_HUMIDITY, CH3_HUMIDITY,
CH4_TEMP, CH4_TEMP,
CH4_HUMIDITY, CH4_HUMIDITY,
OUTSIDE_BATTERY,
] ]
@ -197,3 +204,18 @@ AZIMUT: list[UnitOfDir] = [
UnitOfDir.NNW, UnitOfDir.NNW,
UnitOfDir.N, UnitOfDir.N,
] ]
class UnitOfBat(StrEnum):
"""Battery level unit of measure."""
LOW = "low"
NORMAL = "normal"
UNKNOWN = "unknown"
BATTERY_LEVEL: list[UnitOfBat] = [
UnitOfBat.LOW,
UnitOfBat.NORMAL,
UnitOfBat.UNKNOWN,
]

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": "1.6.5", "version": "1.6.6",
"zeroconf": [] "zeroconf": []
} }

View File

@ -15,6 +15,7 @@ from .const import (
CHILL_INDEX, CHILL_INDEX,
DOMAIN, DOMAIN,
HEAT_INDEX, HEAT_INDEX,
OUTSIDE_BATTERY,
OUTSIDE_HUMIDITY, OUTSIDE_HUMIDITY,
OUTSIDE_TEMP, OUTSIDE_TEMP,
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
@ -26,7 +27,7 @@ from .const import (
from .sensors_common import WeatherSensorEntityDescription from .sensors_common import WeatherSensorEntityDescription
from .sensors_weather import SENSOR_TYPES_WEATHER_API from .sensors_weather import SENSOR_TYPES_WEATHER_API
from .sensors_wslink import SENSOR_TYPES_WSLINK from .sensors_wslink import SENSOR_TYPES_WSLINK
from .utils import chill_index, heat_index from .utils import chill_index, heat_index, battery_level_to_icon, battery_level_to_text
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -130,13 +131,27 @@ class WeatherSensor(
): ):
return self.entity_description.value_fn(chill_index(self.coordinator.data)) return self.entity_description.value_fn(chill_index(self.coordinator.data))
return None if self._data == "" else self.entity_description.value_fn(self._data) return (
None if self._data == "" else self.entity_description.value_fn(self._data)
)
@property @property
def suggested_entity_id(self) -> str: def suggested_entity_id(self) -> str:
"""Return name.""" """Return name."""
return generate_entity_id("sensor.{}", self.entity_description.key) return generate_entity_id("sensor.{}", self.entity_description.key)
@property
def icon(self) -> str | None:
"""Return the dynamic icon for battery representation."""
if self.entity_description.key == OUTSIDE_BATTERY:
try:
return battery_level_to_icon(self.native_value)
except Exception:
return "mdi:battery-unknown"
return self.entity_description.icon
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
"""Device info.""" """Device info."""

View File

@ -27,25 +27,26 @@ from .const import (
DAILY_RAIN, DAILY_RAIN,
DEW_POINT, DEW_POINT,
HEAT_INDEX, HEAT_INDEX,
HOURLY_RAIN,
INDOOR_HUMIDITY, INDOOR_HUMIDITY,
INDOOR_TEMP, INDOOR_TEMP,
MONTHLY_RAIN,
OUTSIDE_BATTERY,
OUTSIDE_HUMIDITY, OUTSIDE_HUMIDITY,
OUTSIDE_TEMP, OUTSIDE_TEMP,
RAIN, RAIN,
SOLAR_RADIATION, SOLAR_RADIATION,
UV, UV,
WEEKLY_RAIN,
WIND_AZIMUT, WIND_AZIMUT,
WIND_DIR, WIND_DIR,
WIND_GUST, WIND_GUST,
WIND_SPEED, WIND_SPEED,
UnitOfDir,
MONTHLY_RAIN,
YEARLY_RAIN, YEARLY_RAIN,
HOURLY_RAIN, UnitOfDir,
WEEKLY_RAIN,
) )
from .sensors_common import WeatherSensorEntityDescription from .sensors_common import WeatherSensorEntityDescription
from .utils import wind_dir_to_text from .utils import battery_level_to_icon, battery_level_to_text, wind_dir_to_text
SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = ( SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
WeatherSensorEntityDescription( WeatherSensorEntityDescription(
@ -127,6 +128,7 @@ SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
key=WIND_DIR, key=WIND_DIR,
native_unit_of_measurement=DEGREE, native_unit_of_measurement=DEGREE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.WIND_DIRECTION,
suggested_display_precision=None, suggested_display_precision=None,
icon="mdi:sign-direction", icon="mdi:sign-direction",
translation_key=WIND_DIR, translation_key=WIND_DIR,
@ -143,7 +145,7 @@ SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
WeatherSensorEntityDescription( WeatherSensorEntityDescription(
key=RAIN, key=RAIN,
native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR, native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
device_class=SensorDeviceClass.PRECIPITATION, device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
state_class=SensorStateClass.TOTAL, state_class=SensorStateClass.TOTAL,
suggested_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR, suggested_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
suggested_display_precision=2, suggested_display_precision=2,
@ -303,4 +305,11 @@ SENSOR_TYPES_WSLINK: tuple[WeatherSensorEntityDescription, ...] = (
translation_key=CHILL_INDEX, translation_key=CHILL_INDEX,
value_fn=lambda data: cast("int", data), value_fn=lambda data: cast("int", data),
), ),
WeatherSensorEntityDescription(
key=OUTSIDE_BATTERY,
translation_key=OUTSIDE_BATTERY,
icon="mdi:battery-unknown",
device_class=SensorDeviceClass.ENUM,
value_fn=lambda data: battery_level_to_text(data),
),
) )

View File

@ -131,6 +131,14 @@
"wnw": "WNW", "wnw": "WNW",
"nw": "NW", "nw": "NW",
"nnw": "NNW" "nnw": "NNW"
},
"outside_battery": {
"name": "Outside battery level",
"state": {
"normal": "OK",
"low": "Low",
"unknown": "Unknown / drained out"
}
} }
} }
} }

View File

@ -136,6 +136,14 @@
"nw": "SZ", "nw": "SZ",
"nnw": "SSZ" "nnw": "SSZ"
} }
},
"outside_battery": {
"name": "Stav nabití venkovní baterie",
"state": {
"low": "Nízká",
"normal": "Normální",
"unknown": "Neznámá / zcela vybitá"
}
} }
} }
}, },

View File

@ -136,6 +136,14 @@
"nw": "NW", "nw": "NW",
"nnw": "NNW" "nnw": "NNW"
} }
},
"outside_battery": {
"name": "Outside battery level",
"state": {
"normal": "OK",
"low": "Low",
"unknown": "Unknown / drained out"
}
} }
} }
}, },

View File

@ -20,6 +20,7 @@ from homeassistant.helpers.translation import async_get_translations
from .const import ( from .const import (
AZIMUT, AZIMUT,
BATTERY_LEVEL,
DATABASE_PATH, DATABASE_PATH,
DEV_DBG, DEV_DBG,
OUTSIDE_HUMIDITY, OUTSIDE_HUMIDITY,
@ -29,6 +30,7 @@ from .const import (
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
WIND_SPEED, WIND_SPEED,
UnitOfDir, UnitOfDir,
UnitOfBat,
) )
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -181,6 +183,32 @@ def wind_dir_to_text(deg: float) -> UnitOfDir | None:
return None return None
def battery_level_to_text(battery: int) -> UnitOfBat:
"""Return battery level in text representation.
Returns UnitOfBat
"""
return {
0: UnitOfBat.LOW,
1: UnitOfBat.NORMAL,
}.get(int(battery) if battery is not None else None, UnitOfBat.UNKNOWN)
def battery_level_to_icon(battery: UnitOfBat) -> str:
"""Return battery level in icon representation.
Returns str
"""
icons = {
UnitOfBat.LOW: "mdi:battery-low",
UnitOfBat.NORMAL: "mdi:battery",
}
return icons.get(battery, "mdi:battery-unknown")
def fahrenheit_to_celsius(fahrenheit: float) -> float: def fahrenheit_to_celsius(fahrenheit: float) -> float:
"""Convert Fahrenheit to Celsius.""" """Convert Fahrenheit to Celsius."""
return (fahrenheit - 32) * 5.0 / 9.0 return (fahrenheit - 32) * 5.0 / 9.0
@ -267,10 +295,12 @@ def long_term_units_in_statistics_meta():
db = conn.cursor() db = conn.cursor()
try: try:
db.execute(""" db.execute(
"""
SELECT statistic_id, unit_of_measurement from statistics_meta SELECT statistic_id, unit_of_measurement from statistics_meta
WHERE statistic_id LIKE 'sensor.weather_station_sws%' WHERE statistic_id LIKE 'sensor.weather_station_sws%'
""") """
)
rows = db.fetchall() rows = db.fetchall()
sensor_units = { sensor_units = {
statistic_id: f"{statistic_id} ({unit})" for statistic_id, unit in rows statistic_id: f"{statistic_id} ({unit})" for statistic_id, unit in rows