@benjaminmichoux/homebridge-leviton 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +36 -29
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -9,6 +9,7 @@ class LevitonDecoraSmartPlatform {
9
9
  this.config = config
10
10
  this.api = api
11
11
  this.accessories = []
12
+ this.token = null
12
13
 
13
14
  const noop = function () {}
14
15
  const logger = (level) => (msg) =>
@@ -37,6 +38,15 @@ class LevitonDecoraSmartPlatform {
37
38
  const excludedModels = (config.excludedModels || []).map((name) => name.toUpperCase())
38
39
  const excludedSerials = (config.excludedSerials || []).map((name) => name.toUpperCase())
39
40
  if (Array.isArray(devices) && devices.length > 0) {
41
+ // Set up accessories restored from cache with the fresh token (their
42
+ // cached token has since expired). Refresh their device data too.
43
+ for (const accessory of this.accessories) {
44
+ const device = devices.find((d) => d.serial === accessory.context.device.serial)
45
+ if (device) accessory.context.device = device
46
+ accessory.context.token = token
47
+ await this.setupService(accessory)
48
+ }
49
+ // Add any newly discovered devices not already restored from cache.
40
50
  devices.forEach((device) => {
41
51
  if (!this.accessories.find((acc) => acc.context.device.serial === device.serial)) {
42
52
  if (!excludedModels.includes(device.model) && !excludedSerials.includes(device.serial)) {
@@ -81,6 +91,7 @@ class LevitonDecoraSmartPlatform {
81
91
  password: this.config['password'],
82
92
  })
83
93
  var { id: token, userId: personID } = login
94
+ this.token = token
84
95
  this.log.debug(`personID: ${personID}, hasToken: ${!!token}`)
85
96
  } catch (err) {
86
97
  this.log.error(`Failed to login to leviton: ${err.message}`)
@@ -176,13 +187,13 @@ class LevitonDecoraSmartPlatform {
176
187
 
177
188
  async configureAccessory(accessory) {
178
189
  this.log.debug(`configureAccessory: ${accessory.displayName}`)
179
- await this.setupService(accessory)
190
+ // Defer service setup until didFinishLaunching, once we have a fresh token.
180
191
  this.accessories.push(accessory)
181
192
  }
182
193
 
183
- async getStatus(device, token) {
194
+ async getStatus(device) {
184
195
  this.log.debug(`getStatus: ${device.name}`)
185
- return Leviton.getIotSwitch({ switchID: device.id, token })
196
+ return Leviton.getIotSwitch({ switchID: device.id, token: this.token })
186
197
  }
187
198
 
188
199
  async setupService(accessory) {
@@ -218,21 +229,20 @@ class LevitonDecoraSmartPlatform {
218
229
  this.log.debug(`Setting up device as Switch: ${accessory.displayName}`)
219
230
 
220
231
  const device = accessory.context.device
221
- const token = accessory.context.token
222
- const status = await this.getStatus(device, token)
232
+ const status = await this.getStatus(device)
223
233
 
224
234
  const service = accessory.getService(Service.Switch) || accessory.addService(Service.Switch, device.name)
225
235
 
226
236
  service
227
237
  .getCharacteristic(Characteristic.On)
228
238
  .onGet(async () => {
229
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
239
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
230
240
  this.log.debug(`onGetPower: ${device.name} ${res.power}`)
231
241
  return res.power === 'ON'
232
242
  })
233
243
  .onSet(async (value) => {
234
- const res = await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token })
235
- this.log.info(`onSetPower: ${device.name} ${res.power}`)
244
+ await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token: this.token })
245
+ this.log.info(`onSetPower: ${device.name} ${value ? 'ON' : 'OFF'}`)
236
246
  })
237
247
  .updateValue(status.power === 'ON')
238
248
  }
@@ -241,21 +251,20 @@ class LevitonDecoraSmartPlatform {
241
251
  this.log.debug(`Setting up device as Outlet: ${accessory.displayName}`)
242
252
 
243
253
  const device = accessory.context.device
244
- const token = accessory.context.token
245
- const status = await this.getStatus(device, token)
254
+ const status = await this.getStatus(device)
246
255
 
247
256
  const service = accessory.getService(Service.Outlet) || accessory.addService(Service.Outlet, device.name)
248
257
 
249
258
  service
250
259
  .getCharacteristic(Characteristic.On)
251
260
  .onGet(async () => {
252
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
261
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
253
262
  this.log.debug(`onGetPower: ${device.name} ${res.power}`)
254
263
  return res.power === 'ON'
255
264
  })
256
265
  .onSet(async (value) => {
257
- const res = await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token })
258
- this.log.info(`onSetPower: ${device.name} ${res.power}`)
266
+ await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token: this.token })
267
+ this.log.info(`onSetPower: ${device.name} ${value ? 'ON' : 'OFF'}`)
259
268
  })
260
269
  .updateValue(status.power === 'ON')
261
270
  }
@@ -264,34 +273,33 @@ class LevitonDecoraSmartPlatform {
264
273
  this.log.debug(`Setting up device as Lightbulb: ${accessory.displayName}`)
265
274
 
266
275
  const device = accessory.context.device
267
- const token = accessory.context.token
268
- const status = await this.getStatus(device, token)
276
+ const status = await this.getStatus(device)
269
277
 
270
278
  const service = accessory.getService(Service.Lightbulb) || accessory.addService(Service.Lightbulb, device.name)
271
279
 
272
280
  service
273
281
  .getCharacteristic(Characteristic.On)
274
282
  .onGet(async () => {
275
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
283
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
276
284
  this.log.debug(`onGetPower: ${device.name} ${res.power}`)
277
285
  return res.power === 'ON'
278
286
  })
279
287
  .onSet(async (value) => {
280
- const res = await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token })
281
- this.log.info(`onSetPower: ${device.name} ${res.power}`)
288
+ await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token: this.token })
289
+ this.log.info(`onSetPower: ${device.name} ${value ? 'ON' : 'OFF'}`)
282
290
  })
283
291
  .updateValue(status.power === 'ON')
284
292
 
285
293
  service
286
294
  .getCharacteristic(Characteristic.Brightness)
287
295
  .onGet(async () => {
288
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
296
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
289
297
  this.log.debug(`onGetBrightness: ${device.name} @ ${res.brightness}%`)
290
298
  return res.brightness
291
299
  })
292
300
  .onSet(async (brightness) => {
293
- const res = await Leviton.putIotSwitch({ switchID: device.id, brightness, token })
294
- this.log.info(`onSetBrightness: ${device.name} @ ${res.brightness}%`)
301
+ await Leviton.putIotSwitch({ switchID: device.id, brightness, token: this.token })
302
+ this.log.info(`onSetBrightness: ${device.name} @ ${brightness}%`)
295
303
  })
296
304
  .setProps({ minValue: status.minLevel, maxValue: status.maxLevel, minStep: 1 })
297
305
  .updateValue(status.brightness)
@@ -301,34 +309,33 @@ class LevitonDecoraSmartPlatform {
301
309
  this.log.debug(`Setting up device as Fan: ${accessory.displayName}`)
302
310
 
303
311
  const device = accessory.context.device
304
- const token = accessory.context.token
305
- const status = await this.getStatus(device, token)
312
+ const status = await this.getStatus(device)
306
313
 
307
314
  const service = accessory.getService(Service.Fan) || accessory.addService(Service.Fan, device.name)
308
315
 
309
316
  service
310
317
  .getCharacteristic(Characteristic.On)
311
318
  .onGet(async () => {
312
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
319
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
313
320
  this.log.debug(`onGetPower: ${device.name} ${res.power}`)
314
321
  return res.power === 'ON'
315
322
  })
316
323
  .onSet(async (value) => {
317
- const res = await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token })
318
- this.log.info(`onSetPower: ${device.name} ${res.power}`)
324
+ await Leviton.putIotSwitch({ switchID: device.id, power: value ? 'ON' : 'OFF', token: this.token })
325
+ this.log.info(`onSetPower: ${device.name} ${value ? 'ON' : 'OFF'}`)
319
326
  })
320
327
  .updateValue(status.power === 'ON')
321
328
 
322
329
  service
323
330
  .getCharacteristic(Characteristic.RotationSpeed)
324
331
  .onGet(async () => {
325
- const res = await Leviton.getIotSwitch({ switchID: device.id, token })
332
+ const res = await Leviton.getIotSwitch({ switchID: device.id, token: this.token })
326
333
  this.log.debug(`onGetRotationSpeed: ${device.name} @ ${res.brightness}%`)
327
334
  return res.brightness
328
335
  })
329
336
  .onSet(async (brightness) => {
330
- const res = await Leviton.putIotSwitch({ switchID: device.id, brightness, token })
331
- this.log.info(`onSetRotationSpeed: ${device.name} @ ${res.brightness}%`)
337
+ await Leviton.putIotSwitch({ switchID: device.id, brightness, token: this.token })
338
+ this.log.info(`onSetRotationSpeed: ${device.name} @ ${brightness}%`)
332
339
  })
333
340
  .setProps({ minValue: 0, maxValue: status.maxLevel, minStep: status.minLevel })
334
341
  .updateValue(status.brightness)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benjaminmichoux/homebridge-leviton",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "A homebridge plugin for Leviton Decora Smart devices",
5
5
  "main": "index.js",
6
6
  "keywords": [