Documentation

Message format

All messages are JSON objects, and look as follows

{
  "#": 1751358313572,
  "#d": "device id",
  "#c": "message type",
  "property": "value",
  ...
}

The # key is always present, and contains the time (Unit timestamp in milliseconds) at which the message was created. All messages from the same module have strictly increasing timestamps, and will arrive in that order. The modules use a time server to keep their clocks synchronized with an accuracy of a few seconds.

The #c key contains the message type (channel).

The #d key contains the id of the device which created the message.

All other keys are specific to the message type.

A message can be up to about 1 kB in size.

Message submission and message queue

Messages are submitted immediately. If the module loses its internet connection, messages are queued and transmitted later. The queue can store about 1 hour worth of messages. If the queue is full, the oldest messages are discarded.

Vend operations

Simple remote vend

The user selects a product on an external device, e.g. his own mobile phone, or a screen attached to the vending machine. Once he has paid, the server sends the following message to the machine:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend",
  "id": "8921ac071285af83",
  "number": 14,
  "price": 320,
  "name": "Strawberry cake",
  "sugar": 2,
  "cup size": 1,
  ...
}

The ID is optional. If provided, it must be a 16 digit hex sequence. It is best to use random IDs.

Upon reception, the machine releases the product with the indicated options (if any) to the customer, and replies with one of the following messages:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend succeeded",
  "id": "8921ac071285af83",
  "cash": 0,
  "number": 14,
  "price": 320,
  "name": "Strawberry cake",
  "sugar": 2,
  "cup size": 1,
  ...
}
{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend failed",
  "id": "8921ac071285af83",
  "cash": 0,
  "number": 14,
  "price": 320,
  "name": "Strawberry cake",
  "sugar": 2,
  "cup size": 1,
  ...
}

The ID mentioned in the vend message is repeated here. The messages indicate what was actually served (or failed to be served). Hence, the vend suceeded messages may be used for accounting purposes, while the vend failed messages may be used for servicing purposes.

In case the vend failed, the money should be returned to the customer.

Only one product release can be underway at a time. If multiple vend messages are sent within a short amount of time, the vend may fail.

Vend initiated on the machine

When a user selects a product on a machine, the module sends a vend request to the server:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend request",
  "id": "8921ac071285af83",
  "number": 14,
  "price": 320,
  "name": "Strawberry cake",
  "sugar": 2,
  "cup size": 1,
  ...
}

The id is a random (unique) hex sequence. The price is indicated in cents. If the user changes the selection, a new vend request message with the same ID will be sent, which updates the previous vend request.

Similarly, if the user changes the selection on the remote device, the server may send a similar vend request update to the machine. The server may also change the price, or the product name. The machine will update the product selection on its display (if any).

If the user cancels the vend on the machine, or the machine decides to cancel the vend after a timeout, the following message will be sent:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend cancelled",
  "id": "8921ac071285af83"
}

Similarly, the server may send a vend cancelled message to the machine to cancel the vend and reset the display on the machine.

Once the payment has been settled, the server sends a vend message to the machine, which releases the product. The procedure is exactly the same as with a remote vend.

Users walking away, coming back, and other edge cases

A vend usually ends with either a vend succeeded, vend failed, or a vend cancelled message. However, in certain cases, a vend may simply be abandoned without sending any notification. If the server suddenly receives a new vend request from a machine, any previous vend requests from that machine should be considered cancelled.

Similarly, the server may start a new vend request without cancelling the old one. The server may also send a vend message to release a product, while a vend request with a different ID is active.

The server may even reopen a cancelled vend by sending vend request or vend messages with a previously used ID. The machine only keeps track of one vend session at a time.

Payment with cash

If a user pays with cash, the machine will release the product, and send a vend succeeded or vend failed message to the server:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vend succeeded",
  "id": "8921ac071285af83",
  "cash": 320,
  "number": 14,
  "price": 320,
  "name": "Strawberry cake",
  "sugar": 2,
  "cup size": 1,
  ...
}

The message mentions the amount paid with cash, as well as the released product.

The machine will accept cash no matter how the vend was initiated. If the server sends a vend request with a price, and the user settles this price with cash, the machine will release the product.

If the user first puts coins into the machine, and then selects the item, the server may only receive a vend succeeded or vend failed message, without any prior vend request. This case is handled entirely by the machine, and the remote system is just notified of the vend for accounting purposes.

Product list

The module maintains a product list. When the user selects a product, the product list is consulted for the product's name and price. If the product is not found, the price indicated by the VMC is used, and the product has no name.

The following message clears the product list:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "clear product list"
}

The following message adds or replaces a product on the list:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "set product",
  "number": 43,
  "name": "Strawberry cake",
  "price": 320
}

If a product with the same number exists on the list, the corresponding entry is replaced.

The following message requests the module to send the product list:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "get product list"
}

The module responds by sending all products.

Display

The following message configures the display if the machine is idle:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "idle display",
  "content": [
    {
      "text": "Welcome HH:MM",
      "alignment": "center",
      "duration": 60
    },
    {
      "text": "DELISS HH:MM",
      "alignment": "center",
      "duration": 60
    }
  ]
}

Line-breaking is applied automatically. The alignment can be left, center (default), or right. HH:MM is replaced by the time.

Up to 8 texts can be configured with a duration (in seconds). These texts are rotated in the order provided.

When a product is selected, the idle screen is replaced by the product name and price, and the inserted coins.

The following message shows a short text on the VMC's display:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "display",
  "text": "Hello",
  "alignment": "center",
  "duration": 10
}

The duration is indicated in seconds, and rounded to the nearest 0.1 seconds. The message may be removed earlier, e.g. if a customer selects a product.

Line-breaking is applied automatically. The alignment can be left, center (default), or right.

Coin changer

If a coin changer is attached, the following message is sent to indicate the amount of coins left:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "changer tubes",
  "tubes": [
    {
      "index": 0,
      "value": 10,
      "count": 172
    },
    {
      "index": 1,
      "value": 20,
      "count": 80
    },
    {
      "index": 2,
      "value": 50,
      "count": 66
    },
    ...
  ]
}

Every entry contains a tube index, the coin value stored in that tube, and the amount of coins remaining. Different tubes may have the same coin value. The coin count is reported as measured by the coin dispenser, and is usually accurate to ±2 coins.

When customers pay with coins, they either go into the tubes, or into a coin box. Only the coins in the tubes are reported, and only these coins are available for dispensing.

For regular vends, coin collection and dispensing are managed automatically. However, coins can also be dispensed remotely by sending the following message:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "dispense coins",
  "amount": 230
}

Measurement messages

Voltage

Every minute, the module reports the voltage of the MDB bus:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "voltage",
  "v": 27.8,
  "raw": 2032
}

The voltage is somewhere between 24 V and 30 V.

Temperature and humidity

Every minute, the module reports temperature and humidity from its onboard sensor:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "t-rh",
  "ts": 1754923440254,
  "t": 23.7,
  "rh": 0.346
}

The t value is the temperature of the electronic board in degrees Celsius. It is usually about 3-5 degrees above the ambient temperature. The rh value reports the relative humidity from 0 (0 %RH) to 1 (100 %RH).

Since this message is sent regularly, and independent of any other activity, it may be used as alive message. As long as this message arrives, the module is powered on, and in normal operation.

ts value denotes the time at which the measurement was recorded, as Unix timestamp in milliseconds.

Noise sensors

A noise sensor reports the ambient noise level:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "noise",
  "ts": 1754923440254,
  "noise": 2844
}

Noise values are determined every second, but submitted only once per minute, or if the value changes significantly since it was last reported.

Values are in the range from 0 to 65536. A quiet place will report values below 1000. A loud noise is a value significantly above the baseline. If a machine is located in a noisy place, the baseline may be above 1000.

Accelerometer

An accelerometer reports physical motion of the machine, e.g. if somebody pushes against the machine:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "motion",
  "ts": 1754923440254,
  "motion": 763
}

Motion is measured once per second, but submitted only once per minute, or if the value changes significantly since it was last reported.

Values are in the range of 0 to 65536. If the machine is not exhibiting any external forces, the reported motion is below 500.

Machine state and diagnostic messages

A machine consists of a VMC (vending machine controller), and a module. The module is attached as a MDB slave (s) and pretends to be a cashless device (cl) and a communications gateway (cg). Each of these components has a state information which is sent in separate messages.

VMC information

When the module starts communicating with the VMC, it reports information about the VMC using the following two messages:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vmc",
  "manufacturer": ...,
  "serial": ...,
  "model": ...,
  "version": ...
}
{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "vmc features",
  "feature level": 3,
  "display": {
    "columns": 16,
    "rows": 2,
    "info": 0
  }
}

The feature level should be 3, as this is the only feature level supported by the module.

Uptime

In regular intervals, the module sends its uptime, i.e. the number of seconds since the module is running:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "uptime",
  "uptime": 514493
}

The uptime can be used to detect module restarts.

Normal operation mode and maintenance mode

The module has two operation modes:

Normal operation: The module is communicating with the VMC, and ready to process orders. In normal operation mode, the green LED shortly blinks once per minute.

Maintenance mode: The module is about to be initialized, configured, updated, or experienced an unexpected problem in normal mode. In this mode, the module does not communicate with the VMC, and cannot process orders. It can however be reconfigured, or update the firmware. In maintenance mode, the blue LED blinks once every 10 seconds.

When the module is powered on, it boots into maintenance mode, carries out a brief hardware check, and then boots into normal operation mode. This takes about 2 seconds.

The module reboots into maintenance mode in the following cases:

When in maintenance mode, the module reboots into normal operation mode in one of the following cases:

WIFI configuration

Upon restart, the module tries to connect to a WIFI network. It keeps trying every 10 seconds until it manages to connect to a network. If it loses a connection, it keeps trying to connect again. While trying to connect, the green (normal mode) or blue (maintenance mode) LED blinks about once per second. Blinking stops as soon as a connection is established.

The module reports its WIFI connection state by sending the following message:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "wifi",
  "ssid": "my wifi",
  "rssi": -55
}

The RSSI denotes the signal strength. This is a negative value between approximately -100 (very bad connection) and -20 (very good connection). Values below -80 are of concern, since the network connection may drop intermittently.

The WIFI networks can be configured with the following message:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "set wifi configuration",
  "networks": [
    {
      "ssid": "my wifi",
      "password": "pass1234word",
      "hostname": "vending"
    },
    ...
  ]
}

Up to 8 networks can be configured. The module tries to connect to them in the order they appear. If a network is not available, or the connection fails, the module gives up after 10 seconds and tries the next network. Once all networks have been tried, it starts from the top of the list.

Note that after receiving a new WIFI configuration, the module remains connected to the current network. To force reconnecting, reboot the module.

To retrieve the list of configured networks, send the following message:

{
  "#": ...,
  "#d": "3c8a1f7c38ec0000",
  "#c": "get wifi configuration"
}

WIFI bootstrapping

If the module cannot connect to any configured WIFI network, it is unable to receive messages to reconfigure the WIFI networks. In this case, the WIFI can be reset and configured as follows:

The module will restart in maintenance mode (if necessary) and connect to the hotspot, and can then be configured through its web interface (http://setup.local), or receive configuration messages from the server.

Network configuration

The module uses the following ports:

  1. TCP/UDP 53 (DNS), outgoing
  2. TCP/UDP 123 (NTP), outgoing
  3. TCP 443 (HTTPS), outgoing
  4. UDP 5101, outgoing

The SumUp Solo terminal uses the following subset of these ports:

  1. TCP/UDP 53 (DNS), outgoing
  2. TCP/UDP 123 (NTP), outgoing
  3. TCP 443 (HTTPS), outgoing

All connections are initiated by the devices, and therefore outgoing.