1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-guides: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker=================== 4*61c4878aSAndroid Build Coastguard WorkerQuickstart & guides 5*61c4878aSAndroid Build Coastguard Worker=================== 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_rpc 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-quickstart: 10*61c4878aSAndroid Build Coastguard Worker 11*61c4878aSAndroid Build Coastguard Worker---------- 12*61c4878aSAndroid Build Coastguard WorkerQuickstart 13*61c4878aSAndroid Build Coastguard Worker---------- 14*61c4878aSAndroid Build Coastguard WorkerThis section guides you through the process of adding ``pw_rpc`` to your project. 15*61c4878aSAndroid Build Coastguard Worker 16*61c4878aSAndroid Build Coastguard WorkerCheck out :ref:`module-pw_rpc-design-overview` for a conceptual explanation 17*61c4878aSAndroid Build Coastguard Workerof the RPC lifecycle. 18*61c4878aSAndroid Build Coastguard Worker 19*61c4878aSAndroid Build Coastguard Worker1. RPC service declaration 20*61c4878aSAndroid Build Coastguard Worker========================== 21*61c4878aSAndroid Build Coastguard WorkerDeclare a :ref:`service <module-pw_rpc-design-services>` in a service 22*61c4878aSAndroid Build Coastguard Workerdefinition: 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf 25*61c4878aSAndroid Build Coastguard Worker 26*61c4878aSAndroid Build Coastguard Worker /* //applications/blinky/blinky.proto */ 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker syntax = "proto3"; 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard Worker package blinky; 31*61c4878aSAndroid Build Coastguard Worker 32*61c4878aSAndroid Build Coastguard Worker import "pw_protobuf_protos/common.proto"; 33*61c4878aSAndroid Build Coastguard Worker 34*61c4878aSAndroid Build Coastguard Worker service Blinky { 35*61c4878aSAndroid Build Coastguard Worker // Toggles the LED on or off. 36*61c4878aSAndroid Build Coastguard Worker rpc ToggleLed(pw.protobuf.Empty) returns (pw.protobuf.Empty); 37*61c4878aSAndroid Build Coastguard Worker // Continuously blinks the board LED a specified number of times. 38*61c4878aSAndroid Build Coastguard Worker rpc Blink(BlinkRequest) returns (pw.protobuf.Empty); 39*61c4878aSAndroid Build Coastguard Worker } 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard Worker message BlinkRequest { 42*61c4878aSAndroid Build Coastguard Worker // The interval at which to blink the LED, in milliseconds. 43*61c4878aSAndroid Build Coastguard Worker uint32 interval_ms = 1; 44*61c4878aSAndroid Build Coastguard Worker // The number of times to blink the LED. 45*61c4878aSAndroid Build Coastguard Worker optional uint32 blink_count = 2; 46*61c4878aSAndroid Build Coastguard Worker } // BlinkRequest 47*61c4878aSAndroid Build Coastguard Worker 48*61c4878aSAndroid Build Coastguard WorkerDeclare the protocol buffer in ``BUILD.bazel``: 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 51*61c4878aSAndroid Build Coastguard Worker 52*61c4878aSAndroid Build Coastguard Worker # //applications/blinky/BUILD.bazel 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard Worker load( 55*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_protobuf_compiler:pw_proto_library.bzl", 56*61c4878aSAndroid Build Coastguard Worker "nanopb_proto_library", 57*61c4878aSAndroid Build Coastguard Worker "nanopb_rpc_proto_library", 58*61c4878aSAndroid Build Coastguard Worker ) 59*61c4878aSAndroid Build Coastguard Worker 60*61c4878aSAndroid Build Coastguard Worker proto_library( 61*61c4878aSAndroid Build Coastguard Worker name = "proto", 62*61c4878aSAndroid Build Coastguard Worker srcs = ["blinky.proto"], 63*61c4878aSAndroid Build Coastguard Worker deps = [ 64*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_protobuf:common_proto", 65*61c4878aSAndroid Build Coastguard Worker ], 66*61c4878aSAndroid Build Coastguard Worker ) 67*61c4878aSAndroid Build Coastguard Worker 68*61c4878aSAndroid Build Coastguard Worker nanopb_proto_library( 69*61c4878aSAndroid Build Coastguard Worker name = "nanopb", 70*61c4878aSAndroid Build Coastguard Worker deps = [":proto"], 71*61c4878aSAndroid Build Coastguard Worker ) 72*61c4878aSAndroid Build Coastguard Worker 73*61c4878aSAndroid Build Coastguard Worker nanopb_rpc_proto_library( 74*61c4878aSAndroid Build Coastguard Worker name = "nanopb_rpc", 75*61c4878aSAndroid Build Coastguard Worker nanopb_proto_library_deps = [":nanopb"], 76*61c4878aSAndroid Build Coastguard Worker deps = [":proto"], 77*61c4878aSAndroid Build Coastguard Worker ) 78*61c4878aSAndroid Build Coastguard Worker 79*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-quickstart-codegen: 80*61c4878aSAndroid Build Coastguard Worker 81*61c4878aSAndroid Build Coastguard Worker2. RPC code generation 82*61c4878aSAndroid Build Coastguard Worker====================== 83*61c4878aSAndroid Build Coastguard WorkerHow do you interact with this protobuf from C++? ``pw_rpc`` uses 84*61c4878aSAndroid Build Coastguard Workercodegen libraries to automatically transform ``.proto`` definitions 85*61c4878aSAndroid Build Coastguard Workerinto C++ header files. These headers are generated in the build 86*61c4878aSAndroid Build Coastguard Workeroutput directory. Their exact location varies by build system and toolchain 87*61c4878aSAndroid Build Coastguard Workerbut the C++ include path always matches the source declarations in 88*61c4878aSAndroid Build Coastguard Worker``proto_library``. The ``.proto`` extension is replaced with an extension 89*61c4878aSAndroid Build Coastguard Workercorresponding to the protobuf codegen library in use: 90*61c4878aSAndroid Build Coastguard Worker 91*61c4878aSAndroid Build Coastguard Worker.. csv-table:: 92*61c4878aSAndroid Build Coastguard Worker :header: "Protobuf libraries", "Build subtarget", "Protobuf header", "pw_rpc header" 93*61c4878aSAndroid Build Coastguard Worker 94*61c4878aSAndroid Build Coastguard Worker "Raw only", "``.raw_rpc``", "(none)", "``.raw_rpc.pb.h``" 95*61c4878aSAndroid Build Coastguard Worker "Nanopb or raw", "``.nanopb_rpc``", "``.pb.h``", "``.rpc.pb.h``" 96*61c4878aSAndroid Build Coastguard Worker "pw_protobuf or raw", "``.pwpb_rpc``", "``.pwpb.h``", "``.rpc.pwpb.h``" 97*61c4878aSAndroid Build Coastguard Worker 98*61c4878aSAndroid Build Coastguard WorkerMost projects should default to Nanopb. See 99*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_rpc-guides-headers`. 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard WorkerFor example, the generated RPC header for ``applications/blinky.proto`` is 102*61c4878aSAndroid Build Coastguard Worker``applications/blinky.rpc.pb.h`` for Nanopb or 103*61c4878aSAndroid Build Coastguard Worker``applications/blinky.raw_rpc.pb.h`` for raw RPCs. 104*61c4878aSAndroid Build Coastguard Worker 105*61c4878aSAndroid Build Coastguard WorkerThe generated header defines a base class for each RPC service declared in the 106*61c4878aSAndroid Build Coastguard Worker``.proto`` file. A service named ``TheService`` in package ``foo.bar`` would 107*61c4878aSAndroid Build Coastguard Workergenerate the following base class for ``pw_protobuf``: 108*61c4878aSAndroid Build Coastguard Worker 109*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: template <typename Implementation> foo::bar::pw_rpc::pwpb::TheService::Service 110*61c4878aSAndroid Build Coastguard Worker 111*61c4878aSAndroid Build Coastguard Worker3. RPC service definition 112*61c4878aSAndroid Build Coastguard Worker========================= 113*61c4878aSAndroid Build Coastguard WorkerImplement a service class by inheriting from the generated RPC service 114*61c4878aSAndroid Build Coastguard Workerbase class and defining a method for each RPC. The methods must match the name 115*61c4878aSAndroid Build Coastguard Workerand function signature for one of the supported protobuf implementations. 116*61c4878aSAndroid Build Coastguard WorkerServices may mix and match protobuf implementations within one service. 117*61c4878aSAndroid Build Coastguard Worker 118*61c4878aSAndroid Build Coastguard WorkerA Nanopb implementation of the ``Blinky`` service looks like this: 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 121*61c4878aSAndroid Build Coastguard Worker 122*61c4878aSAndroid Build Coastguard Worker /* //applications/blinky/main.cc */ 123*61c4878aSAndroid Build Coastguard Worker 124*61c4878aSAndroid Build Coastguard Worker // ... 125*61c4878aSAndroid Build Coastguard Worker #include "applications/blinky/blinky.rpc.pb.h" 126*61c4878aSAndroid Build Coastguard Worker #include "pw_system/rpc_server.h" 127*61c4878aSAndroid Build Coastguard Worker // ... 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker class BlinkyService final 130*61c4878aSAndroid Build Coastguard Worker : public blinky::pw_rpc::nanopb::Blinky::Service<BlinkyService> { 131*61c4878aSAndroid Build Coastguard Worker public: 132*61c4878aSAndroid Build Coastguard Worker pw::Status ToggleLed(const pw_protobuf_Empty &, pw_protobuf_Empty &) { 133*61c4878aSAndroid Build Coastguard Worker // Turn the LED off if it's currently on and vice versa 134*61c4878aSAndroid Build Coastguard Worker } 135*61c4878aSAndroid Build Coastguard Worker pw::Status Blink(const blinky_BlinkRequest &request, pw_protobuf_Empty &) { 136*61c4878aSAndroid Build Coastguard Worker if (request.blink_count == 0) { 137*61c4878aSAndroid Build Coastguard Worker // Stop blinking 138*61c4878aSAndroid Build Coastguard Worker } 139*61c4878aSAndroid Build Coastguard Worker if (request.interval_ms > 0) { 140*61c4878aSAndroid Build Coastguard Worker // Change the blink interval 141*61c4878aSAndroid Build Coastguard Worker } 142*61c4878aSAndroid Build Coastguard Worker if (request.has_blink_count) { // Auto-generated property 143*61c4878aSAndroid Build Coastguard Worker // Blink request.blink_count times 144*61c4878aSAndroid Build Coastguard Worker } 145*61c4878aSAndroid Build Coastguard Worker } 146*61c4878aSAndroid Build Coastguard Worker }; 147*61c4878aSAndroid Build Coastguard Worker 148*61c4878aSAndroid Build Coastguard Worker BlinkyService blinky_service; 149*61c4878aSAndroid Build Coastguard Worker 150*61c4878aSAndroid Build Coastguard Worker namespace pw::system { 151*61c4878aSAndroid Build Coastguard Worker 152*61c4878aSAndroid Build Coastguard Worker void UserAppInit() { 153*61c4878aSAndroid Build Coastguard Worker // ... 154*61c4878aSAndroid Build Coastguard Worker pw::system::GetRpcServer().RegisterService(blinky_service); 155*61c4878aSAndroid Build Coastguard Worker } 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard Worker } // namespace pw::system 158*61c4878aSAndroid Build Coastguard Worker 159*61c4878aSAndroid Build Coastguard WorkerDeclare the implementation in ``BUILD.bazel``: 160*61c4878aSAndroid Build Coastguard Worker 161*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 162*61c4878aSAndroid Build Coastguard Worker 163*61c4878aSAndroid Build Coastguard Worker # //applications/blinky/BUILD.bazel 164*61c4878aSAndroid Build Coastguard Worker 165*61c4878aSAndroid Build Coastguard Worker cc_binary( 166*61c4878aSAndroid Build Coastguard Worker name = "blinky", 167*61c4878aSAndroid Build Coastguard Worker srcs = ["main.cc"], 168*61c4878aSAndroid Build Coastguard Worker deps = [ 169*61c4878aSAndroid Build Coastguard Worker ":nanopb_rpc", 170*61c4878aSAndroid Build Coastguard Worker # ... 171*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_system", 172*61c4878aSAndroid Build Coastguard Worker ], 173*61c4878aSAndroid Build Coastguard Worker ) 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard Worker.. tip:: 176*61c4878aSAndroid Build Coastguard Worker 177*61c4878aSAndroid Build Coastguard Worker The generated code includes RPC service implementation stubs. You can 178*61c4878aSAndroid Build Coastguard Worker reference or copy and paste these to get started with implementing a service. 179*61c4878aSAndroid Build Coastguard Worker These stub classes are generated at the bottom of the pw_rpc proto header. 180*61c4878aSAndroid Build Coastguard Worker 181*61c4878aSAndroid Build Coastguard Worker To use the stubs, do the following: 182*61c4878aSAndroid Build Coastguard Worker 183*61c4878aSAndroid Build Coastguard Worker #. Locate the generated RPC header in the build directory. For example: 184*61c4878aSAndroid Build Coastguard Worker 185*61c4878aSAndroid Build Coastguard Worker .. code-block:: sh 186*61c4878aSAndroid Build Coastguard Worker 187*61c4878aSAndroid Build Coastguard Worker cd bazel-out && find . -name blinky.rpc.pb.h 188*61c4878aSAndroid Build Coastguard Worker 189*61c4878aSAndroid Build Coastguard Worker #. Scroll to the bottom of the generated RPC header. 190*61c4878aSAndroid Build Coastguard Worker #. Copy the stub class declaration to a header file. 191*61c4878aSAndroid Build Coastguard Worker #. Copy the member function definitions to a source file. 192*61c4878aSAndroid Build Coastguard Worker #. Rename the class or change the namespace, if desired. 193*61c4878aSAndroid Build Coastguard Worker #. List these files in a build target with a dependency on 194*61c4878aSAndroid Build Coastguard Worker ``proto_library``. 195*61c4878aSAndroid Build Coastguard Worker 196*61c4878aSAndroid Build Coastguard Worker4. Register the service with a server 197*61c4878aSAndroid Build Coastguard Worker===================================== 198*61c4878aSAndroid Build Coastguard WorkerSet up the server and register the service: 199*61c4878aSAndroid Build Coastguard Worker 200*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 201*61c4878aSAndroid Build Coastguard Worker 202*61c4878aSAndroid Build Coastguard Worker /* //applications/blinky/main.cc */ 203*61c4878aSAndroid Build Coastguard Worker 204*61c4878aSAndroid Build Coastguard Worker // ... 205*61c4878aSAndroid Build Coastguard Worker #include "pw_system/rpc_server.h" 206*61c4878aSAndroid Build Coastguard Worker // ... 207*61c4878aSAndroid Build Coastguard Worker 208*61c4878aSAndroid Build Coastguard Worker namespace pw::system { 209*61c4878aSAndroid Build Coastguard Worker 210*61c4878aSAndroid Build Coastguard Worker void UserAppInit() { 211*61c4878aSAndroid Build Coastguard Worker // ... 212*61c4878aSAndroid Build Coastguard Worker pw::system::GetRpcServer().RegisterService(blinky_service); 213*61c4878aSAndroid Build Coastguard Worker } 214*61c4878aSAndroid Build Coastguard Worker 215*61c4878aSAndroid Build Coastguard Worker } // namespace pw::system 216*61c4878aSAndroid Build Coastguard Worker 217*61c4878aSAndroid Build Coastguard WorkerNext steps 218*61c4878aSAndroid Build Coastguard Worker========== 219*61c4878aSAndroid Build Coastguard WorkerThat's the end of the quickstart! Learn more about ``pw_rpc``: 220*61c4878aSAndroid Build Coastguard Worker 221*61c4878aSAndroid Build Coastguard Worker* Check out :ref:`module-pw_rpc-cpp` for detailed guidance on using the C++ 222*61c4878aSAndroid Build Coastguard Worker client and server libraries. 223*61c4878aSAndroid Build Coastguard Worker 224*61c4878aSAndroid Build Coastguard Worker* If you have any questions, you can talk to the Pigweed team in the ``#pw_rpc`` 225*61c4878aSAndroid Build Coastguard Worker channel of our `Discord <https://discord.gg/M9NSeTA>`_. 226*61c4878aSAndroid Build Coastguard Worker 227*61c4878aSAndroid Build Coastguard Worker* The rest of this page provides general guidance on common questions and use cases. 228*61c4878aSAndroid Build Coastguard Worker 229*61c4878aSAndroid Build Coastguard Worker* The quickstart code was based off these real-world examples of the Pigweed 230*61c4878aSAndroid Build Coastguard Worker team adding ``pw_rpc`` to a project: 231*61c4878aSAndroid Build Coastguard Worker 232*61c4878aSAndroid Build Coastguard Worker * `applications/blinky: Add Blinky RPC service <https://pwrev.dev/218225>`_ 233*61c4878aSAndroid Build Coastguard Worker 234*61c4878aSAndroid Build Coastguard Worker * `rpc: Use nanopb instead of pw_protobuf <https://pwrev.dev/218732>`_ 235*61c4878aSAndroid Build Coastguard Worker 236*61c4878aSAndroid Build Coastguard Worker* You can build clients in other languages, such as Python and TypeScript. 237*61c4878aSAndroid Build Coastguard Worker See :ref:`module-pw_rpc-libraries`. 238*61c4878aSAndroid Build Coastguard Worker 239*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-zephyr: 240*61c4878aSAndroid Build Coastguard Worker 241*61c4878aSAndroid Build Coastguard Worker--------------------------- 242*61c4878aSAndroid Build Coastguard WorkerSetting up pw_rpc in Zephyr 243*61c4878aSAndroid Build Coastguard Worker--------------------------- 244*61c4878aSAndroid Build Coastguard WorkerTo enable ``pw_rpc.*`` for Zephyr add ``CONFIG_PIGWEED_RPC=y`` to the project's 245*61c4878aSAndroid Build Coastguard Workerconfiguration. This will enable the Kconfig menu for the following: 246*61c4878aSAndroid Build Coastguard Worker 247*61c4878aSAndroid Build Coastguard Worker* ``pw_rpc.server`` which can be enabled via ``CONFIG_PIGWEED_RPC_SERVER=y``. 248*61c4878aSAndroid Build Coastguard Worker* ``pw_rpc.client`` which can be enabled via ``CONFIG_PIGWEED_RPC_CLIENT=y``. 249*61c4878aSAndroid Build Coastguard Worker* ``pw_rpc.client_server`` which can be enabled via 250*61c4878aSAndroid Build Coastguard Worker ``CONFIG_PIGWEED_RPC_CLIENT_SERVER=y``. 251*61c4878aSAndroid Build Coastguard Worker* ``pw_rpc.common`` which can be enabled via ``CONFIG_PIGWEED_RPC_COMMON=y``. 252*61c4878aSAndroid Build Coastguard Worker 253*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-syntax-versions: 254*61c4878aSAndroid Build Coastguard Worker 255*61c4878aSAndroid Build Coastguard Worker--------------------------- 256*61c4878aSAndroid Build Coastguard Workerproto2 versus proto3 syntax 257*61c4878aSAndroid Build Coastguard Worker--------------------------- 258*61c4878aSAndroid Build Coastguard WorkerAlways use proto3 syntax rather than proto2 for new protocol buffers. proto2 259*61c4878aSAndroid Build Coastguard Workerprotobufs can be compiled for ``pw_rpc``, but they are not as well supported 260*61c4878aSAndroid Build Coastguard Workeras proto3. Specifically, ``pw_rpc`` lacks support for non-zero default values 261*61c4878aSAndroid Build Coastguard Workerin proto2. When using Nanopb with ``pw_rpc``, proto2 response protobufs with 262*61c4878aSAndroid Build Coastguard Workernon-zero field defaults should be manually initialized to the default struct. 263*61c4878aSAndroid Build Coastguard Worker 264*61c4878aSAndroid Build Coastguard WorkerIn the past, proto3 was sometimes avoided because it lacked support for field 265*61c4878aSAndroid Build Coastguard Workerpresence detection. Fortunately, this has been fixed: proto3 now supports 266*61c4878aSAndroid Build Coastguard Worker``optional`` fields, which are equivalent to proto2 ``optional`` fields. 267*61c4878aSAndroid Build Coastguard Worker 268*61c4878aSAndroid Build Coastguard WorkerIf you need to distinguish between a default-valued field and a missing field, 269*61c4878aSAndroid Build Coastguard Workermark the field as ``optional``. The presence of the field can be detected 270*61c4878aSAndroid Build Coastguard Workerwith ``std::optional``, a ``HasField(name)``, or ``has_<field>`` member, 271*61c4878aSAndroid Build Coastguard Workerdepending on the library. 272*61c4878aSAndroid Build Coastguard Worker 273*61c4878aSAndroid Build Coastguard WorkerOptional fields have some overhead. If using Nanopb, default-valued fields 274*61c4878aSAndroid Build Coastguard Workerare included in the encoded proto, and the proto structs have a 275*61c4878aSAndroid Build Coastguard Worker``has_<field>`` flag for each optional field. Use plain fields if field 276*61c4878aSAndroid Build Coastguard Workerpresence detection is not needed. 277*61c4878aSAndroid Build Coastguard Worker 278*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf 279*61c4878aSAndroid Build Coastguard Worker 280*61c4878aSAndroid Build Coastguard Worker syntax = "proto3"; 281*61c4878aSAndroid Build Coastguard Worker 282*61c4878aSAndroid Build Coastguard Worker message MyMessage { 283*61c4878aSAndroid Build Coastguard Worker // Leaving this field unset is equivalent to setting it to 0. 284*61c4878aSAndroid Build Coastguard Worker int32 number = 1; 285*61c4878aSAndroid Build Coastguard Worker 286*61c4878aSAndroid Build Coastguard Worker // Setting this field to 0 is different from leaving it unset. 287*61c4878aSAndroid Build Coastguard Worker optional int32 other_number = 2; 288*61c4878aSAndroid Build Coastguard Worker } 289*61c4878aSAndroid Build Coastguard Worker 290*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-guides-headers: 291*61c4878aSAndroid Build Coastguard Worker 292*61c4878aSAndroid Build Coastguard Worker----------------------------------------------------------- 293*61c4878aSAndroid Build Coastguard WorkerWhen to use raw, Nanopb, or pw_protobuf headers and methods 294*61c4878aSAndroid Build Coastguard Worker----------------------------------------------------------- 295*61c4878aSAndroid Build Coastguard WorkerThere are three types of generated headers and methods available: 296*61c4878aSAndroid Build Coastguard Worker 297*61c4878aSAndroid Build Coastguard Worker* Raw 298*61c4878aSAndroid Build Coastguard Worker* Nanopb 299*61c4878aSAndroid Build Coastguard Worker* ``pw_protobuf`` 300*61c4878aSAndroid Build Coastguard Worker 301*61c4878aSAndroid Build Coastguard WorkerThis section explains when to use each one. See 302*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_rpc-quickstart-codegen` for context. 303*61c4878aSAndroid Build Coastguard Worker 304*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` doesn't generate raw headers unless you specifically request them 305*61c4878aSAndroid Build Coastguard Workerin your build. These headers allow you to use raw methods. Raw methods only 306*61c4878aSAndroid Build Coastguard Workergive you a serialized request buffer and an output buffer. Projects typically 307*61c4878aSAndroid Build Coastguard Workeronly work with raw headers and methods when they have large, complex proto 308*61c4878aSAndroid Build Coastguard Workerdefinitions (e.g. lots of callbacks) that are difficult to work with. Advanced 309*61c4878aSAndroid Build Coastguard Workerprojects might use raw headers and methods when they need finer control over 310*61c4878aSAndroid Build Coastguard Workerhow a proto is encoded. 311*61c4878aSAndroid Build Coastguard Worker 312*61c4878aSAndroid Build Coastguard WorkerNanopb and ``pw_protobuf`` are higher-level libraries that make it easier 313*61c4878aSAndroid Build Coastguard Workerto serialize or deserialize protos inside raw bytes. Most new projects should 314*61c4878aSAndroid Build Coastguard Workerdefault to Nanopb for the time being. Pigweed has plans to improve ``pw_protobuf`` 315*61c4878aSAndroid Build Coastguard Workerbut those plans will take a while to implement. 316*61c4878aSAndroid Build Coastguard Worker 317*61c4878aSAndroid Build Coastguard WorkerThe Nanopb and ``pw_protobuf`` APIs and codegen are both built on top of the 318*61c4878aSAndroid Build Coastguard Workerunderlying raw APIs, which is why it's always possible to fallback to 319*61c4878aSAndroid Build Coastguard Workerraw APIs. If you define a Nanopb or ``pw_protobuf`` service, you can choose to 320*61c4878aSAndroid Build Coastguard Workermake individual methods raw by defining them using the raw method signature. 321*61c4878aSAndroid Build Coastguard WorkerYou still import the Nanopb or ``pw_protobuf`` header and can use the 322*61c4878aSAndroid Build Coastguard Workermethods from those libraries elsewhere. Unless you believe your entire service 323*61c4878aSAndroid Build Coastguard Workerrequires pure raw methods, it's better to use Nanopb or ``pw_protobuf`` for 324*61c4878aSAndroid Build Coastguard Workermost things and fallback to raw only when needed. 325*61c4878aSAndroid Build Coastguard Worker 326*61c4878aSAndroid Build Coastguard Worker.. caution:: Mixing Nanopb and pw_protobuf within the same service not supported 327*61c4878aSAndroid Build Coastguard Worker 328*61c4878aSAndroid Build Coastguard Worker You can have a mix of Nanopb, ``pw_protobuf``, and raw services on the 329*61c4878aSAndroid Build Coastguard Worker same server. Within a service, you can mix raw and Nanopb or raw and ``pw_protobuf`` 330*61c4878aSAndroid Build Coastguard Worker methods. You can't currently mix Nanopb and ``pw_protobuf`` methods but Pigweed 331*61c4878aSAndroid Build Coastguard Worker can implement this if needed. :bug:`234874320` outlines some conflicts you may 332*61c4878aSAndroid Build Coastguard Worker encounter if you try to include Nanopb and ``pw_protobuf`` headers in the 333*61c4878aSAndroid Build Coastguard Worker same source file. 334*61c4878aSAndroid Build Coastguard Worker 335*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-guides-raw-fallback: 336*61c4878aSAndroid Build Coastguard Worker 337*61c4878aSAndroid Build Coastguard WorkerFalling back to raw methods 338*61c4878aSAndroid Build Coastguard Worker=========================== 339*61c4878aSAndroid Build Coastguard WorkerWhen implementing an RPC service using Nanopb or ``pw_protobuf``, you may 340*61c4878aSAndroid Build Coastguard Workersometimes run into limitations of the protobuf library when used in conjunction 341*61c4878aSAndroid Build Coastguard Workerwith ``pw_rpc``. For example, fields which use callbacks require those callbacks 342*61c4878aSAndroid Build Coastguard Workerto be set prior to the decode operation, but ``pw_rpc`` internally decodes every 343*61c4878aSAndroid Build Coastguard Workermessage passed into a method implementation without any opportunity to set 344*61c4878aSAndroid Build Coastguard Workerthese. Alternatively, you may simply want finer control over how your messages 345*61c4878aSAndroid Build Coastguard Workerare encoded. 346*61c4878aSAndroid Build Coastguard Worker 347*61c4878aSAndroid Build Coastguard WorkerTo assist with these cases, ``pw_rpc`` allows any method within a Nanopb or 348*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` service to use its raw APIs without having to define the entire 349*61c4878aSAndroid Build Coastguard Workerservice as raw. Implementors may choose on a method-by-method basis where they 350*61c4878aSAndroid Build Coastguard Workerdesire to have access to the raw protobuf messages. 351*61c4878aSAndroid Build Coastguard Worker 352*61c4878aSAndroid Build Coastguard WorkerTo implement a method using the raw APIs, all you have to do is change the 353*61c4878aSAndroid Build Coastguard Workersignature of the function --- ``pw_rpc`` will automatically handle the rest. 354*61c4878aSAndroid Build Coastguard WorkerExamples are provided below, each showing a Nanopb method and its equivalent 355*61c4878aSAndroid Build Coastguard Workerraw signature. 356*61c4878aSAndroid Build Coastguard Worker 357*61c4878aSAndroid Build Coastguard WorkerUnary method 358*61c4878aSAndroid Build Coastguard Worker------------ 359*61c4878aSAndroid Build Coastguard WorkerWhen defining a unary method using the raw APIs, it is important to note that 360*61c4878aSAndroid Build Coastguard Workerthere is no synchronous raw unary API. The asynchronous unary method signature 361*61c4878aSAndroid Build Coastguard Workermust be used instead. 362*61c4878aSAndroid Build Coastguard Worker 363*61c4878aSAndroid Build Coastguard Worker**Nanopb** 364*61c4878aSAndroid Build Coastguard Worker 365*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 366*61c4878aSAndroid Build Coastguard Worker 367*61c4878aSAndroid Build Coastguard Worker // Synchronous unary method. 368*61c4878aSAndroid Build Coastguard Worker pw::Status DoFoo(const FooRequest& request, FooResponse response); 369*61c4878aSAndroid Build Coastguard Worker 370*61c4878aSAndroid Build Coastguard Worker // Asynchronous unary method. 371*61c4878aSAndroid Build Coastguard Worker void DoFoo(const FooRequest& request, 372*61c4878aSAndroid Build Coastguard Worker pw::rpc::NanopbUnaryResponder<FooResponse>& responder); 373*61c4878aSAndroid Build Coastguard Worker 374*61c4878aSAndroid Build Coastguard Worker**Raw** 375*61c4878aSAndroid Build Coastguard Worker 376*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 377*61c4878aSAndroid Build Coastguard Worker 378*61c4878aSAndroid Build Coastguard Worker // Only asynchronous unary methods are supported. 379*61c4878aSAndroid Build Coastguard Worker void DoFoo(pw::ConstByteSpan request, pw::rpc::RawUnaryResponder& responder); 380*61c4878aSAndroid Build Coastguard Worker 381*61c4878aSAndroid Build Coastguard WorkerServer streaming method 382*61c4878aSAndroid Build Coastguard Worker----------------------- 383*61c4878aSAndroid Build Coastguard Worker 384*61c4878aSAndroid Build Coastguard Worker**Nanopb** 385*61c4878aSAndroid Build Coastguard Worker 386*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 387*61c4878aSAndroid Build Coastguard Worker 388*61c4878aSAndroid Build Coastguard Worker void DoFoo(const FooRequest& request, 389*61c4878aSAndroid Build Coastguard Worker pw::rpc::NanopbServerWriter<FooResponse>& writer); 390*61c4878aSAndroid Build Coastguard Worker 391*61c4878aSAndroid Build Coastguard Worker**Raw** 392*61c4878aSAndroid Build Coastguard Worker 393*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 394*61c4878aSAndroid Build Coastguard Worker 395*61c4878aSAndroid Build Coastguard Worker void DoFoo(pw::ConstByteSpan request, pw::rpc::RawServerWriter& writer); 396*61c4878aSAndroid Build Coastguard Worker 397*61c4878aSAndroid Build Coastguard WorkerClient streaming method 398*61c4878aSAndroid Build Coastguard Worker----------------------- 399*61c4878aSAndroid Build Coastguard Worker 400*61c4878aSAndroid Build Coastguard Worker**Nanopb** 401*61c4878aSAndroid Build Coastguard Worker 402*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 403*61c4878aSAndroid Build Coastguard Worker 404*61c4878aSAndroid Build Coastguard Worker void DoFoo(pw::rpc::NanopbServerReader<FooRequest, FooResponse>&); 405*61c4878aSAndroid Build Coastguard Worker 406*61c4878aSAndroid Build Coastguard Worker**Raw** 407*61c4878aSAndroid Build Coastguard Worker 408*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 409*61c4878aSAndroid Build Coastguard Worker 410*61c4878aSAndroid Build Coastguard Worker void DoFoo(RawServerReader&); 411*61c4878aSAndroid Build Coastguard Worker 412*61c4878aSAndroid Build Coastguard WorkerBidirectional streaming method 413*61c4878aSAndroid Build Coastguard Worker------------------------------ 414*61c4878aSAndroid Build Coastguard Worker 415*61c4878aSAndroid Build Coastguard Worker**Nanopb** 416*61c4878aSAndroid Build Coastguard Worker 417*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 418*61c4878aSAndroid Build Coastguard Worker 419*61c4878aSAndroid Build Coastguard Worker void DoFoo(pw::rpc::NanopbServerReaderWriter<Request, Response>&); 420*61c4878aSAndroid Build Coastguard Worker 421*61c4878aSAndroid Build Coastguard Worker**Raw** 422*61c4878aSAndroid Build Coastguard Worker 423*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 424*61c4878aSAndroid Build Coastguard Worker 425*61c4878aSAndroid Build Coastguard Worker void DoFoo(RawServerReaderWriter&); 426*61c4878aSAndroid Build Coastguard Worker 427*61c4878aSAndroid Build Coastguard Worker---------------------------- 428*61c4878aSAndroid Build Coastguard WorkerTesting a pw_rpc integration 429*61c4878aSAndroid Build Coastguard Worker---------------------------- 430*61c4878aSAndroid Build Coastguard WorkerAfter setting up a ``pw_rpc`` server in your project, you can test that it is 431*61c4878aSAndroid Build Coastguard Workerworking as intended by registering the provided ``EchoService``, defined in 432*61c4878aSAndroid Build Coastguard Worker``echo.proto``, which echoes back a message that it receives. 433*61c4878aSAndroid Build Coastguard Worker 434*61c4878aSAndroid Build Coastguard Worker.. literalinclude:: echo.proto 435*61c4878aSAndroid Build Coastguard Worker :language: protobuf 436*61c4878aSAndroid Build Coastguard Worker :lines: 14- 437*61c4878aSAndroid Build Coastguard Worker 438*61c4878aSAndroid Build Coastguard WorkerFor example, in C++ with pw_protobuf: 439*61c4878aSAndroid Build Coastguard Worker 440*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 441*61c4878aSAndroid Build Coastguard Worker 442*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/server.h" 443*61c4878aSAndroid Build Coastguard Worker 444*61c4878aSAndroid Build Coastguard Worker // Include the apporpriate header for your protobuf library. 445*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/echo_service_pwpb.h" 446*61c4878aSAndroid Build Coastguard Worker 447*61c4878aSAndroid Build Coastguard Worker constexpr pw::rpc::Channel kChannels[] = { /* ... */ }; 448*61c4878aSAndroid Build Coastguard Worker static pw::rpc::Server server(kChannels); 449*61c4878aSAndroid Build Coastguard Worker 450*61c4878aSAndroid Build Coastguard Worker static pw::rpc::EchoService echo_service; 451*61c4878aSAndroid Build Coastguard Worker 452*61c4878aSAndroid Build Coastguard Worker void Init() { 453*61c4878aSAndroid Build Coastguard Worker server.RegisterService(echo_service); 454*61c4878aSAndroid Build Coastguard Worker } 455*61c4878aSAndroid Build Coastguard Worker 456*61c4878aSAndroid Build Coastguard WorkerSee :ref:`module-pw_rpc-cpp-testing` for more C++-specific testing 457*61c4878aSAndroid Build Coastguard Workerguidance. 458*61c4878aSAndroid Build Coastguard Worker 459*61c4878aSAndroid Build Coastguard Worker------------------------------- 460*61c4878aSAndroid Build Coastguard WorkerBenchmarking and stress testing 461*61c4878aSAndroid Build Coastguard Worker------------------------------- 462*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` provides an RPC service and Python module for stress testing and 463*61c4878aSAndroid Build Coastguard Workerbenchmarking a ``pw_rpc`` deployment. 464*61c4878aSAndroid Build Coastguard Worker 465*61c4878aSAndroid Build Coastguard Workerpw_rpc provides tools for stress testing and benchmarking a Pigweed RPC 466*61c4878aSAndroid Build Coastguard Workerdeployment and the transport it is running over. Two components are included: 467*61c4878aSAndroid Build Coastguard Worker 468*61c4878aSAndroid Build Coastguard Worker* The pw.rpc.Benchmark service and its implementation. 469*61c4878aSAndroid Build Coastguard Worker* A Python module that runs tests using the Benchmark service. 470*61c4878aSAndroid Build Coastguard Worker 471*61c4878aSAndroid Build Coastguard Workerpw.rpc.Benchmark service 472*61c4878aSAndroid Build Coastguard Worker======================== 473*61c4878aSAndroid Build Coastguard WorkerThe Benchmark service provides a low-level RPC service for sending data between 474*61c4878aSAndroid Build Coastguard Workerthe client and server. The service is defined in ``pw_rpc/benchmark.proto``. 475*61c4878aSAndroid Build Coastguard Worker 476*61c4878aSAndroid Build Coastguard WorkerA raw RPC implementation of the benchmark service is provided. This 477*61c4878aSAndroid Build Coastguard Workerimplementation is suitable for use in any system with pw_rpc. To access this 478*61c4878aSAndroid Build Coastguard Workerservice, add a dependency on ``"$dir_pw_rpc:benchmark"`` in GN or 479*61c4878aSAndroid Build Coastguard Worker``pw_rpc.benchmark`` in CMake. Then, include the service 480*61c4878aSAndroid Build Coastguard Worker(``#include "pw_rpc/benchmark.h"``), instantiate it, and register it with your 481*61c4878aSAndroid Build Coastguard WorkerRPC server, like any other RPC service. 482*61c4878aSAndroid Build Coastguard Worker 483*61c4878aSAndroid Build Coastguard WorkerThe Benchmark service was designed with the Python-based benchmarking tools in 484*61c4878aSAndroid Build Coastguard Workermind, but it may be used directly to test basic RPC functionality. The service 485*61c4878aSAndroid Build Coastguard Workeris well suited for use in automated integration tests or in an interactive 486*61c4878aSAndroid Build Coastguard Workerconsole. 487*61c4878aSAndroid Build Coastguard Worker 488*61c4878aSAndroid Build Coastguard WorkerBenchmark service 489*61c4878aSAndroid Build Coastguard Worker----------------- 490*61c4878aSAndroid Build Coastguard Worker.. literalinclude:: benchmark.proto 491*61c4878aSAndroid Build Coastguard Worker :language: protobuf 492*61c4878aSAndroid Build Coastguard Worker :lines: 14- 493*61c4878aSAndroid Build Coastguard Worker 494*61c4878aSAndroid Build Coastguard WorkerExample 495*61c4878aSAndroid Build Coastguard Worker------- 496*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 497*61c4878aSAndroid Build Coastguard Worker 498*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/benchmark.h" 499*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/server.h" 500*61c4878aSAndroid Build Coastguard Worker 501*61c4878aSAndroid Build Coastguard Worker constexpr pw::rpc::Channel kChannels[] = { /* ... */ }; 502*61c4878aSAndroid Build Coastguard Worker static pw::rpc::Server server(kChannels); 503*61c4878aSAndroid Build Coastguard Worker 504*61c4878aSAndroid Build Coastguard Worker static pw::rpc::BenchmarkService benchmark_service; 505*61c4878aSAndroid Build Coastguard Worker 506*61c4878aSAndroid Build Coastguard Worker void RegisterServices() { 507*61c4878aSAndroid Build Coastguard Worker server.RegisterService(benchmark_service); 508*61c4878aSAndroid Build Coastguard Worker } 509*61c4878aSAndroid Build Coastguard Worker 510*61c4878aSAndroid Build Coastguard WorkerStress testing 511*61c4878aSAndroid Build Coastguard Worker============== 512*61c4878aSAndroid Build Coastguard Worker.. attention:: 513*61c4878aSAndroid Build Coastguard Worker This section is experimental and liable to change. 514*61c4878aSAndroid Build Coastguard Worker 515*61c4878aSAndroid Build Coastguard WorkerThe Benchmark service is also used as part of a stress test of the ``pw_rpc`` 516*61c4878aSAndroid Build Coastguard Workermodule. This stress test is implemented as an unguided fuzzer that uses 517*61c4878aSAndroid Build Coastguard Workermultiple worker threads to perform generated sequences of actions using RPC 518*61c4878aSAndroid Build Coastguard Worker``Call`` objects. The test is included as an integration test, and can found and 519*61c4878aSAndroid Build Coastguard Workerbe run locally using GN: 520*61c4878aSAndroid Build Coastguard Worker 521*61c4878aSAndroid Build Coastguard Worker.. code-block:: bash 522*61c4878aSAndroid Build Coastguard Worker 523*61c4878aSAndroid Build Coastguard Worker $ gn desc out //:integration_tests deps | grep fuzz 524*61c4878aSAndroid Build Coastguard Worker //pw_rpc/fuzz:cpp_client_server_fuzz_test(//targets/host/pigweed_internal:pw_strict_host_clang_debug) 525*61c4878aSAndroid Build Coastguard Worker 526*61c4878aSAndroid Build Coastguard Worker $ gn outputs out '//pw_rpc/fuzz:cpp_client_server_fuzz_test(//targets/host/pigweed_internal:pw_strict_host_clang_debug)' 527*61c4878aSAndroid Build Coastguard Worker pw_strict_host_clang_debug/gen/pw_rpc/fuzz/cpp_client_server_fuzz_test.pw_pystamp 528*61c4878aSAndroid Build Coastguard Worker 529*61c4878aSAndroid Build Coastguard Worker $ ninja -C out pw_strict_host_clang_debug/gen/pw_rpc/fuzz/cpp_client_server_fuzz_test.pw_pystamp 530