From 52a8ebebaa31fc5158179af11acae76440898728 Mon Sep 17 00:00:00 2001 From: Andrei Gherzan <andrei.gherzan@huawei.com> Date: Thu, 23 Sep 2021 20:17:31 +0100 Subject: [PATCH] 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 <andrei.gherzan@huawei.com> Signed-off-by: Philippe Coval <philippe.coval@huawei.com> --- docs/blueprints/vending-machine-dev.rst | 658 ++++++++++++++++++++++++ docs/blueprints/vending-machine.rst | 8 + 2 files changed, 666 insertions(+) create mode 100644 docs/blueprints/vending-machine-dev.rst diff --git a/docs/blueprints/vending-machine-dev.rst b/docs/blueprints/vending-machine-dev.rst new file mode 100644 index 00000000..230edb88 --- /dev/null +++ b/docs/blueprints/vending-machine-dev.rst @@ -0,0 +1,658 @@ +.. 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. diff --git a/docs/blueprints/vending-machine.rst b/docs/blueprints/vending-machine.rst index a5e0f942..aaad8ce4 100644 --- a/docs/blueprints/vending-machine.rst +++ b/docs/blueprints/vending-machine.rst @@ -26,3 +26,11 @@ Get sources .. code-block:: bash user@pc:~/ohos$ repo sync -d + +Architecture and Interfaces +*************************** + +.. toctree:: + :maxdepth: 3 + + vending-machine-dev.rst -- GitLab