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 initialize 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() {
  Serial.begin(9600);
}

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() {
  interface(
    Serial,
    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() {
  interface(
    Serial,
    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 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 a Tuple containing an integer, a Vector and an other Tuple respectively.

Vector<Vector<int> > matrix;

Vector<Tuple<int, char> > v;

Tuple<int, Vector<int>, Tuple<char, long> > t;

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

C arrays

Passing a C array as a parameter is supported, but since in general it is not possible to deduce the size or internal structure of an object it is not possible to return a C array. The closely related Vector should be used in this case.

In the following example, an integer C array is passed to a function.

void readArray(int* a) {}

Multidimensional arrays are implemented as NULL terminated arrays of pointers. This allows for structures that do not have a fixed length in any dimension, e.g., a two-dimensional array int** does not have to be rectangular.