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