Skip to content
This repository was archived by the owner on Aug 6, 2025. It is now read-only.
Open
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
26 changes: 20 additions & 6 deletions lifx/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,12 @@ def poll_devices(self):
for device in filter(lambda x:x.seen_ago > poll_delta, self._devices.values()):
device.send_poll_packet()

def get_devices(self, max_seen=None):
def get_devices(self, max_seen=None, refine=None):
"""
Get a list of all responding devices.

:param max_seen: The number of seconds since the device was last seen, defaults to 3 times the devicepoll interval.
:param refine: Filter list of devices using this function
"""
if max_seen is None:
max_seen = self._devicepolltime * MISSED_POLLS
Expand All @@ -182,6 +183,19 @@ def get_devices(self, max_seen=None):

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

if refine is None:
refine = lambda x: True

alive = []
for d in devices:
try:
d.label
if refine(d):
alive.append(d)
except device.DeviceTimeoutError:
pass
devices = alive

# Sort by device id to ensure consistent ordering
return sorted(devices, key=lambda k:k.id)

Expand Down Expand Up @@ -227,7 +241,7 @@ def by_label(self, label):
:param by_label: The label we are looking for.
:returns: list -- The devices that match criteria
"""
return filter(lambda d: d.label == label, self.get_devices())
return self.get_devices(refine=lambda d: d.label == label)

def by_id(self, id):
"""
Expand All @@ -236,7 +250,7 @@ def by_id(self, id):
:param id: The device id
:returns: Device -- The device with the matching id.
"""
return filter(lambda d: d.id == id, self.get_devices())[0]
return self.get_devices(refine=lambda d: d.id == id)

def by_power(self, power):
"""
Expand All @@ -245,7 +259,7 @@ def by_power(self, power):
:param power: True returns all devices that are on, False returns ones that are off.
:returns: list -- The devices that match criteria
"""
return filter(lambda d: d.power == power, self.get_devices())
return self.get_devices(refine=lambda d: d.power == power)

def by_group_id(self, group_id):
"""
Expand All @@ -254,7 +268,7 @@ def by_group_id(self, group_id):
:param group_id: The group id to match on each light.
:returns: list -- The devices that match criteria
"""
return filter(lambda d: d.group_id == group_id, self.get_devices())
return self.get_devices(refine=lambda d: d.group_id == group_id)

def by_location_id(self, location_id):
"""
Expand All @@ -263,7 +277,7 @@ def by_location_id(self, location_id):
:param group_id: The group id to match on each light.
:returns: list -- The devices that match criteria
"""
return filter(lambda d: d.location_id == location_id, self.get_devices())
return self.get_devices(refine=lambda d: d.location_id == location_id)

def __getitem__(self, key):
return self.get_devices()[key]
Expand Down
9 changes: 7 additions & 2 deletions lifx/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self, device_id, host, client):
# Our Device
self._device_id = device_id
self._host = host
self._label = None

# Services
self._services = {}
Expand All @@ -51,6 +52,7 @@ def _seq(self):

def _packethandler(self, host, port, packet):
self._seen()
self._host = host

# If it was a service packet
if packet.protocol_header.pkt_type == protocol.TYPE_STATESERVICE:
Expand Down Expand Up @@ -257,13 +259,16 @@ def label(self):
"""
The label for the device, setting this will change the label on the device.
"""
response = self._block_for_response(pkt_type=protocol.TYPE_GETLABEL)
return protocol.bytes_to_label(response.label)
if self._label is None:
response = self._block_for_response(pkt_type=protocol.TYPE_GETLABEL)
self._label = protocol.bytes_to_label(response.label)
return self._label

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

self._label = newlabel
return self._block_for_ack(newlabel, pkt_type=protocol.TYPE_SETLABEL)

def fade_power(self, power, duration=DEFAULT_DURATION):
Expand Down