hap-nodejs 0.9.8-beta.0 → 0.10.0-beta.10

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 (191) hide show
  1. package/@types/bonjour-hap.d.ts +4 -3
  2. package/@types/simple-plist.d.ts +2 -1
  3. package/dist/BridgedCore.js +5 -4
  4. package/dist/BridgedCore.js.map +1 -1
  5. package/dist/Core.js +12 -10
  6. package/dist/Core.js.map +1 -1
  7. package/dist/accessories/AirConditioner_accessory.js +9 -9
  8. package/dist/accessories/AirConditioner_accessory.js.map +1 -1
  9. package/dist/accessories/AppleTVRemote_accessory.js +9 -8
  10. package/dist/accessories/AppleTVRemote_accessory.js.map +1 -1
  11. package/dist/accessories/Camera_accessory.js +414 -35
  12. package/dist/accessories/Camera_accessory.js.map +1 -1
  13. package/dist/accessories/Fan_accessory.js +6 -11
  14. package/dist/accessories/Fan_accessory.js.map +1 -1
  15. package/dist/accessories/GarageDoorOpener_accessory.js +7 -8
  16. package/dist/accessories/GarageDoorOpener_accessory.js.map +1 -1
  17. package/dist/accessories/Light-AdaptiveLighting_accessory.js +3 -4
  18. package/dist/accessories/Light-AdaptiveLighting_accessory.js.map +1 -1
  19. package/dist/accessories/Light_accessory.js +23 -14
  20. package/dist/accessories/Light_accessory.js.map +1 -1
  21. package/dist/accessories/Lock_accessory.js +7 -8
  22. package/dist/accessories/Lock_accessory.js.map +1 -1
  23. package/dist/accessories/MotionSensor_accessory.js +5 -6
  24. package/dist/accessories/MotionSensor_accessory.js.map +1 -1
  25. package/dist/accessories/Outlet_accessory.js +5 -6
  26. package/dist/accessories/Outlet_accessory.js.map +1 -1
  27. package/dist/accessories/SmartSpeaker_accessory.js +6 -6
  28. package/dist/accessories/SmartSpeaker_accessory.js.map +1 -1
  29. package/dist/accessories/Sprinkler_accessory.js +12 -13
  30. package/dist/accessories/Sprinkler_accessory.js.map +1 -1
  31. package/dist/accessories/TV_accessory.js +4 -5
  32. package/dist/accessories/TV_accessory.js.map +1 -1
  33. package/dist/accessories/TemperatureSensor_accessory.js +5 -6
  34. package/dist/accessories/TemperatureSensor_accessory.js.map +1 -1
  35. package/dist/accessories/Wi-FiRouter_accessory.d.ts +1 -1
  36. package/dist/accessories/Wi-FiRouter_accessory.d.ts.map +1 -1
  37. package/dist/accessories/Wi-FiRouter_accessory.js +7 -8
  38. package/dist/accessories/Wi-FiRouter_accessory.js.map +1 -1
  39. package/dist/accessories/Wi-FiSatellite_accessory.d.ts +1 -1
  40. package/dist/accessories/Wi-FiSatellite_accessory.d.ts.map +1 -1
  41. package/dist/accessories/Wi-FiSatellite_accessory.js +6 -7
  42. package/dist/accessories/Wi-FiSatellite_accessory.js.map +1 -1
  43. package/dist/accessories/gstreamer-audioProducer.d.ts.map +1 -1
  44. package/dist/accessories/gstreamer-audioProducer.js +14 -15
  45. package/dist/accessories/gstreamer-audioProducer.js.map +1 -1
  46. package/dist/index.d.ts +22 -22
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +2 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/internal-types.d.ts +2 -0
  51. package/dist/internal-types.d.ts.map +1 -1
  52. package/dist/internal-types.js.map +1 -1
  53. package/dist/lib/Accessory.d.ts +18 -14
  54. package/dist/lib/Accessory.d.ts.map +1 -1
  55. package/dist/lib/Accessory.js +242 -203
  56. package/dist/lib/Accessory.js.map +1 -1
  57. package/dist/lib/AccessoryLoader.d.ts +10 -10
  58. package/dist/lib/AccessoryLoader.d.ts.map +1 -1
  59. package/dist/lib/AccessoryLoader.js +105 -95
  60. package/dist/lib/AccessoryLoader.js.map +1 -1
  61. package/dist/lib/Advertiser.d.ts +21 -1
  62. package/dist/lib/Advertiser.d.ts.map +1 -1
  63. package/dist/lib/Advertiser.js +215 -10
  64. package/dist/lib/Advertiser.js.map +1 -1
  65. package/dist/lib/Bridge.d.ts +1 -1
  66. package/dist/lib/Bridge.d.ts.map +1 -1
  67. package/dist/lib/Bridge.js.map +1 -1
  68. package/dist/lib/Characteristic.d.ts +22 -21
  69. package/dist/lib/Characteristic.d.ts.map +1 -1
  70. package/dist/lib/Characteristic.js +100 -97
  71. package/dist/lib/Characteristic.js.map +1 -1
  72. package/dist/lib/HAPServer.d.ts +2 -2
  73. package/dist/lib/HAPServer.d.ts.map +1 -1
  74. package/dist/lib/HAPServer.js +18 -14
  75. package/dist/lib/HAPServer.js.map +1 -1
  76. package/dist/lib/Service.d.ts +3 -3
  77. package/dist/lib/Service.d.ts.map +1 -1
  78. package/dist/lib/Service.js +26 -26
  79. package/dist/lib/Service.js.map +1 -1
  80. package/dist/lib/camera/Camera.d.ts +2 -2
  81. package/dist/lib/camera/Camera.d.ts.map +1 -1
  82. package/dist/lib/camera/Camera.js +3 -3
  83. package/dist/lib/camera/Camera.js.map +1 -1
  84. package/dist/lib/camera/RTPProxy.d.ts +19 -19
  85. package/dist/lib/camera/RTPProxy.d.ts.map +1 -1
  86. package/dist/lib/camera/RTPProxy.js +229 -207
  87. package/dist/lib/camera/RTPProxy.js.map +1 -1
  88. package/dist/lib/camera/RTPStreamManagement.d.ts +44 -8
  89. package/dist/lib/camera/RTPStreamManagement.d.ts.map +1 -1
  90. package/dist/lib/camera/RTPStreamManagement.js +111 -37
  91. package/dist/lib/camera/RTPStreamManagement.js.map +1 -1
  92. package/dist/lib/camera/RecordingManagement.d.ts +267 -0
  93. package/dist/lib/camera/RecordingManagement.d.ts.map +1 -0
  94. package/dist/lib/camera/RecordingManagement.js +750 -0
  95. package/dist/lib/camera/RecordingManagement.js.map +1 -0
  96. package/dist/lib/camera/index.d.ts +4 -3
  97. package/dist/lib/camera/index.d.ts.map +1 -1
  98. package/dist/lib/camera/index.js +1 -0
  99. package/dist/lib/camera/index.js.map +1 -1
  100. package/dist/lib/controller/AdaptiveLightingController.d.ts +9 -9
  101. package/dist/lib/controller/AdaptiveLightingController.d.ts.map +1 -1
  102. package/dist/lib/controller/AdaptiveLightingController.js +25 -19
  103. package/dist/lib/controller/AdaptiveLightingController.js.map +1 -1
  104. package/dist/lib/controller/CameraController.d.ts +253 -7
  105. package/dist/lib/controller/CameraController.d.ts.map +1 -1
  106. package/dist/lib/controller/CameraController.js +378 -31
  107. package/dist/lib/controller/CameraController.js.map +1 -1
  108. package/dist/lib/controller/Controller.d.ts +3 -3
  109. package/dist/lib/controller/Controller.d.ts.map +1 -1
  110. package/dist/lib/controller/Controller.js.map +1 -1
  111. package/dist/lib/controller/DoorbellController.d.ts +43 -1
  112. package/dist/lib/controller/DoorbellController.d.ts.map +1 -1
  113. package/dist/lib/controller/DoorbellController.js +63 -11
  114. package/dist/lib/controller/DoorbellController.js.map +1 -1
  115. package/dist/lib/controller/RemoteController.d.ts +4 -4
  116. package/dist/lib/controller/RemoteController.d.ts.map +1 -1
  117. package/dist/lib/controller/RemoteController.js +62 -52
  118. package/dist/lib/controller/RemoteController.js.map +1 -1
  119. package/dist/lib/controller/index.d.ts +4 -4
  120. package/dist/lib/datastream/DataStreamManagement.d.ts.map +1 -1
  121. package/dist/lib/datastream/DataStreamManagement.js +10 -9
  122. package/dist/lib/datastream/DataStreamManagement.js.map +1 -1
  123. package/dist/lib/datastream/DataStreamParser.d.ts +24 -24
  124. package/dist/lib/datastream/DataStreamParser.d.ts.map +1 -1
  125. package/dist/lib/datastream/DataStreamParser.js +16 -7
  126. package/dist/lib/datastream/DataStreamParser.js.map +1 -1
  127. package/dist/lib/datastream/DataStreamServer.d.ts +24 -5
  128. package/dist/lib/datastream/DataStreamServer.d.ts.map +1 -1
  129. package/dist/lib/datastream/DataStreamServer.js +100 -59
  130. package/dist/lib/datastream/DataStreamServer.js.map +1 -1
  131. package/dist/lib/datastream/index.d.ts +3 -3
  132. package/dist/lib/definitions/generate-definitions.d.ts.map +1 -1
  133. package/dist/lib/definitions/generate-definitions.js +18 -14
  134. package/dist/lib/definitions/generate-definitions.js.map +1 -1
  135. package/dist/lib/definitions/generator-configuration.d.ts.map +1 -1
  136. package/dist/lib/definitions/generator-configuration.js +32 -14
  137. package/dist/lib/definitions/generator-configuration.js.map +1 -1
  138. package/dist/lib/model/AccessoryInfo.d.ts +6 -6
  139. package/dist/lib/model/AccessoryInfo.d.ts.map +1 -1
  140. package/dist/lib/model/AccessoryInfo.js +79 -69
  141. package/dist/lib/model/AccessoryInfo.js.map +1 -1
  142. package/dist/lib/model/ControllerStorage.d.ts.map +1 -1
  143. package/dist/lib/model/ControllerStorage.js +3 -3
  144. package/dist/lib/model/ControllerStorage.js.map +1 -1
  145. package/dist/lib/model/HAPStorage.d.ts.map +1 -1
  146. package/dist/lib/model/HAPStorage.js +1 -0
  147. package/dist/lib/model/HAPStorage.js.map +1 -1
  148. package/dist/lib/model/IdentifierCache.d.ts +11 -11
  149. package/dist/lib/model/IdentifierCache.d.ts.map +1 -1
  150. package/dist/lib/model/IdentifierCache.js +67 -65
  151. package/dist/lib/model/IdentifierCache.js.map +1 -1
  152. package/dist/lib/tv/AccessControlManagement.d.ts +1 -1
  153. package/dist/lib/tv/AccessControlManagement.d.ts.map +1 -1
  154. package/dist/lib/tv/AccessControlManagement.js.map +1 -1
  155. package/dist/lib/util/clone.js +1 -0
  156. package/dist/lib/util/clone.js.map +1 -1
  157. package/dist/lib/util/color-utils.d.ts.map +1 -1
  158. package/dist/lib/util/color-utils.js +1 -1
  159. package/dist/lib/util/color-utils.js.map +1 -1
  160. package/dist/lib/util/eventedhttp.d.ts +4 -4
  161. package/dist/lib/util/eventedhttp.d.ts.map +1 -1
  162. package/dist/lib/util/eventedhttp.js +25 -22
  163. package/dist/lib/util/eventedhttp.js.map +1 -1
  164. package/dist/lib/util/hapCrypto.d.ts +5 -5
  165. package/dist/lib/util/hapCrypto.d.ts.map +1 -1
  166. package/dist/lib/util/hapCrypto.js +57 -86
  167. package/dist/lib/util/hapCrypto.js.map +1 -1
  168. package/dist/lib/util/hapStatusError.js +1 -1
  169. package/dist/lib/util/net-utils.d.ts.map +1 -1
  170. package/dist/lib/util/net-utils.js +0 -2
  171. package/dist/lib/util/net-utils.js.map +1 -1
  172. package/dist/lib/util/once.d.ts +1 -1
  173. package/dist/lib/util/once.d.ts.map +1 -1
  174. package/dist/lib/util/once.js +1 -0
  175. package/dist/lib/util/once.js.map +1 -1
  176. package/dist/lib/util/request-util.d.ts.map +1 -1
  177. package/dist/lib/util/request-util.js +1 -0
  178. package/dist/lib/util/request-util.js.map +1 -1
  179. package/dist/lib/util/time.d.ts +1 -1
  180. package/dist/lib/util/time.d.ts.map +1 -1
  181. package/dist/lib/util/time.js +5 -5
  182. package/dist/lib/util/time.js.map +1 -1
  183. package/dist/lib/util/tlv.d.ts.map +1 -1
  184. package/dist/lib/util/tlv.js +9 -6
  185. package/dist/lib/util/tlv.js.map +1 -1
  186. package/dist/lib/util/uuid.d.ts.map +1 -1
  187. package/dist/lib/util/uuid.js +25 -19
  188. package/dist/lib/util/uuid.js.map +1 -1
  189. package/dist/types.d.ts +0 -1
  190. package/dist/types.d.ts.map +1 -1
  191. package/package.json +16 -12
@@ -21,7 +21,7 @@ var clone_1 = require("./util/clone");
21
21
  var request_util_1 = require("./util/request-util");
22
22
  var uuid = (0, tslib_1.__importStar)(require("./util/uuid"));
23
23
  var uuid_1 = require("./util/uuid");
24
- var debug = (0, debug_1.default)('HAP-NodeJS:Accessory');
24
+ var debug = (0, debug_1.default)("HAP-NodeJS:Accessory");
25
25
  var MAX_ACCESSORIES = 149; // Maximum number of bridged accessories per bridge.
26
26
  var MAX_SERVICES = 100;
27
27
  // Known category values. Category is a hint to iOS clients about what "type" of Accessory this represents, for UI only.
@@ -87,6 +87,10 @@ var MDNSAdvertiser;
87
87
  * Use the `bonjour-hap` module as advertiser.
88
88
  */
89
89
  MDNSAdvertiser["BONJOUR"] = "bonjour-hap";
90
+ /**
91
+ * Use Avahi/D-Bus as advertiser.
92
+ */
93
+ MDNSAdvertiser["AVAHI"] = "avahi";
90
94
  })(MDNSAdvertiser = exports.MDNSAdvertiser || (exports.MDNSAdvertiser = {}));
91
95
  var WriteRequestState;
92
96
  (function (WriteRequestState) {
@@ -171,32 +175,14 @@ var Accessory = /** @class */ (function (_super) {
171
175
  _this.getPrimaryAccessory = function () {
172
176
  return _this.bridged ? _this.bridge : _this;
173
177
  };
174
- _this.disableUnusedIDPurge = function () {
175
- _this.shouldPurgeUnusedIDs = false;
176
- };
177
- _this.enableUnusedIDPurge = function () {
178
- _this.shouldPurgeUnusedIDs = true;
179
- };
180
- /**
181
- * Manually purge the unused ids if you like, comes handy
182
- * when you have disabled auto purge so you can do it manually
183
- */
184
- _this.purgeUnusedIDs = function () {
185
- //Cache the state of the purge mechanism and set it to true
186
- var oldValue = _this.shouldPurgeUnusedIDs;
187
- _this.shouldPurgeUnusedIDs = true;
188
- //Reassign all ids
189
- _this._assignIDs(_this._identifierCache);
190
- //Revert back the purge mechanism state
191
- _this.shouldPurgeUnusedIDs = oldValue;
192
- };
193
178
  (0, assert_1.default)(displayName, "Accessories must be created with a non-empty displayName.");
194
179
  (0, assert_1.default)(UUID, "Accessories must be created with a valid UUID.");
195
- (0, assert_1.default)(uuid.isValid(UUID), "UUID '" + UUID + "' is not a valid UUID. Try using the provided 'generateUUID' function to create a valid UUID from any arbitrary string, like a serial number.");
180
+ (0, assert_1.default)(uuid.isValid(UUID), "UUID '" + UUID + "' is not a valid UUID. Try using the provided 'generateUUID' function to create a " +
181
+ "valid UUID from any arbitrary string, like a serial number.");
196
182
  // create our initial "Accessory Information" Service that all Accessories are expected to have
197
183
  _this.addService(Service_1.Service.AccessoryInformation)
198
184
  .setCharacteristic(Characteristic_1.Characteristic.Name, displayName);
199
- // sign up for when iOS attempts to "set" the Identify characteristic - this means a paired device wishes
185
+ // sign up for when iOS attempts to "set" the `Identify` characteristic - this means a paired device wishes
200
186
  // for us to identify ourselves (as opposed to an unpaired device - that case is handled by HAPServer 'identify' event)
201
187
  _this.getService(Service_1.Service.AccessoryInformation)
202
188
  .getCharacteristic(Characteristic_1.Characteristic.Identify)
@@ -220,6 +206,7 @@ var Accessory = /** @class */ (function (_super) {
220
206
  callback();
221
207
  }
222
208
  };
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
223
210
  Accessory.prototype.addService = function (serviceParam) {
224
211
  var e_1, _a;
225
212
  var constructorArgs = [];
@@ -228,7 +215,7 @@ var Accessory = /** @class */ (function (_super) {
228
215
  }
229
216
  // service might be a constructor like `Service.AccessoryInformation` instead of an instance
230
217
  // of Service. Coerce if necessary.
231
- var service = typeof serviceParam === 'function'
218
+ var service = typeof serviceParam === "function"
232
219
  ? new serviceParam(constructorArgs[0], constructorArgs[1], constructorArgs[2])
233
220
  : serviceParam;
234
221
  try {
@@ -237,10 +224,14 @@ var Accessory = /** @class */ (function (_super) {
237
224
  var existing = _c.value;
238
225
  if (existing.UUID === service.UUID) {
239
226
  // OK we have two Services with the same UUID. Check that each defines a `subtype` property and that each is unique.
240
- if (!service.subtype)
241
- throw new Error("Cannot add a Service with the same UUID '" + existing.UUID + "' as another Service in this Accessory without also defining a unique 'subtype' property.");
242
- if (service.subtype === existing.subtype)
243
- throw new Error("Cannot add a Service with the same UUID '" + existing.UUID + "' and subtype '" + existing.subtype + "' as another Service in this Accessory.");
227
+ if (!service.subtype) {
228
+ throw new Error("Cannot add a Service with the same UUID '" + existing.UUID +
229
+ "' as another Service in this Accessory without also defining a unique 'subtype' property.");
230
+ }
231
+ if (service.subtype === existing.subtype) {
232
+ throw new Error("Cannot add a Service with the same UUID '" + existing.UUID +
233
+ "' and subtype '" + existing.subtype + "' as another Service in this Accessory.");
234
+ }
244
235
  }
245
236
  }
246
237
  }
@@ -314,11 +305,11 @@ var Accessory = /** @class */ (function (_super) {
314
305
  try {
315
306
  for (var _b = (0, tslib_1.__values)(this.services), _c = _b.next(); !_c.done; _c = _b.next()) {
316
307
  var service = _c.value;
317
- if (typeof name === 'string' && (service.displayName === name || service.name === name || service.subtype === name)) {
308
+ if (typeof name === "string" && (service.displayName === name || service.name === name || service.subtype === name)) {
318
309
  return service;
319
- // @ts-expect-error
310
+ // @ts-expect-error: UUID property
320
311
  }
321
- else if (typeof name === 'function' && ((service instanceof name) || (name.UUID === service.UUID))) {
312
+ else if (typeof name === "function" && ((service instanceof name) || (name.UUID === service.UUID))) {
322
313
  return service;
323
314
  }
324
315
  }
@@ -339,7 +330,7 @@ var Accessory = /** @class */ (function (_super) {
339
330
  var service = _c.value;
340
331
  if (typeof uuid === "string" && (service.displayName === uuid || service.name === uuid) && service.subtype === subType) {
341
332
  return service;
342
- // @ts-expect-error
333
+ // @ts-expect-error: UUID property
343
334
  }
344
335
  else if (typeof uuid === "function" && ((service instanceof uuid) || (uuid.UUID === service.UUID)) && service.subtype === subType) {
345
336
  return service;
@@ -359,10 +350,11 @@ var Accessory = /** @class */ (function (_super) {
359
350
  * @deprecated Not supported anymore
360
351
  */
361
352
  Accessory.prototype.updateReachability = function (reachable) {
362
- if (!this.bridged)
353
+ if (!this.bridged) {
363
354
  throw new Error("Cannot update reachability on non-bridged accessory!");
355
+ }
364
356
  this.reachable = reachable;
365
- debug('Reachability update is no longer being supported.');
357
+ debug("Reachability update is no longer being supported.");
366
358
  };
367
359
  Accessory.prototype.addBridgedAccessory = function (accessory, deferUpdate) {
368
360
  var e_5, _a;
@@ -421,14 +413,16 @@ var Accessory = /** @class */ (function (_super) {
421
413
  this.enqueueConfigurationUpdate();
422
414
  };
423
415
  Accessory.prototype.removeBridgedAccessory = function (accessory, deferUpdate) {
424
- if (accessory._isBridge)
416
+ if (accessory._isBridge) {
425
417
  throw new Error("Cannot Bridge another Bridge!");
418
+ }
426
419
  // check for UUID conflict
427
420
  var foundMatchAccessory = this.bridgedAccessories.findIndex(function (existing) {
428
421
  return existing.UUID === accessory.UUID;
429
422
  });
430
- if (foundMatchAccessory === -1)
423
+ if (foundMatchAccessory === -1) {
431
424
  throw new Error("Cannot find the bridged Accessory to remove.");
425
+ }
432
426
  this.bridgedAccessories.splice(foundMatchAccessory, 1);
433
427
  accessory.removeAllListeners();
434
428
  if (!deferUpdate) {
@@ -546,7 +540,7 @@ var Accessory = /** @class */ (function (_super) {
546
540
  return; // ignore those services, as they get replaced by the RTPStreamManagement
547
541
  }
548
542
  // all other services get added. We can't really control possibly linking to any of those ignored services
549
- // so this is really only half baked stuff.
543
+ // so this is really only half-baked stuff.
550
544
  _this.addService(service);
551
545
  });
552
546
  // replace stream controllers; basically only to still support the "forceStop" call
@@ -575,15 +569,15 @@ var Accessory = /** @class */ (function (_super) {
575
569
  : controllerConstructor;
576
570
  var id = controller.controllerId();
577
571
  if (this.controllers[id]) {
578
- throw new Error("A Controller with the type/id '" + id + "' was already added to the accessory " + this.displayName);
572
+ throw new Error("A Controller with the type/id '".concat(id, "' was already added to the accessory ").concat(this.displayName));
579
573
  }
580
574
  var savedServiceMap = this.serializedControllers && this.serializedControllers[id];
581
575
  var serviceMap;
582
576
  if (savedServiceMap) { // we found data to restore from
583
577
  var clonedServiceMap = (0, clone_1.clone)(savedServiceMap);
584
578
  var updatedServiceMap = controller.initWithServices(savedServiceMap); // init controller with existing services
585
- serviceMap = updatedServiceMap || savedServiceMap; // initWithServices could return a updated serviceMap, otherwise just use the existing one
586
- if (updatedServiceMap) { // controller returned a ServiceMap and thus signaled a updated set of services
579
+ serviceMap = updatedServiceMap || savedServiceMap; // initWithServices could return an updated serviceMap, otherwise just use the existing one
580
+ if (updatedServiceMap) { // controller returned a ServiceMap and thus signaled an updated set of services
587
581
  // clonedServiceMap is altered by this method, should not be touched again after this call (for the future people)
588
582
  this.handleUpdatedControllerServiceMap(clonedServiceMap, updatedServiceMap);
589
583
  }
@@ -629,7 +623,8 @@ var Accessory = /** @class */ (function (_super) {
629
623
  var storedController = this.controllers[id];
630
624
  if (storedController) {
631
625
  if (storedController.controller !== controller) {
632
- throw new Error("[" + this.displayName + "] tried removing a controller with the id/type '" + id + "' though provided controller isn't the same which is registered!");
626
+ throw new Error("[" + this.displayName + "] tried removing a controller with the id/type '" + id +
627
+ "' though provided controller isn't the same which is registered!");
633
628
  }
634
629
  if ((0, controller_1.isSerializableController)(controller)) {
635
630
  // this will reset the state change delegate before we call handleControllerRemoved()
@@ -707,7 +702,7 @@ var Accessory = /** @class */ (function (_super) {
707
702
  return this._setupURI;
708
703
  }
709
704
  var buffer = Buffer.alloc(8);
710
- var setupCode = this._accessoryInfo && parseInt(this._accessoryInfo.pincode.replace(/-/g, ''), 10);
705
+ var setupCode = this._accessoryInfo && parseInt(this._accessoryInfo.pincode.replace(/-/g, ""), 10);
711
706
  var value_low = setupCode;
712
707
  var value_high = this._accessoryInfo && this._accessoryInfo.category >> 1;
713
708
  value_low |= 1 << 28; // Supports IP;
@@ -717,7 +712,7 @@ var Accessory = /** @class */ (function (_super) {
717
712
  }
718
713
  buffer.writeUInt32BE(value_high, 0);
719
714
  var encodedPayload = (buffer.readUInt32BE(4) + (buffer.readUInt32BE(0) * Math.pow(2, 32))).toString(36).toUpperCase();
720
- if (encodedPayload.length != 9) {
715
+ if (encodedPayload.length !== 9) {
721
716
  for (var i = 0; i <= 9 - encodedPayload.length; i++) {
722
717
  encodedPayload = "0" + encodedPayload;
723
718
  }
@@ -738,6 +733,7 @@ var Accessory = /** @class */ (function (_super) {
738
733
  "This might prevent the accessory from being added to the Home app or leading to the accessory being unresponsive!");
739
734
  }
740
735
  else {
736
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
741
737
  var checkValue = function (name, value) {
742
738
  if (!value) {
743
739
  console.log("HAP-NodeJS WARNING: The accessory '" + _this.displayName + "' is getting published with the characteristic '" + name + "'" +
@@ -819,12 +815,32 @@ var Accessory = /** @class */ (function (_super) {
819
815
  // that have been removed since the last call to assignIDs())
820
816
  if (this._identifierCache) {
821
817
  //Check weather we want to purge the unused ids
822
- if (this.shouldPurgeUnusedIDs)
818
+ if (this.shouldPurgeUnusedIDs) {
823
819
  this._identifierCache.stopTrackingUsageAndExpireUnused();
820
+ }
824
821
  //Save in case we have new ones
825
822
  this._identifierCache.save();
826
823
  }
827
824
  };
825
+ Accessory.prototype.disableUnusedIDPurge = function () {
826
+ this.shouldPurgeUnusedIDs = false;
827
+ };
828
+ Accessory.prototype.enableUnusedIDPurge = function () {
829
+ this.shouldPurgeUnusedIDs = true;
830
+ };
831
+ /**
832
+ * Manually purge the unused ids if you like, comes handy
833
+ * when you have disabled auto purge so you can do it manually
834
+ */
835
+ Accessory.prototype.purgeUnusedIDs = function () {
836
+ //Cache the state of the purge mechanism and set it to true
837
+ var oldValue = this.shouldPurgeUnusedIDs;
838
+ this.shouldPurgeUnusedIDs = true;
839
+ //Reassign all ids
840
+ this._assignIDs(this._identifierCache);
841
+ // Revert the purge mechanism state
842
+ this.shouldPurgeUnusedIDs = oldValue;
843
+ };
828
844
  /**
829
845
  * Returns a JSON representation of this accessory suitable for delivering to HAP clients.
830
846
  */
@@ -908,133 +924,151 @@ var Accessory = /** @class */ (function (_super) {
908
924
  * new Accessory.
909
925
  */
910
926
  Accessory.prototype.publish = function (info, allowInsecureRequest) {
911
- var _this = this;
912
927
  var _a, _b;
913
- // noinspection JSDeprecatedSymbols
914
- if (!info.advertiser && info.useLegacyAdvertiser != null) {
915
- // noinspection JSDeprecatedSymbols
916
- info.advertiser = info.useLegacyAdvertiser ? "bonjour-hap" /* BONJOUR */ : "ciao" /* CIAO */;
917
- console.warn('DEPRECATED The PublishInfo.useLegacyAdvertiser option has been removed. Please use the PublishInfo.advertiser property to enable "ciao" (useLegacyAdvertiser=false) ' +
918
- 'or "bonjour-hap" (useLegacyAdvertiser=true) mdns advertiser libraries!');
919
- }
920
- // noinspection JSDeprecatedSymbols
921
- if (info.mdns && info.advertiser !== "bonjour-hap" /* BONJOUR */) {
922
- console.log("DEPRECATED user supplied a custom 'mdns' option. This option is deprecated and ignored. " +
923
- "Please move to the new 'bind' option.");
924
- }
925
- var service = this.getService(Service_1.Service.ProtocolInformation);
926
- if (!service) {
927
- service = this.addService(Service_1.Service.ProtocolInformation); // add the protocol information service to the primary accessory
928
- }
929
- service.setCharacteristic(Characteristic_1.Characteristic.Version, Advertiser_1.CiaoAdvertiser.protocolVersionService);
930
- if (this.lastKnownUsername && this.lastKnownUsername !== info.username) { // username changed since last publish
931
- Accessory.cleanupAccessoryData(this.lastKnownUsername); // delete old Accessory data
932
- }
933
- if (!this.initialized && ((_a = info.addIdentifyingMaterial) !== null && _a !== void 0 ? _a : true)) {
934
- // adding some identifying material to our displayName if its our first publish() call
935
- this.displayName = this.displayName + " " + crypto_1.default.createHash('sha512')
936
- .update(info.username, 'utf8')
937
- .digest('hex').slice(0, 4).toUpperCase();
938
- this.getService(Service_1.Service.AccessoryInformation).updateCharacteristic(Characteristic_1.Characteristic.Name, this.displayName);
939
- }
940
- // attempt to load existing AccessoryInfo from disk
941
- this._accessoryInfo = AccessoryInfo_1.AccessoryInfo.load(info.username);
942
- // if we don't have one, create a new one.
943
- if (!this._accessoryInfo) {
944
- debug("[%s] Creating new AccessoryInfo for our HAP server", this.displayName);
945
- this._accessoryInfo = AccessoryInfo_1.AccessoryInfo.create(info.username);
946
- }
947
- if (info.setupID) {
948
- this._setupID = info.setupID;
949
- }
950
- else if (this._accessoryInfo.setupID === undefined || this._accessoryInfo.setupID === "") {
951
- this._setupID = Accessory._generateSetupID();
952
- }
953
- else {
954
- this._setupID = this._accessoryInfo.setupID;
955
- }
956
- this._accessoryInfo.setupID = this._setupID;
957
- // make sure we have up-to-date values in AccessoryInfo, then save it in case they changed (or if we just created it)
958
- this._accessoryInfo.displayName = this.displayName;
959
- this._accessoryInfo.model = this.getService(Service_1.Service.AccessoryInformation).getCharacteristic(Characteristic_1.Characteristic.Model).value;
960
- this._accessoryInfo.category = info.category || 1 /* OTHER */;
961
- this._accessoryInfo.pincode = info.pincode;
962
- this._accessoryInfo.save();
963
- // create our IdentifierCache so we can provide clients with stable aid/iid's
964
- this._identifierCache = IdentifierCache_1.IdentifierCache.load(info.username);
965
- // if we don't have one, create a new one.
966
- if (!this._identifierCache) {
967
- debug("[%s] Creating new IdentifierCache", this.displayName);
968
- this._identifierCache = new IdentifierCache_1.IdentifierCache(info.username);
969
- }
970
- //If it's bridge and there are not accessories already assigned to the bridge
971
- //probably purge is not needed since it's going to delete all the ids
972
- //of accessories that might be added later. Useful when dynamically adding
973
- //accessories.
974
- if (this._isBridge && this.bridgedAccessories.length == 0) {
975
- this.disableUnusedIDPurge();
976
- this.controllerStorage.purgeUnidentifiedAccessoryData = false;
977
- }
978
- if (!this.initialized) { // controller storage is only loaded from disk the first time we publish!
979
- this.controllerStorage.load(info.username); // initializing controller data
980
- }
981
- // assign aid/iid
982
- this._assignIDs(this._identifierCache);
983
- // get our accessory information in HAP format and determine if our configuration (that is, our
984
- // Accessories/Services/Characteristics) has changed since the last time we were published. make
985
- // sure to omit actual values since these are not part of the "configuration".
986
- var config = this.internalHAPRepresentation(false); // TODO ensure this stuff is ordered
987
- // TODO queue this check until about 5 seconds after startup, allowing some last changes after the publish call
988
- // without constantly incrementing the current config number
989
- this._accessoryInfo.checkForCurrentConfigurationNumberIncrement(config, true);
990
- this.validateAccessory(true);
991
- // create our Advertiser which broadcasts our presence over mdns
992
- var parsed = Accessory.parseBindOption(info);
993
- switch ((_b = info.advertiser) !== null && _b !== void 0 ? _b : "bonjour-hap" /* BONJOUR */) {
994
- case "ciao" /* CIAO */:
995
- this._advertiser = new Advertiser_1.CiaoAdvertiser(this._accessoryInfo, {
996
- interface: parsed.advertiserAddress
997
- }, {
998
- restrictedAddresses: parsed.serviceRestrictedAddress,
999
- disabledIpv6: parsed.serviceDisableIpv6,
1000
- });
1001
- break;
1002
- case "bonjour-hap" /* BONJOUR */:
1003
- // noinspection JSDeprecatedSymbols
1004
- this._advertiser = new Advertiser_1.BonjourHAPAdvertiser(this._accessoryInfo, info.mdns, {
1005
- restrictedAddresses: parsed.serviceRestrictedAddress,
1006
- disabledIpv6: parsed.serviceDisableIpv6,
1007
- });
1008
- break;
1009
- default:
1010
- throw new Error("Unsupported advertiser setting: '" + info.advertiser + "'");
1011
- }
1012
- this._advertiser.on("updated-name" /* UPDATED_NAME */, function (name) {
1013
- _this.displayName = name;
1014
- if (_this._accessoryInfo) {
1015
- _this._accessoryInfo.displayName = name;
1016
- _this._accessoryInfo.save();
1017
- }
1018
- // bonjour service name MUST match the name in the accessory information service
1019
- _this.getService(Service_1.Service.AccessoryInformation)
1020
- .updateCharacteristic(Characteristic_1.Characteristic.Name, name);
928
+ return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
929
+ var service, config, parsed, defaultAdvertiser, _c;
930
+ var _this = this;
931
+ return (0, tslib_1.__generator)(this, function (_d) {
932
+ switch (_d.label) {
933
+ case 0:
934
+ // noinspection JSDeprecatedSymbols
935
+ if (!info.advertiser && info.useLegacyAdvertiser != null) {
936
+ // noinspection JSDeprecatedSymbols
937
+ info.advertiser = info.useLegacyAdvertiser ? "bonjour-hap" /* BONJOUR */ : "ciao" /* CIAO */;
938
+ console.warn("DEPRECATED The PublishInfo.useLegacyAdvertiser option has been removed. " +
939
+ "Please use the PublishInfo.advertiser property to enable \"ciao\" (useLegacyAdvertiser=false) " +
940
+ "or \"bonjour-hap\" (useLegacyAdvertiser=true) mdns advertiser libraries!");
941
+ }
942
+ // noinspection JSDeprecatedSymbols
943
+ if (info.mdns && info.advertiser !== "bonjour-hap" /* BONJOUR */) {
944
+ console.log("DEPRECATED user supplied a custom 'mdns' option. This option is deprecated and ignored. " +
945
+ "Please move to the new 'bind' option.");
946
+ }
947
+ service = this.getService(Service_1.Service.ProtocolInformation);
948
+ if (!service) {
949
+ service = this.addService(Service_1.Service.ProtocolInformation); // add the protocol information service to the primary accessory
950
+ }
951
+ service.setCharacteristic(Characteristic_1.Characteristic.Version, Advertiser_1.CiaoAdvertiser.protocolVersionService);
952
+ if (this.lastKnownUsername && this.lastKnownUsername !== info.username) { // username changed since last publish
953
+ Accessory.cleanupAccessoryData(this.lastKnownUsername); // delete old Accessory data
954
+ }
955
+ if (!this.initialized && ((_a = info.addIdentifyingMaterial) !== null && _a !== void 0 ? _a : true)) {
956
+ // adding some identifying material to our displayName if its our first publish() call
957
+ this.displayName = this.displayName + " " + crypto_1.default.createHash("sha512")
958
+ .update(info.username, "utf8")
959
+ .digest("hex").slice(0, 4).toUpperCase();
960
+ this.getService(Service_1.Service.AccessoryInformation).updateCharacteristic(Characteristic_1.Characteristic.Name, this.displayName);
961
+ }
962
+ // attempt to load existing AccessoryInfo from disk
963
+ this._accessoryInfo = AccessoryInfo_1.AccessoryInfo.load(info.username);
964
+ // if we don't have one, create a new one.
965
+ if (!this._accessoryInfo) {
966
+ debug("[%s] Creating new AccessoryInfo for our HAP server", this.displayName);
967
+ this._accessoryInfo = AccessoryInfo_1.AccessoryInfo.create(info.username);
968
+ }
969
+ if (info.setupID) {
970
+ this._setupID = info.setupID;
971
+ }
972
+ else if (this._accessoryInfo.setupID === undefined || this._accessoryInfo.setupID === "") {
973
+ this._setupID = Accessory._generateSetupID();
974
+ }
975
+ else {
976
+ this._setupID = this._accessoryInfo.setupID;
977
+ }
978
+ this._accessoryInfo.setupID = this._setupID;
979
+ // make sure we have up-to-date values in AccessoryInfo, then save it in case they changed (or if we just created it)
980
+ this._accessoryInfo.displayName = this.displayName;
981
+ this._accessoryInfo.model = this.getService(Service_1.Service.AccessoryInformation).getCharacteristic(Characteristic_1.Characteristic.Model).value;
982
+ this._accessoryInfo.category = info.category || 1 /* OTHER */;
983
+ this._accessoryInfo.pincode = info.pincode;
984
+ this._accessoryInfo.save();
985
+ // create our IdentifierCache so we can provide clients with stable aid/iid's
986
+ this._identifierCache = IdentifierCache_1.IdentifierCache.load(info.username);
987
+ // if we don't have one, create a new one.
988
+ if (!this._identifierCache) {
989
+ debug("[%s] Creating new IdentifierCache", this.displayName);
990
+ this._identifierCache = new IdentifierCache_1.IdentifierCache(info.username);
991
+ }
992
+ //If it's bridge and there are not accessories already assigned to the bridge
993
+ //probably purge is not needed since it's going to delete all the ids
994
+ //of accessories that might be added later. Useful when dynamically adding
995
+ //accessories.
996
+ if (this._isBridge && this.bridgedAccessories.length === 0) {
997
+ this.disableUnusedIDPurge();
998
+ this.controllerStorage.purgeUnidentifiedAccessoryData = false;
999
+ }
1000
+ if (!this.initialized) { // controller storage is only loaded from disk the first time we publish!
1001
+ this.controllerStorage.load(info.username); // initializing controller data
1002
+ }
1003
+ // assign aid/iid
1004
+ this._assignIDs(this._identifierCache);
1005
+ config = this.internalHAPRepresentation(false);
1006
+ // TODO queue this check until about 5 seconds after startup, allowing some last changes after the publish call
1007
+ // without constantly incrementing the current config number
1008
+ this._accessoryInfo.checkForCurrentConfigurationNumberIncrement(config, true);
1009
+ this.validateAccessory(true);
1010
+ parsed = Accessory.parseBindOption(info);
1011
+ if (!((_b = info.advertiser) !== null && _b !== void 0)) return [3 /*break*/, 1];
1012
+ _c = _b;
1013
+ return [3 /*break*/, 3];
1014
+ case 1: return [4 /*yield*/, Advertiser_1.AvahiAdvertiser.isAvailable()];
1015
+ case 2:
1016
+ _c = ((_d.sent()) ? "avahi" /* AVAHI */ : "bonjour-hap" /* BONJOUR */);
1017
+ _d.label = 3;
1018
+ case 3:
1019
+ defaultAdvertiser = _c;
1020
+ switch (defaultAdvertiser) {
1021
+ case "ciao" /* CIAO */:
1022
+ this._advertiser = new Advertiser_1.CiaoAdvertiser(this._accessoryInfo, {
1023
+ interface: parsed.advertiserAddress,
1024
+ }, {
1025
+ restrictedAddresses: parsed.serviceRestrictedAddress,
1026
+ disabledIpv6: parsed.serviceDisableIpv6,
1027
+ });
1028
+ break;
1029
+ case "bonjour-hap" /* BONJOUR */:
1030
+ // noinspection JSDeprecatedSymbols
1031
+ this._advertiser = new Advertiser_1.BonjourHAPAdvertiser(this._accessoryInfo, info.mdns, {
1032
+ restrictedAddresses: parsed.serviceRestrictedAddress,
1033
+ disabledIpv6: parsed.serviceDisableIpv6,
1034
+ });
1035
+ break;
1036
+ case "avahi" /* AVAHI */:
1037
+ this._advertiser = new Advertiser_1.AvahiAdvertiser(this._accessoryInfo);
1038
+ break;
1039
+ default:
1040
+ throw new Error("Unsupported advertiser setting: '" + info.advertiser + "'");
1041
+ }
1042
+ this._advertiser.on("updated-name" /* UPDATED_NAME */, function (name) {
1043
+ _this.displayName = name;
1044
+ if (_this._accessoryInfo) {
1045
+ _this._accessoryInfo.displayName = name;
1046
+ _this._accessoryInfo.save();
1047
+ }
1048
+ // bonjour service name MUST match the name in the accessory information service
1049
+ _this.getService(Service_1.Service.AccessoryInformation)
1050
+ .updateCharacteristic(Characteristic_1.Characteristic.Name, name);
1051
+ });
1052
+ // create our HAP server which handles all communication between iOS devices and us
1053
+ this._server = new HAPServer_1.HAPServer(this._accessoryInfo);
1054
+ this._server.allowInsecureRequest = !!allowInsecureRequest;
1055
+ this._server.on("listening" /* LISTENING */, this.onListening.bind(this));
1056
+ this._server.on("identify" /* IDENTIFY */, this.identificationRequest.bind(this, false));
1057
+ this._server.on("pair" /* PAIR */, this.handleInitialPairSetupFinished.bind(this));
1058
+ this._server.on("add-pairing" /* ADD_PAIRING */, this.handleAddPairing.bind(this));
1059
+ this._server.on("remove-pairing" /* REMOVE_PAIRING */, this.handleRemovePairing.bind(this));
1060
+ this._server.on("list-pairings" /* LIST_PAIRINGS */, this.handleListPairings.bind(this));
1061
+ this._server.on("accessories" /* ACCESSORIES */, this.handleAccessories.bind(this));
1062
+ this._server.on("get-characteristics" /* GET_CHARACTERISTICS */, this.handleGetCharacteristics.bind(this));
1063
+ this._server.on("set-characteristics" /* SET_CHARACTERISTICS */, this.handleSetCharacteristics.bind(this));
1064
+ this._server.on("connection-closed" /* CONNECTION_CLOSED */, this.handleHAPConnectionClosed.bind(this));
1065
+ this._server.on("request-resource" /* REQUEST_RESOURCE */, this.handleResource.bind(this));
1066
+ this._server.listen(info.port, parsed.serverAddress);
1067
+ this.initialized = true;
1068
+ return [2 /*return*/];
1069
+ }
1070
+ });
1021
1071
  });
1022
- // create our HAP server which handles all communication between iOS devices and us
1023
- this._server = new HAPServer_1.HAPServer(this._accessoryInfo);
1024
- this._server.allowInsecureRequest = !!allowInsecureRequest;
1025
- this._server.on("listening" /* LISTENING */, this.onListening.bind(this));
1026
- this._server.on("identify" /* IDENTIFY */, this.identificationRequest.bind(this, false));
1027
- this._server.on("pair" /* PAIR */, this.handleInitialPairSetupFinished.bind(this));
1028
- this._server.on("add-pairing" /* ADD_PAIRING */, this.handleAddPairing.bind(this));
1029
- this._server.on("remove-pairing" /* REMOVE_PAIRING */, this.handleRemovePairing.bind(this));
1030
- this._server.on("list-pairings" /* LIST_PAIRINGS */, this.handleListPairings.bind(this));
1031
- this._server.on("accessories" /* ACCESSORIES */, this.handleAccessories.bind(this));
1032
- this._server.on("get-characteristics" /* GET_CHARACTERISTICS */, this.handleGetCharacteristics.bind(this));
1033
- this._server.on("set-characteristics" /* SET_CHARACTERISTICS */, this.handleSetCharacteristics.bind(this));
1034
- this._server.on("connection-closed" /* CONNECTION_CLOSED */, this.handleHAPConnectionClosed.bind(this));
1035
- this._server.on("request-resource" /* REQUEST_RESOURCE */, this.handleResource.bind(this));
1036
- this._server.listen(info.port, parsed.serverAddress);
1037
- this.initialized = true;
1038
1072
  };
1039
1073
  /**
1040
1074
  * Removes this Accessory from the local network
@@ -1103,7 +1137,8 @@ var Accessory = /** @class */ (function (_super) {
1103
1137
  // the HAP server is listening, so we can now start advertising our presence.
1104
1138
  this._advertiser.initPort(port);
1105
1139
  this._advertiser.startAdvertising()
1106
- .then(function () { return _this.emit("advertised" /* ADVERTISED */); });
1140
+ .then(function () { return _this.emit("advertised" /* ADVERTISED */); })
1141
+ .catch(function (reason) { return console.error("Could not create mDNS advertisement. The HAP-Server won't be discoverable: " + reason); });
1107
1142
  this.emit("listening" /* LISTENING */, port, hostname);
1108
1143
  };
1109
1144
  Accessory.prototype.handleInitialPairSetupFinished = function (username, publicKey, callback) {
@@ -1242,7 +1277,8 @@ var Accessory = /** @class */ (function (_super) {
1242
1277
  var accessory = _this.getAccessoryByAID(aid);
1243
1278
  var characteristic = accessory.getCharacteristicByIID(iid);
1244
1279
  _this.sendCharacteristicWarning(characteristic, "timeout-read" /* TIMEOUT_READ */, "The read handler for the characteristic '" +
1245
- characteristic.displayName + "' on the accessory '" + accessory.displayName + "' didn't respond at all!. Please check that you properly call the callback!");
1280
+ characteristic.displayName + "' on the accessory '" + accessory.displayName + "' didn't respond at all!. " +
1281
+ "Please check that you properly call the callback!");
1246
1282
  characteristics.push({
1247
1283
  aid: aid,
1248
1284
  iid: iid,
@@ -1268,7 +1304,7 @@ var Accessory = /** @class */ (function (_super) {
1268
1304
  this_1.handleCharacteristicRead(connection, id, request).then(function (value) {
1269
1305
  return (0, tslib_1.__assign)({ aid: id.aid, iid: id.iid }, value);
1270
1306
  }, function (reason) {
1271
- console.error("[" + _this.displayName + "] Read request for characteristic " + name + " encountered an error: " + reason.stack);
1307
+ console.error("[".concat(_this.displayName, "] Read request for characteristic ").concat(name, " encountered an error: ").concat(reason.stack));
1272
1308
  return {
1273
1309
  aid: id.aid,
1274
1310
  iid: id.iid,
@@ -1311,18 +1347,18 @@ var Accessory = /** @class */ (function (_super) {
1311
1347
  return (0, tslib_1.__generator)(this, function (_a) {
1312
1348
  characteristic = this.findCharacteristic(id.aid, id.iid);
1313
1349
  if (!characteristic) {
1314
- debug('[%s] Could not find a Characteristic with aid of %s and iid of %s', this.displayName, id.aid, id.iid);
1350
+ debug("[%s] Could not find a Characteristic with aid of %s and iid of %s", this.displayName, id.aid, id.iid);
1315
1351
  return [2 /*return*/, { status: -70410 /* INVALID_VALUE_IN_REQUEST */ }];
1316
1352
  }
1317
1353
  if (!characteristic.props.perms.includes("pr" /* PAIRED_READ */)) { // check if read is allowed for this characteristic
1318
- debug('[%s] Tried reading from characteristic which does not allow reading (aid of %s and iid of %s)', this.displayName, id.aid, id.iid);
1354
+ debug("[%s] Tried reading from characteristic which does not allow reading (aid of %s and iid of %s)", this.displayName, id.aid, id.iid);
1319
1355
  return [2 /*return*/, { status: -70405 /* WRITE_ONLY_CHARACTERISTIC */ }];
1320
1356
  }
1321
1357
  if (characteristic.props.adminOnlyAccess && characteristic.props.adminOnlyAccess.includes(0 /* READ */)) {
1322
1358
  verifiable = true;
1323
1359
  if (!connection.username || !this._accessoryInfo) {
1324
1360
  verifiable = false;
1325
- debug('[%s] Could not verify admin permissions for Characteristic which requires admin permissions for reading (aid of %s and iid of %s)', this.displayName, id.aid, id.iid);
1361
+ debug("[%s] Could not verify admin permissions for Characteristic which requires admin permissions for reading (aid of %s and iid of %s)", this.displayName, id.aid, id.iid);
1326
1362
  }
1327
1363
  if (!verifiable || !this._accessoryInfo.hasAdminPermissions(connection.username)) {
1328
1364
  return [2 /*return*/, { status: -70401 /* INSUFFICIENT_PRIVILEGES */ }];
@@ -1330,9 +1366,9 @@ var Accessory = /** @class */ (function (_super) {
1330
1366
  }
1331
1367
  return [2 /*return*/, characteristic.handleGetRequest(connection).then(function (value) {
1332
1368
  value = (0, request_util_1.formatOutgoingCharacteristicValue)(value, characteristic.props);
1333
- debug('[%s] Got Characteristic "%s" value: "%s"', _this.displayName, characteristic.displayName, value);
1369
+ debug("[%s] Got Characteristic \"%s\" value: \"%s\"", _this.displayName, characteristic.displayName, value);
1334
1370
  var data = {
1335
- value: value == undefined ? null : value,
1371
+ value: value == null ? null : value,
1336
1372
  };
1337
1373
  if (request.includeMeta) {
1338
1374
  data.format = characteristic.props.format;
@@ -1353,8 +1389,8 @@ var Accessory = /** @class */ (function (_super) {
1353
1389
  }
1354
1390
  return data;
1355
1391
  }, function (reason) {
1356
- // @ts-expect-error
1357
- debug('[%s] Error getting value for characteristic "%s": %s', _this.displayName, characteristic.displayName, HAPServer_1.HAPStatus[reason]);
1392
+ // @ts-expect-error: forceConsistentCasingInFileNames compiler option
1393
+ debug("[%s] Error getting value for characteristic \"%s\": %s", _this.displayName, characteristic.displayName, HAPServer_1.HAPStatus[reason]);
1358
1394
  return { status: reason };
1359
1395
  })];
1360
1396
  });
@@ -1421,7 +1457,8 @@ var Accessory = /** @class */ (function (_super) {
1421
1457
  var accessory = _this.getAccessoryByAID(aid);
1422
1458
  var characteristic = accessory.getCharacteristicByIID(iid);
1423
1459
  _this.sendCharacteristicWarning(characteristic, "timeout-write" /* TIMEOUT_WRITE */, "The write handler for the characteristic '" +
1424
- characteristic.displayName + "' on the accessory '" + accessory.displayName + "' didn't respond at all!. Please check that you properly call the callback!");
1460
+ characteristic.displayName + "' on the accessory '" + accessory.displayName + "' didn't respond at all!. " +
1461
+ "Please check that you properly call the callback!");
1425
1462
  characteristics.push({
1426
1463
  aid: aid,
1427
1464
  iid: iid,
@@ -1447,7 +1484,7 @@ var Accessory = /** @class */ (function (_super) {
1447
1484
  this_2.handleCharacteristicWrite(connection, data, writeState).then(function (value) {
1448
1485
  return (0, tslib_1.__assign)({ aid: data.aid, iid: data.iid }, value);
1449
1486
  }, function (reason) {
1450
- console.error("[" + _this.displayName + "] Write request for characteristic " + name + " encountered an error: " + reason.stack);
1487
+ console.error("[".concat(_this.displayName, "] Write request for characteristic ").concat(name, " encountered an error: ").concat(reason.stack));
1451
1488
  return {
1452
1489
  aid: data.aid,
1453
1490
  iid: data.iid,
@@ -1491,26 +1528,26 @@ var Accessory = /** @class */ (function (_super) {
1491
1528
  characteristic = this.findCharacteristic(data.aid, data.iid);
1492
1529
  evResponse = undefined;
1493
1530
  if (!characteristic) {
1494
- debug('[%s] Could not find a Characteristic with aid of %s and iid of %s', this.displayName, data.aid, data.iid);
1531
+ debug("[%s] Could not find a Characteristic with aid of %s and iid of %s", this.displayName, data.aid, data.iid);
1495
1532
  return [2 /*return*/, { status: -70410 /* INVALID_VALUE_IN_REQUEST */ }];
1496
1533
  }
1497
1534
  if (writeState === 2 /* TIMED_WRITE_REJECTED */) {
1498
1535
  return [2 /*return*/, { status: -70410 /* INVALID_VALUE_IN_REQUEST */ }];
1499
1536
  }
1500
- if (data.ev != undefined) { // register/unregister event notifications
1537
+ if (data.ev != null) { // register/unregister event notifications
1501
1538
  notificationsEnabled = connection.hasEventNotifications(data.aid, data.iid);
1502
1539
  // it seems like the Home App sends unregister requests for characteristics which don't have notify permissions
1503
1540
  // see https://github.com/homebridge/HAP-NodeJS/issues/868
1504
- if (notificationsEnabled != data.ev) {
1541
+ if (notificationsEnabled !== data.ev) {
1505
1542
  if (!characteristic.props.perms.includes("ev" /* NOTIFY */)) { // check if notify is allowed for this characteristic
1506
- debug('[%s] Tried %s notifications for Characteristic which does not allow notify (aid of %s and iid of %s)', this.displayName, data.ev ? "enabling" : "disabling", data.aid, data.iid);
1543
+ debug("[%s] Tried %s notifications for Characteristic which does not allow notify (aid of %s and iid of %s)", this.displayName, data.ev ? "enabling" : "disabling", data.aid, data.iid);
1507
1544
  return [2 /*return*/, { status: -70406 /* NOTIFICATION_NOT_SUPPORTED */ }];
1508
1545
  }
1509
1546
  if (characteristic.props.adminOnlyAccess && characteristic.props.adminOnlyAccess.includes(2 /* NOTIFY */)) {
1510
1547
  verifiable = true;
1511
1548
  if (!connection.username || !this._accessoryInfo) {
1512
1549
  verifiable = false;
1513
- debug('[%s] Could not verify admin permissions for Characteristic which requires admin permissions for notify (aid of %s and iid of %s)', this.displayName, data.aid, data.iid);
1550
+ debug("[%s] Could not verify admin permissions for Characteristic which requires admin permissions for notify (aid of %s and iid of %s)", this.displayName, data.aid, data.iid);
1514
1551
  }
1515
1552
  if (!verifiable || !this._accessoryInfo.hasAdminPermissions(connection.username)) {
1516
1553
  return [2 /*return*/, { status: -70401 /* INSUFFICIENT_PRIVILEGES */ }];
@@ -1521,27 +1558,27 @@ var Accessory = /** @class */ (function (_super) {
1521
1558
  connection.enableEventNotifications(data.aid, data.iid);
1522
1559
  characteristic.subscribe();
1523
1560
  evResponse = true;
1524
- debug('[%s] Registered Characteristic "%s" on "%s" for events', connection.remoteAddress, characteristic.displayName, this.displayName);
1561
+ debug("[%s] Registered Characteristic \"%s\" on \"%s\" for events", connection.remoteAddress, characteristic.displayName, this.displayName);
1525
1562
  }
1526
1563
  else {
1527
1564
  characteristic.unsubscribe();
1528
1565
  connection.disableEventNotifications(data.aid, data.iid);
1529
1566
  evResponse = false;
1530
- debug('[%s] Unregistered Characteristic "%s" on "%s" for events', connection.remoteAddress, characteristic.displayName, this.displayName);
1567
+ debug("[%s] Unregistered Characteristic \"%s\" on \"%s\" for events", connection.remoteAddress, characteristic.displayName, this.displayName);
1531
1568
  }
1532
1569
  }
1533
1570
  // response is returned below in the else block
1534
1571
  }
1535
- if (data.value != undefined) {
1572
+ if (data.value != null) {
1536
1573
  if (!characteristic.props.perms.includes("pw" /* PAIRED_WRITE */)) { // check if write is allowed for this characteristic
1537
- debug('[%s] Tried writing to Characteristic which does not allow writing (aid of %s and iid of %s)', this.displayName, data.aid, data.iid);
1574
+ debug("[%s] Tried writing to Characteristic which does not allow writing (aid of %s and iid of %s)", this.displayName, data.aid, data.iid);
1538
1575
  return [2 /*return*/, { status: -70404 /* READ_ONLY_CHARACTERISTIC */ }];
1539
1576
  }
1540
1577
  if (characteristic.props.adminOnlyAccess && characteristic.props.adminOnlyAccess.includes(1 /* WRITE */)) {
1541
1578
  verifiable = true;
1542
1579
  if (!connection.username || !this._accessoryInfo) {
1543
1580
  verifiable = false;
1544
- debug('[%s] Could not verify admin permissions for Characteristic which requires admin permissions for write (aid of %s and iid of %s)', this.displayName, data.aid, data.iid);
1581
+ debug("[%s] Could not verify admin permissions for Characteristic which requires admin permissions for write (aid of %s and iid of %s)", this.displayName, data.aid, data.iid);
1545
1582
  }
1546
1583
  if (!verifiable || !this._accessoryInfo.hasAdminPermissions(connection.username)) {
1547
1584
  return [2 /*return*/, { status: -70401 /* INSUFFICIENT_PRIVILEGES */ }];
@@ -1561,18 +1598,19 @@ var Accessory = /** @class */ (function (_super) {
1561
1598
  }
1562
1599
  }
1563
1600
  if (characteristic.props.perms.includes("tw" /* TIMED_WRITE */) && writeState !== 1 /* TIMED_WRITE_AUTHENTICATED */) {
1564
- debug('[%s] Tried writing to a timed write only Characteristic without properly preparing (iid of %s and aid of %s)', this.displayName, data.aid, data.iid);
1601
+ debug("[%s] Tried writing to a timed write only Characteristic without properly preparing (iid of %s and aid of %s)", this.displayName, data.aid, data.iid);
1565
1602
  return [2 /*return*/, { status: -70410 /* INVALID_VALUE_IN_REQUEST */ }];
1566
1603
  }
1567
1604
  return [2 /*return*/, characteristic.handleSetRequest(data.value, connection).then(function (value) {
1568
- debug('[%s] Setting Characteristic "%s" to value %s', _this.displayName, characteristic.displayName, data.value);
1605
+ debug("[%s] Setting Characteristic \"%s\" to value %s", _this.displayName, characteristic.displayName, data.value);
1569
1606
  return {
1607
+ // if write response is requests and value is provided, return that
1570
1608
  value: data.r && value ? (0, request_util_1.formatOutgoingCharacteristicValue)(value, characteristic.props) : undefined,
1571
1609
  ev: evResponse,
1572
1610
  };
1573
1611
  }, function (status) {
1574
- // @ts-expect-error
1575
- debug('[%s] Error setting Characteristic "%s" to value %s: ', _this.displayName, characteristic.displayName, data.value, HAPServer_1.HAPStatus[status]);
1612
+ // @ts-expect-error: forceConsistentCasingInFileNames compiler option
1613
+ debug("[%s] Error setting Characteristic \"%s\" to value %s: ", _this.displayName, characteristic.displayName, data.value, HAPServer_1.HAPStatus[status]);
1576
1614
  return { status: status };
1577
1615
  })];
1578
1616
  }
@@ -1604,10 +1642,11 @@ var Accessory = /** @class */ (function (_super) {
1604
1642
  callback({ httpCode: 404 /* NOT_FOUND */, status: -70409 /* RESOURCE_DOES_NOT_EXIST */ });
1605
1643
  return;
1606
1644
  }
1607
- controller.handleSnapshotRequest(data["image-height"], data["image-width"], accessory === null || accessory === void 0 ? void 0 : accessory.displayName).then(function (buffer) {
1645
+ controller.handleSnapshotRequest(data["image-height"], data["image-width"], accessory === null || accessory === void 0 ? void 0 : accessory.displayName, data.reason)
1646
+ .then(function (buffer) {
1608
1647
  callback(undefined, buffer);
1609
1648
  }, function (status) {
1610
- callback({ httpCode: 200 /* OK */, status: status });
1649
+ callback({ httpCode: 207 /* MULTI_STATUS */, status: status });
1611
1650
  });
1612
1651
  return;
1613
1652
  }
@@ -1667,11 +1706,11 @@ var Accessory = /** @class */ (function (_super) {
1667
1706
  if (!this._server) {
1668
1707
  return; // we're not running a HAPServer, so there's no one to notify about this event
1669
1708
  }
1670
- if (accessory.aid == undefined || change.characteristic.iid == undefined) {
1709
+ if (accessory.aid == null || change.characteristic.iid == null) {
1671
1710
  debug("[%s] Muting event notification for %s as ids aren't yet assigned!", accessory.displayName, change.characteristic.displayName);
1672
1711
  return;
1673
1712
  }
1674
- if (change.context != undefined && typeof change.context === "object" && change.context.omitEventUpdate) {
1713
+ if (change.context != null && typeof change.context === "object" && change.context.omitEventUpdate) {
1675
1714
  debug("[%s] Omitting event updates for %s as specified in the context object!", accessory.displayName, change.characteristic.displayName);
1676
1715
  return;
1677
1716
  }
@@ -1705,7 +1744,7 @@ var Accessory = /** @class */ (function (_super) {
1705
1744
  warning.originatorChain = (0, tslib_1.__spreadArray)([this.displayName], (0, tslib_1.__read)(warning.originatorChain), false);
1706
1745
  var emitted = this.emit("characteristic-warning" /* CHARACTERISTIC_WARNING */, warning);
1707
1746
  if (!emitted) {
1708
- var message = "[" + warning.originatorChain.join("@") + "] " + warning.message;
1747
+ var message = "[".concat(warning.originatorChain.join("@"), "] ").concat(warning.message);
1709
1748
  if (warning.type === "error-message" /* ERROR_MESSAGE */
1710
1749
  || warning.type === "timeout-read" /* TIMEOUT_READ */ || warning.type === "timeout-write" /* TIMEOUT_WRITE */) {
1711
1750
  console.error(message);
@@ -1750,9 +1789,9 @@ var Accessory = /** @class */ (function (_super) {
1750
1789
  });
1751
1790
  };
1752
1791
  Accessory._generateSetupID = function () {
1753
- var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
1792
+ var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1754
1793
  var max = chars.length;
1755
- var setupID = '';
1794
+ var setupID = "";
1756
1795
  for (var i = 0; i < 4; i++) {
1757
1796
  var index = Math.floor(Math.random() * max);
1758
1797
  setupID += chars.charAt(index);
@@ -1949,9 +1988,9 @@ var Accessory = /** @class */ (function (_super) {
1949
1988
  };
1950
1989
  };
1951
1990
  /**
1952
- * @deprecated Please use the Categories const enum above. Scheduled to be removed in 2021-06.
1991
+ * @deprecated Please use the Categories const enum above.
1953
1992
  */
1954
- // @ts-ignore
1993
+ // @ts-expect-error: forceConsistentCasingInFileNames compiler option
1955
1994
  Accessory.Categories = Categories;
1956
1995
  return Accessory;
1957
1996
  }(events_1.EventEmitter));