.. _jsonrpc: JSON-RPC Interface ================== This interface uses the `JSON-RPC protocol `__ in version 2.0. The corresponding proxy module :ref:`vnx.JRPC_Proxy` is similar to the :ref:`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 :ref:`vnx.JRPC_Server` create a config file ``config/local/vnx_jrpc_server_map``: .. code-block:: javascript [ ["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 :ref:`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).