Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Few fixes with persistent authentication #21

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = function (homebridge) {
})
})
})

}

class VivintPlatform {
Expand All @@ -59,7 +60,7 @@ module.exports = function (homebridge) {
this.api = api

let VivintApi = VivintApiModule(config, log)
this.vivintApiPromise = VivintApi.login({username: config.username, password: config.password})
this.vivintApiPromise = VivintApi.login({username: config.username, password: config.password}, 1)
let apiLoginRefreshSecs = config.apiLoginRefreshSecs || 1200 // once per 20 minutes default


Expand Down Expand Up @@ -129,5 +130,5 @@ module.exports = function (homebridge) {
}
}

homebridge.registerPlatform(PluginName, PlatformName, VivintPlatform);
homebridge.registerPlatform(PluginName, PlatformName, VivintPlatform)
};
34 changes: 26 additions & 8 deletions lib/device_set.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
}

contactBatteryLevelValue() {
return this.data.bl
return this.data.bl || 1
}

notify() {
Expand Down Expand Up @@ -320,15 +320,15 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
}

motionBatteryLevelValue() {
return this.data.bl
return this.data.bl || 1
}

notify() {
if (this.motionDetectedValue()) {
this.lastSensedMotion = Date.now()
}

if (this.motionBatteryLevelValue()) {
if (this.motionBatteryLevelValue() && this.serviceb) {
if (0 <= this.motionBatteryLevelValue() && this.motionBatteryLevelValue() <= config_LowBatteryLevel) {
this.serviceb.getCharacteristic(Characteristic.StatusLowBattery).updateValue(Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW)
} else this.serviceb.getCharacteristic(Characteristic.StatusLowBattery).updateValue(Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL)
Expand All @@ -344,7 +344,7 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
}
extend(MotionSensor, {
appliesTo: (data) => {
return ((data.t == "wireless_sensor") && ((data.ec == 1249) || (data.ec == 1249)))
return ((data.t == "wireless_sensor") && (data.ec == 1249))
},
addServices: (accessory) => {
accessory.addService(new Service.MotionSensor(accessory.context.name))
Expand Down Expand Up @@ -386,7 +386,7 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
}

lockBatteryLevelValue() {
return this.data.bl
return this.data.bl || 1
}

setLockTargetStateCharacteristic(targetState, next) {
Expand Down Expand Up @@ -596,9 +596,8 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter


doorCurrentValue() {
//log("doorCurrentValue() this.data.s: " + this.data.s)

switch(this.data.s){
case 0: // unknown state but this eliminates double notification
case GARAGEDOOR_VIVINT_CLOSED:
return Characteristic.CurrentDoorState.CLOSED

Expand Down Expand Up @@ -716,6 +715,24 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
constructor(accessory) {
super(accessory)

let self = this
let promiseSetter = function(fn) {
let boundDebounced = debounce(fn.bind(self), 500, {
leading: true
})
return (value, next) => {
boundDebounced(value).then(
(result) => {
next()
},
(failure) => {
log("failure " + failure)
next(failure)
}
)
}
}

this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb)

this.service
Expand All @@ -726,7 +743,8 @@ function DeviceSetModule(config, log, homebridge, vivintApi, ThermostatCharacter
this.service
.getCharacteristic(Characteristic.Brightness)
.on('get', (next) => next(null, this.switchBrightnessValue()))
.on('set', this.setBrightnessValue.bind(this))
.on('set', promiseSetter(this.setBrightnessValue.bind(this)))
//.on('set', this.setBrightnessValue.bind(this))

this.last_val_s = null
this.last_val = null
Expand Down
53 changes: 41 additions & 12 deletions lib/vivint_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ const request = require("request-promise-native")
const PubNub = require('pubnub')
const extend = require('util')._extend

const fetchWithRetry = (url) => {
const fetchDataWithRetry = () => {
return request(url)
.then(result => {
return Promise.resolve(result)
})
.catch(err => {
return new Promise((resolve,reject) => {
setTimeout(() => {
return resolve(fetchDataWithRetry())
}, 5000)
})
})
}
return fetchDataWithRetry()
}

function VivintApiModule(config, log) {
class VivintApi {
constructor(creds, panelId, cookie, sessionInfo, systemInfo) {
Expand Down Expand Up @@ -64,7 +81,7 @@ function VivintApiModule(config, log) {

putDevice(category, id, data) {
//In case of Alarm panel there is no id because it is treated on the Panel level
let uriString = id != null ?
let uriString = id != null ?
"/" + category + "/" + id :
"/" + category

Expand All @@ -83,16 +100,28 @@ function VivintApiModule(config, log) {
}
}

VivintApi.doAuth = (creds) => {
let loginRequest = request({
method: "POST",
url: "https://vivintsky.com/api/login",
body: JSON.stringify(creds)
})
return loginRequest.then((r) => {
let sessionInfo = JSON.parse(r)
let cookie = loginRequest.responseContent.headers["set-cookie"][0].split(";")[0]
VivintApi.doAuth = (creds, persistent = 0) => {
let loginRequest = null

if (persistent === 1) {
loginRequest = fetchWithRetry({
method: "POST",
url: "https://vivintsky.com/api/login",
body: JSON.stringify(creds),
resolveWithFullResponse: true
})
} else {
loginRequest = request({
method: "POST",
url: "https://vivintsky.com/api/login",
body: JSON.stringify(creds),
resolveWithFullResponse: true
})
}

return loginRequest.then((r) => {
let sessionInfo = JSON.parse(r.body)
let cookie = r.headers["set-cookie"][0].split(";")[0]
return {sessionInfo: sessionInfo, cookie: cookie}
})
}
Expand All @@ -106,8 +135,8 @@ function VivintApiModule(config, log) {
}).then(JSON.parse)


VivintApi.login = (creds) => {
return VivintApi.doAuth(creds).then((result) => {
VivintApi.login = (creds, persistent = 0) => {
return VivintApi.doAuth(creds, persistent).then((result) => {
let sessionInfo = result.sessionInfo
let cookie = result.cookie
let panelId = sessionInfo.u.system[0].panid
Expand Down