Skip to content

Commit

Permalink
More work on API V2
Browse files Browse the repository at this point in the history
  • Loading branch information
astrandb committed Sep 17, 2023
1 parent 1979098 commit 9a7c60a
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 59 deletions.
50 changes: 38 additions & 12 deletions custom_components/weatherlink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .config_flow import API_V1, API_V2
from .const import DOMAIN
from .const import (
CONF_API_KEY_V2,
CONF_API_SECRET,
CONF_API_TOKEN,
CONF_API_VERSION,
CONF_STATION_ID,
DOMAIN,
)
from .pyweatherlink import WLHub, WLHubV2

PLATFORMS = [Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]

_LOGGER = logging.getLogger(__name__)

Expand All @@ -27,20 +34,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {}
if entry.data["api_version"] == API_V1:
if entry.data[CONF_API_VERSION] == API_V1:
hass.data[DOMAIN][entry.entry_id]["api"] = WLHub(
websession=async_get_clientsession(hass),
username=entry.data["username"],
password=entry.data["password"],
apitoken=entry.data["apitoken"],
apitoken=entry.data[CONF_API_TOKEN],
)

if entry.data["api_version"] == API_V2:
if entry.data[CONF_API_VERSION] == API_V2:
hass.data[DOMAIN][entry.entry_id]["api"] = WLHubV2(
websession=async_get_clientsession(hass),
station_id=entry.data["station_id"],
api_key_v2=entry.data["api_key_v2"],
api_secret=entry.data["api_secret"],
station_id=entry.data[CONF_STATION_ID],
api_key_v2=entry.data[CONF_API_KEY_V2],
api_secret=entry.data[CONF_API_SECRET],
)
hass.data[DOMAIN][entry.entry_id]["station_data"] = await hass.data[DOMAIN][
entry.entry_id
Expand Down Expand Up @@ -74,8 +81,8 @@ async def get_coordinator(

def _preprocess(indata: str):
outdata = {}
_LOGGER.debug("Received data: %s", indata)
if entry.data["api_version"] == API_V1:
# _LOGGER.debug("Received data: %s", indata)
if entry.data[CONF_API_VERSION] == API_V1:
outdata["DID"] = indata["davis_current_observation"].get("DID")
outdata["station_name"] = indata["davis_current_observation"].get(
"station_name"
Expand All @@ -100,7 +107,7 @@ def _preprocess(indata: str):
outdata["rain_year"] = indata["davis_current_observation"].get(
"rain_year_in"
)
if entry.data["api_version"] == API_V2:
if entry.data[CONF_API_VERSION] == API_V2:
outdata["station_id_uuid"] = indata["station_id_uuid"]
for sensor in indata["sensors"]:
if sensor["sensor_type"] == 37 and sensor["data_structure_type"] == 10:
Expand All @@ -113,6 +120,21 @@ def _preprocess(indata: str):
outdata["rain_rate"] = sensor["data"][0]["rain_rate_last_in"]
outdata["rain_month"] = sensor["data"][0]["rainfall_monthly_in"]
outdata["rain_year"] = sensor["data"][0]["rainfall_year_in"]
outdata["trans_battery_flag"] = sensor["data"][0][
"trans_battery_flag"
]
if sensor["sensor_type"] == 37 and sensor["data_structure_type"] == 2:
outdata["temp_out"] = sensor["data"][0]["temp_out"]
outdata["temp_in"] = sensor["data"][0]["temp_in"]
outdata["bar_sea_level"] = sensor["data"][0]["bar"]
outdata["hum_out"] = sensor["data"][0]["hum_out"]
outdata["wind_mph"] = sensor["data"][0]["wind_speed"]
outdata["wind_dir"] = sensor["data"][0]["wind_dir"]
outdata["dewpoint"] = sensor["data"][0]["dew_point"]
outdata["rain_day"] = float(sensor["data"][0]["rain_day_in"])
outdata["rain_rate"] = sensor["data"][0]["rain_rate_in"]
outdata["rain_month"] = sensor["data"][0]["rain_month_in"]
outdata["rain_year"] = sensor["data"][0]["rain_year_in"]
if sensor["sensor_type"] == 37 and sensor["data_structure_type"] == 23:
outdata["temp_out"] = sensor["data"][0]["temp"]
outdata["hum_out"] = sensor["data"][0]["hum"]
Expand All @@ -123,6 +145,9 @@ def _preprocess(indata: str):
outdata["rain_rate"] = sensor["data"][0]["rain_rate_last_in"]
outdata["rain_month"] = sensor["data"][0]["rainfall_month_in"]
outdata["rain_year"] = sensor["data"][0]["rainfall_year_in"]
outdata["trans_battery_flag"] = sensor["data"][0][
"trans_battery_flag"
]
if sensor["sensor_type"] == 365 and sensor["data_structure_type"] == 21:
outdata["temp_in"] = sensor["data"][0]["temp_in"]
outdata["hum_in"] = sensor["data"][0]["hum_in"]
Expand All @@ -144,6 +169,7 @@ async def async_fetch():
async with async_timeout.timeout(10):
res = await api.request("GET")
json_data = await res.json()
hass.data[DOMAIN][entry.entry_id]["current"] = json_data
return _preprocess(json_data)
except ClientResponseError as exc:
_LOGGER.warning("API fetch failed. Status: %s, - %s", exc.code, exc.message)
Expand All @@ -167,7 +193,7 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
if config_entry.version == 1:
new_data = {**config_entry.data}

new_data["api_version"] = API_V1
new_data[CONF_API_VERSION] = API_V1

config_entry.version = 2
hass.config_entries.async_update_entry(config_entry, data=new_data)
Expand Down
127 changes: 127 additions & 0 deletions custom_components/weatherlink/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Platform for binary sensor integration."""
from __future__ import annotations

from dataclasses import dataclass
import logging
from typing import Final

from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from . import get_coordinator
from .config_flow import API_V1, API_V2
from .const import CONF_API_VERSION, DOMAIN
from .pyweatherlink import WLData

_LOGGER = logging.getLogger(__name__)


@dataclass
class WLBinarySensorDescription(BinarySensorEntityDescription):
"""Class describing Weatherlink binarysensor entities."""

tag: str | None = None
exclude: set = ()


SENSOR_TYPES: Final[tuple[WLBinarySensorDescription, ...]] = (
WLBinarySensorDescription(
key="TransmitterBattery",
tag="trans_battery_flag",
device_class=BinarySensorDeviceClass.BATTERY,
translation_key="trans_battery",
entity_category=EntityCategory.DIAGNOSTIC,
exclude=(API_V1,),
),
)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the binary sensor platform."""
coordinator = await get_coordinator(hass, config_entry)

async_add_entities(
WLSensor(coordinator, hass, config_entry, description)
for description in SENSOR_TYPES
if config_entry.data[CONF_API_VERSION] not in description.exclude
)


class WLSensor(CoordinatorEntity, BinarySensorEntity):
"""Representation of a Binary Sensor."""

entity_description: WLBinarySensorDescription
sensor_data = WLData()

def __init__(
self,
coordinator,
hass: HomeAssistant,
entry: ConfigEntry,
description: WLBinarySensorDescription,
):
"""Initialize the sensor."""
super().__init__(coordinator)
self.hass = hass
self.entry: ConfigEntry = entry
self.entity_description = description
self._attr_has_entity_name = True
self._attr_unique_id = (
f"{self.get_unique_id_base()}-{self.entity_description.key}"
)
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self.get_unique_id_base())},
name=self.generate_name(),
manufacturer="Davis",
model=self.generate_model(),
configuration_url="https://www.weatherlink.com/",
)

def get_unique_id_base(self):
"""Generate base for unique_id."""
unique_base = None
if self.entry.data[CONF_API_VERSION] == API_V1:
unique_base = self.coordinator.data["DID"]
if self.entry.data[CONF_API_VERSION] == API_V2:
unique_base = self.coordinator.data["station_id_uuid"]
return unique_base

def generate_name(self):
"""Generate device name."""
if self.entry.data[CONF_API_VERSION] == API_V1:
return self.coordinator.data["station_name"]
if self.entry.data[CONF_API_VERSION] == API_V2:
return self.hass.data[DOMAIN][self.entry.entry_id]["station_data"][
"stations"
][0]["station_name"]

return "Unknown devicename"

def generate_model(self):
"""Generate model string."""
if self.entry.data[CONF_API_VERSION] == API_V1:
return "Weatherlink - API V1"
if self.entry.data[CONF_API_VERSION] == API_V2:
model = self.hass.data[DOMAIN][self.entry.entry_id]["station_data"][
"stations"
][0].get("product_number")
return f"Weatherlink {model}"
return "Weatherlink"

@property
def is_on(self):
"""Return the state of the sensor."""
# _LOGGER.debug("Key: %s", self.entity_description.key)
return self.coordinator.data.get(self.entity_description.tag)
Loading

0 comments on commit 9a7c60a

Please sign in to comment.