forked from balansse/homebridge-vivint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
133 lines (110 loc) · 4.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
var Accessory, Service, Characteristic, UUIDGen;
const PluginName = "homebridge-vivint";
const PlatformName = "Vivint";
const VivintApiModule = require("./lib/vivint_api.js");
const DeviceSetModule = require("./lib/device_set.js");
const ThermostatCharacteristicsModule = require("./lib/thermostat_characteristics.js");
function asyncAccumulator() {
let accum = [];
var open = true;
let append = (e) => {
if (open)
accum.push(e);
else
throw "Accumulator is closed"
};
var promiseCompleter = null;
let finalize = () => {
open = false;
promiseCompleter(accum)
};
let result = new Promise((success, reject) => {
promiseCompleter = success
});
return {append, finalize, result}
}
module.exports = function (homebridge) {
Accessory = homebridge.platformAccessory;
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
UUIDGen = homebridge.hap.uuid;
let ThermostatCharacteristics = ThermostatCharacteristicsModule(homebridge);
function setCatastrophe(accessories) {
accessories.forEach((accessory) => {
accessory.services
.filter((service) => service.UUID != Service.AccessoryInformation)
.forEach((service) => {
service.characteristics.forEach((characteristic) => {
characteristic.on('get', (next) => {
next(new Error("Platform failed to initialize"))
})
})
})
})
}
class VivintPlatform {
constructor(log, config, api) {
this.log = log;
this.config = config;
this.api = api;
let VivintApi = VivintApiModule(config, log);
this.vivintApiPromise = VivintApi.login({username: config.username, password: config.password});
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))
}, apiLoginRefreshSecs * 1000);
return {deviceSet, DeviceSet};
});
let pubNubPromise = this.vivintApiPromise.then((vivintApi) => vivintApi.connectPubNub());
this.cachedAccessories = asyncAccumulator();
api.on('didFinishLaunching', () => this.cachedAccessories.finalize());
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().d
.filter((data) => data._id && ! cachedIds.includes(data._id))
.map((deviceData) => DeviceSet.createDeviceAccessory(deviceData))
.filter((dvc) => dvc);
log("Adding " + newAccessories.length + " new accessories");
newAccessories.forEach((acc) => log(acc.context));
api.registerPlatformAccessories(PluginName, PlatformName, newAccessories);
// Todo - remove cachedAccessories not in the snapshot anymore, and don't bind them
cachedAccessories.forEach((accessory) => deviceSet.bindAccessory(accessory));
newAccessories.forEach((accessory) => deviceSet.bindAccessory(accessory));
pubNub.addListener({
status: function(statusEvent) {
console.log("status", statusEvent)
},
message: function(msg) {
log("received pubNub msg");
log(JSON.stringify(msg.message));
deviceSet.handleMessage(msg)
},
presence: function(presenceEvent) {
console.log("presence", presenceEvent)
}
});
deviceSet.handleSnapshot(vivintApi.deviceSnapshot(), vivintApi.deviceSnapshotTs())
}
).catch((error) => {
log("Error while bootstrapping accessories");
log(error);
// Make it obvious that things are bad by causing everything to show as "no response"
this.cachedAccessories.result.then(setCatastrophe)
});
}
configureAccessory(accessory) {
console.log("received cached accessory", accessory);
this.cachedAccessories.append(accessory)
}
}
homebridge.registerPlatform(PluginName, PlatformName, VivintPlatform);
};