Skip to content

Commit

Permalink
Add cooler support
Browse files Browse the repository at this point in the history
  • Loading branch information
cgtobi authored and jabesq committed Aug 20, 2024
1 parent 0b87f6c commit 48475c9
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 17 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

-
- Expose camera person status
- Add NLE support
- Add proper energy support
- Add cooler support
- Add BNS support

### Changed

Expand Down
2 changes: 2 additions & 0 deletions fixtures/homesdata.json
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,8 @@
}
],
"therm_setpoint_default_duration": 120,
"temperature_control_mode": "cooling",
"cooling_mode": "schedule",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
Expand Down
3 changes: 1 addition & 2 deletions src/pyatmo/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ def process_topology(self, disabled_homes_ids: list[str] | None = None) -> None:
disabled_homes_ids = []

for home in self.raw_data["homes"]:

home_id = home.get("id", "Unknown")
home_name = home.get("name", "Unknown")
self.all_homes_id[home_id] = home_name
Expand Down Expand Up @@ -237,7 +236,7 @@ async def update_devices(
{HOME: {"modules": [normalize_weather_attributes(device_data)]}},
)
else:
LOG.debug("No home %s found.", home_id)
LOG.debug("No home %s (%s) found.", home_id, home_id)

for module_data in device_data.get("modules", []):
module_data["home_id"] = home_id
Expand Down
3 changes: 2 additions & 1 deletion src/pyatmo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
SCHEDULES = "schedules"
EVENTS = "events"


STATION_TEMPERATURE_TYPE = "temperature"
STATION_PRESSURE_TYPE = "pressure"
STATION_HUMIDITY_TYPE = "humidity"
Expand All @@ -105,3 +104,5 @@

# 2 days of dynamic historical data stored
MAX_HISTORY_TIME_FRAME = 24 * 2 * 3600

UNKNOWN = "unknown"
20 changes: 20 additions & 0 deletions src/pyatmo/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ class Home:
persons: dict[str, Person]
events: dict[str, Event]

temperature_control_mode: str | None = None
therm_mode: str | None = None
therm_setpoint_default_duration: int | None = None
cooling_mode: str | None = None

def __init__(self, auth: AbstractAsyncAuth, raw_data: RawData) -> None:
"""Initialize a Netatmo home instance."""

Expand Down Expand Up @@ -76,6 +81,13 @@ def __init__(self, auth: AbstractAsyncAuth, raw_data: RawData) -> None:
}
self.events = {}

self.temperature_control_mode = raw_data.get("temperature_control_mode")
self.therm_mode = raw_data.get("therm_mode")
self.therm_setpoint_default_duration = raw_data.get(
"therm_setpoint_default_duration",
)
self.cooling_mode = raw_data.get("cooling_mode")

def get_module(self, module: dict) -> Module:
"""Return module."""

Expand All @@ -97,6 +109,14 @@ def update_topology(self, raw_data: RawData) -> None:
self.name = raw_data.get("name", "Unknown")

raw_modules = raw_data.get("modules", [])

self.temperature_control_mode = raw_data.get("temperature_control_mode")
self.therm_mode = raw_data.get("therm_mode")
self.therm_setpoint_default_duration = raw_data.get(
"therm_setpoint_default_duration",
)
self.cooling_mode = raw_data.get("cooling_mode")

for module in raw_modules:
if (module_id := module["id"]) not in self.modules:
self.modules[module_id] = self.get_module(module)
Expand Down
16 changes: 10 additions & 6 deletions src/pyatmo/modules/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ def __init__(self, home: Home, module: ModuleT):
self.boiler_status: bool | None = None


class CoolerMixin(EntityBase):
"""Mixin for cooler data."""

def __init__(self, home: Home, module: ModuleT):
"""Initialize cooler mixin."""

super().__init__(home, module) # type: ignore # mypy issue 4335
self.cooler_status: bool | None = None


class BatteryMixin(EntityBase):
"""Mixin for battery data."""

Expand Down Expand Up @@ -649,13 +659,11 @@ def compute_riemann_sum(

delta_energy = 0
if power_data and len(power_data) > 1:

# compute a rieman sum, as best as possible , trapezoidal, taking pessimistic asumption
# as we don't want to artifically go up the previous one
# (except in rare exceptions like reset, 0 , etc)

for i in range(len(power_data) - 1):

dt_h = float(power_data[i + 1][0] - power_data[i][0]) / 3600.0

if conservative:
Expand Down Expand Up @@ -713,7 +721,6 @@ def get_sum_energy_elec_power_adapted(
delta_energy = 0

if not self.in_reset:

if to_ts is None:
to_ts = int(time())

Expand Down Expand Up @@ -811,7 +818,6 @@ async def async_update_measures(
prev_sum_energy_elec if prev_sum_energy_elec is not None else "NOTHING",
)
else:

await self._prepare_exported_historical_data(
start_time,
end_time,
Expand All @@ -836,7 +842,6 @@ async def _prepare_exported_historical_data(
computed_end = 0
computed_end_for_calculus = 0
for cur_start_time, val, vals in hist_good_vals:

self.sum_energy_elec += val

modes = []
Expand Down Expand Up @@ -971,7 +976,6 @@ def _get_energy_filers(self):
return ENERGY_FILTERS

async def _energy_API_calls(self, start_time, end_time, interval):

filters = self._get_energy_filers()

params = {
Expand Down
10 changes: 8 additions & 2 deletions src/pyatmo/modules/smarther.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@

import logging

from pyatmo.modules.module import BoilerMixin, FirmwareMixin, Module, WifiMixin
from pyatmo.modules.module import (
BoilerMixin,
CoolerMixin,
FirmwareMixin,
Module,
WifiMixin,
)

LOG = logging.getLogger(__name__)


class BNS(FirmwareMixin, BoilerMixin, WifiMixin, Module):
class BNS(FirmwareMixin, BoilerMixin, CoolerMixin, WifiMixin, Module):
"""Smarther thermostat."""
39 changes: 34 additions & 5 deletions src/pyatmo/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
import logging
from typing import TYPE_CHECKING, Any

from pyatmo.const import FROSTGUARD, HOME, MANUAL, SETROOMTHERMPOINT_ENDPOINT, RawData
from pyatmo.const import (
FROSTGUARD,
HOME,
MANUAL,
SETROOMTHERMPOINT_ENDPOINT,
UNKNOWN,
RawData,
)
from pyatmo.modules.base_class import NetatmoBase
from pyatmo.modules.device_types import DeviceType

Expand All @@ -29,15 +36,25 @@ class Room(NetatmoBase):

climate_type: DeviceType | None = None

heating_power_request: int | None = None
humidity: int | None = None
therm_measured_temperature: float | None = None

reachable: bool | None = None

heating_power_request: int | None = None
therm_setpoint_temperature: float | None = None
therm_setpoint_mode: str | None = None
therm_measured_temperature: float | None = None
therm_setpoint_start_time: int | None = None
therm_setpoint_end_time: int | None = None

anticipating: bool | None = None
open_window: bool | None = None

cooling_setpoint_temperature: float | None = None
cooling_setpoint_start_time: int | None = None
cooling_setpoint_end_time: int | None = None
cooling_setpoint_mode: str | None = None

def __init__(
self,
home: Home,
Expand All @@ -60,7 +77,7 @@ def __init__(
def update_topology(self, raw_data: RawData) -> None:
"""Update room topology."""

self.name = raw_data["name"]
self.name = raw_data.get("name", UNKNOWN)
self.modules = {
m_id: m
for m_id, m in self.home.modules.items()
Expand Down Expand Up @@ -91,19 +108,31 @@ def evaluate_device_type(self) -> None:
def update(self, raw_data: RawData) -> None:
"""Update room data."""

self.heating_power_request = raw_data.get("heating_power_request")
self.humidity = raw_data.get("humidity")
if self.climate_type == DeviceType.BNTH:
# BNTH is wired, so the room is always reachable
self.reachable = True
else:
self.reachable = raw_data.get("reachable")

self.therm_measured_temperature = raw_data.get("therm_measured_temperature")

self.reachable = raw_data.get("reachable")

self.heating_power_request = raw_data.get("heating_power_request")
self.therm_setpoint_mode = raw_data.get("therm_setpoint_mode")
self.therm_setpoint_temperature = raw_data.get("therm_setpoint_temperature")
self.therm_setpoint_start_time = raw_data.get("therm_setpoint_start_time")
self.therm_setpoint_end_time = raw_data.get("therm_setpoint_end_time")

self.anticipating = raw_data.get("anticipating")
self.open_window = raw_data.get("open_window")

self.cooling_setpoint_temperature = raw_data.get("cooling_setpoint_temperature")
self.cooling_setpoint_start_time = raw_data.get("cooling_setpoint_start_time")
self.cooling_setpoint_end_time = raw_data.get("cooling_setpoint_end_time")
self.cooling_setpoint_mode = raw_data.get("cooling_setpoint_mode")

async def async_therm_manual(
self,
temp: float | None = None,
Expand Down
2 changes: 2 additions & 0 deletions tests/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ async def test_async_home(async_home):
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NOC

assert async_home.temperature_control_mode == "cooling"


@pytest.mark.asyncio
async def test_async_home_set_schedule(async_home):
Expand Down

0 comments on commit 48475c9

Please sign in to comment.