.. _collector_root: The Collector ============= Photons creates a ``collector`` object when instantiated. The ``collector`` is responsible for reading configuration and loading all available Photons module functionality. The ``collector`` has several useful attributes: configuration This is a dictionary-like object that contains all the :ref:`configuration ` objects created by Photons. ``run_coro_as_main(coro)`` Runs a co-routine as the main Photons task. Handles initial setup and final cleanup when the co-routine ends or the script is stopped. See :ref:`library_setup`. photons_app The ``photons_app`` object contains several useful attributes: ``using_graceful_future()`` A context manager that yields a graceful future. This is used by the :ref:`GracefulTask `. extra The JSON string provided after the ``--`` on the command line. For example, the command ``lifx lan:transform -- '{"power": "off"}'`` results in ``photons_app.extra`` containing the string ``'{"power": "off"}'``. extra_as_json A Python dictionary created from ``json.loads(self.extra)``. Using the example above, ``photons_app.extra_as_json`` is the Python dictionary ``{"power": "off"}``. final_future A future that is cancelled when the application needs to shutdown. cleaners An array of async functions called when Photons shuts down. ``resolve_target(name)`` This returns the target with name ``name``. See :ref:`configuration_targets` for information on how to create custom targets that are resolved with this function. ``reference_object(reference)`` This accepts a :ref:`reference ` or an array of serial numbers e.g. ``["d073d5000001", "d073d5000002"]`` and it'll return a special reference object that discovers the specified devices. See the page on using :ref:`special reference objects ` for more information on using these objects. .. _collector_configuration: The configuration object ------------------------ Photons reads :ref:`configuration ` from files and creates a `merged dictionary `_ of the combined configuration from all specified files. The configuration object includes several registered converters used to transform values on the object to make them more useful. By default, the following attributers are available: ``configuration["photons_app"]`` This is where ``collector.photons_app`` comes from. ``configuration["target_register"]`` This is the "target register" and holds all the targets in your configuration. To use it you say ``configuration["target_register"].resolve("nameoftarget")`` or you can use the shortcut on the collector, ``collector.resolve_target("nameoftarget")``. In your configuration you can reference different targets with ``{targets.nameoftarget}``. ``configuration["protocol_register"]`` This is the register for all the protocol messages. You only need this if you're making a target object programmatically, but you can say: .. code-block:: from photons_transport.targets import LanTarget from photons_messages import protocol_register final_future = "" my_target = LanTarget.create( {"final_future": final_future, "protocol_register": protocol_register}, {"default_broadcast": "192.168.0.255"}, ) ``configuration["reference_resolver_register"]`` This object knows how to create a :ref:`Special reference ` object from a reference, ``configuration["reference_resolver_register"].reference_object("d03d75000001")`` or you can use the shortcut on the collector as mentioned above, ``collector.reference_object("d073d5000001")`` You can add your own objects by creating a hook that will be loaded when Photons started, and then adding your configuration to the collector. .. code-block:: python from photons_app.formatter import MergedOptionStringFormatter from photons_app.tasks import task_register as task from photons_transport.targets.base import Target from photons_messages import DeviceMessages from delfick_project.norms import dictobj, sb from delfick_project.addons import addon_hook class Options(dictobj.Spec): target = dictobj.Field(format_into=sb.typed(Target), default="{targets.lan}") message_timeout = dictobj.Field(sb.integer_spec, default=30) @addon_hook() def __lifx__(collector, *args, **kwargs): collector.register_converters( { "example_script_options": Options.FieldSpec( formatter=MergedOptionStringFormatter ) } ) @task class turn_off(task.Task): """Turn off devices""" target = task.requires_target() reference = task.provides_reference(special=True) async def execute_task(self, **kwargs): options = collector.configuration["example_script_options"] async with options.self.target.session() as sender: await sender( DeviceMessages.SetPower(level=0), self.reference, message_timeout=options.message_timeout, ) if __name__ == "__main__": __import__("photons_core").run("turn_off {@:1:}") Here, our Options has two attributes: target and message_timeout. ``target`` is a Target object that defaults to the lan target, and message_timeout is an integer with a default value of 30. Then in the ``__lifx__`` hook we say that ``example_script_options`` in your configuration gets normalised into one of these objects. So you could say in configuration: .. code-block:: yaml --- example_script_options: target: "{targets.mytarget}" kmessage_timeout: 10 targets: mytarget: type: lan options: default_broadcast: 192.168.0.255 And it'll use you ``mytarget`` target to turn off your lights using a message timeout of ``10`` seconds. See `spec helpers `_ and `the dictobj `_ You can also make your options mandatory by saying: .. code-block:: python @addon_hook() def __lifx__(collector, *args, **kwargs): collector.register_converters( { "example_script_options": sb.required( Options.FieldSpec(formatter=MergedOptionStringFormatter) ) } ) You can then run your script by saying something like ``python turn_off.py`` to turn off all your lights or ``python turn_off.py match:label=den`` to turn off your light with the label of ``den``.