@switchbot/homebridge-switchbot 2.0.0-beta.8 → 2.0.0

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +3 -2
  3. package/config.schema.json +91 -19
  4. package/dist/device/bot.d.ts +34 -28
  5. package/dist/device/bot.d.ts.map +1 -1
  6. package/dist/device/bot.js +657 -648
  7. package/dist/device/bot.js.map +1 -1
  8. package/dist/device/ceilinglight.d.ts +137 -0
  9. package/dist/device/ceilinglight.d.ts.map +1 -0
  10. package/dist/device/ceilinglight.js +1127 -0
  11. package/dist/device/ceilinglight.js.map +1 -0
  12. package/dist/device/colorbulb.d.ts +36 -19
  13. package/dist/device/colorbulb.d.ts.map +1 -1
  14. package/dist/device/colorbulb.js +486 -309
  15. package/dist/device/colorbulb.js.map +1 -1
  16. package/dist/device/contact.d.ts +18 -8
  17. package/dist/device/contact.d.ts.map +1 -1
  18. package/dist/device/contact.js +306 -237
  19. package/dist/device/contact.js.map +1 -1
  20. package/dist/device/curtain.d.ts +23 -16
  21. package/dist/device/curtain.d.ts.map +1 -1
  22. package/dist/device/curtain.js +566 -502
  23. package/dist/device/curtain.js.map +1 -1
  24. package/dist/device/humidifier.d.ts +24 -18
  25. package/dist/device/humidifier.d.ts.map +1 -1
  26. package/dist/device/humidifier.js +453 -369
  27. package/dist/device/humidifier.js.map +1 -1
  28. package/dist/device/lock.d.ts +27 -8
  29. package/dist/device/lock.d.ts.map +1 -1
  30. package/dist/device/lock.js +305 -148
  31. package/dist/device/lock.js.map +1 -1
  32. package/dist/device/meter.d.ts +22 -16
  33. package/dist/device/meter.d.ts.map +1 -1
  34. package/dist/device/meter.js +367 -267
  35. package/dist/device/meter.js.map +1 -1
  36. package/dist/device/meterplus.d.ts +24 -12
  37. package/dist/device/meterplus.d.ts.map +1 -1
  38. package/dist/device/meterplus.js +381 -213
  39. package/dist/device/meterplus.js.map +1 -1
  40. package/dist/device/motion.d.ts +18 -8
  41. package/dist/device/motion.d.ts.map +1 -1
  42. package/dist/device/motion.js +279 -216
  43. package/dist/device/motion.js.map +1 -1
  44. package/dist/device/plug.d.ts +27 -17
  45. package/dist/device/plug.d.ts.map +1 -1
  46. package/dist/device/plug.js +295 -251
  47. package/dist/device/plug.js.map +1 -1
  48. package/dist/device/striplight.d.ts +43 -19
  49. package/dist/device/striplight.d.ts.map +1 -1
  50. package/dist/device/striplight.js +506 -262
  51. package/dist/device/striplight.js.map +1 -1
  52. package/dist/irdevice/airconditioner.d.ts +9 -12
  53. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  54. package/dist/irdevice/airconditioner.js +278 -230
  55. package/dist/irdevice/airconditioner.js.map +1 -1
  56. package/dist/irdevice/airpurifier.d.ts +5 -3
  57. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  58. package/dist/irdevice/airpurifier.js +154 -104
  59. package/dist/irdevice/airpurifier.js.map +1 -1
  60. package/dist/irdevice/camera.d.ts +11 -8
  61. package/dist/irdevice/camera.d.ts.map +1 -1
  62. package/dist/irdevice/camera.js +133 -86
  63. package/dist/irdevice/camera.js.map +1 -1
  64. package/dist/irdevice/fan.d.ts +10 -7
  65. package/dist/irdevice/fan.d.ts.map +1 -1
  66. package/dist/irdevice/fan.js +160 -109
  67. package/dist/irdevice/fan.js.map +1 -1
  68. package/dist/irdevice/light.d.ts +11 -8
  69. package/dist/irdevice/light.d.ts.map +1 -1
  70. package/dist/irdevice/light.js +137 -103
  71. package/dist/irdevice/light.js.map +1 -1
  72. package/dist/irdevice/other.d.ts +11 -8
  73. package/dist/irdevice/other.d.ts.map +1 -1
  74. package/dist/irdevice/other.js +145 -98
  75. package/dist/irdevice/other.js.map +1 -1
  76. package/dist/irdevice/tv.d.ts +12 -9
  77. package/dist/irdevice/tv.d.ts.map +1 -1
  78. package/dist/irdevice/tv.js +143 -93
  79. package/dist/irdevice/tv.js.map +1 -1
  80. package/dist/irdevice/vacuumcleaner.d.ts +9 -10
  81. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  82. package/dist/irdevice/vacuumcleaner.js +132 -89
  83. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  84. package/dist/irdevice/waterheater.d.ts +8 -9
  85. package/dist/irdevice/waterheater.d.ts.map +1 -1
  86. package/dist/irdevice/waterheater.js +132 -89
  87. package/dist/irdevice/waterheater.js.map +1 -1
  88. package/dist/platform.d.ts +13 -12
  89. package/dist/platform.d.ts.map +1 -1
  90. package/dist/platform.js +524 -418
  91. package/dist/platform.js.map +1 -1
  92. package/dist/settings.d.ts +19 -11
  93. package/dist/settings.d.ts.map +1 -1
  94. package/dist/settings.js.map +1 -1
  95. package/homebridge-ui/public/index.html +1 -0
  96. package/package.json +11 -9
  97. package/src/device/bot.ts +656 -659
  98. package/src/device/ceilinglight.ts +1208 -0
  99. package/src/device/colorbulb.ts +490 -344
  100. package/src/device/contact.ts +309 -241
  101. package/src/device/curtain.ts +571 -516
  102. package/src/device/humidifier.ts +456 -403
  103. package/src/device/lock.ts +314 -149
  104. package/src/device/meter.ts +378 -280
  105. package/src/device/meterplus.ts +391 -219
  106. package/src/device/motion.ts +285 -222
  107. package/src/device/plug.ts +299 -260
  108. package/src/device/striplight.ts +522 -289
  109. package/src/irdevice/airconditioner.ts +282 -241
  110. package/src/irdevice/airpurifier.ts +151 -103
  111. package/src/irdevice/camera.ts +131 -85
  112. package/src/irdevice/fan.ts +157 -106
  113. package/src/irdevice/light.ts +135 -103
  114. package/src/irdevice/other.ts +143 -97
  115. package/src/irdevice/tv.ts +142 -93
  116. package/src/irdevice/vacuumcleaner.ts +131 -89
  117. package/src/irdevice/waterheater.ts +130 -89
  118. package/src/platform.ts +522 -446
  119. package/src/settings.ts +20 -11
  120. package/.github/npm-version-script.js +0 -81
@@ -8,6 +8,7 @@ const https_1 = __importDefault(require("https"));
8
8
  const crypto_1 = __importDefault(require("crypto"));
9
9
  const rxjs_1 = require("rxjs");
10
10
  const operators_1 = require("rxjs/operators");
11
+ const super_stringify_1 = __importDefault(require("super-stringify"));
11
12
  const settings_1 = require("../settings");
12
13
  /**
13
14
  * Platform Accessory
@@ -19,12 +20,15 @@ class Motion {
19
20
  this.platform = platform;
20
21
  this.accessory = accessory;
21
22
  this.device = device;
23
+ // Connection
24
+ this.BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI');
25
+ this.OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI');
22
26
  // default placeholders
23
27
  this.logs(device);
24
28
  this.scan(device);
25
29
  this.refreshRate(device);
26
30
  this.config(device);
27
- this.MotionDetected = false;
31
+ this.context();
28
32
  // this is subject we use to track when we need to POST changes to the SwitchBot API
29
33
  this.doMotionUpdate = new rxjs_1.Subject();
30
34
  this.motionUbpdateInProgress = false;
@@ -53,34 +57,34 @@ class Motion {
53
57
  // see https://developers.homebridge.io/#/service/MotionSensor
54
58
  // Light Sensor Service
55
59
  if (device.motion?.hide_lightsensor) {
56
- this.debugLog(`Motion Sensor: ${accessory.displayName} Removing Light Sensor Service`);
60
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
57
61
  this.lightSensorService = this.accessory.getService(this.platform.Service.LightSensor);
58
62
  accessory.removeService(this.lightSensorService);
59
63
  }
60
64
  else if (!this.lightSensorService) {
61
- this.debugLog(`Motion Sensor: ${accessory.displayName} Add Light Sensor Service`);
65
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Light Sensor Service`);
62
66
  (this.lightSensorService =
63
67
  this.accessory.getService(this.platform.Service.LightSensor) || this.accessory.addService(this.platform.Service.LightSensor)),
64
68
  `${accessory.displayName} Light Sensor`;
65
69
  this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Light Sensor`);
66
70
  }
67
71
  else {
68
- this.debugLog(`Motion Sensor: ${accessory.displayName} Light Sensor Service Not Added`);
72
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
69
73
  }
70
74
  // Battery Service
71
- if (!device.ble) {
72
- this.debugLog(`Motion Sensor: ${accessory.displayName} Removing Battery Service`);
75
+ if (!this.BLE) {
76
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
73
77
  this.batteryService = this.accessory.getService(this.platform.Service.Battery);
74
78
  accessory.removeService(this.batteryService);
75
79
  }
76
- else if (device.ble && !this.batteryService) {
77
- this.debugLog(`Motion Sensor: ${accessory.displayName} Add Battery Service`);
80
+ else if (this.BLE && !this.batteryService) {
81
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
78
82
  (this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
79
83
  `${accessory.displayName} Battery`;
80
84
  this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
81
85
  }
82
86
  else {
83
- this.debugLog(`Motion Sensor: ${accessory.displayName} Battery Service Not Added`);
87
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Battery Service Not Added`);
84
88
  }
85
89
  // Retrieve initial values and updateHomekit
86
90
  this.updateHomeKitCharacteristics();
@@ -95,18 +99,22 @@ class Motion {
95
99
  * Parse the device status from the SwitchBot api
96
100
  */
97
101
  async parseStatus() {
98
- if (this.SwitchToOpenAPI || !this.device.ble) {
102
+ if (this.BLE) {
103
+ await this.BLEparseStatus();
104
+ }
105
+ else if (this.OpenAPI && this.platform.config.credentials?.token) {
99
106
  await this.openAPIparseStatus();
100
107
  }
101
108
  else {
102
- await this.BLEparseStatus();
109
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
110
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
103
111
  }
104
112
  }
105
113
  async BLEparseStatus() {
106
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE parseStatus`);
114
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
107
115
  // Movement
108
116
  this.MotionDetected = this.movement;
109
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
117
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
110
118
  // Light Level
111
119
  if (!this.device.motion?.hide_lightsensor) {
112
120
  this.set_minLux = this.minLux();
@@ -119,7 +127,7 @@ class Motion {
119
127
  default:
120
128
  this.CurrentAmbientLightLevel = this.set_maxLux;
121
129
  }
122
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},` +
130
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel},` +
123
131
  ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
124
132
  }
125
133
  // Battery
@@ -133,46 +141,46 @@ class Motion {
133
141
  else {
134
142
  this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
135
143
  }
136
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
144
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
145
+ + ` StatusLowBattery: ${this.StatusLowBattery}`);
137
146
  }
138
147
  async openAPIparseStatus() {
139
- if (this.device.ble) {
140
- this.SwitchToOpenAPI = false;
141
- }
142
- if (this.platform.config.credentials?.token) {
143
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
144
- // Motion State
145
- this.MotionDetected = this.moveDetected;
146
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
147
- // Light Level
148
- if (!this.device.motion?.hide_lightsensor) {
149
- this.set_minLux = this.minLux();
150
- this.set_maxLux = this.maxLux();
151
- switch (this.brightness) {
152
- case 'dim':
153
- this.CurrentAmbientLightLevel = this.set_minLux;
154
- break;
155
- case 'bright':
156
- default:
157
- this.CurrentAmbientLightLevel = this.set_maxLux;
158
- }
159
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
148
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
149
+ // Motion State
150
+ this.MotionDetected = this.moveDetected;
151
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
152
+ // Light Level
153
+ if (!this.device.motion?.hide_lightsensor) {
154
+ this.set_minLux = this.minLux();
155
+ this.set_maxLux = this.maxLux();
156
+ switch (this.brightness) {
157
+ case 'dim':
158
+ this.CurrentAmbientLightLevel = this.set_minLux;
159
+ break;
160
+ case 'bright':
161
+ default:
162
+ this.CurrentAmbientLightLevel = this.set_maxLux;
160
163
  }
164
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
161
165
  }
162
166
  }
163
167
  /**
164
168
  * Asks the SwitchBot API for the latest device information
165
169
  */
166
170
  async refreshStatus() {
167
- if (this.device.ble) {
171
+ if (this.BLE) {
168
172
  await this.BLERefreshStatus();
169
173
  }
170
- else {
174
+ else if (this.OpenAPI && this.platform.config.credentials?.token) {
171
175
  await this.openAPIRefreshStatus();
172
176
  }
177
+ else {
178
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
179
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
180
+ }
173
181
  }
174
182
  async BLERefreshStatus() {
175
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE RefreshStatus`);
183
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
176
184
  const switchbot = await this.platform.connectBLE();
177
185
  // Convert to BLE Address
178
186
  this.device.bleMac =
@@ -181,7 +189,7 @@ class Motion {
181
189
  .deviceId.match(/.{1,2}/g)
182
190
  .join(':')
183
191
  .toLowerCase();
184
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
192
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
185
193
  this.getCustomBLEAddress(switchbot);
186
194
  // Start to monitor advertisement packets
187
195
  if (switchbot !== false) {
@@ -194,26 +202,22 @@ class Motion {
194
202
  // Set an event hander
195
203
  switchbot.onadvertisement = (ad) => {
196
204
  this.address = ad.address;
197
- if (this.deviceLogging.includes('debug')) {
198
- this.infoLog(this.address);
199
- this.infoLog(this.device.bleMac);
200
- this.infoLog(`Motion Sensor: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
201
- this.infoLog(`Motion Sensor: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
202
- }
205
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
206
+ + ` BLE Address Found: ${this.address}`);
203
207
  this.serviceData = ad.serviceData;
204
208
  this.movement = ad.serviceData.movement;
205
209
  this.battery = ad.serviceData.battery;
206
210
  this.lightLevel = ad.serviceData.lightLevel;
207
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
208
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} movement: ${ad.serviceData.movement}, lightLevel: ` +
211
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${(0, super_stringify_1.default)(ad.serviceData)}`);
212
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} movement: ${ad.serviceData.movement}, lightLevel: ` +
209
213
  `${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}`);
210
214
  if (this.serviceData) {
211
215
  this.connected = true;
212
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} connected: ${this.connected}`);
216
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
213
217
  }
214
218
  else {
215
219
  this.connected = false;
216
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} connected: ${this.connected}`);
220
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
217
221
  }
218
222
  };
219
223
  // Wait 10 seconds
@@ -223,113 +227,77 @@ class Motion {
223
227
  // Stop to monitor
224
228
  switchbot.stopScan();
225
229
  if (this.connected) {
226
- this.parseStatus();
230
+ this.BLEparseStatus();
227
231
  this.updateHomeKitCharacteristics();
228
232
  }
229
233
  else {
230
- await this.BLEconnection(switchbot);
234
+ await this.BLERefreshConnection(switchbot);
231
235
  }
232
236
  })
233
237
  .catch(async (e) => {
234
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
235
- if (this.deviceLogging.includes('debug')) {
236
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` +
237
- ` Error Message: ${JSON.stringify(e.message)}`);
238
- }
239
- if (this.platform.config.credentials?.token) {
240
- this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
241
- this.SwitchToOpenAPI = true;
242
- await this.openAPIRefreshStatus();
243
- }
244
238
  this.apiError(e);
239
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
240
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
241
+ await this.BLERefreshConnection(switchbot);
245
242
  });
246
243
  }
247
244
  else {
248
- await this.BLEconnection(switchbot);
249
- }
250
- }
251
- async getCustomBLEAddress(switchbot) {
252
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
253
- (async () => {
254
- // Start to monitor advertisement packets
255
- await switchbot.startScan({
256
- model: 's',
257
- });
258
- // Set an event handler
259
- switchbot.onadvertisement = (ad) => {
260
- this.warnLog(`Motion Sensor: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
261
- };
262
- await switchbot.wait(10000);
263
- // Stop to monitor
264
- switchbot.stopScan();
265
- })();
266
- }
267
- }
268
- async BLEconnection(switchbot) {
269
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
270
- if (this.platform.config.credentials?.token) {
271
- this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
272
- this.SwitchToOpenAPI = true;
273
- await this.openAPIRefreshStatus();
245
+ await this.BLERefreshConnection(switchbot);
274
246
  }
275
247
  }
276
248
  async openAPIRefreshStatus() {
277
- if (this.platform.config.credentials?.token) {
278
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI RefreshStatus`);
279
- try {
280
- const t = Date.now();
281
- const nonce = 'requestID';
282
- const data = this.platform.config.credentials?.token + t + nonce;
283
- const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
284
- const sign = signTerm.toString('base64');
285
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} sign: ${sign}`);
286
- const options = {
287
- hostname: settings_1.HostDomain,
288
- port: 443,
289
- path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
290
- method: 'GET',
291
- headers: {
292
- Authorization: this.platform.config.credentials?.token,
293
- sign: sign,
294
- nonce: nonce,
295
- t: t,
296
- 'Content-Type': 'application/json',
297
- },
298
- };
299
- const req = https_1.default.request(options, (res) => {
300
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
301
- let rawData = '';
302
- res.on('data', (d) => {
303
- rawData += d;
304
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} d: ${d}`);
305
- });
306
- res.on('end', () => {
307
- try {
308
- this.deviceStatus = JSON.parse(rawData);
309
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
310
- this.moveDetected = this.deviceStatus.body.moveDetected;
311
- this.brightness = this.deviceStatus.body.brightness;
312
- this.parseStatus();
313
- this.updateHomeKitCharacteristics();
314
- }
315
- catch (e) {
316
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
317
- }
318
- });
249
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
250
+ try {
251
+ const t = Date.now();
252
+ const nonce = 'requestID';
253
+ const data = this.platform.config.credentials?.token + t + nonce;
254
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
255
+ const sign = signTerm.toString('base64');
256
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
257
+ const options = {
258
+ hostname: settings_1.HostDomain,
259
+ port: 443,
260
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
261
+ method: 'GET',
262
+ headers: {
263
+ Authorization: this.platform.config.credentials?.token,
264
+ sign: sign,
265
+ nonce: nonce,
266
+ t: t,
267
+ 'Content-Type': 'application/json',
268
+ },
269
+ };
270
+ const req = https_1.default.request(options, (res) => {
271
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
272
+ this.statusCode({ res });
273
+ let rawData = '';
274
+ res.on('data', (d) => {
275
+ rawData += d;
276
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
319
277
  });
320
- req.on('error', (e) => {
321
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
278
+ res.on('end', () => {
279
+ try {
280
+ this.deviceStatus = JSON.parse(rawData);
281
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
282
+ this.moveDetected = this.deviceStatus.body.moveDetected;
283
+ this.brightness = this.deviceStatus.body.brightness;
284
+ this.openAPIparseStatus();
285
+ this.updateHomeKitCharacteristics();
286
+ }
287
+ catch (e) {
288
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
289
+ }
322
290
  });
323
- req.end();
324
- }
325
- catch (e) {
326
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
327
- if (this.deviceLogging.includes('debug')) {
328
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` +
329
- ` Error Message: ${JSON.stringify(e.message)}`);
330
- }
331
- this.apiError(e);
332
- }
291
+ });
292
+ req.on('error', (e) => {
293
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
294
+ });
295
+ req.end();
296
+ }
297
+ catch (e) {
298
+ this.apiError(e);
299
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
300
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
333
301
  }
334
302
  }
335
303
  /**
@@ -337,116 +305,152 @@ class Motion {
337
305
  */
338
306
  async updateHomeKitCharacteristics() {
339
307
  if (this.MotionDetected === undefined) {
340
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
308
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
341
309
  }
342
310
  else {
311
+ this.accessory.context.MotionDetected = this.MotionDetected;
343
312
  this.motionSensorService.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.MotionDetected);
344
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic MotionDetected: ${this.MotionDetected}`);
313
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic MotionDetected: ${this.MotionDetected}`);
345
314
  }
346
- if (this.device.ble) {
315
+ if (this.BLE) {
347
316
  if (this.BatteryLevel === undefined) {
348
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
317
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
349
318
  }
350
319
  else {
320
+ this.accessory.context.BatteryLevel = this.BatteryLevel;
351
321
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
352
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
322
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
353
323
  }
354
324
  if (this.StatusLowBattery === undefined) {
355
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
325
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
356
326
  }
357
327
  else {
328
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
358
329
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
359
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
330
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
360
331
  }
361
332
  if (this.CurrentAmbientLightLevel === undefined) {
362
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
333
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
363
334
  }
364
335
  else {
336
+ this.accessory.context.CurrentAmbientLightLevel = this.CurrentAmbientLightLevel;
365
337
  this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
366
- this.debugLog(`Motion Sensor: ${this.accessory.displayName}` + ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
338
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
339
+ + ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
367
340
  }
368
341
  }
369
342
  }
370
- async apiError(e) {
371
- this.motionSensorService.updateCharacteristic(this.platform.Characteristic.MotionDetected, e);
372
- if (this.device.ble) {
373
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
374
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
375
- this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
343
+ async getCustomBLEAddress(switchbot) {
344
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
345
+ (async () => {
346
+ // Start to monitor advertisement packets
347
+ await switchbot.startScan({
348
+ model: 's',
349
+ });
350
+ // Set an event handler
351
+ switchbot.onadvertisement = (ad) => {
352
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
353
+ };
354
+ await switchbot.wait(10000);
355
+ // Stop to monitor
356
+ switchbot.stopScan();
357
+ })();
376
358
  }
377
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
378
359
  }
379
- async config(device) {
380
- let config = {};
381
- if (device.motion) {
382
- config = device.motion;
383
- }
384
- if (device.ble !== undefined) {
385
- config['ble'] = device.ble;
386
- }
387
- if (device.logging !== undefined) {
388
- config['logging'] = device.logging;
389
- }
390
- if (device.refreshRate !== undefined) {
391
- config['refreshRate'] = device.refreshRate;
392
- }
393
- if (device.scanDuration !== undefined) {
394
- config['scanDuration'] = device.scanDuration;
360
+ async BLERefreshConnection(switchbot) {
361
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
362
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
363
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
364
+ await this.openAPIRefreshStatus();
395
365
  }
396
- if (device.offline !== undefined) {
397
- config['offline'] = device.offline;
366
+ }
367
+ minLux() {
368
+ if (this.device.motion?.set_minLux) {
369
+ this.set_minLux = this.device.motion.set_minLux;
398
370
  }
399
- if (Object.entries(config).length !== 0) {
400
- this.infoLog(`Motion Sensor: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
371
+ else {
372
+ this.set_minLux = 1;
401
373
  }
374
+ return this.set_minLux;
402
375
  }
403
- async refreshRate(device) {
404
- if (device.refreshRate) {
405
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
406
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
376
+ maxLux() {
377
+ if (this.device.motion?.set_maxLux) {
378
+ this.set_maxLux = this.device.motion.set_maxLux;
407
379
  }
408
- else if (this.platform.config.options.refreshRate) {
409
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
410
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
380
+ else {
381
+ this.set_maxLux = 6001;
411
382
  }
383
+ return this.set_maxLux;
412
384
  }
413
385
  async scan(device) {
414
386
  if (device.scanDuration) {
415
387
  this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
416
- if (device.ble) {
417
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
388
+ if (this.BLE) {
389
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
418
390
  }
419
391
  }
420
392
  else {
421
393
  this.scanDuration = this.accessory.context.scanDuration = 1;
422
- if (this.device.ble) {
423
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
394
+ if (this.BLE) {
395
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
424
396
  }
425
397
  }
426
398
  }
427
- async logs(device) {
428
- if (this.platform.debugMode) {
429
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
430
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
431
- }
432
- else if (device.logging) {
433
- this.deviceLogging = this.accessory.context.logging = device.logging;
434
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
399
+ async statusCode({ res }) {
400
+ switch (res.statusCode) {
401
+ case 151:
402
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
403
+ break;
404
+ case 152:
405
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
406
+ break;
407
+ case 160:
408
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
409
+ break;
410
+ case 161:
411
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
412
+ this.offlineOff();
413
+ break;
414
+ case 171:
415
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
416
+ this.offlineOff();
417
+ break;
418
+ case 190:
419
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
420
+ ` Or command: ${(0, super_stringify_1.default)(res)} format is invalid`);
421
+ break;
422
+ case 100:
423
+ if (this.platform.debugMode) {
424
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
425
+ }
426
+ break;
427
+ default:
428
+ if (this.platform.debugMode) {
429
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
430
+ }
435
431
  }
436
- else if (this.platform.config.options?.logging) {
437
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
438
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
432
+ }
433
+ async offlineOff() {
434
+ if (this.device.offline) {
435
+ this.MotionDetected = false;
436
+ this.motionSensorService.getCharacteristic(this.platform.Characteristic.MotionDetected).updateValue(this.MotionDetected);
437
+ await this.updateHomeKitCharacteristics();
439
438
  }
440
- else {
441
- this.deviceLogging = this.accessory.context.logging = 'standard';
442
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
439
+ }
440
+ async apiError(e) {
441
+ this.motionSensorService.updateCharacteristic(this.platform.Characteristic.MotionDetected, e);
442
+ if (this.BLE) {
443
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
444
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
445
+ this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
443
446
  }
444
447
  }
445
448
  FirmwareRevision(accessory, device) {
446
449
  let FirmwareRevision;
447
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
448
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
449
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
450
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
451
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
452
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
453
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
450
454
  if (accessory.context.FirmwareRevision) {
451
455
  FirmwareRevision = accessory.context.FirmwareRevision;
452
456
  }
@@ -458,23 +462,68 @@ class Motion {
458
462
  }
459
463
  return FirmwareRevision;
460
464
  }
461
- minLux() {
462
- if (this.device.motion?.set_minLux) {
463
- this.set_minLux = this.device.motion.set_minLux;
465
+ async context() {
466
+ if (this.MotionDetected === undefined) {
467
+ this.MotionDetected = false;
464
468
  }
465
469
  else {
466
- this.set_minLux = 1;
470
+ this.MotionDetected = this.accessory.context.MotionDetected;
467
471
  }
468
- return this.set_minLux;
469
472
  }
470
- maxLux() {
471
- if (this.device.motion?.set_maxLux) {
472
- this.set_maxLux = this.device.motion.set_maxLux;
473
+ async refreshRate(device) {
474
+ if (device.refreshRate) {
475
+ this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
476
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
477
+ }
478
+ else if (this.platform.config.options.refreshRate) {
479
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
480
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
481
+ }
482
+ }
483
+ async config(device) {
484
+ let config = {};
485
+ if (device.motion) {
486
+ config = device.motion;
487
+ }
488
+ if (device.connectionType !== undefined) {
489
+ config['connectionType'] = device.connectionType;
490
+ }
491
+ if (device.external !== undefined) {
492
+ config['external'] = device.external;
493
+ }
494
+ if (device.logging !== undefined) {
495
+ config['logging'] = device.logging;
496
+ }
497
+ if (device.refreshRate !== undefined) {
498
+ config['refreshRate'] = device.refreshRate;
499
+ }
500
+ if (device.scanDuration !== undefined) {
501
+ config['scanDuration'] = device.scanDuration;
502
+ }
503
+ if (device.offline !== undefined) {
504
+ config['offline'] = device.offline;
505
+ }
506
+ if (Object.entries(config).length !== 0) {
507
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
508
+ }
509
+ }
510
+ async logs(device) {
511
+ if (this.platform.debugMode) {
512
+ this.deviceLogging = this.accessory.context.logging = 'debugMode';
513
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
514
+ }
515
+ else if (device.logging) {
516
+ this.deviceLogging = this.accessory.context.logging = device.logging;
517
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
518
+ }
519
+ else if (this.platform.config.options?.logging) {
520
+ this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
521
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
473
522
  }
474
523
  else {
475
- this.set_maxLux = 6001;
524
+ this.deviceLogging = this.accessory.context.logging = 'standard';
525
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
476
526
  }
477
- return this.set_maxLux;
478
527
  }
479
528
  /**
480
529
  * Logging for Device
@@ -489,11 +538,25 @@ class Motion {
489
538
  this.platform.log.warn(String(...log));
490
539
  }
491
540
  }
541
+ debugWarnLog(...log) {
542
+ if (this.enablingDeviceLogging()) {
543
+ if (this.deviceLogging?.includes('debug')) {
544
+ this.platform.log.warn('[DEBUG]', String(...log));
545
+ }
546
+ }
547
+ }
492
548
  errorLog(...log) {
493
549
  if (this.enablingDeviceLogging()) {
494
550
  this.platform.log.error(String(...log));
495
551
  }
496
552
  }
553
+ debugErrorLog(...log) {
554
+ if (this.enablingDeviceLogging()) {
555
+ if (this.deviceLogging?.includes('debug')) {
556
+ this.platform.log.error('[DEBUG]', String(...log));
557
+ }
558
+ }
559
+ }
497
560
  debugLog(...log) {
498
561
  if (this.enablingDeviceLogging()) {
499
562
  if (this.deviceLogging === 'debug') {