Skip to content

The Robot Server Protocol

Reinhard Budde edited this page Aug 5, 2024 · 15 revisions

Introduction

After the user created a program and compiled it, it must be transferred to the robot. The lab supports a lot of transfer methods:

  • if the robot can be mounted as a USB storage device, i.e. it supports the USB mass storage class (e.g. calliopev3), the hex-file can be returned by the server as a file. Using the ''save as''-dialog of the browser it can be transferred to the robot.

  • if the robot can be mounted as a USB device and supports WEBUSB, i.e. follows guidelines as described for instance in how WEBUSB works (e.g. calliopev3), the hex file can be returned by the server as a file and using WEBUSB capabilities of a browser, it can be transferred directly to the robot. https only!

  • if the robot can be mounted as a USB device and the two techniques mentioned above are not appropriate, the ''openroberta connector'' can be installed locally and run. The connector connects to both the robot and the lab server and handles the hex-file transfer (e.g. arduinos). To achieve this, a token generated by the openroberta connector must be presented by the user to the lab to achieve the connection.

  • if the robot supports WLAN, it can connect directly to the openroberta lab server. This is the best way, but only a few robots supports this (e.g. ev3, TXT4). This kind robot-lab-communication is based on a simple protocol. This protocol is described in this text.

Overview about the protocol

The protocol itself is intended to be generic. If you have suggestions for improvements in this area, feel free to contact reinhard.budde AT iais.fraunhofer.de, so we can discuss it.

To not require any "push"- technology from the robot side, the protocol is based on long polling rfc6202).

First the robot has to register itself. This is done once. This is the register command. After identification the robot sends one request after the other to the server (a push command). The server returns a response:

  • after a period of time (say 5 seconds) a ''repeat'' notification, indicating, that nothing has happened at server side. The robot should issue a push command again. The robot knows, that the server is alive (at least for the last seconds).
  • if the user commands, that a program has to be executed on the robot (by pressing the run-button) the server returns a ''download'' notification. This instructs the robot, to download the program as hex-file and execute it.

This keeps the whole system responsive, without demanding too many resources on server side.

The request from the robot should be https and must use the POST method. The data payload is a JSONObject. A hex-file is transferred as octet-stream.

p-1

The register command is issued by the robot

  • REST endpoint: /rest/pushcmd, method is POST

  • the payload is a JSONObject consisting of the required fields (with example values):

{
  "cmd":"register", 
  "token":"LINA1234", 
  "pluginname":"txt4", 
  "macaddr": "01-23-45-67-89-ab"
}

Some optional fields are described later. The server respone is a JSONObject.

The register command must be the first command issued by the robot. The robot must generate a token. The token consists of 8 numbers 0-9 and upper characters A-Z. The token must be shown on a display by the robot. When the register-command hits the server, the server will put the token into a wait list. Later the user may type this token into a form activated by the menu entry ''verbinden''/''connect''. As a result, the client and the robot are "linked together" on server side by the token as a unique identifier. The token must be presented in all REST-calls.

If the user doesn't supply the token for a given period (about 5 minutes), the token expires.

When client and robot get paired, the server returns the payload {"cmd":"repeat","response":"ok"}. In this case the robot should issue an endless (repeated) sequence of push commands.

The push command is issued by the robot

  • REST endpoint is /rest/pushcmd, method is POST

  • the payload is a JSONObject consisting of the required field (with example values):

{
  "cmd":"push",
  "token":"LINA1234",
  "pluginname":"txt4"
}

Some optional fields are described later. The payload of the server respone is a JSONObject.

When the push commands hits the server, the server has two options:

  • if there is nothing to do, the server returns the JSNObject {"cmd":"repeat","response":"ok"}. Another push command is expected from the robot immediately.
  • if a program is to execute, the server returns the JSNObject {"cmd":"download","response":"ok"}. Now a download command from the robot is expected.

The download command is issued by the robot

  • REST endpoint is /rest/download, method is POST

  • the payload is a JSONObject consisting of the required field (with an example value):

{
  "cmd":"download",
  "token":"LINA1234"
}

The payload of the server response is a application/octet-stream and consists of the program as expected by the robot. A file name is set in the HTTP-header field "Filename". The robot will execute the progran. If the programm terminates sometimes in the future, the robot issues the next push command.

Optional fields of the JSONObject, that can be supplied by the robot

The optional fields (with an example value) are:

{
  "robotname":"myTxt4",
  "robot":"Txt4 Controller",
  "nepoexitvalue":"0",
  "battery":"8.4",
  "firmwareversion":"0.9.1-beta",
  "menuversion":"1.3.0"
}

"robotname", "robot" and "battery" can be viewed in the "info"-popup of the browser window. The ''nepoexitvalue'' communicates whether the execution of a previously transferred program was successful (''0'') or not (value not equal ''0''). Other fields are currently unused.

Notes

While running a hex-file on the robot, there is no communication (push requests) between the robot and the server. This is ok, because the server considers the robot as "running the program" for a long time, until another push request arrives.

The push requests tell the server, that the robot is alive and connected to the Open Roberta Lab. If a push request was answered by the server, but the no push command arrives for some time interval (about 10 sec), the robot is considered as offline/disconnected by the server. In case of heavy load in the network, it can occur, that the robot looses the connection to Open Roberta Lab and must be reconnected by a new register command and a new token.

This REST-based protocol can easily tested either with a gui-client or with command line tools like curl. If you run a local instance of the lab, at port 1999 for example, you can register with (1). This command terminates successful, if you enter the token into the connect form. Afterwards (2) can be sent repeatedly to keep the communication alive.

URL=https://dev3.open-roberta.org

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"cmd":"register","token":"LINA123D","pluginname":"txt4"}' \
  $URL # register command (1)

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"cmd":"push","token":"LINA123D","pluginname":"txt4"}' \
  $URL  # push command (2)

The following python3 program demonstrates how the protocol can be used by the robot. The downloaded program is written to the console.

# Remarks please to reinhard.budde AT iais.fraunhofer.de

# Run this python3 program on a laptop. The device needs access to the internet (to access the url below).
# Point your browser to the url, select the controller plugin to be tested, in the robot menu type the token.
# Then write a block-based program in the bowser and press the run button (the black triangle on the botton of the tab).
# The generated program is transferred from the openrovberta lab to this program and then written to stdout.

import requests
import time

url = 'https://dev3.open-roberta.org'
rest_endpoint_push = url + '/rest/pushcmd'
rest_endpoint_download = url + '/rest/download'

print('url of openroberta lab server is ' + url)

while (True):

# 'identify' is the very first request. First a token is generated and shown to the user. The user has to type it in the browser session
# of the lab to create a connection between the browser session and the controller. The request blocks until the connection is established
# or a timeout occurs. In this case a new token has to be generated. This is simulated by the 'token_suffix'

    token_suffix = 0
    while (True):
        token_suffix += 1
        token_value = 'LINA{:04d}'.format(token_suffix) # a new token is generated
        print('use the token "' + token_value + '"')
        r = requests.post(rest_endpoint_push, json={"cmd":"register","token":token_value,"pluginname":"txt4","robotname":"myTxt4"})
        result = r.json()
        if (result['cmd'] == 'repeat'):
            break
        print('register command failed and must be re-issued with a new token')

# the repeat loop: execute the repeat command over and over again. Terminate if the server returns 'download'.

    repeat_count = 1
    while (True):
        while (True):
            print('repeat ' + str(repeat_count))
            repeat_count += 1
            r = requests.post(rest_endpoint_push, json={"cmd":"push","token":token_value,"pluginname":"txt4","battery":'9'})
            result = r.json()
            if (result['cmd'] == 'download'):
                break

# retrieve the download, execute the program
# after the program has terminated, resume the repeat loop

        r = requests.post(rest_endpoint_download, json={"cmd":"download","token":token_value,"pluginname":"txt4"})
        if (r.status_code == 200):
            result = r.content
            print('download successful')
            # work with the downloaded data. Run the program. If that terminates, the repeat loop gets control again.

Updating firmware (not in use anymore, could be reactivated if needed)

As development continues, most likely there are library and system updates for the robot. Because reinstalling the firmware (on a micro SD-card for example) is time consuming and not trivial, Open Roberta Lab is able to provide the necessary files as a download for the robot system. The version number of the robot is compared to the version number from the server everytime a new robot is connected to Open Roberta Lab by a token and before running a program. If the firmware needs to be updated, the server answers the push request with an "update" command. This issues the robot to download files from the/rest/update/ endpoint. At this point, the robot is not considered connected to Open Roberta Lab. To download the files, a request with method GET is used. The filename is available in the header field "Filename" of the response.

Usually, to take benefit of the new files, the robot system has to reboot or it has to restart some parts of the system (for example the menu on the EV3). After that, the robot is able to register with Open Roberta Lab again.

Clone this wiki locally