Skip to content

Commit

Permalink
fix: set schedule service
Browse files Browse the repository at this point in the history
  • Loading branch information
EuleMitKeule committed Jan 22, 2024
1 parent 0d8e216 commit e436efb
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 306 deletions.
9 changes: 7 additions & 2 deletions custom_components/eq3btsmart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

thermostat = Thermostat(
thermostat_config=thermostat_config,
device=device,
ble_device=device,
)

try:
await thermostat.async_connect()
except Exception as e:
raise ConfigEntryNotReady(f"Could not connect to device: {e}")

eq3_config_entry = Eq3ConfigEntry(eq3_config=eq3_config, thermostat=thermostat)

domain_data: dict[str, Any] = hass.data.setdefault(DOMAIN, {})
Expand All @@ -110,7 +115,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

if unload_ok:
eq3_config_entry: Eq3ConfigEntry = hass.data[DOMAIN].pop(entry.entry_id)
eq3_config_entry.thermostat.shutdown()
await eq3_config_entry.thermostat.async_disconnect()

return unload_ok

Expand Down
35 changes: 13 additions & 22 deletions custom_components/eq3btsmart/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""Platform for eQ-3 binary sensor entities."""


import json

from custom_components.eq3btsmart.eq3_entity import Eq3Entity
from custom_components.eq3btsmart.models import Eq3Config, Eq3ConfigEntry
from eq3btsmart import Thermostat
Expand Down Expand Up @@ -80,15 +78,13 @@ class BusySensor(Base):
def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._thermostat.register_connection_callback(self.schedule_update_ha_state)
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_name = ENTITY_NAME_BUSY

@property
def is_on(self) -> bool:
return self._thermostat._conn._lock.locked()
return self._thermostat._lock.locked()


class ConnectedSensor(Base):
Expand All @@ -97,30 +93,25 @@ class ConnectedSensor(Base):
def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._thermostat.register_connection_callback(self.schedule_update_ha_state)
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_name = ENTITY_NAME_CONNECTED
self._attr_device_class = BinarySensorDeviceClass.CONNECTIVITY

@property
def extra_state_attributes(self) -> dict[str, str] | None:
if (device := self._thermostat._conn._device) is None:
return None
if (details := device.details) is None:
return None
if "props" not in details:
return None
# @property
# def extra_state_attributes(self) -> dict[str, str] | None:
# if (device := self._thermostat._conn._device) is None:
# return None
# if (details := device.details) is None:
# return None
# if "props" not in details:
# return None

return json.loads(json.dumps(details["props"], default=lambda obj: None))
# return json.loads(json.dumps(details["props"], default=lambda obj: None))

@property
def is_on(self) -> bool:
if self._thermostat._conn._conn is None:
return False

return self._thermostat._conn._conn.is_connected
return self._thermostat._conn.is_connected


class BatterySensor(Base):
Expand Down
49 changes: 28 additions & 21 deletions custom_components/eq3btsmart/button.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"""Platform for eQ-3 button entities."""

import datetime
import logging
from typing import Any

from custom_components.eq3btsmart.eq3_entity import Eq3Entity
from custom_components.eq3btsmart.models import Eq3Config, Eq3ConfigEntry
from eq3btsmart import Thermostat
from eq3btsmart.const import WeekDay
from eq3btsmart.eq3_schedule_time import Eq3ScheduleTime
from eq3btsmart.eq3_temperature import Eq3Temperature
from eq3btsmart.models import Schedule, ScheduleDay, ScheduleHour
from homeassistant.components.button import ButtonEntity
from homeassistant.config_entries import ConfigEntry, UndefinedType
from homeassistant.const import WEEKDAYS
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_platform
from homeassistant.helpers.device_registry import format_mac
Expand Down Expand Up @@ -100,20 +101,30 @@ async def set_schedule(self, **kwargs) -> None:

schedule = Schedule()
for day in kwargs["days"]:
week_day = WeekDay[day.upper()]
index = WEEKDAYS.index(day)
week_day = WeekDay.from_index(index)

schedule_hours: list[ScheduleHour] = []
schedule_day = ScheduleDay(week_day=week_day, schedule_hours=schedule_hours)

times = [
kwargs.get(f"next_change_at_{i}", datetime.time(0, 0)) for i in range(6)
kwargs.get(f"next_change_at_{i}", None)
for i in range(6)
if f"next_change_at_{i}" in kwargs
]
# times[times.index(datetime.time(0, 0))] = HOUR_24_PLACEHOLDER
temps = [kwargs.get(f"target_temp_{i}", 0) for i in range(7)]
temps = [kwargs.get(f"target_temp_{i}", None) for i in range(6)]

times = list(filter(None, times))
temps = list(filter(None, temps))

if len(times) != len(temps) - 1:
raise ValueError("Times and temps must be of equal length")

for i in range(0, 6):
for time, temp in zip(times, temps):
schedule_hour = ScheduleHour(
target_temperature=temps[i],
next_change_at=times[i],
target_temperature=Eq3Temperature(temp),
next_change_at=Eq3ScheduleTime(time),
)
schedule_hours.append(schedule_hour)

Expand All @@ -125,19 +136,15 @@ async def set_schedule(self, **kwargs) -> None:
def extra_state_attributes(self):
schedule = {}
for day in self._thermostat.schedule.schedule_days:
day_nice: dict[str, Any] = {"day": day}
for i, schedule_hour in enumerate(day.schedule_hours):
day_nice[
f"target_temp_{i}"
] = schedule_hour.target_temperature.friendly_value
# if schedule_hour.next_change_at == HOUR_24_PLACEHOLDER:
# break
day_nice[
f"next_change_at_{i}"
] = schedule_hour.next_change_at.friendly_value.isoformat()
schedule[day] = day_nice

return schedule
schedule[str(day.week_day)] = [
{
"target_temperature": schedule_hour.target_temperature.friendly_value,
"next_change_at": schedule_hour.next_change_at.friendly_value.isoformat(),
}
for schedule_hour in day.schedule_hours
]

return {"schedule": schedule}


class FetchButton(Base):
Expand Down
3 changes: 2 additions & 1 deletion custom_components/eq3btsmart/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from enum import Enum

from eq3btsmart.const import Adapter, OperationMode
from homeassistant.components.climate import HVACMode
from homeassistant.components.climate import PRESET_NONE, HVACMode
from homeassistant.components.climate.const import (
PRESET_AWAY,
PRESET_BOOST,
Expand Down Expand Up @@ -33,6 +33,7 @@


class Preset(str, Enum):
NONE = PRESET_NONE
ECO = PRESET_ECO
COMFORT = PRESET_COMFORT
BOOST = PRESET_BOOST
Expand Down
16 changes: 16 additions & 0 deletions custom_components/eq3btsmart/eq3_coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from datetime import timedelta
from logging import Logger

from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator


class Eq3Coordinator(DataUpdateCoordinator):
def __init__(
self,
hass: HomeAssistant,
logger: Logger,
name: str,
update_interval: timedelta | None,
):
super().__init__(hass, logger, name=name, update_interval=update_interval)
51 changes: 2 additions & 49 deletions custom_components/eq3btsmart/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
ENTITY_NAME_AWAY_END,
ENTITY_NAME_FIRMWARE_VERSION,
ENTITY_NAME_MAC,
ENTITY_NAME_PATH,
ENTITY_NAME_RETRIES,
ENTITY_NAME_RSSI,
ENTITY_NAME_SERIAL_NUMBER,
ENTITY_NAME_VALVE,
Expand Down Expand Up @@ -54,8 +52,6 @@ async def async_setup_entry(
new_devices += [
RssiSensor(eq3_config, thermostat),
MacSensor(eq3_config, thermostat),
RetriesSensor(eq3_config, thermostat),
PathSensor(eq3_config, thermostat),
]

async_add_entities(new_devices)
Expand Down Expand Up @@ -123,17 +119,14 @@ class RssiSensor(Base):
def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._thermostat.register_connection_callback(self.schedule_update_ha_state)
self._attr_name = ENTITY_NAME_RSSI
self._attr_native_unit_of_measurement = SIGNAL_STRENGTH_DECIBELS_MILLIWATT
self._attr_entity_category = EntityCategory.DIAGNOSTIC

@property
def state(self) -> int | None:
return None
return self._thermostat._conn.rssi
return self._thermostat._device._rssi


class SerialNumberSensor(Base):
Expand Down Expand Up @@ -204,43 +197,3 @@ def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
@property
def state(self) -> str | None:
return self._eq3_config.mac_address


class RetriesSensor(Base):
"""Sensor for the number of retries."""

def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._attr_name = ENTITY_NAME_RETRIES
self._attr_entity_category = EntityCategory.DIAGNOSTIC

@property
def state(self) -> int:
return self._thermostat._conn.retries


class PathSensor(Base):
"""Sensor for the device path."""

def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._attr_name = ENTITY_NAME_PATH
self._attr_entity_category = EntityCategory.DIAGNOSTIC

@property
def state(self) -> str | None:
if self._thermostat._conn._conn is None:
return None

if not hasattr(self._thermostat._conn._conn._backend, "_device_path"):
return None

return self._thermostat._conn._conn._backend._device_path
13 changes: 4 additions & 9 deletions custom_components/eq3btsmart/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,23 +129,18 @@ class ConnectionSwitch(Base):
def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat._conn.register_connection_callback(
self.schedule_update_ha_state
)
self._thermostat.register_connection_callback(self.schedule_update_ha_state)
self._attr_name = ENTITY_NAME_CONNECTION
self._attr_icon = ENTITY_ICON_CONNECTION
self._attr_assumed_state = True
self._attr_entity_category = EntityCategory.DIAGNOSTIC

async def async_turn_on(self, **kwargs: Any) -> None:
await self._thermostat._conn.async_make_request()
await self._thermostat.async_connect()

async def async_turn_off(self, **kwargs: Any) -> None:
if self._thermostat._conn._conn:
await self._thermostat._conn._conn.disconnect()
await self._thermostat.async_disconnect()

@property
def is_on(self) -> bool | None:
if self._thermostat._conn._conn is None:
return None
return self._thermostat._conn._conn.is_connected
return self._thermostat._conn.is_connected
1 change: 0 additions & 1 deletion eq3btsmart/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
from eq3btsmart.bleakconnection import BleakConnection as BleakConnection
from eq3btsmart.thermostat import Thermostat as Thermostat
Loading

0 comments on commit e436efb

Please sign in to comment.