The Product Registry
Different LIFX devices have a range of capabilities. For example, the LIFX+ range have the ability to output Infrared light, and the Tile has a 2d matrix of zones.
You can query devices for their product id to work out what kind of device
it is and use that to then determine what you can do with the device. This is
done with the GetVersion message, which gives
you a vendor
and product
. The vendor
is always 1
to specify
the device is a LIFX
device. There may be additional vendor
values
in the future.
Photons provides a registry of the products that allow you to match the
vendor
and product
to an object that tells you what capabilities are
available.
You can get this object by doing something like:
from photons_messages import DeviceMessages
from photons_products import Products
async def my_script(sender, reference):
async for pkt in sender(DeviceMessages.GetVersion(), reference):
if pkt | DeviceMessages.StateVersion:
cap = Products[pkt.vendor, pkt.product].cap
have = "has" if cap.has_ir else "doesn't have"
print(f"device {pkt.serial} {have} infrared ability")
Some capabilities are dependent on the firmware version, which you can get with the GetHostFirmware message. If you have a StateVersion and StateHostFirmware message then you can do something like:
from photons_app.tasks import task_register as task
from photons_messages import DeviceMessages
from photons_products import Products
from collections import defaultdict
@task
class has_multizone(task.Task):
"""Print if the device supports multizone"""
target = task.requires_target()
reference = task.provides_reference(special=True)
async def execute_task(self, **kwargs):
by_device = defaultdict(dict)
async with self.target.session() as sender:
async for pkt in sender(
[DeviceMessages.GetVersion(), DeviceMessages.GetHostFirmware()], self.reference
):
if pkt | DeviceMessages.StateVersion:
by_device[pkt.serial]["version"] = pkt
elif pkt | DeviceMessages.StateHostFirmware:
by_device[pkt.serial]["firmware"] = pkt
for serial, pkts in by_device.items():
version = pkts["version"]
firmware = pkts["firmware"]
# Calling cap with the major and minor parts of the firmware version
# will return a new capability object that then knows what
# firmware is on the device.
cap = Products[version.vendor, version.product].cap(
firmware.version_major, firmware.version_minor
)
if cap.has_extended_multizone:
print(f"device {serial} has extended multizone capability")
elif cap.has_multizone:
print(f"device {serial} has multizone, but not extended multizone")
else:
print(f"device {serial} doesn't have any multizone capability")
if __name__ == "__main__":
__import__("photons_core").run("lan:has_multizone {@:1:}")
The problem with this script is you have to wait for all the devices to return values before you get any results. If you want to print the information as devices return information, you can use the gatherer:
from photons_app.tasks import task_register as task
@task
class has_multizone(task.Task):
"""Print if the device supports multizone"""
target = task.requires_target()
reference = task.provides_reference(special=True)
async def execute_task(self, **kwargs):
async with self.target.session() as sender:
plans = sender.make_plans("capability")
async for serial, complete, info in sender.gatherer.gather_per_serial(
plans, self.reference
):
if complete:
cap = info["capability"]["cap"]
if cap.has_extended_multizone:
print(f"device {serial} has extended multizone capability")
elif cap.has_multizone:
print(f"device {serial} has multizone, but not extended multizone")
else:
print(f"device {serial} doesn't have any multizone capability")
if __name__ == "__main__":
__import__("photons_core").run("lan:has_multizone {@:1:}")
You can see the available capabilities and the products that photons knows about.