Technical Documentation: TSD REST API
The REST API for the TSD service can be used to obtain TSD data from proficloud.io.
What you will need:
- A user account
- At least one device sending data to the time series data (you need the UUID of the device)
- The name of the metrics you want to read (hint: check the dashboarding system)
- Any tool or programming language you like to use to query the REST-API
To acess the API, authentication via OAuth is mandatory.
A token can be requested either via username and password (on initial authentication) or via a refresh token (provided by initial login).
The response yields an access token and refresh token with corresponding expiration times. An access token should be re-used until it expires, and the refresh token can be used to get new tokens without the need to supply username and password again.
The TSD REST APi uses JSON payloads and can be used from any programming language or tool capable of working with REST API’s. This tutorial provides Python examples, but of course other languages or tools can be used.
The following tutorial shows examples for the retrieval and renewal of tokens and also shows different possibilities for querying data!
#In this Python example we will use the requests library: import requests import json url = "https://tsd.proficloud.io/epts/token" username = "demohmi2020@phoenixcontact-sb.io" password = "GoDigital2020!" uuid = '355f6856-e9a4-469f-8f22-3f8b037d064a' metrics = "auto~pressure,auto~temperature,auto~watt"
Authentication
First we need to authenticate at the REST API as a user. The access token is used to authenticate the user for each REST-call and the refresh token can be used to renew the tokens without the need for a username and password.
Initial token retrieval / username & password
Initially, tokens can be retrieved with the username and password:
#Headers: header = { "Content-Type": "application/json" } #Payload: data = { "username": username, "password": password } #Send post request token_response = requests.post(url, json=data, headers=header) if token_response.ok: access_token = token_response.json().get("access_token") expires_in = token_response.json().get("expires_in") refresh_token = token_response.json().get("refresh_token") refresh_expires_in = token_response.json().get("refresh_expires_in") print("Access token: ...{}...(length: {}, expires in {}s)".format(access_token[500:600], len(access_token), expires_in)) print("Refresh token: ...{}... (length: {}, expires in {}s, 0 means infinite)".format(refresh_token[500:600], len(refresh_token), refresh_expires_in))
Access token: ...MzQtODljYWYzMDE2MmZmIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL3Byb2ZpY2xvdWQuaW8iLCJodHRw...(length: 1726, expires in 86400s) Refresh token: ...mF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjJhMjFhZmRhLTRmMDUtNDA5Ny1hZTM0LTg5Y2FmMzAxNjJmZiIsInJlYWxtX... (length: 1079, expires in 0s, 0 means infinite)
Token renewal
The refresh token can be used to obtain new tokens, without the need for a username and password. In [3]:
#Headers: header = { "Content-Type": "application/json" } #Payload: data = { "refresh_token": refresh_token } #Send post request token_response = requests.post(url, json=data, headers=header) if token_response.ok: access_token = token_response.json().get("access_token") expires_in = token_response.json().get("expires_in") refresh_token = token_response.json().get("refresh_token") refresh_expires_in = token_response.json().get("refresh_expires_in") print("Access token: ...{}...(length: {}, expires in {}s)".format(access_token[500:600], len(access_token), expires_in)) print("Refresh token: ...{}... (length: {}, expires in {}s, 0 means infinite)".format(refresh_token[500:600], len(refresh_token), refresh_expires_in))
Access token: ...MzQtODljYWYzMDE2MmZmIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL3Byb2ZpY2xvdWQuaW8iLCJodHRw...(length: 1726, expires in 86400s) Refresh token: ...mF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjJhMjFhZmRhLTRmMDUtNDA5Ny1hZTM0LTg5Y2FmMzAxNjJmZiIsInJlYWxtX... (length: 1079, expires in 0s, 0 means infinite)
Querying data
There are three options when it comes to querying data from the TSD REST API:
- Query last data points
- Query historical raw data
- Query historical data using database queries (advanced users)
Query last data points
The endpoint /epts/last returns the most recent time series data. (EPTS stands for “endpoint time-series”)
The base url is https://tsd.proficloud.io/epts/last with the following possible parameters. The request method is “GET”.
Authentication happens via header “Authorization” with value “Bearer ACCESS_TOKEN“.
Parameters:
- uuid: One or more UUIDs, comma separated without spaces
- timeSeriesName: One or more metrics, comma separated without spaces
The response yields in status code 200 and contains a JSON object containing the time series. Possible errors are:
- 401 – Unauthorized.
- 500 – e.g. wrong input parameters, content-type, etc. Error message given in response body.
header = { "Content-Type": "application/json", "Authorization": "Bearer {}".format(access_token) } url = "https://tsd.proficloud.io/epts/last?uuid={}&timeSeriesName={}".format(uuid, metrics) result = requests.get(url, headers=header) if result.ok: print(json.dumps(result.json(), indent=4))
{ "355f6856-e9a4-469f-8f22-3f8b037d064a": { "auto~pressure": [ { "timestamp": "2020-07-21T11:43:05Z", "values": { "value": 1000 } } ], "auto~temperature": [ { "timestamp": "2020-07-21T11:43:05Z", "values": { "value": 60 } } ], "auto~watt": [ { "timestamp": "2020-07-21T11:43:05Z", "values": { "value": 5000 } } ] } }
Query historical raw data
The endpoint /epts/data returns a block time series data from the selected range. (EPTS stands for “endpoint time-series”)
The base url is https://tsd.proficloud.io/epts/data with the following possible parameters. The request method is “GET”.
Authentication happens via header “Authorization” with value “Bearer ACCESS_TOKEN“.
Parameters:
- uuid: One or more UUIDs, comma separated without spaces
- timeSeriesName: One or more metrics, comma separated without spaces
- fromDate: ISO-8601 encoded start time to retrieve data points from (example: 2017-04-20T00:00:00.000Z)
- toDate: ISO-8601 encoded end time to retrieve data points to (example: 2017-04-20T00:00:00.000Z)
The response yields in status code 200 and contains a JSON object containing the time series. Possible errors are:
- 401 – Unauthorized.
- 500 – e.g. wrong input parameters, content-type, etc. Error message given in response body.
header = { "Content-Type": "application/json", "Authorization": "Bearer {}".format(access_token) } #Dates are ISO-8601! fromDate = "2020-07-21T10:45:00.000Z" toDate = "2020-07-21T10:45:05.000Z" url = "https://tsd.proficloud.io/epts/data?uuid={}&timeSeriesName={}&fromDate={}&toDate={}".format(uuid, metrics, fromDate, toDate) result = requests.get(url, headers=header) if result.ok: print(json.dumps(result.json(), indent=4))
[ { "355f6856-e9a4-469f-8f22-3f8b037d064a": { "auto~pressure": [ { "timestamp": "2020-07-21T10:45:01Z", "values": { "value": 10 } }, { "timestamp": "2020-07-21T10:45:02Z", "values": { "value": 0 } }, { "timestamp": "2020-07-21T10:45:03Z", "values": { "value": 10 } }, { "timestamp": "2020-07-21T10:45:04Z", "values": { "value": 100 } } ] } }, { "355f6856-e9a4-469f-8f22-3f8b037d064a": { "auto~temperature": [ { "timestamp": "2020-07-21T10:45:01Z", "values": { "value": 50 } }, { "timestamp": "2020-07-21T10:45:02Z", "values": { "value": 35 } }, { "timestamp": "2020-07-21T10:45:03Z", "values": { "value": 45 } }, { "timestamp": "2020-07-21T10:45:04Z", "values": { "value": 55 } } ] } }, { "355f6856-e9a4-469f-8f22-3f8b037d064a": { "auto~watt": [ { "timestamp": "2020-07-21T10:45:01Z", "values": { "value": 800 } }, { "timestamp": "2020-07-21T10:45:02Z", "values": { "value": 300 } }, { "timestamp": "2020-07-21T10:45:03Z", "values": { "value": 800 } }, { "timestamp": "2020-07-21T10:45:04Z", "values": { "value": 1500 } } ] } } ]
Query historical data using database queries (advanced users)
For advanced users, we also offer the ability to formulate custom queries to read data through the endpoint /query.
The base url is https://tsd.proficloud.io/query with the following possible parameters. The request method is “GET”.
Authentication happens via header “Authorization” with value “Bearer ACCESS_TOKEN“.
Parameters:
- q: Query for reading tsd data InfluxDB-Style. An example is shown below, detailed information on the queries can be found here
The response yields in status code 200 and contains a JSON object containing the time series. Possible errors are:
- 401 – Unauthorized.
- 500 – e.g. wrong input parameters, content-type, etc. Error message given in response body.
query = "SELECT mean(\"value\") FROM \"auto~watt\" WHERE (\"uuid\" = '355f6856-e9a4-469f-8f22-3f8b037d064a') AND time >= now() - 30s GROUP BY time(10s) fill(none)" header = { "Content-Type": "application/json", "Authorization": "Bearer {}".format(access_token) } url = "https://tsd.proficloud.io/query?q={}".format(query) result = requests.get(url, headers=header) if result.ok: print(json.dumps(result.json(), indent=4))
{ "results": [ { "statement_id": 0, "series": [ { "name": "auto~watt", "columns": [ "time", "mean" ], "values": [ [ "2020-07-21T13:01:30Z", 4520 ], [ "2020-07-21T13:01:40Z", 7690 ], [ "2020-07-21T13:01:50Z", 23500 ] ] } ] } ] }