bmRPC is a remote procedure call framework suitable for operating system-less embedded devices. This rpc framework allows to invoke and execute functions located on one device from a connected and trusted other device. It can solve the “Last mile” problem for the implementation of the Industrial Internet of Things IIoT - Industry 4.0 by simplifying the connection of non-IIoT-enabled devices. The installation of this framework allows the data access and device control from Internet in the least intrusive way:
- no other external application or libraries.
- no development of custom protocols.
- no heavy source code modification and regression testing.
Copyright 2022 Claudio Lanfranchi.
bmRPC is licensed under Apache License Version 2.0. See LICENSE for more information.
- Transport layer independent. It is required only the provision of a driver implementing the Data Link layer (e.g. I2C/SPI/UART driver). The data streaming is implemented with optimized circular buffers. CAN/USB/BT/TCPIP can also be adopted.
- bmRPC does not require Interface Description Language (IDL) and other applications for code generation. Function prototypes are used to exchange information between Client and Server. The RPC identification is automatically created from the function prototype.
- Unlimited number of parameters.
- Several parameter types (fundamental types, std::strings, std::vectors). Other types support can be easily added.
- Parameters passed by reference.
- Arguments number and type control at compilation time.
- Function overloading support. The text format of the complete function prototype is used as RPC identification.
- Multiple client invokation instances of the same RPC.
- Text protocol and binary protocol with endianness handling.
- Reduced code footprint by limiting the use of template meta programming for arguments marshalling and serialization.
- Minimum overhead for RPC call. Use of static polymorphism instead of dynamic polymorphism.
- Support for version C++17 or higher.
- STL library.
- Data Link driver: I2C/SPI/UART...
- std::chrono or other high resolution timer.
- Any C++ IDEs.
Take the following steps:
- Includes bmRPC files in you projects for compilation.
- Implement the Data Link driver using provided Comm class interface located in the bmRPCDataLink.h file.
- Configure user settings located in the bmRPC.h file and reported in the table below:
BMRPC_SERVER: | Enable server compilation |
BMRPC_CLIENT: | Enable client compilation |
BINARY_BASED_PROTOCOL: | Select binary or text protocol |
P64: | Select the P64 fundamental types support |
SRV_NATIVE: | Set server endianess |
CLN_NATIVE: | Set client endianess |
Take the following steps:
Server side. Register the function to be called from the client:
Skeleton<Data>* func_skeleton = server.CONNECT(func_name);
where func_name is the function prototype name.
Client side. Register the function to be executed in the server:
RpcHandle<Stub<Data>> func_handle = client.CONNECT(func_pointer_name);
where func_pointer_name is the pointer name to the function type equivalent to the one registered by the server.
Client side. Invoke the function execution:
Client.ASYNC_RPC_WITH_CB(func_pointer_name, func_handle, callback lambda, arguments…);
Refer to the file main.cpp for details.
The framework setup requires the following:
Server side.
- Create the Data Link driver:
auto server_com = ServerCom<DataItem>();
- Create the RPC Server:
RpcServer server = CREATE_SERVER(ServerCom<DataItem>, server_com);
- Open the Data Link com driver:
server_com.open();
- Init RPC Server loop:
server.init_loop();
- Invoke
server.doLoop();
in the main working thread. - Disconnect registered functions before shutdown:
server.disconnect(func_skeleton);
Client side. 7. Create the Data Link driver:
auto client_com = ClientCom<DataItem>();
- Create the RPC Client:
RpcClient client = CREATE_CLIENT(ClientCom<DataItem>, client_com);
- Open the Data Link com driver:
client_com.open();
- Init RPC Client loop:
client.init_loop();
- Invoke
client.doLoop();
in the main working thread. - Disconnect registered functions before shutdown:
client.disconnect(func_handle);
- Improve optimization.
- Implement bidirectional rpc invokation: allow the server to call functions registered by the client.
- Implement multithreading support.
- Framework porting to Heap-less memory solution.
- Implement function prototypes discovery.
- Make bmRPC reusable as Inter-Process Communication (IPC).
- Cognitive RPC.
Contributions are welcome! Contribution guide document is pendiing.