homebridge-unifi-protect 7.20.1 → 7.22.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 (63) hide show
  1. package/dist/devices/protect-camera-package.js +14 -6
  2. package/dist/devices/protect-camera-package.js.map +1 -1
  3. package/dist/devices/protect-camera.d.ts +3 -2
  4. package/dist/devices/protect-camera.js +121 -61
  5. package/dist/devices/protect-camera.js.map +1 -1
  6. package/dist/devices/protect-chime.js +3 -2
  7. package/dist/devices/protect-chime.js.map +1 -1
  8. package/dist/devices/protect-device.js +19 -22
  9. package/dist/devices/protect-device.js.map +1 -1
  10. package/dist/devices/protect-doorbell.d.ts +4 -2
  11. package/dist/devices/protect-doorbell.js +37 -22
  12. package/dist/devices/protect-doorbell.js.map +1 -1
  13. package/dist/devices/protect-light.js +6 -6
  14. package/dist/devices/protect-light.js.map +1 -1
  15. package/dist/devices/protect-liveviews.js +8 -26
  16. package/dist/devices/protect-liveviews.js.map +1 -1
  17. package/dist/devices/protect-nvr-systeminfo.d.ts +0 -2
  18. package/dist/devices/protect-nvr-systeminfo.js +13 -47
  19. package/dist/devices/protect-nvr-systeminfo.js.map +1 -1
  20. package/dist/devices/protect-securitysystem.js +17 -36
  21. package/dist/devices/protect-securitysystem.js.map +1 -1
  22. package/dist/devices/protect-sensor.d.ts +2 -2
  23. package/dist/devices/protect-sensor.js +16 -16
  24. package/dist/devices/protect-sensor.js.map +1 -1
  25. package/dist/devices/protect-viewer.js +8 -8
  26. package/dist/devices/protect-viewer.js.map +1 -1
  27. package/dist/protect-events.js +16 -20
  28. package/dist/protect-events.js.map +1 -1
  29. package/dist/protect-livestream.d.ts +1 -0
  30. package/dist/protect-livestream.js +23 -3
  31. package/dist/protect-livestream.js.map +1 -1
  32. package/dist/protect-nvr.d.ts +5 -5
  33. package/dist/protect-nvr.js +36 -34
  34. package/dist/protect-nvr.js.map +1 -1
  35. package/dist/protect-options.d.ts +4 -4
  36. package/dist/protect-options.js +16 -15
  37. package/dist/protect-options.js.map +1 -1
  38. package/dist/protect-platform.d.ts +1 -1
  39. package/dist/protect-platform.js +8 -14
  40. package/dist/protect-platform.js.map +1 -1
  41. package/dist/protect-record.d.ts +1 -4
  42. package/dist/protect-record.js +13 -28
  43. package/dist/protect-record.js.map +1 -1
  44. package/dist/protect-snapshot.js.map +1 -1
  45. package/dist/protect-stream.js +39 -56
  46. package/dist/protect-stream.js.map +1 -1
  47. package/dist/protect-timeshift.d.ts +0 -2
  48. package/dist/protect-timeshift.js +12 -23
  49. package/dist/protect-timeshift.js.map +1 -1
  50. package/dist/protect-types.d.ts +1 -0
  51. package/dist/protect-types.js +1 -0
  52. package/dist/protect-types.js.map +1 -1
  53. package/dist/settings.d.ts +4 -4
  54. package/dist/settings.js +5 -5
  55. package/dist/settings.js.map +1 -1
  56. package/homebridge-ui/public/index.html +54 -51
  57. package/homebridge-ui/public/lib/featureoptions.js +7 -8
  58. package/homebridge-ui/public/lib/featureoptions.js.map +1 -1
  59. package/homebridge-ui/public/lib/webUi-featureoptions.mjs +3484 -558
  60. package/homebridge-ui/public/lib/webUi.mjs +13 -5
  61. package/homebridge-ui/public/ui.mjs +62 -99
  62. package/homebridge-ui/server.js +6 -1
  63. package/package.json +10 -13
@@ -30,7 +30,15 @@ export class ProtectCameraPackage extends ProtectCamera {
30
30
  this.accessory.context = {};
31
31
  // Inherit our HKSV and motion awareness states from our parent camera.
32
32
  this.accessory.context.detectMotion = savedContext.detectMotion ?? true;
33
- this.accessory.context.hksvRecording = savedContext.hksvRecording ?? true;
33
+ if (this.hasFeature("Video.HKSV.Recording.Switch")) {
34
+ // Compatibility with older releases. I'll remove this in the future.
35
+ if (savedContext.hksvRecording !== undefined) {
36
+ this.accessory.context.hksvRecordingDisabled = !savedContext.hksvRecording;
37
+ }
38
+ else {
39
+ this.accessory.context.hksvRecordingDisabled = savedContext.hksvRecordingDisabled ?? false;
40
+ }
41
+ }
34
42
  // We explicitly avoid adding the MAC address of the camera - that's reserved for real Protect devices, not synthetic ones we create.
35
43
  this.accessory.context.nvr = this.nvr.ufp.mac;
36
44
  this.accessory.context.packageCamera = this.ufp.mac;
@@ -103,8 +111,8 @@ export class ProtectCameraPackage extends ProtectCamera {
103
111
  return false;
104
112
  }
105
113
  // Activate or deactivate the package camera flashlight.
106
- service.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => !!this.flashlightState);
107
- service.getCharacteristic(this.hap.Characteristic.On)?.onSet(async (value) => {
114
+ service.getCharacteristic(this.hap.Characteristic.On).onGet(() => !!this.flashlightState);
115
+ service.getCharacteristic(this.hap.Characteristic.On).onSet(async (value) => {
108
116
  // Stop heartbeating the flashlight to allow it to turn off.
109
117
  if (!value) {
110
118
  clearInterval(this.flashlightTimer);
@@ -138,7 +146,7 @@ export class ProtectCameraPackage extends ProtectCamera {
138
146
  clearInterval(this.flashlightTimer);
139
147
  // If it's dark, we're done.
140
148
  if (!this.ufp.isDark) {
141
- setTimeout(() => service?.updateCharacteristic(this.hap.Characteristic.On, false), 50);
149
+ setTimeout(() => service.updateCharacteristic(this.hap.Characteristic.On, false), 50);
142
150
  return;
143
151
  }
144
152
  // Activate the flashlight.
@@ -164,8 +172,8 @@ export class ProtectCameraPackage extends ProtectCamera {
164
172
  return {
165
173
  channel: channel,
166
174
  lens: 2,
167
- name: this.getResolution([channel.width, channel.height, channel.fps]) + " (" + channel.name + ") [" + (this.ufp.videoCodec.replace("h265", "hevc")).toUpperCase() +
168
- "]",
175
+ name: this.getResolution([channel.width, channel.height, channel.fps]) + " (" + channel.name + ") [" +
176
+ (this.ufp.videoCodec.replace("h265", "hevc")).toUpperCase() + "]",
169
177
  resolution: [channel.width, channel.height, channel.fps],
170
178
  url: "rtsps://" + this.nvr.config.address + ":" + this.nvr.ufp.ports.rtsps.toString() + "/" + channel.rtspAlias + "?enableSrtp"
171
179
  };
@@ -1 +1 @@
1
- {"version":3,"file":"protect-camera-package.js","sourceRoot":"","sources":["../../src/devices/protect-camera-package.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protect-camera-package.js","sourceRoot":"","sources":["../../src/devices/protect-camera-package.ts"],"names":[],"mappings":"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"}
@@ -29,11 +29,10 @@ export declare class ProtectCamera extends ProtectDevice {
29
29
  detectLicensePlate: string[];
30
30
  readonly livestream: LivestreamManager;
31
31
  messageSwitches: {
32
- [index: string]: MessageSwitchInterface;
32
+ [index: string]: MessageSwitchInterface | undefined;
33
33
  };
34
34
  packageCamera?: Nullable<ProtectCameraPackage>;
35
35
  private rtspEntries;
36
- private rtspQuality;
37
36
  stream: ProtectStreamingDelegate;
38
37
  ufp: ProtectCameraConfig;
39
38
  constructor(nvr: ProtectNvr, device: ProtectCameraConfig, accessory: PlatformAccessory);
@@ -45,6 +44,7 @@ export declare class ProtectCamera extends ProtectDevice {
45
44
  private configureAmbientLightSensor;
46
45
  private configureAccessFeatures;
47
46
  private configureMotionSmartSensor;
47
+ private configureDoorbellMuteSwitch;
48
48
  private configureDoorbellTrigger;
49
49
  protected configureVideoDoorbell(): boolean;
50
50
  private configureCameraDetails;
@@ -64,5 +64,6 @@ export declare class ProtectCamera extends ProtectDevice {
64
64
  get isHksvCapable(): boolean;
65
65
  private get nightVision();
66
66
  private get nightVisionBrightness();
67
+ get audioFilters(): string[];
67
68
  }
68
69
  export {};
@@ -1,5 +1,6 @@
1
1
  import { ProtectReservedNames, toCamelCase } from "../protect-types.js";
2
2
  import { LivestreamManager } from "../protect-livestream.js";
3
+ import { PROTECT_FFMPEG_AUDIO_FILTER_FFTNR } from "../settings.js";
3
4
  import { ProtectDevice } from "./protect-device.js";
4
5
  import { ProtectStreamingDelegate } from "../protect-stream.js";
5
6
  export class ProtectCamera extends ProtectDevice {
@@ -13,7 +14,6 @@ export class ProtectCamera extends ProtectDevice {
13
14
  messageSwitches;
14
15
  packageCamera;
15
16
  rtspEntries;
16
- rtspQuality;
17
17
  stream;
18
18
  ufp;
19
19
  // Create an instance.
@@ -26,7 +26,6 @@ export class ProtectCamera extends ProtectDevice {
26
26
  this.livestream = new LivestreamManager(this);
27
27
  this.messageSwitches = {};
28
28
  this.rtspEntries = [];
29
- this.rtspQuality = {};
30
29
  this.ufp = device;
31
30
  this.configureHints();
32
31
  this.configureDevice();
@@ -55,10 +54,10 @@ export class ProtectCamera extends ProtectDevice {
55
54
  this.hints.twoWayAudio = this.ufp.featureFlags.hasSpeaker && this.hasFeature("Audio") && this.hasFeature("Audio.TwoWay");
56
55
  this.hints.twoWayAudioDirect = this.ufp.featureFlags.hasSpeaker && this.hasFeature("Audio") && this.hasFeature("Audio.TwoWay.Direct");
57
56
  // Sanity check our target transcoding bitrates, if defined.
58
- if ((this.hints.transcodeBitrate === null) || (this.hints.transcodeBitrate === undefined) || (this.hints.transcodeBitrate <= 0)) {
57
+ if (!this.hints.transcodeBitrate || (this.hints.transcodeBitrate <= 0)) {
59
58
  this.hints.transcodeBitrate = -1;
60
59
  }
61
- if ((this.hints.transcodeHighLatencyBitrate === null) || (this.hints.transcodeHighLatencyBitrate === undefined) || (this.hints.transcodeHighLatencyBitrate <= 0)) {
60
+ if (!this.hints.transcodeHighLatencyBitrate || (this.hints.transcodeHighLatencyBitrate <= 0)) {
62
61
  this.hints.transcodeHighLatencyBitrate = -1;
63
62
  }
64
63
  return true;
@@ -70,9 +69,20 @@ export class ProtectCamera extends ProtectDevice {
70
69
  // Clean out the context object in case it's been polluted somehow.
71
70
  this.accessory.context = {};
72
71
  this.accessory.context.detectMotion = savedContext.detectMotion ?? true;
73
- this.accessory.context.hksvRecording = savedContext.hksvRecording ?? true;
74
72
  this.accessory.context.mac = this.ufp.mac;
75
73
  this.accessory.context.nvr = this.nvr.ufp.mac;
74
+ if (this.hasFeature("Video.HKSV.Recording.Switch")) {
75
+ // Compatibility with older releases. I'll remove this in the future.
76
+ if (savedContext.hksvRecording !== undefined) {
77
+ this.accessory.context.hksvRecordingDisabled = !savedContext.hksvRecording;
78
+ }
79
+ else {
80
+ this.accessory.context.hksvRecordingDisabled = savedContext.hksvRecordingDisabled ?? false;
81
+ }
82
+ }
83
+ if (this.hasFeature("Doorbell.Mute")) {
84
+ this.accessory.context.doorbellMuted = savedContext.doorbellMuted ?? false;
85
+ }
76
86
  // Inform the user that motion detection will suck.
77
87
  if (this.ufp.recordingSettings.mode === "never") {
78
88
  this.log.warn("Motion events will not be generated by the Protect controller when the controller's camera recording options are set to \"never\".");
@@ -114,6 +124,8 @@ export class ProtectCamera extends ProtectDevice {
114
124
  this.configureStatusLedSwitch();
115
125
  // Configure the night vision indicator light switch.
116
126
  this.configureNightVisionDimmer();
127
+ // Configure the doorbell mute switch.
128
+ this.configureDoorbellMuteSwitch();
117
129
  // Configure the doorbell trigger.
118
130
  this.configureDoorbellTrigger();
119
131
  // Listen for events.
@@ -125,15 +137,13 @@ export class ProtectCamera extends ProtectDevice {
125
137
  // Cleanup after ourselves if we're being deleted.
126
138
  cleanup() {
127
139
  // If we've got HomeKit Secure Video enabled and recording, disable it.
128
- if (this.stream?.hksv?.isRecording) {
140
+ if (this.stream.hksv?.isRecording) {
129
141
  void this.stream.hksv.updateRecordingActive(false);
130
142
  }
131
143
  // Cleanup our livestream manager.
132
144
  this.livestream.shutdown();
133
145
  // Unregister our controller.
134
- if (this.stream?.controller) {
135
- this.accessory.removeController(this.stream.controller);
136
- }
146
+ this.accessory.removeController(this.stream.controller);
137
147
  super.cleanup();
138
148
  this.isDeleted = true;
139
149
  }
@@ -152,7 +162,7 @@ export class ProtectCamera extends ProtectDevice {
152
162
  // - HKSV recording enabled.
153
163
  // - No enabled smart motion detection capabilities on the Protect device.
154
164
  // - Smart detection disabled.
155
- if (this.stream?.hksv?.isRecording ||
165
+ if (this.stream.hksv?.isRecording ||
156
166
  !(this.ufp.featureFlags.smartDetectAudioTypes.length || this.ufp.featureFlags.smartDetectTypes.length) || !this.hints.smartDetect) {
157
167
  this.nvr.events.motionEventHandler(this);
158
168
  }
@@ -164,8 +174,9 @@ export class ProtectCamera extends ProtectDevice {
164
174
  // If smart detection is enabled, we need to filter out any events tagged as "motion". When users enable the "Create motion events" setting on a camera, Protect will
165
175
  // create motion-specific thumbnail events. We're only interested in true smart detection events.
166
176
  if (this.hints.smartDetect) {
167
- if (payload.metadata) {
168
- payload.metadata.detectedThumbnails = payload.metadata.detectedThumbnails?.filter(({ type }) => type !== "motion");
177
+ const event = payload;
178
+ if (event.metadata?.detectedThumbnails) {
179
+ event.metadata.detectedThumbnails = event.metadata.detectedThumbnails.filter(({ type }) => type !== "motion");
169
180
  }
170
181
  }
171
182
  // Process smart detection events that have occurred on a non-realtime basis. Generally, this includes audio and video events that require more analysis by Protect.
@@ -186,7 +197,7 @@ export class ProtectCamera extends ProtectDevice {
186
197
  addEventHandler(packet) {
187
198
  const payload = packet.payload;
188
199
  // Detect UniFi Access unlock events surfaced in Protect.
189
- if ((packet.header.modelKey === "event") && (payload.metadata?.action === "open_door") && payload.metadata?.openSuccess) {
200
+ if ((packet.header.modelKey === "event") && (payload.metadata?.action === "open_door") && payload.metadata.openSuccess) {
190
201
  const lockService = this.accessory.getServiceById(this.hap.Service.LockMechanism, ProtectReservedNames.LOCK_ACCESS);
191
202
  if (!lockService) {
192
203
  return;
@@ -198,8 +209,8 @@ export class ProtectCamera extends ProtectDevice {
198
209
  clearTimeout(this.accessUnlockTimer);
199
210
  }
200
211
  this.accessUnlockTimer = setTimeout(() => {
201
- lockService?.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
202
- lockService?.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
212
+ lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
213
+ lockService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
203
214
  this.accessUnlockTimer = undefined;
204
215
  }, 2000);
205
216
  return;
@@ -211,7 +222,7 @@ export class ProtectCamera extends ProtectDevice {
211
222
  // - We explicitly filter out events tagged as "motion". When users enable the "Create motion events" setting on a camera, Protect will create motion-specific
212
223
  // thumbnail events. We're only interested in true smart detection events.
213
224
  if (!this.hints.smartDetect || !((packet.header.modelKey === "smartDetectObject") || ((packet.header.modelKey === "event") &&
214
- ["smartDetectLine", "smartDetectZone"].includes(payload.type) && (payload.type !== "motion") && payload.smartDetectTypes.length))) {
225
+ ["smartDetectLine", "smartDetectZone"].includes(payload.type) && (payload.type !== "motion") && payload.smartDetectTypes?.length))) {
215
226
  return;
216
227
  }
217
228
  // Process the motion event.
@@ -241,11 +252,9 @@ export class ProtectCamera extends ProtectDevice {
241
252
  return -1;
242
253
  }
243
254
  try {
244
- let lux = (await response?.body.json()).illuminance ?? -1;
255
+ let lux = (await response?.body.json()).illuminance ?? 0;
245
256
  // The minimum value for ambient light in HomeKit is 0.0001. I have no idea why...but it is. Honor it.
246
- if (!lux) {
247
- lux = 0.0001;
248
- }
257
+ lux ||= 0.0001;
249
258
  return lux;
250
259
  // eslint-disable-next-line @stylistic/keyword-spacing
251
260
  }
@@ -273,14 +282,14 @@ export class ProtectCamera extends ProtectDevice {
273
282
  this.publish("ambientlight", this.ambientLight.toString());
274
283
  }, 60 * 1000);
275
284
  // Retrieve the active state when requested.
276
- service.getCharacteristic(this.hap.Characteristic.StatusActive)?.onGet(() => this.isOnline);
285
+ service.getCharacteristic(this.hap.Characteristic.StatusActive).onGet(() => this.isOnline);
277
286
  // Initialize the sensor.
278
287
  this.ambientLight = await getLux();
279
288
  if (this.ambientLight === -1) {
280
289
  this.ambientLight = 0.0001;
281
290
  }
282
291
  // Retrieve the current light level when requested.
283
- service.getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)?.onGet(() => this.ambientLight);
292
+ service.getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel).onGet(() => this.ambientLight);
284
293
  service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.ambientLight);
285
294
  service.updateCharacteristic(this.hap.Characteristic.StatusActive, this.isOnline);
286
295
  return true;
@@ -288,7 +297,7 @@ export class ProtectCamera extends ProtectDevice {
288
297
  // Configure UniFi Access specific features for devices that are made available in Protect.
289
298
  configureAccessFeatures() {
290
299
  // If the Access device doesn't have unlock capabilities, we're done.
291
- if (!this.ufp.accessDeviceMetadata?.featureFlags?.supportUnlock) {
300
+ if (!this.ufp.accessDeviceMetadata?.featureFlags.supportUnlock) {
292
301
  return false;
293
302
  }
294
303
  // Validate whether we should have this service enabled.
@@ -308,8 +317,8 @@ export class ProtectCamera extends ProtectDevice {
308
317
  if (value === this.hap.Characteristic.LockTargetState.SECURED) {
309
318
  // Let's make sure we revert the lock to it's prior state.
310
319
  setTimeout(() => {
311
- service?.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
312
- service?.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
320
+ service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
321
+ service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
313
322
  }, 50);
314
323
  return;
315
324
  }
@@ -318,8 +327,8 @@ export class ProtectCamera extends ProtectDevice {
318
327
  if (this.nvr.ufpApi.responseOk(response?.statusCode)) {
319
328
  // Something went wrong, revert to our prior state.
320
329
  setTimeout(() => {
321
- service?.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
322
- service?.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
330
+ service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
331
+ service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
323
332
  }, 50);
324
333
  return;
325
334
  }
@@ -341,7 +350,7 @@ export class ProtectCamera extends ProtectDevice {
341
350
  }
342
351
  // We don't have this contact sensor enabled, remove it.
343
352
  this.accessory.removeService(objectService);
344
- this.log.info("Disabling smart motion license plate contact sensor: %s.", objectService.subtype?.slice(objectService.subtype?.indexOf(".") + 1));
353
+ this.log.info("Disabling smart motion license plate contact sensor: %s.", objectService.subtype?.slice(objectService.subtype.indexOf(".") + 1));
345
354
  }
346
355
  // If we don't have smart motion detection available or we have smart motion object contact sensors disabled, let's remove them.
347
356
  if (!this.hints.smartDetectSensors) {
@@ -349,7 +358,7 @@ export class ProtectCamera extends ProtectDevice {
349
358
  for (const objectService of this.accessory.services.filter(x => x.subtype?.startsWith(ProtectReservedNames.CONTACT_MOTION_SMARTDETECT + "."))) {
350
359
  // We don't have this contact sensor enabled, remove it.
351
360
  this.accessory.removeService(objectService);
352
- this.log.info("Disabling smart motion contact sensor: %s.", objectService.subtype?.slice(objectService.subtype?.indexOf(".") + 1));
361
+ this.log.info("Disabling smart motion contact sensor: %s.", objectService.subtype?.slice(objectService.subtype.indexOf(".") + 1));
353
362
  }
354
363
  }
355
364
  // If we don't have smart motion detection, we're done.
@@ -394,6 +403,32 @@ export class ProtectCamera extends ProtectDevice {
394
403
  }
395
404
  return true;
396
405
  }
406
+ // Configure a switch to mute doorbell ring events in HomeKit.
407
+ configureDoorbellMuteSwitch() {
408
+ // Validate whether we should have this service enabled.
409
+ if (!this.validService(this.hap.Service.Switch, this.hasFeature("Doorbell.Mute"), ProtectReservedNames.SWITCH_DOORBELL_MUTE) ||
410
+ !this.accessory.getService(this.hap.Service.Doorbell)) {
411
+ delete this.accessory.context.doorbellMuted;
412
+ return false;
413
+ }
414
+ // Add the switch to the camera, if needed.
415
+ const service = this.acquireService(this.hap.Service.Switch, this.accessoryName + " Doorbell Mute", ProtectReservedNames.SWITCH_DOORBELL_MUTE);
416
+ // Fail gracefully.
417
+ if (!service) {
418
+ this.log.error("Unable to add the doorbell mute switch.");
419
+ return false;
420
+ }
421
+ // Configure the switch.
422
+ service.getCharacteristic(this.hap.Characteristic.On).onGet(() => this.accessory.context.doorbellMuted);
423
+ service.getCharacteristic(this.hap.Characteristic.On).onSet((value) => {
424
+ this.accessory.context.doorbellMuted = !!value;
425
+ this.log.info("Doorbell chime %s.", value ? "disabled" : "enabled");
426
+ });
427
+ // Initialize the switch.
428
+ service.updateCharacteristic(this.hap.Characteristic.On, this.accessory.context.doorbellMuted);
429
+ this.log.info("Enabling doorbell mute switch.");
430
+ return true;
431
+ }
397
432
  // Configure a switch to manually trigger a doorbell ring event for HomeKit.
398
433
  configureDoorbellTrigger() {
399
434
  // See if we have a doorbell service configured.
@@ -426,10 +461,8 @@ export class ProtectCamera extends ProtectDevice {
426
461
  return false;
427
462
  }
428
463
  // Trigger the doorbell.
429
- triggerService.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
430
- return this.isRinging;
431
- });
432
- triggerService.getCharacteristic(this.hap.Characteristic.On)?.onSet((value) => {
464
+ triggerService.getCharacteristic(this.hap.Characteristic.On).onGet(() => this.isRinging);
465
+ triggerService.getCharacteristic(this.hap.Characteristic.On).onSet((value) => {
433
466
  if (value) {
434
467
  // Trigger the ring event.
435
468
  this.nvr.events.doorbellEventHandler(this, Date.now());
@@ -438,7 +471,7 @@ export class ProtectCamera extends ProtectDevice {
438
471
  else {
439
472
  // If the doorbell ring event is still going, we should be as well.
440
473
  if (this.isRinging) {
441
- setTimeout(() => triggerService?.updateCharacteristic(this.hap.Characteristic.On, true), 50);
474
+ setTimeout(() => triggerService.updateCharacteristic(this.hap.Characteristic.On, true), 50);
442
475
  }
443
476
  }
444
477
  });
@@ -492,7 +525,7 @@ export class ProtectCamera extends ProtectDevice {
492
525
  const newUfp = await this.nvr.ufpApi.updateDevice(this.ufp, { ispSettings: { irLedMode: value ? "auto" : "off" } });
493
526
  if (!newUfp) {
494
527
  this.log.error("Unable to set night vision to %s. Please ensure this username has the Administrator role in UniFi Protect.", value ? "auto" : "off");
495
- setTimeout(() => service?.updateCharacteristic(this.hap.Characteristic.NightVision, !value), 50);
528
+ setTimeout(() => service.updateCharacteristic(this.hap.Characteristic.NightVision, !value), 50);
496
529
  return;
497
530
  }
498
531
  // Update our internal view of the device configuration.
@@ -542,7 +575,7 @@ export class ProtectCamera extends ProtectDevice {
542
575
  async configureVideoStream() {
543
576
  const rtspEntries = [];
544
577
  // No channels exist on this camera or we don't have access to the bootstrap configuration.
545
- if (!this.ufp.channels) {
578
+ if (!this.ufp.channels.length) {
546
579
  return false;
547
580
  }
548
581
  // Enable RTSP on the camera if needed and get the list of RTSP streams we have ultimately configured.
@@ -550,7 +583,7 @@ export class ProtectCamera extends ProtectDevice {
550
583
  // Figure out which camera channels are RTSP-enabled, and user-enabled. We also filter out any package camera entries. We deal with those independently elsewhere.
551
584
  const cameraChannels = this.ufp.channels.filter(channel => channel.isRtspEnabled && (channel.name !== "Package Camera"));
552
585
  // Set the camera and shapshot URLs.
553
- const cameraUrl = "rtsps://" + (this.nvr.config.overrideAddress ?? this.ufp.connectionHost ?? this.nvr.ufp.host) + ":" + this.nvr.ufp.ports.rtsps.toString() + "/";
586
+ const cameraUrl = "rtsps://" + (this.nvr.config.overrideAddress ?? this.ufp.connectionHost) + ":" + this.nvr.ufp.ports.rtsps.toString() + "/";
554
587
  // No RTSP streams are available that meet our criteria - we're done.
555
588
  if (!cameraChannels.length) {
556
589
  this.log.info("No RTSP profiles found for this camera. " +
@@ -643,6 +676,7 @@ export class ProtectCamera extends ProtectDevice {
643
676
  // Publish our updated list of supported resolutions and their URLs.
644
677
  this.rtspEntries = rtspEntries;
645
678
  // If we've already configured the HomeKit video streaming delegate, we're done here.
679
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
646
680
  if (this.stream) {
647
681
  return true;
648
682
  }
@@ -714,8 +748,8 @@ export class ProtectCamera extends ProtectDevice {
714
748
  configureHksvRecordingSwitch() {
715
749
  // Validate whether we should have this service enabled.
716
750
  if (!this.validService(this.hap.Service.Switch, this.hasFeature("Video.HKSV.Recording.Switch"), ProtectReservedNames.SWITCH_HKSV_RECORDING)) {
717
- // We want to default this back to recording whenever we disable the recording switch.
718
- this.accessory.context.hksvRecording = true;
751
+ // Remove our stateful context since it's unneeded.
752
+ delete this.accessory.context.hksvRecordingDisabled;
719
753
  return false;
720
754
  }
721
755
  // Acquire the service.
@@ -726,17 +760,15 @@ export class ProtectCamera extends ProtectDevice {
726
760
  return false;
727
761
  }
728
762
  // Activate or deactivate HKSV recording.
729
- service.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
730
- return this.accessory.context.hksvRecording ?? true;
731
- });
732
- service.getCharacteristic(this.hap.Characteristic.On)?.onSet((value) => {
733
- if (this.accessory.context.hksvRecording !== value) {
763
+ service.getCharacteristic(this.hap.Characteristic.On).onGet(() => !this.accessory.context.hksvRecordingDisabled);
764
+ service.getCharacteristic(this.hap.Characteristic.On).onSet((value) => {
765
+ if (this.accessory.context.hksvRecordingDisabled !== !value) {
734
766
  this.log.info("HKSV event recording %s.", value ? "enabled" : "disabled");
735
767
  }
736
- this.accessory.context.hksvRecording = !!value;
768
+ this.accessory.context.hksvRecordingDisabled = !value;
737
769
  });
738
770
  // Initialize the switch.
739
- service.updateCharacteristic(this.hap.Characteristic.On, this.accessory.context.hksvRecording);
771
+ service.updateCharacteristic(this.hap.Characteristic.On, !this.accessory.context.hksvRecordingDisabled);
740
772
  this.log.info("Enabling HKSV recording switch.");
741
773
  return true;
742
774
  }
@@ -755,8 +787,8 @@ export class ProtectCamera extends ProtectDevice {
755
787
  return false;
756
788
  }
757
789
  // Adjust night vision capabilities.
758
- service.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => this.nightVision);
759
- service.getCharacteristic(this.hap.Characteristic.On)?.onSet(async (value) => {
790
+ service.getCharacteristic(this.hap.Characteristic.On).onGet(() => this.nightVision);
791
+ service.getCharacteristic(this.hap.Characteristic.On).onSet(async (value) => {
760
792
  if (this.nightVision !== value) {
761
793
  this.log.info("Night vision %s.", value ? "enabled" : "disabled");
762
794
  }
@@ -765,15 +797,15 @@ export class ProtectCamera extends ProtectDevice {
765
797
  const newUfp = await this.nvr.ufpApi.updateDevice(this.ufp, { ispSettings: { irLedMode: value ? mode : "off" } });
766
798
  if (!newUfp) {
767
799
  this.log.error("Unable to set night vision to %s. Please ensure this username has the Administrator role in UniFi Protect.", value ? "custom" : "off");
768
- setTimeout(() => service?.updateCharacteristic(this.hap.Characteristic.On, !value), 50);
800
+ setTimeout(() => service.updateCharacteristic(this.hap.Characteristic.On, !value), 50);
769
801
  return;
770
802
  }
771
803
  // Update our internal view of the device configuration.
772
804
  this.ufp = newUfp;
773
805
  });
774
806
  // Adjust the sensitivity of night vision.
775
- service.getCharacteristic(this.hap.Characteristic.Brightness)?.onGet(() => this.nightVisionBrightness);
776
- service.getCharacteristic(this.hap.Characteristic.Brightness)?.onSet(async (value) => {
807
+ service.getCharacteristic(this.hap.Characteristic.Brightness).onGet(() => this.nightVisionBrightness);
808
+ service.getCharacteristic(this.hap.Characteristic.Brightness).onSet(async (value) => {
777
809
  let level = value;
778
810
  let nightvision = {};
779
811
  // If we're less than 10% in brightness, assume we want to disable night vision.
@@ -813,7 +845,7 @@ export class ProtectCamera extends ProtectDevice {
813
845
  // Set the context to our updated device configuration.
814
846
  this.ufp = newUfp;
815
847
  // Make sure we properly reflect what brightness we're actually at, given the differences in setting granularity between Protect and HomeKit.
816
- setTimeout(() => service?.updateCharacteristic(this.hap.Characteristic.Brightness, level), 50);
848
+ setTimeout(() => service.updateCharacteristic(this.hap.Characteristic.Brightness, level), 50);
817
849
  });
818
850
  // Initialize the dimmer state.
819
851
  service.updateCharacteristic(this.hap.Characteristic.On, this.nightVision);
@@ -840,10 +872,8 @@ export class ProtectCamera extends ProtectDevice {
840
872
  continue;
841
873
  }
842
874
  // Activate or deactivate the appropriate recording mode on the Protect controller.
843
- service.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
844
- return this.ufp.recordingSettings.mode === ufpRecordingSetting;
845
- });
846
- service.getCharacteristic(this.hap.Characteristic.On)?.onSet(async (value) => {
875
+ service.getCharacteristic(this.hap.Characteristic.On).onGet(() => this.ufp.recordingSettings.mode === ufpRecordingSetting);
876
+ service.getCharacteristic(this.hap.Characteristic.On).onSet(async (value) => {
847
877
  // We only want to do something if we're being activated. Turning off the switch would really be an undefined state given that there are three different
848
878
  // settings one can choose from. Instead, we do nothing and leave it to the user to choose what state they really want to set.
849
879
  if (!value) {
@@ -887,7 +917,7 @@ export class ProtectCamera extends ProtectDevice {
887
917
  this.subscribeGet("rtsp", "RTSP information", () => {
888
918
  // Grab all the available RTSP channels and return them as a JSON.
889
919
  return JSON.stringify(Object.assign({}, ...this.ufp.channels.filter(channel => channel.isRtspEnabled)
890
- .map(channel => ({ [channel.name]: "rtsps://" + (this.nvr.config.overrideAddress ?? this.ufp.connectionHost ?? this.nvr.ufp.host) + ":" +
920
+ .map(channel => ({ [channel.name]: "rtsps://" + (this.nvr.config.overrideAddress ?? this.ufp.connectionHost) + ":" +
891
921
  this.nvr.ufp.ports.rtsp + "/" + channel.rtspAlias + "?enableSrtp" }))));
892
922
  });
893
923
  // Trigger snapshots when requested.
@@ -896,6 +926,7 @@ export class ProtectCamera extends ProtectDevice {
896
926
  if (value !== "true") {
897
927
  return;
898
928
  }
929
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
899
930
  void this.stream?.handleSnapshotRequest();
900
931
  });
901
932
  // Enable doorbell-specific MQTT capabilities only when we have a Protect doorbell or a doorbell trigger enabled.
@@ -951,7 +982,7 @@ export class ProtectCamera extends ProtectDevice {
951
982
  findRtspEntry(width, height, options) {
952
983
  const rtspEntries = options?.rtspEntries ?? this.rtspEntries;
953
984
  // No RTSP entries to choose from, we're done.
954
- if (!rtspEntries || !rtspEntries.length) {
985
+ if (!rtspEntries.length) {
955
986
  return null;
956
987
  }
957
988
  // Second, we check to see if we've set an explicit preference for stream quality.
@@ -975,11 +1006,11 @@ export class ProtectCamera extends ProtectDevice {
975
1006
  // Find a streaming RTSP configuration for a given target resolution.
976
1007
  findRtsp(width, height, options) {
977
1008
  // Create our options JSON if needed.
978
- options = options ?? {};
1009
+ options ??= {};
979
1010
  // Set our default stream, if we've configured one.
980
1011
  options.default = this.hints.streamingDefault;
981
1012
  // See if we've been given RTSP entries or whether we should default to our own.
982
- options.rtspEntries = options.rtspEntries ?? this.rtspEntries;
1013
+ options.rtspEntries ??= this.rtspEntries;
983
1014
  // If we've imposed a constraint on the maximum dimensions of what we want due to a hardware limitation, filter out those entries.
984
1015
  if (options.maxPixels !== undefined) {
985
1016
  options.rtspEntries = options.rtspEntries.filter(x => (x.channel.width * x.channel.height) <= (options.maxPixels ?? Infinity));
@@ -1025,7 +1056,7 @@ export class ProtectCamera extends ProtectDevice {
1025
1056
  }
1026
1057
  // Utility property to return the current night vision state of a camera. It's a blunt instrument due to HomeKit constraints.
1027
1058
  get nightVision() {
1028
- return this.ufp?.ispSettings?.irLedMode !== "off";
1059
+ return this.ufp.ispSettings.irLedMode !== "off";
1029
1060
  }
1030
1061
  // Utility property to return the current night vision state of a camera, mapped to a brightness characteristic.
1031
1062
  get nightVisionBrightness() {
@@ -1044,5 +1075,34 @@ export class ProtectCamera extends ProtectDevice {
1044
1075
  return 0;
1045
1076
  }
1046
1077
  }
1078
+ // Utility to return our audio filter pipeline for this camera.
1079
+ get audioFilters() {
1080
+ // If we don't have audio filtering enabled, we're done.
1081
+ if (!this.hasFeature("Audio.Filter.Noise")) {
1082
+ return [];
1083
+ }
1084
+ const afOptions = [];
1085
+ // See what the user has set for the afftdn filter for this camera.
1086
+ let fftNr = this.getFeatureFloat("Audio.Filter.Noise.FftNr") ?? PROTECT_FFMPEG_AUDIO_FILTER_FFTNR;
1087
+ // If we have an invalid setting, use the defaults.
1088
+ fftNr = Math.max(0.01, Math.min(97, fftNr));
1089
+ const highpass = this.getFeatureNumber("Audio.Filter.Noise.HighPass");
1090
+ const lowpass = this.getFeatureNumber("Audio.Filter.Noise.LowPass");
1091
+ // We use the following order of operations for our filter: highpass, then lowpass, and finally afftdn.
1092
+ // Only set the highpass and lowpass filters if the user has explicitly enabled them.
1093
+ if (typeof highpass === "number") {
1094
+ afOptions.push("highpass=p=2:f=" + highpass.toString());
1095
+ }
1096
+ if (typeof lowpass === "number") {
1097
+ afOptions.push("lowpass=p=2:f=" + lowpass.toString());
1098
+ }
1099
+ // The afftdn filter options we use are:
1100
+ //
1101
+ // nt=c Use the custom noise profile that we've measured for two seconds at the beginning of our session.
1102
+ // tn=1 Enable noise tracking.
1103
+ // nr=X Noise reduction value in decibels.
1104
+ afOptions.push("asendcmd=c='1.0 afftdn sn start ; 3.0 afftdn sn stop', afftdn=nt=c:tn=1:nr=" + fftNr.toString());
1105
+ return afOptions;
1106
+ }
1047
1107
  }
1048
1108
  //# sourceMappingURL=protect-camera.js.map