Skip to content

Commit f8bdaeb

Browse files
authored
Error handling and code style fixes (#62)
fix: Error handling and code style fixes (#62)
1 parent b9869f4 commit f8bdaeb

16 files changed

+100
-119
lines changed

README.md

+13-27
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,12 @@ const PORT = 8080;
6464

6565
server.use(express.json());
6666

67-
// @smartthings_rsa.pub is your on-disk public key
68-
// If you do not have it yet, omit publicKey()
67+
/* Define the SmartApp */
6968
smartapp
69+
// @smartthings_rsa.pub is your on-disk public key
70+
// If you do not have it yet, omit publicKey()
7071
.publicKey('@smartthings_rsa.pub') // optional until app verified
72+
.app.enableEventLogging(2) // logs all lifecycle event requests and responses as pretty-printed JSON. Omit in production
7173
.configureI18n()
7274
.page('mainPage', (context, page, configData) => {
7375
page.section('sensors', section => {
@@ -77,36 +79,18 @@ smartapp
7779
section.deviceSetting('lights').capabilities(['switch']).multiple(true).permissions('rx');
7880
});
7981
})
80-
.installed((context, installData) => {
81-
console.log('installed', JSON.stringify(installData));
82+
.updated(async (context, updateData) => {
83+
// Called for both INSTALLED and UPDATED lifecycle events if there is no separate installed() handler
84+
await context.api.subscriptions.unsubscribeAll()
85+
return context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'contactSensor', 'contact', 'myDeviceEventHandler');
8286
})
83-
.uninstalled((context, uninstallData) => {
84-
console.log('uninstalled', JSON.stringify(uninstallData));
85-
})
86-
.updated((context, updateData) => {
87-
console.log('updated', JSON.stringify(updateData));
88-
context.api.subscriptions.unsubscribeAll().then(() => {
89-
console.log('unsubscribeAll() executed');
90-
context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'contactSensor', 'contact', 'myDeviceEventHandler');
91-
});
92-
})
93-
.subscribedEventHandler('myDeviceEventHandler', (context, deviceEvent) => {
94-
const value = deviceEvent.value === 'open' ? 'on' : 'off';
87+
.subscribedEventHandler('myDeviceEventHandler', (context, event) => {
88+
const value = event.value === 'open' ? 'on' : 'off';
9589
context.api.devices.sendCommands(context.config.lights, 'switch', value);
96-
console.log(`sendCommands(${JSON.stringify(context.config.lights)}, 'switch', '${value}')`);
97-
98-
/* All subscription event handler types:
99-
* - DEVICE_EVENT (context, deviceEvent)
100-
* - TIMER_EVENT (context, timerEvent)
101-
* - DEVICE_COMMANDS_EVENT (context, deviceId, command, deviceCommandsEvent)
102-
* - MODE_EVENT (context, modeEvent)
103-
* - SECURITY_ARM_STATE_EVENT (context, securityArmStateEvent)
104-
*/
10590
});
10691

10792
/* Handle POST requests */
10893
server.post('/', function(req, res, next) {
109-
console.log(`${new Date().toISOString()} ${req.method} ${req.path} ${req.body && req.body.lifecycle}`);
11094
smartapp.handleHttpCallback(req, res);
11195
});
11296

@@ -120,12 +104,14 @@ To run as a Lambda function instead of an HTTP server, ensure that your main ent
120104

121105
> **Note:** This snippet is heavily truncated for brevity – see the web service example above a more detailed example of how to define a `smartapp`.
122106
123-
```javascript
107+
```
124108
const smartapp = require('@smartthings/smartapp')
125109
smartapp
110+
.app.enableEventLogging() // logs all lifecycle event requests and responses. Omit in production
126111
.page( ... )
127112
.updated(() => { ... })
128113
.subscribedEventHandler( ... );
114+
129115
exports.handle = (event, context, callback) => {
130116
smartapp.handleLambdaCallback(event, context, callback);
131117
};

lib/platform/apps.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Apps extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list() {
117
return this.st.client.request('apps')
128
}

lib/platform/client-error.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict'
2+
3+
module.exports = class ClientError {
4+
constructor(error) {
5+
const {name, message, response} = error
6+
const {statusCode, request} = response
7+
const {href, body} = request
8+
9+
this.name = name === 'StatusCodeError' ? 'SmartThingsApiError' : name
10+
this.statusCode = statusCode
11+
this.message = messageString(message)
12+
this.url = href
13+
this.body = body
14+
}
15+
16+
toString() {
17+
if (this.body) {
18+
return `${this.name}: ${this.message}, statusCode=${this.statusCode}, url=${this.url}, body=${this.body}`
19+
}
20+
21+
return `${this.name}: ${this.message}, statusCode=${this.statusCode}, url=${this.url}`
22+
}
23+
}
24+
25+
function messageString(msg) {
26+
if (typeof msg === 'object') {
27+
return JSON.stringify(msg)
28+
}
29+
30+
return msg
31+
}

lib/platform/client.js

+6-23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const rp = require('request-promise-native')
4+
const ClientError = require('./client-error')
45

56
class Client {
67
constructor(options) {
@@ -47,7 +48,7 @@ class Client {
4748
}
4849

4950
return rp(opts).catch(error => {
50-
logError(this._log, error, opts)
51+
logError(this._log, error)
5152
})
5253
}
5354

@@ -96,11 +97,11 @@ class Client {
9697
opts.headers.Authorization = 'Bearer ' + client.authToken
9798

9899
return rp(opts).catch(error => {
99-
logError(client._log, error, opts, 'TRY2 ')
100+
logError(client._log, error)
100101
})
101102
}
102103
} else {
103-
logError(client._log, error, opts)
104+
logError(client._log, error)
104105
}
105106

106107
release()
@@ -115,26 +116,8 @@ module.exports = function (authToken, clientId, clientSecret) {
115116
return new Client(authToken, clientId, clientSecret)
116117
}
117118

118-
function logError(log, error, opts, prefix = '') {
119-
try {
120-
const msg = prefix + error.message
121-
const err = {
122-
statusCode: error.statusCode,
123-
request: opts
124-
}
125-
const p0 = msg.indexOf('{')
126-
if (p0 > 0) {
127-
err.message = JSON.parse(msg.slice(msg.indexOf('{')))
128-
} else {
129-
err.message = msg
130-
}
131-
132-
log.apiError(JSON.stringify(err, null, 2))
133-
throw error
134-
} catch (error2) {
135-
log.error(error2.message)
136-
throw error2
137-
}
119+
function logError(log, error) {
120+
throw new ClientError(error)
138121
}
139122

140123
function refreshToken(url, clientId, clientSecret, refreshToken) {

lib/platform/deviceprofiles.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class DeviceProfiles extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list(query = {max: 500}) {
117
return this.st.client.request('deviceprofiles', 'GET', null, null, query)
128
}

lib/platform/devices.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Devices extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
create(params) {
117
const body = {
128
label: params.label,
@@ -64,11 +60,14 @@ module.exports = class Devices extends Base {
6460
}
6561

6662
sendCommands(items, capability, command, args) {
63+
const results = []
6764
if (items) {
6865
for (const it of items) {
69-
this.sendCommand(it, capability, command, args)
66+
results.push(this.sendCommand(it, capability, command, args))
7067
}
7168
}
69+
70+
return Promise.all(results)
7271
}
7372

7473
postCommands(deviceId, body) {

lib/platform/installedapps.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class InstalledApps extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list(locationId = null) {
117
const loc = locationId ? locationId : this.st.locationId
128
return this.st.client.request('installedapps', null, {locationId: loc, max: 500})

lib/platform/locations.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Locations extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list(query = {max: 500}) {
117
return this.st.client.request('locations', 'GET', null, null, query)
128
}

lib/platform/modes.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Modes extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list(query = {max: 500}) {
117
return this.st.client.request(`locations/${this.st.locationId}/modes`, 'GET', null, null, query)
128
}

lib/platform/scenes.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Scenes extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
list(query = {max: 500}) {
117
const qs = query
128
if (this.st.locationId) {

lib/platform/schedules.js

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
const Base = require('./base')
44

55
module.exports = class Schedules extends Base {
6-
constructor(st) {
7-
super(st)
8-
}
9-
106
schedule(name, cronExpression) {
117
const body = {
128
name,

lib/platform/subscriptions.js

-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
const Base = require('./base')
33

44
module.exports = class Subscriptions extends Base {
5-
constructor(st) {
6-
super(st)
7-
}
8-
95
list() {
106
return this.st.client.request(`installedapps/${this.st.installedAppId}/subscriptions`)
117
}

0 commit comments

Comments
 (0)