Go Down

Topic: Simple RPC implementation. (Read 452 times) previous topic - next topic

jfjlaros


ron_sutherland

I like it, thanks for showing this.

When I have time I'm going to see how happy it is on my multi-drop serial. Also, it seems like a candidate to extend with a web-enabled gateway interface (WSGI).
I use an R-Pi Zero on an RPUpi shield to have a tool-chain at the network edge.

jfjlaros

Since editing a library header to add a method, its return type and its parameter types is a bit awkward, we made a new implementation of the device library. In this version all type inference is done automatically, the user only needs to provide a function pointer and a documentation string (the latter will become optional in a later version).

An example of how to use the new interface can be found here.

jfjlaros

In the latest release:

- Support for strings.
- New documentation string format, added parameter names.
- The documentation string can now be empty or can have missing fields.

We also added an example for the device and a demo for using the Python library.

jfjlaros

Also, it seems like a candidate to extend with a web-enabled gateway interface (WSGI).
@ron_sutherland: I gave this remark some thought, it should be relatively straightforward.

The host library already exposes a structured representation of the exported methods. E.g., if we export digitalRead() as an RPC method, the host library exposes it as follows.

Code: [Select]

{
  "name": "read_digital",
  "return": {
    "fmt": "<h",
    "typename": "int",
    "doc": "Pin value."
  },
  "parameters": [
    {
      "name": "pin",
      "fmt": "B",
      "typename": "int",
      "doc": "Pin number."
    }
  ],
  "index": 2,
  "doc": "Read a pin value."
}


This information can be used to build an interface, like the command line interface in our example.

We could perhaps convert this representation into a Swagger specification which can be used to generate a web API. Is this in line with your ideas?

ron_sutherland

I do like the idea of a simple RPC over serial implementation but I got too many things going on right now to dig into this.

I am fearful of what might be happening in the heap memory space of the AVR. It is so easy to fragment and then end up with odd behavior, I have learned to look into that early.

For WSGI I was thinking about doing something like this idea that I was tinkering with.

https://github.com/epccs/RPUpi/tree/master/WSGIdaemon

the URL would hold the RPC parts, sort of like this.

Code: [Select]
http://192.168.0.7:8000/?name=read_digital&return=int...

The WSGI service aggregates the serial command from the URL parts. The AVR sees a normal serial command, just like it would from the RPC host. The pain is crafting the URL for the RPC, it is not obvious at first glance. Actually, it is not obvious what ends up on the serial link for that digitalRead command?
I use an R-Pi Zero on an RPUpi shield to have a tool-chain at the network edge.

jfjlaros

I am fearful of what might be happening in the heap memory space of the AVR.
All type introspection is done at compile time by using template metaprogramming. No memory allocation or global variables are used, so I do not think heap fragmentation is possible in this setup.

Actually, it is not obvious what ends up on the serial link for that digitalRead command?
The C types are encoded in the fmt fields, this is only relevant for the library, but it is exposed nonetheless. The Python equivalents of the types can be found in the typename fields.

Each RPC method has a number associated to it, which is stored in the index field.

In this particular case, one byte containing the value 0x02 is sent, selecting the digitalRead() function. The value for its parameter pin is sent as an unsigned char (B). The function returns a little endian short int (<h) which is read from the serial device. So for this call two bytes are sent and two bytes are received. All conversions between C- and Python types are done by the host library.

jfjlaros

#7
Nov 28, 2018, 08:54 pm Last Edit: Nov 28, 2018, 10:27 pm by jfjlaros
The pain is crafting the URL for the RPC, ...
I quickly whipped up something using Swagger. Please note that REST conventions are not followed, this is purely a proof of concept.

In the browser an overview of all exported methods can be seen:



From this page it is possible to select a method, supply it with input (if applicable) and execute the method. The result shows up on the page:



Other clients like curl seem to work fine as well.


Go Up