Implementing Devices¶
All devices must implement some requirements to be able to be controlled by the app.
device.json¶
Each device shall be individually controllable. In order to achieve this the app needs to know which device has which options. These options have to be defined in the file device.json. The app will request and render the options when it is navigated to the send page of a selected device.
Options¶
All options which the device is able to control have to be inside the “options” array:
"options": []
Each option has to provide all of the following tags:
name¶
The name which will be displayed for each option in the app. It is freely choosable.
id¶
A unique identifier for each option. Make sure that there are no duplicates, it must be unique on device scope, otherwise there will be errors when sending instructions to the device. The value of the id has some restrictions, which are the same like the ones of html id attributes. Which means:
It must at least contain one character
It is case sensitive
There can be no white spaces
This id can later also be used to retrieve values from the device configuration inside the device application, for example to check the a configured maximum value.
type¶
A defined selection of possible input types. Which are:
values¶
All values which are available for the option must be inside a json object:
"values": {}
Note
The value is strongly dependent of the type of option. See the corresponding description.
Note
Except for File Up-/Download and Info, adding options to device.json needs them to be placed as parameter in device.execute
Optional Option Tags¶
In addition to the required tags above, each option may define the following optional tags:
refresh¶
"refresh": true
A boolean which defaults to false. When set to true, the app reloads the device information (and refreshes the dashboard layout, if the device supports one) after a successful send. For options of type file-upload, the reload is triggered after a successful upload instead.
The state of the input form is preserved during the reload where possible, i.e. values already entered by the user are kept for all options which still exist after the reload.
This is useful when executing an instruction changes the options of the device itself, for example when the available options depend on a mode which the user can switch.
Note
Independently of this tag, the send page also has a manual reload button which the user can press at any time to reload the device information.
API Version¶
"apiVersion": "v2"
The version of the device RPC API which the app uses when calling device.execute. Currently "v1" and "v2" are supported:
"v1"passes each option as its own parameter todevice.execute"v2"wraps all option values into a single parameter list of the form[{"input": {...}}]
See the API v2 section of the execute method for details on the resulting parameter structure.
Note
If this field is omitted, the default API version configured in the webapp is used
(see the device section of the frontend configuration, default "v2").
Dashboard¶
For a device to support the dashboard this option has to be set to true. It will be checked when registering a device. Make sure to implement the layout and the data for the dashboard on the device.
"dashboard_supported": true
Optionally, the height (in pixels) of the dashboard graph on the device’s send page can be set. It defaults to a larger value if omitted and only affects the send page - the device cards on the home page are not changed.
"dashboard_height": 650
RPC API¶
Our devices implement a json RPC API. Ping and Info are already implemented by the skeleton, the remaining methods have to be implemented by you in api/device/methods.py:
File Up and Download¶
The devices provide two endpoints over which some file exchange can happen. These endpoints can be used for example to download, recording data or to upload a file with a set of instructions for the device.
Hardware Communication¶
You will need to implement all communication to your hardware inside the hardware directory. Make sure to import all functionality which you want to have available in api/device/methods.py in the file hardware/__init__.py. Everything inside this file will be imported there.
When you need to install additional libraries or dependencies make sure to install them in the virtual environment using pip. When you are finished write them into the requirements.txt with
pip freeze > requirements.txt
For the hardware implementation it is suggested that you to use a folder structure like this:
rpc_api
├── api
│ └── ...
├── hardware
│ ├── HARWARE_OPTION_1
| | ├── __init__.py
| | ├── config.py
| | ├── hardware_option_1.py
│ | └── ... optional helper files ...
│ ├── HARWARE_OPTION_2
| | ├── __init__.py
| | ├── config.py
| | ├── hardware_option_2.py
│ | └── ... optional helper files ...
│ └── __init__.py
└── ...
Which may then look something like this:
rpc_api
├── api
│ └── ...
├── hardware
│ ├── parker_compax_3s // hw package to communicate with a frequency converter via a serial
| | ├── __init__.py
| | ├── config.py
| | ├── compax3s.py
| | ├── exceptions.py
│ | └── serial.py
│ ├── sensors // hw package to read sensor data and provide them for a graph on the user interface
| | ├── __init__.py
| | ├── config.py
| | ├── graph.py
│ | └── sensors.py
│ └── __init__.py
└── ...
However, you are free on how your structure will look.