-
Gururaj Shetty authored
* Project rename * adr directory removed * Closes distro/docs#77 Signed-off-by:
Gururaj Shetty <gururaj.shetty@huawei.com>
Gururaj Shetty authored* Project rename * adr directory removed * Closes distro/docs#77 Signed-off-by:
Gururaj Shetty <gururaj.shetty@huawei.com>
Vending Machine Blueprint Applications Interface and Protocol
Contents
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:
┌────────────────┐ 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
{
"messageType": "setProperty",
"data": {
"selection": [0, 0, 0, 1]
}
}
Actions
{
"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:
{
"messageType": "addEventSubscription",
"data": {
"delivered": {}
}
}
{
"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:
┌────┐ ┌────┐
│ │ │ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ selection │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ │ │
│ │ [...] │ │
│ │ │ │
│ UI │ [...] │ IO │
│ │ │ │
│ │ │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ │ │
│ │ deliver │ │
│ ├─────────────────────►│ │
│ │ │ │
│ │ delivered │ │
│ │◄─────────────────────┤ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
└────┘ └────┘
Detailed example flow:
Firstly, client is intializing by subscribing for server's future "delivered" events:
{
"messageType": "addEventSubscription",
"data": {
"delivered": {}
}
}
Client's application is setting an empty selection on server and then UI will wait for user inputs:
{
"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"
{
"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":
{
"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:
{
"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:
{
"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
Oniro Project supports the following libraries for message encoding/decoding/parsing and the communication protocol:
- libwebsockets 4.0.1
- cjson 1.7.13 (to be upgraded to 1.7.14 for OpenHarmony convergence)
- json-c 0.13.1
Extra software could be integrated if needed:
For prototyping purposes server can be easily implemented using webthings framework.
Message schema
Selection Message Schema
The schema for the "selection" messages is:
{
"$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:
{
"$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:
{
"$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:
{
"$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.