From b43c5c80cde82d03eceeaa8008abd91a45c2bc83 Mon Sep 17 00:00:00 2001 From: Alexandr Balan Date: Fri, 26 Jun 2020 11:00:01 -0500 Subject: [PATCH 1/3] Increase stability of event stream; Dynamically add and remove accessories; Remove excessive logging; --- index.js | 50 +++++++++++++++++++++++++++++++---------------- lib/device_set.js | 2 +- lib/vivint_api.js | 9 ++++++--- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/index.js b/index.js index 98caa3e..15cbe33 100644 --- a/index.js +++ b/index.js @@ -63,20 +63,24 @@ 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((systemInfo) => { - deviceSet.handleSnapshot(vivintApi.deviceSnapshot(), vivintApi.deviceSnapshotTs())}) - .catch((err) => log("error refreshing", err)) + .catch((err) => log("Error refreshing login info", err)) }, apiLoginRefreshSecs * 1000) - return {deviceSet, DeviceSet}; + //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} }) let pubNubPromise = this.vivintApiPromise.then((vivintApi) => vivintApi.connectPubNub()) @@ -86,32 +90,44 @@ 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) { - console.log("status", statusEvent) + //Log unsuccesful event, PubNub SDK will reconnect automatically + if (statusEvent.category !== 'PNConnectedCategory') + log("Could not connect to Pubnub, reconnecting...", statusEvent) }, message: function(msg) { - log("received pubNub msg") - log(JSON.stringify(msg.message)) + //log("received pubNub msg") + //log(JSON.stringify(msg.message)) deviceSet.handleMessage(vivintApi.parsePubNub(msg.message)) - }, - presence: function(presenceEvent) { - console.log("presence", presenceEvent) } }) deviceSet.handleSnapshot(vivintApi.deviceSnapshot(), vivintApi.deviceSnapshotTs()) diff --git a/lib/device_set.js b/lib/device_set.js index 0c9f7c5..c068000 100644 --- a/lib/device_set.js +++ b/lib/device_set.js @@ -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) diff --git a/lib/vivint_api.js b/lib/vivint_api.js index 55ba9f5..7416e8b 100644 --- a/lib/vivint_api.js +++ b/lib/vivint_api.js @@ -98,7 +98,7 @@ function VivintApiModule(config, log) { renewSystemInfo() { return VivintApi.getSystemInfo(this.cookie, this.panelId).then((sysInfo) => { this.systemInfo = sysInfo - return true + return this }) } @@ -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) => { From 990009b725ca274b28e4d5df2abda773e77720c5 Mon Sep 17 00:00:00 2001 From: Alexandr Balan Date: Fri, 26 Jun 2020 11:00:13 -0500 Subject: [PATCH 2/3] Merge conflicts fix --- lib/device_set.js | 4 ++-- lib/vivint_api.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/device_set.js b/lib/device_set.js index c068000..7bd9c7d 100644 --- a/lib/device_set.js +++ b/lib/device_set.js @@ -134,11 +134,11 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter return dc.appliesTo(data) }) if (!deviceClass) { - log("Do not know how to handle device! ID: " + data.Id + " Data.t: " + data.Type + " data.ec: " + data.EquipmentCode + " Data.n: " + data.Name) + log("Unhandled device [ID]: " + data.Id + " [Type]: " + data.Type + " [EquipmentCode]: " + data.EquipmentCode + " [Name]: " + data.Name) return null // we don't know how to handle this device. } if (config_IgnoredDeviceTypes.indexOf(data.Type) != -1){ - log("Ignored device ID: " + data.Id + " Data.t: " + data.Type + " data.ec: " + data.EquipmentCode + " Data.n: " + data.Name) + log("Ignored device [ID]: " + data.Id + " [Type]: " + data.Type + " [EquipmentCode]: " + data.EquipmentCode + " [Name]: " + data.Name) return null } diff --git a/lib/vivint_api.js b/lib/vivint_api.js index 7416e8b..7cdac85 100644 --- a/lib/vivint_api.js +++ b/lib/vivint_api.js @@ -43,7 +43,7 @@ function mapObject(object, dict){ const value = object[property] var mappedProperty = getKeyByValueDeep(dict.Fields, property) - mappedProperty = mappedProperty ?? getKeyByValueDeep(dict, property) ?? property + mappedProperty = mappedProperty || getKeyByValueDeep(dict, property) || property if (!isObject(value) && !Array.isArray(value)){ mappedObject[mappedProperty] = value @@ -103,7 +103,7 @@ function VivintApiModule(config, log) { } connectPubNub() { - let channel = "PlatformChannel#" + this.sessionInfo.u.mbc + let channel = "PlatformChannel#" + this.sessionInfo.Users.MessageBroadcastChannel let pubnub = new PubNub({ subscribeKey : "sub-c-6fb03d68-6a78-11e2-ae8f-12313f022c90" }) From 9931eca64685bb56eed71b98d99d1934545f3037 Mon Sep 17 00:00:00 2001 From: Alexandr Balan Date: Fri, 26 Jun 2020 11:25:30 -0500 Subject: [PATCH 3/3] Updated package version to 0.0.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0815a79..8f782fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "homebridge-vivint", - "version": "0.0.5", + "version": "0.0.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fa33eed..4659b56 100644 --- a/package.json +++ b/package.json @@ -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 ",