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

Improvements mostly from jnxxx #43

Merged
merged 20 commits into from
Oct 24, 2022
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
41 changes: 34 additions & 7 deletions custom_components/danfoss_ally/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Adds support for Danfoss Ally Gateway."""
import asyncio
import logging
from datetime import timedelta
from datetime import datetime, timedelta

import voluptuous as vol
from homeassistant.components.climate.const import PRESET_AWAY, PRESET_HOME
Expand Down Expand Up @@ -89,11 +89,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
_LOGGER.error("Error authorizing")
return False

await hass.async_add_executor_job(allyconnector.update)
async def _update(now):
"""Periodic update."""
await allyconnector.async_update()
await _update(None)

update_track = async_track_time_interval(
hass,
lambda now: allyconnector.update(),
_update,
timedelta(seconds=SCAN_INTERVAL),
)

Expand Down Expand Up @@ -148,6 +151,8 @@ def __init__(self, hass, key, secret):
self._secret = secret
self.ally = DanfossAlly()
self._authorized = False
self._latest_write_time = datetime.min
self._latest_poll_time = datetime.min

def setup(self) -> None:
"""Setup API connection."""
Expand All @@ -156,10 +161,20 @@ def setup(self) -> None:
self._authorized = auth

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self) -> None:
async def async_update(self) -> None:
"""Update API data."""
_LOGGER.debug("Updating Danfoss Ally devices")
self.ally.getDeviceList()

# Postpone poll if a recent change were made - Attempt to avoid UI glitches
seconds_since_write = (datetime.utcnow() - self._latest_write_time).total_seconds()
if (seconds_since_write < 1):
_LOGGER.debug("Seconds since last write %f. Postponing update for 1 sec.", seconds_since_write)
await asyncio.sleep(1)

# Poll API
await self.hass.async_add_executor_job(self.ally.getDeviceList) #self.ally.getDeviceList()
self._latest_poll_time = datetime.utcnow()

for device in self.ally.devices: # pylint: disable=consider-using-dict-items
_LOGGER.debug("%s: %s", device, self.ally.devices[device])
dispatcher_send(self.hass, SIGNAL_ALLY_UPDATE_RECEIVED)
Expand All @@ -169,14 +184,26 @@ def devices(self):
"""Return device list from API."""
return self.ally.devices

def set_temperature(self, device_id: str, temperature: float) -> None:
def set_temperature(self, device_id: str, temperature: float, code = "manual_mode_fast") -> None:
"""Set temperature for device_id."""
self.ally.setTemperature(device_id, temperature)
self._latest_write_time = datetime.utcnow()
self.ally.setTemperature(device_id, temperature, code)

# Debug info - log if update was done approximately as the same time as write
seconds_since_poll = (datetime.utcnow() - self._latest_poll_time).total_seconds()
if (seconds_since_poll < 0.5):
_LOGGER.warn("set_temperature: Time since last poll %f sec.", seconds_since_poll)

def set_mode(self, device_id: str, mode: str) -> None:
"""Set operating mode for device_id."""
self._latest_write_time = datetime.utcnow()
self.ally.setMode(device_id, mode)

# Debug info - log if update was done approximately as the same time as write
seconds_since_poll = (datetime.utcnow() - self._latest_poll_time).total_seconds()
if (seconds_since_poll < 0.5):
_LOGGER.warn("set_mode: Time since last poll %f sec.", seconds_since_poll)

@property
def authorized(self) -> bool:
"""Return authorized state."""
Expand Down
34 changes: 26 additions & 8 deletions custom_components/danfoss_ally/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from homeassistant.components.binary_sensor import (
DEVICE_CLASS_CONNECTIVITY,
DEVICE_CLASS_LOCK,
DEVICE_CLASS_TAMPER,
DEVICE_CLASS_WINDOW,
BinarySensorEntity,
)
Expand Down Expand Up @@ -31,7 +32,7 @@ async def async_setup_entry(
entities.extend(
[
AllyBinarySensor(
ally, ally.devices[device]["name"], device, "open window"
ally, ally.devices[device]["name"], device, "open window", ally.devices[device]["model"]
)
]
)
Expand All @@ -42,7 +43,7 @@ async def async_setup_entry(
entities.extend(
[
AllyBinarySensor(
ally, ally.devices[device]["name"], device, "child lock"
ally, ally.devices[device]["name"], device, "child lock", ally.devices[device]["model"]
)
]
)
Expand All @@ -53,7 +54,18 @@ async def async_setup_entry(
entities.extend(
[
AllyBinarySensor(
ally, ally.devices[device]["name"], device, "connectivity"
ally, ally.devices[device]["name"], device, "connectivity", ally.devices[device]["model"]
)
]
)
if 'banner_ctrl' in ally.devices[device]:
_LOGGER.debug(
"Found banner_ctrl detector for %s", ally.devices[device]["name"]
)
entities.extend(
[
AllyBinarySensor(
ally, ally.devices[device]["name"], device, 'banner control', ally.devices[device]["model"]
)
]
)
Expand All @@ -65,13 +77,13 @@ async def async_setup_entry(
class AllyBinarySensor(AllyDeviceEntity, BinarySensorEntity):
"""Representation of an Ally binary_sensor."""

def __init__(self, ally, name, device_id, device_type):
def __init__(self, ally, name, device_id, device_type, model):
"""Initialize Ally binary_sensor."""
self._ally = ally
self._device = ally.devices[device_id]
self._device_id = device_id
self._type = device_type
super().__init__(name, device_id, device_type)
super().__init__(name, device_id, device_type, model)

_LOGGER.debug("Device_id: %s --- Device: %s", self._device_id, self._device)

Expand All @@ -86,9 +98,11 @@ def __init__(self, ally, name, device_id, device_type):
elif self._type == "open window":
self._state = bool(self._device["window_open"])
elif self._type == "child lock":
self._state = bool(self._device["child_lock"])
self._state = not bool(self._device["child_lock"])
elif self._type == "connectivity":
self._state = bool(self._device["online"])
elif self._type == "banner control":
self._state = bool(self._device["banner_ctrl"])

async def async_added_to_hass(self):
"""Register for sensor updates."""
Expand Down Expand Up @@ -123,10 +137,12 @@ def device_class(self):
return DEVICE_CLASS_CONNECTIVITY
elif self._type == "open window":
return DEVICE_CLASS_WINDOW
elif self._type == "child_lock":
elif self._type == "child lock":
return DEVICE_CLASS_LOCK
elif self._type == "connectivity":
return DEVICE_CLASS_CONNECTIVITY
elif self._type == "banner control":
return DEVICE_CLASS_TAMPER
return None

@callback
Expand All @@ -146,6 +162,8 @@ def _async_update_data(self):
elif self._type == "open window":
self._state = bool(self._device["window_open"])
elif self._type == "child lock":
self._state = bool(self._device["child_lock"])
self._state = not bool(self._device["child_lock"])
elif self._type == "connectivity":
self._state = bool(self._device["online"])
elif self._type == "banner control":
self._state = bool(self._device['banner_ctrl'])
Loading