Usage

Include the header file to use the simpleRPC library.

#include <simpleRPC.h>

The library provides the interface() function, which is responsible for all communication with the host. To use this function, first define which interface to use by instantiating one of the plugins, HardwareSerialIO for example.

HardwareSerialIO io;

This particular plugin needs to be initialised with the standard Serial class instance to enable communication using the hardware serial interface. This is done using the begin() method in the setup() body.

void setup(void) {
  Serial.begin(9600);
  io.begin(Serial);
}

Please see the Plugins section for using other I/O interfaces.

Exporting C functions

Standard C functions are exported as RPC methods by calling the interface() function from the loop() body. This function accepts (function, documentation) pairs as parameters.

Interface function parameters.
parameter description
0 I/O class instance.
1 Function one.
2 Documentation string of function one.
3 Function two.
4 Documentation string of function two.

A documentation string consists of a list of key-value pairs in the form key: value delimited by the @ character. The first pair in this list is reserved for the RPC method name and its description, all subsequent pairs are used to name and describe parameters or to describe a return value.

Documentation string.
field prefix key value
  RPC method name. RPC method description.
@ Parameter name. Parameter description.
@ return Return value description.

The documentation string may be incomplete or empty. The following defaults are used for missing keys. All descriptions may be empty.

Default names.
key default
RPC method name. method followed by a number, e.g., method0.
Parameter name. arg followed by a number, e.g., arg0.
return return

To reduce the memory footprint, the F() macro can be used in the interface() function. This stores the documentation string in program memory instead of SRAM. For more information, see the progmem documentation.

Example

Suppose we want to export a function that sets the brightness of an LED and a function that takes one parameter and returns a value.

void setLed(byte brightness) {
  analogWrite(LED_BUILTIN, brightness);
}

int inc(int a) {
  return a + 1;
}

Exporting these functions goes as follows:

void loop(void) {
  interface(
    io,
    inc, "inc: Increment a value. @a: Value. @return: a + 1.",
    setLed, "set_led: Set LED brightness. @brightness: Brightness.");
}

We can now build and upload the sketch.

The client reference documentation includes an example on how these methods can be accessed from the host.

Exporting class methods

Class methods are different from ordinary functions in the sense that they always operate on an object. This is why both a function pointer and a class instance need to be provided to the interface() function. To facilitate this, the pack() function can be used to combine a class instance and a function pointer before passing them to interface().

For a class instance c of class C, the class method f() can be packed as follows:

pack(&c, &C::f)

The result can be passed to interface().

Example

Suppose we have a library named led which provides the class LED. This class has a method named setBrightness.

#include "led.h"

LED led(LED_BUILTIN);

Exporting this class method goes as follows:

void loop(void) {
  interface(
    io,
    pack(&led, &LED::setBrightness),
      "set_led: Set LED brightness. @brightness: Brightness.");
}

Complex objects

In some cases, basic C types and C strings are not sufficient or convenient. This is why simpleRPC supports higher order objects described in detail in the Tuples and Objects and Vectors sections.

Arbitrary combinations of these higher order objects can be made to construct complex objects.

In the following example, we create a 2-dimensional matrix of integers, a Vector of Tuples and an Object containing an integer, a Vector and an other Object respectively.

Vector<Vector<int> > matrix;

Vector<Tuple<int, char> > v;

Object<int, Vector<int>, Object<char, long> > o;

These objects can be used for parameters as well as for return values. Note that these objects, like any higher order data structure should be passed by reference.