Skip to content

Commit 3dd8571

Browse files
authored
Merge pull request #40 from bflorian/callback-example
Bumped version to 1.3.3 with README update and security fix
2 parents 1c8518e + 32b29e9 commit 3dd8571

File tree

2 files changed

+60
-67
lines changed

2 files changed

+60
-67
lines changed

README.md

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ const deviceStates = { switch: 'off', level: 100}
6666
const connector = new SchemaConnector()
6767
.discoveryHandler((accessToken, response) => {
6868
response.addDevice('external-device-1', 'Test Dimmer', 'c2c-dimmer')
69+
.manufacturerName('Example Connector')
70+
.modelName('Virtual Dimmer');
6971
})
7072
.stateRefreshHandler((accessToken, response) => {
7173
response.addDevice('external-device-1', [
@@ -174,14 +176,16 @@ called when device state changes. Note that this simple implementation stores th
174176
the server will cause them to be lost. The app also has new `callbackAccessHandler` and `integrationDeletedHandler`
175177
handlers defined to add and remove entries from the `accessTokens` map.
176178
```javascript
177-
const {SchemaConnector} = require('st-schema')
178-
const deviceStates = {switch: 'off', level: 100}
179-
const accessTokens = {}
179+
const {SchemaConnector} = require('st-schema');
180+
const deviceStates = {switch: 'off', level: 100};
181+
const accessTokens = {};
180182
const connector = new SchemaConnector()
181183
.clientId(process.env.ST_CLIENT_ID)
182184
.clientSecret(process.env.ST_CLIENT_SECRET)
183185
.discoveryHandler((accessToken, response) => {
184186
response.addDevice('external-device-1', 'Test Dimmer', 'c2c-dimmer')
187+
.manufacturerName('Example Connector')
188+
.modelName('Virtual Dimmer');
185189
})
186190
.stateRefreshHandler((accessToken, response) => {
187191
response.addDevice('external-device-1', [
@@ -241,75 +245,64 @@ module.exports = {
241245
deviceStates: deviceStates,
242246
accessTokens: accessTokens
243247
};
248+
244249
```
245250
246251
#### server.js
247252
248-
The web server is modified to add a new `/commands` endpoint for turning on and off the switch. It expects
249-
a body of the form `{"attribute": "switch", "value": "on"}`.
253+
The web server is modified to add a new `/command` endpoint for turning on and off the switch. It expects
254+
a JSON body of the form `{"attribute": "switch", "value": "on"}`.
255+
250256
```javascript
251-
const {SchemaConnector} = require('st-schema')
252-
const deviceStates = {switch: 'off', level: 100}
253-
const accessTokens = {}
254-
const connector = new SchemaConnector()
255-
.clientId(process.env.ST_CLIENT_ID)
256-
.clientSecret(process.env.ST_CLIENT_SECRET)
257-
.discoveryHandler((accessToken, response) => {
258-
response.addDevice('external-device-1', 'Test Dimmer', 'c2c-dimmer')
259-
})
260-
.stateRefreshHandler((accessToken, response) => {
261-
response.addDevice('external-device-1', [
262-
{
263-
component: 'main',
264-
capability: 'st.switch',
265-
attribute: 'switch',
266-
value: deviceStates.switch
267-
},
257+
"use strict";
258+
require('dotenv').config();
259+
const express = require('express');
260+
const {StateUpdateRequest} = require('st-schema');
261+
const {connector, deviceStates, accessTokens} = require('./app');
262+
const server = express();
263+
const port = 3001;
264+
server.use(express.json());
265+
266+
server.post('/', (req, res) => {
267+
if (accessTokenIsValid(req)) {
268+
connector.handleHttpCallback(req, res)
269+
}
270+
});
271+
272+
server.post('/command', (req, res) => {
273+
deviceStates[req.body.attribute] = req.body.value;
274+
for (const accessToken of Object.keys(accessTokens)) {
275+
const item = accessTokens[accessToken];
276+
const updateRequest = new StateUpdateRequest(process.env.ST_CLIENT_ID, process.env.ST_CLIENT_SECRET);
277+
const deviceState = [
268278
{
269-
component: 'main',
270-
capability: 'st.switchLevel',
271-
attribute: 'level',
272-
value: deviceStates.level
273-
}
274-
])
275-
})
276-
.commandHandler((accessToken, response, devices) => {
277-
for (const device of devices) {
278-
response.addDevice(device.externalDeviceId, device.commands.map(cmd => {
279-
if (cmd.command === 'setLevel') {
280-
deviceStates.level = cmd.arguments[0];
281-
return {
282-
component: cmd.component,
283-
capability: cmd.capability,
284-
attribute: 'level',
285-
value: deviceStates.level
279+
externalDeviceId: 'external-device-1',
280+
states: [
281+
{
282+
component: 'main',
283+
capability: req.body.attribute === 'level' ? 'st.switchLevel' : 'st.switch',
284+
attribute: req.body.attribute,
285+
value: req.body.value
286286
}
287-
} else {
288-
deviceStates.switch = cmd.command === 'on' ? 'on' : 'off';
289-
return {
290-
component: cmd.component,
291-
capability: cmd.capability,
292-
attribute: 'switch',
293-
value: deviceStates.switch
294-
}
295-
}
296-
}))
297-
}
298-
})
299-
.callbackAccessHandler(async (accessToken, callbackAuthentication, callbackUrls) => {
300-
accessTokens[accessToken] = {
301-
callbackAuthentication,
302-
callbackUrls
303-
}
304-
})
305-
.integrationDeletedHandler(accessToken => {
306-
delete accessTokens[accessToken]
307-
});
308-
;
287+
]
288+
}
289+
];
290+
updateRequest.updateState(item.callbackUrls, item.callbackAuthentication, deviceState)
291+
}
292+
res.send({});
293+
res.end()
294+
});
309295

310-
module.exports = {
311-
connector: connector,
312-
deviceStates: deviceStates,
313-
accessTokens: accessTokens
314-
};
296+
297+
function accessTokenIsValid(req) {
298+
// Replace with proper validation of issued access token
299+
if (req.body.authentication && req.body.authentication.token) {
300+
return true;
301+
}
302+
res.status(401).send('Unauthorized');
303+
return false;
304+
}
305+
306+
server.listen(port);
307+
console.log(`Server listening on http://127.0.0.1:${port}`);
315308
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "st-schema",
3-
"version": "1.3.2",
3+
"version": "1.3.3",
44
"description": "SmartThings Schema for C2C integration",
55
"main": "index.js",
66
"directories": {

0 commit comments

Comments
 (0)