Skip to content
This repository was archived by the owner on Aug 6, 2025. It is now read-only.

Commit 2c1fbb0

Browse files
committed
Don't error if device switched off
Previously get_device or the related functions would retrieve a list of devices that it contacted in the last x seconds. Then we would contact each light in turn to try and apply some sort of filtering. This would error out if the light had been switched off. This patch attempts to contact each light and skips it if it cannot be contacted. This also caches the label of the light so we can display the repr string even if the light is offline. Closes #6
1 parent b8e5c1c commit 2c1fbb0

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

lifx/client.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,12 @@ def poll_devices(self):
169169
for device in filter(lambda x:x.seen_ago > poll_delta, self._devices.values()):
170170
device.send_poll_packet()
171171

172-
def get_devices(self, max_seen=None):
172+
def get_devices(self, max_seen=None, refine=None):
173173
"""
174174
Get a list of all responding devices.
175175
176176
:param max_seen: The number of seconds since the device was last seen, defaults to 3 times the devicepoll interval.
177+
:param refine: Filter list of devices using this function
177178
"""
178179
if max_seen is None:
179180
max_seen = self._devicepolltime * MISSED_POLLS
@@ -182,6 +183,19 @@ def get_devices(self, max_seen=None):
182183

183184
devices = filter(lambda x:x.seen_ago < seen_delta, self._devices.values())
184185

186+
if refine is None:
187+
refine = lambda x: True
188+
189+
alive = []
190+
for d in devices:
191+
try:
192+
d.label
193+
if refine(d):
194+
alive.append(d)
195+
except device.DeviceTimeoutError:
196+
pass
197+
devices = alive
198+
185199
# Sort by device id to ensure consistent ordering
186200
return sorted(devices, key=lambda k:k.id)
187201

@@ -227,7 +241,7 @@ def by_label(self, label):
227241
:param by_label: The label we are looking for.
228242
:returns: list -- The devices that match criteria
229243
"""
230-
return filter(lambda d: d.label == label, self.get_devices())
244+
return self.get_devices(refine=lambda d: d.label == label)
231245

232246
def by_id(self, id):
233247
"""
@@ -236,7 +250,7 @@ def by_id(self, id):
236250
:param id: The device id
237251
:returns: Device -- The device with the matching id.
238252
"""
239-
return filter(lambda d: d.id == id, self.get_devices())[0]
253+
return self.get_devices(refine=lambda d: d.id == id)
240254

241255
def by_power(self, power):
242256
"""
@@ -245,7 +259,7 @@ def by_power(self, power):
245259
:param power: True returns all devices that are on, False returns ones that are off.
246260
:returns: list -- The devices that match criteria
247261
"""
248-
return filter(lambda d: d.power == power, self.get_devices())
262+
return self.get_devices(refine=lambda d: d.power == power)
249263

250264
def by_group_id(self, group_id):
251265
"""
@@ -254,7 +268,7 @@ def by_group_id(self, group_id):
254268
:param group_id: The group id to match on each light.
255269
:returns: list -- The devices that match criteria
256270
"""
257-
return filter(lambda d: d.group_id == group_id, self.get_devices())
271+
return self.get_devices(refine=lambda d: d.group_id == group_id)
258272

259273
def by_location_id(self, location_id):
260274
"""
@@ -263,7 +277,7 @@ def by_location_id(self, location_id):
263277
:param group_id: The group id to match on each light.
264278
:returns: list -- The devices that match criteria
265279
"""
266-
return filter(lambda d: d.location_id == location_id, self.get_devices())
280+
return self.get_devices(refine=lambda d: d.location_id == location_id)
267281

268282
def __getitem__(self, key):
269283
return self.get_devices()[key]

lifx/device.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self, device_id, host, client):
2727
# Our Device
2828
self._device_id = device_id
2929
self._host = host
30+
self._label = None
3031

3132
# Services
3233
self._services = {}
@@ -257,13 +258,16 @@ def label(self):
257258
"""
258259
The label for the device, setting this will change the label on the device.
259260
"""
260-
response = self._block_for_response(pkt_type=protocol.TYPE_GETLABEL)
261-
return protocol.bytes_to_label(response.label)
261+
if self._label is None:
262+
response = self._block_for_response(pkt_type=protocol.TYPE_GETLABEL)
263+
self._label = protocol.bytes_to_label(response.label)
264+
return self._label
262265

263266
@label.setter
264267
def label(self, label):
265268
newlabel = bytearray(label.encode('utf-8')[0:protocol.LABEL_MAXLEN])
266269

270+
self._label = newlabel
267271
return self._block_for_ack(newlabel, pkt_type=protocol.TYPE_SETLABEL)
268272

269273
def fade_power(self, power, duration=DEFAULT_DURATION):

0 commit comments

Comments
 (0)