Skip to content
Snippets Groups Projects
Commit 52a8ebeb authored by Andrei Gherzan's avatar Andrei Gherzan :penguin:
Browse files

docs/vending-machine: Document applications protocol and message format

The "Vending Machine" blueprint takes advantage of two Linux
applications: a UI and a Control one. These applications will exchange
messages over a defined interface using a specific protocol. This
documentation provides the specification of the communication protocol,
message format, schemas and more.

Fixes https://git.ostc-eu.org/OSTC/planning/core-os/-/issues/224

Relate-to: https://git.ostc-eu.org/OSTC/OHOS/meta-ohos/-/merge_requests/282


Signed-off-by: Andrei Gherzan's avatarAndrei Gherzan <andrei.gherzan@huawei.com>
Signed-off-by: default avatarPhilippe Coval <philippe.coval@huawei.com>
parent b9159a2a
No related branches found
No related tags found
No related merge requests found
.. SPDX-FileCopyrightText: Huawei Inc.
..
.. SPDX-License-Identifier: CC-BY-4.0
Vending Machine Blueprint Applications Interface and Protocol
#############################################################
.. contents::
:depth: 4
Communication Protocol
**********************
The "Vending Machine" blueprint will take advantage of two applications: a UI
and an "IO Controller". These applications will exchange messages over a
defined interface using a specific protocol. For the scope of this
specification, the communication will happen over plain WebSockets/TCP.
Specification
-------------
In terms of roles, we have a client and a server. The "IO Controller" acts as a
server while the "UI" process, as a client.
As a minimum client/server specification, the applications will exchange
messages as per the following diagram:
.. code-block::
┌────────────────┐ selection ┌─────────────────────┐
│ ├───────────────────>┤ │
│ │ │ │
│ │ deliver │ IO │
│ UI Application ├───────────────────>┤ Control Application │
│ (client) │ │ (server) │
│ │ delivered │ │
│ │◄───────────────────┤ │
└────────────────┘ └─────────────────────┘
Static information can be set in configuration files shared between both
applications (e.g. for items name, a timeout for simulated actions, number of
item slots, etc.).
Server application is made on generic concepts inspired by WoT/WebThings:
- properties: set a *selection* of products
- selection is a fixed size array and items are identified from indices in
this array while the values represent the associated item quantity
- actions: request a *deliver* order
- order also contain the current selection as a parameter
- events: *delivered* event will notify that the *deliver* action was finished
- event is delivered based on the *addEventSubscription* subscription message
Thoses objects will be used through websockets's messages on default endpoint
(ie: `<ws://localhost:8888/>`).
Client request's payloads are formatted using JSON structures. Below there is
an example for each of the types defined:
Properties
==========
.. code-block:: json
{
"messageType": "setProperty",
"data": {
"selection": [0, 0, 0, 1]
}
}
Actions
=======
.. code-block:: json
{
"messageType": "requestAction",
"data": {
"deliver": {
"input": {
"selection": [0, 1, 0, 0]
}
}
}
}
Events
======
The client needs to send a subscription message once and listen from server's
event messages:
.. code-block:: json
{
"messageType": "addEventSubscription",
"data": {
"delivered": {}
}
}
.. code-block:: json
{
"messageType": "event",
"data": {
"delivered": {}
}
}
Inter-application message flow
------------------------------
The UI and Control applications will adhere to the message schema defined
above. The message flow is described as it follows:
.. code-block::
┌────┐ ┌────┐
│ │ │ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ │ │
│ │ [...] │ │
│ │ │ │
│ UI │ [...] │ IO │
│ │ │ │
│ │ │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ │ │
│ │ deliver │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ delivered │ │
│ │◄─────────────────────┤ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
└────┘ └────┘
Detailed example flow:
Firstly, client is intializing by subscribing for server's future **"delivered" events**:
.. code-block:: json
{
"messageType": "addEventSubscription",
"data": {
"delivered": {}
}
}
Client's application is setting an empty selection on server and then UI will
wait for user inputs:
.. code-block:: json
{
"messageType": "setProperty",
"data": {
"selection": [0, 0, 0, 0]
}
}
User selects one product (one of type "1"):
- UI will be updated accordigly
- The client process makes a request to the server to set **selection
"property"**
.. code-block:: json
{
"messageType": "setProperty",
"data": {
"selection": [0, 1, 0, 0]
}
}
The IO Controller will turn on the associated LEDs to show another visual
indication.
Then the user decides to add 1 more product of type "3":
.. code-block:: json
{
"messageType": "setProperty",
"data": {
"selection": [0, 1, 0, 1]
}
}
The user confirms the order by pressing the relevant UI element, then a
**"deliver" action"** is sent from client to the server:
.. code-block:: json
{
"messageType": "requestAction",
"data": {
"deliver": {
"input": {
"selection": [0, 1, 0, 1]
}
}
}
}
The UI application will be blocked until ready or timeout is reached:
- watchdog/timeout timer starts on UI/client
- UI waits for the **delivered** event
Processing is done server-side and **delivered event** is triggered:
.. code-block:: json
{
"messageType": "event",
"data": {
"delivered": {}
}
}
The UI is unblocked and ready for new selection (it should reinitialized to
empty).
If no "delivered" event after a defined timeout, the UI will display an "out of
order" message and show a "reset" button to refresh for the next order.
Software Dependencies Versions
------------------------------
ASOS supports the following libraries for message encoding/decoding/parsing and
the communication protocol:
* `libwebsockets <https://libwebsockets.org/>`_ 4.0.1
* `cjson <https://github.com/DaveGamble/cJSON/>`_ 1.7.13 (to be upgraded to
1.7.14 for OHOS convergence reasons)
* `json-c <https://github.com/json-c/json-c>`_ 0.13.1
Extra software could be integrated if needed:
* `libmicrohttpd <https://git.gnunet.org/libmicrohttpd.git/tree/src/include/microhttpd.h>`_
For prototyping purposes server can be easily implemented using
`webthings framework <https://webthings.io/>`_.
Message schema
--------------
Selection Message Schema
========================
The schema for the "selection" messages is:
.. code-block:: json
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": {},
"examples": [
{
"messageType": "setProperty",
"data": {
"selection": [
0,
1,
0,
0
]
}
}
],
"required": [
"messageType",
"data"
],
"properties": {
"messageType": {
"$id": "#/properties/messageType",
"type": "string",
"title": "The messageType schema",
"default": "",
"examples": [
"setProperty"
]
},
"data": {
"$id": "#/properties/data",
"type": "object",
"title": "The data schema",
"default": {},
"examples": [
{
"selection": [
0,
1,
0,
0
]
}
],
"required": [
"selection"
],
"properties": {
"selection": {
"$id": "#/properties/data/properties/selection",
"type": "array",
"title": "The selection schema",
"default": [],
"examples": [
[
0,
1
]
],
"additionalItems": true,
"items": {
"$id": "#/properties/data/properties/selection/items",
"anyOf": [
{
"$id": "#/properties/data/properties/selection/items/anyOf/0",
"type": "integer",
"title": "The first anyOf schema",
"default": 0,
"examples": [
0,
1
]
}
]
}
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Deliver Message Schema
======================
The schema for the "deliver" messages is:
.. code-block:: json
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": {},
"examples": [
{
"messageType": "requestAction",
"data": {
"deliver": {
"input": {
"selection": [
0,
1,
0,
0
]
}
}
}
}
],
"required": [
"messageType",
"data"
],
"properties": {
"messageType": {
"$id": "#/properties/messageType",
"type": "string",
"title": "The messageType schema",
"default": "",
"examples": [
"requestAction"
]
},
"data": {
"$id": "#/properties/data",
"type": "object",
"title": "The data schema",
"default": {},
"examples": [
{
"deliver": {
"input": {
"selection": [
0,
1,
0,
0
]
}
}
}
],
"required": [
"deliver"
],
"properties": {
"deliver": {
"$id": "#/properties/data/properties/deliver",
"type": "object",
"title": "The deliver schema",
"default": {},
"examples": [
{
"input": {
"selection": [
0,
1,
0,
0
]
}
}
],
"required": [
"input"
],
"properties": {
"input": {
"$id": "#/properties/data/properties/deliver/properties/input",
"type": "object",
"title": "The input schema",
"default": {},
"examples": [
{
"selection": [
0,
1,
0,
0
]
}
],
"required": [
"selection"
],
"properties": {
"selection": {
"$id": "#/properties/data/properties/deliver/properties/input/properties/selection",
"type": "array",
"title": "The selection schema",
"default": [],
"examples": [
[
0,
1
]
],
"additionalItems": true,
"items": {
"$id": "#/properties/data/properties/deliver/properties/input/properties/selection/items",
"anyOf": [
{
"$id": "#/properties/data/properties/deliver/properties/input/properties/selection/items/anyOf/0",
"type": "integer",
"title": "The first anyOf schema",
"default": 0,
"examples": [
0,
1
]
}
]
}
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Delivered Message Schema
========================
The schema for the "delivered" messages is:
.. code-block:: json
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": {},
"examples": [
{
"messageType": "event",
"data": {
"delivered": {}
}
}
],
"required": [
"messageType",
"data"
],
"properties": {
"messageType": {
"$id": "#/properties/messageType",
"type": "string",
"title": "The messageType schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": [
"event"
]
},
"data": {
"$id": "#/properties/data",
"type": "object",
"title": "The data schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [
{
"delivered": {}
}
],
"required": [
"delivered"
],
"properties": {
"delivered": {
"$id": "#/properties/data/properties/delivered",
"type": "object",
"title": "The delivered schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [
{}
],
"required": [],
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Previous event will be notified if the client sends a subscription message:
.. code-block:: json
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "object",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": {},
"examples": [
{
"messageType": "addEventSubscription",
"data": {
"delivered": {}
}
}
],
"required": [
"messageType",
"data"
],
"properties": {
"messageType": {
"$id": "#/properties/messageType",
"type": "string",
"title": "The messageType schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": [
"addEventSubscription"
]
},
"data": {
"$id": "#/properties/data",
"type": "object",
"title": "The data schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [
{
"delivered": {}
}
],
"required": [
"delivered"
],
"properties": {
"delivered": {
"$id": "#/properties/data/properties/delivered",
"type": "object",
"title": "The delivered schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [
{}
],
"required": [],
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
Current assumptions
-------------------
* Both of the applications (server/client, "UI"/"IO Controller" are running on
the same, Linux-based target.
* The quantity of a selection is maximum "1". This means that the selection
array can contain values of 0 or 1.
* The availability from the perspective of the "IO Controller" is infinite.
...@@ -26,3 +26,11 @@ Get sources ...@@ -26,3 +26,11 @@ Get sources
.. code-block:: bash .. code-block:: bash
user@pc:~/ohos$ repo sync -d user@pc:~/ohos$ repo sync -d
Architecture and Interfaces
***************************
.. toctree::
:maxdepth: 3
vending-machine-dev.rst
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment