Implementing the `is-discrete` trait

The is-discrete trait is formally defined by YEP-309.

The DiscreteHardware class provides the is-discrete, has-position, and is-daemon traits. Implementation usually involves subclassing and writing two methods. It's also necessary to define _position_identifiers.

from yaqd_core import DiscreteHardware

class ExampleHasPosition(Hardware):
    _kind = "example-has-position"

    def __init__(self, name, config, config_filepath):
        super().__init__(name, config, config_filepath)
    # Gets read from config, but you can define it programattically as well
    # Generally defining programmatically should be done only if reading
    # directly from a device (rather than a static mapping).
        self._position_identifiers = {
                "red": 667,
                "orange": 613,
                "yellow": 575,
                "green": 540,
                "blue": 470,
                "violet": 425,

    def _set_position(self, position):
        # you will recieve position as a number
        # it's up to you to use that number to communicate appropriately
        # the following snippet is something that might appear here

    async def update_state(self):
        # you must update position and position_identifier
        # it's up to you exactly how that works for your hardware
        # remember that position_identifier can be None
        # typically, position remains numeric although it can be nan
        while True:
            self._state["position"] = self.device.get_position()
            self._state["position_identifier"] = convert(self._position)
            self._busy = not self.device.is_ready()
            if self._busy:
                await asyncio.sleep(0.01)
                await self._busy_sig.wait()

Check out the following implementations for good examples of typical DiscreteHardware:

built 2020-09-26 00:52:26                                      CC0: no copyright