@switchbot/homebridge-switchbot 3.5.1-beta.8 → 3.5.1
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 +7 -0
- package/config.schema.json +19 -3
- package/dist/device/blindtilt.d.ts +6 -4
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +60 -46
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +6 -3
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +59 -25
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +6 -3
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +47 -29
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +6 -3
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +53 -36
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +6 -3
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +45 -31
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +6 -4
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +41 -27
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +6 -3
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +59 -152
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +6 -3
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +53 -32
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +6 -3
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +49 -30
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +6 -3
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +47 -28
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +6 -3
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +44 -27
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +6 -3
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +46 -28
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +6 -3
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +38 -25
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +6 -3
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +43 -27
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +6 -3
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +42 -27
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +6 -3
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +37 -24
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +6 -3
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +30 -17
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +6 -3
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +37 -22
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +6 -3
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +44 -25
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +2 -2
- package/dist/irdevice/airconditioner.d.ts +1 -3
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +67 -177
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +0 -1
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +24 -53
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +12 -17
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +22 -38
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +22 -10
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +94 -100
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +20 -38
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +79 -77
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +38 -53
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +11 -16
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +11 -16
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +4 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +564 -665
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +10 -8
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/bledevicestatus.d.ts +2 -1
- package/dist/types/bledevicestatus.d.ts.map +1 -1
- package/dist/types/devicestatus.d.ts +1 -1
- package/dist/types/devicestatus.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/device/blindtilt.ts +64 -48
- package/src/device/bot.ts +79 -26
- package/src/device/ceilinglight.ts +57 -31
- package/src/device/colorbulb.ts +57 -43
- package/src/device/contact.ts +49 -31
- package/src/device/curtain.ts +51 -28
- package/src/device/device.ts +61 -135
- package/src/device/fan.ts +67 -33
- package/src/device/hub.ts +62 -33
- package/src/device/humidifier.ts +60 -33
- package/src/device/iosensor.ts +51 -30
- package/src/device/lightstrip.ts +52 -29
- package/src/device/lock.ts +55 -26
- package/src/device/meter.ts +60 -29
- package/src/device/meterplus.ts +56 -29
- package/src/device/motion.ts +50 -26
- package/src/device/plug.ts +38 -18
- package/src/device/robotvacuumcleaner.ts +53 -24
- package/src/device/waterdetector.ts +63 -27
- package/src/homebridge-ui/public/index.html +2 -2
- package/src/irdevice/airconditioner.ts +76 -165
- package/src/irdevice/airpurifier.ts +29 -49
- package/src/irdevice/camera.ts +13 -16
- package/src/irdevice/fan.ts +25 -35
- package/src/irdevice/irdevice.ts +97 -96
- package/src/irdevice/light.ts +21 -35
- package/src/irdevice/other.ts +79 -77
- package/src/irdevice/tv.ts +40 -51
- package/src/irdevice/vacuumcleaner.ts +12 -15
- package/src/irdevice/waterheater.ts +12 -15
- package/src/platform.ts +566 -696
- package/src/settings.ts +11 -8
- package/src/types/bledevicestatus.ts +4 -2
- package/src/types/devicestatus.ts +1 -1
- package/.github/npm-version-script.cjs +0 -81
package/src/device/device.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { hostname } from 'os';
|
|
7
7
|
import { request } from 'undici';
|
|
8
|
-
import asyncmqtt from 'async-mqtt';
|
|
9
8
|
import { Devices } from '../settings.js';
|
|
10
9
|
import { BlindTiltMappingMode, sleep } from '../utils.js';
|
|
10
|
+
import { SwitchBotModel, SwitchBotBLEModel, SwitchBotBLEModelName, SwitchBotBLEModelFriendlyName } from 'node-switchbot';
|
|
11
11
|
|
|
12
12
|
import type { MqttClient } from 'mqtt';
|
|
13
13
|
import type { device } from '../types/devicelist.js';
|
|
@@ -15,7 +15,6 @@ import type { ad } from '../types/bledevicestatus.js';
|
|
|
15
15
|
import type { SwitchBotPlatform } from '../platform.js';
|
|
16
16
|
import type { SwitchBotPlatformConfig, devicesConfig } from '../settings.js';
|
|
17
17
|
import type { API, CharacteristicValue, HAP, Logging, PlatformAccessory, Service } from 'homebridge';
|
|
18
|
-
import { SwitchBotModel, SwitchBotBLEModel, SwitchBotBLEModelName, SwitchBotBLEModelFriendlyName } from 'node-switchbot';
|
|
19
18
|
|
|
20
19
|
export abstract class deviceBase {
|
|
21
20
|
public readonly api: API;
|
|
@@ -39,6 +38,11 @@ export abstract class deviceBase {
|
|
|
39
38
|
protected deviceModel!: SwitchBotModel;
|
|
40
39
|
protected deviceBLEModel!: SwitchBotBLEModel;
|
|
41
40
|
|
|
41
|
+
// MQTT
|
|
42
|
+
protected deviceMqttURL!: string;
|
|
43
|
+
protected deviceMqttOptions!: any;
|
|
44
|
+
protected deviceMqttPubOptions!: any;
|
|
45
|
+
|
|
42
46
|
// BLE
|
|
43
47
|
protected scanDuration!: number;
|
|
44
48
|
|
|
@@ -68,90 +72,49 @@ export abstract class deviceBase {
|
|
|
68
72
|
this.getDeviceConfigSettings(accessory, device);
|
|
69
73
|
this.getDeviceContext(accessory, device);
|
|
70
74
|
this.getDeviceScanDuration(accessory, device);
|
|
71
|
-
this.
|
|
75
|
+
this.getMqttSettings(device);
|
|
72
76
|
|
|
73
77
|
// Set accessory information
|
|
74
78
|
accessory
|
|
75
79
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
76
80
|
.setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
|
|
77
81
|
.setCharacteristic(this.hap.Characteristic.AppMatchingIdentifier, 'id1087374760')
|
|
78
|
-
.setCharacteristic(this.hap.Characteristic.Name, device.deviceName ?? accessory.displayName)
|
|
79
|
-
.setCharacteristic(this.hap.Characteristic.ConfiguredName, device.deviceName ?? accessory.displayName)
|
|
82
|
+
.setCharacteristic(this.hap.Characteristic.Name, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
|
|
83
|
+
.setCharacteristic(this.hap.Characteristic.ConfiguredName, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
|
|
80
84
|
.setCharacteristic(this.hap.Characteristic.Model, device.model ?? accessory.context.model)
|
|
81
85
|
.setCharacteristic(this.hap.Characteristic.ProductData, device.deviceId ?? accessory.context.deviceId)
|
|
82
86
|
.setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId);
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
async getDeviceLogSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
this.deviceLogging = accessory.context.logging = device.logging;
|
|
91
|
-
this.debugWarnLog(`Using Device Config Logging: ${this.deviceLogging}`);
|
|
92
|
-
} else if (this.config.logging) {
|
|
93
|
-
this.deviceLogging = accessory.context.logging = this.config.logging;
|
|
94
|
-
this.debugWarnLog(`Using Platform Config Logging: ${this.deviceLogging}`);
|
|
95
|
-
} else {
|
|
96
|
-
this.deviceLogging = accessory.context.logging = 'standard';
|
|
97
|
-
this.debugWarnLog(`Logging Not Set, Using: ${this.deviceLogging}`);
|
|
98
|
-
}
|
|
90
|
+
this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.config.logging ?? 'standard';
|
|
91
|
+
const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.config.logging ? 'Platform Config' : 'Default';
|
|
92
|
+
accessory.context.deviceLogging = this.deviceLogging;
|
|
93
|
+
await this.debugLog(`Using ${logging} Logging: ${this.deviceLogging}`);
|
|
99
94
|
}
|
|
100
95
|
|
|
101
96
|
async getDeviceRateSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
102
97
|
// refreshRate
|
|
103
|
-
|
|
104
|
-
this.deviceRefreshRate = device.refreshRate;
|
|
105
|
-
this.debugLog(`Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
106
|
-
} else if (this.config.options?.refreshRate) {
|
|
107
|
-
this.deviceRefreshRate = this.config.options.refreshRate;
|
|
108
|
-
this.debugLog(`Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
109
|
-
} else {
|
|
110
|
-
this.deviceRefreshRate = 5;
|
|
111
|
-
this.debugLog(`Using Default refreshRate: ${this.deviceRefreshRate}`);
|
|
112
|
-
}
|
|
98
|
+
this.deviceRefreshRate = device.refreshRate ?? this.config.options?.refreshRate ?? 5;
|
|
113
99
|
accessory.context.deviceRefreshRate = this.deviceRefreshRate;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.deviceUpdateRate = device.updateRate;
|
|
117
|
-
this.debugLog(`Using Device Config updateRate: ${this.deviceUpdateRate}`);
|
|
118
|
-
} else if (this.config.options?.updateRate) {
|
|
119
|
-
this.deviceUpdateRate = this.config.options.updateRate;
|
|
120
|
-
this.debugLog(`Using Platform Config updateRate: ${this.deviceUpdateRate}`);
|
|
121
|
-
} else {
|
|
122
|
-
this.deviceUpdateRate = 5;
|
|
123
|
-
this.debugLog(`Using Default updateRate: ${this.deviceUpdateRate}`);
|
|
124
|
-
}
|
|
100
|
+
const refreshRate = device.refreshRate ? 'Device Config' : this.config.options?.refreshRate ? 'Platform Config' : 'Default';
|
|
101
|
+
this.deviceUpdateRate = device.updateRate ?? this.config.options?.updateRate ?? 5;
|
|
125
102
|
accessory.context.deviceUpdateRate = this.deviceUpdateRate;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this.devicePushRate = device.pushRate;
|
|
129
|
-
this.debugLog(`Using Device Config pushRate: ${this.deviceUpdateRate}`);
|
|
130
|
-
} else if (this.config.options?.pushRate) {
|
|
131
|
-
this.devicePushRate = this.config.options.pushRate;
|
|
132
|
-
this.debugLog(`Using Platform Config pushRate: ${this.deviceUpdateRate}`);
|
|
133
|
-
} else {
|
|
134
|
-
this.devicePushRate = 1;
|
|
135
|
-
this.debugLog(`Using Default pushRate: ${this.deviceUpdateRate}`);
|
|
136
|
-
}
|
|
103
|
+
const updateRate = device.updateRate ? 'Device Config' : this.config.options?.updateRate ? 'Platform Config' : 'Default';
|
|
104
|
+
this.devicePushRate = device.pushRate ?? this.config.options?.pushRate ?? 1;
|
|
137
105
|
accessory.context.devicePushRate = this.devicePushRate;
|
|
106
|
+
const pushRate = device.pushRate ? 'Device Config' : this.config.options?.pushRate ? 'Platform Config' : 'Default';
|
|
107
|
+
await this.debugLog(`Using ${refreshRate} refreshRate: ${this.deviceRefreshRate}, ${updateRate} updateRate: ${this.deviceUpdateRate},`
|
|
108
|
+
+ ` ${pushRate} pushRate: ${this.devicePushRate}`);
|
|
138
109
|
}
|
|
139
110
|
|
|
140
111
|
async getDeviceRetry(device: device & devicesConfig): Promise<void> {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
if (device.delayBetweenRetries) {
|
|
149
|
-
this.deviceDelayBetweenRetries = device.delayBetweenRetries * 1000;
|
|
150
|
-
this.debugLog(`Using Device Delay Between Retries: ${this.deviceDelayBetweenRetries}`);
|
|
151
|
-
} else {
|
|
152
|
-
this.deviceDelayBetweenRetries = 3000; // Delay between retries in milliseconds
|
|
153
|
-
this.debugLog(`Delay Between Retries Not Set, Using: ${this.deviceDelayBetweenRetries}`);
|
|
154
|
-
}
|
|
112
|
+
this.deviceMaxRetries = device.maxRetries ?? 5;
|
|
113
|
+
const maxRetries = device.maxRetries ? 'Device' : 'Default';
|
|
114
|
+
this.deviceDelayBetweenRetries = device.delayBetweenRetries ? (device.delayBetweenRetries * 1000) : 3000;
|
|
115
|
+
const delayBetweenRetries = device.delayBetweenRetries ? 'Device' : 'Default';
|
|
116
|
+
await this.debugLog(`Using ${maxRetries} Max Retries: ${this.deviceMaxRetries},`
|
|
117
|
+
+ ` ${delayBetweenRetries} Delay Between Retries: ${this.deviceDelayBetweenRetries}`);
|
|
155
118
|
}
|
|
156
119
|
|
|
157
120
|
async retryBLE({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
@@ -167,14 +130,12 @@ export abstract class deviceBase {
|
|
|
167
130
|
}
|
|
168
131
|
|
|
169
132
|
async maxRetryBLE(): Promise<number> {
|
|
170
|
-
|
|
171
|
-
return this.device.maxRetry;
|
|
172
|
-
} else {
|
|
173
|
-
return 5;
|
|
174
|
-
}
|
|
133
|
+
return this.device.maxRetry ? this.device.maxRetry : 5;
|
|
175
134
|
}
|
|
176
135
|
|
|
177
136
|
async getDeviceScanDuration(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
137
|
+
this.scanDuration = device.scanDuration ? (this.deviceUpdateRate > device.scanDuration) ? this.deviceUpdateRate : device.scanDuration
|
|
138
|
+
? (this.deviceUpdateRate > 1) ? this.deviceUpdateRate : 1 : this.deviceUpdateRate : 1;
|
|
178
139
|
if (device.scanDuration) {
|
|
179
140
|
if (this.deviceUpdateRate > device.scanDuration) {
|
|
180
141
|
this.scanDuration = this.deviceUpdateRate;
|
|
@@ -231,6 +192,12 @@ export abstract class deviceBase {
|
|
|
231
192
|
if (device.mqttURL !== '') {
|
|
232
193
|
deviceConfig['mqttURL'] = device.mqttURL;
|
|
233
194
|
}
|
|
195
|
+
if (device.mqttOptions) {
|
|
196
|
+
deviceConfig['mqttOptions'] = device.mqttOptions;
|
|
197
|
+
}
|
|
198
|
+
if (device.mqttPubOptions) {
|
|
199
|
+
deviceConfig['mqttPubOptions'] = device.mqttPubOptions;
|
|
200
|
+
}
|
|
234
201
|
if (device.maxRetries !== 0) {
|
|
235
202
|
deviceConfig['maxRetries'] = device.maxRetries;
|
|
236
203
|
}
|
|
@@ -319,21 +286,10 @@ export abstract class deviceBase {
|
|
|
319
286
|
const numberOfLevels = spaceBetweenLevels + 1;
|
|
320
287
|
this.debugLog(`LightLevel: ${lightLevel}, set_minLux: ${set_minLux}, set_maxLux: ${set_maxLux}, spaceBetweenLevels: ${spaceBetweenLevels},`
|
|
321
288
|
+ ` numberOfLevels: ${numberOfLevels}`);
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.debugLog(`LightLevel: ${lightLevel}, set_minLux: ${set_minLux}`);
|
|
327
|
-
break;
|
|
328
|
-
case numberOfLevels:
|
|
329
|
-
CurrentAmbientLightLevel = set_maxLux;
|
|
330
|
-
this.debugLog(`LightLevel: ${lightLevel}, set_maxLux: ${set_maxLux}`);
|
|
331
|
-
break;
|
|
332
|
-
default:
|
|
333
|
-
CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(lightLevel) - 1);
|
|
334
|
-
this.debugLog(`LightLevel: ${lightLevel}`);
|
|
335
|
-
}
|
|
336
|
-
this.debugLog(`CurrentAmbientLightLevel: ${CurrentAmbientLightLevel}`);
|
|
289
|
+
const CurrentAmbientLightLevel = lightLevel === 1 ? set_minLux : lightLevel = numberOfLevels
|
|
290
|
+
? set_maxLux : ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(lightLevel) - 1);
|
|
291
|
+
await this.debugLog(`CurrentAmbientLightLevel: ${CurrentAmbientLightLevel}, LightLevel: ${lightLevel}, set_minLux: ${set_minLux},`
|
|
292
|
+
+ ` set_maxLux: ${set_maxLux}`);
|
|
337
293
|
return CurrentAmbientLightLevel;
|
|
338
294
|
}
|
|
339
295
|
|
|
@@ -342,41 +298,29 @@ export abstract class deviceBase {
|
|
|
342
298
|
* 'homebridge-switchbot/${this.device.deviceType}/xx:xx:xx:xx:xx:xx'
|
|
343
299
|
*/
|
|
344
300
|
async mqttPublish(message: string, topic?: string) {
|
|
345
|
-
const mac = this.device.deviceId
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const options = this.device.mqttPubOptions || {};
|
|
350
|
-
let mqttTopic: string;
|
|
351
|
-
let mqttMessageTopic: string;
|
|
352
|
-
if (topic) {
|
|
353
|
-
mqttTopic = `/${topic}`;
|
|
354
|
-
mqttMessageTopic = `${topic}/`;
|
|
355
|
-
} else {
|
|
356
|
-
mqttTopic = '';
|
|
357
|
-
mqttMessageTopic = '';
|
|
358
|
-
}
|
|
301
|
+
const mac = this.device.deviceId?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':');
|
|
302
|
+
const options = this.deviceMqttPubOptions ?? {};
|
|
303
|
+
const mqttTopic = topic ? `/${topic}` : '';
|
|
304
|
+
const mqttMessageTopic = topic ? `${topic}/` : '';
|
|
359
305
|
this.mqttClient?.publish(`homebridge-switchbot/${this.device.deviceType}/${mac}${mqttTopic}`, `${message}`, options);
|
|
360
306
|
this.debugLog(`MQTT message: ${mqttMessageTopic}${message} options:${JSON.stringify(options)}`);
|
|
361
307
|
}
|
|
362
308
|
|
|
363
309
|
/*
|
|
364
|
-
*
|
|
310
|
+
* MQTT Settings
|
|
365
311
|
*/
|
|
366
|
-
async
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
}
|
|
312
|
+
async getMqttSettings(device: device & devicesConfig): Promise<void> {
|
|
313
|
+
// mqttURL
|
|
314
|
+
this.deviceMqttURL = device.mqttURL ?? this.config.options?.mqttURL ?? '';
|
|
315
|
+
const mqttURL = device.mqttURL ? 'Device Config' : this.config.options?.mqttURL ? 'Platform Config' : 'Default';
|
|
316
|
+
// mqttOptions
|
|
317
|
+
this.deviceMqttOptions = device.mqttOptions ?? this.config.options?.mqttOptions ?? {};
|
|
318
|
+
const mqttOptions = device.mqttOptions ? 'Device Config' : this.config.options?.mqttOptions ? 'Platform Config' : 'Default';
|
|
319
|
+
// mqttPubOptions
|
|
320
|
+
this.deviceMqttPubOptions = device.mqttPubOptions ?? this.config.options?.mqttPubOptions ?? {};
|
|
321
|
+
const mqttPubOptions = device.mqttPubOptions ? 'Device Config' : this.config.options?.mqttPubOptions ? 'Platform Config' : 'Default';
|
|
322
|
+
await this.debugLog(`Using ${mqttURL} MQTT URL: ${this.deviceMqttURL}, ${mqttOptions} mqttOptions: ${JSON.stringify(this.deviceMqttOptions)},`
|
|
323
|
+
+ ` ${mqttPubOptions} mqttPubOptions: ${JSON.stringify(this.deviceMqttPubOptions)}`);
|
|
380
324
|
}
|
|
381
325
|
|
|
382
326
|
/*
|
|
@@ -715,32 +659,14 @@ export abstract class deviceBase {
|
|
|
715
659
|
device.bleModelName = SwitchBotBLEModelName.Unknown;
|
|
716
660
|
device.bleModelFriednlyName = SwitchBotBLEModelFriendlyName.Unknown;
|
|
717
661
|
}
|
|
718
|
-
this.debugLog(`Model: ${device.model}, BLE Model: ${device.bleModel}, BLE Model Name: ${device.bleModelName}, `
|
|
662
|
+
await this.debugLog(`Model: ${device.model}, BLE Model: ${device.bleModel}, BLE Model Name: ${device.bleModelName}, `
|
|
719
663
|
+ `BLE Model Friendly Name: ${device.bleModelFriednlyName}`);
|
|
720
664
|
accessory.context.model = device.model;
|
|
721
665
|
accessory.context.bleModel = device.bleModel;
|
|
722
666
|
accessory.context.bleModelName = device.bleModelName;
|
|
723
667
|
accessory.context.bleModelFriednlyName = device.bleModelFriednlyName;
|
|
724
668
|
|
|
725
|
-
|
|
726
|
-
let deviceFirmwareVersion: string;
|
|
727
|
-
if (device.firmware) {
|
|
728
|
-
deviceFirmwareVersion = device.firmware;
|
|
729
|
-
this.debugSuccessLog(`1 FirmwareRevision: ${device.firmware}`);
|
|
730
|
-
} else if (device.version) {
|
|
731
|
-
deviceFirmwareVersion = JSON.stringify(device.version);
|
|
732
|
-
this.debugSuccessLog(`2 FirmwareRevision: ${device.version}`);
|
|
733
|
-
} else if (accessory.context.deviceVersion) {
|
|
734
|
-
deviceFirmwareVersion = accessory.context.deviceVersion;
|
|
735
|
-
this.debugSuccessLog(`3 FirmwareRevision: ${accessory.context.deviceVersion}`);
|
|
736
|
-
} else {
|
|
737
|
-
deviceFirmwareVersion = this.platform.version ?? '0.0.0';
|
|
738
|
-
if (this.platform.version) {
|
|
739
|
-
this.debugSuccessLog(`4 FirmwareRevision: ${this.platform.version}`);
|
|
740
|
-
} else {
|
|
741
|
-
this.debugSuccessLog(`5 FirmwareRevision: ${deviceFirmwareVersion}`);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
669
|
+
const deviceFirmwareVersion = device.firmware ?? device.version ?? accessory.context.version ?? this.platform.version ?? '0.0.0';
|
|
744
670
|
const version = deviceFirmwareVersion.toString();
|
|
745
671
|
this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
|
|
746
672
|
let deviceVersion: string;
|
|
@@ -759,8 +685,8 @@ export abstract class deviceBase {
|
|
|
759
685
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
760
686
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
761
687
|
.updateValue(deviceVersion);
|
|
762
|
-
accessory.context.
|
|
763
|
-
this.debugSuccessLog(`
|
|
688
|
+
accessory.context.version = deviceVersion;
|
|
689
|
+
this.debugSuccessLog(`version: ${accessory.context.version}`);
|
|
764
690
|
}
|
|
765
691
|
|
|
766
692
|
async statusCode(statusCode: number): Promise<void> {
|
package/src/device/fan.ts
CHANGED
|
@@ -39,6 +39,15 @@ export class Fan extends deviceBase {
|
|
|
39
39
|
Brightness: CharacteristicValue;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
// OpenAPI
|
|
43
|
+
deviceStatus!: batteryCirculatorFanStatus;
|
|
44
|
+
|
|
45
|
+
//Webhook
|
|
46
|
+
webhookContext!: batteryCirculatorFanWebhookContext;
|
|
47
|
+
|
|
48
|
+
// BLE
|
|
49
|
+
serviceData!: batteryCirculatorFanServiceData;
|
|
50
|
+
|
|
42
51
|
// Updates
|
|
43
52
|
fanUpdateInProgress!: boolean;
|
|
44
53
|
doFanUpdate!: Subject<void>;
|
|
@@ -49,6 +58,9 @@ export class Fan extends deviceBase {
|
|
|
49
58
|
device: device & devicesConfig,
|
|
50
59
|
) {
|
|
51
60
|
super(platform, accessory, device);
|
|
61
|
+
// Set category
|
|
62
|
+
accessory.category = this.hap.Categories.FAN;
|
|
63
|
+
|
|
52
64
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
53
65
|
this.doFanUpdate = new Subject();
|
|
54
66
|
this.fanUpdateInProgress = false;
|
|
@@ -149,10 +161,12 @@ export class Fan extends deviceBase {
|
|
|
149
161
|
.onSet(this.BrightnessSet.bind(this));
|
|
150
162
|
|
|
151
163
|
// Retrieve initial values and updateHomekit
|
|
164
|
+
this.debugLog('Retrieve initial values and update Homekit');
|
|
152
165
|
this.refreshStatus();
|
|
153
166
|
|
|
154
|
-
//
|
|
155
|
-
this.
|
|
167
|
+
//regisiter webhook event handler
|
|
168
|
+
this.debugLog('Registering Webhook Event Handler');
|
|
169
|
+
this.registerWebhook();
|
|
156
170
|
|
|
157
171
|
//regisiter webhook event handler
|
|
158
172
|
this.registerWebhook();
|
|
@@ -184,35 +198,45 @@ export class Fan extends deviceBase {
|
|
|
184
198
|
});
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
async BLEparseStatus(
|
|
201
|
+
async BLEparseStatus(): Promise<void> {
|
|
188
202
|
await this.debugLog('BLEparseStatus');
|
|
203
|
+
await this.debugLog(`(powerState, fanSpeed) = BLE:(${this.serviceData.state}, ${this.serviceData.fanSpeed}), current:(${this.Fan.Active},`
|
|
204
|
+
+ ` ${this.Fan.RotationSpeed})`);
|
|
205
|
+
|
|
189
206
|
// Active
|
|
190
|
-
this.Fan.Active = serviceData.state === 'on' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
207
|
+
this.Fan.Active = this.serviceData.state === 'on' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
191
208
|
await this.debugLog(`Active: ${this.Fan.Active}`);
|
|
209
|
+
|
|
210
|
+
// RotationSpeed
|
|
211
|
+
this.Fan.RotationSpeed = this.serviceData.fanSpeed;
|
|
192
212
|
}
|
|
193
213
|
|
|
194
|
-
async openAPIparseStatus(
|
|
214
|
+
async openAPIparseStatus() {
|
|
195
215
|
await this.debugLog('openAPIparseStatus');
|
|
216
|
+
await this.debugLog(`(version, battery, powerState, oscillation, chargingStatus, fanSpeed) = OpenAPI:(${this.deviceStatus.version},`
|
|
217
|
+
+ ` ${this.deviceStatus.battery}, ${this.deviceStatus.power}, ${this.deviceStatus.oscillation}, ${this.deviceStatus.chargingStatus},`
|
|
218
|
+
+ ` ${this.deviceStatus.fanSpeed}), current:(${this.accessory.context.version}, ${this.Battery.BatteryLevel}, ${this.Fan.Active},`
|
|
219
|
+
+ ` ${this.Fan.SwingMode}, ${this.Battery.ChargingState}, ${this.Fan.RotationSpeed})`);
|
|
196
220
|
|
|
197
221
|
// Active
|
|
198
|
-
this.Fan.Active = deviceStatus.power === 'on' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
222
|
+
this.Fan.Active = this.deviceStatus.power === 'on' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
199
223
|
this.debugLog(`Active: ${this.Fan.Active}`);
|
|
200
224
|
|
|
201
225
|
// SwingMode
|
|
202
|
-
this.Fan.SwingMode = deviceStatus.oscillation === 'on' ?
|
|
226
|
+
this.Fan.SwingMode = this.deviceStatus.oscillation === 'on' ?
|
|
203
227
|
this.hap.Characteristic.SwingMode.SWING_ENABLED : this.hap.Characteristic.SwingMode.SWING_DISABLED;
|
|
204
228
|
await this.debugLog(`SwingMode: ${this.Fan.SwingMode}`);
|
|
205
229
|
|
|
206
230
|
// RotationSpeed
|
|
207
|
-
this.Fan.RotationSpeed = deviceStatus.fanSpeed;
|
|
231
|
+
this.Fan.RotationSpeed = this.deviceStatus.fanSpeed;
|
|
208
232
|
await this.debugLog(`RotationSpeed: ${this.Fan.RotationSpeed}`);
|
|
209
233
|
|
|
210
234
|
// ChargingState
|
|
211
|
-
this.Battery.ChargingState = deviceStatus.chargingStatus === 'charging' ?
|
|
235
|
+
this.Battery.ChargingState = this.deviceStatus.chargingStatus === 'charging' ?
|
|
212
236
|
this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
|
|
213
237
|
|
|
214
238
|
// BatteryLevel
|
|
215
|
-
this.Battery.BatteryLevel =
|
|
239
|
+
this.Battery.BatteryLevel = this.deviceStatus.battery;
|
|
216
240
|
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
217
241
|
|
|
218
242
|
// StatusLowBattery
|
|
@@ -221,9 +245,9 @@ export class Fan extends deviceBase {
|
|
|
221
245
|
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
222
246
|
|
|
223
247
|
// Firmware Version
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
248
|
+
if (this.deviceStatus.version) {
|
|
249
|
+
const version = this.deviceStatus.version.toString();
|
|
250
|
+
await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
|
|
227
251
|
const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
|
|
228
252
|
this.accessory
|
|
229
253
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
@@ -231,49 +255,56 @@ export class Fan extends deviceBase {
|
|
|
231
255
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
232
256
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
233
257
|
.updateValue(deviceVersion);
|
|
234
|
-
this.accessory.context.
|
|
235
|
-
await this.debugSuccessLog(`
|
|
258
|
+
this.accessory.context.version = deviceVersion;
|
|
259
|
+
await this.debugSuccessLog(`version: ${this.accessory.context.version}`);
|
|
236
260
|
}
|
|
237
261
|
}
|
|
238
262
|
|
|
239
|
-
async parseStatusWebhook(
|
|
263
|
+
async parseStatusWebhook(): Promise<void> {
|
|
240
264
|
await this.debugLog('parseStatusWebhook');
|
|
241
|
-
await this.debugLog(`(version, battery, powerState, oscillation, chargingStatus, fanSpeed) = Webhook:(${
|
|
242
|
-
+ ` ${
|
|
243
|
-
+ `
|
|
244
|
-
+ ` ${this.Battery.ChargingState}, ${this.Fan.RotationSpeed})`);
|
|
265
|
+
await this.debugLog(`(version, battery, powerState, oscillation, chargingStatus, fanSpeed) = Webhook:(${this.webhookContext.version},`
|
|
266
|
+
+ ` ${this.webhookContext.battery}, ${this.webhookContext.powerState}, ${this.webhookContext.oscillation},`
|
|
267
|
+
+ ` ${this.webhookContext.chargingStatus}, ${this.webhookContext.fanSpeed}), current:(${this.accessory.context.version},`
|
|
268
|
+
+ ` ${this.Battery.BatteryLevel}, ${this.Fan.Active}, ${this.Fan.SwingMode}, ${this.Battery.ChargingState}, ${this.Fan.RotationSpeed})`);
|
|
269
|
+
|
|
245
270
|
// Active
|
|
246
|
-
this.Fan.Active =
|
|
271
|
+
this.Fan.Active = this.webhookContext.powerState === 'ON' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
247
272
|
await this.debugLog(`Active: ${this.Fan.Active}`);
|
|
273
|
+
|
|
248
274
|
// SwingMode
|
|
249
|
-
this.Fan.SwingMode =
|
|
275
|
+
this.Fan.SwingMode = this.webhookContext.oscillation === 'on' ?
|
|
250
276
|
this.hap.Characteristic.SwingMode.SWING_ENABLED : this.hap.Characteristic.SwingMode.SWING_DISABLED;
|
|
251
277
|
await this.debugLog(`SwingMode: ${this.Fan.SwingMode}`);
|
|
278
|
+
|
|
252
279
|
// RotationSpeed
|
|
253
|
-
this.Fan.RotationSpeed =
|
|
280
|
+
this.Fan.RotationSpeed = this.webhookContext.fanSpeed;
|
|
254
281
|
await this.debugLog(`RotationSpeed: ${this.Fan.RotationSpeed}`);
|
|
282
|
+
|
|
255
283
|
// BatteryLevel
|
|
256
|
-
this.Battery.BatteryLevel =
|
|
284
|
+
this.Battery.BatteryLevel = this.webhookContext.battery;
|
|
257
285
|
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
286
|
+
|
|
258
287
|
// StatusLowBattery
|
|
259
288
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
260
289
|
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
261
290
|
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
291
|
+
|
|
262
292
|
// ChargingState
|
|
263
|
-
this.Battery.ChargingState =
|
|
293
|
+
this.Battery.ChargingState = this.webhookContext.chargingStatus === 'charging' ?
|
|
264
294
|
this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
|
|
265
295
|
await this.debugLog(`ChargingState: ${this.Battery.ChargingState}`);
|
|
296
|
+
|
|
266
297
|
// FirmwareVersion
|
|
267
|
-
if (
|
|
268
|
-
const deviceVersion =
|
|
298
|
+
if (this.webhookContext.version) {
|
|
299
|
+
const deviceVersion = this.webhookContext.version.replace(/^V|-.*$/g, '') ?? '0.0.0';
|
|
269
300
|
this.accessory
|
|
270
301
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
271
302
|
.setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
|
|
272
303
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
273
304
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
274
305
|
.updateValue(deviceVersion);
|
|
275
|
-
this.accessory.context.
|
|
276
|
-
await this.debugSuccessLog(`
|
|
306
|
+
this.accessory.context.version = deviceVersion;
|
|
307
|
+
await this.debugSuccessLog(`version: ${this.accessory.context.version}`);
|
|
277
308
|
}
|
|
278
309
|
}
|
|
279
310
|
|
|
@@ -303,10 +334,11 @@ export class Fan extends deviceBase {
|
|
|
303
334
|
// Start to monitor advertisement packets
|
|
304
335
|
(async () => {
|
|
305
336
|
// Start to monitor advertisement packets
|
|
306
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as
|
|
337
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as batteryCirculatorFanServiceData;
|
|
307
338
|
// Update HomeKit
|
|
308
339
|
if (serviceData.model === SwitchBotBLEModel.Unknown && SwitchBotBLEModelName.Unknown) {
|
|
309
|
-
|
|
340
|
+
this.serviceData = serviceData;
|
|
341
|
+
await this.BLEparseStatus();
|
|
310
342
|
await this.updateHomeKitCharacteristics();
|
|
311
343
|
} else {
|
|
312
344
|
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
@@ -324,7 +356,8 @@ export class Fan extends deviceBase {
|
|
|
324
356
|
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);;
|
|
325
357
|
if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
|
|
326
358
|
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
327
|
-
|
|
359
|
+
this.deviceStatus = deviceStatus.body;
|
|
360
|
+
await this.openAPIparseStatus();
|
|
328
361
|
await this.updateHomeKitCharacteristics();
|
|
329
362
|
} else {
|
|
330
363
|
await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
@@ -342,7 +375,8 @@ export class Fan extends deviceBase {
|
|
|
342
375
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context: batteryCirculatorFanWebhookContext) => {
|
|
343
376
|
try {
|
|
344
377
|
await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
|
|
345
|
-
|
|
378
|
+
this.webhookContext = context;
|
|
379
|
+
await this.parseStatusWebhook();
|
|
346
380
|
await this.updateHomeKitCharacteristics();
|
|
347
381
|
} catch (e: any) {
|
|
348
382
|
await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|