Beispiel #1
0
class Dispatcher(BaseDispatcher):
    def __init__(self, config):
        super(Dispatcher, self).__init__(config)

        self.load_config_object('j1', on_down=self.on_button_down)
        self.load_config_object('badge_reader', on_scan=self.badge_scan)

        self.load_config_object('buzzer')
        self.load_config_object('relays')
        # This may be a MultiProxy, which makes this easier.
        self.relays.on()
        self.relay_value = True

        # Run fans for 10 seconds on startup
        self.relay_timer = Timer(self.event_queue, 'relay_timer',
                                 self.toggle_relays)
        self.relay_toggle_interval = 10
        self.relay_timer.set(self.relay_toggle_interval)
        self.threads.extend([self.relay_timer])

    def on_button_down(self, source):
        print "Button down", source
        self.buzzer.beep()

        source.on()
        time.sleep(0.3)
        source.off()

    def badge_scan(self, badge_id):
        print "Badge ID", badge_id

    def toggle_relays(self, source):
        print "Toggle relay", self.relay_value
        if self.relay_value:
            self.relays.off()
            self.relay_value = False
        else:
            self.relays.on()
            self.relay_value = True
        self.relay_timer.set(self.relay_toggle_interval)
class Dispatcher(BaseDispatcher):
  def __init__(self, config):
    super(Dispatcher, self).__init__(config)

    for i in range(1, 6+1):
      self.load_config_object('j%d' % i, on_down=self.on_button_down)

    self.load_config_object('buzzer')
    self.load_config_object('relays')
    # This may be a MultiProxy, which makes this easier.
    self.relays.on()
    self.relay_value = True

    # Run fans for 10 seconds on startup
    self.relay_timer = Timer(self.event_queue, 'relay_timer', self.toggle_relays)
    self.relay_toggle_interval = 10
    self.relay_timer.set(self.relay_toggle_interval)
    self.threads.extend([self.relay_timer])

  def on_button_down(self, source):
    print "Button down", source
    self.buzzer.beep()

    source.on()
    time.sleep(0.3)
    source.off()

  def toggle_relays(self, source):
    print "Toggle relay", self.relay_value
    if self.relay_value:
      self.relays.off()
      self.relay_value = False
    else:
      self.relays.on()
      self.relay_value = True
    self.relay_timer.set(self.relay_toggle_interval)
Beispiel #3
0
class Dispatcher(BaseDispatcher):
    def __init__(self, config):
        super(Dispatcher, self).__init__(config)

        self.authorized = False
        self.load_config_object('on_button', on_down=self.on_button_down)
        self.load_config_object('off_button', on_down=self.abort)
        self.load_config_object('badge_reader', on_scan=self.badge_scan)
        self.load_config_object('enable_output')
        self.load_config_object('buzzer')
        self.warning_timer = Timer(self.event_queue, 'warning_timer',
                                   self.warning)
        self.expire_timer = Timer(self.event_queue, 'expire_timer', self.abort)
        self.expecting_press_timer = Timer(self.event_queue,
                                           'expecting_press_timer', self.abort)
        # Otherwise, start them manually!
        self.threads.extend([
            self.warning_timer, self.expire_timer, self.expecting_press_timer
        ])

        self.noise = None

    def _get_command_line(self, section, key, format_args):
        """Constructs a command line, safely.

    The value can contain {key}, {}, and {5} style interpolation:
      - {key} will be resolved in the config.get; those are considered safe and
        spaces will separate args.
      - {} works on each arg independently (probably not what you want).
      - {5} works fine.
    """
        value = self.config.get(section, key)
        pieces = shlex.split(value)
        return [p.format(*format_args) for p in pieces]

    def badge_scan(self, badge_id):
        # Malicious badge "numbers" that contain spaces require this extra work.
        command = self._get_command_line('auth', 'command', [badge_id])
        # TODO timeout
        # TODO test with missing command
        rc = subprocess.call(command)
        if rc == 0:
            self.buzzer.beep()
            self.authorized = True
            self.badge_id = badge_id
            self.expecting_press_timer.set(30)
            self.on_button.blink()
        else:
            self.buzzer.beep()
            if self.noise:
                self.noise.kill()
            if self.config.get('sounds', 'enable') == '1':
                sound_command = self._get_command_line(
                    'sounds', 'command',
                    [self.config.get('sounds', 'sad_filename')])
                self.noise = subprocess.Popen(sound_command,
                                              stdin=DEVNULL,
                                              stdout=DEVNULL,
                                              stderr=DEVNULL)

    def on_button_down(self, source):
        print "Button down", source
        if not self.authorized:
            self.buzzer.beep()
            if self.noise:
                self.noise.kill()
            if self.config.get('sounds', 'enable') == '1':
                sound_command = self._get_command_line(
                    'sounds', 'command',
                    [self.config.get('sounds', 'sad_filename')])
                self.noise = subprocess.Popen(sound_command,
                                              stdin=DEVNULL,
                                              stdout=DEVNULL,
                                              stderr=DEVNULL)
            return
        self.expecting_press_timer.cancel()
        self.on_button.on()
        self.enable_output.on()
        self.buzzer.off()
        self.warning_timer.cancel()
        self.expire_timer.cancel()
        # TODO use extend time if we were already enabled, and run its command for
        # logging.
        # N.b. Duration (or extend) includes the warning time.
        self.warning_timer.set(
            self.config.get_int_seconds('auth', 'duration', '5m') -
            self.config.get_int_seconds('auth', 'warning', '10s'))
        self.expire_timer.set(
            self.config.get_int_seconds('auth', 'duration', '5m'))
        if self.noise:
            self.noise.kill()
            self.noise = None

    def abort(self, source):
        print "Abort", source
        if self.authorized:
            command = self._get_command_line('auth', 'deauth_command',
                                             [self.badge_id])
            subprocess.call(command)
        self.authorized = False
        self.warning_timer.cancel()
        self.expecting_press_timer.cancel()
        self.on_button.off()
        self.enable_output.off()
        self.buzzer.off()
        if self.noise:
            self.noise.kill()
            self.noise = None

    def warning(self, unused_source):
        self.buzzer.beepbeep()
        if self.config.get('sounds', 'enable') == '1':
            sound_command = self._get_command_line(
                'sounds', 'command',
                [self.config.get('sounds', 'warning_filename')])
            self.noise = subprocess.Popen(shlex.split(sound_command),
                                          stdin=DEVNULL,
                                          stdout=DEVNULL,
                                          stderr=DEVNULL)
        self.on_button.blink()
class Dispatcher(BaseDispatcher):
  def __init__(self, config):
    super(Dispatcher, self).__init__(config)

    self.authorized = False
    self.load_config_object('on_button', on_down=self.on_button_down)
    self.load_config_object('off_button', on_down=self.abort)
    self.load_config_object('badge_reader', on_scan=self.badge_scan)
    self.load_config_object('enable_output')
    self.load_config_object('buzzer')
    self.warning_timer = Timer(self.event_queue, 'warning_timer', self.warning)
    self.expire_timer = Timer(self.event_queue, 'expire_timer', self.abort)
    self.expecting_press_timer = Timer(self.event_queue, 'expecting_press_timer', self.abort)
    # Otherwise, start them manually!
    self.threads.extend([self.warning_timer, self.expire_timer, self.expecting_press_timer])

    self.noise = None

  def _get_command_line(self, section, key, format_args):
    """Constructs a command line, safely.

    The value can contain {key}, {}, and {5} style interpolation:
      - {key} will be resolved in the config.get; those are considered safe and
        spaces will separate args.
      - {} works on each arg independently (probably not what you want).
      - {5} works fine.
    """
    value = self.config.get(section, key)
    pieces = shlex.split(value)
    return [p.format(*format_args) for p in pieces]

  def badge_scan(self, badge_id):
    # Malicious badge "numbers" that contain spaces require this extra work.
    command = self._get_command_line('auth', 'command', [badge_id])
    # TODO timeout
    # TODO test with missing command
    rc = subprocess.call(command)
    if rc == 0:
      self.buzzer.beep()
      self.authorized = True
      self.badge_id = badge_id
      self.expecting_press_timer.set(30)
      self.on_button.blink()
    else:
      self.buzzer.beep()
      if self.noise:
        self.noise.kill()
      if self.config.get('sounds', 'enable') == '1':
        sound_command = self._get_command_line('sounds', 'command', [self.config.get('sounds', 'sad_filename')])
        self.noise = subprocess.Popen(sound_command, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)

  def on_button_down(self, source):
    print "Button down", source
    if not self.authorized:
      self.buzzer.beep()
      if self.noise:
        self.noise.kill()
      if self.config.get('sounds', 'enable') == '1':
        sound_command = self._get_command_line('sounds', 'command', [self.config.get('sounds', 'sad_filename')])
        self.noise = subprocess.Popen(sound_command, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)
      return
    self.expecting_press_timer.cancel()
    self.on_button.on()
    self.enable_output.on()
    self.buzzer.off()
    self.warning_timer.cancel()
    self.expire_timer.cancel()
    # TODO use extend time if we were already enabled, and run its command for
    # logging.
    # N.b. Duration (or extend) includes the warning time.
    self.warning_timer.set(self.config.get_int_seconds('auth', 'duration', '5m') -
                           self.config.get_int_seconds('auth', 'warning', '10s'))
    self.expire_timer.set(self.config.get_int_seconds('auth', 'duration', '5m'))
    if self.noise:
      self.noise.kill()
      self.noise = None

  def abort(self, source):
    print "Abort", source
    if self.authorized:
      command = self._get_command_line('auth', 'deauth_command', [self.badge_id])
      subprocess.call(command)
    self.authorized = False
    self.warning_timer.cancel()
    self.expecting_press_timer.cancel()
    self.on_button.off()
    self.enable_output.off()
    self.buzzer.off()
    if self.noise:
      self.noise.kill()
      self.noise = None

  def warning(self, unused_source):
    self.buzzer.beepbeep()
    if self.config.get('sounds', 'enable') == '1':
      sound_command = self._get_command_line('sounds', 'command', [self.config.get('sounds', 'warning_filename')])
      self.noise = subprocess.Popen(shlex.split(sound_command), stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)
    self.on_button.blink()
Beispiel #5
0
class Dispatcher(BaseDispatcher):
    def __init__(self, config):
        super(Dispatcher, self).__init__(config)

        self.authorized = False
        self.load_config_object('badge_reader', on_scan=self.badge_scan)
        self.load_config_object('enable_output')
        self.load_config_object('buzzer')
        self.door_timer = Timer(self.event_queue, 'door_timer', self.abort)
        self.noise = None
        self.threads.extend([self.door_timer])

    def _get_command_line(self, section, key, format_args):
        """Constructs a command line, safely.

    The value can contain {key}, {}, and {5} style interpolation:
      - {key} will be resolved in the config.get; those are considered safe and
        spaces will separate args.
      - {} works on each arg independently (probably not what you want).
      - {5} works fine.
    """
        value = self.config.get(section, key)
        pieces = shlex.split(value)
        return [p.format(*format_args) for p in pieces]

    def badge_scan(self, badge_id):
        """Executes scanning of a users badge.

    Note:
        "command" below will execute a shell operation defined via the
        configuration option in authboxrc.  This script should exit with a zero
        error code on a successful authorization and non-zero on a failure.

    Args:
        badge_id: The badge value as passed directly by the reader.
    """

        print("Badge scanned - {}".format(badge_id))
        try:
            # Malicious badge "numbers" that contain spaces require this extra work.
            command = self._get_command_line('auth', 'command', [badge_id])
            rc = subprocess.call(command)
        except IOError as e:
            print("Error, command %s not found" % e.filename)
            # TODO timeout
            # TODO test with missing command

        if rc == 0:
            # If the return code on the previous command exited with a 0 error code,
            # then buzz the buzzer, set the authorized propety on our object to true
            # and the badge_id property to the value returned by the badge reader.
            self.authorized = True
            self.badge_id = badge_id
            # Read the "auth" section of authboxrc and retieve the duration setting.
            # If there is no value set, default to 30 seconds.
            self.door_timer.set(
                self.config.get_int_seconds('auth', 'duration', '30s'))
            # Enable the pin defined in our "enable_output" configuration definition
            # (defined in the __init__ of this class), setting it to an "on" value.
            self.enable_output.on()

        else:
            # If the command did not return a zero error code, then buzz the buzzer,
            # terminate any sounds which may be playing, determine from the "enable"
            # value in the "sounds" section of the authboxrc config if sounds should
            # be enabled.
            # If sounds are to be enabled, then also within the "sounds" section of
            # the authboxrc config file, determine the audio file based on the
            # value of "sad_filename" and supply it to the command defined by the
            # value of "command".
            if self.noise:
                self.noise.kill()
            if self.config.get('sounds', 'enable') == '1':
                sound_command = self._get_command_line(
                    'sounds', 'command',
                    [self.config.get('sounds', 'sad_filename')])
                self.noise = subprocess.Popen(sound_command,
                                              stdin=DEVNULL,
                                              stdout=DEVNULL,
                                              stderr=DEVNULL)

    def abort(self, source):
        """Perform operations on authorization timeout.

    Args:
        source: the device a user attempted to authorize for use, but was
            denied
    """
        print "Abort", source
        self.authorized = False
        self.enable_output.off()
        self.buzzer.off()
        if self.noise:
            self.noise.kill()
            self.noise = None