@switchbot/homebridge-switchbot 1.7.1-beta.0 → 1.7.1-beta.4

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.
@@ -17,9 +17,9 @@ export class Motion {
17
17
 
18
18
  // Characteristic Values
19
19
  MotionDetected!: CharacteristicValue;
20
+ CurrentAmbientLightLevel!: CharacteristicValue;
20
21
  BatteryLevel?: CharacteristicValue;
21
22
  StatusLowBattery?: CharacteristicValue;
22
- CurrentAmbientLightLevel?: CharacteristicValue;
23
23
 
24
24
  // OpenAPI Others
25
25
  deviceStatus!: deviceStatusResponse;
@@ -27,12 +27,15 @@ export class Motion {
27
27
  // BLE Others
28
28
  connected?: boolean;
29
29
  switchbot!: switchbot;
30
+ SwitchToOpenAPI?: boolean;
30
31
  serviceData!: serviceData;
31
32
  battery!: serviceData['battery'];
32
33
  movement!: serviceData['movement'];
33
34
  lightLevel!: serviceData['lightLevel'];
34
35
 
35
36
  // Config
37
+ set_minLux!: number;
38
+ set_maxLux!: number;
36
39
  scanDuration!: number;
37
40
  deviceLogging!: string;
38
41
  deviceRefreshRate!: number;
@@ -40,6 +43,8 @@ export class Motion {
40
43
  // Updates
41
44
  motionUbpdateInProgress!: boolean;
42
45
  doMotionUpdate!: Subject<void>;
46
+ moveDetected: boolean | undefined;
47
+ brightness: string | number | undefined;
43
48
 
44
49
  constructor(
45
50
  private readonly platform: SwitchBotPlatform,
@@ -52,6 +57,11 @@ export class Motion {
52
57
  this.refreshRate();
53
58
  this.MotionDetected = false;
54
59
 
60
+ // Motion Config
61
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
62
+ + ` hide_lightsensor: ${device.motion?.hide_lightsensor},`
63
+ + ` set_minLux: ${this.device.motion?.set_minLux}, set_maxLux: ${this.device.motion?.set_maxLux})`);
64
+
55
65
  // this is subject we use to track when we need to POST changes to the SwitchBot API
56
66
  this.doMotionUpdate = new Subject();
57
67
  this.motionUbpdateInProgress = false;
@@ -72,21 +82,6 @@ export class Motion {
72
82
  accessory.getService(this.platform.Service.MotionSensor) ||
73
83
  accessory.addService(this.platform.Service.MotionSensor)), `${accessory.displayName} Motion Sensor`;
74
84
 
75
- if (device.ble) {
76
- (this.lightSensorService =
77
- accessory.getService(this.platform.Service.LightSensor) ||
78
- accessory.addService(this.platform.Service.LightSensor)), `${accessory.displayName} Light Sensor`;
79
-
80
- this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Light Sensor`);
81
-
82
-
83
- (this.batteryService =
84
- accessory.getService(this.platform.Service.Battery) ||
85
- accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
86
-
87
- this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
88
- }
89
-
90
85
  // To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
91
86
  // when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
92
87
  // accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Motion, 'NAME', 'USER_DEFINED_SUBTYPE');
@@ -98,8 +93,39 @@ export class Motion {
98
93
  // each service must implement at-minimum the "required characteristics" for the given service type
99
94
  // see https://developers.homebridge.io/#/service/MotionSensor
100
95
 
101
- // create handlers for required characteristics
102
- //this.service.setCharacteristic(this.platform.Characteristic.ChargingState, 2);
96
+ // Light Sensor Service
97
+ if (device.motion?.hide_lightsensor) {
98
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Removing Light Sensor Service`);
99
+ this.lightSensorService = this.accessory.getService(this.platform.Service.LightSensor);
100
+ accessory.removeService(this.lightSensorService!);
101
+ } else if (!this.lightSensorService) {
102
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Add Light Sensor Service`);
103
+ (this.lightSensorService =
104
+ this.accessory.getService(this.platform.Service.LightSensor) ||
105
+ this.accessory.addService(this.platform.Service.LightSensor)), `${accessory.displayName} Light Sensor`;
106
+
107
+ this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Light Sensor`);
108
+
109
+ } else {
110
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Light Sensor Service Not Added`);
111
+ }
112
+
113
+ // Battery Service
114
+ if (!device.ble) {
115
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Removing Battery Service`);
116
+ this.batteryService = this.accessory.getService(this.platform.Service.Battery);
117
+ accessory.removeService(this.batteryService!);
118
+ } else if (!this.batteryService) {
119
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Add Battery Service`);
120
+ (this.batteryService =
121
+ this.accessory.getService(this.platform.Service.Battery) ||
122
+ this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
123
+
124
+ this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
125
+
126
+ } else {
127
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Battery Service Not Added`);
128
+ }
103
129
 
104
130
  // Retrieve initial values and updateHomekit
105
131
  this.updateHomeKitCharacteristics();
@@ -159,59 +185,92 @@ export class Motion {
159
185
  }
160
186
  }
161
187
 
188
+ private minLux(): number {
189
+ if (this.device.motion?.set_minLux) {
190
+ this.set_minLux = this.device.motion!.set_minLux!;
191
+ } else {
192
+ this.set_minLux = 1;
193
+ }
194
+ return this.set_minLux;
195
+ }
196
+
197
+ private maxLux(): number {
198
+ if (this.device.motion?.set_maxLux) {
199
+ this.set_maxLux = this.device.motion!.set_maxLux!;
200
+ } else {
201
+ this.set_maxLux = 6001;
202
+ }
203
+ return this.set_maxLux;
204
+ }
205
+
162
206
  /**
163
207
  * Parse the device status from the SwitchBot api
164
208
  */
165
209
  async parseStatus() {
166
- if (this.device.ble) {
167
- await this.BLEparseStatus();
168
- } else {
210
+ if (this.SwitchToOpenAPI || !this.device.ble) {
169
211
  await this.openAPIparseStatus();
212
+ } else {
213
+ await this.BLEparseStatus();
170
214
  }
171
215
  }
172
216
 
173
217
  private async BLEparseStatus() {
174
218
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE parseStatus`);
175
- this.MotionDetected = Boolean(this.movement);
219
+ // Movement
220
+ this.MotionDetected = this.movement!;
176
221
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
177
222
  // Light Level
178
- switch (this.lightLevel) {
179
- case 'dark':
180
- case 0:
181
- this.CurrentAmbientLightLevel = 0.0001;
182
- break;
183
- default:
184
- this.CurrentAmbientLightLevel = 100000;
223
+ if (!this.device.motion?.hide_lightsensor) {
224
+ this.set_minLux = this.minLux();
225
+ this.set_maxLux = this.maxLux();
226
+ switch (this.lightLevel) {
227
+ case 'dark':
228
+ case 1:
229
+ this.CurrentAmbientLightLevel = this.set_minLux;
230
+ break;
231
+ default:
232
+ this.CurrentAmbientLightLevel = this.set_maxLux;
233
+ }
234
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
235
+ + ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
185
236
  }
186
237
  // Battery
187
- this.BatteryLevel = Number(this.battery);
238
+ if (this.battery === undefined) {
239
+ this.battery = 100;
240
+ }
241
+ this.BatteryLevel = this.battery!;
188
242
  if (this.BatteryLevel < 10) {
189
243
  this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
190
244
  } else {
191
245
  this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
192
246
  }
247
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
193
248
  }
194
249
 
195
250
  private async openAPIparseStatus() {
196
- try {
197
- if (this.platform.config.credentials?.openToken) {
198
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
199
- if (typeof this.deviceStatus.body.moveDetected === 'boolean') {
200
- this.MotionDetected = this.deviceStatus.body.moveDetected;
251
+ if (this.device.ble) {
252
+ this.SwitchToOpenAPI = false;
253
+ }
254
+ if (this.platform.config.credentials?.openToken) {
255
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
256
+ // Motion State
257
+ this.MotionDetected = this.moveDetected!;
258
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
259
+ // Light Level
260
+ if (!this.device.motion?.hide_lightsensor) {
261
+ this.set_minLux = this.minLux();
262
+ this.set_maxLux = this.maxLux();
263
+ switch (this.brightness) {
264
+ case 'dim':
265
+ this.CurrentAmbientLightLevel = this.set_minLux;
266
+ break;
267
+ case 'bright':
268
+ default:
269
+ this.CurrentAmbientLightLevel = this.set_maxLux;
201
270
  }
202
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
203
- }
204
- } catch (e: any) {
205
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed parseStatus with OpenAPI Connection`);
206
- if (this.deviceLogging === 'debug') {
207
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed parseStatus with OpenAPI Connection,`
208
- + ` Error Message: ${JSON.stringify(e.message)}`);
209
- }
210
- if (this.platform.debugMode) {
211
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed parseStatus with OpenAPI Connection,`
212
- + ` Error: ${JSON.stringify(e)}`);
271
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
272
+
213
273
  }
214
- this.apiError(e);
215
274
  }
216
275
  }
217
276
 
@@ -301,6 +360,7 @@ export class Motion {
301
360
  }
302
361
  if (this.platform.config.credentials?.openToken) {
303
362
  this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
363
+ this.SwitchToOpenAPI = true;
304
364
  await this.openAPIRefreshStatus();
305
365
  }
306
366
  this.apiError(e);
@@ -314,6 +374,7 @@ export class Motion {
314
374
  this.errorLog(`Motion Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
315
375
  if (this.platform.config.credentials?.openToken) {
316
376
  this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
377
+ this.SwitchToOpenAPI = true;
317
378
  await this.openAPIRefreshStatus();
318
379
  }
319
380
  }
@@ -324,6 +385,11 @@ export class Motion {
324
385
  try {
325
386
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
326
387
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
388
+ if (this.deviceStatus.body.moveDetected === undefined) {
389
+ this.errorLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
390
+ }
391
+ this.moveDetected = this.deviceStatus.body.moveDetected;
392
+ this.brightness = this.deviceStatus.body.brightness;
327
393
  this.parseStatus();
328
394
  this.updateHomeKitCharacteristics();
329
395
  } catch (e: any) {
package/src/platform.ts CHANGED
@@ -192,8 +192,21 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
192
192
  }
193
193
  }
194
194
 
195
+ connectBLE() {
196
+ let Switchbot: new () => any;
197
+ let switchbot: any;
198
+ try {
199
+ Switchbot = require('node-switchbot');
200
+ switchbot = new Switchbot();
201
+ } catch (e) {
202
+ switchbot = false;
203
+ this.errorLog(`Was 'node-switchbot' found: ${switchbot}`);
204
+ }
205
+ return switchbot;
206
+ }
207
+
195
208
  /**
196
- * this method discovers the Locations
209
+ * this method discovers devices
197
210
  */
198
211
  async discoverDevices() {
199
212
  try {
package/src/settings.ts CHANGED
@@ -48,6 +48,7 @@ export interface devicesConfig extends device {
48
48
  humidifier?: humidifier;
49
49
  curtain?: curtain;
50
50
  contact?: contact;
51
+ motion?: motion;
51
52
  colorbulb?: colorbulb;
52
53
  ble?: string;
53
54
  scanDuration?: number;
@@ -89,6 +90,12 @@ export type contact = {
89
90
  hide_motionsensor?: boolean;
90
91
  };
91
92
 
93
+ export type motion = {
94
+ hide_lightsensor?: boolean;
95
+ set_minLux?: number;
96
+ set_maxLux?: number;
97
+ };
98
+
92
99
  export type colorbulb = {
93
100
  set_minStep?: number;
94
101
  adaptiveLightingShift?: number;