Skip to content

Commit

Permalink
Rain collector information is now read from the console/envoy, and ca…
Browse files Browse the repository at this point in the history
…n be changed by using an action.
  • Loading branch information
MarcoGos committed Feb 8, 2025
1 parent 22183d8 commit 5679fad
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 54 deletions.
25 changes: 20 additions & 5 deletions custom_components/davis_vantage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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 = (
Expand All @@ -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))
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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


Expand Down
71 changes: 52 additions & 19 deletions custom_components/davis_vantage/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
)
from .const import (
RAIN_COLLECTOR_IMPERIAL,
RAIN_COLLECTOR_METRIC,
RAIN_COLLECTOR_METRIC_0_1,
PROTOCOL_NETWORK,
)

Expand All @@ -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

Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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)
14 changes: 3 additions & 11 deletions custom_components/davis_vantage/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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]
),
}
)

Expand All @@ -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

Expand Down Expand Up @@ -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]
),
}
)

Expand Down
5 changes: 3 additions & 2 deletions custom_components/davis_vantage/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion custom_components/davis_vantage/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
4 changes: 2 additions & 2 deletions custom_components/davis_vantage/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": []
}
4 changes: 3 additions & 1 deletion custom_components/davis_vantage/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
12 changes: 11 additions & 1 deletion custom_components/davis_vantage/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
16 changes: 12 additions & 4 deletions custom_components/davis_vantage/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Expand Down Expand Up @@ -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"
}
}
}
}
}
Loading

0 comments on commit 5679fad

Please sign in to comment.