From 3a49bad5c427aab6d1ad3dc2b9dfa22d301b3280 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Mon, 9 Jun 2025 18:10:09 +0200 Subject: [PATCH] mod: client and server can be instantiated passing phys transport. doc: impr documentation and examples --- README.md | 78 ++++++++++++++++++++ examples/rpc_lite_client/rpc_lite_client.ino | 7 +- examples/rpc_lite_server/rpc_lite_server.ino | 14 ++-- src/SerialTransport.h | 2 + src/client.h | 20 +++-- src/server.h | 15 ++-- 6 files changed, 115 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c2446c6..f70ea97 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,84 @@ A MessagePack RPC library for Arduino allows to create a client/server architecture using MessagePack as the serialization format. It follows the [MessagePack-RPC protocol specification](https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md). It is designed to be lightweight and easy to use, making it suitable for embedded systems and IoT applications. + +## Server + +```cpp +#include + +RPCServer server(Serial1); + +int add(int a, int b){ + return a+b; +} + +String loopback(String message){ + return message; +} + +void setup() { + Serial1.begin(115200); + while(!Serial1); + + Serial.begin(9600); + while(!Serial); + + server.bind("add", add); + server.bind("loopback", loopback); + +} + +void loop() { + server.run(); +} + +``` + + +## Client + +```cpp +#include + +RPCClient client(Serial1); + +void setup() { + Serial1.begin(115200); + while(!Serial1); + + pinMode(LED_BUILTIN, OUTPUT); + + Serial.begin(9600); + while(!Serial); +} + +void loop() { + + bool ok; + + String response; + ok = client.call("loopback", response, "Sending a greeting"); + if (ok) Serial.println(str_res); + + int sum_result; + ok = client.call("add", sum_result, 2. 3); + if (ok) Serial.println(sum_result); // must print 5 + + // ERROR handling + float result; + bool ok = client.call("unbound_method", result, 10.0); + if (!ok) { + Serial.print("Testing Server-side exception OK. ERR code: "); + Serial.print(client.lastError.code); + Serial.print(" ERR trace: "); + Serial.println(client.lastError.traceback); + } + +} + +``` + ### Credits This library is based on the MsgPack library by @hideakitai. diff --git a/examples/rpc_lite_client/rpc_lite_client.ino b/examples/rpc_lite_client/rpc_lite_client.ino index aaeb392..f0f0a15 100644 --- a/examples/rpc_lite_client/rpc_lite_client.ino +++ b/examples/rpc_lite_client/rpc_lite_client.ino @@ -1,12 +1,13 @@ #include -SerialTransport transport(&Serial1); -RPCClient client(transport); +RPCClient client(Serial1); void setup() { Serial1.begin(115200); - transport.begin(); + while(!Serial1); + pinMode(LED_BUILTIN, OUTPUT); + Serial.begin(9600); while(!Serial); } diff --git a/examples/rpc_lite_server/rpc_lite_server.ino b/examples/rpc_lite_server/rpc_lite_server.ino index 3bd2f79..ccf4497 100644 --- a/examples/rpc_lite_server/rpc_lite_server.ino +++ b/examples/rpc_lite_server/rpc_lite_server.ino @@ -1,17 +1,16 @@ #include -SerialTransport transport(&Serial1); -RPCServer server(transport); +RPCServer server(Serial1); int add(int a, int b){ return a+b; } -MsgPack::str_t greet(){ - return MsgPack::str_t ("Hello Friend"); +String greet(){ + return String("Hello Friend"); } -MsgPack::str_t loopback(MsgPack::str_t message){ +String loopback(String message){ return message; } @@ -27,13 +26,16 @@ public: void setup() { Serial1.begin(115200); - transport.begin(); + while(!Serial1); + pinMode(LED_BUILTIN, OUTPUT); + Serial.begin(9600); while(!Serial); server.bind("add", add); server.bind("greet", greet); + server.bind("loopback", loopback); server.bind("another_greeting", [] {return MsgPack::str_t ("This is a lambda greeting");}); server.bind("object_multi", &multiplier::mult); diff --git a/src/SerialTransport.h b/src/SerialTransport.h index 53c07d3..1dcb649 100644 --- a/src/SerialTransport.h +++ b/src/SerialTransport.h @@ -14,6 +14,8 @@ class SerialTransport: public ITransport { SerialTransport(Stream* stream): _stream(stream){} + SerialTransport(Stream& stream): _stream(&stream){} + void begin(){} bool available() override { diff --git a/src/client.h b/src/client.h index 5041edb..0ac7fec 100644 --- a/src/client.h +++ b/src/client.h @@ -6,33 +6,39 @@ #define RPCLITE_CLIENT_H #include "error.h" #include "decoder_manager.h" +#include "SerialTransport.h" + class RPCClient { - ITransport& transport; - RpcDecoder<>& decoder; + RpcDecoder<>* decoder = nullptr; public: RpcError lastError; - RPCClient(ITransport& t) : transport(t), decoder(RpcDecoderManager<>::getDecoder(t)) {} + RPCClient(ITransport& t) : decoder(&RpcDecoderManager<>::getDecoder(t)) {} + + RPCClient(Stream& stream) { + ITransport* transport = (ITransport*) new SerialTransport(stream); + decoder = &RpcDecoderManager<>::getDecoder(*transport); + } template void notify(const MsgPack::str_t method, Args&&... args) { int _id; - decoder.send_call(NOTIFY_MSG, method, _id, std::forward(args)...); + decoder->send_call(NOTIFY_MSG, method, _id, std::forward(args)...); } template bool call(const MsgPack::str_t method, RType& result, Args&&... args) { int msg_id; - if (!decoder.send_call(CALL_MSG, method, msg_id, std::forward(args)...)){ + if (!decoder->send_call(CALL_MSG, method, msg_id, std::forward(args)...)){ } RpcError error; // blocking call - while (!decoder.get_response(msg_id, result, error)){ - decoder.process(); + while (!decoder->get_response(msg_id, result, error)){ + decoder->process(); delay(1); } diff --git a/src/server.h b/src/server.h index 0021c16..e7154ee 100644 --- a/src/server.h +++ b/src/server.h @@ -10,16 +10,21 @@ #include "dispatcher.h" #include "decoder.h" #include "decoder_manager.h" +#include "SerialTransport.h" #define MAX_CALLBACKS 100 class RPCServer { - ITransport& transport; - RpcDecoder<>& decoder; + RpcDecoder<>* decoder = nullptr; RpcFunctionDispatcher dispatcher; public: - RPCServer(ITransport& t) : transport(t), decoder(RpcDecoderManager<>::getDecoder(t)) {} + RPCServer(ITransport& t) : decoder(&RpcDecoderManager<>::getDecoder(t)) {} + + RPCServer(Stream& stream) { + ITransport* transport = (ITransport*) new SerialTransport(stream); + decoder = &RpcDecoderManager<>::getDecoder(*transport); + } template bool bind(const MsgPack::str_t& name, F&& func){ @@ -27,8 +32,8 @@ class RPCServer { } void run() { - decoder.process(); - decoder.process_requests(dispatcher); + decoder->process(); + decoder->process_requests(dispatcher); delay(1); }