diff --git a/custom_components/davis_vantage/__init__.py b/custom_components/davis_vantage/__init__.py index 4b8c5f7..7b0e8b5 100755 --- a/custom_components/davis_vantage/__init__.py +++ b/custom_components/davis_vantage/__init__.py @@ -13,12 +13,18 @@ from .const import ( DOMAIN, NAME, - VERSION, MANUFACTURER, + RAIN_COLLECTOR_IMPERIAL, SERVICE_SET_DAVIS_TIME, SERVICE_GET_DAVIS_TIME, SERVICE_GET_RAW_DATA, - SERVICE_GET_INFO + SERVICE_GET_INFO, + CONFIG_RAIN_COLLECTOR, + CONFIG_STATION_MODEL, + CONFIG_INTERVAL, + CONFIG_WINDROSE8, + CONFIG_PROTOCOL, + CONFIG_LINK ) from .coordinator import DavisVantageDataUpdateCoordinator from .utils import convert_to_iso_datetime @@ -40,14 +46,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: _LOGGER.debug("entry.data: %s", entry.data) - protocol = entry.data.get("protocol", "") - link = entry.data.get("link", "") - rain_collector = entry.data.get("rain_collector", "0.01""") - windrose8 = entry.data.get("windrose8", False) + protocol = entry.data.get(CONFIG_PROTOCOL, "") + link = entry.data.get(CONFIG_LINK, "") + rain_collector = entry.data.get(CONFIG_RAIN_COLLECTOR, RAIN_COLLECTOR_IMPERIAL) + windrose8 = entry.data.get(CONFIG_WINDROSE8, False) - hass.data[DOMAIN]['interval'] = entry.data.get("interval", 30) + hass.data[DOMAIN]['interval'] = entry.data.get(CONFIG_INTERVAL, 30) client = DavisVantageClient(hass, protocol, link, rain_collector, windrose8) + await client.connect_to_station() info = await client.async_get_info() firmware_version = info.get('version', None) if info is not None else None @@ -55,7 +62,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: identifiers={(DOMAIN, entry.entry_id)}, manufacturer=MANUFACTURER, name=NAME, - model=VERSION, + model=entry.data.get(CONFIG_STATION_MODEL, "Unknown"), sw_version=firmware_version, hw_version=None ) @@ -86,7 +93,7 @@ async def get_raw_data(call: ServiceCall) -> dict[str, Any]: raw_data = client.get_raw_data() json_data = safe_serialize(raw_data) return json.loads(json_data) - + async def get_info(call: ServiceCall) -> dict[str, Any]: info = await client.async_get_info() if info is not None: diff --git a/custom_components/davis_vantage/client.py b/custom_components/davis_vantage/client.py index 99331dd..2618d19 100755 --- a/custom_components/davis_vantage/client.py +++ b/custom_components/davis_vantage/client.py @@ -32,6 +32,7 @@ class DavisVantageClient: """Davis Vantage Client class""" + _vantagepro2: VantagePro2 = None def __init__( self, hass: HomeAssistant, @@ -47,8 +48,29 @@ def __init__( self._rain_collector = rain_collector self._last_data: LoopDataParserRevB = {} # type: ignore self._last_raw_data: DataParser = {} # type: ignore - self._vantagepro2 = VantagePro2.from_url(self.get_link()) - self._vantagepro2.link.close() + + def get_vantagepro2fromurl(self, url: str) -> VantagePro2 | None: + vp = None + try: + vp = VantagePro2.from_url(url) + except Exception as e: + raise e + finally: + vp.link.close() + return vp + + async def async_get_vantagepro2fromurl(self, url: str) -> VantagePro2 | None: + _LOGGER.debug('async_get_vantagepro2fromurl with url=%s', url) + vp = None + try: + loop = asyncio.get_event_loop() + vp = await loop.run_in_executor(None, self.get_vantagepro2fromurl, url) + except Exception as e: + _LOGGER.error('Error on opening device from url: %s: %s', url, e) + return vp + + async def connect_to_station(self): + self._vantagepro2 = await self.async_get_vantagepro2fromurl(self.get_link()) def get_current_data(self) -> LoopDataParserRevB | None: """Get current date from weather station.""" diff --git a/custom_components/davis_vantage/config_flow.py b/custom_components/davis_vantage/config_flow.py index eacbd51..7a5cb8f 100755 --- a/custom_components/davis_vantage/config_flow.py +++ b/custom_components/davis_vantage/config_flow.py @@ -20,6 +20,15 @@ RAIN_COLLECTOR_METRIC, PROTOCOL_NETWORK, PROTOCOL_SERIAL, + MODEL_VANTAGE_PRO2, + MODEL_VANTAGE_PRO2PLUS, + MODEL_VANTAGE_VUE, + CONFIG_RAIN_COLLECTOR, + CONFIG_STATION_MODEL, + CONFIG_INTERVAL, + CONFIG_WINDROSE8, + CONFIG_PROTOCOL, + CONFIG_LINK ) from .client import DavisVantageClient @@ -37,6 +46,7 @@ async def authenticate(self, protocol: str, link: str) -> bool: """Test if we can find data for the given link.""" _LOGGER.info(f"authenticate called") client = DavisVantageClient(self._hass, protocol, link, "", False) + await client.connect_to_station() return await client.async_get_davis_time() != None @@ -46,7 +56,7 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user. """ hub = PlaceholderHub(hass) - if not await hub.authenticate(data["protocol"], data["link"]): + if not await hub.authenticate(data[CONFIG_PROTOCOL], data[CONFIG_LINK]): raise InvalidAuth # Return info that you want to store in the config entry. @@ -65,21 +75,24 @@ async def async_step_user( ) -> FlowResult: """Handle the initial step.""" if user_input is not None: - self.protocol = user_input["protocol"] + self.protocol = user_input[CONFIG_PROTOCOL] if self.protocol == PROTOCOL_SERIAL: return await self.async_step_setup_serial() return await self.async_step_setup_network() - list_of_types = [PROTOCOL_SERIAL, PROTOCOL_NETWORK] - schema = vol.Schema({vol.Required("protocol"): vol.In(list_of_types)}) + list_of_types = [ + PROTOCOL_SERIAL, + PROTOCOL_NETWORK + ] + schema = vol.Schema({vol.Required(CONFIG_PROTOCOL): vol.In(list_of_types)}) return self.async_show_form(step_id="user", data_schema=schema) async def async_step_setup_serial( self, user_input: dict[str, Any] | None = None ) -> FlowResult: if user_input is not None: - self.link = user_input["link"] + self.link = user_input[CONFIG_LINK] return await self.async_step_setup_other_info() ports = await self.hass.async_add_executor_job(serial.tools.list_ports.comports) @@ -90,7 +103,7 @@ async def async_step_setup_serial( } STEP_USER_DATA_SCHEMA = vol.Schema( - {vol.Required("link"): vol.In(list_of_ports)} + {vol.Required(CONFIG_LINK): vol.In(list_of_ports)} ) return self.async_show_form( @@ -101,10 +114,10 @@ async def async_step_setup_network( self, user_input: dict[str, Any] | None = None ) -> FlowResult: if user_input is not None: - self.link = user_input["link"] + self.link = user_input[CONFIG_LINK] return await self.async_step_setup_other_info() - STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required("link"): str}) + STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONFIG_LINK): str}) return self.async_show_form( step_id="setup_network", data_schema=STEP_USER_DATA_SCHEMA @@ -117,8 +130,8 @@ async def async_step_setup_other_info( if user_input is not None: await self.async_set_unique_id(DOMAIN) self._abort_if_unique_id_configured() - user_input["protocol"] = self.protocol - user_input["link"] = self.link + user_input[CONFIG_PROTOCOL] = self.protocol + user_input[CONFIG_LINK] = self.link try: info = await validate_input(self.hass, user_input) except CannotConnect: @@ -131,15 +144,24 @@ async def async_step_setup_other_info( else: return self.async_create_entry(title=info["title"], data=user_input) - list_of_rain_collector = [RAIN_COLLECTOR_IMPERIAL, RAIN_COLLECTOR_METRIC] + list_of_rain_collector = [ + RAIN_COLLECTOR_IMPERIAL, + RAIN_COLLECTOR_METRIC + ] + list_of_station_models = [ + MODEL_VANTAGE_PRO2, + MODEL_VANTAGE_PRO2PLUS, + MODEL_VANTAGE_VUE + ] STEP_USER_DATA_SCHEMA = vol.Schema( { + vol.Required(CONFIG_STATION_MODEL): vol.In(list_of_station_models), vol.Required( - "interval", + CONFIG_INTERVAL, default=DEFAULT_SYNC_INTERVAL): vol.All(int, vol.Range(min=5) # type: ignore ), - vol.Required("rain_collector"): vol.In(list_of_rain_collector), - vol.Required("windrose8"): bool, + vol.Required(CONFIG_RAIN_COLLECTOR): vol.In(list_of_rain_collector), + vol.Required(CONFIG_WINDROSE8): bool, } ) diff --git a/custom_components/davis_vantage/const.py b/custom_components/davis_vantage/const.py index 5df3673..ea5143f 100755 --- a/custom_components/davis_vantage/const.py +++ b/custom_components/davis_vantage/const.py @@ -19,3 +19,14 @@ SERVICE_GET_DAVIS_TIME = 'get_davis_time' SERVICE_GET_RAW_DATA = 'get_raw_data' SERVICE_GET_INFO = 'get_info' + +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_WINDROSE8 = "windrose8" +CONFIG_PROTOCOL = "protocol" +CONFIG_LINK = "link" diff --git a/custom_components/davis_vantage/sensor.py b/custom_components/davis_vantage/sensor.py index 4d0ac83..77fff41 100755 --- a/custom_components/davis_vantage/sensor.py +++ b/custom_components/davis_vantage/sensor.py @@ -1,3 +1,4 @@ +import logging from homeassistant.components.sensor import ( DOMAIN as SENSOR_DOMAIN, SensorEntity, @@ -22,7 +23,13 @@ from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DEFAULT_NAME, DOMAIN +from .const import ( + DEFAULT_NAME, + DOMAIN, + CONFIG_STATION_MODEL, + MODEL_VANTAGE_PRO2PLUS +) + from .coordinator import DavisVantageDataUpdateCoordinator DESCRIPTIONS: list[SensorEntityDescription] = [ @@ -381,6 +388,8 @@ ) ] +_LOGGER: logging.Logger = logging.getLogger(__package__) + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, @@ -393,6 +402,9 @@ async def async_setup_entry( # Add all meter sensors described above. for description in DESCRIPTIONS: + if entry.data.get(CONFIG_STATION_MODEL, '') == MODEL_VANTAGE_PRO2PLUS: + if description.key in ["SolarRad", "UV"]: + description.entity_registry_enabled_default = True entities.append( DavisVantageSensor( coordinator=coordinator, diff --git a/custom_components/davis_vantage/strings.json b/custom_components/davis_vantage/strings.json index 704dc29..45e36f6 100755 --- a/custom_components/davis_vantage/strings.json +++ b/custom_components/davis_vantage/strings.json @@ -18,6 +18,7 @@ }, "setup_other_info": { "data": { + "station_model": "[%key:common::config_flow::data::station_model%]", "interval": "[%key:common::config_flow::data::interval%]", "rain_collector": "[%key:common::config_flow::data::rain_collector%]", "windrose8": "[%key:common::config_flow::data::windrose8%]" diff --git a/custom_components/davis_vantage/translations/en.json b/custom_components/davis_vantage/translations/en.json index fda7e28..c84c267 100755 --- a/custom_components/davis_vantage/translations/en.json +++ b/custom_components/davis_vantage/translations/en.json @@ -26,6 +26,7 @@ }, "setup_other_info": { "data": { + "station_model": "Davis weather station model", "interval": "Interval", "rain_collector": "Rain collector", "windrose8": "Wind rose with 8 cardinal directions" diff --git a/custom_components/davis_vantage/translations/nl.json b/custom_components/davis_vantage/translations/nl.json index 9d18388..74091c7 100755 --- a/custom_components/davis_vantage/translations/nl.json +++ b/custom_components/davis_vantage/translations/nl.json @@ -26,6 +26,7 @@ }, "setup_other_info": { "data": { + "station_model": "Davis weerstation model", "interval": "Interval", "rain_collector": "Regenmeter", "windrose8": "Windroos met 8 cardinale richtingen"