Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
vending-machine-dev.rst 17.97 KiB

Vending Machine Blueprint Applications Interface and Protocol

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:

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.