You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
10 KiB
300 lines
10 KiB
3 months ago
|
|
||
|
# Control
|
||
|
|
||
|
Controls are commands from a client to the server, e.g. start streaming, set option value etc...
|
||
|
|
||
|
|
||
|
## Replies
|
||
|
|
||
|
All control messages need to be re-broadcast with a result, for other clients to be notified and made aware. The [notifications](notifications.md) topic is used for this.
|
||
|
|
||
|
When a control is sent, some way to identify a reply to that specific control must exist:
|
||
|
|
||
|
- Replies will have the same `id` as the original control. This means **controls and notifications must have separate identifiers**
|
||
|
- The `id` may be retrieved from the attached `control` (see below) if available with `sample`
|
||
|
|
||
|
Additionally, when the server gets a control message, the DDS sample will contain a "publication handle". This is the `GUID` of the writer (including the participant) to identify the control source. A unique sequence number for each control sample is available from the `sample-identity`. Without these, it is impossible to identify the origin of the control and therefore, whether we're waiting on it or not.
|
||
|
|
||
|
- Replies must contain a `sample` field containing the GUID of the participant from which the control request originated, plus the sequence-number, e.g.: `"sample": ["010f6ad8708c95e000000000.303",4]`
|
||
|
|
||
|
Replies must also include a success/failure status:
|
||
|
|
||
|
- Replies will include a `status` for anything other than `OK`
|
||
|
- Replies will include an `explanation` if status is not `OK`
|
||
|
|
||
|
It is recommended that replies also contain the original control request:
|
||
|
|
||
|
- A `control` field in the reply should contain the original control request, though some freedom exists depending on each control
|
||
|
|
||
|
Replies must function even in recovery mode.
|
||
|
|
||
|
|
||
|
### Errors
|
||
|
|
||
|
An error is a reply where the `status` is not OK:
|
||
|
|
||
|
- the `explanation` is a human-readable string explaining the failure (like an exception's `what`)
|
||
|
|
||
|
```JSON
|
||
|
{
|
||
|
"control": {
|
||
|
"id": "query-option",
|
||
|
"option-name": "opt16"
|
||
|
},
|
||
|
"sample": ["010f9a5f64d95fd300000000.403", 1],
|
||
|
"status": "error",
|
||
|
"explanation": "Test Device does not support option opt16"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
|
||
|
### Combining Multiple Controls
|
||
|
|
||
|
Unlike [notifications](notifications.md), this is not possible.
|
||
|
|
||
|
|
||
|
## Control Messages
|
||
|
|
||
|
|
||
|
### `query-option` & `set-option`
|
||
|
|
||
|
Returns or sets the `value` of a single option within the device.
|
||
|
|
||
|
- `id` is `query-option` or `set-option`
|
||
|
- `option-name` is the option name, a string value
|
||
|
- `stream-name` is the name of the stream the option is in
|
||
|
- For device options, this should be omitted
|
||
|
- for `set-option`, a `value` supplies the value to set
|
||
|
- Note: the reply may provide a different value that was actually set
|
||
|
|
||
|
E.g.:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "query-option",
|
||
|
"option-name": "IP address"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The reply should include the original control plus a `value`:
|
||
|
```JSON
|
||
|
{
|
||
|
"sample": ["010f9a5f64d95fd300000000.403", 1],
|
||
|
"value": "1.2.3.4",
|
||
|
"control": {
|
||
|
"id": "query-option",
|
||
|
"option-name": "IP address"
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The same exact behavior for `set-option` except a `value` is provided in the control:
|
||
|
```JSON
|
||
|
{
|
||
|
"sample": ["010f9a5f64d95fd300000000.403", 1],
|
||
|
"value": 10.0,
|
||
|
"control": {
|
||
|
"id": "set-option",
|
||
|
"stream-name": "Color",
|
||
|
"option-name": "Exposure",
|
||
|
"value": 10.5
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
New option values should conform to each specific option's value range as communicated when the device was [initialized](initialization.md).
|
||
|
|
||
|
|
||
|
### `query-options`: bulk queries
|
||
|
|
||
|
Like `query-option`, but asking for all option values at once, based on either stream, sensor, or device.
|
||
|
|
||
|
- For stream-specific options, use `stream-name`
|
||
|
- For device-specific options, use `"stream-name": ""`
|
||
|
- For sensor-specific options, use `sensor-name`
|
||
|
- To globally get ALL options for all streams including device options, use neither
|
||
|
|
||
|
E.g.:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "query-options",
|
||
|
"stream-name": "Color"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
A stream-name-to-option-name-to-value mapping called `option-values` is returned:
|
||
|
```JSON
|
||
|
{
|
||
|
"sample": ["010f9a5f64d95fd300000000.403", 1],
|
||
|
"option-values": {
|
||
|
"IP address": "1.2.3.4",
|
||
|
"Color": {
|
||
|
"Exposure": 10.0,
|
||
|
"Gain": 5
|
||
|
},
|
||
|
"Depth": {
|
||
|
"Exposure": 15.0
|
||
|
}
|
||
|
},
|
||
|
"control": {
|
||
|
"id": "query-options"
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
Device options are directly embedded in `option-values`; stream options are in hierarchies of their own.
|
||
|
|
||
|
#### periodic updates
|
||
|
|
||
|
Option values that are changed *by the server* (without a control message) are expected to send `query-options` notifications with no `control` or `sample` fields:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "query-options",
|
||
|
"option-values": {
|
||
|
"Color": {
|
||
|
"Exposure": 8.0,
|
||
|
},
|
||
|
"Depth": {
|
||
|
"Exposure": 20.0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
It is recommended this happens at least periodically (based on possible configuration setting?) to avoid the clients all having to query the device repeatedly.
|
||
|
|
||
|
|
||
|
### `hw-reset`
|
||
|
|
||
|
Can be used to cause the server to perform a "hardware reset", if available, bringing it back to the same state as after power-up.
|
||
|
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "hw-reset"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
* If boolean `recovery` is set, then the device will reset to recovery mode (error if this is not possible)
|
||
|
|
||
|
A reply can be expected.
|
||
|
|
||
|
A [disconnection event](discovery.md#disconnection) can be expected if the reply is a success.
|
||
|
|
||
|
|
||
|
### `hwm`
|
||
|
|
||
|
Can be used to send internal commands to the hardware and may brick the device if used. May or may not be implemented, and is not documented.
|
||
|
|
||
|
* `data` is required
|
||
|
|
||
|
It is up to the server to validate and make sure everything is as expected.
|
||
|
|
||
|
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "hwm",
|
||
|
"data": "1400abcd1000000000000000000000000000000000000000"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The above is a `GVD` HWM command.
|
||
|
|
||
|
A reply can be expected. Attaching the control is recommended so it's clear what was done. The reply `data` should be preset:
|
||
|
|
||
|
```JSON
|
||
|
{
|
||
|
"sample": ["010f9a5f64d95fd300000000.403", 1],
|
||
|
"control": {
|
||
|
"id": "hwm",
|
||
|
"data": "1400abcd1000000000000000000000000000000000000000"
|
||
|
},
|
||
|
"data": "10000000011004000e01ffffff01010102000f05000000000000000064006b0000001530ffffffffffffffffffffffffffffffff0365220706600000ffff3935343031300094230500730000ffffffffffffffff0aff3939394146509281a1ffffffffffffffffff9281a1ffffffffffffffffffffffffffffffffffffffffff1f0fffffffffffffffff000027405845ffffffffffffffff908907ffffff01ffffff050aff00260000000200000001000000010000000100000001000000000600010001000100030303020200000000000100070001ffffffffffffffffffffffffffffffffffff014a34323038362d31303001550400ae810100c50004006441050011d00000388401002e0000002dc00000ff"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
#### A more verbose method
|
||
|
|
||
|
You may also instruct the server to **build the HWM** command if you have knowledge of the available opcodes and data needed:
|
||
|
|
||
|
* `opcode` (string) is required
|
||
|
* `param1`, `param2`, `param3`, `param4` are all 32-bit integers whose meaning depends on the `opcode`, and with a default of `0`
|
||
|
* The `data` field, in this case, points to the command data, if needed, and becomes part of the generated HWM
|
||
|
|
||
|
If an optional `build-command` field is present and `true`, then the reply `data` will contain the generated HWM command **without running it**.
|
||
|
|
||
|
|
||
|
#### `hexarray` type
|
||
|
|
||
|
A `hexarray` is a special encoding for a `bytearray`, or array of bytes, in JSON.
|
||
|
|
||
|
Rather than representing as `[0,100,2,255]`, a `hexarray` is instead represented as a string `"006402ff"` which is a hexadecimal representation of all the consecutive bytes, from index 0 onwards.
|
||
|
|
||
|
* Only lower-case alphabetical letters are used (`[0-9a-f]`)
|
||
|
* The length must be even (2 hex digits per byte)
|
||
|
* The first hex pair is for the first byte, the second hex pair for the second, onwards
|
||
|
|
||
|
|
||
|
### DFU
|
||
|
|
||
|
**D**evice **F**irmware **U**pdate is the mechanism with which the device can have its firmware updated.
|
||
|
|
||
|
A device can run the flow when in recovery mode or during normal operation:
|
||
|
* `dfu-start` starts the DFU process
|
||
|
* The client will then publish the binary image over the `dfu` topic
|
||
|
* Once the image is verified, the device will send back a notification, `dfu-ready`
|
||
|
* When ready, a client can then send a `dfu-apply`
|
||
|
|
||
|
#### `dfu-start`
|
||
|
|
||
|
Starts the DFU process.
|
||
|
|
||
|
The device will subscribe to a `dfu` topic under the topic root (accepting a `blob` message, reliable). Enough memory should be allocated to make sure we're ready to receive the image before a reply is sent.
|
||
|
|
||
|
A reply should indicate the image is ready to be received.
|
||
|
|
||
|
#### `dfu-ready`
|
||
|
|
||
|
The device will wait a certain amount of time for an image to be received. It may error out with a timeout.
|
||
|
|
||
|
Only one image can be received, and it should be from the same participant that initiated the DFU.
|
||
|
|
||
|
The image, once received, will be checked for compatibility. If incompatible, incomplete, missing, etc. -- an error will be sent to the client.
|
||
|
|
||
|
Errors can look like this:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "dfu-ready",
|
||
|
"status": "error",
|
||
|
"explanation": "incompatible FW version (5.17.0.1)"
|
||
|
}
|
||
|
```
|
||
|
If status is not `OK`, then the device is expected to go back to the pre-DFU state and the process needs to start over.
|
||
|
|
||
|
On success, the device may send back a `"crc": <crc32-value>` or `"size": <number-of-bytes>`, to help debug, or any other relevant content:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "dfu-ready",
|
||
|
"crc": <value>
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The `dfu` subscription can be removed at this time.
|
||
|
|
||
|
#### `dfu-apply`
|
||
|
|
||
|
When all the above is successful and the client is ready, a `dfu-apply` is sent to the device.
|
||
|
If for any reason the DFU should be cancelled, the same message is sent but a `"cancel": true` should be present.
|
||
|
In any case, the device needs to reply right away, **before** the DFU is actually applied!
|
||
|
|
||
|
The device then takes whatever time is needed to have the image take effect. Progress notifications are recommended and take the same form as the reply:
|
||
|
```JSON
|
||
|
{
|
||
|
"id": "dfu-apply",
|
||
|
"progress": 0.2
|
||
|
}
|
||
|
```
|
||
|
|
||
|
At any time, the process may error out. The device is expected to reset itself and the process would have to start over.
|
||
|
|
||
|
On successful application of the image, the device shall perform a hardware-reset and come back up normally.
|
||
|
Before any restart, the device will send a disconnection event on `device-info`.
|
||
|
The disconnection is the signal to the client that the DFU is over.
|
||
|
|