@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -1
- package/README.md +1 -2
- package/config.schema.json +51 -32
- package/dist/device/bot.d.ts +32 -29
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +549 -575
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +33 -15
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +426 -341
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +16 -9
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +246 -208
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +21 -18
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +449 -449
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +22 -20
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +346 -324
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +22 -10
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +257 -178
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +21 -14
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +287 -239
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +23 -10
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +308 -190
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +17 -10
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +225 -193
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +24 -17
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +270 -267
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +36 -14
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +447 -299
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -14
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +177 -169
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -5
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -57
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +3 -4
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -33
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +3 -4
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +66 -48
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +3 -4
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +48 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +3 -4
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +47 -33
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +10 -11
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +64 -48
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -12
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +52 -41
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -11
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +52 -42
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +0 -4
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +44 -66
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +3 -3
- package/dist/settings.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/device/bot.ts +551 -589
- package/src/device/colorbulb.ts +441 -375
- package/src/device/contact.ts +249 -213
- package/src/device/curtain.ts +452 -461
- package/src/device/humidifier.ts +358 -365
- package/src/device/lock.ts +263 -179
- package/src/device/meter.ts +302 -253
- package/src/device/meterplus.ts +319 -194
- package/src/device/motion.ts +230 -199
- package/src/device/plug.ts +273 -274
- package/src/device/striplight.ts +460 -316
- package/src/irdevice/airconditioner.ts +181 -183
- package/src/irdevice/airpurifier.ts +70 -60
- package/src/irdevice/camera.ts +46 -36
- package/src/irdevice/fan.ts +64 -49
- package/src/irdevice/light.ts +47 -51
- package/src/irdevice/other.ts +46 -36
- package/src/irdevice/tv.ts +64 -51
- package/src/irdevice/vacuumcleaner.ts +52 -45
- package/src/irdevice/waterheater.ts +50 -45
- package/src/platform.ts +44 -68
- package/src/settings.ts +3 -3
package/dist/device/meterplus.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.MeterPlus = void 0;
|
|
7
7
|
const https_1 = __importDefault(require("https"));
|
|
8
8
|
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
const os_1 = require("os");
|
|
10
|
+
const async_mqtt_1 = require("async-mqtt");
|
|
9
11
|
const rxjs_1 = require("rxjs");
|
|
10
12
|
const operators_1 = require("rxjs/operators");
|
|
11
13
|
const super_stringify_1 = __importDefault(require("super-stringify"));
|
|
@@ -20,24 +22,19 @@ class MeterPlus {
|
|
|
20
22
|
this.platform = platform;
|
|
21
23
|
this.accessory = accessory;
|
|
22
24
|
this.device = device;
|
|
25
|
+
//MQTT stuff
|
|
26
|
+
this.mqttClient = null;
|
|
27
|
+
// Connection
|
|
28
|
+
this.BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
29
|
+
this.OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
23
30
|
// default placeholders
|
|
24
31
|
this.logs(device);
|
|
25
|
-
this.openAPI();
|
|
26
32
|
this.scan(device);
|
|
27
33
|
this.refreshRate(device);
|
|
28
34
|
this.config(device);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
else {
|
|
33
|
-
this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
|
|
34
|
-
}
|
|
35
|
-
if (this.CurrentTemperature === undefined) {
|
|
36
|
-
this.CurrentTemperature = 0;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
40
|
-
}
|
|
35
|
+
this.context();
|
|
36
|
+
this.setupHistoryService(device);
|
|
37
|
+
this.setupMqtt(device);
|
|
41
38
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
42
39
|
this.doMeterUpdate = new rxjs_1.Subject();
|
|
43
40
|
this.meterUpdateInProgress = false;
|
|
@@ -105,12 +102,12 @@ class MeterPlus {
|
|
|
105
102
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
|
|
106
103
|
}
|
|
107
104
|
// Battery Service
|
|
108
|
-
if (!
|
|
105
|
+
if (!this.BLE) {
|
|
109
106
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
|
|
110
107
|
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
111
108
|
accessory.removeService(this.batteryService);
|
|
112
109
|
}
|
|
113
|
-
else if (
|
|
110
|
+
else if (this.BLE && !this.batteryService) {
|
|
114
111
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
|
|
115
112
|
(this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
|
|
116
113
|
`${accessory.displayName} Battery`;
|
|
@@ -133,15 +130,20 @@ class MeterPlus {
|
|
|
133
130
|
* Parse the device status from the SwitchBot api
|
|
134
131
|
*/
|
|
135
132
|
async parseStatus() {
|
|
136
|
-
if (this.
|
|
133
|
+
if (this.BLE && !this.SwitchToOpenAPI) {
|
|
134
|
+
await this.BLEparseStatus();
|
|
135
|
+
}
|
|
136
|
+
else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
137
|
+
this.SwitchToOpenAPI = false;
|
|
137
138
|
await this.openAPIparseStatus();
|
|
138
139
|
}
|
|
139
140
|
else {
|
|
140
|
-
|
|
141
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
142
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
async BLEparseStatus() {
|
|
144
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
146
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
145
147
|
// Battery
|
|
146
148
|
this.BatteryLevel = Number(this.battery);
|
|
147
149
|
if (this.BatteryLevel < 15) {
|
|
@@ -164,36 +166,35 @@ class MeterPlus {
|
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
async openAPIparseStatus() {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
170
|
+
// Current Relative Humidity
|
|
171
|
+
if (!this.device.meter?.hide_humidity) {
|
|
172
|
+
this.CurrentRelativeHumidity = this.Humidity;
|
|
173
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
|
|
169
174
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
this.CurrentRelativeHumidity = this.Humidity;
|
|
175
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
|
|
176
|
-
}
|
|
177
|
-
// Current Temperature
|
|
178
|
-
if (!this.device.meter?.hide_temperature) {
|
|
179
|
-
this.CurrentTemperature = this.Temperature;
|
|
180
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
181
|
-
}
|
|
175
|
+
// Current Temperature
|
|
176
|
+
if (!this.device.meter?.hide_temperature) {
|
|
177
|
+
this.CurrentTemperature = this.Temperature;
|
|
178
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
182
179
|
}
|
|
183
180
|
}
|
|
184
181
|
/**
|
|
185
182
|
* Asks the SwitchBot API for the latest device information
|
|
186
183
|
*/
|
|
187
184
|
async refreshStatus() {
|
|
188
|
-
if (this.
|
|
189
|
-
this.
|
|
185
|
+
if (this.BLE) {
|
|
186
|
+
await this.BLERefreshStatus();
|
|
187
|
+
}
|
|
188
|
+
else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
189
|
+
await this.openAPIRefreshStatus();
|
|
190
190
|
}
|
|
191
191
|
else {
|
|
192
|
-
this.
|
|
192
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
193
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
|
-
async
|
|
196
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
196
|
+
async BLERefreshStatus() {
|
|
197
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
197
198
|
const switchbot = await this.platform.connectBLE();
|
|
198
199
|
// Convert to BLE Address
|
|
199
200
|
this.device.bleMac = this.device
|
|
@@ -219,9 +220,12 @@ class MeterPlus {
|
|
|
219
220
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
220
221
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
221
222
|
}
|
|
223
|
+
if (ad.serviceData.humidity > 0) {
|
|
224
|
+
// reject unreliable data
|
|
225
|
+
this.humidity = ad.serviceData.humidity;
|
|
226
|
+
}
|
|
222
227
|
this.serviceData = ad.serviceData;
|
|
223
228
|
this.temperature = ad.serviceData.temperature.c;
|
|
224
|
-
this.humidity = ad.serviceData.humidity;
|
|
225
229
|
this.battery = ad.serviceData.battery;
|
|
226
230
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${(0, super_stringify_1.default)(ad.serviceData)}`);
|
|
227
231
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
|
|
@@ -251,122 +255,87 @@ class MeterPlus {
|
|
|
251
255
|
}
|
|
252
256
|
})
|
|
253
257
|
.catch(async (e) => {
|
|
254
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
255
|
-
if (this.deviceLogging.includes('debug')) {
|
|
256
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
|
|
257
|
-
+ ` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
258
|
-
}
|
|
259
|
-
if (this.platform.config.credentials?.token) {
|
|
260
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
261
|
-
this.SwitchToOpenAPI = true;
|
|
262
|
-
this.openAPIRefreshStatus();
|
|
263
|
-
}
|
|
264
258
|
this.apiError(e);
|
|
259
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
260
|
+
+ ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
261
|
+
await this.BLEconnection(switchbot);
|
|
265
262
|
});
|
|
266
263
|
}
|
|
267
264
|
else {
|
|
268
265
|
await this.BLEconnection(switchbot);
|
|
269
266
|
}
|
|
270
267
|
}
|
|
271
|
-
async getCustomBLEAddress(switchbot) {
|
|
272
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
273
|
-
(async () => {
|
|
274
|
-
// Start to monitor advertisement packets
|
|
275
|
-
await switchbot.startScan({
|
|
276
|
-
model: 'i',
|
|
277
|
-
});
|
|
278
|
-
// Set an event handler
|
|
279
|
-
switchbot.onadvertisement = (ad) => {
|
|
280
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
|
|
281
|
-
};
|
|
282
|
-
await switchbot.wait(10000);
|
|
283
|
-
// Stop to monitor
|
|
284
|
-
switchbot.stopScan();
|
|
285
|
-
})();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async BLEconnection(switchbot) {
|
|
289
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
290
|
-
if (this.platform.config.credentials?.token) {
|
|
291
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
292
|
-
this.SwitchToOpenAPI = true;
|
|
293
|
-
await this.openAPIRefreshStatus();
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
268
|
async openAPIRefreshStatus() {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
325
|
-
});
|
|
326
|
-
res.on('end', () => {
|
|
327
|
-
try {
|
|
328
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
329
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
|
|
330
|
-
this.Humidity = this.deviceStatus.body.humidity;
|
|
331
|
-
this.Temperature = this.deviceStatus.body.temperature;
|
|
332
|
-
this.parseStatus();
|
|
333
|
-
this.updateHomeKitCharacteristics();
|
|
334
|
-
}
|
|
335
|
-
catch (e) {
|
|
336
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
337
|
-
}
|
|
338
|
-
});
|
|
269
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
270
|
+
try {
|
|
271
|
+
const t = Date.now();
|
|
272
|
+
const nonce = 'requestID';
|
|
273
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
274
|
+
const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
275
|
+
const sign = signTerm.toString('base64');
|
|
276
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
277
|
+
const options = {
|
|
278
|
+
hostname: settings_1.HostDomain,
|
|
279
|
+
port: 443,
|
|
280
|
+
path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
|
|
281
|
+
method: 'GET',
|
|
282
|
+
headers: {
|
|
283
|
+
Authorization: this.platform.config.credentials?.token,
|
|
284
|
+
sign: sign,
|
|
285
|
+
nonce: nonce,
|
|
286
|
+
t: t,
|
|
287
|
+
'Content-Type': 'application/json',
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
const req = https_1.default.request(options, (res) => {
|
|
291
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
292
|
+
let rawData = '';
|
|
293
|
+
res.on('data', (d) => {
|
|
294
|
+
rawData += d;
|
|
295
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
339
296
|
});
|
|
340
|
-
|
|
341
|
-
|
|
297
|
+
res.on('end', () => {
|
|
298
|
+
try {
|
|
299
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
300
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
|
|
301
|
+
this.Humidity = this.deviceStatus.body.humidity;
|
|
302
|
+
this.Temperature = this.deviceStatus.body.temperature;
|
|
303
|
+
this.parseStatus();
|
|
304
|
+
this.updateHomeKitCharacteristics();
|
|
305
|
+
}
|
|
306
|
+
catch (e) {
|
|
307
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
308
|
+
}
|
|
342
309
|
});
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` +
|
|
349
|
-
` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
350
|
-
}
|
|
351
|
-
this.apiError(e);
|
|
352
|
-
}
|
|
310
|
+
});
|
|
311
|
+
req.on('error', (e) => {
|
|
312
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
313
|
+
});
|
|
314
|
+
req.end();
|
|
353
315
|
}
|
|
354
|
-
|
|
355
|
-
this.
|
|
316
|
+
catch (e) {
|
|
317
|
+
this.apiError(e);
|
|
318
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
319
|
+
+ ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
356
320
|
}
|
|
357
321
|
}
|
|
358
322
|
/**
|
|
359
323
|
* Updates the status for each of the HomeKit Characteristics
|
|
360
324
|
*/
|
|
361
325
|
async updateHomeKitCharacteristics() {
|
|
326
|
+
const mqttmessage = [];
|
|
327
|
+
const entry = { time: Math.round(new Date().valueOf() / 1000) };
|
|
362
328
|
if (!this.device.meter?.hide_humidity) {
|
|
363
329
|
if (this.CurrentRelativeHumidity === undefined) {
|
|
364
330
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
365
331
|
}
|
|
366
332
|
else {
|
|
333
|
+
this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
|
|
367
334
|
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
|
|
368
335
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
369
336
|
+ ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
337
|
+
mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
|
|
338
|
+
entry['humidity'] = this.CurrentRelativeHumidity;
|
|
370
339
|
}
|
|
371
340
|
}
|
|
372
341
|
if (!this.device.meter?.hide_temperature) {
|
|
@@ -374,15 +343,20 @@ class MeterPlus {
|
|
|
374
343
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
|
|
375
344
|
}
|
|
376
345
|
else {
|
|
346
|
+
mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
|
|
347
|
+
entry['temp'] = this.CurrentTemperature;
|
|
348
|
+
this.accessory.context.CurrentTemperature = this.CurrentTemperature;
|
|
377
349
|
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
|
|
378
350
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
|
|
379
351
|
}
|
|
380
352
|
}
|
|
381
|
-
if (this.
|
|
353
|
+
if (this.BLE) {
|
|
382
354
|
if (this.BatteryLevel === undefined) {
|
|
383
355
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
384
356
|
}
|
|
385
357
|
else {
|
|
358
|
+
mqttmessage.push(`"battery": ${this.BatteryLevel}`);
|
|
359
|
+
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
386
360
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
387
361
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
388
362
|
}
|
|
@@ -390,23 +364,89 @@ class MeterPlus {
|
|
|
390
364
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
391
365
|
}
|
|
392
366
|
else {
|
|
367
|
+
mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
|
|
368
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
393
369
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
394
370
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
395
371
|
}
|
|
396
372
|
}
|
|
373
|
+
this.mqttPublish(`{${mqttmessage.join(',')}}`);
|
|
374
|
+
if (this.CurrentRelativeHumidity > 0) {
|
|
375
|
+
// reject unreliable data
|
|
376
|
+
this.historyService?.addEntry(entry);
|
|
377
|
+
}
|
|
397
378
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
379
|
+
/*
|
|
380
|
+
* Publish MQTT message for topics of
|
|
381
|
+
* 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
|
|
382
|
+
*/
|
|
383
|
+
mqttPublish(message) {
|
|
384
|
+
const mac = this.device.deviceId
|
|
385
|
+
?.toLowerCase()
|
|
386
|
+
.match(/[\s\S]{1,2}/g)
|
|
387
|
+
?.join(':');
|
|
388
|
+
const options = this.device.mqttPubOptions || {};
|
|
389
|
+
this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
|
|
390
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${(0, super_stringify_1.default)(options)}`);
|
|
391
|
+
}
|
|
392
|
+
/*
|
|
393
|
+
* Setup MQTT hadler if URL is specifed.
|
|
394
|
+
*/
|
|
395
|
+
async setupMqtt(device) {
|
|
396
|
+
if (device.mqttURL) {
|
|
397
|
+
try {
|
|
398
|
+
this.mqttClient = await (0, async_mqtt_1.connectAsync)(device.mqttURL, device.mqttOptions || {});
|
|
399
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
|
|
400
|
+
this.mqttClient.on('error', (e) => {
|
|
401
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
catch (e) {
|
|
405
|
+
this.mqttClient = null;
|
|
406
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
|
|
407
|
+
}
|
|
401
408
|
}
|
|
402
|
-
|
|
403
|
-
|
|
409
|
+
}
|
|
410
|
+
/*
|
|
411
|
+
* Setup EVE history graph feature if enabled.
|
|
412
|
+
*/
|
|
413
|
+
async setupHistoryService(device) {
|
|
414
|
+
const mac = this.device
|
|
415
|
+
.deviceId.match(/.{1,2}/g)
|
|
416
|
+
.join(':')
|
|
417
|
+
.toLowerCase();
|
|
418
|
+
this.historyService = device.history
|
|
419
|
+
? new this.platform.fakegatoAPI('room', this.accessory, {
|
|
420
|
+
log: this.platform.log,
|
|
421
|
+
storage: 'fs',
|
|
422
|
+
filename: `${(0, os_1.hostname)().split('.')[0]}_${mac}_persist.json`,
|
|
423
|
+
})
|
|
424
|
+
: null;
|
|
425
|
+
}
|
|
426
|
+
async getCustomBLEAddress(switchbot) {
|
|
427
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
428
|
+
(async () => {
|
|
429
|
+
// Start to monitor advertisement packets
|
|
430
|
+
await switchbot.startScan({
|
|
431
|
+
model: 'i',
|
|
432
|
+
});
|
|
433
|
+
// Set an event handler
|
|
434
|
+
switchbot.onadvertisement = (ad) => {
|
|
435
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
|
|
436
|
+
};
|
|
437
|
+
await switchbot.wait(10000);
|
|
438
|
+
// Stop to monitor
|
|
439
|
+
switchbot.stopScan();
|
|
440
|
+
})();
|
|
404
441
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
442
|
+
}
|
|
443
|
+
async BLEconnection(switchbot) {
|
|
444
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
445
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
446
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
447
|
+
this.SwitchToOpenAPI = true;
|
|
448
|
+
await this.openAPIRefreshStatus();
|
|
408
449
|
}
|
|
409
|
-
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
410
450
|
}
|
|
411
451
|
model(device) {
|
|
412
452
|
let model;
|
|
@@ -418,28 +458,125 @@ class MeterPlus {
|
|
|
418
458
|
}
|
|
419
459
|
return model;
|
|
420
460
|
}
|
|
421
|
-
async
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
461
|
+
async scan(device) {
|
|
462
|
+
if (device.scanDuration) {
|
|
463
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
464
|
+
if (this.BLE) {
|
|
465
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
466
|
+
}
|
|
425
467
|
}
|
|
426
|
-
|
|
427
|
-
|
|
468
|
+
else {
|
|
469
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
470
|
+
if (this.BLE) {
|
|
471
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
472
|
+
}
|
|
428
473
|
}
|
|
429
|
-
|
|
430
|
-
|
|
474
|
+
}
|
|
475
|
+
async statusCode({ res }) {
|
|
476
|
+
switch (res.statusCode) {
|
|
477
|
+
case 151:
|
|
478
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
479
|
+
break;
|
|
480
|
+
case 152:
|
|
481
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
482
|
+
break;
|
|
483
|
+
case 160:
|
|
484
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
485
|
+
break;
|
|
486
|
+
case 161:
|
|
487
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
488
|
+
this.offlineOff();
|
|
489
|
+
break;
|
|
490
|
+
case 171:
|
|
491
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
|
|
492
|
+
this.offlineOff();
|
|
493
|
+
break;
|
|
494
|
+
case 190:
|
|
495
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
496
|
+
` Or command: ${(0, super_stringify_1.default)(res)} format is invalid`);
|
|
497
|
+
break;
|
|
498
|
+
case 100:
|
|
499
|
+
if (this.platform.debugMode) {
|
|
500
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
if (this.platform.debugMode) {
|
|
505
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
506
|
+
}
|
|
431
507
|
}
|
|
432
|
-
|
|
433
|
-
|
|
508
|
+
}
|
|
509
|
+
async offlineOff() {
|
|
510
|
+
if (this.device.offline) {
|
|
511
|
+
if (!this.device.meter?.hide_humidity) {
|
|
512
|
+
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.accessory.context.CurrentRelativeHumidity);
|
|
513
|
+
}
|
|
514
|
+
if (!this.device.meter?.hide_temperature) {
|
|
515
|
+
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.accessory.context.CurrentTemperature);
|
|
516
|
+
}
|
|
517
|
+
if (this.BLE) {
|
|
518
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.accessory.context.BatteryLevel);
|
|
519
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.accessory.context.StatusLowBattery);
|
|
520
|
+
}
|
|
521
|
+
await this.updateHomeKitCharacteristics();
|
|
434
522
|
}
|
|
435
|
-
|
|
436
|
-
|
|
523
|
+
}
|
|
524
|
+
async apiError(e) {
|
|
525
|
+
if (!this.device.meter?.hide_humidity) {
|
|
526
|
+
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
|
|
437
527
|
}
|
|
438
|
-
if (device.
|
|
439
|
-
|
|
528
|
+
if (!this.device.meter?.hide_temperature) {
|
|
529
|
+
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
|
|
440
530
|
}
|
|
441
|
-
if (
|
|
442
|
-
this.
|
|
531
|
+
if (this.BLE) {
|
|
532
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
533
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
FirmwareRevision(accessory, device) {
|
|
537
|
+
let FirmwareRevision;
|
|
538
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
539
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
540
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
541
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
542
|
+
if (accessory.context.FirmwareRevision) {
|
|
543
|
+
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
544
|
+
}
|
|
545
|
+
else if (device.firmware) {
|
|
546
|
+
FirmwareRevision = device.firmware;
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
FirmwareRevision = this.platform.version;
|
|
550
|
+
}
|
|
551
|
+
return FirmwareRevision;
|
|
552
|
+
}
|
|
553
|
+
context() {
|
|
554
|
+
if (this.CurrentRelativeHumidity === undefined) {
|
|
555
|
+
this.CurrentRelativeHumidity = 0;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
|
|
559
|
+
}
|
|
560
|
+
if (this.CurrentTemperature === undefined) {
|
|
561
|
+
this.CurrentTemperature = 0;
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
565
|
+
}
|
|
566
|
+
if (this.BLE) {
|
|
567
|
+
if (this.BatteryLevel === undefined) {
|
|
568
|
+
this.BatteryLevel = 100;
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
this.BatteryLevel = this.accessory.context.BatteryLevel;
|
|
572
|
+
}
|
|
573
|
+
if (this.StatusLowBattery === undefined) {
|
|
574
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
575
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
this.StatusLowBattery = this.accessory.context.StatusLowBattery;
|
|
579
|
+
}
|
|
443
580
|
}
|
|
444
581
|
}
|
|
445
582
|
async refreshRate(device) {
|
|
@@ -452,27 +589,25 @@ class MeterPlus {
|
|
|
452
589
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
453
590
|
}
|
|
454
591
|
}
|
|
455
|
-
async
|
|
456
|
-
|
|
457
|
-
|
|
592
|
+
async config(device) {
|
|
593
|
+
let config = {};
|
|
594
|
+
if (device.meter) {
|
|
595
|
+
config = device.meter;
|
|
458
596
|
}
|
|
459
|
-
|
|
460
|
-
|
|
597
|
+
if (device.connectionType !== undefined) {
|
|
598
|
+
config['connectionType'] = device.connectionType;
|
|
461
599
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
async scan(device) {
|
|
465
|
-
if (device.scanDuration) {
|
|
466
|
-
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
467
|
-
if (device.ble) {
|
|
468
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
469
|
-
}
|
|
600
|
+
if (device.logging !== undefined) {
|
|
601
|
+
config['logging'] = device.logging;
|
|
470
602
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
603
|
+
if (device.refreshRate !== undefined) {
|
|
604
|
+
config['refreshRate'] = device.refreshRate;
|
|
605
|
+
}
|
|
606
|
+
if (device.scanDuration !== undefined) {
|
|
607
|
+
config['scanDuration'] = device.scanDuration;
|
|
608
|
+
}
|
|
609
|
+
if (Object.entries(config).length !== 0) {
|
|
610
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
|
|
476
611
|
}
|
|
477
612
|
}
|
|
478
613
|
async logs(device) {
|
|
@@ -493,23 +628,6 @@ class MeterPlus {
|
|
|
493
628
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
494
629
|
}
|
|
495
630
|
}
|
|
496
|
-
FirmwareRevision(accessory, device) {
|
|
497
|
-
let FirmwareRevision;
|
|
498
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
499
|
-
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
500
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
501
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
502
|
-
if (accessory.context.FirmwareRevision) {
|
|
503
|
-
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
504
|
-
}
|
|
505
|
-
else if (device.firmware) {
|
|
506
|
-
FirmwareRevision = device.firmware;
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
FirmwareRevision = this.platform.version;
|
|
510
|
-
}
|
|
511
|
-
return FirmwareRevision;
|
|
512
|
-
}
|
|
513
631
|
/**
|
|
514
632
|
* Logging for Device
|
|
515
633
|
*/
|