@switchbot/homebridge-switchbot 0.1.2-beta.7 → 0.2.0-alpha.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/.github/ISSUE_TEMPLATE/feature-request.yml +1 -1
- package/.github/dependabot.yml +2 -0
- package/.github/workflows/codeql-analysis.yml +71 -0
- package/CHANGELOG.md +5 -1
- package/README.md +2 -1
- package/config.schema.json +420 -471
- package/dist/devices/bots.d.ts +19 -5
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +172 -148
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/bulb.d.ts +8 -6
- package/dist/devices/bulb.d.ts.map +1 -1
- package/dist/devices/bulb.js +45 -28
- package/dist/devices/bulb.js.map +1 -1
- package/dist/devices/contact.d.ts +10 -5
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +94 -63
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +14 -5
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +174 -120
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts +6 -6
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +78 -94
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/indoorcam.d.ts +43 -0
- package/dist/devices/indoorcam.d.ts.map +1 -0
- package/dist/devices/indoorcam.js +241 -0
- package/dist/devices/indoorcam.js.map +1 -0
- package/dist/devices/meters.d.ts +8 -5
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +126 -92
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +9 -5
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +74 -59
- package/dist/devices/motion.js.map +1 -1
- package/dist/devices/plugs.d.ts +5 -4
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js +65 -56
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.d.ts +3 -3
- package/dist/irdevices/airconditioners.d.ts.map +1 -1
- package/dist/irdevices/airconditioners.js +12 -7
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.d.ts +3 -3
- package/dist/irdevices/airpurifiers.d.ts.map +1 -1
- package/dist/irdevices/airpurifiers.js +1 -1
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.d.ts +3 -3
- package/dist/irdevices/cameras.d.ts.map +1 -1
- package/dist/irdevices/cameras.js +1 -1
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.d.ts +3 -3
- package/dist/irdevices/fans.d.ts.map +1 -1
- package/dist/irdevices/fans.js +11 -12
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.d.ts +3 -3
- package/dist/irdevices/lights.d.ts.map +1 -1
- package/dist/irdevices/lights.js +1 -1
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.d.ts +3 -3
- package/dist/irdevices/others.d.ts.map +1 -1
- package/dist/irdevices/others.js +8 -8
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts +3 -3
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +16 -6
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.d.ts +3 -3
- package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
- package/dist/irdevices/vacuumcleaners.js +2 -3
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/dist/irdevices/waterheaters.d.ts +3 -3
- package/dist/irdevices/waterheaters.d.ts.map +1 -1
- package/dist/irdevices/waterheaters.js +2 -2
- package/dist/irdevices/waterheaters.js.map +1 -1
- package/dist/platform.d.ts +14 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +420 -418
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +18 -15
- package/dist/settings.d.ts.map +1 -1
- package/package.json +65 -65
- package/src/devices/bots.ts +188 -165
- package/src/devices/bulb.ts +48 -40
- package/src/devices/contact.ts +100 -73
- package/src/devices/curtains.ts +192 -140
- package/src/devices/humidifiers.ts +82 -124
- package/src/devices/indoorcam.ts +303 -0
- package/src/devices/meters.ts +130 -110
- package/src/devices/motion.ts +80 -69
- package/src/devices/plugs.ts +67 -65
- package/src/irdevices/airconditioners.ts +14 -10
- package/src/irdevices/airpurifiers.ts +4 -4
- package/src/irdevices/cameras.ts +4 -4
- package/src/irdevices/fans.ts +14 -18
- package/src/irdevices/lights.ts +4 -4
- package/src/irdevices/others.ts +12 -14
- package/src/irdevices/tvs.ts +21 -10
- package/src/irdevices/vacuumcleaners.ts +5 -9
- package/src/irdevices/waterheaters.ts +5 -5
- package/src/platform.ts +455 -619
- package/src/settings.ts +19 -15
- package/.github/workflows/issue-validate.yml +0 -18
package/src/devices/bulb.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { Service, PlatformAccessory, CharacteristicValue, MacAddress } from 'hom
|
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device,
|
|
6
|
-
import { AxiosResponse } from 'axios';
|
|
5
|
+
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Platform Accessory
|
|
@@ -20,7 +19,7 @@ export class Bulb {
|
|
|
20
19
|
ColorTemperature!: CharacteristicValue;
|
|
21
20
|
|
|
22
21
|
// Others
|
|
23
|
-
deviceStatus
|
|
22
|
+
deviceStatus: any;
|
|
24
23
|
switchbot!: {
|
|
25
24
|
discover: (
|
|
26
25
|
arg0:
|
|
@@ -39,25 +38,24 @@ export class Bulb {
|
|
|
39
38
|
// Updates
|
|
40
39
|
bulbUpdateInProgress!: boolean;
|
|
41
40
|
doBulbUpdate;
|
|
41
|
+
set_minStep: any;
|
|
42
42
|
|
|
43
43
|
constructor(
|
|
44
44
|
private readonly platform: SwitchBotPlatform,
|
|
45
45
|
private accessory: PlatformAccessory,
|
|
46
|
-
public device: device,
|
|
46
|
+
public device: device & devicesConfig,
|
|
47
47
|
) {
|
|
48
48
|
// default placeholders
|
|
49
49
|
this.On = false;
|
|
50
50
|
this.Brightness = 0;
|
|
51
|
-
if (
|
|
51
|
+
if (device.ble) {
|
|
52
52
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
53
53
|
const SwitchBot = require('node-switchbot');
|
|
54
54
|
this.switchbot = new SwitchBot();
|
|
55
55
|
const colon = device.deviceId!.match(/.{1,2}/g);
|
|
56
56
|
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
57
57
|
this.device.bleMac = bleMac.toLowerCase();
|
|
58
|
-
|
|
59
|
-
this.platform.log.warn(this.device.bleMac.toLowerCase());
|
|
60
|
-
}
|
|
58
|
+
this.platform.device(this.device.bleMac.toLowerCase());
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
@@ -72,14 +70,14 @@ export class Bulb {
|
|
|
72
70
|
accessory
|
|
73
71
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
74
72
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
75
|
-
.setCharacteristic(this.platform.Characteristic.Model,
|
|
76
|
-
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId);
|
|
73
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'SWITCHBOT-BULB-W1401400')
|
|
74
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
77
75
|
|
|
78
76
|
// get the Television service if it exists, otherwise create a new Television service
|
|
79
77
|
// you can create multiple services for each accessory
|
|
80
78
|
(this.service =
|
|
81
79
|
accessory.getService(this.platform.Service.Lightbulb) ||
|
|
82
|
-
accessory.addService(this.platform.Service.Lightbulb)), `${
|
|
80
|
+
accessory.addService(this.platform.Service.Lightbulb)), `${accessory.displayName} Light Bulb`;
|
|
83
81
|
|
|
84
82
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
85
83
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -96,7 +94,7 @@ export class Bulb {
|
|
|
96
94
|
// handle Brightness events using the Brightness characteristic
|
|
97
95
|
this.service.getCharacteristic(this.platform.Characteristic.Brightness)
|
|
98
96
|
.setProps({
|
|
99
|
-
minStep: this.
|
|
97
|
+
minStep: this.minStep(),
|
|
100
98
|
minValue: 0,
|
|
101
99
|
maxValue: 100,
|
|
102
100
|
validValueRanges: [0, 100],
|
|
@@ -109,7 +107,7 @@ export class Bulb {
|
|
|
109
107
|
// handle ColorTemperature events using the ColorTemperature characteristic
|
|
110
108
|
this.service.getCharacteristic(this.platform.Characteristic.ColorTemperature)
|
|
111
109
|
.setProps({
|
|
112
|
-
minStep: this.
|
|
110
|
+
minStep: this.minStep(),
|
|
113
111
|
minValue: 0,
|
|
114
112
|
maxValue: 100,
|
|
115
113
|
validValueRanges: [0, 100],
|
|
@@ -129,7 +127,7 @@ export class Bulb {
|
|
|
129
127
|
this.refreshStatus();
|
|
130
128
|
});
|
|
131
129
|
|
|
132
|
-
// Watch for
|
|
130
|
+
// Watch for Bulb change events
|
|
133
131
|
// We put in a debounce of 100ms so we don't make duplicate calls
|
|
134
132
|
this.doBulbUpdate
|
|
135
133
|
.pipe(
|
|
@@ -143,13 +141,22 @@ export class Bulb {
|
|
|
143
141
|
await this.pushChanges();
|
|
144
142
|
} catch (e: any) {
|
|
145
143
|
this.platform.log.error(JSON.stringify(e.message));
|
|
146
|
-
this.platform.debug(`
|
|
144
|
+
this.platform.debug(`Bulb ${accessory.displayName} - ${JSON.stringify(e)}`);
|
|
147
145
|
this.apiError(e);
|
|
148
146
|
}
|
|
149
147
|
this.bulbUpdateInProgress = false;
|
|
150
148
|
});
|
|
151
149
|
}
|
|
152
150
|
|
|
151
|
+
private minStep(): number | undefined {
|
|
152
|
+
if (this.device.bulb?.set_minStep) {
|
|
153
|
+
this.set_minStep = this.device.bulb?.set_minStep;
|
|
154
|
+
} else {
|
|
155
|
+
this.set_minStep = 1;
|
|
156
|
+
}
|
|
157
|
+
return this.set_minStep;
|
|
158
|
+
}
|
|
159
|
+
|
|
153
160
|
parseStatus() {
|
|
154
161
|
switch (this.deviceStatus.body.power) {
|
|
155
162
|
case 'on':
|
|
@@ -158,29 +165,21 @@ export class Bulb {
|
|
|
158
165
|
default:
|
|
159
166
|
this.On = false;
|
|
160
167
|
}
|
|
161
|
-
this.platform.debug(`
|
|
168
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} On: ${this.On}`);
|
|
162
169
|
this.deviceStatus.body.brightness = Number(this.Brightness);
|
|
163
170
|
this.deviceStatus.body.colorTemperature = Number(this.ColorTemperature);
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
async refreshStatus() {
|
|
167
174
|
try {
|
|
168
|
-
this.platform.debug('
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
this.deviceStatus = deviceStatus;
|
|
174
|
-
this.platform.log.warn(`Plug ${this.accessory.displayName} refreshStatus - ${JSON.stringify(this.deviceStatus)}`);
|
|
175
|
-
this.parseStatus();
|
|
176
|
-
this.updateHomeKitCharacteristics();
|
|
177
|
-
}
|
|
175
|
+
this.platform.debug('Bulb - Reading', `${DeviceURL}/${this.device.deviceId}/status`);
|
|
176
|
+
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
177
|
+
this.platform.device(`Bulb ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
178
|
+
this.parseStatus();
|
|
179
|
+
this.updateHomeKitCharacteristics();
|
|
178
180
|
} catch (e: any) {
|
|
179
|
-
this.platform.log.error(
|
|
180
|
-
|
|
181
|
-
JSON.stringify(e.message),
|
|
182
|
-
this.platform.debug(`Plug ${this.accessory.displayName} - ${JSON.stringify(e)}`),
|
|
183
|
-
);
|
|
181
|
+
this.platform.log.error(`Bulb ${this.accessory.displayName} failed to refresh status, Error Message ${JSON.stringify(e.message)}`);
|
|
182
|
+
this.platform.debug(`Bulb ${this.accessory.displayName}, Error: ${JSON.stringify(e)}`);
|
|
184
183
|
this.apiError(e);
|
|
185
184
|
}
|
|
186
185
|
}
|
|
@@ -188,8 +187,8 @@ export class Bulb {
|
|
|
188
187
|
/**
|
|
189
188
|
* Pushes the requested changes to the SwitchBot API
|
|
190
189
|
* deviceType commandType Command command parameter Description
|
|
191
|
-
*
|
|
192
|
-
*
|
|
190
|
+
* Bulb - "command" "turnOff" "default" = set to OFF state
|
|
191
|
+
* Bulb - "command" "turnOn" "default" = set to ON state
|
|
193
192
|
*/
|
|
194
193
|
async pushChanges() {
|
|
195
194
|
const payload = {
|
|
@@ -213,23 +212,32 @@ export class Bulb {
|
|
|
213
212
|
'commandType:',
|
|
214
213
|
payload.commandType,
|
|
215
214
|
);
|
|
216
|
-
this.platform.debug(`
|
|
215
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} pushchanges: ${JSON.stringify(payload)}`);
|
|
217
216
|
|
|
218
217
|
// Make the API request
|
|
219
|
-
const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
|
|
220
|
-
this.platform.debug(`
|
|
218
|
+
const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
|
|
219
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} Changes pushed: ${JSON.stringify(push.data)}`);
|
|
221
220
|
this.statusCode(push);
|
|
222
221
|
}
|
|
223
222
|
|
|
224
223
|
updateHomeKitCharacteristics() {
|
|
225
|
-
if (this.On
|
|
224
|
+
if (this.On === undefined) {
|
|
225
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} On: ${this.On}`);
|
|
226
|
+
} else {
|
|
226
227
|
this.service.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
228
|
+
this.platform.device(`Bulb ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
227
229
|
}
|
|
228
|
-
if (this.Brightness
|
|
230
|
+
if (this.Brightness === undefined) {
|
|
231
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} Brightness: ${this.Brightness}`);
|
|
232
|
+
} else {
|
|
229
233
|
this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.Brightness);
|
|
234
|
+
this.platform.device(`Bulb ${this.accessory.displayName} updateCharacteristic Brightness: ${this.Brightness}`);
|
|
230
235
|
}
|
|
231
|
-
if (this.ColorTemperature
|
|
236
|
+
if (this.ColorTemperature === undefined) {
|
|
237
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
|
|
238
|
+
} else {
|
|
232
239
|
this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.ColorTemperature);
|
|
240
|
+
this.platform.debug(`Bulb ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
|
|
233
241
|
}
|
|
234
242
|
}
|
|
235
243
|
|
|
@@ -240,7 +248,7 @@ export class Bulb {
|
|
|
240
248
|
}
|
|
241
249
|
|
|
242
250
|
|
|
243
|
-
private statusCode(push:
|
|
251
|
+
private statusCode(push: { data: { statusCode: any; }; }) {
|
|
244
252
|
switch (push.data.statusCode) {
|
|
245
253
|
case 151:
|
|
246
254
|
this.platform.log.error('Command not supported by this device type.');
|
package/src/devices/contact.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Service, PlatformAccessory, CharacteristicValue, MacAddress } from 'hom
|
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { skipWhile } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device,
|
|
5
|
+
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Platform Accessory
|
|
@@ -19,7 +19,9 @@ export class Contact {
|
|
|
19
19
|
MotionDetected!: CharacteristicValue;
|
|
20
20
|
|
|
21
21
|
// Others
|
|
22
|
-
deviceStatus!:
|
|
22
|
+
deviceStatus!: any;
|
|
23
|
+
BLEmotion!: boolean;
|
|
24
|
+
BLEstate!: boolean;
|
|
23
25
|
switchbot!: {
|
|
24
26
|
discover: (
|
|
25
27
|
arg0:
|
|
@@ -42,21 +44,22 @@ export class Contact {
|
|
|
42
44
|
constructor(
|
|
43
45
|
private readonly platform: SwitchBotPlatform,
|
|
44
46
|
private accessory: PlatformAccessory,
|
|
45
|
-
public device: device,
|
|
47
|
+
public device: device & devicesConfig,
|
|
46
48
|
) {
|
|
47
49
|
// default placeholders
|
|
48
|
-
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.
|
|
49
|
-
|
|
50
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
51
|
+
|
|
52
|
+
// BLE Connection
|
|
53
|
+
if (device.ble) {
|
|
50
54
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
51
55
|
const SwitchBot = require('node-switchbot');
|
|
52
56
|
this.switchbot = new SwitchBot();
|
|
53
57
|
const colon = device.deviceId!.match(/.{1,2}/g);
|
|
54
58
|
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
55
59
|
this.device.bleMac = bleMac.toLowerCase();
|
|
56
|
-
|
|
57
|
-
this.platform.log.warn(this.device.bleMac.toLowerCase());
|
|
58
|
-
}
|
|
60
|
+
this.platform.device(this.device.bleMac.toLowerCase());
|
|
59
61
|
}
|
|
62
|
+
|
|
60
63
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
61
64
|
this.doContactUpdate = new Subject();
|
|
62
65
|
this.contactUbpdateInProgress = false;
|
|
@@ -68,14 +71,14 @@ export class Contact {
|
|
|
68
71
|
accessory
|
|
69
72
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
70
73
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
71
|
-
.setCharacteristic(this.platform.Characteristic.Model, 'SWITCHBOT-
|
|
72
|
-
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId);
|
|
74
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'SWITCHBOT-WOCONTACT-W1201500')
|
|
75
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
73
76
|
|
|
74
77
|
// get the Battery service if it exists, otherwise create a new Contact service
|
|
75
78
|
// you can create multiple services for each accessory
|
|
76
79
|
(this.service =
|
|
77
80
|
accessory.getService(this.platform.Service.ContactSensor) ||
|
|
78
|
-
accessory.addService(this.platform.Service.ContactSensor)), `${
|
|
81
|
+
accessory.addService(this.platform.Service.ContactSensor)), `${accessory.displayName} Contact Sensor`;
|
|
79
82
|
|
|
80
83
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
81
84
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -89,10 +92,9 @@ export class Contact {
|
|
|
89
92
|
// see https://developers.homebridge.io/#/service/MotionSensor
|
|
90
93
|
(this.motionService =
|
|
91
94
|
accessory.getService(this.platform.Service.MotionSensor) ||
|
|
92
|
-
accessory.addService(this.platform.Service.MotionSensor)), `${
|
|
95
|
+
accessory.addService(this.platform.Service.MotionSensor)), `${accessory.displayName} Motion Sensor`;
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
//this.service.setCharacteristic(this.platform.Characteristic.ChargingState, 2);
|
|
97
|
+
this.motionService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Motion Sensor`);
|
|
96
98
|
|
|
97
99
|
// Retrieve initial values and updateHomekit
|
|
98
100
|
this.updateHomeKitCharacteristics();
|
|
@@ -108,12 +110,32 @@ export class Contact {
|
|
|
108
110
|
/**
|
|
109
111
|
* Parse the device status from the SwitchBot api
|
|
110
112
|
*/
|
|
111
|
-
parseStatus() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
async parseStatus() {
|
|
114
|
+
if (this.device.ble) {
|
|
115
|
+
this.platform.device('BLE');
|
|
116
|
+
await this.BLEparseStatus();
|
|
115
117
|
} else {
|
|
118
|
+
this.platform.device('OpenAPI');
|
|
119
|
+
await this.openAPIparseStatus();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private async BLEparseStatus() {
|
|
124
|
+
this.MotionDetected = Boolean(this.BLEmotion);
|
|
125
|
+
this.ContactSensorState = Boolean(this.BLEstate);
|
|
126
|
+
this.platform.debug(`${this.accessory.displayName}
|
|
127
|
+
, ContactSensorState: ${this.ContactSensorState}, MotionDetected: ${this.MotionDetected}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async openAPIparseStatus() {
|
|
131
|
+
if (this.deviceStatus.body.openState === 'open') {
|
|
116
132
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
133
|
+
this.platform.log.info(`${this.accessory.displayName} ${this.deviceStatus.body.openState}`);
|
|
134
|
+
} else if (this.deviceStatus.body.openState === 'close') {
|
|
135
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
136
|
+
this.platform.device(`${this.accessory.displayName} ${this.deviceStatus.body.openState}`);
|
|
137
|
+
} else {
|
|
138
|
+
this.platform.device(`${this.accessory.displayName} ${this.deviceStatus.body.openState}`);
|
|
117
139
|
}
|
|
118
140
|
this.MotionDetected = Boolean(this.deviceStatus.body.moveDetected);
|
|
119
141
|
this.platform.debug(`${this.accessory.displayName}
|
|
@@ -124,77 +146,76 @@ export class Contact {
|
|
|
124
146
|
* Asks the SwitchBot API for the latest device information
|
|
125
147
|
*/
|
|
126
148
|
async refreshStatus() {
|
|
127
|
-
if (this.
|
|
128
|
-
this.platform.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
if (this.device.ble) {
|
|
150
|
+
this.platform.device('BLE');
|
|
151
|
+
await this.BLERefreshStatus();
|
|
152
|
+
} else {
|
|
153
|
+
this.platform.device('OpenAPI');
|
|
154
|
+
await this.openAPIRefreshStatus();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private async BLERefreshStatus() {
|
|
159
|
+
this.platform.debug('Contact BLE Device RefreshStatus');
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
161
|
+
const Switchbot = require('node-switchbot');
|
|
162
|
+
const switchbot = new Switchbot();
|
|
163
|
+
const colon = this.device.deviceId!.match(/.{1,2}/g);
|
|
164
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
165
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
166
|
+
this.platform.device(this.device.bleMac!);
|
|
167
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
168
|
+
this.platform.log.info(JSON.stringify(ad, null, ' '));
|
|
169
|
+
this.platform.device('ad:', JSON.stringify(ad));
|
|
170
|
+
this.BLEmotion = ad.serviceData.motion;
|
|
171
|
+
this.BLEstate = ad.serviceData.state;
|
|
172
|
+
};
|
|
173
|
+
switchbot
|
|
174
|
+
.startScan({
|
|
175
|
+
id: this.device.bleMac,
|
|
176
|
+
})
|
|
177
|
+
.then(() => {
|
|
178
|
+
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
179
|
+
})
|
|
180
|
+
.then(() => {
|
|
181
|
+
switchbot.stopScan();
|
|
182
|
+
})
|
|
183
|
+
.catch(async (error: any) => {
|
|
184
|
+
this.platform.log.error(error);
|
|
185
|
+
await this.openAPIRefreshStatus();
|
|
186
|
+
});
|
|
187
|
+
setInterval(() => {
|
|
188
|
+
this.platform.log.info('Start scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
142
189
|
switchbot
|
|
143
190
|
.startScan({
|
|
144
|
-
|
|
191
|
+
mode: 'D',
|
|
192
|
+
id: bleMac,
|
|
145
193
|
})
|
|
146
194
|
.then(() => {
|
|
147
195
|
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
148
196
|
})
|
|
149
197
|
.then(() => {
|
|
150
198
|
switchbot.stopScan();
|
|
199
|
+
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
151
200
|
})
|
|
152
201
|
.catch(async (error: any) => {
|
|
153
202
|
this.platform.log.error(error);
|
|
154
203
|
await this.openAPIRefreshStatus();
|
|
155
204
|
});
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
.startScan({
|
|
160
|
-
mode: 'C',
|
|
161
|
-
id: bleMac,
|
|
162
|
-
})
|
|
163
|
-
.then(() => {
|
|
164
|
-
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
165
|
-
})
|
|
166
|
-
.then(() => {
|
|
167
|
-
switchbot.stopScan();
|
|
168
|
-
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
169
|
-
})
|
|
170
|
-
.catch(async (error: any) => {
|
|
171
|
-
this.platform.log.error(error);
|
|
172
|
-
await this.openAPIRefreshStatus();
|
|
173
|
-
});
|
|
174
|
-
}, this.platform.config.options!.refreshRate! * 60000);
|
|
175
|
-
} else {
|
|
176
|
-
await this.openAPIRefreshStatus();
|
|
177
|
-
}
|
|
205
|
+
this.parseStatus();
|
|
206
|
+
this.updateHomeKitCharacteristics();
|
|
207
|
+
}, this.platform.config.options!.refreshRate! * 60000);
|
|
178
208
|
}
|
|
179
209
|
|
|
180
210
|
private async openAPIRefreshStatus() {
|
|
181
211
|
try {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
this.deviceStatus = deviceStatus;
|
|
187
|
-
this.platform.debug(`Contact ${this.accessory.displayName} refreshStatus - ${JSON.stringify(this.deviceStatus)}`);
|
|
188
|
-
|
|
189
|
-
this.parseStatus();
|
|
190
|
-
this.updateHomeKitCharacteristics();
|
|
191
|
-
}
|
|
212
|
+
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
213
|
+
this.platform.debug(`Contact ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
214
|
+
this.parseStatus();
|
|
215
|
+
this.updateHomeKitCharacteristics();
|
|
192
216
|
} catch (e: any) {
|
|
193
|
-
this.platform.log.error(
|
|
194
|
-
|
|
195
|
-
this.device.deviceName,
|
|
196
|
-
JSON.stringify(e.message),
|
|
197
|
-
this.platform.debug(`Contact ${this.accessory.displayName} - ${JSON.stringify(e)}`));
|
|
217
|
+
this.platform.log.error(`Contact ${this.accessory.displayName} failed to refresh status. Error Message: ${JSON.stringify(e.message)}`);
|
|
218
|
+
this.platform.debug(`Contact ${this.accessory.displayName}, Error: ${JSON.stringify(e)}`);
|
|
198
219
|
this.apiError(e);
|
|
199
220
|
}
|
|
200
221
|
}
|
|
@@ -203,11 +224,17 @@ export class Contact {
|
|
|
203
224
|
* Updates the status for each of the HomeKit Characteristics
|
|
204
225
|
*/
|
|
205
226
|
updateHomeKitCharacteristics() {
|
|
206
|
-
if (this.ContactSensorState
|
|
227
|
+
if (this.ContactSensorState === undefined) {
|
|
228
|
+
this.platform.debug(`Contact ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
229
|
+
} else {
|
|
207
230
|
this.service.updateCharacteristic(this.platform.Characteristic.ContactSensorState, this.ContactSensorState);
|
|
231
|
+
this.platform.device(`Contact ${this.accessory.displayName} updateCharacteristic ContactSensorState: ${this.ContactSensorState}`);
|
|
208
232
|
}
|
|
209
|
-
if (this.MotionDetected
|
|
233
|
+
if (this.MotionDetected === undefined) {
|
|
234
|
+
this.platform.debug(`Contact ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
235
|
+
} else {
|
|
210
236
|
this.motionService.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.MotionDetected);
|
|
237
|
+
this.platform.device(`Contact ${this.accessory.displayName} updateCharacteristic MotionDetected: ${this.MotionDetected}`);
|
|
211
238
|
}
|
|
212
239
|
}
|
|
213
240
|
|