Skip to content
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
43 changes: 20 additions & 23 deletions homeassistant/components/tradfri/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from __future__ import annotations

from datetime import datetime, timedelta
import logging
from typing import Any

from pytradfri import Gateway, RequestError
Expand All @@ -11,7 +10,7 @@
from pytradfri.device import Device

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, EVENT_HOMEASSISTANT_STOP
from homeassistant.const import CONF_HOST, EVENT_HOMEASSISTANT_STOP, Platform
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
import homeassistant.helpers.config_validation as cv
Expand All @@ -23,28 +22,28 @@
from homeassistant.helpers.event import async_track_time_interval

from .const import (
ATTR_TRADFRI_GATEWAY,
ATTR_TRADFRI_GATEWAY_MODEL,
ATTR_TRADFRI_MANUFACTURER,
CONF_GATEWAY_ID,
CONF_IDENTITY,
CONF_KEY,
COORDINATOR,
COORDINATOR_LIST,
DOMAIN,
FACTORY,
KEY_API,
PLATFORMS,
SIGNAL_GW,
TIMEOUT_API,
LOGGER,
)
from .coordinator import TradfriDeviceDataUpdateCoordinator

_LOGGER = logging.getLogger(__name__)

FACTORY = "tradfri_factory"
LISTENERS = "tradfri_listeners"

CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
Comment thread
MartinHjelmare marked this conversation as resolved.
PLATFORMS = [
Platform.COVER,
Platform.FAN,
Platform.LIGHT,
Platform.SENSOR,
Platform.SWITCH,
]
SIGNAL_GW = "tradfri.gw_status"
TIMEOUT_API = 30


async def async_setup_entry(
Expand All @@ -54,7 +53,6 @@ async def async_setup_entry(
"""Create a gateway."""
tradfri_data: dict[str, Any] = {}
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = tradfri_data
listeners = tradfri_data[LISTENERS] = []

factory = await APIFactory.init(
entry.data[CONF_HOST],
Expand All @@ -68,7 +66,9 @@ async def on_hass_stop(event: Event) -> None:
await factory.shutdown()

# Setup listeners
listeners.append(hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop))
entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)
)

api = factory.request
gateway = Gateway()
Expand All @@ -89,10 +89,10 @@ async def on_hass_stop(event: Event) -> None:
config_entry_id=entry.entry_id,
connections=set(),
identifiers={(DOMAIN, entry.data[CONF_GATEWAY_ID])},
manufacturer=ATTR_TRADFRI_MANUFACTURER,
name=ATTR_TRADFRI_GATEWAY,
manufacturer="IKEA of Sweden",
name="Gateway",
# They just have 1 gateway model. Type is not exposed yet.
model=ATTR_TRADFRI_GATEWAY_MODEL,
model="E1526",
sw_version=gateway_info.firmware_version,
)

Expand Down Expand Up @@ -126,12 +126,12 @@ async def async_keep_alive(now: datetime) -> None:
try:
await api(gateway.get_gateway_info())
except RequestError:
_LOGGER.error("Keep-alive failed")
LOGGER.error("Keep-alive failed")
gw_status = False

async_dispatcher_send(hass, SIGNAL_GW, gw_status)

listeners.append(
entry.async_on_unload(
async_track_time_interval(hass, async_keep_alive, timedelta(seconds=60))
)

Expand All @@ -147,9 +147,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
tradfri_data = hass.data[DOMAIN].pop(entry.entry_id)
factory = tradfri_data[FACTORY]
await factory.shutdown()
# unsubscribe listeners
for listener in tradfri_data[LISTENERS]:
listener()

return unload_ok

Expand Down
7 changes: 2 additions & 5 deletions homeassistant/components/tradfri/base_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from abc import abstractmethod
from collections.abc import Callable
from functools import wraps
import logging
from typing import Any, cast

from pytradfri.command import Command
Expand All @@ -15,11 +14,9 @@
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .const import DOMAIN, LOGGER
from .coordinator import TradfriDeviceDataUpdateCoordinator

_LOGGER = logging.getLogger(__name__)


def handle_error(
func: Callable[[Command | list[Command]], Any]
Expand All @@ -32,7 +29,7 @@ async def wrapper(command: Command | list[Command]) -> None:
try:
await func(command)
except RequestError as err:
_LOGGER.error("Unable to execute command %s: %s", command, err)
LOGGER.error("Unable to execute command %s: %s", command, err)

return wrapper

Expand Down
12 changes: 4 additions & 8 deletions homeassistant/components/tradfri/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult

from .const import (
CONF_GATEWAY_ID,
CONF_IDENTITY,
CONF_IMPORT_GROUPS,
CONF_KEY,
DOMAIN,
KEY_SECURITY_CODE,
)
from .const import CONF_GATEWAY_ID, CONF_IDENTITY, CONF_KEY, DOMAIN

CONF_IMPORT_GROUPS = "import_groups"
KEY_SECURITY_CODE = "security_code"


class AuthError(Exception):
Expand Down
44 changes: 6 additions & 38 deletions homeassistant/components/tradfri/const.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,13 @@
"""Consts used by Tradfri."""
from typing import Final
import logging

from homeassistant.components.light import SUPPORT_TRANSITION
from homeassistant.const import ( # noqa: F401 pylint: disable=unused-import
CONF_HOST,
Platform,
)
LOGGER = logging.getLogger(__package__)

ATTR_AUTO = "Auto"
ATTR_DIMMER = "dimmer"
ATTR_HUE = "hue"
ATTR_SAT = "saturation"
ATTR_TRADFRI_GATEWAY = "Gateway"
ATTR_TRADFRI_GATEWAY_MODEL = "E1526"
ATTR_TRADFRI_MANUFACTURER = "IKEA of Sweden"
ATTR_TRANSITION_TIME = "transition_time"
ATTR_MODEL = "model"
CONF_IDENTITY = "identity"
CONF_IMPORT_GROUPS = "import_groups"
CONF_GATEWAY_ID = "gateway_id"
CONF_IDENTITY = "identity"
CONF_KEY = "key"

DOMAIN = "tradfri"
KEY_API = "tradfri_api"
DEVICES = "tradfri_devices"
SIGNAL_GW = "tradfri.gw_status"
KEY_SECURITY_CODE = "security_code"
SUPPORTED_LIGHT_FEATURES = SUPPORT_TRANSITION
PLATFORMS = [
Platform.COVER,
Platform.FAN,
Platform.LIGHT,
Platform.SENSOR,
Platform.SWITCH,
]
TIMEOUT_API = 30
ATTR_MAX_FAN_STEPS = 49

SCAN_INTERVAL = 60 # Interval for updating the coordinator

COORDINATOR = "coordinator"
COORDINATOR_LIST = "coordinator_list"

ATTR_FILTER_LIFE_REMAINING: Final = "filter_life_remaining"
DOMAIN = "tradfri"
FACTORY = "tradfri_factory"
KEY_API = "tradfri_api"
9 changes: 4 additions & 5 deletions homeassistant/components/tradfri/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from collections.abc import Callable
from datetime import timedelta
import logging
from typing import Any

from pytradfri.command import Command
Expand All @@ -13,9 +12,9 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import SCAN_INTERVAL
from .const import LOGGER

_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = 60 # Interval for updating the coordinator


class TradfriDeviceDataUpdateCoordinator(DataUpdateCoordinator[Device]):
Expand All @@ -35,7 +34,7 @@ def __init__(

super().__init__(
hass,
_LOGGER,
LOGGER,
name=f"Update coordinator for {device}",
update_interval=timedelta(seconds=SCAN_INTERVAL),
)
Expand All @@ -62,7 +61,7 @@ async def _handle_exception(self, exc: Exception) -> None:
# Store exception so that it gets raised in _async_update_data
self._exception = exc

_LOGGER.debug(
LOGGER.debug(
"Observation failed for %s, trying again", self.device, exc_info=exc
)
# Change interval so we get a swift refresh
Expand Down
11 changes: 2 additions & 9 deletions homeassistant/components/tradfri/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .base_class import TradfriBaseEntity
from .const import (
ATTR_MODEL,
CONF_GATEWAY_ID,
COORDINATOR,
COORDINATOR_LIST,
DOMAIN,
KEY_API,
)
from .const import CONF_GATEWAY_ID, COORDINATOR, COORDINATOR_LIST, DOMAIN, KEY_API
from .coordinator import TradfriDeviceDataUpdateCoordinator


Expand Down Expand Up @@ -70,7 +63,7 @@ def _refresh(self) -> None:
@property
def extra_state_attributes(self) -> dict[str, str] | None:
"""Return the state attributes."""
return {ATTR_MODEL: self._device.device_info.model_number}
return {"model": self._device.device_info.model_number}

@property
def current_cover_position(self) -> int | None:
Expand Down
13 changes: 4 additions & 9 deletions homeassistant/components/tradfri/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,12 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .base_class import TradfriBaseEntity
from .const import (
ATTR_AUTO,
ATTR_MAX_FAN_STEPS,
CONF_GATEWAY_ID,
COORDINATOR,
COORDINATOR_LIST,
DOMAIN,
KEY_API,
)
from .const import CONF_GATEWAY_ID, COORDINATOR, COORDINATOR_LIST, DOMAIN, KEY_API
from .coordinator import TradfriDeviceDataUpdateCoordinator

ATTR_AUTO = "Auto"
ATTR_MAX_FAN_STEPS = 49


def _from_fan_percentage(percentage: int) -> int:
"""Convert percent to a value that the Tradfri API understands."""
Expand Down
41 changes: 18 additions & 23 deletions homeassistant/components/tradfri/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
SUPPORT_TRANSITION,
LightEntity,
)
from homeassistant.config_entries import ConfigEntry
Expand All @@ -22,20 +23,11 @@
import homeassistant.util.color as color_util

from .base_class import TradfriBaseEntity
from .const import (
ATTR_DIMMER,
ATTR_HUE,
ATTR_SAT,
ATTR_TRANSITION_TIME,
CONF_GATEWAY_ID,
COORDINATOR,
COORDINATOR_LIST,
DOMAIN,
KEY_API,
SUPPORTED_LIGHT_FEATURES,
)
from .const import CONF_GATEWAY_ID, COORDINATOR, COORDINATOR_LIST, DOMAIN, KEY_API
from .coordinator import TradfriDeviceDataUpdateCoordinator

SUPPORTED_LIGHT_FEATURES = SUPPORT_TRANSITION


async def async_setup_entry(
hass: HomeAssistant,
Expand Down Expand Up @@ -142,8 +134,11 @@ async def async_turn_off(self, **kwargs: Any) -> None:
if ATTR_TRANSITION in kwargs:
transition_time = int(kwargs[ATTR_TRANSITION]) * 10

dimmer_data = {ATTR_DIMMER: 0, ATTR_TRANSITION_TIME: transition_time}
await self._api(self._device_control.set_dimmer(**dimmer_data))
await self._api(
self._device_control.set_dimmer(
dimmer=0, transition_time=transition_time
)
)
else:
await self._api(self._device_control.set_state(False))

Expand All @@ -160,8 +155,8 @@ async def async_turn_on(self, **kwargs: Any) -> None:
brightness = kwargs[ATTR_BRIGHTNESS]
brightness = min(brightness, 254)
dimmer_data = {
ATTR_DIMMER: brightness,
ATTR_TRANSITION_TIME: transition_time,
"dimmer": brightness,
"transition_time": transition_time,
}
dimmer_command = self._device_control.set_dimmer(**dimmer_data)
transition_time = None
Expand All @@ -175,9 +170,9 @@ async def async_turn_on(self, **kwargs: Any) -> None:
kwargs[ATTR_HS_COLOR][1] * (self._device_control.max_saturation / 100)
)
color_data = {
ATTR_HUE: hue,
ATTR_SAT: sat,
ATTR_TRANSITION_TIME: transition_time,
"hue": hue,
"saturation": sat,
"transition_time": transition_time,
}
color_command = self._device_control.set_hsb(**color_data)
transition_time = None
Expand All @@ -195,7 +190,7 @@ async def async_turn_on(self, **kwargs: Any) -> None:
temp = self.min_mireds
temp_data = {
ATTR_COLOR_TEMP: temp,
ATTR_TRANSITION_TIME: transition_time,
"transition_time": transition_time,
}
temp_command = self._device_control.set_color_temp(**temp_data)
transition_time = None
Expand All @@ -207,9 +202,9 @@ async def async_turn_on(self, **kwargs: Any) -> None:
hue = int(hs_color[0] * (self._device_control.max_hue / 360))
sat = int(hs_color[1] * (self._device_control.max_saturation / 100))
color_data = {
ATTR_HUE: hue,
ATTR_SAT: sat,
ATTR_TRANSITION_TIME: transition_time,
"hue": hue,
"saturation": sat,
"transition_time": transition_time,
}
color_command = self._device_control.set_hsb(**color_data)
transition_time = None
Expand Down
Loading