Mentions légales du service

Skip to content
Snippets Groups Projects
user avatar
Eric Pascual authored
a1f728bf
History

Room control REST API

This project provides an HTTP server exposing services for controlling the devices of the escape game rooms.

The control can be at :

  • semantic level, such as opening a room door, or unlocking a room lid for example, without having to kwow which servo is involved in the action,
  • low level, contolling directly the servos by setting their position.

Each servo can be configured in terms of mapping between the logical output angle and the pulse timing. This makes possible to restrict the usable part of the output total travel, to avoid out of range commands with repect to the mechanical device powered by the servo. It can also be usefull to take in account the fact that not all servos accept the default [.5ms, 2.5ms] pulse range, and that using values close to the bounds can make the motor trying to go past the mechanical stops. If your servos fall in this category, you'll have to adjust the default values in the configuration file.

Dependencies

The projects depends on the following items:

Build

The documentation hereafter illustrates the make based workflow. You are of course not forced to use it and can instead work with the IDE builtin commands.

Reminder: If you use the IDE, before the first build remember to select Adafruit ESP32 Feather as the target board type.

Use make verify to compile the project code.

Note : This is not the default Makefile target, since the common workflow chains the target flash (aka upload) when the compilation succeed.

Installation

Deployment on the ESP32 is done with make upload (which will re-compile the code too, but this is the way Arduino tools work :/)

Since the process of building and uploading the firmware is often executed, the upload target is the default one of the Makefile. So make alone will suffice.

You'll need to either edit the Makefile or define the ARDUINO_PORT environment variable (prefered way) it the ESP32 does not appear as /dev/ttyUSB0.

Configuration files located in the data sub-directory of the project must be edited and uploaded separately. Review their embedded comments and apply the procedure they describe.

You'll have to use the ESP32 SPIFFS IDE plugin to upload the files (until we find a way to perform the task in command line and integrate it in the Makefile).

API operations

General considerations

The API includes routes for the following operations:

  • room door and lid lock control
  • room door and lid lock current status query
  • room door and lid lock configuration edit and query
  • servo direct control
  • servo status query
  • servo configuration edit and query
  • global configuration query
  • system level configuration edit
  • board restart

Parameters of POST and PUT requests are passed as the request body in URL encoded form.

All requests use the standard HTTP statuses in teir response:

  • 200 : success
  • 400 : invalid request (wrong parameter for instance)
  • 404 : not found (i.e. a rooom number outside the vaid range)
  • 500 : internal error

The only infringement is that using an unsupported method for a given method does not returns a 405 status but a 404 one.

Error responses include a JSON body with the following format :

{
    "detail": "Houston we got a problem"
}

Thanks to mDSN being activated, the ESP can be accessed with a host name in the form roomctrl-<id>.local, <id> being the value of the controller_id configuration parameter (0 by default).

Device oriented routes

POST /rooms/{num}/door

Moves a room door and returns its new state. The control can be given in different forms :

  • action : semantic action (open or close)
  • position : angular servo position (in the range configured for the servo)
  • percent : servo position as a percent of its full travel (0-100)
  • pulse : with of the servo control pulse (in micro-seconds)

pos and pct can be used as abbreviated forms of position and percent respectively.

Path variables:

  • num : the room number (currently 1 or 2)

Body data:

  • One of action, position, pos, percent, pct, pulse and the associated value

Response: The resulting position of the door and its state. The state is eithed opened or closed if the position matches one of the pre-defined ones, or undef for all other values.

{
    "position": 90,
    "state": "opened"
}

cURL examples:

curl -X POST -d "action=open" http://roomctrl-O.local:8000/rooms/1/door
curl -X POST -d "position=90" http://roomctrl-O.local:8000/rooms/1/door
curl -X POST -d "percent=50" http://roomctrl-O.local:8000/rooms/1/door
curl -X POST -d "pulse=1500" http://roomctrl-O.local:8000/rooms/1/door

GET /rooms/{num}/door

Returns the current position and state of a door.

Path variables:

  • num : the room number (currently 1 or 2)

Response:

{
    "position": 90,
    "state": "opened"
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/rooms/1/door

GET /rooms/{num}/door/settings

Returns the settings of a given door. The response is always in JSON format.

Path variables:

  • num : the room number (currently 1 or 2)

Response:

{
    "pos_closed": 90,
    "pos_opened": 0,
    "servo": 0
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/rooms/1/door/settings

PUT /rooms/{num}/door/settings

Changes the settings of a room door servo and returns the updated configuration.

Changes are immediatly applied and are persisted in the ESP32 flash. Updated values will this be recovered on subsequent boots.

The settings which can be changed are:

  • servo : the id (from 0 to 7) of the servo which powers the room
  • pos_opened : the position for of the opened position
  • pos_closed : the position for of the closed position

Positions can be anything (degrees, distance,...) depending on the servo type and usage, as long as control requests use the same convention.

Path variables:

  • num : the room number (currently 1 or 2)

Body data:

  • name : the name of the setting, among the above list
  • value : the new value of the setting

Response: The new settings, with the same format as the GET equivalent request.

cURL example:

curl -X PUT -d "name=pos_opened&value=90" http://roomctrl-O.local:8000/rooms/1/door/settings

POST /rooms/{num}/lid

Controls the lid lock, the same was as for doors with respect to control type. The only difference is that action valid values are lock and unlock.

Path variables:

  • num : the room number (currently 1 or 2)

Body data:

  • One of action, position, pos, percent, pct, pulse and the associated value

Response: The resulting position of the lid lock and its state. The state is eithed unlocked or locked if the position matches one of the pre-defined ones, or undef for all other values.

{
    "position": 180,
    "state": "unlocked"
}

cURL example:

curl -X POST -d "action=lock" http://roomctrl-O.local:8000/rooms/1/lid
curl -X POST -d "position=90" http://roomctrl-O.local:8000/rooms/1/door
curl -X POST -d "percent=50" http://roomctrl-O.local:8000/rooms/1/door
curl -X POST -d "pulse=1500" http://roomctrl-O.local:8000/rooms/1/door

GET /rooms/{num}/lid

Returns the current position and state of a room lid lock.

Path variables:

  • num : the room number (currently 1 or 2)

Response:

{
    "position": 180,
    "state": "unlocked"
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/rooms/1/lid

GET /rooms/{num}/lid/settings

Returns the settings of a given lid lock. The response is always in JSON format.

Path variables:

  • num : the room number (currently 1 or 2)

Response:

{
    "pos_locked": 0,
    "pos_unlocked": 180,
    "servo": 1
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/rooms/1/lid/settings

PUT /rooms/{num}/lid/settings

Changes the settings of a room lid servo and returns the updated configuration.

The settings which can be changed are:

  • servo : the id (from 0 to 7) of the servo which powers the lock
  • pos_locked : the position for of the locked position
  • pos_unlocked : the position for of the unlocked position

Positions can be anything (degrees, distance,...) depending on the servo type and usage, as long as control requests use the same convention.

Path variables:

  • num : the room number (currently 1 or 2)

Body data:

  • name : the name of the setting, among the above list
  • value : the new value of the setting

Response: The new settings, with the same format as the GET equivalent request.

cURL example:

curl -X PUT -d "name=pos_locked&value=180" http://roomctrl-O.local:8000/rooms/1/lid/settings

Servo oriented routes

POST /servos/{id}

Makes a servo move to a given position.

Path variables:

  • id : the servo id (from 0 to 7), which is the same as the number of the PCA port it is connected to

Body data:

  • One of position, pos, percent, pct, pulse and the associated value

Response: The resulting position of the servo, whatever was the type of parameter provided in the request.

{
    "position": 180,
}

cURL example:

curl -X POST -d "position=90" http://roomctrl-O.local:8000/servos/0
curl -X POST -d "percent=50" http://roomctrl-O.local:8000/servos/0
curl -X POST -d "pulse=1500" http://roomctrl-O.local:8000/servos/0

GET /servos/{id}/settings

Returns the settings of a given servo. The response is always in JSON format.

Path variables:

  • id : the servo id (from 0 to 7), which is the same as the number of the PCA port it is connected to

Response:

{
    "inverted": 0,
    "pos_max": 180,
    "pos_min": 0,
    "pulse_max": 2500,
    "pulse_min": 500
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/servos/0/settings

PUT /servos/{id}/settings

Changes the settings of a servo and returns the updated configuration.

The settings which can be changed are:

  • pos_min : the lower bound of the position range
  • pos_max : the upper bound of the position range
  • pulse_min : the duration (in micro-seconds) of the pulse for min position
  • pulse_max : the duration (in micro-seconds) of the pulse for max position
  • inverted : 0 (default) CCW rotation, 1 CW rotation

Positions can be anything (degrees, distance,...) depending on the servo type and usage, as long as control requests use the same convention.

Path variables:

  • id : the servo id (from 0 to 7), which is the same as the number of the PCA port it is connected to

Body data:

  • name : the name of the setting, among the above list
  • value : the new value of the setting

Response:

{
    "inverted": 0,
    "pos_max": 180,
    "pos_min": 0,
    "pulse_max": 2500,
    "pulse_min": 500
}

cURL example:

curl -X PUT -d "name=pos_min&value=0" http://roomctrl-O.local:8000/servos/0/settings

Misc routes

GET /

Returns the version of the firmware, in JSON format.

Response:

{
    "version": "0.0.0"
}

cURL example: curl -X GET http://roomctrl-0.local:8000/

GET /settings

Returns the current settings of the whole system.

By default, they are returned in JSON format, but the can be queried in raw format, which the reproduction of the file in which they ar persisted on the ESP32.

Query argument:

  • format : raw for getting the settings in raw format (anything else or omitting the argument will return them in JSON format

Response: JSON format:

{
    "rooms": {
        "1": {
            "door": {
                "pos_closed": 90,
                "pos_opened": 0,
                "servo": 0
            },
            "lid": {
                "pos_locked": 0,
                "pos_unlocked": 180,
                "servo": 1
            }
        },
        "2": {
            ...
        }
    },
    "servos": {
        "0": {
            "pos_max": 180,
            "pos_min": 0,
            "pulse_max": 2500,
            "pulse_min": 500
        },
        "1": {
            "pos_max": 180,
            "pos_min": 0,
            "pulse_max": 2500,
            "pulse_min": 500
        },
        ...
        "7": {
            "pos_max": 180,
            "pos_min": 0,
            "pulse_max": 2500,
            "pulse_min": 500
        }
    }
}

Raw format:

controller_id=0
server.port=8000
pwm_freq_compensation_dividor=0.943000
servos.0.pos_min=0
servos.0.pos_max=180
servos.0.pulse_min=500
servos.0.pulse_max=2500
servos.1.pos_min=0
servos.1.pos_max=180
...
servos.7.pulse_min=500
servos.7.pulse_max=2500
rooms.1.door.servo=0
rooms.1.door.pos_opened=0
rooms.1.door.pos_closed=90
rooms.1.lid.servo=1
rooms.1.lid.pos_unlocked=180
rooms.1.lid.pos_locked=15
rooms.2.door.servo=2
rooms.2.door.pos_opened=0
rooms.2.door.pos_closed=90
rooms.2.lid.servo=3
rooms.2.lid.pos_unlocked=180
rooms.2.lid.pos_locked=0

cURL example:

curl -X GET http://roomctrl-O.local:8000/settings

POST /pwm

Enables or disables the pulses generation for all the servos, and returns the new status for confirmation.

Body data:

  • action : enable or disable

Response:

{
    "is_enabled": 1
}

cURL example:

curl -X POST -d "action=enable" http://roomctrl-O.local:8000/pwm

GET /pwm

Returns the current status of the pulses generation.

Response:

{
    "is_enabled": 1
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/pwm

PUT /id

Changes the controller id, used to build the hostname with which it will be accessible.

The new hostname will be visible on next reboot of the controller.

Body data:

  • value : the new id

Response:

{
    "controller_id": "1"
}

cURL example:

curl -X PUT -d "value=1" http://roomctrl-O.local:8000/id

GET /id

Returns the current controller id.

Response:

{
    "controller_id": "1"
}

cURL example:

curl -X GET http://roomctrl-O.local:8000/id

POST /restart

Restarts the ESP32 by executing a soft reboot.

Response:

This request returns an empty response.

cURL example:

curl -X POST  http://roomctrl-O.local:8000/restart