Ejemplo n.º 1
0
 def reaction_toggle_blue_orange(self):
     if self.color == "blue":
         self.color = "orange"
     elif self.color == "orange":
         self.color = "blue"
     else:
         logger.info("Color is {}: nothing to do".format(self.color))
Ejemplo n.º 2
0
def run_broker():
    parser = argparse.ArgumentParser()
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        default=3031,
                        help='3031 by default')
    parser.add_argument('-l',
                        '--log-level',
                        type=str,
                        default='INFO',
                        help='INFO by default')
    parser.add_argument('-f',
                        '--log-file',
                        type=str,
                        default='/dev/null',
                        help='/dev/null by default (no file)')
    parser.add_argument('-t',
                        '--twisted-logs',
                        action='store_true',
                        help='Include twisted logs (no by default)')
    args = parser.parse_args()

    init_logging(level=args.log_level,
                 file=args.log_file,
                 twisted_logs=args.twisted_logs)

    logger.info("Starting broker")

    reactor.listenTCP(args.port, BrokerFactory())

    logger.info("Listening on port {}".format(args.port))

    reactor.run()
Ejemplo n.º 3
0
 def on_success(self):
     if not self.success:
         self.success = True
         logger.info("Success")
         self.publish({"category": "success"})
         self.send_serial(
             {ArduinoProtocol.CATEGORY: ArduinoProtocol.SUCCESS})
Ejemplo n.º 4
0
 def color(self, value):
     self._color = value
     if value == 'blue':
         self.led_pin.on()
     else:
         self.led_pin.off()
     logger.info("Letter {}: {}".format(self.index, value))
Ejemplo n.º 5
0
 def event_reset(self):
     logger.info("Reset")
     self.success = False
     self.send_serial({ArduinoProtocol.CATEGORY: ArduinoProtocol.PLAYING})
     for letter in self.letters:
         letter.color = self.letters_configuration[
             letter.index]['led_initial_color']
Ejemplo n.º 6
0
 def on_chopstick_plug(self, letter_index: int):
     logger.info("Letter {} chopstick plugged".format(letter_index))
     reaction = self.letters_configuration[letter_index].get(
         'chopstick_plug_reactions', {}).get(self.difficulty, 'do_nothing')
     reaction_callable = getattr(self.letters[letter_index],
                                 'reaction_{}'.format(reaction))
     reaction_callable()
Ejemplo n.º 7
0
    def status(self, value):
        if value not in self.STATUSES:
            logger.error(
                "Unknown status {} (must be one of {}): skipping".format(
                    value, ", ".join(self.STATUSES)))
            return

        if self.status == value:
            logger.info("Status is already {}: skipping".format(value))
            return

        self._status = value

        if self.status == 'playing':
            category = ArduinoProtocol.PLAYING
            self.on_playing()
        elif self.status == 'success':
            category = ArduinoProtocol.SUCCESS
            self.on_success()
        else:
            # status is disabled
            category = ArduinoProtocol.DISABLED

        for port in self.authenticators.keys():
            self.send_serial({ArduinoProtocol.CATEGORY: category}, port)
Ejemplo n.º 8
0
 def event_set_freq(self, value: float):
     value = min(value, 50.)
     logger.info("Set lights freq to {}/50".format(value))
     self.send_serial({
         ArduinoProtocol.CATEGORY: ArduinoProtocol.SET_FREQ,
         ArduinoProtocol.VALUE: value,
     })
Ejemplo n.º 9
0
    def display_sequence(self):
        logger.info("Displaying sequence")

        self.skip_skippable_animations()

        def display_element(index=0):
            if index < len(self.success_sequence):
                # For the last element of the sequence, this code saves a task in the unskippable_animation_task,
                # ensuring that the animation time lasts until the last led has turned black again.
                self.unskippable_animation_task = callLater(
                    2, display_element, index + 1)
                element = self.success_sequence[index]

                self.air_ducts[element["air_duct"]].fan.on()
                self.animation_tasks["fan"] = callLater(
                    1.4, self.air_ducts[element["air_duct"]].fan.off)

                self.fluid_to_color(
                    self.air_ducts[element["air_duct"]].led_index,
                    element["color"],
                    1,
                    "display_element",
                    self.fluid_to_color,
                    self.air_ducts[element["air_duct"]].led_index,
                    "black",
                    1,
                    "display_element",
                )

        self.unskippable_animation_task = callLater(0.5, display_element)
Ejemplo n.º 10
0
    def event_set_status(self, status: str):
        if self.success is False:
            if status in self.STATUSES:
                logger.info("Setting status to '{}'".format(status))
                self.status = status
                if status == 'alarm':
                    self.event_set_led_color(
                        'red',
                        sum(led_strip
                            for led_strip, led_color in self.leds.items()
                            if led_color != 'black'))

                    # If all cells are deactivated while an alarm has been raised. This case should not happen because
                    # players are supposed to be walking on the floor to raise an alarm. But there might be corner cases
                    # where a player extends their hand, is on a cell with no load sensor or if this event has been
                    # triggered from the admin interface...
                    if all(not c for c in self.cells):
                        self.clear_alarm_task = reactor.callLater(
                            self.clear_alarm_delay, self.event_set_status,
                            "playing")

                elif status == 'playing':
                    self.event_set_led_color(
                        'orange',
                        sum(led_strip
                            for led_strip, led_color in self.leds.items()
                            if led_color != 'black'))
                    self.notify_clear()

            else:
                logger.warning("Unknown status '{}': skipping".format(status))
        else:
            logger.warning(
                "Node is in success mode: ignoring set status to '{}'".format(
                    status))
Ejemplo n.º 11
0
    def status(self, value):
        if value not in self.STATUSES:
            logger.warning("Status {} not in {}: skipping".format(
                value, ", ".join(self.STATUSES)))
            return

        if value == self.status:
            logger.info("Status is already {}: skipping".format(value))
            return

        logger.info("Setting status to {}".format(value))
        self._status = value

        if self._status == "inactive":
            self.skip_skippable_animations()

            if self.unskippable_animation_task and self.unskippable_animation_task.active(
            ):
                self.unskippable_animation_task.cancel()
            self.on_inactive()

        elif self._status == "playing":
            self.skip_skippable_animations()

            if self.unskippable_animation_task and self.unskippable_animation_task.active(
            ):
                self.unskippable_animation_task.cancel()
            self.on_playing()

        elif self._status == "success":
            self.on_success()

        self.service.notify_status(self.status)
Ejemplo n.º 12
0
 def difficulty(self, value):
     if value not in self.difficulties:
         logger.warning("Difficulty {} not in {}: skipping".format(
             value, ", ".join(self.difficulties)))
     else:
         logger.info("Setting difficulty to {}".format(value))
         self._difficulty = value
Ejemplo n.º 13
0
def run_node(klass):
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', type=str, default='localhost', help='localhost by default')
    parser.add_argument('-p', '--port', type=int, default=3031, help='3031 by default')
    parser.add_argument('-c', '--config', type=str, help='Path to a config file')
    parser.add_argument('-l', '--log-level', type=str, default='INFO', help='INFO by default')
    parser.add_argument('-f', '--log-file', type=str, default='/dev/null', help='/dev/null by default (no file)')
    parser.add_argument('-t', '--twisted-logs', action='store_true', help='Include twisted logs (no by default)')
    args = parser.parse_args()

    init_logging(level=args.log_level, file=args.log_file, twisted_logs=args.twisted_logs)

    if args.config:
        with open(args.config, "rt") as f:
            config = yaml.safe_load(f.read())

    kwargs = {'config': config} if args.config else {}

    logger.info("Initializing node")
    node = klass(**kwargs)

    logger.info("Connecting to broker at {}:{}".format(args.host, args.port))

    reactor.connectTCP(args.host, args.port, node)
    reactor.run()
Ejemplo n.º 14
0
    def event_reset(self):
        logger.info("Resetting")
        self.status = "disabled"

        shuffle(self.credits)
        self.credits_filo = copy(self.config['credits'])
        self.tag_credits = {}
Ejemplo n.º 15
0
    def display_connected_air_ducts_before_restart(self):
        logger.info("Displaying connected air ducts in red before restart")

        for ad_name, ad in self.air_ducts.items():
            if ad.connected_source is None:
                ad.set_color("black")
            else:
                ad.set_color("red")
Ejemplo n.º 16
0
    def play_pause_stop(self, action, method, track_id):
        logger.info("{} track id={}".format(action, track_id))

        track = self.tracks.get(track_id, None)
        if track is None:
            raise ValueError("Unknown track id={}: aborting".format(track_id))

        getattr(track, method)()
Ejemplo n.º 17
0
    def connection_opened(self):
        for channel in self._subscriptions:
            logger.info("Subscribing to {}".format(channel))
            self.subscribe(channel)

        if not self._first_connection:
            self._first_connection = True
            self.on_first_connection()
Ejemplo n.º 18
0
 def event_reset(self):
     logger.info("Reset")
     self.event_basket_led_off()
     for light_led_id, light_led in self.light_led.items():
         if light_led['on_by_default']:
             self.event_light_on(light_led_id)
         else:
             self.event_light_off(light_led_id)
Ejemplo n.º 19
0
    def play_pause_stop(self, action, method_name, delay):
        if not isinstance(delay, (int, float)):
            raise TypeError(
                "Delay must be int or float (received={}): skipping".format(
                    delay))

        logger.info("{} video".format(action))

        reactor.callLater(delay, getattr(self.player, method_name))
Ejemplo n.º 20
0
    def _cancel_table_tasks(self):
        logger.debug("Cancelling table tasks")
        if self.table_led_task and self.table_led_task.active():
            logger.info("Cancelling table led task")
            self.table_led_task.cancel()

        if self.table_stop_motor_task and self.table_stop_motor_task.active():
            logger.info("Cancelling table stop motor task")
            self.table_stop_motor_task.cancel()
Ejemplo n.º 21
0
    def event_print_pattern(self, pattern: str):
        instructions = self.printer_patterns.get(pattern)
        if instructions is None:
            logger.info(
                "Unknown pattern '{}'. It must be one of {}: ignoring".format(
                    ",".join(self.printer_patterns), pattern))
            return

        self.process_gcode_instructions(instructions)
Ejemplo n.º 22
0
 def event_set_target_freq(self, value: float, step: float):
     value = min(value, 50.)
     logger.info("Set lights target freq to {}/50 with a step of {}".format(
         value, step))
     self.send_serial({
         ArduinoProtocol.CATEGORY: ArduinoProtocol.SET_TARGET_FREQ,
         ArduinoProtocol.VALUE: value,
         ArduinoProtocol.STEP: step,
     })
Ejemplo n.º 23
0
    def event_reset(self):
        logger.info("Resetting")
        if self.send_fog_task and self.send_fog_task.active():
            self.send_fog_task.cancel()

        if self.send_fog_forever_task and self.send_fog_forever_task.active():
            self.send_fog_forever_task.cancel()

        self._release_fog_pin()
        self.event_off()
Ejemplo n.º 24
0
    def check_lock_mistake(self):
        reactor.callLater(self.unlock_frequency, self.check_lock_mistake)
        logger.debug(
            "Checking that locker is not locked (to prevent players from locking by mistake)"
        )

        if not self.locked and self.limit_switch.value:
            logger.info(
                "Locker was locked while it should not have been: unlocking")
            self.event_unlock()
Ejemplo n.º 25
0
    def event_unlock(self):
        self.locked = False
        logger.info("Unlock rising edge: setting device pin to high")
        self.device.on()

        def unlock_falling_edge():
            logger.info("Unlock falling edge: setting device pin to low")
            self.device.off()

        reactor.callLater(self.unlock_falling_edge_delay, unlock_falling_edge)
Ejemplo n.º 26
0
    def process_gcode_instructions(self, instructions):
        if self.printer_is_halted:
            logger.info("Printer is halted: waiting to resume")
            return

        if self.printer_gcode_instructions:
            logger.info("Some gcode instructions are already queued: ignoring")
            return

        self.printer_gcode_instructions = instructions
        self.process_gcode_instruction(self.printer_gcode_instructions[0])
Ejemplo n.º 27
0
    def event_tare(self):
        logger.info("Triggering tare rising edge...")
        self.tare.on()

        # Blocking sleep (no reactor.callLater), because load cell pins will not behave deterministically during this
        # operation. It has not a huge impact on the whole system, and this way, in the hypothetical case in which
        # players toggle cells states (on/off), it should be transparent after the sleep.
        time.sleep(0.5)

        logger.info("Triggering tare falling edge...")
        self.tare.off()
Ejemplo n.º 28
0
    def load_printer_patterns(self):
        patterns_directory = self.config['printer_patterns_directory']
        for filename in os.listdir(patterns_directory):
            path = os.path.join(patterns_directory, filename)

            if not os.path.isfile(path):
                logger.warning("{} is not a file: skipping".format(path))
                continue

            with open(path, 'r') as fh:
                logger.info("Adding printer pattern {}".format(filename))
                self.printer_patterns[filename] = fh.readlines()
Ejemplo n.º 29
0
    def detach_servo(self, servo_id: str):
        logger.info("Detaching servo {}".format(servo_id))

        servo_index = self.servos[servo_id]['index']

        self.send_serial(
            {
                ArduinoProtocol.CATEGORY: ArduinoProtocol.DETACH_SERVO,
                ArduinoProtocol.SERVO_INDEX: servo_index,
            },
            port='/dev/factory',
        )
Ejemplo n.º 30
0
    def new_success_sequence(self):
        logger.info("Loading a new success sequence (try counter={})".format(
            self.try_counters[self.round]))

        round_sequences = self.difficulties[self.difficulty][self.round]
        sequence_index = (self.try_counters[self.round] -
                          1) % len(round_sequences)

        self.success_sequence = round_sequences[sequence_index]

        logger.info("The new success sequence is {}".format(
            self.success_sequence))