Ejemplo n.º 1
0
async def start(zeroconf=None,
                tdm_addr=None,
                tdm_port=None,
                password=None,
                debug=0,
                **kwargs):
    """Start the connection with the Thymio and variable synchronization.

    Arguments:
        tdm_addr - TDM address as a string (default: localhost)
        tdm_port - TDM TCP port number
                   (default: standard or provided by zeroconf)
        password - TDM password (default: None, not necessary for local TDM)
        robot_id - robot node id (default: any)
        robot_name - robot name (default: any)
        zeroconf - True to find TDM with zeroconf (default: automatic)
    """

    client = ClientAsync(zeroconf=zeroconf,
                         tdm_addr=tdm_addr,
                         tdm_port=tdm_port,
                         password=password,
                         debug=debug)
    node = await client.wait_for_node(**kwargs)
    await node.lock()

    global _interactive_console
    _interactive_console = TDMConsole(local_var=get_ipython().user_ns)
    await _interactive_console.init(client, node)

    # configure ipython
    ip = get_ipython()

    ip.events.register("pre_run_cell", _pre_run_cell)
    ip.events.register("post_run_cell", _post_run_cell)
Ejemplo n.º 2
0
async def list(zeroconf=None,
               tdm_addr=None,
               tdm_port=None,
               password=None,
               robot_id=None,
               robot_name=None,
               timeout=5):
    """Display a list of all the robots.

    Arguments:
        tdm_addr - TDM address as a string (default: as in start())
        tdm_port - TDM TCP port number (default: as in start())
        password - TDM password (default: None, not necessary for local TDM)
        robot_id - robot id to restrict the output (default: any)
        robot_name - robot name to restrict the output (default: any)
        timeout - time to obtain at least one node (default: 5s)
        zeroconf - True to find TDM with zeroconf (default: automatic)
    """

    with (ClientAsync(zeroconf=zeroconf,
                      tdm_addr=tdm_addr,
                      tdm_port=tdm_port,
                      password=password) if zeroconf is not None or tdm_addr
          is not None or tdm_port is not None or _interactive_console is None
          else _interactive_console.client) as client:

        for _ in range(1 if timeout < 0.1 else int(timeout / 0.1)):
            client.process_waiting_messages()
            if len(client.nodes) > 0:
                break
            await client.sleep(0.1)

        for node in client.filter_nodes(client.nodes,
                                        node_id=robot_id,
                                        node_name=robot_name):
            print(f"id:       {node.id_str}")
            if "group_id_str" in node.props and node.props[
                    "group_id_str"] is not None:
                print(f"group id: {node.props['group_id_str']}")
            if "name" in node.props:
                print(f"name:     {node.props['name']}")
            if "status" in node.props:
                status_str = {
                    ClientAsync.NODE_STATUS_UNKNOWN: "unknown",
                    ClientAsync.NODE_STATUS_CONNECTED: "connected",
                    ClientAsync.NODE_STATUS_AVAILABLE: "available",
                    ClientAsync.NODE_STATUS_BUSY: "busy",
                    ClientAsync.NODE_STATUS_READY: "ready",
                    ClientAsync.NODE_STATUS_DISCONNECTED: "disconnected",
                }[node.status]
                print(f"status:   {node.status} ({status_str})")
            if "capabilities" in node.props:
                print(f"cap:      {node.props['capabilities']}")
            if "fw_version" in node.props:
                print(f"firmware: {node.props['fw_version']}")
            print()
Ejemplo n.º 3
0
def main(argv=None):
    tdm_addr = None
    tdm_port = None
    password = None
    robot_id = None
    robot_name = None

    if argv is not None:
        try:
            arguments, values = getopt.getopt(argv[1:], "", [
                "help",
                "password="******"robotid=",
                "robotname=",
                "tdmaddr=",
                "tdmport=",
            ])
        except getopt.error as err:
            print(str(err))
            sys.exit(1)
        for arg, val in arguments:
            if arg == "--help":
                help()
                sys.exit(0)
            elif arg == "--password":
                password = val
            elif arg == "--robotid":
                robot_id = val
            elif arg == "--robotname":
                robot_name = val
            elif arg == "--tdmaddr":
                tdm_addr = val
            elif arg == "--tdmport":
                tdm_port = int(val)

    with ClientAsync(tdm_addr=tdm_addr, tdm_port=tdm_port,
                     password=password) as client:

        async def co_init():
            with await client.lock(node_id=robot_id,
                                   node_name=robot_name) as node:
                interactive_console = TDMConsole(user_functions={
                    "get_client": lambda: client,
                    "get_node": lambda: node,
                })
                await interactive_console.init(client, node)
                interactive_console.interact()

        client.run_async_program(co_init)
Ejemplo n.º 4
0
    def connect(self):
        def on_nodes_changed(nodes):
            nodes = [
                node for node in ClientAsync.filter_nodes(
                    nodes, node_id=self.node_id, node_name=self.node_name)
                if node.status != self.client.NODE_STATUS_DISCONNECTED
            ]
            self.node = nodes[0] if len(nodes) > 0 else None
            if self.node is None:
                self.clear_variables()
                self.set_title()
                self.info_mode["text"] = ""
            else:
                self.info_mode["text"] = {
                    self.client.NODE_STATUS_UNKNOWN: "No robot",
                    self.client.NODE_STATUS_CONNECTED: "Robot connected",
                    self.client.NODE_STATUS_AVAILABLE: "Observe",
                    self.client.NODE_STATUS_BUSY: "Observe (robot busy)",
                    self.client.NODE_STATUS_READY: "Control",
                    self.client.NODE_STATUS_DISCONNECTED: "Robot disconnected",
                }[self.node.status]
                # new node, set it up by starting coroutine
                self.start_co = self.init_prog()
                # disable menu Control if busy
                if self.node.status in {
                        self.client.NODE_STATUS_AVAILABLE,
                        self.client.NODE_STATUS_READY
                }:
                    self.robot_menu.entryconfig("Control", state="normal")
                else:
                    self.robot_menu.entryconfig("Control", state="disabled")

        def on_variables_changed(node, variables):
            if self.edited_variable is None:
                for name in variables:
                    if variables[name] is not None:
                        self.add_variable(name, variables[name])

        self.client = ClientAsync(zeroconf=self.zeroconf,
                                  tdm_addr=self.tdm_addr,
                                  tdm_port=self.tdm_port,
                                  password=self.password,
                                  debug=self.debug)
        self.client.on_nodes_changed = on_nodes_changed
        self.client.add_variables_changed_listener(on_variables_changed)
        # schedule communication
        self.after(100, self.run)
Ejemplo n.º 5
0
            sys.exit(0)
        elif arg == "--debug":
            debug = int(val)
        elif arg == "--password":
            password = val
        elif arg == "--robotid":
            robot_id = val
        elif arg == "--robotname":
            robot_name = val
        elif arg == "--tdmaddr":
            tdm_addr = val
        elif arg == "--tdmport":
            tdm_port = int(val)

    with ClientAsync(tdm_addr=tdm_addr,
                     tdm_port=tdm_port,
                     password=password,
                     debug=debug) as client:

        for _ in range(50):
            client.process_waiting_messages()
            if len(client.nodes) > 0:
                break
            sleep(0.1)

        for node in client.filter_nodes(client.nodes,
                                        node_id=robot_id,
                                        node_name=robot_name):
            print(f"id:       {node.id_str}")
            if "group_id_str" in node.props and node.props[
                    "group_id_str"] is not None:
                print(f"group id: {node.props['group_id_str']}")
Ejemplo n.º 6
0
#!/usr/bin/env python3

# This file is part of tdmclient.
# Copyright 2021 ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE,
# Miniature Mobile Robots group, Switzerland
# Author: Yves Piguet
#
# SPDX-License-Identifier: BSD-3-Clause

from tdmclient import ClientAsync

if __name__ == "__main__":

    with ClientAsync(debug=0) as client:

        thymio_program = """
leds.top = [0, 0, 32]
leds.bottom.left = [32, 0, 0]
leds.bottom.right = [0, 32, 0]
"""

        async def prog():
            await client.wait_for_status(client.NODE_STATUS_AVAILABLE)
            node = client.first_node()
            print(node.id_str)
            await node.lock_node()
            await client.wait_for_status(client.NODE_STATUS_READY)
            error = await node.compile(thymio_program)
            if error is not None:
                print(f"Compilation error: {error['error_msg']}")
            else:
Ejemplo n.º 7
0
# This file is part of tdmclient.
# Copyright 2021 ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE,
# Miniature Mobile Robots group, Switzerland
# Author: Yves Piguet
#
# SPDX-License-Identifier: BSD-3-Clause

from tdmclient import ClientAsync

if __name__ == "__main__":

    with ClientAsync() as client:

        async def prog():
            with await client.lock() as node:
                while True:
                    str = input("System sound id (0-8 or exit): ")
                    if str == "exit":
                        break
                    try:
                        i = int(str)
                        error = await node.compile(f"call sound.system({i})")
                        if error is not None:
                            print(f"Compilation error: {error['error_msg']}")
                        else:
                            await node.watch(events=True)
                            error = await node.run()
                            if error is not None:
                                print(f"Error {error['error_code']}")
                    except ValueError:
                        print("Unexpected value")
Ejemplo n.º 8
0
async def watch(timeout=-1,
                zeroconf=None,
                tdm_addr=None,
                tdm_port=None,
                password=None,
                robot_id=None,
                robot_name=None):
    """Display the robot variables with live updates until the timeout elapses
    or the execution is interrupted.

    Arguments:
        timeout -- amount of time until updates stop
        zeroconf -- True to use find TDM with zeroconf (default: automatic)
        password - TDM password (default: None, not necessary for local TDM)
        tdm_addr -- address of the tdm
        tdm_port -- port of the tdm
            (default: connection established by start(), or from zeroconf)
        robot_id ID -- robot specified by id (default: first robot)

        robot_name NAME -- robot specified by name (default: first robot)
    """

    import IPython.display

    def var_dict_to_md(variable_dict):
        md = "| Variable | Value |\n| --- | --- |\n"
        md += "\n".join(
            [f"| {name} | {variable_dict[name]} |" for name in variable_dict])
        return md

    async def watch_node(client, node):
        variable_dict = node.var

        def variables_changed_listener(node, variable_update_dict):
            nonlocal variable_dict
            variable_dict = dict(
                sorted({
                    **variable_dict,
                    **variable_update_dict
                }.items()))
            IPython.display.clear_output(wait=True)
            md = var_dict_to_md(variable_dict)
            IPython.display.display(IPython.display.Markdown(md))

        node.add_variables_changed_listener(variables_changed_listener)
        variables_changed_listener(node, node.var)
        try:
            await client.sleep()
        except:
            # avoid long exception message with stack trace
            print("Interrupted")
        finally:
            IPython.display.clear_output(wait=True)
            node.remove_variables_changed_listener(variables_changed_listener)

    if _interactive_console is not None:
        await watch_node(_interactive_console.client,
                         _interactive_console.node)
    else:
        with ClientAsync(zeroconf=zeroconf,
                         tdm_addr=tdm_addr,
                         tdm_port=tdm_port,
                         password=password) as client:
            await client.wait_for_status_set({
                ClientAsync.NODE_STATUS_AVAILABLE, ClientAsync.NODE_STATUS_BUSY
            })
            node = client.first_node(node_id=robot_id, node_name=robot_name)
            await node.watch(variables=True)
            await watch_node(client, node)