v3 API Reference
Synse Server provides an interface to physical and virtual devices through an HTTP or WebSocket API. Both APIs expose the same information, with only a few changes to the expected response data framing.
HTTP API¶
In the API Reference section below, each item describes the URI and method(s) for the endpoint, as well as the expected response data on success, and possible error codes on failure.
Within this document:
localhost:5000
,${server}
, and other references to the hostname/IP and port of the Synse Server instance are all functionally equivalent and serve only as a placeholder which should be replaced with your instance's IP/port.- The examples provided for each item use the Synse Python Client for the Python examples.
- All specified URI parameters are required.
- All specified query parameters are optional.
Requests¶
Each route defines the basic endpoint information in a table which looks like:
HTTP | GET | /test |
This says that for the HTTP API, issue a GET request against the /test
URI. Given a Synse Server
instance running at localhost:5000
, this would translate to
GET http://localhost:5000/test
Responses¶
Each route also defines a Response Data section, which describes the JSON payload that is returned on success. For the HTTP API, this is the exact data that is returned (no additional formatting is done).
WebSocket API¶
You can connect to the WebSocket API via:
ws://${server}/v3/connect
where ${server}
is the hostname[:port] of the Synse Server instance.
In the API Reference section below, each item describes the event of the request for the WebSocket API. Both client requests and server responses use the same message format:
{
"id": 0,
"event": "request/status",
"data": {}
}
The fields of the request structure are described below:
Field | Type | Description |
---|---|---|
id | int |
The numeric ID of the message. Each client session should track and increment its own IDs. The server reflects this ID in the response message(s). This can be used for matching responses with their originating requests. |
event | string |
The type of message that is being sent. All client requests are prefixed with request/ . All server responses are prefixed with response/ . |
data | object |
The data being sent. For requests, this will include the equivalent of URI parameters and query parameters. If a given event does not have any such parameters, this can be left empty ("data": {} ) or omitted entirely. For responses, this will hold the server response data -- this is equivalent to the response you would get from the HTTP API, as defined in the Response Data section. |
Errors are returned with response/error
. If an error occurs prior to the request
being parsed (or due to an invalid request which cannot be parsed), the return ID will be -1
.
Within this document:
- The contents of the
data
field for a given request are not explicitly called out. They are instead implied from the HTTP URI parameters (required) and query parameters (optional). The names of the parameters correspond to their keys in thedata
field. - One exception to the above is for writes - POSTed data is specified via the
payload
key.
Requests¶
Each item defines the basic event information in a table which looks like:
WebSocket | request | "request/status" |
response | "response/status" |
This says that for the WebSocket API, issue a status request using the request/status
event.
This would translate into the message:
{
"id": 0,
"event": "request/status"
}
Responses¶
Responses use the same message scheme, where:
- the response
id
is the request ID reflected back - the
event
is the corresponding response event for the given request type - the
data
contains the JSON data defined in the Response Data section
A table of all request-response event mappings follows. Note that all requests may have an error response.
Request | Response |
---|---|
request/status |
response/status |
request/version |
response/version |
request/config |
response/config |
request/plugin |
response/plugin_info |
request/plugins |
response/plugin_summary |
request/plugin_health |
response/plugin_health |
request/scan |
response/device_summary |
request/tags |
response/tags |
request/info |
response/device_info |
request/read |
response/reading |
request/read_device |
response/reading |
request/read_cache |
response/reading |
request/read_stream |
response/reading |
request/write_async |
response/transaction_info |
request/write_sync |
response/transaction_status |
request/transaction |
response/transaction_status |
request/transactions |
response/transaction_list |
Reference¶
Errors¶
Most errors returned from Synse Server will come back with a JSON payload in order to provide additional context for the error. Some errors will not return a JSON payload; this class of error is generally due to the application not being ready, available, or reachable.
HTTP Codes¶
An error response will be returned with one of the following HTTP codes:
- 400: Invalid user input. This can range from invalid POSTed JSON, unsupported query parameters being used, or invalid resource types.
- 404: The specified resource was not found.
- 405: Action not supported for device (read/write).
- 500: Server side processing error.
Response Data¶
{
"http_code": 404,
"description": "resource not found",
"timestamp": "2019-01-01T12:00:00Z",
"context": "transaction not found: f041883c-cf87-55d7-a978-3d3103836412"
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
http_code | int |
The HTTP code corresponding to the error. (e.g. 400, 404, 500) |
description | string |
A short description of the error. |
timestamp | string |
The RFC3339 formatted timestamp at which the error occurred. |
context | string |
Contextual message associated with the error's root cause. This will typically include the pertinent internal state. |
HTTP
Request
GET http://localhost:5000/v3/transaction/f041883c-cf87-55d7-a978-3d3103836412
Response
{
"http_code": 404,
"description": "resource not found",
"timestamp": "2019-01-01T12:00:00Z",
"context": "transaction not found: f041883c-cf87-55d7-a978-3d3103836412"
}
WebSocket
Request
{
"id": 0,
"event": "request/transaction",
"data": {
"transaction": "f041883c-cf87-55d7-a978-3d3103836412"
}
}
Response
{
"id": 0,
"event": "response/error",
"data": {
"http_code": 404,
"description": "resource not found",
"timestamp": "2019-01-01T12:00:00Z",
"context": "transaction not found: f041883c-cf87-55d7-a978-3d3103836412"
}
}
Test¶
HTTP | GET | /test |
WebSocket | request | "request/status" |
response | "response/status" |
Check whether the server is reachable and responsive.
If the endpoint is reachable (e.g. if Synse Server is up and ready), this will return a 200 response. If the test endpoint is unreachable or otherwise fails, it will return a 500 response, typically with no JSON payload.
Example
shell
curl http://${server}:5000/test
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.status()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Response Data¶
{
"status": "ok",
"timestamp": "2020-01-01T12:00:00Z"
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
status | string |
"ok" if the endpoint returns successfully. |
timestamp | string |
An RFC3339 timestamp of when the status was tested. |
HTTP
Request
GET http://localhost:5000/test
Response
{
"status": "ok",
"timestamp": "2020-01-01T12:00:00Z"
}
WebSocket
Request
{
"id": 0,
"event": "request/status"
}
Response
{
"id": 0,
"event": "response/status",
"data": {
"status": "ok",
"timestamp": "2020-01-01T12:00:00Z"
}
}
Error¶
- 500 - No JSON: route not reachable/service not ready
Version¶
HTTP | GET | /version |
WebSocket | request | "request/version" |
response | "response/version" |
Get the version info of the Synse Server instance. The API version provided by this endpoint should be used in subsequent requests.
Example
shell
curl http://${server}:5000/version
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.version()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Response Data¶
{
"version": "3.0.0",
"api_version": "v3"
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
version | string |
The full version (<major.minor.micro>) of the Synse Server instance. |
api_version | string |
The API version (v<major>) that can be used to construct subsequent API requests. |
HTTP
Request
GET http://localhost:5000/version
Response
{
"version": "3.0.0",
"api_version": "v3"
}
WebSocket
Request
{
"id": 0,
"event": "request/version"
}
Response
{
"id": 0,
"event": "response/version",
"data": {
"version": "3.0.0",
"api_version": "v3"
}
}
Error¶
- 500 - No JSON: route not reachable/service not ready
Config¶
HTTP | GET | /v3/config |
WebSocket | request | "request/config" |
response | "response/config" |
Get a the unified configuration of the Synse Server instance.
This endpoint is added as a convenience to make it easier to determine what configuration the server instance is running with. The Synse Server configuration is made up of default, file, environment, and override config components. This endpoint provides the final joined configuration which Synse Server ultimately runs with.
Example
shell
curl http://${server}:5000/v3/config
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.config()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Response Data¶
The response JSON will match the configuration scheme. See: Config.
Error¶
The error response can be one of:
- 500 - Catchall processing error
Plugin Info¶
HTTP | GET | /v3/plugin/<plugin> |
WebSocket | request | "request/plugin" |
response | "response/plugin_info" |
Get detailed information about the specified plugin.
If a plugin has registered with Synse Server and is communicating successfully, it will be marked as "active". If registration or communication fail, it will be marked as "inactive".
You can get a summary of all currently registered plugins via Plugins.
Example
shell
curl http://${server}:5000/v3/plugin/4032ffbe-80db-5aa5-b794-f35c88dff85c
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.plugin('4032ffbe-80db-5aa5-b794-f35c88dff85c')
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
plugin | The ID of the plugin to get more information for. Plugin IDs can be enumerated via the /plugin endpoint without specifying a URI parameter. |
Response Data¶
{
"name": "emulator plugin",
"maintainer": "vaporio",
"tag": "vaporio/emulator-plugin",
"description": "A plugin with emulated devices and data",
"vcs": "github.com/vapor-ware/synse-emulator-plugin",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true,
"network": {
"address": "emulator:5001",
"protocol": "tcp"
},
"version": {
"plugin_version": "3.0.0",
"sdk_version": "2.0.0",
"build_date": "2020-01-01T12:00:00Z",
"git_commit": "00d612b",
"git_tag": "3.0.0",
"arch": "amd64",
"os": "linux"
},
"health": {
"timestamp": "2020-01-01T12:00:00Z",
"status": "OK",
"checks": [
{
"name": "read queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
},
{
"name": "write queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
}
]
}
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
active | bool |
This field specifies whether the plugin is active or not. |
id | string |
A deterministic ID hash for identifying the plugin. |
tag | string |
The plugin tag. This is a normalized string made up of its name and maintainer. |
name | string |
The name of plugin. |
maintainer | string |
The maintainer of the plugin. |
description | string |
A short description of the plugin. |
vcs | string |
A link to the version control repo for the plugin. |
version | object |
An object which contains version information about the plugin. |
version.plugin_version | string |
The plugin version. |
version.sdk_version | string |
The version of the Synse SDK that the plugin is using. |
version.build_date | string |
The date that the plugin was built. |
version.git_commit | string |
The git commit at which the plugin was built. |
version.git_tag | string |
The git tag at which the plugin was built. |
version.arch | string |
The architecture that the plugin is built for. |
version.os | string |
The OS that the plugin is built for. |
network | object |
An object which describes the network configurations for the plugin. |
network.address | string |
The address of the plugin for the protocol used. |
network.protocol | string |
The protocol that is used to communicate with the plugin (unix, tcp). |
health | object |
An object which describes the overall health of the plugin. |
health.timestamp | string |
The time at which the health status applies. |
health.status | string |
The health status of the plugin (unknown, ok, failing) |
health.checks | list |
A collection of health check snapshots for the plugin. |
There may be 0..N
health checks for a Plugin, depending on how it is configured.
The health check elements here make up a snapshot of the plugin's health at a given time.
Field | Type | Description |
---|---|---|
name | string |
The name of the health check. |
status | string |
The status of the health check (unknown, ok, failing) |
message | string |
A message describing the failure, if in a failing state. |
timestamp | string |
An RFC3339 timestamp for when the status applied. |
type | string |
The type of health check (e.g. periodic) |
HTTP
Request
GET http://localhost:5000/v3/plugin/4032ffbe-80db-5aa5-b794-f35c88dff85c
Response
{
"name": "emulator plugin",
"maintainer": "vaporio",
"tag": "vaporio/emulator-plugin",
"description": "A plugin with emulated devices and data",
"vcs": "github.com/vapor-ware/synse-emulator-plugin",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true,
"network": {
"address": "emulator:5001",
"protocol": "tcp"
},
"version": {
"plugin_version": "3.0.0",
"sdk_version": "2.0.0",
"build_date": "2020-01-01T12:00:00Z",
"git_commit": "00d612b",
"git_tag": "3.0.0",
"arch": "amd64",
"os": "linux"
},
"health": {
"timestamp": "2020-01-01T12:00:00Z",
"status": "OK",
"checks": [
{
"name": "read queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
},
{
"name": "write queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
}
]
}
}
WebSocket
Request
{
"id": 0,
"event": "request/plugin",
"data": {
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c"
}
}
Response
{
"id": 0,
"event": "response/plugin_info",
"data": {
"name": "emulator plugin",
"maintainer": "vaporio",
"tag": "vaporio/emulator-plugin",
"description": "A plugin with emulated devices and data",
"vcs": "github.com/vapor-ware/synse-emulator-plugin",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true,
"network": {
"address": "emulator:5001",
"protocol": "tcp"
},
"version": {
"plugin_version": "3.0.0",
"sdk_version": "2.0.0",
"build_date": "2020-01-01T12:00:00Z",
"git_commit": "00d612b",
"git_tag": "3.0.0",
"arch": "amd64",
"os": "linux"
},
"health": {
"timestamp": "2020-01-01T12:00:00Z",
"status": "OK",
"checks": [
{
"name": "read queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
},
{
"name": "write queue health",
"status": "OK",
"type": "periodic",
"message": "",
"timestamp": "2020-01-01T12:00:00Z"
}
]
}
}
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 404 - Plugin not found
Plugins¶
HTTP | GET | /v3/plugin |
WebSocket | request | "request/plugins" |
response | "response/plugin_summary" |
Get a summary of all plugins currently registered with the server instance.
Example
shell
curl http://${server}:5000/v3/plugin
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.plugins()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Info
There is no guarantee that all plugins are represented in the returned list if the server is configured to use plugin discovery. When discovering plugins, a plugin can only be registered when it makes itself available to the server. Depending on the plugin and any setup actions, this may take longer for some plugins than others.
Query Parameters¶
Key | Description |
---|---|
refresh | Set to true to force a refresh of plugins. Plugins are refreshed in the background periodically, this allows it to be done on demand. (default: false) |
Response Data¶
[
{
"name": "emulator plugin",
"maintainer": "vapor io",
"tag": "vaporio/emulator-plugin",
"description": "a plugin with emulated devices and data",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true
},
{
"name": "custom-plugin",
"maintainer": "third-party",
"tag": "third-party/custom-plugin",
"description": "a custom third party plugin",
"id": "3042ffce-81db-5bb6-b794-f35c88dff85d",
"active": true
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
active | bool |
This field specifies whether the plugin is active or not. |
id | string |
A deterministic ID hash for identifying the plugin. |
tag | string |
The plugin tag. This is a normalized string made up of its name and maintainer. |
name | string |
The name of plugin. |
maintainer | string |
The maintainer of the plugin. |
description | string |
A short description of the plugin. |
HTTP
Request
GET http://localhost:5000/v3/plugin
Response
[
{
"name": "emulator plugin",
"maintainer": "vapor io",
"tag": "vaporio/emulator-plugin",
"description": "a plugin with emulated devices and data",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true
},
{
"name": "custom-plugin",
"maintainer": "third-party",
"tag": "third-party/custom-plugin",
"description": "a custom third party plugin",
"id": "3042ffce-81db-5bb6-b794-f35c88dff85d",
"active": true
}
]
WebSocket
Request
{
"id": 0,
"event": "request/plugins"
}
Response
{
"id": 0,
"event": "response/plugin_summary",
"data": [
{
"name": "emulator plugin",
"maintainer": "vapor io",
"tag": "vaporio/emulator-plugin",
"description": "a plugin with emulated devices and data",
"id": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"active": true
},
{
"name": "custom-plugin",
"maintainer": "third-party",
"tag": "third-party/custom-plugin",
"description": "a custom third party plugin",
"id": "3042ffce-81db-5bb6-b794-f35c88dff85d",
"active": true
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
Plugin Health¶
HTTP | GET | /v3/plugin/health |
WebSocket | request | "request/plugin_health" |
response | "response/plugin_health" |
Get a summary of the health of registered plugins.
This provides an easy way to programmatically determine whether the registered plugins are considered healthy by the server.
Example
shell
curl http://${server}:5000/v3/plugin/health
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.plugin_health()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Response Data¶
{
"status": "healthy",
"updated": "2020-01-01T12:00:00Z",
"healthy": [
"4032ffbe-80db-5aa5-b794-f35c88dff85c",
"3042ffce-81db-5bb6-b794-f35c88dff85d"
],
"unhealthy": [],
"active": 2,
"inactive": 0
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
status | string |
A string describing the overall health state of the registered plugins. This can be either "healthy" or "unhealthy" . It will only be healthy if all plugins are found to be healthy, otherwise the overall state is unhealthy. |
updated | string |
An RFC3339 timestamp describing the time that the plugin health state was last updated. |
healthy | list[string] |
A list containing the plugin IDs for those plugins deemed to be healthy. |
unhealthy | list[string] |
A list containing the plugin IDs for those plugins deemed to be unhealthy. |
active | int |
The count of active plugins. |
inactive | int |
The count of inactive plugins. |
HTTP
Request
GET http://localhost:5000/v3/plugin/health
Response
{
"status": "healthy",
"updated": "2020-01-01T12:00:00Z",
"healthy": [
"4032ffbe-80db-5aa5-b794-f35c88dff85c",
"3042ffce-81db-5bb6-b794-f35c88dff85d"
],
"unhealthy": [],
"active": 2,
"inactive": 0
}
WebSocket
Request
{
"id": 0,
"event": "request/plugin_health"
}
Response
{
"id": 0,
"event": "response/plugin_health",
"data": {
"status": "healthy",
"updated": "2020-01-01T12:00:00Z",
"healthy": [
"4032ffbe-80db-5aa5-b794-f35c88dff85c",
"3042ffce-81db-5bb6-b794-f35c88dff85d"
],
"unhealthy": [],
"active": 2,
"inactive": 0
}
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
Scan¶
HTTP | GET | /v3/scan |
WebSocket | request | "request/scan" |
response | "response/device_summary" |
List the devices that Synse knows about and can read from/write to via the registered plugins.
This endpoint provides an aggregated view of the devices made known to the server by each of its registered plugins. It provides a high-level view of what exists in the system. Scan info can be filtered to show only those devices which match a set of provided tags.
By default, scan results are sorted by device id. The sort
query parameter
may be used to modify the sort behavior.
Example
shell
curl http://${server}:5000/v3/scan
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.scan()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Query Parameters¶
Key | Description |
---|---|
ns | The default namespace to use for the specified labels. (default: default ) |
tags | The tags to filter devices by. Multiple tag groups may be specified by providing the tags query parameter multiple times, e.g. ?tags=foo&tags=bar . Each tag group may consist of one or more comma-separated tags. Each tag group only selects devices which match all of the tags in the group. If multiple tag groups are specified, the result is the union of the matches from each individual tag group. |
force | Force a re-scan. This will take longer than scanning using the cache, since it needs to rebuild the cache. (default: false) |
sort | Specify the fields to sort by. Multiple fields can be specified as a comma separated string, e.g. "plugin,id" . The "tags" field can not be used for sorting. (default: "plugin,sort_index,id", where the sort_index is an internal sort preference which a plugin can optionally specify.) |
Response Data¶
[
{
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"alias": "",
"info": "Synse Temperature Sensor 1",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"metadata": {}
},
{
"id": "f041883c-cf87-55d7-a978-3d3103836412",
"alias": "emulator-led",
"info": "Synse LED",
"type": "led",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:f041883c-cf87-55d7-a978-3d3103836412",
"system/type:led"
],
"metadata": {}
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
id | string |
The globally unique deterministic ID for the device. |
alias | string |
A human-readable name for the device. |
info | string |
A human-readable string providing identifying info about a device. |
type | string |
The type of the device. |
plugin | string |
The ID of the plugin which the device is managed by. |
tags | list[string] |
A list of the tags associated with this device. One of the tags will be the id tag. |
metadata | object |
Any metadata or contextual information configured with the device. The data stored here are arbitrary keys and values. |
HTTP
Request
GET http://localhost:5000/v3/scan
Response
[
{
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"alias": "",
"info": "Synse Temperature Sensor 1",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"metadata": {}
},
{
"id": "f041883c-cf87-55d7-a978-3d3103836412",
"alias": "emulator-led",
"info": "Synse LED",
"type": "led",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:f041883c-cf87-55d7-a978-3d3103836412",
"system/type:led"
],
"metadata": {}
}
]
WebSocket
Request
{
"id": 0,
"event": "request/scan"
}
Response
{
"id": 0,
"event": "response/device_summary",
"data": [
{
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"alias": "",
"info": "Synse Temperature Sensor 1",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"metadata": {}
},
{
"id": "f041883c-cf87-55d7-a978-3d3103836412",
"alias": "emulator-led",
"info": "Synse LED",
"type": "led",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"tags": [
"system/id:f041883c-cf87-55d7-a978-3d3103836412",
"system/type:led"
],
"metadata": {}
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid parameter(s)
Tags¶
HTTP | GET | /v3/tags |
WebSocket | request | "request/tags" |
response | "response/tags" |
List all of the tags currently associated with devices.
This will list the tags in the specified tag namespace. If no tag namespace is specified (via query parameters), the default tag namespace is used.
By default, this endpoint will omit the id
tags since they match the
device id enumerated by the scan
endpoint. The id
tags may
be included in the response by setting the ids
query parameter to true
.
Multiple tag namespaces may be queried at once by using a comma delimiter
between namespaces in the ns
query parameter value, e.g.
?ns=default,ns1,ns2
.
Tags are sorted alphanumerically.
Example
shell
curl http://${server}:5000/v3/tags
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.tags()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Query Parameters¶
Key | Description |
---|---|
ns | The tag namespace(s) to use when searching for tags. (default: default ) |
ids | A flag which determines whether id tags are included in the response. (default: false ) |
Response Data¶
[
"system/type:airflow",
"system/type:fan",
"system/type:humidity",
"system/type:led",
"system/type:lock",
"system/type:pressure",
"system/type:temperature"
]
HTTP
Request
GET http://localhost:5000/v3/tags
Response
[
"system/type:airflow",
"system/type:fan",
"system/type:humidity",
"system/type:led",
"system/type:lock",
"system/type:pressure",
"system/type:temperature"
]
WebSocket
Request
{
"id": 0,
"event": "request/tags"
}
Response
{
"id": 0,
"event": "response/tags",
"data": [
"system/type:airflow",
"system/type:fan",
"system/type:humidity",
"system/type:led",
"system/type:lock",
"system/type:pressure",
"system/type:temperature"
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid parameter(s)
Info¶
HTTP | GET | /v3/info/<device> |
WebSocket | request | "request/info" |
response | "response/device_info" |
Get the full set of metadata and capabilities for a specified device.
Example
shell
curl http://${server}:5000/v3/info/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.info('c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07')
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
device | The globally unique deterministic ID or alias of the device to get info for. |
Response Data¶
{
"timestamp": "2020-01-01T12:00:00Z",
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"alias": "",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"info": "Synse Temperature Sensor 1",
"sort_index": 0,
"metadata": {
"model":"emul8-temp"
},
"capabilities": {
"mode": "rw",
"write": {
"actions": []
}
},
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"outputs": [
{
"name": "temperature",
"type": "temperature",
"precision": 2,
"scalingFactor": 0.0,
"unit": {
"name": "celsius",
"symbol": "C"
}
}
]
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
timestamp | string |
An RFC3339 timestamp describing the time that the device info was gathered. |
id | string |
The globally unique ID for the device. |
alias | string |
A human-readable name for the device. |
type | string |
The device type. |
plugin | string |
The ID of the plugin that manages the device. |
info | string |
A human-readable string providing identifying info about a device. |
sort_index | int |
The custom sort index specified for the device by the plugin. The default value of 0 indicates no special sorting. |
metadata | object |
A map of arbitrary values that provide additional data for the device. |
capabilities | object |
Specifies the actions which the device is able to perform (e.g. for writes). |
tags | list[string] |
A list of the tags associated with this device. One of the tags will be the 'id' tag which should match the id field. |
outputs | list[object] |
A list of the output types that the device supports. |
Capabilities¶
Field | Type | Description |
---|---|---|
mode | string |
A string specifying the device capabilities. This can be "r" (read only), "rw" (read write), "w" (write only). |
write | object |
Any additional information regarding device writes. |
write.actions | list[string] |
A list of actions which the device supports for writing. |
Outputs¶
Field | Type | Description |
---|---|---|
name | string |
The name of the output type. |
type | string |
The type of the output. |
precision | int |
The number of decimal places the value will be rounded to. |
scalingFactor | float |
A scaling factor which is applied to readings using the output. The default factor of 0 indicates no scaling factor applied. |
unit | object |
Information for the reading's units of measure. |
unit.name | string |
The complete name of the unit of measure (e.g. "meters per second"). |
unit.symbol | string |
A symbolic representation of the unit of measure (e.g. "m/s"). |
HTTP
Request
GET http://localhost:5000/v3/info/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
Response
{
"timestamp": "2020-01-01T12:00:00Z",
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"info": "Synse Temperature Sensor 4",
"alias": "",
"sort_index": 0,
"metadata": {
"model": "emul8-temp"
},
"capabilities": {
"mode": "rw",
"write": {
"actions": []
}
},
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"outputs": [
{
"name": "temperature",
"type": "temperature",
"precision": 2,
"scalingFactor": 0.0,
"unit": {
"name": "celsius",
"symbol": "C"
}
}
]
}
WebSocket
Request
{
"id": 0,
"event": "request/info",
"data": {
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07"
}
}
Response
{
"id": 0,
"event": "response/device_info",
"data": {
"timestamp": "2020-01-01T12:00:00Z",
"id": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"type": "temperature",
"plugin": "4032ffbe-80db-5aa5-b794-f35c88dff85c",
"info": "Synse Temperature Sensor 4",
"alias": "",
"sort_index": 0,
"metadata": {
"model": "emul8-temp"
},
"capabilities": {
"mode": "rw",
"write": {
"actions": []
}
},
"tags": [
"system/id:c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"system/type:temperature"
],
"outputs": [
{
"name": "temperature",
"type": "temperature",
"precision": 2,
"scalingFactor": 0.0,
"unit": {
"name": "celsius",
"symbol": "C"
}
}
]
}
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 404 - Device not found
Read¶
HTTP | GET | /v3/read |
WebSocket | request | "request/read" |
response | "response/reading" |
Read data from devices which match the set of provided tags. If no tags are provided, all devices are read.
Passing in the id
tag here is functionally equivalent to using the read device
endpoint.
Reading data will be returned only for devices which match all of the specified tags. The contents of prior reads are not necessarily indicative of the content of future reads. That is to say, if a plugin terminates and a read command is issued, the devices managed by that plugin which previously would have matched the tags are no longer available to Synse (until the plugin comes back up), and as such, can not be read from. When the plugin becomes available again, the devices from that plugin are available to be read from.
For readability and consistency, readings are sorted by a combination of originating plugin ID, any plugin-specified sort index on the reading's device (by default, there is no additional sort index), and by device ID.
Example
shell
curl http://${server}:5000/v3/read
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.read()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Query Parameters¶
Key | Description |
---|---|
ns | The default namespace to use for the tags which do not include a namespace. This will not effect tags with a namespace already specified. (default: default ) |
tags | The tags to filter devices by. Multiple tag groups may be specified by providing multiple tags query parameters, e.g. ?tags=foo&tags=bar . Each tag group may consist of one or more comma-separated tags. Each tag group only selects devices which match all of the tags in the group. If multiple tag groups are specified, the result is the union of the matches from each individual tag group. |
plugin | The ID of the plugin to get device readings from. If not specified, all plugins are considered valid for reading. |
Response Data¶
[
{
"device": "1b714cf2-cc56-5c36-9741-fd6a483b5f10",
"timestamp": "2020-01-01T12:00:00Z",
"type": "status",
"device_type": "lock",
"unit": null,
"value": "locked",
"context": {}
},
{
"device": "fef34490-4952-5e92-bf4d-aad169df980e",
"timestamp": "2020-01-01T12:00:00Z",
"type": "humidity",
"device_type": "humidity",
"unit": {
"name": "percent humidity",
"symbol": "%"
},
"value": 9,
"context": {}
},
{
"device": "fef34490-4952-5e92-bf4d-aad169df980e",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "humidity",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 72,
"context": {}
},
{
"device": "69c2e1e2-e658-5d71-8e43-091f68aa6e84",
"timestamp": "2020-01-01T12:00:00Z",
"type": "",
"device_type": "airflow",
"unit": {
"name": "millimeters per second",
"symbol": "mm/s"
},
"value": -90,
"context": {}
},
{
"device": "01976737-085c-5e4c-94bc-a383d3d130fb",
"timestamp": "2020-01-01T12:00:00Z",
"type": "state",
"device_type": "led",
"unit": null,
"value": "off",
"context": {}
},
{
"device": "01976737-085c-5e4c-94bc-a383d3d130fb",
"timestamp": "2020-01-01T12:00:00Z",
"type": "color",
"device_type": "led",
"unit": null,
"value": "000000",
"context": {}
},
{
"device": "494bd3ed-72ec-53e9-ba65-729610516e25",
"timestamp": "2020-01-01T12:00:00Z",
"type": "pressure",
"device_type": "pressure",
"unit": {
"name": "pascal",
"symbol": "Pa"
},
"value": -4,
"context": {}
},
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 6,
"context": {}
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
device | string |
The globally unique ID of the device which the reading(s) originated from. |
device_type | string |
The type of the device (defined by the plugin). |
type | string |
The type of the reading. A single device may produce readings of different types (e.g. LED status and LED color). |
value | any |
The value of the reading. |
timestamp | string |
An RFC3339 timestamp describing the time at which the reading was taken. |
unit | object |
The unit of measure for the reading. If there is no unit, this will be null . |
context | object |
A mapping of arbitrary values to provide additional context for the reading. |
The context
field of a reading allows the plugin to specify additional context related to
that particular reading. It is optional and may be left empty. The contents of the context
are arbitrary and unrestricted, so the plugin can include whatever information it needs to.
As an example, the context could contain additional information about the data provenance or attributes (e.g. sample rate). It could also be used to give readings a label which could make them easier to parse upstream, such as a canonical name, or information about the location of the device/reading.
Info
The read
, read device
, and read cache
endpoints all return reading data in the same scheme, however the read cache
endpoint returns its data as a streamed response.
HTTP
Request
GET http://localhost:5000/v3/read
Response
[
{
"device": "1b714cf2-cc56-5c36-9741-fd6a483b5f10",
"timestamp": "2020-01-01T12:00:00Z",
"type": "status",
"device_type": "lock",
"unit": null,
"value": "locked",
"context": {}
},
{
"device": "fef34490-4952-5e92-bf4d-aad169df980e",
"timestamp": "2020-01-01T12:00:00Z",
"type": "humidity",
"device_type": "humidity",
"unit": {
"name": "percent humidity",
"symbol": "%"
},
"value": 9,
"context": {}
}
]
WebSocket
Request
{
"id": 0,
"event": "request/read"
}
Response
{
"id": 0,
"event": "response/reading",
"data": [
{
"device": "1b714cf2-cc56-5c36-9741-fd6a483b5f10",
"timestamp": "2020-01-01T12:00:00Z",
"type": "status",
"device_type": "lock",
"unit": null,
"value": "locked",
"context": {}
},
{
"device": "fef34490-4952-5e92-bf4d-aad169df980e",
"timestamp": "2020-01-01T12:00:00Z",
"type": "humidity",
"device_type": "humidity",
"unit": {
"name": "percent humidity",
"symbol": "%"
},
"value": 9,
"context": {}
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid parameter(s)
Read Device¶
HTTP | GET | /v3/read/<device> |
WebSocket | request | "request/read_device" |
response | "response/reading" |
Get the current reading(s) from the specified device. This endpoint is effectively the
same as using the read
endpoint with a device ID tag.
Example
shell
curl http://${server}:5000/v3/read/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.read_device('c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07')
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
device | The globally unique ID or alias of the device to read. |
Response Data¶
[
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
device | string |
The globally unique ID of the device which the reading(s) originated from. |
device_type | string |
The type of the device (defined by the plugin). |
type | string |
The type of the reading. A single device may produce readings of different types (e.g. LED status and LED color). |
value | any |
The value of the reading. |
timestamp | string |
An RFC3339 timestamp describing the time at which the reading was taken. |
unit | object |
The unit of measure for the reading. If there is no unit, this will be null . |
context | object |
A mapping of arbitrary values to provide additional context for the reading. |
Info
The read
, read device
, and read cache
endpoints all return reading data in the same scheme, however the read cache
endpoint returns its data as a streamed response.
HTTP
Request
GET http://localhost:5000/v3/read/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
Response
[
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
WebSocket
Request
{
"id": 0,
"event": "request/read_device",
"data": {
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07"
}
}
Response
{
"id": 0,
"event": "response/reading",
"data": [
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 404 - Device not found
Read Cache¶
HTTP | GET | /v3/readcache |
WebSocket | request | "request/read_cache" |
response | "response/reading" |
Stream reading data from the registered plugins.
All plugins have the capability of caching their readings locally in order to maintain a higher resolution of reading state beyond the poll frequency which Synse Server may request at. This is particularly useful for push-based plugins where data may be lost if it is pushed more frequently than the poll interval.
Plugin reading caching is disabled by default, but can be enabled in the plugin
configuration. When caching is disabled, this endpoint
will return a dump of the current reading state held by the plugin. In this case, the
start
and end
bounds are ignored, as there is no historical data to bound.
Example
shell
curl http://${server}:5000/v3/readcache
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
async for reading in api_client.read_cache():
print(reading)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Query Parameters¶
Key | Description |
---|---|
start | An RFC3339 formatted timestamp which specifies a starting bound on the cache data to return. If no timestamp is specified, there will not be a starting bound. |
end | An RFC3339 formatted timestamp which specifies an ending bound on the cache data to return. If no timestamp is specified, there will not be an ending bound. |
Response Data¶
{"device":"01976737-085c-5e4c-94bc-a383d3d130fb","timestamp":"2020-01-01T12:00:00Z","type":"state","device_type":"led","unit":null,"value":"off","context":{}}{"device":"01976737-085c-5e4c-94bc-a383d3d130fb","timestamp":"2020-01-01T12:00:00Z","type":"color","device_type":"led","unit":null,"value":"000000","context":{}}
Unlike the read
and read device
endpoints, the response for this endpoint is
streamed JSON. One block of the streamed JSON has the same data scheme as a reading from the other
read endpoints, e.g.
{
"device": "01976737-085c-5e4c-94bc-a383d3d130fb",
"timestamp": "2020-01-01T12:00:00Z",
"type": "state",
"device_type": "led",
"unit" :null,
"value": "off",
"context": {}
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
device | string |
The globally unique ID of the device which the reading(s) originated from. |
device_type | string |
The type of the device (defined by the plugin). |
type | string |
The type of the reading. A single device may produce readings of different types (e.g. LED status and LED color). |
value | any |
The value of the reading. |
timestamp | string |
An RFC3339 timestamp describing the time at which the reading was taken. |
unit | object |
The unit of measure for the reading. If there is no unit, this will be null . |
context | object |
A mapping of arbitrary values to provide additional context for the reading. |
Info
The read
, read device
, and read cache
endpoints all return reading data in the same scheme, however the read cache
endpoint returns its data as a streamed response.
HTTP
Request
GET http://localhost:5000/v3/readcache
Response
{"device":"01976737-085c-5e4c-94bc-a383d3d130fb","timestamp":"2020-01-01T12:00:00Z","type":"state","device_type":"led","unit":null,"value":"off","context":{}}
{"device":"01976737-085c-5e4c-94bc-a383d3d130fb","timestamp":"2020-01-01T12:00:00Z","type":"color","device_type":"led","unit":null,"value":"000000","context":{}}
WebSocket
Request
{
"id": 0,
"event": "request/read_cache"
}
Response
{
"id": 0,
"event": "response/reading",
"data": [
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid query parameters
Stream Readings¶
WebSocket | request | "request/read_stream" |
response | "response/reading" |
Stream readings from Synse.
Info
This functionality is currently only available via the WebSocket API. Streamed reading functionality will be added to the HTTP API in the future when HTTP/2 is fully supported by the backend web framework.
This request streams readings from Synse Server as readings are updated by the underlying
plugins. This is effectively a "live stream" of data. Reading data will continue to be streamed
over the WebSocket connection until either the connection is closed, or the stop
parameter
is sent with a value of true
.
Data may be streamed for all devices across all plugins, or the devices to stream readings from may be filtered by device ID or tag groups.
Query Parameters¶
Key | Description |
---|---|
ids | A list of device IDs which can be used to constrain the devices for which readings should be streamed. If no IDs are specified, no filtering by ID is done. |
tag_groups | A collection of tag groups to constrain the devices for which readings should be streamed. The tags within a group are subtractive (e.g. a device must match all tags in the group to match the filter), but each tag group specified is additive (e.g. readings will be streamed for the union of all specified groups). If no tag groups are specified, no filtering by tags is done. |
stop | A boolean value indicating whether or not to stop the reading stream. By default, this is False. |
Response Data¶
[
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
device | string |
The globally unique ID of the device which the reading(s) originated from. |
device_type | string |
The type of the device (defined by the plugin). |
type | string |
The type of the reading. A single device may produce readings of different types (e.g. LED status and LED color). |
value | any |
The value of the reading. |
timestamp | string |
An RFC3339 timestamp describing the time at which the reading was taken. |
unit | object |
The unit of measure for the reading. If there is no unit, this will be null . |
context | object |
A mapping of arbitrary values to provide additional context for the reading. |
WebSocket
Request
{
"id": 0,
"event": "request/read_cache"
}
Response
{
"id": 0,
"event": "response/reading",
"data": [
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
}
Write (Asynchronous)¶
HTTP | POST | /v3/write/<device> |
{"action": "<action>", "data": "<data>"} |
WebSocket | request | "request/write_async" |
|
response | "response/transaction_info" |
Write data to a device asynchronously.
At the plugin level, Synse performs writes asynchronously. This endpoint issues a
write to a plugin and returns the transaction information that is associated with the
write action. The transaction can be checked later for completion with the transaction
endpoint.
Multiple write operations may be specified in the POSTed JSON payload. When this is done, write actions will be processed in the order by which they are specified in the array.
There are four states a transaction can be in:
- PENDING: The write action is queued up but has not been processed.
- WRITING: The write action is in the process of being executed.
- DONE: The write action completed successfully.
- ERROR: An error occurred at some point during the write.
Both DONE and ERROR are terminal states, meaning that once a transaction reaches this state, no further processing will be done for the action and no further updates will be made, so the returned response will not change.
Not all devices support writing. This is determined per-device at the plugin level. If
a device which does not support writing is written to, an error is returned. The info
endpoint can be used to check if a device supports writing (via the capabilities
field).
In some cases, it may be desirable to issue writes synchronously. For such cases, see
the synchronous write
endpoint.
Example
shell
curl \
-H "Content-Type: application/json" \
-X POST \
-d '{"action": "color", "data": "f38ac2"}' \
http://${server}:5000/v3/write/f041883c-cf87-55d7-a978-3d3103836412
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.write_async(
'f041883c-cf87-55d7-a978-3d3103836412',
payload={
'action': 'color',
'data': 'f38ac2',
},
)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
device | The globally unique ID or alias of the device that is being written to. |
POST Body¶
[
{
"transaction": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"action": "color",
"data": "f38ac2"
}
]
Tip
The POSTed body can be either a single payload object, e.g. {"action": "<action>", "data": "<data>"}
,
or an array of payload objects, e.g. [{"action": "<action>", "data": "<data>"}, {"action": "<action>", "data": "<data>"}]
.
An array signifies multiple writes to the same device.
The fields of the payload are described below:
Field | Required | Description |
---|---|---|
transaction | no | A user-defined transaction ID for the write. If this conflicts with an existing transaction ID, an error is returned. If this is not specified, a transaction ID will be automatically generated for the write action. |
action | yes | The action that the device will perform. This is set at the plugin level and exposed in the info endpoint. |
data | sometimes | Any data that an action may require. Not all actions require data. This is plugin-defined. |
To batch multiple writes to a device, the additional writes can be appended to the POST body JSON array. The writes will be processed in the order which they are provided in this array. In the example below, "color" will be processed first, then "state".
[
{
"action": "color",
"data": "f38ac2"
},
{
"action": "state",
"data": "blink"
}
]
Response Data¶
[
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"timeout": "30s"
},
{
"id": "ab42719f-1aab-920d-b37a-0092ba631e2e",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"timeout": "30s"
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
context | object |
The data written to the device. This is provided as context info to help identify the write action. |
device | string |
The globally unique ID of the device being written to. |
id | string |
The ID of the transaction. This can be passed to the transaction endpoint to get the status of the write action. |
timeout | string |
The timeout for the write transaction, after which it will be cancelled. This is effectively the maximum wait time for the transaction to resolve. This is defined by the plugin. |
HTTP
Request
POST http://localhost:5000/v3/write/f041883c-cf87-55d7-a978-3d3103836412
[{"action": "color", "data": "f38ac2"}, {"action": "state", "data": "blink"}]
Response
[
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"timeout": "30s"
},
{
"id": "ab42719f-1aab-920d-b37a-0092ba631e2e",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"timeout": "30s"
}
]
WebSocket
Request
{
"id": 0,
"event": "request/write_async",
"data": {
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"payload": [
{
"action": "color",
"data": "f38ac2"
},
{
"action": "state",
"data": "blink"
}
]
}
}
Response
{
"id": 0,
"event": "response/transaction_info",
"data": [
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"timeout": "30s"
},
{
"id": "ab42719f-1aab-920d-b37a-0092ba631e2e",
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"timeout": "30s"
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid JSON provided
- 404 - Device not found
- 405 - Device does not support writing
Write (Synchronous)¶
HTTP | POST | /v3/write/wait/<device> |
{"action": "<action>", "data": "<data>"} |
WebSocket | request | "request/write_sync" |
|
response | "response/transaction_status" |
Write data to a device, waiting for the write to complete.
This endpoint is the synchronous version of the asynchronous write
endpoint.
In some cases, it may be more convenient to just wait for a response instead of polling
Synse Server to check whether the transaction completed. For these cases, this endpoint
may be used.
Note that the length of time it takes for a write to complete depends on the device and its plugin, so there is likely to be a variance in response times when waiting. It is up to the user to define a sane timeout such that the request does not prematurely terminate.
Since this endpoint will wait until the transaction has completed, the returned transaction status should always be one of the two terminal states (DONE, ERROR).
Example
shell
curl \
-H "Content-Type: application/json" \
-X POST \
-d '{"action": "color", "data": "f38ac2"}' \
http://${server}:5000/v3/write/wait/f041883c-cf87-55d7-a978-3d3103836412
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.write_sync(
'f041883c-cf87-55d7-a978-3d3103836412',
payload={
'action': 'color',
'data': 'f38ac2',
},
)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
device | The globally unique ID or alias of the device that is being written to. |
POST Body¶
[
{
"transaction": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"action": "color",
"data": "f38ac2"
}
]
Tip
The POSTed body can be either a single payload object, e.g. {"action": "<action>", "data": "<data>"}
,
or an array of payload objects, e.g. [{"action": "<action>", "data": "<data>"}, {"action": "<action>", "data": "<data>"}]
.
An array signifies multiple writes to the same device.
The fields of the payload are described below:
Field | Required | Description |
---|---|---|
transaction | no | A user-defined transaction ID for the write. If this conflicts with an existing transaction ID, an error is returned. If this is not specified, a transaction ID will be automatically generated for the write action. |
action | yes | The action that the device will perform. This is set at the plugin level and exposed in the info endpoint. |
data | sometimes | Any data that an action may require. Not all actions require data. This is plugin-defined. |
To batch multiple writes to a device, the additional writes can be appended to the POST body JSON array. The writes will be processed in the order which they are provided in this array. In the example below, "color" will be processed first, then "state".
[
{
"action": "color",
"data": "f38ac2"
},
{
"action": "state",
"data": "blink"
}
]
Response Data¶
[
{
"id": "ea80f074-bc80-4fdd-b842-8392514bd19b",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
},
{
"id": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
]
The response for a synchronous write has the same scheme as the transaction
response,
albeit in a list.
It is up to the user to iterate though the response and ensure that each individual write completed successfully. While this endpoint will return an error in cases where the plugin is not reachable, the data is invalid, etc., it will not return an error if a write returns an error state.
HTTP
Request
POST http://localhost:5000/v3/write/wait/f041883c-cf87-55d7-a978-3d3103836412
[{"action": "color", "data": "f38ac2"}, {"action": "state", "data": "blink"}]
Response
[
{
"id": "ea80f074-bc80-4fdd-b842-8392514bd19b",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
},
{
"id": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
]
WebSocket
Request
{
"id": 0,
"event": "request/write_sync",
"data": {
"device": "f041883c-cf87-55d7-a978-3d3103836412",
"payload": [
{
"action": "color",
"data": "f38ac2"
},
{
"action": "state",
"data": "blink"
}
]
}
}
Response
{
"id": 0,
"event": "response/transaction_status",
"data": [
{
"id": "ea80f074-bc80-4fdd-b842-8392514bd19b",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
},
{
"id": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid JSON provided
- 404 - Device not found
- 405 - Device does not support writing
Transaction¶
HTTP | GET | /v3/transaction/<transaction> |
WebSocket | request | "request/transaction" |
response | "response/transaction_status" |
Check the status of a write transaction.
If the provided transaction ID does not exist, an error is returned. Note that transaction IDs are not stored indefinitely. After a configurable TTL, the transaction will be removed from the system and any subsequent lookups for it will result in a "Not Found" error.
There are four states a transaction can be in:
- PENDING: The write action is queued up but has not been processed.
- WRITING: The write action is in the process of being executed.
- DONE: The write action completed successfully.
- ERROR: An error occurred at some point during the write.
Both DONE and ERROR are terminal states, meaning that once a transaction reaches this state, no further processing will be done for the action and no further updates will be made, so the returned response will not change.
Example
shell
curl http://${server}:5000/v3/transaction/2b717ced-58ff-43dc-ab6f-d4c0c6008ebb
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.transaction('2b717ced-58ff-43dc-ab6f-d4c0c6008ebb')
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
URI Parameters¶
Parameter | Description |
---|---|
transaction | The ID of the transaction to get the status of. Transaction IDs are provided from a write response. |
Response Data¶
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
The fields of the response are described below:
Field | Type | Description |
---|---|---|
id | string |
The ID of the transaction. |
timeout | string |
A string representing the timeout for the write transaction after which it will be cancelled. This is effectively the maximum wait time for the transaction to resolve. |
device | string |
The globally unique ID of the device being written to. |
context | object |
The POSTed write data for the given write transaction. |
status | string |
The current status of the transaction. (PENDING , WRITING , DONE , ERROR ) |
created | string |
The time at which the transaction was created. This timestamp is generated by the plugin. |
updated | string |
The last time the transaction status was updated. Once the transaction reaches a terminal state, no further updates will occur. |
message | string |
Any context information relating to a transaction's error state. If there is no error, this will be an empty string. |
HTTP
Request
GET http://localhost:5000/v3/transaction/2b717ced-58ff-43dc-ab6f-d4c0c6008ebb
Response
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
WebSocket
Request
{
"id": 0,
"event": "request/transaction",
"data": {
"transaction": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb"
}
}
Response
{
"id": 0,
"event": "response/transaction_status",
"data": {
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 404 - Transaction not found
Transactions¶
HTTP | GET | /v3/transaction |
WebSocket | request | "request/transactions" |
response | "response/transaction_list" |
Get a list of all tracked transaction IDs.
All transactions which are currently active (e.g. have not exceeded their TTL) will have their IDs returned by this endpoint.
Example
shell
curl http://${server}:5000/v3/transaction
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.transactions()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Response Data¶
[
"2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"ea80f074-bc80-4fdd-b842-8392514bd19b"
]
HTTP
Request
GET http://localhost:5000/v3/transaction
Response
[
"2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"ea80f074-bc80-4fdd-b842-8392514bd19b"
]
WebSocket
Request
{
"id": 0,
"event": "request/transactions"
}
Response
{
"id": 0,
"event": "response/transaction_list",
"data": [
"2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"ea80f074-bc80-4fdd-b842-8392514bd19b"
]
}
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 404 - Transaction not found
Devices¶
HTTP | GET | /v3/device |
WebSocket | request | "request/scan" |
response | "response/device_summary" |
This endpoint is an alias for the scan endpoint, added for API consistency and convenience. See the scan documentation for details.
Example
shell
curl http://${server}:5000/v3/device
python
import asyncio
from synse import client
async def main():
async with client.HTTPClientV3('localhost') as api_client:
resp = await api_client.scan()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
Device¶
HTTP | GET | /v3/device/<device> |
|
POST | /v3/device/<device> |
{"action": "<action>", "data": "<data>"} |
|
WebSocket | -- | not supported |
Read and write to a device.
This endpoint allows read and write access to a device through a single endpoint.
This is added as a convenience and is effectively just a wrapper around the read device
endpoint and synchronous write
endpoint.
Info
This endpoint only exists in the HTTP API. There is no "device" event in the
WebSocket API, as the read device
and synchronous write
can be used instead.
Similarly, the API clients do not support a "device" event for the same reason.
This HTTP endpoint was added as a convenience for interacting with a device.
Example
shell
# read from the device
curl http://${server}:5000/v3/device/4032ffbe-80db-5aa5-b794-f35c88dff85c
# write to the device
curl \
-H "Content-Type: application/json" \
-X POST \
-d '{"action": "color", "data": "f38ac2"}' \
http://${server}:5000/v3/device/4032ffbe-80db-5aa5-b794-f35c88dff85c
URI Parameters¶
Parameter | Description |
---|---|
device | The globally unique ID or alias of the device that is being read from/written to. |
POST Body¶
[
{
"transaction": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"action": "color",
"data": "f38ac2"
}
]
The fields of the payload are described below:
Field | Required | Description |
---|---|---|
transaction | no | A user-defined transaction ID for the write. If this conflicts with an existing transaction ID, an error is returned. If this is not specified, a transaction ID will be automatically generated for the write action. |
action | yes | The action that the device will perform. This is set at the plugin level and exposed in the info endpoint. |
data | sometimes | Any data that an action may require. Not all actions require data. This is plugin-defined. |
Response Data¶
GET
(See: read device
)
[
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
device | string |
The globally unique ID of the device which the reading(s) originated from. |
device_type | string |
The type of the device (defined by the plugin). |
type | string |
The type of the reading. A single device may produce readings of different types (e.g. LED status and LED color). |
value | any |
The value of the reading. |
timestamp | string |
An RFC3339 timestamp describing the time at which the reading was taken. |
unit | object |
The unit of measure for the reading. If there is no unit, this will be null . |
context | object |
A mapping of arbitrary values to provide additional context for the reading. |
HTTP
Request
GET http://localhost:5000/v3/read/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
Response
[
{
"device": "c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07",
"timestamp": "2020-01-01T12:00:00Z",
"type": "temperature",
"device_type": "temperature",
"unit": {
"name": "celsius",
"symbol": "C"
},
"value": 85,
"context": {}
}
]
WebSocket
Not supported - read device
is equivalent
POST
(See: synchronous write
)
[
{
"id": "2b717ced-58ff-43dc-ab6f-d4c0c6008ebb",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
]
The fields of the response are described below:
Field | Type | Description |
---|---|---|
id | string |
The ID of the transaction. |
timeout | string |
A string representing the timeout for the write transaction after which it will be cancelled. This is effectively the maximum wait time for the transaction to resolve. |
device | string |
The globally unique ID of the device being written to. |
context | object |
The POSTed write data for the given write transaction. |
status | string |
The current status of the transaction. (PENDING , WRITING , DONE , ERROR ) |
created | string |
The time at which the transaction was created. This timestamp is generated by the plugin. |
updated | string |
The last time the transaction status was updated. Once the transaction reaches a terminal state, no further updates will occur. |
message | string |
Any context information relating to a transaction's error state. If there is no error, this will be an empty string. |
HTTP
Request
POST http://localhost:5000/v3/write/c2f6f762-fa30-5f0a-ba6c-f52d8deb3c07
[{"action": "color", "data": "f38ac2"}, {"action": "state", "data": "blink"}]
Response
[
{
"id": "ea80f074-bc80-4fdd-b842-8392514bd19b",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "color",
"data": "f38ac2",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
},
{
"id": "56a32eba-1aa6-4868-84ee-fe01af8b2e6d",
"created": "2020-01-01T12:00:00Z",
"updated": "2020-01-01T12:00:00Z",
"timeout": "30s",
"status": "DONE",
"context": {
"action": "state",
"data": "blink",
"transaction": ""
},
"message": "",
"device": "f041883c-cf87-55d7-a978-3d3103836412"
}
]
WebSocket
Not supported - synchronous write
is equivalent
Error¶
The error response can be one of:
- 500 - Catchall processing error
- 400 - Invalid JSON provided/Invalid parameters
- 404 - Device not found
- 405 - Device does not support reading/writing