Skip to content

Commit

Permalink
Merge pull request #2 from balansse/feature/EventStreamStability
Browse files Browse the repository at this point in the history
Increase stability of event stream;
Dynamically add and remove accessories;
Remove excessive logging;
Add object mapping using dictionary;
  • Loading branch information
balansse authored Jun 26, 2020
2 parents bd98b0f + 9931eca commit a44e999
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 16 deletions.
38 changes: 28 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,22 @@ module.exports = function (homebridge) {
this.vivintApiPromise = VivintApi.login({username: config.username, password: config.password}, 1)
let apiLoginRefreshSecs = config.apiLoginRefreshSecs || 1200 // once per 20 minutes default


this.deviceSetPromise = this.vivintApiPromise.then((vivintApi) => {
let DeviceSet = DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacteristics, setInterval, Date)
let deviceSet = new DeviceSet()

setInterval(() => {
vivintApi.renew()
.then((_) => vivintApi.renewSystemInfo())
.then((_) => deviceSet.handleSnapshot(vivintApi.deviceSnapshot(), vivintApi.deviceSnapshotTs()))
.catch((err) => log("Error refreshing", err))
.catch((err) => log("Error refreshing login info", err))
}, apiLoginRefreshSecs * 1000)

//Setting up the system info refresh to keep the notification stream active
setInterval(() => {
vivintApi.renewSystemInfo()
.then((vivintApi) => deviceSet.handleSnapshot(vivintApi.deviceSnapshot(), vivintApi.deviceSnapshotTs()))
.catch((err) => log("Error getting system info", err))
}, (apiLoginRefreshSecs / 20) * 1000)

return {deviceSet, DeviceSet}
})

Expand All @@ -84,24 +89,37 @@ module.exports = function (homebridge) {

Promise.all([pubNubPromise, this.vivintApiPromise, this.cachedAccessories.result, this.deviceSetPromise]).then(
([pubNub, vivintApi, cachedAccessories, {DeviceSet, deviceSet}]) => {
// add any new devices
let cachedIds = cachedAccessories.map((acc) => acc.context.id)
let newAccessories = vivintApi.deviceSnapshot().Devices
.filter((data) => data.Id && !cachedIds.includes(data.Id))

let snapshotDevices = vivintApi.deviceSnapshot().Devices
let snapshotAccessories = snapshotDevices
.filter((data) => data.Id)
.map((deviceData) => DeviceSet.createDeviceAccessory(deviceData))
.filter((dvc) => dvc)

let snapshotAccessoriesIds = snapshotAccessories.map((acc) => acc.context.id)
let removedAccessories = cachedAccessories
.filter((acc) => !snapshotAccessoriesIds.includes(acc.context.id))

let cachedIds = cachedAccessories.map((acc) => acc.context.id)
let newAccessories = snapshotAccessories
.filter((acc) => !cachedIds.includes(acc.context.id))

log("Removing " + removedAccessories.length + " stale accessories")
removedAccessories.forEach((acc) => log(acc.context))

log("Adding " + newAccessories.length + " new accessories")
newAccessories.forEach((acc) => log(acc.context))

api.unregisterPlatformAccessories(PluginName, PlatformName, removedAccessories)
api.registerPlatformAccessories(PluginName, PlatformName, newAccessories)
// Todo - remove cachedAccessories not in the snapshot anymore, and don't bind them

cachedAccessories = cachedAccessories.filter((el) => !removedAccessories.includes(el));
cachedAccessories.forEach((accessory) => deviceSet.bindAccessory(accessory))
newAccessories.forEach((accessory) => deviceSet.bindAccessory(accessory))

pubNub.addListener({
status: function(statusEvent) {
//Log unsuccesful
//Log unsuccesful event, PubNub SDK will reconnect automatically
if (statusEvent.category !== 'PNConnectedCategory')
log("Could not connect to Pubnub, reconnecting...", statusEvent)
},
Expand Down
2 changes: 1 addition & 1 deletion lib/device_set.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter

handleSnapshot(deviceData, timestamp) {
this.lastSnapshotTime = timestamp
log("Handling incoming device snapshot for timestamp", timestamp)
//log("Handling incoming device snapshot for timestamp", timestamp)

// update armed status
this.handleSecurity(deviceData.Status)
Expand Down
9 changes: 6 additions & 3 deletions lib/vivint_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function VivintApiModule(config, log) {
renewSystemInfo() {
return VivintApi.getSystemInfo(this.cookie, this.panelId).then((sysInfo) => {
this.systemInfo = sysInfo
return true
return this
})
}

Expand Down Expand Up @@ -175,9 +175,12 @@ function VivintApiModule(config, log) {
request({
"url": "https://vivintsky.com/api/systems/" + panelId,
"headers": {
"Cookie": cookie
"Cookie": cookie,
"Cache-Control": "no-store"
}
}).then((sysInfo) => { return mapObject(JSON.parse(sysInfo), VivintDict) })
}).then((sysInfo) => {
return mapObject(JSON.parse(sysInfo), VivintDict)
})


VivintApi.login = (creds, persistent = 0) => {
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "homebridge-vivint",
"version": "0.0.6",
"version": "0.0.7",
"description": "Control Vivint with HomeBridge",
"license": "ISC",
"author": "Tim Harper <[email protected]>",
Expand Down

0 comments on commit a44e999

Please sign in to comment.