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))
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()
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})
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))
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']
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()
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)
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, })
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)
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))
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)
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
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()
def event_reset(self): logger.info("Resetting") self.status = "disabled" shuffle(self.credits) self.credits_filo = copy(self.config['credits']) self.tag_credits = {}
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")
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)()
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()
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)
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))
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()
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)
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, })
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()
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()
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)
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])
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()
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()
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', )
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))