Skip to content

Commit 0ec6ea9

Browse files
committed
feat: decoder_manager creates one singleton decoder per transport. feat: RpcDecoder handles clients, manages msg_id over transport. send_response TBT
1 parent 67410de commit 0ec6ea9

File tree

7 files changed

+179
-90
lines changed

7 files changed

+179
-90
lines changed

examples/rpc_lite_client/rpc_lite_client.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include <Arduino_RPClite.h>
22

3-
SerialTransport transport(&Serial2);
3+
SerialTransport transport(&Serial0);
44
RPCClient client(transport);
55

66
void setup() {
7-
Serial2.begin(115200);
7+
Serial0.begin(115200);
88
transport.begin();
99
pinMode(LED_BUILTIN, OUTPUT);
1010
Serial.begin(9600);

src/Arduino_RPClite.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
#include "Arduino.h"
99

1010
//#define HANDLE_RPC_ERRORS
11-
//#define DEBUG
12-
#include "rpc.h"
11+
#define DEBUG
1312
#include "transport.h"
1413
#include "client.h"
1514
#include "server.h"
1615
#include "wrapper.h"
1716
#include "dispatcher.h"
1817
#include "decoder.h"
18+
#include "decoder_manager.h"
1919

2020
#include "DummyTransport.h"
2121
#include "SerialTransport.h"

src/client.h

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,106 +4,44 @@
44

55
#ifndef RPCLITE_CLIENT_H
66
#define RPCLITE_CLIENT_H
7-
#include "rpc.h"
87
#include "error.h"
8+
#include "decoder_manager.h"
99

1010
class RPCClient {
1111
ITransport& transport;
12-
int msg_id = 1;
12+
RpcDecoder<>& decoder;
1313

1414
public:
15-
RPCClient(ITransport& t) : transport(t) {}
15+
RPCClient(ITransport& t) : transport(t), decoder(RpcDecoderManager<>::getDecoder(t)) {}
1616

1717
template<typename... Args>
1818
void notify(const MsgPack::str_t method, Args&&... args) {
19-
MsgPack::Packer packer;
20-
21-
int msg_type = NOTIFY_MSG;
22-
23-
MsgPack::arr_size_t notify_size(3);
24-
25-
packer.serialize(notify_size, msg_type, method);
26-
27-
MsgPack::arr_size_t arg_size(sizeof...(args));
28-
29-
packer.serialize(arg_size, std::forward<Args>(args)...);
30-
31-
send_msg(transport, packer.packet());
19+
int _id;
20+
decoder.send_call(NOTIFY_MSG, method, _id, std::forward<Args>(args)...);
3221
}
3322

3423
template<typename RType, typename... Args>
3524
bool call(const MsgPack::str_t method, RType& result, Args&&... args) {
3625

37-
MsgPack::Packer packer;
38-
39-
int msg_type = CALL_MSG;
40-
41-
MsgPack::arr_size_t call_size(4);
42-
43-
packer.serialize(call_size, msg_type, msg_id, method);
44-
45-
MsgPack::arr_size_t arg_size(sizeof...(args));
46-
47-
packer.serialize(arg_size, std::forward<Args>(args)...);
48-
49-
send_msg(transport, packer.packet());
50-
51-
MsgPack::Unpacker unpacker;
26+
int msg_id;
27+
if (!decoder.send_call(CALL_MSG, method, msg_id, std::forward<Args>(args)...)){
28+
}
5229

30+
RpcError error;
5331
// blocking call
54-
55-
while (true){
56-
if (!recv_msg(transport, unpacker)){
57-
// If not receiving new bytes yield first then attempt a new deserialization
58-
delay(1);
59-
}
60-
61-
if (is_empty_buffer()){
62-
//Serial.println("Empty buffer... waiting response");
63-
continue;
64-
}
65-
66-
int r_msg_type;
67-
int r_msg_id;
68-
MsgPack::object::nil_t nil;
69-
RpcError rpc_error;
70-
71-
MsgPack::arr_size_t resp_size;
72-
73-
if (!unpacker.deserialize(resp_size, r_msg_type, r_msg_id)){
74-
Serial.println("incomplete or malformed response");
75-
continue;
76-
};
77-
78-
if ((resp_size.size() != 4) || (r_msg_type != 1) || (r_msg_id != msg_id)){
79-
Serial.println("wrong msg received");
80-
continue;
81-
}
82-
83-
if (!unpacker.unpackable(nil)){
84-
Serial.print("RPC error - ");
85-
if (!unpacker.deserialize(rpc_error, nil)){
86-
Serial.println("wrong error msg received");
87-
continue;
88-
}
89-
Serial.print(" error code: ");
90-
Serial.print(rpc_error.code);
91-
Serial.print(" error str: ");
92-
Serial.println(rpc_error.traceback);
93-
msg_id += 1;
94-
flush_buffer();
95-
return false;
96-
} else if (!unpacker.deserialize(nil, result)){
97-
Serial.println("Unexpected result");
98-
continue;
99-
}
100-
break;
32+
while (!decoder.get_response(msg_id, result, error)){
33+
decoder.process();
34+
delay(1);
10135
}
10236

103-
msg_id += 1;
37+
#ifdef DEBUG
38+
if (error.code != NO_ERR){
39+
Serial.print("Server-side error message: ");
40+
Serial.println(error.traceback);
41+
}
42+
#endif
10443

105-
flush_buffer();
106-
return true;
44+
return (error.code == NO_ERR);
10745

10846
}
10947
};

src/decoder.h

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#define RESP_MSG 1
1010
#define NOTIFY_MSG 2
1111

12+
#define REQUEST_SIZE 4
13+
#define RESPONSE_SIZE 4
14+
#define NOTIFY_SIZE 3
15+
1216
#define MAX_BUFFER_SIZE 1024
1317
#define CHUNK_SIZE 32
1418

@@ -18,6 +22,96 @@ class RpcDecoder {
1822
public:
1923
RpcDecoder(ITransport& transport) : _transport(transport) {}
2024

25+
template<typename... Args>
26+
bool send_call(const int call_type, const MsgPack::str_t method, int& msg_id, Args&&... args) {
27+
28+
if (call_type!=CALL_MSG && call_type!=NOTIFY_MSG) return false;
29+
30+
static MsgPack::Packer packer;
31+
packer.clear();
32+
33+
if (call_type == CALL_MSG){
34+
msg_id = _msg_id;
35+
MsgPack::arr_size_t call_size(REQUEST_SIZE);
36+
packer.serialize(call_size, call_type, msg_id, method);
37+
} else {
38+
MsgPack::arr_size_t call_size(NOTIFY_SIZE);
39+
packer.serialize(call_size, call_type, method);
40+
}
41+
42+
MsgPack::arr_size_t arg_size(sizeof...(args));
43+
packer.serialize(arg_size, std::forward<Args>(args)...);
44+
45+
#ifdef DEBUG
46+
Serial.print("Sending: ");
47+
for (size_t i=0; i<packer.size(); i++){
48+
Serial.print(packer.data()[i], HEX);
49+
Serial.print(" ");
50+
}
51+
Serial.println(" ");
52+
#endif
53+
54+
if (send(reinterpret_cast<const uint8_t*>(packer.data()), packer.size()) == packer.size()){
55+
_msg_id++;
56+
return true;
57+
}
58+
return false;
59+
}
60+
61+
template<typename RType>
62+
bool get_response(const int msg_id, RType& result, RpcError& error) {
63+
64+
if (!packet_incoming() || packet_type()!=RESP_MSG) return false;
65+
66+
static MsgPack::Unpacker unpacker;
67+
68+
size_t bytes_checked = 0;
69+
70+
while (bytes_checked < _bytes_stored) {
71+
bytes_checked++;
72+
unpacker.clear();
73+
if (!unpacker.feed(_raw_buffer, bytes_checked)) continue;
74+
MsgPack::arr_size_t resp_size;
75+
int resp_type;
76+
int resp_id;
77+
if (!unpacker.deserialize(resp_size, resp_type, resp_id)) continue;
78+
if (resp_size.size() != RESPONSE_SIZE) continue;
79+
if (resp_type != RESP_MSG) continue;
80+
if (resp_id != msg_id) continue;
81+
82+
MsgPack::object::nil_t nil;
83+
if (unpacker.unpackable(nil)){ // No error
84+
if (!unpacker.deserialize(nil, result)) continue;
85+
} else { // RPC returned an error
86+
if (!unpacker.deserialize(error, nil)) continue;
87+
}
88+
pop_packet(bytes_checked);
89+
return true;
90+
}
91+
#ifdef DEBUG
92+
print_buffer();
93+
#endif
94+
return false;
95+
}
96+
97+
template<typename RType>
98+
bool send_response(const int msg_id, const RpcError& error, const RType& result) {
99+
static MsgPack::Packer packer;
100+
MsgPack::arr_size_t resp_size(RESPONSE_SIZE);
101+
MsgPack::object::nil_t nil;
102+
103+
packer.clear();
104+
packer.serialize(resp_size, RESP_MSG, msg_id);
105+
106+
if (error.code == NO_ERR){
107+
packer.serialize(nil, result);
108+
} else {
109+
packer.serialize(error, nil);
110+
}
111+
112+
return send(reinterpret_cast<const uint8_t*>(packer.data()), packer.size()) == packer.size();
113+
114+
}
21115

22116
void process(){
23117
if (advance()) parse_packet();
@@ -119,8 +213,8 @@ void print_buffer(){
119213
ITransport& _transport;
120214
uint8_t _raw_buffer[BufferSize];
121215
size_t _bytes_stored = 0;
122-
123216
int _packet_type = NO_MSG;
217+
int _msg_id = 0;
124218

125219
inline bool buffer_full() const { return _bytes_stored == BufferSize; }
126220
inline bool buffer_empty() const { return _bytes_stored == 0;}
@@ -129,6 +223,9 @@ void print_buffer(){
129223
while (_transport.read(discard_buf, CHUNK_SIZE) > 0);
130224
_bytes_stored = 0;
131225
}
226+
inline size_t send(const uint8_t* data, const size_t size) {
227+
return _transport.write(data, size);
228+
}
132229
};
133230

134231
#endif

src/decoder_manager.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// This is a static implementation of the decoder manager
2+
3+
#ifndef RPCLITE_DECODER_MANAGER_H
4+
#define RPCLITE_DECODER_MANAGER_H
5+
6+
#define RPCLITE_MAX_TRANSPORTS 3
7+
8+
#include <array>
9+
#include "transport.h"
10+
#include "decoder.h"
11+
12+
template<size_t MaxTransports = RPCLITE_MAX_TRANSPORTS>
13+
class RpcDecoderManager {
14+
public:
15+
static RpcDecoder<>& getDecoder(ITransport& transport) {
16+
for (auto& entry : decoders_) {
17+
if (entry.transport == &transport) {
18+
return *entry.decoder;
19+
}
20+
21+
if (entry.transport == nullptr) {
22+
entry.transport = &transport;
23+
// In-place construct
24+
entry.decoder = new (&entry.decoder_storage.instance) RpcDecoder<>(transport);
25+
return *entry.decoder;
26+
}
27+
}
28+
29+
// No slot available — simple trap for now
30+
while (true);
31+
}
32+
33+
private:
34+
struct DecoderStorage {
35+
union {
36+
RpcDecoder<> instance;
37+
uint8_t raw[sizeof(RpcDecoder<>)];
38+
};
39+
40+
DecoderStorage() {}
41+
~DecoderStorage() {}
42+
};
43+
44+
struct Entry {
45+
ITransport* transport = nullptr;
46+
RpcDecoder<>* decoder = nullptr;
47+
DecoderStorage decoder_storage;
48+
};
49+
50+
static std::array<Entry, MaxTransports> decoders_;
51+
};
52+
53+
// Definition of the static member
54+
template<size_t MaxTransports>
55+
std::array<typename RpcDecoderManager<MaxTransports>::Entry, MaxTransports> RpcDecoderManager<MaxTransports>::decoders_;
56+
57+
#endif RPCLITE_DECODER_MANAGER_H

src/error.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
#include "MsgPack.h"
88

9-
#include "MsgPack.h"
10-
11-
129
#define NO_ERR 0x00
1310
#define MALFORMED_CALL_ERR 0xFD
1411
#define FUNCTION_NOT_FOUND_ERR 0xFE

src/transport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class ITransport {
1111
// Transport abstraction interface
1212

1313
public:
14-
virtual size_t write(const uint8_t* data, size_t size) = 0;
14+
virtual size_t write(const uint8_t* data, const size_t size) = 0;
1515
virtual size_t read(uint8_t* buffer, size_t size) = 0;
1616
virtual size_t read_byte(uint8_t& r) = 0;
1717
virtual bool available() = 0;

0 commit comments

Comments
 (0)