Beispiel #1
0
    def onMessage(self, payload, isBinary):
        if isBinary:
            logger.warning(
                "Binary message received ({} bytes): ignoring".format(
                    len(payload)))
            return

        try:
            unicode_message = payload.decode('utf8')
        except UnicodeDecodeError:
            logger.exception("Cannot decode {}: ignoring".format(payload))
            return

        try:
            message = json.loads(unicode_message)
        except json.JSONDecodeError:
            logger.exception(
                "Cannot load {}: ignoring".format(unicode_message))
            return

        ok, warning = self.validate_message(message)
        if not ok:
            logger.info("Received {}".format(message))
            logger.warning(warning)
            logger.info("Ignoring")
        else:
            logger.debug("Received {}".format(message))
            self.log_message(message, to_server=False)
            self.factory.process_event(message[P.EVENT])
Beispiel #2
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))
Beispiel #3
0
    def eject_floppy(self, reader_index):
        logger.info("Remove floppy {} from reader index={}".format(
            self.floppy_readers[reader_index], reader_index))
        self.floppy_readers[reader_index] = None

        if self.status != "playing":
            logger.debug("Game is not started yet: nothing to do")
            return

        animation_task = self.tasks.get("animation", None)
        if animation_task and animation_task.active():
            animation_task.cancel()

        chrono_task = self.tasks.get("chrono", None)
        if chrono_task and chrono_task.active():
            logger.debug(
                "Chrono is running: stopping chrono and running bad move animation"
            )
            chrono_task.cancel()
            self.bad_move_failure_animation(reader_index)
        else:
            if all([floppy is None for floppy in self.floppy_readers]):
                logger.debug(
                    "All floppies have been removed: restart the game")
                self.restart_game()
            else:
                logger.debug("Some floppies remain inserted: updating errors")
                self.display_inserted_floppies_errors_before_restart()
Beispiel #4
0
    def cancel_tasks(self):
        logger.debug("Cancelling tasks")
        if self.led_task and self.led_task.active():
            logger.info("Cancelling led task")
            self.led_task.cancel()

        if self.stop_motor_task and self.stop_motor_task.active():
            logger.info("Cancelling stop motor task")
            self.stop_motor_task.cancel()
Beispiel #5
0
    def position_down(self):
        if self.motor_up.is_active:
            logger.info(
                "Motor was in up position. Turning off the up position and sleeping for {} seconds"
                .format(self.up_down_minimum_delay))
            self.motor_up.off()
            time.sleep(self.up_down_minimum_delay)

        logger.info("Setting the motor in down position")
        self.motor_down.on()
Beispiel #6
0
    def connectionLost(self, reason):
        if self.client_type == P.CLIENT_ADMIN:
            identifier = self.name
            self.factory.unregister_admin(self)
        elif self.client_type == P.CLIENT_NODE:
            identifier = "{}@{}".format(self.name, self.channel)
            self.factory.unregister_node(self)
        else:
            identifier = self.peer

        logger.info("Lost connection with {}".format(identifier))
Beispiel #7
0
    def play_pause_stop(self, action, method, track_id, delay=0):
        if not isinstance(delay, (int, float)):
            raise ValueError("Delay must be int or float (received={}): skipping".format(delay))

        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))

        reactor.callLater(delay, getattr(track, method))
Beispiel #8
0
    def new_success_sequence(self):
        logger.debug("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))
Beispiel #9
0
    def event_play(self, sound_id: str, delay=0):
        if not isinstance(delay, (int, float)):
            raise ValueError(
                "Delay must be int or float (received={}): skipping".format(
                    delay))

        logger.info("Playing sound id={}".format(sound_id))

        sound = self.sounds.get(sound_id, None)
        if sound is None:
            raise ValueError("Unknown sound id={}: aborting".format(sound_id))

        reactor.callLater(delay, self.sound_player, sound)
Beispiel #10
0
    def check_myself(self):
        callLater(0, self.check_myself)

        is_activated = bool(self.device.value)
        if is_activated is self.last_state:
            return

        self.last_state = is_activated

        if is_activated:
            logger.info("Cell (pin={}) has been activated".format(self.pin))
            self.on_activation()
        else:
            logger.info("Cell (pin={}) has been deactivated".format(self.pin))
            self.on_deactivation()
Beispiel #11
0
    def event_pause(self, video_id: str, delay=0):
        if not isinstance(delay, (int, float)):
            raise ValueError(
                "Delay must be int or float (received={}): skipping".format(
                    delay))

        if video_id not in self.videos:
            raise ValueError(
                "Video id={} is not configured: aborting".format(video_id))

        if delay > 0:
            logger.info("Scheduling to pause video {} in {} seconds".format(
                video_id, delay))

        reactor.callLater(delay, self.videos[video_id].pause)
Beispiel #12
0
    def log_message(self, message, to_server=True):
        identifier = "{}@{}".format(self.name, self.channel)

        if to_server:
            from_ = identifier
            to = P.SERVER
        else:
            from_ = P.SERVER
            to = identifier

        type_ = message[P.MESSAGE_TYPE]

        content = message.get(P.EVENT, "")

        logger.info("[{} > {}] {} {}".format(from_, to, type_, content))
Beispiel #13
0
    def event_set_slide(self, slide_index: int, chapter_id: str, delay=0):
        if not isinstance(delay, (int, float)):
            raise TypeError("Delay must be int or float (received={}): skipping".format(delay))

        if slide_index >= len(self.player.slides):
            raise ValueError("Video has only {} slides ({} is out of range): skipping".format(
                len(self.player.slides), slide_index))

        if chapter_id not in self.player.chapters:
            raise ValueError("Video has no chapter id={}: skipping".format(
                chapter_id))

        logger.info("Setting chapter id={} in slide index={}".format(
            chapter_id, slide_index))

        reactor.callLater(delay, self.player.set_slide, slide_index, chapter_id)
Beispiel #14
0
 def event_reset(self):
     logger.info("Resetting")
     self.motor.position_up()
     logger.info("Turning off the led")
     self.led.off()
     self.cancel_tasks()
     logger.info("Scheduling the motor to stop after {} seconds".format(
         self.pull_delay))
     self.stop_motor_task = callLater(self.pull_delay, self.motor.stop)
     logger.info("Starting to listen to the switch")
     if not self.check_switch_task.running:
         self.check_switch_task.start(1 / 25)
Beispiel #15
0
 def event_down(self):
     logger.info("Pulling table down")
     self.motor.position_down()
     self.cancel_tasks()
     logger.info("Scheduling the led to turn on after {} seconds".format(
         self.pull_delay))
     self.led_task = callLater(self.pull_delay, self.led.on)
     logger.info("Scheduling the motor to stop after {} seconds".format(
         self.pull_delay))
     self.stop_motor_task = callLater(self.pull_delay, self.motor.stop)
     if self.check_switch_task.running:
         logger.info("Stop listening to the switch")
         self.check_switch_task.stop()
Beispiel #16
0
    def insert_floppy(self, reader_index, floppy):
        logger.info("Insert floppy {} in reader index={}".format(
            floppy, reader_index))
        self.floppy_readers[reader_index] = floppy

        if self.status != "playing":
            logger.debug("Game is not started yet: nothing to do")
            return

        animation_task = self.tasks.get("animation", None)
        if animation_task and animation_task.active():
            animation_task.cancel()

        # Chrono has not started <=> game is not started
        chrono_task = self.tasks.get("chrono", None)
        if not chrono_task or not chrono_task.active():
            logger.debug("Chrono is not running: updating errors")
            self.display_inserted_floppies_errors_before_restart()

        # The game has started
        else:
            expected_reader_index = 4 - self.floppy_readers.count(None)
            insert_in_expected_reader = reader_index == expected_reader_index
            good_insert = self.floppy_readers[
                reader_index] == self.success_sequence[reader_index]

            if not insert_in_expected_reader or not good_insert:
                logger.debug(
                    "Bad insert: stopping chrono and running bad move animation"
                )
                chrono_task.cancel()
                self.bad_move_failure_animation(reader_index)

            else:
                if expected_reader_index == 4:
                    logger.debug("Good insert in the last reader: victory!")
                    self.status = "success"
                else:
                    logger.debug("Good insert: running good move animation")
                    self.good_move_animation(reader_index)
Beispiel #17
0
 def event_up(self):
     logger.info("Pulling table up")
     self.motor.position_up()
     logger.info("Turning off the led")
     self.led.off()
     self.cancel_tasks()
     logger.info("Scheduling the motor to stop after {} seconds".format(
         self.pull_delay))
     self.stop_motor_task = callLater(self.pull_delay, self.motor.stop)
Beispiel #18
0
    def generate_success_sequence(self):
        logger.debug("Generating new success sequence")
        new_sequence = []
        available_floppies = self.difficulties[
            self.difficulty]["available_floppies"]
        if 6 > len(available_floppies):
            # The algorithm below might end up in a deadlock
            logger.error(
                "Please submit at least 6 available floppies: skipping sequence generation"
            )
            return

        for i in range(5):
            valid_choice = False
            while not valid_choice:
                floppy = random.choice(available_floppies)
                if self.success_sequence[
                        i] != floppy and floppy not in new_sequence:
                    new_sequence.append(floppy)
                    valid_choice = True

        self.success_sequence = new_sequence
        logger.info("The new success sequence is {}".format(
            self.success_sequence))
Beispiel #19
0
 def onConnect(self, response):
     logger.info("Connected to server: {}".format(response.peer))
Beispiel #20
0
 def onOpen(self):
     logger.info("Node connected: {}".format(self.peer))
Beispiel #21
0
 def check_switch(self):
     if self.switch.is_active:
         if not self.motor.is_position_up:
             logger.info("Switch is active and motor is in position up")
             self.event_down()
             self.check_switch_task.stop()
Beispiel #22
0
 def stop(self):
     logger.info("Stopping the motor")
     self.motor_up.off()
     self.motor_down.off()
Beispiel #23
0
    def onMessage(self, payload, isBinary):
        if isBinary:
            logger.warning(
                "Binary message received ({} bytes): ignoring".format(
                    len(payload)))
            return

        try:
            unicode_message = payload.decode('utf8')
        except UnicodeDecodeError:
            logger.exception("Cannot load {}: ignoring".format(payload))
            return

        try:
            message = json.loads(unicode_message)
        except json.JSONDecodeError:
            logger.exception(
                "Cannot load {}: ignoring".format(unicode_message))
            return

        ok, warning = self.validate_message(message)
        if not ok:
            logger.info("Received {}".format(message))
            logger.warning(warning)
            logger.info("Ignoring")
        else:
            logger.debug("Received {}".format(message))

            self.log_message(message, to_server=True)

            if self.client_type == P.CLIENT_NODE:
                if message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_EVENT:
                    event = message[P.EVENT]
                    self.factory.process_event(self.name, self.channel, event)
                elif message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_LOG:
                    level = message[P.LOG_LEVEL]
                    content = message[P.LOG_CONTENT]
                    if level == P.LOG_LEVEL_INFO:
                        self.factory.send_log_info(content)
                    elif level == P.LOG_LEVEL_ERROR:
                        self.factory.send_log_error(content)

            elif self.client_type == P.CLIENT_ADMIN:
                room_id = message[P.ROOM_ID]

                if message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_RUN:
                    self.factory.process_run_room(room_id)
                elif message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_HALT:
                    self.factory.process_halt_room(room_id)
                elif message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_RESET:
                    self.factory.process_reset_room(room_id)
                elif message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_SEND_EVENT_TO:
                    node = message[P.SEND_EVENT_NODE]
                    event_to_send = message[P.EVENT]
                    self.factory.process_send_event_to(room_id, node,
                                                       event_to_send)
                elif message[P.MESSAGE_TYPE] == P.MESSAGE_TYPE_SEND_EVENT_AS:
                    node = message[P.SEND_EVENT_NODE]
                    event_to_send = message[P.EVENT]
                    self.factory.process_send_event_as(room_id, node,
                                                       event_to_send)
                elif message[
                        P.MESSAGE_TYPE] == P.MESSAGE_TYPE_PRESSED_ADMIN_BUTTON:
                    button_id = message[P.PRESSED_BUTTON_ID]
                    self.factory.process_on_admin_button_pressed(
                        room_id, button_id)

            else:
                self.process_i_am_message(message)
Beispiel #24
0
 def event_stop(self):
     logger.info("Stopping the table")
     self.motor.stop()
Beispiel #25
0
 def event_on(self, color):
     logger.info("Turning on {}".format(color))
     self.colors[color].on()
Beispiel #26
0
 def event_off(self, color):
     logger.info("Turning off {}".format(color))
     self.colors[color].off()
Beispiel #27
0
 def onClose(self, wasClean, code, reason):
     logger.info("WebSocket connection closed: {}".format(reason))
Beispiel #28
0
 def onConnect(self, request):
     logger.info("Node connecting: {}".format(request.peer))
Beispiel #29
0
    def display_sequence(self):
        logger.info("Displaying sequence")

        self.skip_skippable_animations()

        def pre_display_animation():
            self.unskippable_animation_task = callLater(1.6, display_element)
            for ad in self.air_ducts.values():
                ad.set_color("black")
                self.fluid_to_color(
                    ad.led_index,
                    "red",
                    0.1,
                    "display_element",
                    self.fluid_to_color,
                    ad.led_index,
                    "black",
                    0.1,
                    "display_element",
                    self.fluid_to_color,
                    ad.led_index,
                    "red",
                    0.1,
                    "display_element",
                    self.fluid_to_color,
                    ad.led_index,
                    "black",
                    0.1,
                    "display_element",
                    self.fluid_to_color,
                    ad.led_index,
                    "red",
                    0.1,
                    "display_element",
                    self.fluid_to_color,
                    ad.led_index,
                    "black",
                    0.1,
                    "display_element",
                )

        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",
                )

        pre_display_animation()
Beispiel #30
0
    def process_event(self, event):
        logger.debug("Processing event '{}'".format(event))
        if type(event) is not dict:
            logger.debug("Unknown event: skipping")
            return

        if "action" not in event:
            logger.debug("Event has no action: skipping")
            return

        if event["action"] == "calibrate":
            auto = event.get("auto", False)
            if auto:
                logger.info("Start an auto calibration")
                self.niryo.calibrate_auto()
            else:
                logger.info("Start a manual calibration")
                self.niryo.calibrate_manual()
            logger.info("Calibration finished")

        elif event["action"] == "configure":
            if "learning_mode" in event:
                if event["learning_mode"]:
                    logger.info("Activate learning mode")
                    self.niryo.activate_learning_mode(True)
                else:
                    logger.info("Deactivate learning mode")
                    self.niryo.activate_learning_mode(False)
            if "velocity" in event:
                velocity = int(event["velocity"])
                assert 1 <= velocity <= 100, "Speed must be between 1 and 100"
                logger.info("Set velocity to {}".format(velocity))
                self.niryo.set_arm_max_velocity(velocity)

        elif event["action"] == "move_position":
            position_name = str(event.get("position", ""))
            joints = self.get_joints_from_position_name(position_name)
            self.niryo.move_joints(joints)

        elif event["action"] == "move_joint":
            joint = int(event.get("joint", 0))
            assert 0 <= joint <= 5, "Joint must be between 0 and 5"
            position_name = str(event.get("position", ""))

            position_joints = self.get_joints_from_position_name(position_name)
            joints = self.niryo.joints[:]

            joints[joint] = position_joints[joint]

            self.niryo.move_joints(joints)

        elif event["action"] == "open_gripper":
            self.niryo.open_gripper(TOOL_GRIPPER_1_ID, 350)

        elif event["action"] == "close_gripper":
            self.niryo.close_gripper(TOOL_GRIPPER_1_ID, 350)

        else:
            logger.debug("Unknown action type '{}': skipping".format(event["action"]))