diff --git a/custom_components/davis_vantage/__init__.py b/custom_components/davis_vantage/__init__.py index 612b523..9736097 100755 --- a/custom_components/davis_vantage/__init__.py +++ b/custom_components/davis_vantage/__init__.py @@ -2,10 +2,10 @@ from __future__ import annotations from typing import Any +from zoneinfo import ZoneInfo import logging import json import voluptuous as vol -from zoneinfo import ZoneInfo from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, ServiceCall, SupportsResponse @@ -17,13 +17,15 @@ NAME, MANUFACTURER, RAIN_COLLECTOR_IMPERIAL, + RAIN_COLLECTOR_METRIC, + RAIN_COLLECTOR_METRIC_0_1, SERVICE_SET_DAVIS_TIME, SERVICE_GET_DAVIS_TIME, SERVICE_GET_RAW_DATA, SERVICE_GET_INFO, SERVICE_SET_YEARLY_RAIN, SERVICE_SET_ARCHIVE_PERIOD, - CONFIG_RAIN_COLLECTOR, + SERVICE_SET_RAIN_COLLECTOR, CONFIG_STATION_MODEL, CONFIG_INTERVAL, CONFIG_PROTOCOL, @@ -50,11 +52,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: protocol = entry.data.get(CONFIG_PROTOCOL, "") link = entry.data.get(CONFIG_LINK, "") - rain_collector = entry.data.get(CONFIG_RAIN_COLLECTOR, RAIN_COLLECTOR_IMPERIAL) hass.data[DOMAIN]["interval"] = entry.data.get(CONFIG_INTERVAL, 30) - client = DavisVantageClient(hass, protocol, link, rain_collector) + client = DavisVantageClient(hass, protocol, link) await client.connect_to_station() static_info = await client.async_get_static_info() firmware_version = ( @@ -74,7 +75,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass=hass, client=client, device_info=device_info ) - await coordinator.async_config_entry_first_refresh() + await coordinator.async_refresh() await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(async_reload_entry)) @@ -114,6 +115,9 @@ async def set_archive_period(call: ServiceCall) -> None: await client.async_set_archive_period(call.data["archive_period"]) client.clear_cached_property('archive_period') + async def set_rain_collector(call: ServiceCall) -> None: + await client.async_set_rain_collector(call.data["rain_collector"]) + hass.services.async_register(DOMAIN, SERVICE_SET_DAVIS_TIME, set_davis_time) hass.services.async_register( DOMAIN, @@ -153,6 +157,17 @@ async def set_archive_period(call: ServiceCall) -> None: }) ) + hass.services.async_register( + DOMAIN, + SERVICE_SET_RAIN_COLLECTOR, + set_rain_collector, + schema=vol.Schema({ + vol.Required('rain_collector'): vol.In( + [RAIN_COLLECTOR_IMPERIAL, RAIN_COLLECTOR_METRIC, RAIN_COLLECTOR_METRIC_0_1] + ) + }) + ) + return True diff --git a/custom_components/davis_vantage/client.py b/custom_components/davis_vantage/client.py index 1a419a5..0730885 100755 --- a/custom_components/davis_vantage/client.py +++ b/custom_components/davis_vantage/client.py @@ -28,6 +28,8 @@ ) from .const import ( RAIN_COLLECTOR_IMPERIAL, + RAIN_COLLECTOR_METRIC, + RAIN_COLLECTOR_METRIC_0_1, PROTOCOL_NETWORK, ) @@ -40,12 +42,12 @@ class DavisVantageClient: _vantagepro2: VantagePro2 = None # type: ignore def __init__( - self, hass: HomeAssistant, protocol: str, link: str, rain_collector: str + self, hass: HomeAssistant, protocol: str, link: str ) -> None: self._hass = hass self._protocol = protocol self._link = link - self._rain_collector = rain_collector + self._rain_collector = "" self._last_data: LoopDataParserRevB = {} # type: ignore self._last_raw_data: DataParser = {} # type: ignore @@ -96,11 +98,14 @@ def get_current_data( try: end_datetime = datetime.now() start_datetime = end_datetime - timedelta( - minutes=self._vantagepro2.archive_period * 2 # type: ignore + minutes=self._vantagepro2.archive_period * 2 # type: ignore ) archives = self._vantagepro2.get_archives(start_datetime, end_datetime) # type: ignore except Exception: pass + + try: + self._rain_collector = self.get_rain_collector() finally: self._vantagepro2.link.close() @@ -321,27 +326,22 @@ def convert_values(self, data: dict[str, Any]) -> None: if data["SolarRad"] is not None: data["SolarRad"] = get_solar_rad(data["SolarRad"]) if data["ForecastRuleNo"] is not None: - # data["ForecastRuleNo"] = get_forecast_string(data["ForecastRuleNo"]) data["ForecastRuleNo"] = data["ForecastRuleNo"] data["RainCollector"] = self._rain_collector - if data["RainCollector"] != RAIN_COLLECTOR_IMPERIAL: - self.correct_rain_values(data) data["StormStartDate"] = self.strtodate(data["StormStartDate"]) + self.correct_rain_values(data) def correct_rain_values(self, data: dict[str, Any]): - if data["RainDay"] is not None: - data["RainDay"] *= 2 / 2.54 - if data["RainMonth"] is not None: - data["RainMonth"] *= 2 / 2.54 - if data["RainYear"] is not None: - data["RainYear"] *= 2 / 2.54 - if data["RainRate"] is not None: - data["RainRate"] *= 2 / 2.54 - if data["RainStorm"] is not None: - data["RainStorm"] *= 2 / 2.54 - if "RainRateDay" in data: - if data["RainRateDay"] is not None: - data["RainRateDay"] *= 2 / 2.54 + rain_collector_factor: dict[str, float] = { + RAIN_COLLECTOR_IMPERIAL: 1.0, + RAIN_COLLECTOR_METRIC: 2 / 2.54, + RAIN_COLLECTOR_METRIC_0_1: 1 / 2.54, + } + factor = rain_collector_factor.get(data["RainCollector"], 1.0) + for key in ["RainDay", "RainMonth", "RainYear", "RainRate", "RainStorm", "RainRateDay"]: + if key in data: + if data[key] is not None: + data[key] *= factor def remove_all_incorrect_data(self, raw_data: DataParser, data: LoopDataParserRevB): data_info = {key: value for key, value in LoopDataParserRevB.LOOP_FORMAT} @@ -431,3 +431,36 @@ def strtodate(self, date_str: str | None) -> date | None: def clear_cached_property(self, property_name: str): del self._vantagepro2.__dict__[property_name] + + def get_rain_collector(self) -> str: + rain_collector_map = { + 0x00: RAIN_COLLECTOR_IMPERIAL, + 0x10: RAIN_COLLECTOR_METRIC, + 0x20: RAIN_COLLECTOR_METRIC_0_1, + } + rain_collector = self._vantagepro2.get_rain_collector() # type: ignore + return rain_collector_map.get(rain_collector, "") # type: ignore + + async def async_get_rain_collector(self) -> str: + info = '' + try: + loop = asyncio.get_event_loop() + info = await loop.run_in_executor(None, self.get_rain_collector) + except Exception as e: + _LOGGER.error("Couldn't get rain collector: %s", e) + return info + + def set_rain_collector(self, rain_collector: str): + rain_collector_map = { + RAIN_COLLECTOR_IMPERIAL: 0x00, + RAIN_COLLECTOR_METRIC: 0x10, + RAIN_COLLECTOR_METRIC_0_1: 0x20, + } + self._vantagepro2.set_rain_collector(rain_collector_map.get(rain_collector, 0x00)) + + async def async_set_rain_collector(self, rain_collector: str): + try: + loop = asyncio.get_event_loop() + await loop.run_in_executor(None, self.set_rain_collector, rain_collector) + except Exception as e: + _LOGGER.error("Couldn't set rain collector: %s", e) diff --git a/custom_components/davis_vantage/config_flow.py b/custom_components/davis_vantage/config_flow.py index 6391e24..dae9d4f 100755 --- a/custom_components/davis_vantage/config_flow.py +++ b/custom_components/davis_vantage/config_flow.py @@ -16,13 +16,11 @@ NAME, DOMAIN, DEFAULT_SYNC_INTERVAL, - RAIN_COLLECTOR_IMPERIAL, - RAIN_COLLECTOR_METRIC, PROTOCOL_NETWORK, PROTOCOL_SERIAL, MODEL_VANTAGE_PRO2, MODEL_VANTAGE_PRO2PLUS, - CONFIG_RAIN_COLLECTOR, + MODEL_VANTAGE_VUE, CONFIG_STATION_MODEL, CONFIG_INTERVAL, CONFIG_MINIMAL_INTERVAL, @@ -37,9 +35,6 @@ vol.Required(CONFIG_INTERVAL, default=DEFAULT_SYNC_INTERVAL): vol.All( int, vol.Range(min=CONFIG_MINIMAL_INTERVAL) # type: ignore ), - vol.Required(CONFIG_RAIN_COLLECTOR): vol.In( - [RAIN_COLLECTOR_IMPERIAL, RAIN_COLLECTOR_METRIC] - ), } ) @@ -56,7 +51,7 @@ def __init__(self, hass: HomeAssistant) -> None: async def authenticate(self, protocol: str, link: str) -> bool: """Test if we can find data for the given link.""" _LOGGER.info("authenticate called") - client = DavisVantageClient(self._hass, protocol, link, "") + client = DavisVantageClient(self._hass, protocol, link) await client.connect_to_station() return (await client.async_get_davis_time()) is not None @@ -155,14 +150,11 @@ async def async_step_setup_other_info( step_user_data_schema = vol.Schema( { vol.Required(CONFIG_STATION_MODEL): vol.In( - [MODEL_VANTAGE_PRO2, MODEL_VANTAGE_PRO2PLUS] + [MODEL_VANTAGE_PRO2, MODEL_VANTAGE_PRO2PLUS, MODEL_VANTAGE_VUE] ), vol.Required(CONFIG_INTERVAL, default=DEFAULT_SYNC_INTERVAL): vol.All( int, vol.Range(min=CONFIG_MINIMAL_INTERVAL) # type: ignore ), - vol.Required(CONFIG_RAIN_COLLECTOR): vol.In( - [RAIN_COLLECTOR_IMPERIAL, RAIN_COLLECTOR_METRIC] - ), } ) diff --git a/custom_components/davis_vantage/const.py b/custom_components/davis_vantage/const.py index 097149f..1333179 100755 --- a/custom_components/davis_vantage/const.py +++ b/custom_components/davis_vantage/const.py @@ -3,13 +3,14 @@ NAME = "Davis Vantage" DOMAIN = "davis_vantage" MANUFACTURER = "Davis" -VERSION = "1.3.6" +VERSION = "1.3.7" DEFAULT_SYNC_INTERVAL = 30 # seconds DEFAULT_NAME = NAME RAIN_COLLECTOR_IMPERIAL = '0.01"' RAIN_COLLECTOR_METRIC = '0.2 mm' +RAIN_COLLECTOR_METRIC_0_1 = '0.1 mm' PROTOCOL_NETWORK = 'Network' PROTOCOL_SERIAL = 'Serial' @@ -20,12 +21,12 @@ SERVICE_GET_INFO = 'get_info' SERVICE_SET_YEARLY_RAIN = 'set_yearly_rain' SERVICE_SET_ARCHIVE_PERIOD = 'set_archive_period' +SERVICE_SET_RAIN_COLLECTOR = 'set_rain_collector' MODEL_VANTAGE_PRO2 = 'Vantage Pro2' MODEL_VANTAGE_PRO2PLUS = 'Vantage Pro2 Plus' MODEL_VANTAGE_VUE = 'Vantage Vue' -CONFIG_RAIN_COLLECTOR = "rain_collector" CONFIG_STATION_MODEL = "station_model" CONFIG_INTERVAL = "interval" CONFIG_MINIMAL_INTERVAL = 5 diff --git a/custom_components/davis_vantage/icons.json b/custom_components/davis_vantage/icons.json index bf6bc85..3d10101 100755 --- a/custom_components/davis_vantage/icons.json +++ b/custom_components/davis_vantage/icons.json @@ -5,7 +5,8 @@ "get_raw_data": "mdi:export", "get_info": "mdi:information-box-outline", "set_yearly_rain": "mdi:weather-pouring", - "set_archive_period": "mdi:archive-clock-outline" + "set_archive_period": "mdi:archive-clock-outline", + "set_rain_collector": "mdi:bucket-outline" }, "entity": { "sensor": { diff --git a/custom_components/davis_vantage/manifest.json b/custom_components/davis_vantage/manifest.json index 9580b60..308ef04 100755 --- a/custom_components/davis_vantage/manifest.json +++ b/custom_components/davis_vantage/manifest.json @@ -10,8 +10,8 @@ "homekit": {}, "iot_class": "local_polling", "issue_tracker": "https://github.com/MarcoGos/davis_vantage/issues", - "requirements": ["PyVantagePro-MarcoGos==0.3.17"], + "requirements": ["PyVantagePro-MarcoGos==0.3.21"], "ssdp": [], - "version": "1.3.6", + "version": "1.3.7", "zeroconf": [] } diff --git a/custom_components/davis_vantage/sensor.py b/custom_components/davis_vantage/sensor.py index 2e0c00d..a2d742b 100755 --- a/custom_components/davis_vantage/sensor.py +++ b/custom_components/davis_vantage/sensor.py @@ -33,6 +33,7 @@ DOMAIN, RAIN_COLLECTOR_IMPERIAL, RAIN_COLLECTOR_METRIC, + RAIN_COLLECTOR_METRIC_0_1, CONFIG_STATION_MODEL, MODEL_VANTAGE_PRO2PLUS, KEY_TO_NAME @@ -437,7 +438,8 @@ def get_sensor_descriptions(model: str) -> list[SensorEntityDescription]: device_class=SensorDeviceClass.ENUM, options=[ RAIN_COLLECTOR_IMPERIAL, - RAIN_COLLECTOR_METRIC + RAIN_COLLECTOR_METRIC, + RAIN_COLLECTOR_METRIC_0_1 ] ), SensorEntityDescription( diff --git a/custom_components/davis_vantage/services.yaml b/custom_components/davis_vantage/services.yaml index 78d63f8..bf219ad 100755 --- a/custom_components/davis_vantage/services.yaml +++ b/custom_components/davis_vantage/services.yaml @@ -24,4 +24,14 @@ set_archive_period: - "30" - "60" - "120" - +set_rain_collector: + fields: + rain_collector: + required: true + example: "0.2 mm" + selector: + select: + options: + - "0.01\"" + - "0.2 mm" + - "0.1 mm" diff --git a/custom_components/davis_vantage/translations/de.json b/custom_components/davis_vantage/translations/de.json index 32c63e4..78a3c91 100755 --- a/custom_components/davis_vantage/translations/de.json +++ b/custom_components/davis_vantage/translations/de.json @@ -28,16 +28,14 @@ "setup_other_info": { "data": { "station_model": "Davis-Wetterstationsmodell", - "interval": "Intervall", - "rain_collector": "Regensammler" + "interval": "Intervall" } }, "reconfigure_confirm": { "description": "Neukonfiguration für {name}.", "data": { "link": "Hostname", - "interval": "Intervall", - "rain_collector": "Regensammler" + "interval": "Intervall" } } } @@ -502,6 +500,16 @@ "description": "Archivierungsperiode in Minuten" } } + }, + "set_rain_collector": { + "name": "Regensammler einstellen", + "description": "Die Regensammler einstellen (0.01\", 0.2 mm oder 0.1 mm)", + "fields": { + "rain_collector": { + "name": "Regensammler", + "description": "Regensammler Einstellung" + } + } } } } \ No newline at end of file diff --git a/custom_components/davis_vantage/translations/en.json b/custom_components/davis_vantage/translations/en.json index 3581795..41df9dc 100755 --- a/custom_components/davis_vantage/translations/en.json +++ b/custom_components/davis_vantage/translations/en.json @@ -28,16 +28,14 @@ "setup_other_info": { "data": { "station_model": "Davis weather station model", - "interval": "Interval", - "rain_collector": "Rain collector" + "interval": "Interval" } }, "reconfigure_confirm": { "description": "Update configuration for {name}.", "data": { "link": "Host", - "interval": "Interval", - "rain_collector": "Rain collector" + "interval": "Interval" } } } @@ -502,6 +500,16 @@ "description": "Archive Period in minutes" } } + }, + "set_rain_collector": { + "name": "Set rain collector", + "description": "Set the rain collector (0.01\", 0.2 mm or 0.1 mm)", + "fields": { + "rain_collector": { + "name": "Regen Collector", + "description": "Rain Collector setting" + } + } } } } \ No newline at end of file diff --git a/custom_components/davis_vantage/translations/nl.json b/custom_components/davis_vantage/translations/nl.json index 4bca571..bf24501 100755 --- a/custom_components/davis_vantage/translations/nl.json +++ b/custom_components/davis_vantage/translations/nl.json @@ -28,16 +28,14 @@ "setup_other_info": { "data": { "station_model": "Davis weerstation model", - "interval": "Interval", - "rain_collector": "Regenmeter" + "interval": "Interval" } }, "reconfigure_confirm": { "description": "Bijwerken configuratie voor {name}.", "data": { "link": "Hostnaam", - "interval": "Interval", - "rain_collector": "Regenmeter" + "interval": "Interval" } } } @@ -502,6 +500,16 @@ "description": "Archiefinterval in minuten" } } + }, + "set_rain_collector": { + "name": "Stel regenmeter in", + "description": "Stel de regenmeter in. Keuze uit 0.01\", 0.2 mm of 0.1 mm", + "fields": { + "rain_collector": { + "name": "Regenmeter", + "description": "Regenmeter instelling" + } + } } } } \ No newline at end of file