Touch to Identify
An example of how to use the REST API with a simple script that identifies devices by touch.
Last updated
Was this helpful?
Was this helpful?
pip install requests==2.31.0pip install --upgrade disruptivenpm install eventsource@2.0.2
npm install jsonwebtoken@9.0.1
npm install axios@1.4.0export DT_SERVICE_ACCOUNT_KEY_ID=<YOUR_SERVICE_ACCOUNT_KEY_ID>
export DT_SERVICE_ACCOUNT_SECRET=<YOUR_SERVICE_ACCOUNT_SECRET>
export DT_SERVICE_ACCOUNT_EMAIL=<YOUR_SERVICE_ACCOUNT_EMAIL>
export DT_PROJECT_ID=<YOUR_PROJECT_ID>import os
import json
import requests
# Service Account credentials.
SERVICE_ACCOUNT_KEY_ID = os.getenv('DT_SERVICE_ACCOUNT_KEY_ID')
SERVICE_ACCOUNT_SECRET = os.getenv('DT_SERVICE_ACCOUNT_SECRET')
# Construct API URL.
PROJECT_ID = os.getenv('DT_PROJECT_ID')
API_BASE = 'https://api.d21s.com/v2/'
DEVICES_STREAM_URL = '{}projects/{}/devices:stream'.format(
API_BASE,
PROJECT_ID
)
if __name__ == '__main__':
# Set up a stream connection.
print('Waiting for touch event...')
stream = requests.get(
url=DEVICES_STREAM_URL,
auth=(SERVICE_ACCOUNT_KEY_ID, SERVICE_ACCOUNT_SECRET),
stream=True,
params={
'event_types': ['touch'],
},
)
# Iterate through the events as they come in (one event per line).
for line in stream.iter_lines():
# Decode the response payload and isolate event dictionary.
payload = json.loads(line.decode('ascii'))
# Halt at missing key.
if 'result' not in payload.keys():
print(payload)
break
# Fetch touched device blob for more detailed information.
event = payload['result']['event']
device = requests.get(
url=API_BASE + event['targetName'],
auth=(SERVICE_ACCOUNT_KEY_ID, SERVICE_ACCOUNT_SECRET),
).json()
# Print some device information.
print('\nTouch event received:')
print(json.dumps(device, indent=4))
# Stop stream as we've found a device.
breakimport os
import disruptive as dt
# Environment variables for target project.
PROJECT_ID = os.getenv('DT_PROJECT_ID', '')
if __name__ == '__main__':
# Enable logging to see what's happening under the hood.
dt.log_level = 'debug'
# Set up a stream for all touch events in a project.
for e in dt.Stream.event_stream(PROJECT_ID, event_types=['touch']):
# When a touch event is received, fetch the source device.
touched_device = dt.Device.get_device(e.device_id)
# Print information about the touched device.
print(touched_device)
# Stop the stream as we've found a device.
breakconst EventSource = require("eventsource") // npm install eventsource@1.0.7
const jwt = require('jsonwebtoken') // npm install jsonwebtoken@8.5.1
const axios = require('axios').default // npm install axios@0.21.1
// Service Account credentials
const serviceAccountKeyID = process.env.DT_SERVICE_ACCOUNT_KEY_ID
const serviceAccountSecret = process.env.DT_SERVICE_ACCOUNT_SECRET
const serviceAccountEmail = process.env.DT_SERVICE_ACCOUNT_EMAIL
// Construct API URL
const projectID = process.env.DT_PROJECT_ID
const apiBase = 'https://api.d21s.com/v2/'
const devicesStreamUrl = apiBase + `projects/${projectID}/devices:stream`
async function main() {
let retryCount = 0
let stream
setupStream()
async function setupStream() {
// Since EventSource does not support setting HTTP headers, we need to use
// OAuth for authentication. The received access token will be set as a
// `token` query parameter when setting up the stream in the next step.
const accessToken = await getAccessToken(
serviceAccountKeyID,
serviceAccountEmail,
serviceAccountSecret,
)
// Add query parameters to the URL
let url = devicesStreamUrl
url += `?eventTypes=touch` // Filters out all events except touch
url += `&token=${accessToken}` // The access token for authentication
// Set up a new stream with callback functions for messages
console.log('Waiting for touch event...')
stream = new EventSource(url)
stream.onmessage = handleStreamMessage
}
async function handleStreamMessage(message) {
// Parse the payload as JSON
const data = JSON.parse(message.data)
if (!data || !data.result) {
return
}
// Parse the event object
const event = data.result.event
// Close stream as we've found a device
stream.close()
// Send GET request to fetch device information.
const response = await axios({
method: 'GET',
url: apiBase + event.targetName,
auth: {
username: process.env.DT_SERVICE_ACCOUNT_KEY_ID,
password: process.env.DT_SERVICE_ACCOUNT_SECRET,
}
})
// Print response contents.
console.log('\nTouch event received:')
console.log(JSON.stringify(response.data, null, 2))
}
}
main().catch((err) => {console.log(err)})
// Fetches an access token. See the following guide for documentation:
// https://developer.d12s.com/docs/authentication/oauth2
async function getAccessToken(keyID, email, secret) {
// Construct the JWT header
let jwtHeaders = {
'alg': 'HS256',
'kid': keyID,
}
// Construct the JWT payload
let jwtPayload = {
'iat': Math.floor(Date.now() / 1000), // current unixtime
'exp': Math.floor(Date.now() / 1000) + 3600, // expiration unixtime
'aud': 'https://identity.disruptive-technologies.com/oauth2/token',
'iss': email,
}
// Sign and encode JWT with the secret
const jwtEncoded = jwt.sign(
jwtPayload,
secret,
{
header: jwtHeaders,
algorithm: 'HS256',
},
)
// Prepare POST request data
const requestObject = {
'assertion': jwtEncoded,
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
}
// Converts the requestObject to a Form URL-Encoded string
const requestData = Object.keys(requestObject).map(function(key) {
return encodeURIComponent(key)+'='+encodeURIComponent(requestObject[key])
}).join('&')
// Exchange JWT for access token
const accessTokenResponse = await axios({
method: 'POST',
url: 'https://identity.disruptive-technologies.com/oauth2/token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: requestData,
}).catch(function (error) {
if (error.response) {
console.log(error.response.data)
}
throw error
})
// Return the access token in the request
return accessTokenResponse.data.access_token
}Waiting for touch event...
Touch event received:
{
"name": "projects/c0md3mm0c7bet3vico8g/devices/emuc0uc989qdqebrvv29so0",
"type": "touch",
"labels": {
"name": "my-favorite-sensor",
"virtual-sensor": ""
},
"reported": {
"networkStatus": {
"signalStrength": 99,
"rssi": 0,
"updateTime": "2021-03-03T17:21:53.080314Z",
"cloudConnectors": [
{
"id": "emulated-ccon",
"signalStrength": 99,
"rssi": 0
}
],
"transmissionMode": "LOW_POWER_STANDARD_MODE"
},
"batteryStatus": null,
"touch": {
"updateTime": "2021-03-03T17:22:51.059514Z"
}
}
}
Terminating stream.