xref: /aosp_15_r20/external/pigweed/pw_rpc/guides.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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