1 """The Twinkly light component."""
3 from __future__
import annotations
8 from aiohttp
import ClientError
9 from awesomeversion
import AwesomeVersion
10 from ttls.client
import Twinkly
46 _LOGGER = logging.getLogger(__name__)
51 config_entry: ConfigEntry,
52 async_add_entities: AddEntitiesCallback,
54 """Setups an entity from a config entry (UI config flow)."""
56 client = hass.data[DOMAIN][config_entry.entry_id][DATA_CLIENT]
57 device_info = hass.data[DOMAIN][config_entry.entry_id][DATA_DEVICE_INFO]
58 software_version = hass.data[DOMAIN][config_entry.entry_id][ATTR_SW_VERSION]
60 entity =
TwinklyLight(config_entry, client, device_info, software_version)
66 """Implementation of the light for the Twinkly service."""
68 _attr_has_entity_name =
True
70 _attr_translation_key =
"light"
77 software_version: str |
None =
None,
79 """Initialize a TwinklyLight entity."""
80 self._attr_unique_id: str = conf.data[CONF_ID]
83 if device_info.get(DEV_LED_PROFILE) == DEV_PROFILE_RGBW:
87 elif device_info.get(DEV_LED_PROFILE) == DEV_PROFILE_RGB:
98 self.
_name_name = conf.data[CONF_NAME]
or "Twinkly light"
99 self.
_model_model = conf.data[CONF_MODEL]
107 self.
_movies_movies: list[Any] = []
114 """Get device specific attributes."""
116 identifiers={(DOMAIN, self._attr_unique_id)},
117 manufacturer=
"LEDWORKS",
119 name=self.
_name_name,
125 """Return the current effect."""
127 return f
"{self._current_movie['id']} {self._current_movie['name']}"
132 """Return the list of saved effects."""
133 return [f
"{movie['id']} {movie['name']}" for movie
in self.
_movies_movies]
136 """Device is added to hass."""
144 device_registry = dr.async_get(self.
hasshass)
145 device_entry = device_registry.async_get_device(
146 {(DOMAIN, self._attr_unique_id)}, set()
149 device_registry.async_update_device(
154 """Turn device on."""
155 if ATTR_BRIGHTNESS
in kwargs:
156 brightness =
int(
int(kwargs[ATTR_BRIGHTNESS]) / 2.55)
164 await self.
_client_client.set_brightness(brightness)
167 ATTR_RGBW_COLOR
in kwargs
170 await self.
_client_client.interview()
173 await self.
_client_client.set_static_colour(
175 kwargs[ATTR_RGBW_COLOR][0],
176 kwargs[ATTR_RGBW_COLOR][1],
177 kwargs[ATTR_RGBW_COLOR][2],
180 await self.
_client_client.set_mode(
"color")
181 self.
_client_client.default_mode =
"color"
183 await self.
_client_client.set_cycle_colours(
185 kwargs[ATTR_RGBW_COLOR][3],
186 kwargs[ATTR_RGBW_COLOR][0],
187 kwargs[ATTR_RGBW_COLOR][1],
188 kwargs[ATTR_RGBW_COLOR][2],
191 await self.
_client_client.set_mode(
"movie")
192 self.
_client_client.default_mode =
"movie"
195 if ATTR_RGB_COLOR
in kwargs
and kwargs[ATTR_RGB_COLOR] != self.
_attr_rgb_color_attr_rgb_color:
196 await self.
_client_client.interview()
198 await self.
_client_client.set_static_colour(kwargs[ATTR_RGB_COLOR])
199 await self.
_client_client.set_mode(
"color")
200 self.
_client_client.default_mode =
"color"
202 await self.
_client_client.set_cycle_colours(kwargs[ATTR_RGB_COLOR])
203 await self.
_client_client.set_mode(
"movie")
204 self.
_client_client.default_mode =
"movie"
209 ATTR_EFFECT
in kwargs
212 movie_id = kwargs[ATTR_EFFECT].split(
" ")[0]
216 await self.
_client_client.interview()
217 await self.
_client_client.set_current_movie(
int(movie_id))
218 await self.
_client_client.set_mode(
"movie")
219 self.
_client_client.default_mode =
"movie"
224 """Turn device off."""
228 """Asynchronously updates the device properties."""
229 _LOGGER.debug(
"Updating '%s'", self.
_client_client.host)
234 brightness = await self.
_client_client.get_brightness()
236 int(brightness[
"value"])
if brightness[
"mode"] ==
"enabled" else 100
240 int(round(brightness_value * 2.55))
if self.
_attr_is_on_attr_is_on
else 0
243 device_info = await self.
_client_client.get_details()
246 DEV_NAME
in device_info
247 and DEV_MODEL
in device_info
249 device_info[DEV_NAME] != self.
_name_name
250 or device_info[DEV_MODEL] != self.
_model_model
253 self.
_name_name = device_info[DEV_NAME]
254 self.
_model_model = device_info[DEV_MODEL]
259 self.
hasshass.config_entries.async_update_entry(
262 CONF_HOST: self.
_client_client.host,
263 CONF_ID: self._attr_unique_id,
264 CONF_NAME: self.
_name_name,
265 CONF_MODEL: self.
_model_model,
269 device_registry = dr.async_get(self.
hasshass)
270 device_entry = device_registry.async_get_device(
271 {(DOMAIN, self._attr_unique_id)}
274 device_registry.async_update_device(
275 device_entry.id, name=self.
_name_name, model=self.
_model_model
283 _LOGGER.warning(
"Twinkly '%s' is now available", self.
_client_client.host)
288 except (TimeoutError, ClientError):
293 "Twinkly '%s' is not reachable (client error)", self.
_client_client.host
298 """Update the list of movies (effects)."""
299 movies = await self.
_client_client.get_saved_movies()
300 _LOGGER.debug(
"Movies: %s", movies)
301 if movies
and "movies" in movies:
305 """Update the current active movie."""
306 current_movie = await self.
_client_client.get_current_movie()
307 _LOGGER.debug(
"Current movie: %s", current_movie)
308 if current_movie
and "id" in current_movie:
LightEntityFeature supported_features(self)
None __init__(self, ConfigEntry conf, Twinkly client, device_info, str|None software_version=None)
_attr_supported_color_modes
None async_turn_off(self, **Any kwargs)
None async_added_to_hass(self)
DeviceInfo|None device_info(self)
None async_turn_on(self, **Any kwargs)
None async_update_current_movie(self)
None async_update_movies(self)
list[str] effect_list(self)
int|None supported_features(self)
None turn_off(self, **Any kwargs)
None turn_on(self, **Any kwargs)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)