-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
195 lines (165 loc) · 7.76 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
"use strict";
const frigengine = require('./frigidairmain');
const dehumidifierAppliance = require('./accessories/dehumfier');
const airpurifierAppliance = require('./accessories/airpurifier');
const PLUGIN_NAME = 'homebridge-frigidaire-dehumidifier';
const PLATFORM_NAME = 'FrigidaireAppliance';
const CLEAN_AIR_MODE = '1004';
const DEHUMIDIFIER = "DH";
var Service, Characteristic, HomebridgeAPI, UUIDGen;
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
HomebridgeAPI = homebridge;
UUIDGen = homebridge.hap.uuid;
homebridge.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, FrigidaireAppliancePlatform);
}
class FrigidaireAppliancePlatform {
constructor(log, config, api) {
this.log = log;
this.api = api;
this.name = config.name;
this.config = config;
this.accessories = [];
this.persistPath = undefined;
// Check if authentication information has been provided.
try{
if ((this.config.auth.username == "") || (this.config.auth.password == "") || (!this.config.auth.password) || (!this.config.auth.username))
{
this.log.error('Plug-in configuration error: Frigidaire Application authentication information not provided.');
// terminate plug-in initialization
return;
}
}
catch(err) {
this.log.error('Plug-in configuration error: Frigidaire Application authentication information not provided.');
// terminate plug-in initialization
return;
}
// Determine if purifiers should be enabled
this.enableAirPurifier = this.config.enableAirPurifier ?? true;
// Homebridge storage folder for local storage of access and refresh token
this.persistPath = api.user.persistPath();
// Create new frigidaire device retrival object
this.frig = new frigengine (log, this.config, this.persistPath);
// When this event is fired it means Homebridge has restored all cached accessories from disk.
// Dynamic Platform plugins should only register new accessories after this event was fired,
// in order to ensure they weren't added to homebridge already. This event can also be used
// to start discovery of new accessories.
api.on('didFinishLaunching', () => {
this.initialLoad = this.frig.init().then (() => {
// Once devices are discovered update Homekit accessories
this.refreshAccessories();
}).catch(err => {
this.log.error('Frigidaire Application initialization Failure:', err);
// terminate plug-in initialization
return;
});
});
}
// Create associates in Homekit based on devices in Frigidaire Appliance account
async refreshAccessories() {
// Track number of device added to homekit
var homekit_appliance_count = 0;
// Process each flo devices and create accessories within the platform.
if(this.frig.frig_devices.length <= 0) return;
// Process each appliance
for (var i = 0; i < this.frig.frig_devices.length; i++) {
let currentDevice = this.frig.frig_devices[i];
this.log.debug(this.frig.frig_devices[i]);
// Confirm appliance is a dehumidifier
if (currentDevice.destination == DEHUMIDIFIER) {
this.log(`Configuring ${currentDevice.name} with a Device ID: ${currentDevice.deviceId}`);
let deviceAccessory = new dehumidifierAppliance(this.frig, i, currentDevice, this.config, this.log, Service, Characteristic, UUIDGen);
// check the accessory was not restored from cache
let foundAccessory = this.accessories.find(accessory => accessory.UUID === deviceAccessory.uuid)
if (!foundAccessory) {
// create a new accessory
let newAccessory = new this.api.platformAccessory(deviceAccessory.name, deviceAccessory.uuid);
// add services and Characteristic
deviceAccessory.setAccessory(newAccessory);
// register the accessory
this.addAccessory(deviceAccessory);
}
else {// accessory already exist just set characteristic
deviceAccessory.setAccessory(foundAccessory);
}
// if clean air enabled create an air purifier tile to control functionality.
if (this.enableAirPurifier) {
let deviceAccessoryAir = new airpurifierAppliance(this.frig, i, currentDevice, this.config, this.log, Service, Characteristic, UUIDGen, deviceAccessory);
// check the accessory was not restored from cache
let foundAccessory = this.accessories.find(accessory => accessory.UUID === deviceAccessoryAir.uuid)
if (!foundAccessory) {
// create a new accessory
let newAccessory = new this.api.platformAccessory(deviceAccessoryAir.name, deviceAccessoryAir.uuid);
// add services and Characteristic
deviceAccessoryAir.setAccessory(newAccessory);
// register the accessory
this.addAccessory(deviceAccessoryAir);
}
else {// accessory already exist just set characteristic
deviceAccessoryAir.setAccessory(foundAccessory);
}
}
homekit_appliance_count += 1;
}
}
this.log.info(`Frigidaire Appliance configured: ${homekit_appliance_count}`);
// Clean accessories with no association with Flo devices.
this.orphanAccessory();
//Start background process to poll devices, if any devices were present
if (homekit_appliance_count != 0) {
this.log.info(`Frigidaire background update process started. Appliance status will be check each ${Math.floor((this.config.deviceRefresh / 60))} min(s) ${Math.floor((this.config.deviceRefresh % 60))} second(s).`);
this.frig.startPollingProcess();
}
};
// Find accessory with no association with frigidaire appliances and remove
async orphanAccessory() {
var cachedAccessory = this.accessories;
var foundAccessory;
for (var i = 0; i < cachedAccessory.length; i++)
{
let accessory = cachedAccessory[i];
// determine if accessory is currently a device in frigidaire account, thus should remain
foundAccessory = this.frig.frig_devices.find(device => UUIDGen.generate(device.deviceId.toString()) === accessory.UUID)
if (!foundAccessory) {
if (this.enableAirPurifier) {
// check for additional accessories that is link to this device.
foundAccessory = this.frig.frig_devices.find(device => UUIDGen.generate(device.deviceId.toString()+ "-" + CLEAN_AIR_MODE) === accessory.UUID)
if (!foundAccessory)
this.removeAccessory(accessory,true);
}
else
this.removeAccessory(accessory,true);
}
}
}
//Add accessory to homekit dashboard
addAccessory(device) {
this.log.debug('Adding accessory');
try {
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [device.accessory]);
this.accessories.push(device.accessory);
} catch (err) {
this.log.error(`An error occurred while adding accessory: ${err}`);
}
}
//Remove accessory to homekit dashboard
removeAccessory(accessory, updateIndex) {
this.log.info('Removing accessory from cache:',accessory.displayName );
if (accessory) {
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
}
if (updateIndex) {
if (this.accessories.indexOf(accessory) > -1) {
this.accessories.splice(this.accessories.indexOf(accessory), 1);
}}
}
// This function is invoked when homebridge restores cached accessories from disk at startup.
// It should be used to setup event handlers for characteristics and update respective values.
configureAccessory(accessory) {
this.log.info('Loading accessory from cache:', accessory.displayName);
// add the restored accessory to the accessories cache so we can track if it has already been registered
this.accessories.push(accessory);
}
}