JSON-RPC Interface

This interface uses the JSON-RPC protocol in version 2.0.

The corresponding proxy module vnx.JRPC_Proxy is similar to the vnx.Proxy and mostly follows the same protocol, only it wraps its messages into appropriate JSON objects.

Message format

A message in our setting of the JSON RPC protocol may look like this:

{
        "jsonrpc": "2.0",
        "id": "123some_id456",
        "method": "MyModule.some_method",
        "params": {
                "first": "Hello",
                "second": 4321
        }
}

Some remarks:

  • The id is optional. If you provide it, you will get a response message, otherwise you will get nothing. This includes error messages!

  • method consists of a module name and its method name, separated by a dot. If you omit the module name (but keep the dot), the request is directed at the proxy module itself.

    The proxy module has a method select_service to assign a module name for the rest of the connection:

    {
            "jsonrpc": "2.0",
            "id": "123some_id456",
            "method": ".select_service",
            "params": {
                    "service_name": "MyModule"
            }
    }
    

    Now you can omit the module name (and the dot) in future requests.

  • params is an object indexed by the names of the parameters as defined in the interface of the module. You can also supply a list instead, although that is not encouraged.

Server

To enable a vnx.JRPC_Server create a config file config/local/vnx_jrpc_server_map:

[
        ["JRPC_Server", "0.0.0.0:5556"],
        ...
]

This will start a JSON RPC server that listens on the TCP/IP address 0.0.0.0:5556.

Connecting

Open a TCP connection to the port of the server. You should be greeted with a welcome message (method .on_remote_connect) that you can safely ignore.

To authenticate use the on_login method of the proxy:

{
        "jsonrpc": "2.0",
        "method": ".on_login",
        "params": {
                "name": "username",
                "password": "23f/*...*/995"
        }
}

where password is a SHA-256 hash of the actual password. On success you should receive a call to .on_remote_login providing some information on your established session.

Return Values

Note

You will only receive return values if you supply the id field in your request.

Return values are wrapped inside a success message with the result field holding the actual return value. A successful call to RoadMapPlanner.find_station may look like this:

{
        "__type": "vnx.JRPC_Success",
        "jsonrpc": "2.0",
        "id": 5566,
        "result": {
                "__type": "pilot.MapStation",
                "drive_flags": [],
                "goal_tolerance": {"__type": "pilot.vector_3f_param_t", "type": "DEFAULT", "x": {"__type": "pilot.float_param_t", "type": "DEFAULT", "value": 0}, "y": {"__type": "pilot.float_param_t", "type": "DEFAULT", "value": 0}, "z": {"__type": "pilot.float_param_t", "type": "DEFAULT", "value": 0}},
                "goal_tune_time": {"__type": "pilot.float_param_t", "type": "DEFAULT", "value": 0},
                "group": "",
                "id": 120,
                "name": "Station120",
                "orientation": -3.13343,
                "position": [-0.611983, 2.81928],
                "profiles": [],
                "tolerance": {"__type": "pilot.float_param_t", "type": "DEFAULT", "value": 0}
        }
}

The result of calling a void method has a null return value:

{
        "__type": "vnx.JRPC_Success",
        "jsonrpc": "2.0",
        "id": 43,
        "result": null
}

Errors

Note

You will only receive errors if you supply the id field in your request.

If your request failed, you will get an error response. It contains an error field with an object giving an error code, a short message and the actual error object.

When the method you called throws an exception, the error will look like this:

{
        "__type": "vnx.JRPC_Failure",
        "jsonrpc": "2.0",
        "id": 43,
        "error": {
                "__type": "vnx.JRPC_Error",
                "code": 500,
                "message": "roadmap station does not exist",
                "data": {
                        "__type": "vnx.InternalError",
                        "what": "roadmap station does not exist"
                }
        }
}

This shows an error that you get if you lack a permission to do something:

{
        "__type": "vnx.JRPC_Failure",
        "jsonrpc": "2.0",
        "id": 42,
        "error": {
                "__type": "vnx.JRPC_Error",
                "code": 403,
                "message": "permission denied (pilot.permission_e.MOVE)",
                "data": {
                        "__type": "vnx.PermissionDenied",
                        "what": "permission denied (pilot.permission_e.MOVE)",
                        "dst_mac": 0,
                        "method": "pilot.HybridPlanner.set_goal_station",
                        "permission": "pilot.permission_e.MOVE"
                }
        }
}

See vnx.JRPC_Error for a list of error codes.

Topics

As with the VNX protocol, subscribing to a topic is done with the enable_export method of the proxy:

{
        "jsonrpc": "2.0",
        "method":".enable_export",
        "params": {
                "topic_name": "some.topic"
        }
}

Received samples will have the following form:

{
        "jsonrpc": "2.0",
        "method": "!some.topic",
        "params": {
                "seq_num": 42,
                "value": {"__type": "some.Datatype", "time": 1600000023, "some_more": "fields"}
        }
}

Notice that we are relaxing the notion of a “method” here: The initial ! makes clear that it actually refers to a topic and the parameters really just hold the value.

Using the same format in the other direction, you can also publish samples on the named topic (given sufficient permissions).