Ejemplo n.º 1
0
 def __init__(self,
              console,
              default_node,
              nodes):
     self.default_node = default_node
     self.nodes = nodes
     for node in nodes:
         if node != default_node:
             ClientAsync.aw(node.lock())
Ejemplo n.º 2
0
    def process_events(self, on_event_data=None, all_nodes=False):
        """Listen to events sent by the program running on the robot and process
        them until _exit is received.

        Argument:
            on_event_data -- func(node, event_name) called when new data is received
        """

        exit_received = None  # or exit code once received

        def on_event_received(node, event_name, event_data):
            if self.output_enabled:
                if event_name == "_exit":
                    nonlocal exit_received
                    exit_received = event_data[0]
                elif event_name == "_print":
                    print_id = event_data[0]
                    print_format, print_num_args = print_statements[print_id]
                    print_args = tuple(event_data[1 : 1 + print_num_args])
                    print_str = print_format % print_args
                    print(print_str)
                else:
                    if len(event_data) > 0:
                        if node.id_str not in self.event_data_dict:
                            self.event_data_dict[node.id_str] = {}
                        if event_name not in self.event_data_dict[node.id_str]:
                            self.event_data_dict[node.id_str][event_name] = []
                        self.event_data_dict[node.id_str][event_name].append(event_data)
                        if on_event_data is not None:
                            on_event_data(node, event_name)

        def wake():
            return exit_received is not None

        self.client.clear_event_received_listeners()
        self.client.add_event_received_listener(on_event_received)
        try:
            if all_nodes:
                for node in self.client.nodes:
                    ClientAsync.aw(node.watch(events=True))
            else:
                ClientAsync.aw(self.node.watch(events=True))
            ClientAsync.aw(self.client.sleep(wake=wake))
            self.stop_program(self.node, discard_output=True)
            if exit_received:
                print(f"Exit, status={exit_received}")
        finally:
            if all_nodes:
                for node in self.client.nodes:
                    ClientAsync.aw(node.watch(events=False))
            else:
                ClientAsync.aw(self.node.watch(events=False))
            self.client.clear_event_received_listeners()
Ejemplo n.º 3
0
        def sleep(t):
            """Wait for some time.

            Argument:
                t -- time to wait in seconds
            """

            # send and flush all variables which might have been changed
            self.send_variables(self.var_set)

            # wait
            ClientAsync.aw(self.client.sleep(t))

            # fetch all variables which might be used
            self.fetch_variables(self.var_got, node_flush=False)
Ejemplo n.º 4
0
 def stop_program(self, node, discard_output=False):
     with self.lock_robots({node}) as nodes_l:
         output_enabled_orig = self.output_enabled
         self.output_enabled = not discard_output
         try:
             error = ClientAsync.aw(node.stop())
             if error is not None:
                 raise Exception(f"Error {error['error_code']}")
         finally:
             self.output_enabled = output_enabled_orig
Ejemplo n.º 5
0
 def run_node(node):
     """Compile, configure node, load and start program on a node.
     Return True if the node requires waiting.
     """
     print_statements[node] = []
     events = []
     if language == "python":
         # transpile from Python to Aseba
         transpiler = self.transpile(src, import_thymio)
         src_aseba = transpiler.get_output()
         print_statements[node] = transpiler.print_format_strings
         if len(print_statements[node]) > 0:
             events.append(("_print", 1 + transpiler.print_max_num_args))
         if transpiler.has_exit_event:
             events.append(("_exit", 1))
         for event_name in transpiler.events_in:
             events.append((event_name, transpiler.events_in[event_name]))
         for event_name in transpiler.events_out:
             events.append((event_name, transpiler.events_out[event_name]))
         if len(events) > 0:
             events = ClientAsync.aw(node.filter_out_vm_events(events))
         if len(events) > 0:
             ClientAsync.aw(node.register_events(events))
     elif language == "aseba":
         src_aseba = src
     else:
         raise Exception(f"Unsupported language {language}")
     error = ClientAsync.aw(node.compile(src_aseba))
     if error is not None:
         raise Exception(error["error_msg"])
     node.send_set_scratchpad(src_aseba)
     wait_for_node = wait
     if wait is None:
         # default: wait if there are events to receive
         wait_for_node = len(events) > 0
     if wait_for_node:
         ClientAsync.aw(node.watch(events=True, vm_state=True))
     error = ClientAsync.aw(node.run())
     if error is not None:
         raise Exception(f"Error {error['error_code']}")
     return wait_for_node
Ejemplo n.º 6
0
    def run_program(self, src,
                    nodes=None,
                    language="aseba", wait=False, import_thymio=True):
        if nodes is None:
            nodes = [self.node]

        running_nodes = set()

        # exit_received[node] = exit code once received
        exit_received = {}
        # print_statements[node][print_id] = (print_format, print_num_args)
        print_statements = {}

        def on_event_received(node, event_name, event_data):
            if self.output_enabled:
                if event_name == "_exit":
                    exit_received[node] = event_data[0]
                    if event_data[0]:
                        exit_str = f"Exit, status={event_data[0]}"
                        if len(nodes) > 1:
                            # multiple nodes: add prefix
                            exit_str = f"[R{nodes.index(node)}] " + exit_str
                        print(exit_str)
                    self.stop_program(node, discard_output=True)
                    running_nodes.remove(node)
                elif event_name == "_print":
                    print_id = event_data[0]
                    print_format, print_num_args = print_statements[node][print_id]
                    print_args = tuple(event_data[1 : 1 + print_num_args])
                    print_str = print_format % print_args
                    if len(nodes) > 1:
                        # multiple nodes: add prefix
                        print_str = f"[R{nodes.index(node)}] " + print_str
                    print(print_str)
                else:
                    if len(event_data) > 0:
                        if node.id_str not in self.event_data_dict:
                            self.event_data_dict[node.id_str] = {}
                        if event_name not in self.event_data_dict[node.id_str]:
                            self.event_data_dict[node.id_str][event_name] = []
                        self.event_data_dict[node.id_str][event_name].append(event_data)

        def on_vm_state_changed(node, state, line, error, error_msg):
            if error != ClientAsync.ERROR_NO_ERROR:
                exit_received[node] = f"vm error {error}"
            if error_msg:
                print(f"{error_msg} (line {line}{' in Aseba' if language != 'aseba' else ''})")

        def run_node(node):
            """Compile, configure node, load and start program on a node.
            Return True if the node requires waiting.
            """
            print_statements[node] = []
            events = []
            if language == "python":
                # transpile from Python to Aseba
                transpiler = self.transpile(src, import_thymio)
                src_aseba = transpiler.get_output()
                print_statements[node] = transpiler.print_format_strings
                if len(print_statements[node]) > 0:
                    events.append(("_print", 1 + transpiler.print_max_num_args))
                if transpiler.has_exit_event:
                    events.append(("_exit", 1))
                for event_name in transpiler.events_in:
                    events.append((event_name, transpiler.events_in[event_name]))
                for event_name in transpiler.events_out:
                    events.append((event_name, transpiler.events_out[event_name]))
                if len(events) > 0:
                    events = ClientAsync.aw(node.filter_out_vm_events(events))
                if len(events) > 0:
                    ClientAsync.aw(node.register_events(events))
            elif language == "aseba":
                src_aseba = src
            else:
                raise Exception(f"Unsupported language {language}")
            error = ClientAsync.aw(node.compile(src_aseba))
            if error is not None:
                raise Exception(error["error_msg"])
            node.send_set_scratchpad(src_aseba)
            wait_for_node = wait
            if wait is None:
                # default: wait if there are events to receive
                wait_for_node = len(events) > 0
            if wait_for_node:
                ClientAsync.aw(node.watch(events=True, vm_state=True))
            error = ClientAsync.aw(node.run())
            if error is not None:
                raise Exception(f"Error {error['error_code']}")
            return wait_for_node

        self.reset_sync_var()
        self.client.clear_event_received_listeners()
        self.client.add_event_received_listener(on_event_received)
        self.client.add_vm_state_changed_listener(on_vm_state_changed)
        wait_for_nodes = False
        with self.lock_robots(nodes) as nodes_l:
            # transpile, compile, load, set scratchpad, and run
            for node in nodes_l:
                wait_for_node = run_node(node)
                wait_for_nodes = wait_for_nodes or wait_for_node
                running_nodes.add(node)

        # wait until all nodes have exited
        if wait_for_nodes:
            try:
                def wake():
                    # True when all nodes have exited
                    return len(exit_received) >= len(nodes)
                ClientAsync.aw(self.client.sleep(wake=wake))
            finally:
                # stop nodes still running
                for node in running_nodes:
                    self.stop_program(node, discard_output=True)
                self.client.clear_event_received_listeners()
                self.client.clear_vm_state_changed_listener()