Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding more settings #3

Merged
merged 3 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions custom_components/webastoconnect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if result:
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

# await async_setup_services(hass)

return result


Expand All @@ -51,3 +49,19 @@ async def _async_setup(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_config_entry_first_refresh()

return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
for platform in PLATFORMS:
await hass.config_entries.async_forward_entry_unload(entry, platform)

hass.data[DOMAIN].pop(entry.entry_id)

return True


async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload config entry."""
await async_unload_entry(hass, entry)
await async_setup_entry(hass, entry)
11 changes: 11 additions & 0 deletions custom_components/webastoconnect/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dataclasses import dataclass

from homeassistant.components.binary_sensor import BinarySensorEntityDescription
from homeassistant.components.number import NumberEntityDescription
from homeassistant.components.sensor import SensorEntityDescription
from homeassistant.components.switch import SwitchEntityDescription

Expand Down Expand Up @@ -45,3 +46,13 @@ class WebastoConnectSwitchEntityDescription(
command_fn: Callable[[WebastoConnect], None] = None
type_fn: Callable[[WebastoConnect], None] = None
name_fn: Callable[[WebastoConnect], None] = None


@dataclass
class WebastoConnectNumberEntityDescription(
NumberEntityDescription, WebastoConnectBaseEntityDescriptionMixin
):
"""Describes a Webasto number."""

set_fn: Callable[[WebastoConnect], None] = None
unit_fn: Callable[["WebastoConnect"], None] = None
2 changes: 1 addition & 1 deletion custom_components/webastoconnect/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

DOMAIN = "webastoconnect"

PLATFORMS = ["binary_sensor", "switch", "sensor", "device_tracker"]
PLATFORMS = ["binary_sensor", "switch", "sensor", "device_tracker", "number"]

NEW_DATA = "webasto_signal"

Expand Down
124 changes: 124 additions & 0 deletions custom_components/webastoconnect/number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""Support for number entities in Webasto Connect."""

import logging
from typing import Any, cast

from homeassistant.components import number
from homeassistant.components.number import NumberEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import callback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import slugify as util_slugify

from .api import WebastoConnectUpdateCoordinator
from .base import WebastoConnectNumberEntityDescription
from .const import ATTR_COORDINATOR, DOMAIN

LOGGER = logging.getLogger(__name__)

NUMBERS = [
WebastoConnectNumberEntityDescription(
key="low_voltage_cutoff",
name="Low Voltage Cutoff",
entity_category=EntityCategory.CONFIG,
value_fn=lambda webasto: webasto.low_voltage_cutoff,
set_fn=lambda webasto, state: webasto.set_low_voltage_cutoff(state),
native_min_value=0,
native_max_value=30,
native_step=0.1,
native_unit_of_measurement="V",
entity_registry_enabled_default=False,
icon="mdi:battery-off",
),
WebastoConnectNumberEntityDescription(
key="ext_temp_comp",
name="Temperature Compensation",
entity_category=EntityCategory.CONFIG,
value_fn=lambda webasto: webasto.temperature_compensation,
set_fn=lambda webasto, state: webasto.set_temperature_compensation(state),
native_min_value=-10,
native_max_value=10,
native_step=0.5,
unit_fn=lambda webasto: webasto.temperature_unit,
entity_registry_enabled_default=False,
icon="mdi:thermometer-alert",
),
]


async def async_setup_entry(hass, entry: ConfigEntry, async_add_devices):
"""Setup switch."""
numbers_list = []

coordinator = hass.data[DOMAIN][entry.entry_id][ATTR_COORDINATOR]

for number in NUMBERS:
entity = WebastoConnectNumber(number, coordinator)
LOGGER.debug(
"Adding number '%s' with entity_id '%s'", number.name, entity.entity_id
)
numbers_list.append(entity)

async_add_devices(numbers_list)


class WebastoConnectNumber(CoordinatorEntity, NumberEntity):
"""Representation of a Webasto Connect number."""

def __init__(
self,
description: WebastoConnectNumberEntityDescription,
coordinator: WebastoConnectUpdateCoordinator,
) -> None:
"""Initialize a Webasto Connect number."""
super().__init__(coordinator)

self.entity_description = description
self._config = coordinator.entry
self.coordinator = coordinator
self._hass = coordinator.hass

self._attr_name = self.entity_description.name
self._attr_unique_id = util_slugify(
f"{self._attr_name}_{self._config.entry_id}"
)
self._attr_should_poll = False
self._attr_device_info = {
"identifiers": {(DOMAIN, self.coordinator.cloud.device_id)},
"name": self.name,
"model": "ThermoConnect",
"manufacturer": "Webasto",
}

if not isinstance(description.unit_fn, type(None)):
self._attr_native_unit_of_measurement = description.unit_fn(
coordinator.cloud
)

self.entity_id = number.ENTITY_ID_FORMAT.format(
util_slugify(f"{self.coordinator.cloud.name} {self._attr_name}")
)

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self.async_write_ha_state()

@property
def native_value(self) -> float | None:
"""Get the native value."""
LOGGER.debug(
"Native value for '%s' is '%s'",
self.entity_id,
self.entity_description.value_fn(self.coordinator.cloud),
)
return cast(float, self.entity_description.value_fn(self.coordinator.cloud))

async def async_set_native_value(self, value: float) -> None:
"""Set new value."""
LOGGER.debug("Setting '%s' to '%s'", self.entity_id, value)
await self._hass.async_add_executor_job(
self.entity_description.set_fn, self.coordinator.cloud, value
)
await self.coordinator.async_refresh()
7 changes: 7 additions & 0 deletions custom_components/webastoconnect/pywebasto/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Module for interfacing with Webasto Connect."""

from datetime import datetime
import json
import threading
from typing import Any
Expand Down Expand Up @@ -301,6 +302,12 @@ def output_name(self) -> str:
"""Get the main output name."""
return self._mainOutput["name"]

@property
def subscription_expiration(self) -> datetime:
"""Get subscription expiration."""
expiration = self._dev_data["subscription"]["expiration"]
return datetime.fromtimestamp(expiration)

def __get_value(self, group: str, key: str) -> Any:
"""Get a value from the settings dict."""
for g in self._settings["settings_tab"]:
Expand Down
12 changes: 11 additions & 1 deletion custom_components/webastoconnect/sensor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Sensors for Webasto Connect."""

import logging
from typing import cast

import homeassistant.util.dt as dt_util
from homeassistant.components import sensor
from homeassistant.components.sensor import (
SensorDeviceClass,
Expand Down Expand Up @@ -42,6 +42,16 @@
value_fn=lambda webasto: webasto.voltage,
icon="mdi:car-battery",
),
WebastoConnectSensorEntityDescription(
key="subscription_expiration",
name="Subscription Expiration",
entity_category=EntityCategory.DIAGNOSTIC,
state_class=None,
device_class=None,
entity_registry_enabled_default=False,
value_fn=lambda webasto: webasto.subscription_expiration.strftime("%d-%m-%Y"),
icon="mdi:calendar-end",
),
]


Expand Down
8 changes: 4 additions & 4 deletions custom_components/webastoconnect/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

LOGGER = logging.getLogger(__name__)

BINARY_SENSORS = [
SWITCHES = [
WebastoConnectSwitchEntityDescription(
key="main_output",
name="Output",
Expand All @@ -44,10 +44,10 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_devices):

coordinator = hass.data[DOMAIN][entry.entry_id][ATTR_COORDINATOR]

for b_s in BINARY_SENSORS:
entity = WebastoConnectSwitch(b_s, coordinator)
for sw in SWITCHES:
entity = WebastoConnectSwitch(sw, coordinator)
LOGGER.debug(
"Adding switch '%s' with entity_id '%s'", b_s.name, entity.entity_id
"Adding switch '%s' with entity_id '%s'", sw.name, entity.entity_id
)
switches.append(entity)

Expand Down
Loading