コード例 #1
0
class PumpController(StateMachine):
    def __init__(self, loop):
        super(PumpController, self).__init__(loop)

        self.pfd = PiFaceDigital()

        self.listener = InputEventListener(chip=self.pfd)
        self.listener.register(0, IODIR_BOTH, self.in_upper)
        self.listener.register(1, IODIR_RISING_EDGE, self.in_lower)
        self.listener.register(3, IODIR_RISING_EDGE, self.in_button)
        self.listener.activate()

    def stop(self):
        self.pfd.output_port.all_off()
        self.listener.deactivate()

    def set_pump_state(self, state):
        self.pfd.relays[0].value = state

    def in_upper(self, event):
        self.logger.info('Input event pin0 (upper)')
        self.loop.call_soon_threadsafe(
            self.handle_upper_sensor,
            event.direction != 1
        )

    def in_lower(self, event):
        self.logger.info('Input event pin1 (lower)')
        self.loop.call_soon_threadsafe(self.handle_lower_sensor, False)

    def in_button(self, event):
        self.logger.info('Input event pin3 (button)')
        self.loop.call_soon_threadsafe(self.handle_button, True)
コード例 #2
0
 def run(self):
     """initialize and run the chip interface and event listener"""
     logger.debug("initializing chip")
     self.chip = PiFaceDigital()
     logger.debug("chip initialized")
     logger.debug("creating InputEventListener")
     self.listener = InputEventListener(chip=self.chip)
     self.register_callbacks()
     logger.debug("activating listener")
     self.listener.activate()
コード例 #3
0
    def __init__(self, loop):
        super(PumpController, self).__init__(loop)

        self.pfd = PiFaceDigital()

        self.listener = InputEventListener(chip=self.pfd)
        self.listener.register(0, IODIR_BOTH, self.in_upper)
        self.listener.register(1, IODIR_RISING_EDGE, self.in_lower)
        self.listener.register(3, IODIR_RISING_EDGE, self.in_button)
        self.listener.activate()
コード例 #4
0
class Listener(object):

    def __init__(self):
        self.config = Config()
        logger.info("Initializing listener")
        if len(self.config.PINS) < 4:
            logger.critical("ERROR - please configure all 4 pins")
            raise SystemExit(1)
        self.write_files = True
        self.current_values = []

    def run(self):
        """initialize and run the chip interface and event listener"""
        logger.debug("initializing chip")
        self.chip = PiFaceDigital()
        logger.debug("chip initialized")
        logger.debug("creating InputEventListener")
        self.listener = InputEventListener(chip=self.chip)
        self.register_callbacks()
        logger.debug("activating listener")
        self.listener.activate()

    def register_callbacks(self):
        """record current pin state and register the event callbacks"""
        logger.debug("registering callbacks")
        self.current_values = [None] * 4
        for i in range(4):
            self.current_values[i] = self.chip.input_pins[i].value
            logger.debug("registering callback for %s ON", i)
            self.listener.register(i, IODIR_ON, self.handle_input_on)
            logger.debug("registering callback for %s OFF", i)
            self.listener.register(i, IODIR_OFF, self.handle_input_off)
        logger.debug("done registering callbacks")
        logger.info("Initial pin states: %s", self.current_values)

    def handle_input_on(self, event):
        """
        InputEventListener callback function for IODIR_ON (pin on)

        :param event: the event that was detected
        :type event: pifacecommon.interrupts.InterruptEvent
        """
        if self.no_state_change(event.pin_num, 1):
            logger.info("Ignoring duplicate event for pin %s state %s",
                        event.pin_num, 1)
            return
        else:
            self.current_values[event.pin_num] = 1
        logger.info("Received ON event for pin %s", event.pin_num)
        self.handle_change(event.pin_num, 1, event.timestamp)
        self.set_output(event.pin_num, 1)

    def handle_input_off(self, event):
        """
        InputEventListener callback function for IODIR_OFF (pin off)

        :param event: the event that was detected
        :type event: pifacecommon.interrupts.InterruptEvent
        """
        if self.no_state_change(event.pin_num, 0):
            logger.info("Ignoring duplicate event for pin %s state %s",
                        event.pin_num, 0)
            return
        else:
            self.current_values[event.pin_num] = 0
        logger.info("Received OFF event for pin %s", event.pin_num)
        self.handle_change(event.pin_num, 0, event.timestamp)
        self.set_output(event.pin_num, 0)

    def no_state_change(self, pin, new_state):
        """
        Return True if the pin's state has changed, False otherwise.

        :param pin: the pin number
        :type pin: int
        :param new_state: the new pin state/value
        :type state: int
        :rtype: bool
        """
        if self.current_values[pin] == new_state:
            return True
        return False

    def handle_change(self, pin_num, state, timestamp):
        """
        Handler for pin state change.

        :param pin_num: the pin number that changed
        :type pin_num: int
        :param state: the new state of the pin (1==on, 0==off)
        :type state: int
        :param timestamp: timestamp when the event happened (Float unix TS)
        :type timestamp: float
        """
        fname = 'pinevent_%s_pin%s_state%s' % (timestamp, pin_num, state)
        fpath = os.path.join(self.config.QUEUE_PATH, fname)
        if not self.write_files:
            logger.warning('Would create event file: %s', fpath)
            return
        # touch the file
        with open(fpath, 'a'):
            os.utime(fpath, None)
        logger.debug('Created event file: %s', fpath)

    def set_output(self, pin_num, state):
        """
        Change the state of an output pin in response to an input change. Set
        the output to the same state as the input, unless
        ``config.INVERT_LED is True``, in which case set it to the opposite.

        :param pin_num: the pin number to change
        :type pin_num: int
        :param state: the new state - 0=off, 1=on
        :type state: int
        """
        if self.config.NO_LEDS:
            logger.debug("Not lighting LEDs")
            return
        if self.config.INVERT_LED:
            if state == 0:
                state = 1
            else:
                state = 0
        if state == 1:
            logger.debug("Setting output %s on", pin_num)
            self.chip.output_pins[pin_num].turn_on()
        else:
            logger.debug("Setting output %s off", pin_num)
            self.chip.output_pins[pin_num].turn_off()

    def console_entry_point(self):
        """entry point to handle args and call run function"""
        args = self.parse_args(sys.argv[1:])
        if args.version:
            print("pyface-webhooks %s "
                  "<https://github.com/jantman/piface_webhooks>" % VERSION)
            raise SystemExit(0)
        if args.verbose == 1:
            logger.warning("Setting log level to INFO")
            logger.setLevel(logging.INFO)
        elif args.verbose > 1:
            logger.warning("Setting log level to DEBUG")
            # debug-level logging hacks
            FORMAT = "[%(asctime)s][%(levelname)s %(filename)s:%(lineno)s - " \
                     "%(name)s.%(funcName)s() ] %(message)s"
            debug_formatter = logging.Formatter(fmt=FORMAT)
            logger.handlers[0].setFormatter(debug_formatter)
            logger.setLevel(logging.DEBUG)
        self.write_files = args.write_files
        self.run()

    def parse_args(self, argv):
        """
        parse arguments/options

        :param argv: argument list to parse, usually ``sys.argv[1:]``
        :type argv: list
        :returns: parsed arguments
        :rtype: :py:class:`argparse.Namespace`
        """
        desc = 'Listen for PiFace input changes and queue them to disk'
        p = argparse.ArgumentParser(description=desc)
        p.add_argument('-w', '--no-write', dest='write_files',
                       action='store_false', default=True,
                       help='do not write queue files; just log changes')
        p.add_argument('-v', '--verbose', dest='verbose', action='count',
                       default=0,
                       help='verbose output. specify twice for debug-level '
                       'output.')
        p.add_argument('-V', '--version', dest='version', action='store_true',
                       default=False,
                       help='print version number and exit.')
        args = p.parse_args(argv)
        return args