homebridge-unifi-protect 6.21.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +29 -29
  2. package/config.schema.json +5 -15
  3. package/dist/devices/protect-camera-package.d.ts +0 -2
  4. package/dist/devices/protect-camera-package.js +4 -12
  5. package/dist/devices/protect-camera-package.js.map +1 -1
  6. package/dist/devices/protect-camera.d.ts +8 -9
  7. package/dist/devices/protect-camera.js +30 -119
  8. package/dist/devices/protect-camera.js.map +1 -1
  9. package/dist/devices/protect-chime.js +2 -6
  10. package/dist/devices/protect-chime.js.map +1 -1
  11. package/dist/devices/protect-device.d.ts +11 -5
  12. package/dist/devices/protect-device.js +17 -20
  13. package/dist/devices/protect-device.js.map +1 -1
  14. package/dist/devices/protect-doorbell.d.ts +0 -2
  15. package/dist/devices/protect-doorbell.js +39 -58
  16. package/dist/devices/protect-doorbell.js.map +1 -1
  17. package/dist/devices/protect-light.js +1 -3
  18. package/dist/devices/protect-light.js.map +1 -1
  19. package/dist/devices/protect-liveviews.js +2 -1
  20. package/dist/devices/protect-liveviews.js.map +1 -1
  21. package/dist/devices/protect-nvr-systeminfo.js +1 -1
  22. package/dist/devices/protect-nvr-systeminfo.js.map +1 -1
  23. package/dist/devices/protect-securitysystem.js +4 -4
  24. package/dist/devices/protect-securitysystem.js.map +1 -1
  25. package/dist/devices/protect-sensor.js +2 -6
  26. package/dist/devices/protect-sensor.js.map +1 -1
  27. package/dist/ffmpeg/protect-ffmpeg-codecs.js.map +1 -1
  28. package/dist/ffmpeg/protect-ffmpeg-exec.js.map +1 -1
  29. package/dist/ffmpeg/protect-ffmpeg-options.js +2 -20
  30. package/dist/ffmpeg/protect-ffmpeg-options.js.map +1 -1
  31. package/dist/ffmpeg/protect-ffmpeg-record.js +2 -1
  32. package/dist/ffmpeg/protect-ffmpeg-record.js.map +1 -1
  33. package/dist/ffmpeg/protect-ffmpeg-stream.js +14 -8
  34. package/dist/ffmpeg/protect-ffmpeg-stream.js.map +1 -1
  35. package/dist/ffmpeg/protect-ffmpeg.d.ts +2 -2
  36. package/dist/ffmpeg/protect-ffmpeg.js.map +1 -1
  37. package/dist/protect-events.d.ts +1 -1
  38. package/dist/protect-events.js +36 -33
  39. package/dist/protect-events.js.map +1 -1
  40. package/dist/protect-nvr.d.ts +7 -11
  41. package/dist/protect-nvr.js +14 -60
  42. package/dist/protect-nvr.js.map +1 -1
  43. package/dist/protect-options.d.ts +8 -23
  44. package/dist/protect-options.js +7 -129
  45. package/dist/protect-options.js.map +1 -1
  46. package/dist/protect-platform.d.ts +2 -4
  47. package/dist/protect-platform.js +3 -28
  48. package/dist/protect-platform.js.map +1 -1
  49. package/dist/protect-record.d.ts +2 -1
  50. package/dist/protect-record.js +21 -27
  51. package/dist/protect-record.js.map +1 -1
  52. package/dist/protect-snapshot.d.ts +2 -2
  53. package/dist/protect-snapshot.js +7 -3
  54. package/dist/protect-snapshot.js.map +1 -1
  55. package/dist/protect-stream.d.ts +3 -3
  56. package/dist/protect-stream.js +102 -93
  57. package/dist/protect-stream.js.map +1 -1
  58. package/dist/protect-timeshift.d.ts +9 -3
  59. package/dist/protect-timeshift.js +76 -24
  60. package/dist/protect-timeshift.js.map +1 -1
  61. package/dist/protect-types.d.ts +0 -7
  62. package/dist/protect-types.js +0 -1
  63. package/dist/protect-types.js.map +1 -1
  64. package/dist/settings.d.ts +4 -1
  65. package/dist/settings.js +8 -2
  66. package/dist/settings.js.map +1 -1
  67. package/homebridge-ui/public/index.html +43 -22
  68. package/homebridge-ui/public/lib/featureoptions.js +376 -0
  69. package/homebridge-ui/public/lib/featureoptions.js.map +1 -0
  70. package/homebridge-ui/public/lib/webUi-featureoptions.mjs +836 -0
  71. package/homebridge-ui/public/lib/webUi.mjs +184 -0
  72. package/homebridge-ui/public/ui.mjs +208 -124
  73. package/homebridge-ui/server.js +13 -39
  74. package/package.json +22 -21
  75. package/dist/protect-mqtt.d.ts +0 -20
  76. package/dist/protect-mqtt.js +0 -177
  77. package/dist/protect-mqtt.js.map +0 -1
  78. package/dist/protect-rtp.d.ts +0 -26
  79. package/dist/protect-rtp.js +0 -180
  80. package/dist/protect-rtp.js.map +0 -1
  81. package/homebridge-ui/public/lib/featureoptions.mjs +0 -201
  82. package/homebridge-ui/public/protect-featureoptions.mjs +0 -736
package/README.md CHANGED
@@ -75,35 +75,35 @@ I hope to continue to work on this one to get AEC working for two-way audio. [Yo
75
75
  * [Plugin Configuration Reference](https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/ConfigurationReference.md): complete list of configuration options available in this plugin.
76
76
 
77
77
  ## Installation
78
- ### Prerequisites:
79
78
 
80
- * Ensure you are using a machine that can handle the CPU and GPU requirements of `homebridge-unifi-protect`. The more cameras you have, the higher the performance requirements. If you intend to use HomeKit Secure Video, in particular, you will need a capable, modern CPU. Raspberry Pi 4 is a great piece of hardware, but it cannot keep up with the demands of more than a few Protect cameras, and definitely not the higher end members of the Protect camera ecosystem.
81
- * If you are new to Homebridge, please first read the [Homebridge](https://homebridge.io) [documentation](https://github.com/homebridge/homebridge/wiki) and installation instructions before proceeding. Ensure you've installed Homebridge and the [Homebridge Config UI](https://github.com/homebridge/homebridge-config-ui-x) before proceeding.
82
- * Ensure you have a ***local user*** account on your UniFi console dedicated to `homebridge-unifi-protect`. To create a local user account on your UniFi console:
83
- * Go to the ***OS Settings*** tab on the Protect controller web interface. This is typicaly near the top left of the Protect controller UI page.
84
- * Click ***Add Admin*** located near the top right of the ***OS Settings*** page.
85
- * Click ***Restrict to local access only*** and then enter in a username and password for the new local user.
86
- * Optionally customize the role of the user to adjust the roles. HBUP requires the ***Full Management*** role for all of it's capabilities to work, although it will work in a more limited form without administrative privileges.
87
-
88
- ### Getting Started
89
- To install `homebridge-unifi-protect`:
90
-
91
- 1. Go to the `Plugins` tab in the Homebridge Config UI and searching for `homebridge-unifi-protect` and install it.
92
- 2. Click on the ***Set Up*** icon located in the top right corner of the Homebridge UniFi Protect tile and then enter the hostname or IP address of the Protect controller as well as the username and password you created in the steps above and then login to the Protect controller.
93
- 3. For the moment, don't make any other configuration changes and click ***Save*** and then click ***Restart Homebridge***.
94
- 4. After restarting Homebridge, click on the ***Set Up Child Bridge*** icon located in the top right corner of the Homebridge UniFi Protect tile. Toggle the child bridge setting for UniFi Protect to ***on*** and then save and restart Homebridge.
95
- 5. After restarting Homebridge, click on the ***Connect to HomeKit*** icon located in the top right corner of the Homebridge UniFi Protect tile. Use the Home app on your iPhone and scan the QR code to connect UniFi Protect to HomeKit. The Home app may ask questions about where to locate your cameras and whether you want to enable HomeKit Secure Video. Answer according to your preferences.
96
- 6. That's it! You should now be able to access all your UniFi Protect devices in HomeKit. You can further tailor your experience by going to the Homebridge UniFi Protect webUI and exploring the various features and options that are available to you.
97
-
98
- ### Technical Considerations
99
-
100
- HBUP includes everything required to get up and running on many of the [more popular platforms and operating systems](https://github.com/homebridge/ffmpeg-for-homebridge#supported-platforms). **If you're running on an unsupported platform, you will need to install a working version of *FFmpeg* for `homebridge-unifi-protect` to work correctly with your cameras. Additionally, your FFmpeg will need to support the *fdk-aac* codec if you want audio support to work. Setting up and configuring FFmpeg is beyond the scope of this documentation.**
101
-
102
- ### Things To Be Aware Of
103
- - Only official releases of UniFi Protect and UniFi OS firmwares are supported. **No beta, early access, or release candidate versions of any kind are supported**.
104
- - Only official hardware releases for UniFi Protect are supported. Early access or beta hardware is unsupported.
105
- - No support is provided for any beta versions of Apple operating systems (iOS, iPadOS, macOS, tvOS, etc.).
106
- - **My philosophy is to aggressively adopt the capability and features (that make sense in a HomeKit context) in the latest official Ubiquiti firmware releases and to deprecate old functionality that's been superceded by newer, richer, or more performant capabilities - either by HomeKit or Ubiquiti. Read the [Changelog](https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/Changelog.md) carefully for the latest information on what's new.**
79
+ > [!IMPORTANT]
80
+ > ### Prerequisites
81
+ > * Ensure you are using a machine that can handle the CPU and GPU requirements of `homebridge-unifi-protect`. The more cameras you have, the higher the performance requirements. If you intend to use HomeKit Secure Video, in particular, you will need a capable, modern CPU. Raspberry Pi 4 is a great piece of hardware, but it cannot keep up with the demands of more than a few Protect cameras, and definitely not the higher end members of the Protect camera ecosystem.
82
+ > * If you are new to Homebridge, please first read the [Homebridge](https://homebridge.io) [documentation](https://github.com/homebridge/homebridge/wiki) and installation instructions before proceeding. Ensure you've installed Homebridge and the [Homebridge Config UI](https://github.com/homebridge/homebridge-config-ui-x) before proceeding.
83
+ > * Ensure you have a ***local user*** account on your UniFi console dedicated to `homebridge-unifi-protect`. To create a local user account on your UniFi console:
84
+ > * Go to the ***OS Settings*** tab on the Protect controller web interface. This is typicaly near the top left of the Protect controller UI page.
85
+ > * Click ***Add Admin*** located near the top right of the ***OS Settings*** page.
86
+ > * Click ***Restrict to local access only*** and then enter in a username and password for the new local user.
87
+ > * Optionally customize the role of the user to adjust the roles. HBUP requires the ***Full Management*** role for all of it's capabilities to work, although it will work in a more limited form without administrative privileges.
88
+ >
89
+ > ### Getting Started
90
+ > To install `homebridge-unifi-protect`:
91
+ >
92
+ > 1. Go to the `Plugins` tab in the Homebridge Config UI and searching for `homebridge-unifi-protect` and install it.
93
+ > 2. Click on the ***Set Up*** icon located in the top right corner of the Homebridge UniFi Protect tile and then enter the hostname or IP address of the Protect controller as well as the username and password you created in the steps above and then login to the Protect controller.
94
+ > 3. For the moment, don't make any other configuration changes and click ***Save*** and then click ***Restart Homebridge***.
95
+ > 4. After restarting Homebridge, click on the ***Set Up Child Bridge*** icon located in the top right corner of the Homebridge UniFi Protect tile. Toggle the child bridge setting for UniFi Protect to ***on*** and then save and restart Homebridge.
96
+ > 5. After restarting Homebridge, click on the ***Connect to HomeKit*** icon located in the top right corner of the Homebridge UniFi Protect tile. Use the Home app on your iPhone and scan the QR code to connect UniFi Protect to HomeKit. The Home app may ask questions about where to locate your cameras and whether you want to enable HomeKit Secure Video. Answer according to your preferences.
97
+ > 6. That's it! You should now be able to access all your UniFi Protect devices in HomeKit. You can further tailor your experience by going to the Homebridge UniFi Protect webUI and exploring the various features and options that are available to you.
98
+
99
+ > [!NOTE]
100
+ > HBUP includes everything required to get up and running on many of the [more popular platforms and operating systems](https://github.com/homebridge/ffmpeg-for-homebridge#supported-platforms). **If you're running on an unsupported platform, you will need to install a working version of *FFmpeg* for `homebridge-unifi-protect` to work correctly with your cameras. Additionally, your FFmpeg will need to support the *fdk-aac* codec if you want audio support to work. Setting up and configuring FFmpeg is beyond the scope of this documentation.**
101
+
102
+ > [!TIP]
103
+ > - Only official releases of UniFi Protect and UniFi OS firmwares are supported. **No beta, early access, or release candidate versions of any kind are supported**.
104
+ > - Only official hardware releases for UniFi Protect are supported. Early access or beta hardware is unsupported.
105
+ > - No support is provided for any beta versions of Apple operating systems (iOS, iPadOS, macOS, tvOS, etc.).
106
+ > - **My philosophy is to aggressively adopt the capability and features (that make sense in a HomeKit context) in the latest official Ubiquiti firmware releases and to deprecate old functionality that's been superceded by newer, richer, or more performant capabilities - either by HomeKit or Ubiquiti. Read the [Changelog](https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/Changelog.md) carefully for the latest information on what's new.**
107
107
 
108
108
  ## Plugin Development Dashboard
109
109
  This is mostly of interest to the true developer nerds amongst us.
@@ -111,4 +111,4 @@ This is mostly of interest to the true developer nerds amongst us.
111
111
  [![License](https://img.shields.io/npm/l/homebridge-unifi-protect?color=%230559C9&logo=open%20source%20initiative&logoColor=%23FFFFFF&style=for-the-badge)](https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/LICENSE.md)
112
112
  [![Build Status](https://img.shields.io/github/actions/workflow/status/hjdhjd/homebridge-unifi-protect/ci.yml?branch=main&color=%230559C9&logo=github-actions&logoColor=%23FFFFFF&style=for-the-badge)](https://github.com/hjdhjd/homebridge-unifi-protect/actions?query=workflow%3A%22Continuous+Integration%22)
113
113
  [![Dependencies](https://img.shields.io/librariesio/release/npm/homebridge-unifi-protect?color=%230559C9&logo=dependabot&style=for-the-badge)](https://libraries.io/npm/homebridge-unifi-protect)
114
- [![GitHub commits since latest release (by SemVer)](https://img.shields.io/github/commits-since/hjdhjd/homebridge-unifi-protect/latest?color=%230559C9&logo=github&sort=semver&style=for-the-badge)](https://github.com/hjdhjd/homebridge-unifi-protect/commits/master)
114
+ [![GitHub commits since latest release (by SemVer)](https://img.shields.io/github/commits-since/hjdhjd/homebridge-unifi-protect/latest?color=%230559C9&logo=github&sort=semver&style=for-the-badge)](https://github.com/hjdhjd/homebridge-unifi-protect/commits/main)
@@ -2,7 +2,7 @@
2
2
  "pluginAlias": "UniFi Protect",
3
3
  "pluginType": "platform",
4
4
  "headerDisplay": "Full HomeKit support UniFi Protect devices. See the [homebridge-unifi-protect](https://github.com/hjdhjd/homebridge-unifi-protect) developer page for detailed documentation.",
5
- "footerDisplay": "A working **ffmpeg** installation is required for this plugin to work. For audio support, make sure your version of ffmpeg is compiled with support for **fdk-aac**.",
5
+ "footerDisplay": "A working **FFmpeg** installation is required for this plugin to work. For audio support, make sure your version of ffmpeg is compiled with support for the **fdk-aac** codec.",
6
6
  "singular": true,
7
7
  "customUi": true,
8
8
 
@@ -28,15 +28,6 @@
28
28
  "description": "Hostname or IP address of your UniFi Protect controller."
29
29
  },
30
30
 
31
- "defaultDoorbellMessage": {
32
- "type": "string",
33
- "title": "Default doorbell message",
34
- "required": false,
35
- "maxLength": 30,
36
- "placeholder": "e.g. WELCOME",
37
- "description": "Default message to be used on UniFi Protect doorbells. Default: WELCOME."
38
- },
39
-
40
31
  "doorbellMessages": {
41
32
  "type": "array",
42
33
  "title": "Doorbell Messages",
@@ -138,8 +129,8 @@
138
129
  "type": "string",
139
130
  "title": "Feature Option",
140
131
  "required": false,
141
- "description": "Enter only one option per entry. See the plugin documentation for the complete list of available options or use the feature options webUI tab above.",
142
- "placeholder": "e.g. Disable.Video.Transcode"
132
+ "description": "Enter only one option per entry. Use the feature options webUI tab above unless you know what you're doing.",
133
+ "placeholder": "e.g. Disable.Device"
143
134
  }
144
135
  },
145
136
 
@@ -210,7 +201,6 @@
210
201
  "expanded": false,
211
202
  "items": [
212
203
 
213
- "controllers[].defaultDoorbellMessage",
214
204
  {
215
205
  "key": "controllers[].doorbellMessages",
216
206
  "type": "array",
@@ -273,8 +263,8 @@
273
263
  "key": "options",
274
264
  "type": "array",
275
265
  "name": " ",
276
- "description": "Feature options allow you to further customize the behavior of this plugin such as the ability to show or hide cameras or specify stream quality. You can use the the feature options tab above (recommended) to customize these settings or enter them manually below.",
277
- "orderable": false,
266
+ "description": "Use the feature options webUI tab above instead of manually configuring feature options here.",
267
+ "orderable": true,
278
268
  "buttonText": "Add Feature Option",
279
269
  "items": [
280
270
  "options[]"
@@ -4,6 +4,4 @@ export declare class ProtectCameraPackage extends ProtectCamera {
4
4
  get id(): string;
5
5
  findRtsp(): RtspEntry | null;
6
6
  findRecordingRtsp(): RtspEntry | null;
7
- getBitrate(channelId: number): number;
8
- setBitrate(): Promise<boolean>;
9
7
  }
@@ -13,10 +13,12 @@ export class ProtectCameraPackage extends ProtectCamera {
13
13
  this.hasHksv = true;
14
14
  this.hints.probesize = 32768;
15
15
  if (parentCamera) {
16
- this.hints.timeshift = parentCamera.hints.timeshift;
16
+ this.hints.apiStreaming = parentCamera.hints.apiStreaming;
17
17
  this.hints.hardwareDecoding = parentCamera.hints.hardwareDecoding;
18
- this.hints.hardwareTranscoding = false;
18
+ this.hints.hardwareTranscoding = parentCamera.hints.hardwareTranscoding;
19
+ this.hints.highResSnapshots = parentCamera.hints.highResSnapshots;
19
20
  this.hints.logHksv = parentCamera.hints.logHksv;
21
+ this.hints.timeshift = parentCamera.hints.timeshift;
20
22
  }
21
23
  // Clean out the context object in case it's been polluted somehow.
22
24
  this.accessory.context = {};
@@ -102,15 +104,5 @@ export class ProtectCameraPackage extends ProtectCamera {
102
104
  findRecordingRtsp() {
103
105
  return this.findRtsp();
104
106
  }
105
- // Get the current bitrate for a specific camera channel.
106
- getBitrate(channelId) {
107
- // Find the right channel.
108
- const channel = this.ufp.channels.find(x => x.id === channelId);
109
- return channel?.bitrate ?? -1;
110
- }
111
- // Set the bitrate for a specific camera channel.
112
- setBitrate() {
113
- return Promise.resolve(true);
114
- }
115
107
  }
116
108
  //# sourceMappingURL=protect-camera-package.js.map
@@ -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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"}
@@ -10,6 +10,12 @@ export interface RtspEntry {
10
10
  resolution: Resolution;
11
11
  url: string;
12
12
  }
13
+ type RtspOptions = Partial<{
14
+ biasHigher: boolean;
15
+ default: string;
16
+ maxPixels: number;
17
+ rtspEntries: RtspEntry[];
18
+ }>;
13
19
  export declare class ProtectCamera extends ProtectDevice {
14
20
  hasHksv: boolean;
15
21
  private isDeleted;
@@ -33,20 +39,13 @@ export declare class ProtectCamera extends ProtectDevice {
33
39
  private configureVideoStream;
34
40
  private configureHksv;
35
41
  private configureHksvRecordingSwitch;
36
- private configureDynamicBitrateSwitch;
37
42
  private configureNvrRecordingSwitch;
38
43
  protected configureMqtt(): boolean;
39
44
  updateDevice(): boolean;
40
- getBitrate(channelId: number): number;
41
- setBitrate(channelId: number, value: number): Promise<boolean>;
42
45
  private findRtspEntry;
43
- findRtsp(width: number, height: number, options?: {
44
- biasHigher?: boolean;
45
- default?: string;
46
- maxPixels?: number;
47
- rtspEntries?: RtspEntry[];
48
- }): RtspEntry | null;
46
+ findRtsp(width: number, height: number, options?: RtspOptions): RtspEntry | null;
49
47
  findRecordingRtsp(width: number, height: number): RtspEntry | null;
50
48
  private sortByResolutions;
51
49
  protected getResolution(resolution: Resolution): string;
52
50
  }
51
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { ProtectReservedNames, toCamelCase } from "../protect-types.js";
2
- import { PROTECT_HOMEKIT_IDR_INTERVAL } from "../settings.js";
2
+ import { PROTECT_HKSV_IDR_INTERVAL } from "../settings.js";
3
3
  import { ProtectDevice } from "./protect-device.js";
4
4
  import { ProtectStreamingDelegate } from "../protect-stream.js";
5
5
  export class ProtectCamera extends ProtectDevice {
@@ -28,6 +28,7 @@ export class ProtectCamera extends ProtectDevice {
28
28
  configureHints() {
29
29
  // Configure our parent's hints.
30
30
  super.configureHints();
31
+ this.hints.apiStreaming = this.hasFeature("Video.Stream.UseApi");
31
32
  this.hints.crop = this.hasFeature("Video.Crop");
32
33
  this.hints.hardwareDecoding = true;
33
34
  this.hints.hardwareTranscoding = this.hasFeature("Video.Transcode.Hardware");
@@ -39,8 +40,17 @@ export class ProtectCamera extends ProtectDevice {
39
40
  this.hints.smartDetect = this.ufp.featureFlags.hasSmartDetect && this.hasFeature("Motion.SmartDetect");
40
41
  this.hints.timeshift = this.hasFeature("Video.HKSV.TimeshiftBuffer");
41
42
  this.hints.transcode = this.hasFeature("Video.Transcode");
43
+ this.hints.transcodeBitrate = this.getFeatureNumber("Video.Transcode.Bitrate");
42
44
  this.hints.transcodeHighLatency = this.hasFeature("Video.Transcode.HighLatency");
45
+ this.hints.transcodeHighLatencyBitrate = this.getFeatureNumber("Video.Transcode.HighLatency.Bitrate");
43
46
  this.hints.twoWayAudio = this.ufp.featureFlags.hasSpeaker && this.hasFeature("Audio") && this.hasFeature("Audio.TwoWay");
47
+ // Sanity check our target transcoding bitrates, if defined.
48
+ if ((this.hints.transcodeBitrate === undefined) || (this.hints.transcodeBitrate <= 0)) {
49
+ this.hints.transcodeBitrate = -1;
50
+ }
51
+ if ((this.hints.transcodeHighLatencyBitrate === undefined) || (this.hints.transcodeHighLatencyBitrate <= 0)) {
52
+ this.hints.transcodeHighLatencyBitrate = -1;
53
+ }
44
54
  return true;
45
55
  }
46
56
  // Configure a camera accessory for HomeKit.
@@ -50,17 +60,12 @@ export class ProtectCamera extends ProtectDevice {
50
60
  // Clean out the context object in case it's been polluted somehow.
51
61
  this.accessory.context = {};
52
62
  this.accessory.context.detectMotion = savedContext.detectMotion ?? true;
53
- this.accessory.context.dynamicBitrate = savedContext.dynamicBitrate ?? false;
54
63
  this.accessory.context.hksvRecording = savedContext.hksvRecording ?? true;
55
64
  this.accessory.context.mac = this.ufp.mac;
56
65
  this.accessory.context.nvr = this.nvr.ufp.mac;
57
66
  // Inform the user that motion detection will suck.
58
67
  if (this.ufp.recordingSettings.mode === "never") {
59
- this.log.info("WARNING: motion events will not be generated by the Protect controller when the controller's camera recording options are set to \"never\".");
60
- }
61
- // Inform the user if we have enabled the dynamic bitrate setting.
62
- if (this.hasFeature("Video.DynamicBitrate")) {
63
- this.log.info("Dynamic streaming bitrate adjustment on the UniFi Protect controller enabled.");
68
+ this.log.warn("Motion events will not be generated by the Protect controller when the controller's camera recording options are set to \"never\".");
64
69
  }
65
70
  // Check to see if we have smart motion events enabled on a supported camera.
66
71
  if (this.hints.smartDetect) {
@@ -72,6 +77,9 @@ export class ProtectCamera extends ProtectDevice {
72
77
  this.log.info("Smart motion detection enabled%s.", this.ufp.featureFlags.smartDetectTypes.length ?
73
78
  ": " + this.ufp.featureFlags.smartDetectTypes.sort().join(", ") : "");
74
79
  }
80
+ if (this.hints.apiStreaming) {
81
+ this.log.warn("API streaming enabled. This feature is experimental and provided without support. Any related support requests will be closed without comment.");
82
+ }
75
83
  // Configure accessory information.
76
84
  this.configureInfo();
77
85
  // Configure MQTT services.
@@ -91,8 +99,6 @@ export class ProtectCamera extends ProtectDevice {
91
99
  await this.configureVideoStream();
92
100
  // Configure our camera details.
93
101
  this.configureCameraDetails();
94
- // Configure our bitrate switch.
95
- this.configureDynamicBitrateSwitch();
96
102
  // Configure our NVR recording switches.
97
103
  this.configureNvrRecordingSwitch();
98
104
  // Configure the doorbell trigger.
@@ -268,9 +274,7 @@ export class ProtectCamera extends ProtectDevice {
268
274
  else {
269
275
  // If the doorbell ring event is still going, we should be as well.
270
276
  if (this.isRinging) {
271
- setTimeout(() => {
272
- triggerService?.updateCharacteristic(this.hap.Characteristic.On, true);
273
- }, 50);
277
+ setTimeout(() => triggerService?.updateCharacteristic(this.hap.Characteristic.On, true), 50);
274
278
  }
275
279
  }
276
280
  });
@@ -370,12 +374,12 @@ export class ProtectCamera extends ProtectDevice {
370
374
  // Enable RTSP on the camera if needed and get the list of RTSP streams we have ultimately configured.
371
375
  this.ufp = await this.nvr.ufpApi.enableRtsp(this.ufp) ?? this.ufp;
372
376
  // Figure out which camera channels are RTSP-enabled, and user-enabled.
373
- let cameraChannels = this.ufp.channels.filter(x => x.isRtspEnabled && this.hasFeature("Video.Stream." + x.name, true));
377
+ let cameraChannels = this.ufp.channels.filter(x => x.isRtspEnabled);
374
378
  // Make sure we've got a HomeKit compatible IDR frame interval. If not, let's take care of that.
375
- const idrChannels = cameraChannels.filter(x => x.idrInterval !== PROTECT_HOMEKIT_IDR_INTERVAL);
379
+ const idrChannels = cameraChannels.filter(x => x.idrInterval !== PROTECT_HKSV_IDR_INTERVAL);
376
380
  if (idrChannels.length) {
377
381
  // Edit the channel map and update the Protect controller.
378
- this.ufp = await this.nvr.ufpApi.updateDevice(this.ufp, { channels: idrChannels.map(x => Object.assign(x, { idrInterval: PROTECT_HOMEKIT_IDR_INTERVAL })) }) ??
382
+ this.ufp = await this.nvr.ufpApi.updateDevice(this.ufp, { channels: idrChannels.map(x => Object.assign(x, { idrInterval: PROTECT_HKSV_IDR_INTERVAL })) }) ??
379
383
  this.ufp;
380
384
  }
381
385
  // Set the camera and shapshot URLs.
@@ -384,9 +388,8 @@ export class ProtectCamera extends ProtectDevice {
384
388
  cameraChannels = cameraChannels.filter(x => x.name !== "Package Camera");
385
389
  // No RTSP streams are available that meet our criteria - we're done.
386
390
  if (!cameraChannels.length) {
387
- this.log.info("No RTSP stream profiles have been configured for this camera. " +
388
- "Enable at least one RTSP stream profile in the UniFi Protect webUI to resolve this issue or " +
389
- "assign the Administrator role to the user configured for this plugin to allow it to automatically configure itself.");
391
+ this.log.info("No RTSP streaming profiles have been configured for this camera. You can resolve this issue by either enabling at least one RTSP profile in the " +
392
+ "UniFi Protect webUI or assigning an admin role to the local Protect user account you configured for this plugin.");
390
393
  return false;
391
394
  }
392
395
  // Now that we have our RTSP streams, create a list of supported resolutions for HomeKit.
@@ -485,24 +488,24 @@ export class ProtectCamera extends ProtectDevice {
485
488
  for (const rtspProfile of ["LOW", "MEDIUM", "HIGH"]) {
486
489
  // Check to see if the user has requested a specific streaming profile for this camera.
487
490
  if (this.hasFeature("Video.Stream.Only." + rtspProfile)) {
488
- this.rtspQuality.streamingDefault = rtspProfile;
491
+ this.hints.streamingDefault = rtspProfile;
489
492
  }
490
493
  // Check to see if the user has requested a specific recording profile for this camera.
491
494
  if (this.hasFeature("Video.HKSV.Record.Only." + rtspProfile)) {
492
- this.rtspQuality.recordingDefault = rtspProfile;
495
+ this.hints.recordingDefault = rtspProfile;
493
496
  }
494
497
  }
495
498
  // Inform the user if we've set a streaming default.
496
- if (this.rtspQuality.streamingDefault) {
497
- this.log.info("Video streaming configured to use only: %s.", toCamelCase(this.rtspQuality.streamingDefault.toLowerCase()));
499
+ if (this.hints.streamingDefault) {
500
+ this.log.info("Video streaming configured to use only: %s.", toCamelCase(this.hints.streamingDefault.toLowerCase()));
498
501
  }
499
502
  // Inform the user if they've selected the legacy snapshot API.
500
503
  if (!this.hints.highResSnapshots) {
501
504
  this.log.info("Disabling the use of higher quality snapshots.");
502
505
  }
503
506
  // Inform the user if we've set a recording default.
504
- if (this.rtspQuality.recordingDefault) {
505
- this.log.info("HomeKit Secure Video event recording configured to use only: %s.", toCamelCase(this.rtspQuality.recordingDefault.toLowerCase()));
507
+ if (this.hints.recordingDefault) {
508
+ this.log.info("HomeKit Secure Video event recording configured to use only: %s.", toCamelCase(this.hints.recordingDefault.toLowerCase()));
506
509
  }
507
510
  // Configure the video stream with our resolutions.
508
511
  this.stream = new ProtectStreamingDelegate(this, this.rtspEntries.map(x => x.resolution));
@@ -557,60 +560,6 @@ export class ProtectCamera extends ProtectDevice {
557
560
  this.log.info("Enabling HKSV recording switch.");
558
561
  return true;
559
562
  }
560
- // Configure a switch to manually enable or disable dynamic bitrate capabilities for a camera.
561
- configureDynamicBitrateSwitch() {
562
- // Validate whether we should have this service enabled.
563
- if (!this.validService(this.hap.Service.Switch, () => {
564
- // If we don't want a dynamic bitrate switch, disable it and we're done.
565
- if (!this.hasFeature("Video.DynamicBitrate.Switch")) {
566
- return false;
567
- }
568
- return true;
569
- }, ProtectReservedNames.SWITCH_DYNAMIC_BITRATE)) {
570
- // We want to default this back to off by default whenever we disable the dynamic bitrate switch.
571
- this.accessory.context.dynamicBitrate = false;
572
- return false;
573
- }
574
- // Acquire the service.
575
- const service = this.acquireService(this.hap.Service.Switch, this.accessoryName + " Dynamic Bitrate", ProtectReservedNames.SWITCH_DYNAMIC_BITRATE);
576
- // Fail gracefully.
577
- if (!service) {
578
- this.log.error("Unable to add dynamic bitrate switch.");
579
- return false;
580
- }
581
- // Activate or deactivate dynamic bitrate for this device.
582
- service.getCharacteristic(this.hap.Characteristic.On)?.onGet(() => {
583
- return this.accessory.context.dynamicBitrate ?? false;
584
- });
585
- service.getCharacteristic(this.hap.Characteristic.On)?.onSet(async (value) => {
586
- if (this.accessory.context.dynamicBitrate === value) {
587
- return;
588
- }
589
- // We're enabling dynamic bitrate for this device.
590
- if (value) {
591
- this.accessory.context.dynamicBitrate = true;
592
- this.log.info("Dynamic streaming bitrate adjustment on the UniFi Protect controller enabled.");
593
- return;
594
- }
595
- // We're disabling dynamic bitrate for this device. Update the channels JSON to revert to the maximum bitrate we can.
596
- const updatedChannels = this.ufp.channels.map(channel => ({ ...channel, bitrate: channel.maxBitrate }));
597
- // Send the channels JSON to Protect.
598
- const newDevice = await this.nvr.ufpApi.updateDevice(this.ufp, { channels: updatedChannels });
599
- // We failed.
600
- if (!newDevice) {
601
- this.log.error("Unable to set the streaming bitrate to %s.", value);
602
- }
603
- else {
604
- this.ufp = newDevice;
605
- }
606
- this.accessory.context.dynamicBitrate = false;
607
- this.log.info("Dynamic streaming bitrate adjustment on the UniFi Protect controller disabled.");
608
- });
609
- // Initialize the switch.
610
- service.updateCharacteristic(this.hap.Characteristic.On, this.accessory.context.dynamicBitrate);
611
- this.log.info("Enabling the dynamic streaming bitrate adjustment switch.");
612
- return true;
613
- }
614
563
  // Configure a series of switches to manually enable or disable recording on the UniFi Protect controller for a camera.
615
564
  configureNvrRecordingSwitch() {
616
565
  const switchesEnabled = [];
@@ -643,9 +592,7 @@ export class ProtectCamera extends ProtectDevice {
643
592
  // 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
644
593
  // settings one can choose from. Instead, we do nothing and leave it to the user to choose what state they really want to set.
645
594
  if (!value) {
646
- setTimeout(() => {
647
- this.updateDevice();
648
- }, 50);
595
+ setTimeout(() => this.updateDevice(), 50);
649
596
  return;
650
597
  }
651
598
  // Set our recording mode.
@@ -729,42 +676,6 @@ export class ProtectCamera extends ProtectDevice {
729
676
  }
730
677
  return true;
731
678
  }
732
- // Get the current bitrate for a specific camera channel.
733
- getBitrate(channelId) {
734
- // Find the right channel.
735
- const channel = this.ufp.channels.find(x => x.id === channelId);
736
- return channel?.bitrate ?? -1;
737
- }
738
- // Set the bitrate for a specific camera channel.
739
- async setBitrate(channelId, value) {
740
- // If we've disabled the ability to set the bitrate dynamically, silently fail. We prioritize switches over the global setting here, in case the user enabled both,
741
- // using the principle that the most specific setting always wins. If the user has both the global setting and the switch enabled, the switch will take precedence.
742
- if ((!this.accessory.context.dynamicBitrate && !this.hasFeature("Video.DynamicBitrate")) ||
743
- (!this.accessory.context.dynamicBitrate && this.hasFeature("Video.DynamicBitrate") && this.hasFeature("Video.DynamicBitrate.Switch"))) {
744
- return true;
745
- }
746
- // Find the right channel.
747
- const channel = this.ufp.channels.find(x => x.id === channelId);
748
- // No channel, we're done.
749
- if (!channel) {
750
- return false;
751
- }
752
- // If our correct bitrate is already set, we're done.
753
- if (channel.bitrate === value) {
754
- return true;
755
- }
756
- // Make sure the requested bitrate fits within the constraints of what this channel can do.
757
- channel.bitrate = Math.min(channel.maxBitrate, Math.max(channel.minBitrate, value));
758
- // Tell Protect about it.
759
- const newDevice = await this.nvr.ufpApi.updateDevice(this.ufp, { channels: this.ufp.channels });
760
- if (!newDevice) {
761
- this.log.error("Unable to set the streaming bitrate to %s.", value);
762
- return false;
763
- }
764
- // Save our updated device context.
765
- this.ufp = newDevice;
766
- return true;
767
- }
768
679
  // Find an RTSP configuration for a given target resolution.
769
680
  findRtspEntry(width, height, options) {
770
681
  const rtspEntries = options?.rtspEntries ?? this.rtspEntries;
@@ -795,7 +706,7 @@ export class ProtectCamera extends ProtectDevice {
795
706
  // Create our options JSON if needed.
796
707
  options = options ?? {};
797
708
  // Set our default stream, if we've configured one.
798
- options.default = this.rtspQuality.streamingDefault;
709
+ options.default = this.hints.streamingDefault;
799
710
  // See if we've been given RTSP entries or whether we should default to our own.
800
711
  options.rtspEntries = options.rtspEntries ?? this.rtspEntries;
801
712
  // If we've imposed a constraint on the maximum dimensions of what we want due to a hardware limitation, filter out those entries.
@@ -807,7 +718,7 @@ export class ProtectCamera extends ProtectDevice {
807
718
  }
808
719
  // Find a recording RTSP configuration for a given target resolution.
809
720
  findRecordingRtsp(width, height) {
810
- return this.findRtspEntry(width, height, { biasHigher: true, default: this.rtspQuality.recordingDefault ?? this.stream.ffmpegOptions.recordingDefaultChannel });
721
+ return this.findRtspEntry(width, height, { biasHigher: true, default: this.hints.recordingDefault ?? this.stream.ffmpegOptions.recordingDefaultChannel });
811
722
  }
812
723
  // Utility function for sorting by resolution.
813
724
  sortByResolutions(a, b) {