| .. _module-pw_hdlc-rpc-example: |
| |
| ===================== |
| RPC over HDLC example |
| ===================== |
| .. pigweed-module-subpage:: |
| :name: pw_hdlc |
| |
| The :ref:`module-pw_hdlc` module includes an example of bringing up a |
| :ref:`module-pw_rpc` server that can be used to invoke RPCs. The example code |
| is located at `//pw_hdlc/rpc_example/ |
| <https://cs.opensource.google/pigweed/pigweed/+/main:pw_hdlc/rpc_example/>`_. |
| This tutorial walks through invoking RPCs interactively and with a script using |
| the RPC over HDLC example. |
| |
| The example implementation of the ``system_server`` facade from ``pw_rpc`` |
| sends HDLC-encoded RPC packets via ``pw_sys_io``. It has blocking sends and |
| reads so it is not suitable for performance-sensitive applications. This |
| mostly serves as a simplistic example for quickly bringing up RPC over HDLC |
| on bare-metal targets. |
| |
| .. note:: |
| |
| This tutorial assumes that you've got a :ref:`target-stm32f429i-disc1` |
| board, but the instructions work with any target that has implemented |
| :ref:`module-pw_sys_io`. |
| |
| ----------- |
| Get started |
| ----------- |
| |
| 1. Set up your board |
| ==================== |
| Connect the board you'll be communicating with. For the |
| :ref:`target-stm32f429i-disc1` board, connect the mini USB port, and note which |
| serial device it appears as (e.g. ``/dev/ttyACM0``). |
| |
| 2. Build Pigweed |
| ================ |
| Activate the Pigweed environment and run the default build. |
| |
| .. code-block:: console |
| |
| . ./activate.sh |
| pw package install nanopb |
| gn gen out --args='dir_pw_third_party_nanopb="//environment/packages/nanopb"' |
| ninja -C out |
| |
| 3. Flash the firmware image |
| =========================== |
| After a successful build, the binary for the example will be located at |
| ``//out/<toolchain>/obj/pw_hdlc/rpc_example/bin/rpc_example.elf``. |
| |
| Flash this image to your board. If you are using the |
| :ref:`target-stm32f429i-disc1` board you can flash the image with |
| `OpenOCD <http://openocd.org>`_. |
| |
| .. code-block:: console |
| |
| openocd -f \ |
| targets/stm32f429i_disc1/py/stm32f429i_disc1_utils/openocd_stm32f4xx.cfg \ |
| -c "program \ |
| out/stm32f429i_disc1_debug/obj/pw_hdlc/rpc_example/bin/rpc_example.elf \ |
| verify reset exit" |
| |
| 4. Invoke RPCs from an interactive console |
| ========================================== |
| The RPC console uses :ref:`module-pw_console` to make a rich interactive |
| console for working with ``pw_rpc``. Run the RPC console with the following |
| command, replacing ``/dev/ttyACM0`` with the correct serial device for your |
| board. |
| |
| .. code-block:: console |
| |
| pw-system-console --no-rpc-logging --proto-globs pw_rpc/echo.proto \ |
| --device /dev/ttyACM0 |
| |
| RPCs may be accessed through the predefined ``rpcs`` variable. RPCs are |
| organized by their protocol buffer package and RPC service, as defined in a |
| .proto file. The ``Echo`` method is part of the ``EchoService``, which |
| is in the ``pw.rpc`` package. To invoke it synchronously, call |
| ``rpcs.pw.rpc.EchoService.Echo()``: |
| |
| .. code-block:: pycon |
| |
| >>> device.rpcs.pw.rpc.EchoService.Echo(msg='Hello, world!') |
| (Status.OK, pw.rpc.EchoMessage(msg='Hello, world!')) |
| |
| 5. Invoke RPCs with a script |
| ============================ |
| RPCs may also be invoked from Python scripts. Close the RPC console if it is |
| running, and execute the example script. Set the ``--device`` argument to the |
| serial port for your device. |
| |
| .. code-block:: console |
| |
| python pw_hdlc/rpc_example/example_script.py --device /dev/ttyACM0 |
| |
| You should see this output: |
| |
| .. code-block:: text |
| |
| The status was Status.OK |
| The payload was msg: "Hello" |
| |
| The device says: Goodbye! |
| |
| ------------------------- |
| Local RPC example project |
| ------------------------- |
| This example is similar to the above example, except it uses a socket to |
| connect a server to a client, both running on the host. |
| |
| 1. Build Pigweed |
| ================ |
| Activate the Pigweed environment and build the code. |
| |
| .. code-block:: console |
| |
| . ./activate.sh |
| pw package install nanopb |
| gn gen out --args='dir_pw_third_party_nanopb="//environment/packages/nanopb"' |
| ninja -C out |
| |
| 2. Start the server |
| =================== |
| Run a ``pw_rpc`` server in one terminal window. |
| |
| .. code-block:: console |
| |
| ./out/pw_strict_host_clang_debug/obj/pw_hdlc/rpc_example/bin/rpc_example |
| |
| 3. Start the client |
| =================== |
| In a separate Pigweed-activated terminal, run the ``pw-system-console`` RPC |
| client with ``--proto-globs`` set to ``pw_rpc/echo.proto``. Additional protos |
| can be added if needed. |
| |
| .. code-block:: console |
| |
| pw-system-console --no-rpc-logging --proto-globs pw_rpc/echo.proto \ |
| --socket-addr default |
| |
| .. tip:: |
| |
| The ``--socket-addr`` value may be replaced with an IP and port separated by |
| a colon, e.g. ``127.0.0.1:33000``. If using a Unix socket, the path to the |
| file follows ``file:``, e.g. ``file:/path/to/unix/socket``. Unix socket |
| Python support is pending, see `python/cpython#77589 |
| <https://github.com/python/cpython/issues/77589>`_. |
| |
| .. tip:: |
| |
| The default RPC channel ID (``1``) can be overriden with ``--channel-id``. |
| |
| 4. Invoke RPCs from the client |
| ============================== |
| Invoke RPCs from the interactive console on the client side. |
| |
| .. code-block:: pycon |
| |
| >>> device.rpcs.pw.rpc.EchoService.Echo(msg='Hello, world!') |
| (Status.OK, pw.rpc.EchoMessage(msg='Hello, world!')) |
| |
| .. seealso:: |
| |
| - The :ref:`module-pw_console` |
| :bdg-ref-primary-line:`module-pw_console-user_guide` for more info on using |
| the the pw_console UI. |
| |
| - The target docs for other RPC-enabled application examples: |
| |
| - :bdg-ref-primary-line:`target-host-device-simulator` |
| - :bdg-ref-primary-line:`target-raspberry-pi-pico` |
| - :bdg-ref-primary-line:`target-stm32f429i-disc1-stm32cube` |
| |
| ----------------- |
| More pw_hdlc docs |
| ----------------- |
| .. include:: ../docs.rst |
| :start-after: .. pw_hdlc-nav-start |
| :end-before: .. pw_hdlc-nav-end |