The API library provides several interfaces, discussed below. All interfaces share the methods described in Section Methods.

Generic interface

The Interface class can be used when the type of device is not known beforehand, A class instance is made by passing either the path to a device or a URI to the constructor.

>>> from simple_rpc import Interface
>>> interface = Interface('/dev/ttyACM0')

The constructor takes the following parameters.

Constructor parameters.






Device name.



Baud rate.



Time in seconds before communication starts.



Automatically connect.



Load interface definition from file.

Please see the list of handlers for a full description of the supported interface types.

Serial interface

When a path to a serial device is given, the Interface constructor returns a SerialInterface class instance.

>>> from simple_rpc import Interface
>>> interface = Interface('/dev/ttyACM0')
>>> interface.__class__
<class 'simple_rpc.simple_rpc.SerialInterface'>

Alternatively, the SerialInterface class can be used directly.

>>> from simple_rpc import SerialInterface
>>> interface = SerialInterface('/dev/ttyACM0')

Socket interface

When a socket URI is given, the Interface constructor returns a SocketInterface class instance.

>>> interface = Interface('socket://')
>>> interface.__class__
<class 'simple_rpc.simple_rpc.SocketInterface'>

Alternatively, the SocketInterface class can be used directly.

>>> from simple_rpc import SocketInterface
>>> interface = SocketInterface('socket://')


The Interface class provides the following methods.

Class methods.




Connect to device.


Disconnect from device.


Query device state.


Execute a method.


Save the interface definition to a file.

The open() function is used to connect to a device, this is needed when autoconnect=False is passed to the constructor.

>>> interface = Interface('/dev/ttyACM0', autoconnect=False)
>>> # Do something.

The open() function accepts the optional parameter handle, which can be used to load an interface definition from a file. This can be useful when working with low throughput networks.


The connection state can be queried using the is_open() function and it can be closed using the close() function.

>>> if interface.is_open():
>>>     interface.close()

Additionally, the with statement is supported for easy opening and closing.

>>> with Interface('/dev/ttyACM0') as interface:

The class instance has a public member variable named device which contains the device definitions and its exported method definitions.

>>> list(interface.device['methods'])
['inc', 'set_led']

Example of a method definition.

>>> interface.device['methods']['inc']
  'doc': 'Increment a value.',
  'index': 2,
  'name': 'inc',
  'parameters': [
      'doc': 'Value.',
      'name': 'a',
      'fmt': 'h',
      'typename': 'int'
  'return': {
    'doc': 'a + 1.',
    'fmt': 'h',
    'typename': 'int'}

Every exported method will show up as a class method of the interface class instance. These methods can be used like any normal class methods. Alternatively, the exported methods can be called by name using the call_method() function.

The save() function is used to save the interface definition to a file. This can later be used by the constructor or the open() function to initialise the interface without having to query the device.

>>>'interface.yml', 'w'))

Basic usage

In the example given in the device library documentation, the inc method is exported, which is now present as a class method of the class instance.


Alternatively, the exported method can be called using the call_mathod() function.

>>> interface.call_method('inc', 1)

To get more information about this class method, the built-in help() function can be used.

>>> help(
Help on method inc:

inc(a) method of simple_rpc.simple_rpc.SerialInterface instance
    Increment a value.

    :arg int a: Value.

    :returns int: a + 1.

Note that strings should be encoded as bytes objects. If, for example, we have a function named test that takes a string as parameter, we should call this function as follows.

>>> interface.test(b'hello world')

Complex objects

Some methods may have complex objects like Tuples, Objects or Vectors as parameters or return type.

In the following example, we call a method that takes a Vector of integers and returns a Vector of floats.

>>> interface.vector([1, 2, 3, 4])
[1.40, 2.40, 3.40, 4.40]

In this example, we call a method that takes an Object containing a byte and an other Object. A similar Object is returned.

>>> interface.object((b'a', (10, b'b')))
(b'b', (11, b'c'))


In this implementation, the Tuple type is regarded as a flat sequence of elements, not as a separate type. The Object type is used to assign this sequence of elements to a Python tuple and the Vector type is used to assign this sequence of elements to a Python list. Bare tuples are not supported in this implementation.

Using Tuples may lead to some other counter intuitive results. For example, a Vector of length l containing Tuples of size n is received as a list containing l·n elements.