libjapi  0.3.2
Universal JSON API Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
Communication Concepts

There are two types of communication - requests and push-services.

JSON requests

JSON requests are synchronous requests. A valid request results in an response.

Push-services

Push services are asynchronous responses from the server. They can be subscribed and unsubscribed through synchron request. The push service will send JSON responses until it's unsubscribed by a JSON request to the server, by the respective client.

If subscribed trough an synchronous JSON requests, push services are pushed dependent on there configured interval, to the subscribed clients. Internally they are run in an own thread. That means, the service messages are pushed independently from the server. One push service (thread) can manage multiple clients, that are subscribed to him.

Note
japi_pushsrv_list is registered by default.

JSON specification for communication types

Request format

JSON requests to the libjapi always start with the JSON key japi_request followed by the japi request name:

{
"japi_request": "<request_name>",
"args": {
"<request-specific-key-1>": "<request-specific-value-1>",
"<request-specific-key-n>": "<request-specific-value-n>"
}
}

A missing japi_request key in a JSON request will result in errors. The JSON keys in args are additional values the request needs for processing. It's the same for self-defined request-functions; the needed keys are defined by the functions. See here for detailed examples.

Providing request number

An optional key japi_request_no can be included with each request and will be added to the response accordingly. japi_request_no can be any valid JSON value.

{
...
"japi_request_no": "<request_number>",
...
}

Example request with request number:

{
"japi_request": "some_request",
"japi_request_no": "2020-02-20 20:22:20.202"
}

Response including request number:

{
"japi_response": "some_request",
"japi_request_no": "2020-02-20 20:22:20.202"
}

Response format

All requests return a response. The reponse format begins always with the JSON key japi_response followed by the request, that returned the response:

{
"japi_response": "<request_name>",
"data": {
"<request-specific-return-key-1>": "<request-specific-return-value-1>",
"<request-specific-return-key-n>": "<request-specific-return-value-n>"
}
}

Like the JSON request the keys and values in data, are request specific; additional information, like return values of a function.

Response including request arguments

If configured via japi_include_args_in_response(ctx, true), the response will additionally include the arguments given in the request:

{
"japi_response": "<request_name>",
"args": {
"<request-specific-key-1>": "<request-specific-value-1>",
"<request-specific-key-n>": "<request-specific-value-n>"
},
"data": {
"<request-specific-return-key-1>": "<request-specific-return-value-1>",
"<request-specific-return-key-n>": "<request-specific-return-value-n>"
}
}

Request and response format for push services

It's the same for the push services, with the difference that there is an additional key service or services to identify the service to be targeted by the requests. For the push services like japi_pushsrv_subscribe, japi_pushsrv_unsubscribe, japi_pushsrv_list etc. an additional key value will be the service, or services for japi_pushsrv_list, so it's possible to backtrack the response to the origin of the request. Push service requests, responses and push-messages should look like this: Push service list request:

{
"japi_request": "japi_pushsrv_list",
}

Push service list response:

Note
The service list in services can be empty if there is no push service registered.
{
"japi_response": "japi_pushsrv_list",
"data": {
"services": [
"push-service-name-1",
"push-service-name-n"
]}
}

Push service subscribe request:

{
"japi_request": "japi_pushsrv_subscribe",
"args": {
"service": "<push_service_name>"
}
}

Push service subscribe response:

{
"japi_response": "japi_pushsrv_subscribe",
"data": {
"service": "<push_service_name>",
"success": {true/false}
}
}

Push service unsubscribe request:

{
"japi_request": "japi_pushsrv_unsubscribe",
"args": {
"service": "<push_service_name>"
}
}

Push service unsubscribe response:

{
"japi_response": "japi_pushsrv_unsubscribe",
"data": {
"service": "<push_service_name>",
"success": {true/false}
}
}

Push service messages after successful subscribing a push service:

Note
The push service messages just return the push service name, from which they are send.
{
"japi_pushsrv": "<push_service_name>",
"data": {
"<push-service-specific-return-key-1>": "<push-service-specific-return-value-1>",
"<push-service-specific-return-key-n>": "<push-service-specific-return-value-n>"
}
}
Note
In JSON the order of the key-value pair lines are not ensured.

Communication example

Create JAPI context
Register services
Register push+services
Server Client1 Client2
+ + +
Start registered push-services +---------------------------> push_temperature() | { |
| + | "japi_request": "get_temperature", |
| | | "args": { |
| | | "unit": "kelvin" |
| | | } |
| <----------------------------------------------+ } |
{ | | | |
"japi_response": "get_temperature", | | | |
"data": { | | | |
"temperature": 300.0, | | | |
"unit": "kelvin" | | | |
} | | | |
} +----------------------------------------------> | |
| | | | {
| | | | "japi_request": "japi_pushsrv_list",
| | | | }
| <------------------------------------------------------------------------------------------------+
{ | | | |
"japi_response": "japi_pushsrv_list", | | | |
"data": { | | | |
"services": [ | | | |
"push_temperature", | | | |
]} | | | |
} +------------------------------------------------------------------------------------------------> |
| | | |
| | | |
| | | { |
| | | "japi_request": "japi_pushsrv_subscribe", |
| | | "args": { |
| | | "service": "push_temperature" |
| | | } |
| | | } |
{ | <----------------------------------------------+ |
"japi_response": "japi_pushsrv_subscribe", | | | |
"data": { | | | |
"service": "push_temperature", | | | |
"success": true | | | |
} | | | |
} +----------------------------------------------> | |
| | | |
| { | | |
| "data": { | | |
| "temperature": 31.986693 | | |
| }, +--------> | |
| "japi_pushsrv": "push_temperature" | | |
| } | | |
| +--------> | |
| | | |{
| | | | "japi_request": "japi_pushsrv_subscribe,
| | | | "args": {
| +--------> | | "service": "push_temperature"
| | | | }
| | | |}
{ + <-----------------------------------+----------+-------------------------------------------------+
"japi_response": "japi_pushsrv_subscribe", | | | |
"data": { | | | |
"service": "push_temperature", | | | |
"success": true +------------------------------------------------------------------------------------------------> |
} | | | |
} | | | |
| +----------------------------------------------------------> |
|{ | | |
| "data": { | | |
| "temperature": 42.136809 | | |
| }, | | |
| "japi_pushsrv": "push_temperature" +--------> | |
| } | | |
| | | |
| +----------------------------------------------------------> |
| | | |
| | | { |
| | | "args": { |
| | | "service": "push_temperature" |
| | | } |
| | | } |
| <----------------------------------------------+ |
{ | | | | {
"data": { | | | | "args": {
"service": "push_temperature", +----------------------------------------------> | | "service": "push_temperature"
"success": true | | | | }
} | | | | }
} | <------------------------------------------------------------------------------------------------+
| | | |
{ | | | |
"japi_response": "japi_pushsrv_unsubscribe",| | | |
"data": { | | | |
"service": "push_temperature", +------------------------------------------------------------------------------------------------> |
"success": true | | | |
} | | | |
} v v v v