homebridge-unifi-protect 6.8.1 → 6.9.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 (51) hide show
  1. package/config.schema.json +0 -24
  2. package/dist/protect-camera-package.d.ts +9 -0
  3. package/dist/protect-camera-package.js +120 -0
  4. package/dist/protect-camera-package.js.map +1 -0
  5. package/dist/protect-camera.d.ts +5 -12
  6. package/dist/protect-camera.js +43 -134
  7. package/dist/protect-camera.js.map +1 -1
  8. package/dist/protect-device.d.ts +7 -1
  9. package/dist/protect-device.js +56 -5
  10. package/dist/protect-device.js.map +1 -1
  11. package/dist/protect-doorbell.d.ts +4 -0
  12. package/dist/protect-doorbell.js +54 -0
  13. package/dist/protect-doorbell.js.map +1 -1
  14. package/dist/protect-ffmpeg-codecs.js +5 -4
  15. package/dist/protect-ffmpeg-codecs.js.map +1 -1
  16. package/dist/protect-ffmpeg-options.d.ts +2 -2
  17. package/dist/protect-ffmpeg-options.js +199 -149
  18. package/dist/protect-ffmpeg-options.js.map +1 -1
  19. package/dist/protect-ffmpeg-record.js +1 -1
  20. package/dist/protect-ffmpeg-record.js.map +1 -1
  21. package/dist/protect-ffmpeg.d.ts +3 -3
  22. package/dist/protect-ffmpeg.js.map +1 -1
  23. package/dist/protect-nvr-events.js +28 -29
  24. package/dist/protect-nvr-events.js.map +1 -1
  25. package/dist/protect-nvr-systeminfo.js +1 -1
  26. package/dist/protect-nvr-systeminfo.js.map +1 -1
  27. package/dist/protect-nvr.d.ts +2 -3
  28. package/dist/protect-nvr.js +22 -101
  29. package/dist/protect-nvr.js.map +1 -1
  30. package/dist/protect-options.d.ts +4 -3
  31. package/dist/protect-options.js +84 -86
  32. package/dist/protect-options.js.map +1 -1
  33. package/dist/protect-platform.js +3 -13
  34. package/dist/protect-platform.js.map +1 -1
  35. package/dist/protect-record.js +7 -6
  36. package/dist/protect-record.js.map +1 -1
  37. package/dist/protect-sensor.d.ts +6 -3
  38. package/dist/protect-sensor.js +65 -13
  39. package/dist/protect-sensor.js.map +1 -1
  40. package/dist/protect-stream.d.ts +2 -2
  41. package/dist/protect-stream.js +18 -27
  42. package/dist/protect-stream.js.map +1 -1
  43. package/dist/protect-timeshift.d.ts +1 -1
  44. package/dist/protect-timeshift.js +2 -2
  45. package/dist/protect-timeshift.js.map +1 -1
  46. package/dist/protect-viewer.d.ts +2 -1
  47. package/dist/protect-viewer.js +12 -0
  48. package/dist/protect-viewer.js.map +1 -1
  49. package/homebridge-ui/public/index.html +235 -39
  50. package/homebridge-ui/server.js +2 -2
  51. package/package.json +7 -7
@@ -178,6 +178,10 @@
178
178
  // Retrieve the current plugin configuration.
179
179
  let currentConfig = await homebridge.getPluginConfig();
180
180
 
181
+ // Keep a list of all the feature options and option groups.
182
+ let featureOptionList = {};
183
+ let featureOptionGroups = {};
184
+
181
185
  // Show an navigation bar at the top of the plugin configuration UI.
182
186
  const showIntro = () => {
183
187
 
@@ -321,7 +325,6 @@
321
325
  controllersTable.appendChild(trDevice);
322
326
 
323
327
  controllerList.push(label);
324
-
325
328
  }
326
329
 
327
330
  // All done. Let the user interact with us.
@@ -454,32 +457,32 @@
454
457
  };
455
458
 
456
459
  // Initialize our feature option configuration.
457
- updateConfigOptions(currentConfig[0].options ?? [])
460
+ updateConfigOptions(currentConfig[0].options ?? []);
458
461
 
459
462
  // Is this feature option set explicitly?
460
463
  const isOptionSet = (featureOption, deviceMac) => {
461
464
 
462
- const optionRegex = new RegExp("^(Enable|Disable)\." + featureOption + (!deviceMac ? "" : "\." + deviceMac) + "$", "gi");
463
- return optionsList.filter(x => x.match(optionRegex)).length ? true : false;
465
+ const optionRegex = new RegExp("^(?:Enable|Disable)\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "$", "gi");
466
+ return optionsList.filter(x => optionRegex.test(x)).length ? true : false;
464
467
  };
465
468
 
466
469
  // Is a feature option globally enabled?
467
- const isGlobalOptionEnabled = (featureOption, defaultValue) => {
470
+ const isGlobalOptionEnabled = (featureOption, defaultState) => {
468
471
 
469
472
  featureOption = featureOption.toUpperCase();
470
473
 
471
474
  // Test device-specific options.
472
475
  return optionsList.some(x => x === ("ENABLE." + featureOption)) ? true :
473
- (optionsList.some(x => x === ("DISABLE." + featureOption)) ? false : defaultValue
476
+ (optionsList.some(x => x === ("DISABLE." + featureOption)) ? false : defaultState
474
477
  );
475
478
  };
476
479
 
477
- // Is a feature option enabled at the device or global level. It does not traverse the scoping hierarchy.
478
- const isDeviceOptionEnabled = (featureOption, mac, defaultValue) => {
480
+ // Is a feature option enabled at the device or global level. This function does not traverse the scoping hierarchy.
481
+ const isDeviceOptionEnabled = (featureOption, mac, defaultState) => {
479
482
 
480
483
  if(!mac) {
481
484
 
482
- return isGlobalOptionEnabled(featureOption, defaultValue);
485
+ return isGlobalOptionEnabled(featureOption, defaultState);
483
486
  }
484
487
 
485
488
  featureOption = featureOption.toUpperCase();
@@ -487,60 +490,113 @@
487
490
 
488
491
  // Test device-specific options.
489
492
  return optionsList.some(x => x === ("ENABLE." + featureOption + "." + mac)) ? true :
490
- (optionsList.some(x => x === ("DISABLE." + featureOption + "." + mac)) ? false : defaultValue
493
+ (optionsList.some(x => x === ("DISABLE." + featureOption + "." + mac)) ? false : defaultState
491
494
  );
492
495
  };
493
496
 
497
+ // Is a value-centric feature option enabled at the device or global level. This function does not traverse the scoping hierarchy.
498
+ const isOptionValueSet = (featureOption, deviceMac) => {
499
+
500
+ const optionRegex = new RegExp("^Enable\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "\\.([^\\.]+)$", "gi");
501
+
502
+ return optionsList.filter(x => optionRegex.test(x)).length ? true : false;
503
+ };
504
+
505
+ // Get the value of a value-centric feature option.
506
+ const getOptionValue = (featureOption, deviceMac) => {
507
+
508
+ const optionRegex = new RegExp("^Enable\\." + featureOption + (!deviceMac ? "" : "\\." + deviceMac) + "\\.([^\\.]+)$", "gi");
509
+
510
+ // Get the option value, if we have one.
511
+ for(const option of optionsList) {
512
+
513
+ const regexMatch = optionRegex.exec(option);
514
+
515
+ if(regexMatch) {
516
+
517
+ return regexMatch[1];
518
+ }
519
+ }
520
+
521
+ return undefined;
522
+ };
523
+
494
524
  // Is a feature option enabled at the device or global level. It does traverse the scoping hierarchy.
495
- const isOptionEnabled = (featureOption, deviceMac, defaultValue) => {
525
+ const isOptionEnabled = (featureOption, deviceMac) => {
526
+
527
+ const defaultState = featureOptionList[featureOption]?.default ?? true;
496
528
 
497
529
  if(deviceMac) {
498
530
 
499
531
  // Device level check.
500
- if(isDeviceOptionEnabled(featureOption, deviceMac, defaultValue) !== defaultValue) {
532
+ if(isDeviceOptionEnabled(featureOption, deviceMac, defaultState) !== defaultState) {
501
533
 
502
- return !defaultValue;
534
+ return !defaultState;
503
535
  }
504
536
 
505
537
  // Controller level check.
506
- if(isDeviceOptionEnabled(featureOption, nvr.mac, defaultValue) !== defaultValue) {
538
+ if(isDeviceOptionEnabled(featureOption, nvr.mac, defaultState) !== defaultState) {
507
539
 
508
- return !defaultValue;
540
+ return !defaultState;
509
541
  }
510
542
  }
511
543
 
512
544
  // Global check.
513
- if(isGlobalOptionEnabled(featureOption, defaultValue) !== defaultValue) {
545
+ if(isGlobalOptionEnabled(featureOption, defaultState) !== defaultState) {
514
546
 
515
- return !defaultValue;
547
+ return !defaultState;
516
548
  }
517
549
 
518
550
  // Return the default.
519
- return defaultValue;
551
+ return defaultState;
520
552
  };
521
553
 
522
554
  // Return the scope level of a feature option.
523
- const optionScope = (featureOption, deviceMac, defaultValue) => {
555
+ const optionScope = (featureOption, deviceMac, defaultState, isOptionValue = false) => {
524
556
 
525
557
  // Scope priority is always: device, NVR, global.
526
558
 
559
+ // If we have a value-centric feature option, our lookups are a bit different.
560
+ if(isOptionValue) {
561
+
562
+ if(deviceMac) {
563
+
564
+ if(isOptionValueSet(featureOption, deviceMac)) {
565
+
566
+ return "device";
567
+ }
568
+
569
+ if(isOptionValueSet(featureOption, nvr.mac)) {
570
+
571
+ return "nvr";
572
+ }
573
+ }
574
+
575
+ if(isOptionValueSet(featureOption)) {
576
+
577
+ return "global";
578
+ }
579
+
580
+ return "none";
581
+ }
582
+
527
583
  if(deviceMac) {
528
584
 
529
585
  // Let's see if we've set it at the device-level.
530
- if((isDeviceOptionEnabled(featureOption, deviceMac, defaultValue) !== defaultValue) || isOptionSet(featureOption, deviceMac)) {
586
+ if((isDeviceOptionEnabled(featureOption, deviceMac, defaultState) !== defaultState) || isOptionSet(featureOption, deviceMac)) {
531
587
 
532
588
  return "device";
533
589
  }
534
590
 
535
591
  // Now let's test the controller level.
536
- if((isDeviceOptionEnabled(featureOption, nvr.mac, defaultValue) !== defaultValue) || isOptionSet(featureOption, nvr.mac)) {
592
+ if((isDeviceOptionEnabled(featureOption, nvr.mac, defaultState) !== defaultState) || isOptionSet(featureOption, nvr.mac)) {
537
593
 
538
594
  return "nvr";
539
595
  }
540
596
  }
541
597
 
542
598
  // Finally, let's test the global level.
543
- if((isGlobalOptionEnabled(featureOption, defaultValue) !== defaultValue) || isOptionSet(featureOption)) {
599
+ if((isGlobalOptionEnabled(featureOption, defaultState) !== defaultState) || isOptionSet(featureOption)) {
544
600
 
545
601
  return "global";
546
602
  }
@@ -550,9 +606,9 @@
550
606
  };
551
607
 
552
608
  // Return the color hinting for a given option's scope.
553
- const optionScopeColor = (featureOption, deviceMac, defaultValue) => {
609
+ const optionScopeColor = (featureOption, deviceMac, defaultState, isOptionValue) => {
554
610
 
555
- switch(optionScope(featureOption, deviceMac, defaultValue)) {
611
+ switch(optionScope(featureOption, deviceMac, defaultState, isOptionValue)) {
556
612
 
557
613
  case "device":
558
614
 
@@ -623,6 +679,36 @@
623
679
  let newConfigTableHtml = "";
624
680
  configTable.innerHTML = "";
625
681
 
682
+ // Initialize the full list of options.
683
+ featureOptionList = {};
684
+ featureOptionGroups = {};
685
+
686
+ for(const category of ufpFeatures.categories) {
687
+
688
+ // Now enumerate all the feature options for a given device and add then to the full list.
689
+ for(const option of optionsDevice[category.name]) {
690
+
691
+ const featureOption = category.name + (option.name.length ? ("." + option.name): "");
692
+
693
+ // Add it to our full list.
694
+ featureOptionList[featureOption] = option;
695
+
696
+ // Cross reference the feature option group it belongs to, if any.
697
+ if(option.group !== undefined) {
698
+
699
+ const expandedGroup = category.name + (option.group.length ? ("." + option.group): "");
700
+
701
+ // Initialize the group entry if needed.
702
+ if(!featureOptionGroups[expandedGroup]) {
703
+
704
+ featureOptionGroups[expandedGroup] = [];
705
+ }
706
+
707
+ featureOptionGroups[expandedGroup].push(featureOption);
708
+ }
709
+ }
710
+ }
711
+
626
712
  for(const category of ufpFeatures.categories) {
627
713
 
628
714
  // Only show feature option categories that are valid for this context.
@@ -641,7 +727,7 @@
641
727
  optionTable.classList.add("table", "table-borderless", "table-sm", "table-hover");
642
728
  th.classList.add("p-0");
643
729
  th.style.fontWeight = "bold";
644
- th.colSpan = 2;
730
+ th.colSpan = 3;
645
731
  tbody.classList.add("table-bordered");
646
732
 
647
733
  // Add the feature option category description.
@@ -667,9 +753,13 @@
667
753
  continue;
668
754
  }
669
755
 
756
+ // Expand the full feature option.
757
+ const featureOption = category.name + (option.name.length ? ("." + option.name): "");
758
+
670
759
  // Create the next table row.
671
760
  const trX = document.createElement("tr");
672
761
  trX.classList.add("align-top");
762
+ trX.id = "row-" + featureOption;
673
763
 
674
764
  // Create a checkbox for the option.
675
765
  const tdCheckbox = document.createElement("td");
@@ -677,14 +767,17 @@
677
767
  // Create the actual checkbox for the option.
678
768
  const checkbox = document.createElement("input");
679
769
 
680
- const featureOption = category.name + (option.name.length ? ("." + option.name): "");
681
770
  checkbox.type = "checkbox";
682
771
  checkbox.readOnly = false;
683
772
  checkbox.id = featureOption;
684
773
  checkbox.name = featureOption;
685
774
  checkbox.value = featureOption + (!ufpDevice ? "" : ("." + ufpDevice.mac));
686
775
 
687
- switch(optionScope(featureOption, ufpDevice?.mac, option.default)) {
776
+ let initialValue = undefined;
777
+ let initialScope;
778
+
779
+ // Determine our initial option scope to show the user what's been set.
780
+ switch(initialScope = optionScope(featureOption, ufpDevice?.mac, option.default, ("defaultValue" in option))) {
688
781
 
689
782
  case "global":
690
783
  case "nvr":
@@ -692,7 +785,14 @@
692
785
  // If we're looking at the global scope, show the option value. Otherwise, we show that we're inheriting a value from the scope above.
693
786
  if(!ufpDevice) {
694
787
 
695
- checkbox.checked = isGlobalOptionEnabled(featureOption, option.default);
788
+ if("defaultValue" in option) {
789
+
790
+ checkbox.checked = isOptionValueSet(featureOption);
791
+ initialValue = getOptionValue(checkbox.id);
792
+ } else {
793
+
794
+ checkbox.checked = isGlobalOptionEnabled(featureOption, option.default);
795
+ }
696
796
 
697
797
  if(checkbox.checked) {
698
798
 
@@ -701,6 +801,11 @@
701
801
 
702
802
  } else {
703
803
 
804
+ if("defaultValue" in option) {
805
+
806
+ initialValue = getOptionValue(checkbox.id, (initialScope === "nvr") ? nvr.mac : undefined);
807
+ }
808
+
704
809
  checkbox.readOnly = checkbox.indeterminate = true;
705
810
  }
706
811
 
@@ -709,7 +814,16 @@
709
814
  case "device":
710
815
  case "none":
711
816
  default:
712
- checkbox.checked = isDeviceOptionEnabled(featureOption, ufpDevice?.mac, option.default);
817
+
818
+ if("defaultValue" in option) {
819
+
820
+ checkbox.checked = isOptionValueSet(featureOption, ufpDevice?.mac);
821
+ initialValue = getOptionValue(checkbox.id, ufpDevice?.mac);
822
+ } else {
823
+
824
+ checkbox.checked = isDeviceOptionEnabled(featureOption, ufpDevice?.mac, option.default);
825
+ }
826
+
713
827
  break;
714
828
  }
715
829
 
@@ -724,6 +838,50 @@
724
838
 
725
839
  const tdLabel = document.createElement("td");
726
840
  tdLabel.classList.add("w-100");
841
+ tdLabel.colSpan = 2;
842
+
843
+ let inputValue = null;
844
+
845
+ // Add an input field if we have a value-centric feature option.
846
+ if(("defaultValue" in option)) {
847
+
848
+ const tdInput = document.createElement("td");
849
+
850
+ inputValue = document.createElement("input");
851
+ inputValue.type = "text";
852
+ inputValue.value = initialValue ?? option.defaultValue;
853
+ inputValue.size = 5;
854
+ inputValue.readOnly = !checkbox.checked;
855
+ inputValue.classList.add("mr-2");
856
+
857
+ // Add or remove the setting from our configuration when we've changed our state.
858
+ inputValue.addEventListener("change", async () => {
859
+
860
+ // Find the option in our list and delete it if it exists.
861
+ const optionRegex = new RegExp("^(?:Enable|Disable)\\." + checkbox.id + (!ufpDevice ? "" : ("\\." + ufpDevice.mac)) + "\\.[^\\.]+$", "gi");
862
+ const newOptions = configOptions.filter(x => !optionRegex.test(x));
863
+
864
+ if(checkbox.checked) {
865
+
866
+ newOptions.push("Enable." + checkbox.value + "." + inputValue.value);
867
+ } else if(checkbox.indeterminate) {
868
+
869
+ // If we're in an indeterminate state, we need to traverse the tree to get the upstream value we're inheriting.
870
+ inputValue.value = (ufpDevice?.mac !== nvr.mac) ? (getOptionValue(checkbox.id, nvr.mac) ?? getOptionValue(checkbox.id)) : (getOptionValue(checkbox.id) ?? option.defaultValue);
871
+ } else {
872
+
873
+ inputValue.value = option.defaultValue;
874
+ }
875
+
876
+ // Update our configuration in Homebridge.
877
+ currentConfig[0].options = newOptions;
878
+ updateConfigOptions(newOptions);
879
+ await homebridge.updatePluginConfig(currentConfig);
880
+ });
881
+
882
+ tdInput.appendChild(inputValue);
883
+ trX.appendChild(tdInput);
884
+ }
727
885
 
728
886
  // Create a label for the checkbox with our option description.
729
887
  const labelDescription = document.createElement("label");
@@ -732,7 +890,7 @@
732
890
  labelDescription.classList.add("user-select-none", "my-0", "py-0");
733
891
 
734
892
  // Highlight options for the user that are different than our defaults.
735
- const scopeColor = optionScopeColor(featureOption, ufpDevice?.mac, option.default);
893
+ const scopeColor = optionScopeColor(featureOption, ufpDevice?.mac, option.default, ("defaultValue" in option));
736
894
 
737
895
  if(scopeColor) {
738
896
 
@@ -743,14 +901,14 @@
743
901
  checkbox.addEventListener("change", async () => {
744
902
 
745
903
  // Find the option in our list and delete it if it exists.
746
- const optionRegex = new RegExp("^(Enable|Disable)\." + checkbox.id + (!ufpDevice ? "" : ("\." + ufpDevice.mac)) + "$", "gi");
747
- const newOptions = configOptions.filter(x => !x.match(optionRegex));
904
+ const optionRegex = new RegExp("^(?:Enable|Disable)\\." + checkbox.id + (!ufpDevice ? "" : ("\\." + ufpDevice.mac)) + "$", "gi");
905
+ const newOptions = configOptions.filter(x => !optionRegex.test(x));
748
906
 
749
907
  // Figure out if we've got the option set upstream.
750
908
  let upstreamOption = false;
751
909
 
752
910
  // We explicitly want to check for the scope of the feature option above where we are now, so we can appropriately determine what we should show.
753
- switch(optionScope(checkbox.id, (ufpDevice && (ufpDevice.mac !== nvr.mac)) ? nvr.mac : null, option.default)) {
911
+ switch(optionScope(checkbox.id, (ufpDevice && (ufpDevice.mac !== nvr.mac)) ? nvr.mac : null, option.default, ("defaultValue" in option))) {
754
912
 
755
913
  case "device":
756
914
  case "nvr":
@@ -776,7 +934,8 @@
776
934
  break;
777
935
  }
778
936
 
779
- if(checkbox.readOnly) {
937
+ // For value-centric feature options, if there's an upstream value assigned above us, we don't allow for an unchecked state as it makes no sense in that context.
938
+ if(checkbox.readOnly && (!("defaultValue" in option) || (("defaultValue" in option) && inputValue && !upstreamOption))) {
780
939
 
781
940
  // We're truly unchecked. We need this because a checkbox can be in both an unchecked and indeterminate simultaneously,
782
941
  // so we use the readOnly property to let us know that we've just cycled from an indeterminate state.
@@ -791,10 +950,19 @@
791
950
  checkbox.readOnly = checkbox.indeterminate = true;
792
951
  }
793
952
 
953
+ if(("defaultValue" in option) && inputValue) {
954
+
955
+ inputValue.readOnly = true;
956
+ }
794
957
  } else if(checkbox.checked) {
795
958
 
796
959
  // We've explicitly checked this option.
797
960
  checkbox.readOnly = checkbox.indeterminate = false;
961
+
962
+ if(("defaultValue" in option) && inputValue) {
963
+
964
+ inputValue.readOnly = false;
965
+ }
798
966
  }
799
967
 
800
968
  // The setting is different from the default, highlight it for the user, accounting for upstream scope, and add it to our configuration.
@@ -808,21 +976,43 @@
808
976
  labelDescription.classList.remove("text-info");
809
977
  }
810
978
 
811
- // Update our configuration in Homebridge.
812
- currentConfig[0].options = newOptions;
813
- updateConfigOptions(newOptions);
814
- await homebridge.updatePluginConfig(currentConfig);
979
+ // Update our Homebridge configuration.
980
+ if(("defaultValue" in option) && inputValue) {
981
+
982
+ // Inform our value-centric feature option to update Homebridge.
983
+ const changeEvent = new Event("change");
984
+
985
+ inputValue.dispatchEvent(changeEvent);
986
+ } else {
987
+
988
+ // Update our configuration in Homebridge.
989
+ currentConfig[0].options = newOptions;
990
+ updateConfigOptions(newOptions);
991
+ await homebridge.updatePluginConfig(currentConfig);
992
+ }
815
993
 
816
994
  // If we've reset to defaults, make sure our color coding for scope is reflected.
817
995
  if((checkbox.checked === option.default) || checkbox.indeterminate) {
818
996
 
819
- const scopeColor = optionScopeColor(featureOption, ufpDevice?.mac, option.default);
997
+ const scopeColor = optionScopeColor(featureOption, ufpDevice?.mac, option.default, ("defaultValue" in option));
820
998
 
821
999
  if(scopeColor) {
822
1000
 
823
1001
  labelDescription.classList.add(scopeColor);
824
1002
  }
825
1003
  }
1004
+
1005
+ // Adjust visibility of other feature options that depend on us.
1006
+ if(featureOptionGroups[checkbox.id]) {
1007
+
1008
+ const entryVisibility = isOptionEnabled(featureOption, ufpDevice?.mac) ? "" : "none";
1009
+
1010
+ // Lookup each feature option setting and set the visibility accordingly.
1011
+ for(const entry of featureOptionGroups[checkbox.id]) {
1012
+
1013
+ document.getElementById("row-" + entry).style.display = entryVisibility;
1014
+ }
1015
+ }
826
1016
  });
827
1017
 
828
1018
  // Add the actual description for the option after the checkbox.
@@ -837,6 +1027,12 @@
837
1027
  // Add the label table cell to the table row.
838
1028
  trX.appendChild(tdLabel);
839
1029
 
1030
+ // Adjust the visibility of the feature option, if it's logically grouped.
1031
+ if((option.group !== undefined) && !isOptionEnabled(category.name + (option.group.length ? ("." + option.group): ""), ufpDevice?.mac)) {
1032
+
1033
+ trX.style.display = "none";
1034
+ }
1035
+
840
1036
  // Add the table row to the table body.
841
1037
  tbody.appendChild(trX);
842
1038
  }
@@ -11,7 +11,7 @@
11
11
  /* eslint-disable new-cap */
12
12
  "use strict";
13
13
 
14
- import { featureOptionCategories, featureOptions, optionEnabled } from "../dist/protect-options.js";
14
+ import { featureOptionCategories, featureOptions, isOptionEnabled } from "../dist/protect-options.js";
15
15
  import { HomebridgePluginUiServer } from "@homebridge/plugin-ui-utils";
16
16
  import { ProtectApi } from "unifi-protect";
17
17
  import * as fs from "node:fs";
@@ -113,7 +113,7 @@ class PluginUiServer extends HomebridgePluginUiServer {
113
113
 
114
114
  for(const options of featureOptions[category.name]) {
115
115
 
116
- options.value = optionEnabled(request.configOptions, request.nvrUfp, request.deviceUfp, category.name + "." + options.name, options.default);
116
+ options.value = isOptionEnabled(request.configOptions, request.nvrUfp, request.deviceUfp, category.name + "." + options.name, options.default);
117
117
  optionSet[category.name].push(options);
118
118
  }
119
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-unifi-protect",
3
- "version": "6.8.1",
3
+ "version": "6.9.0",
4
4
  "displayName": "Homebridge UniFi Protect",
5
5
  "description": "Homebridge UniFi Protect plugin providing complete HomeKit integration for the UniFi Protect ecosystem with full support for most features including autoconfiguration, motion detection, multiple controllers, and realtime updates.",
6
6
  "author": {
@@ -68,15 +68,15 @@
68
68
  "@homebridge/plugin-ui-utils": "^0.0.19",
69
69
  "ffmpeg-for-homebridge": "^0.1.4",
70
70
  "mqtt": "4.3.7",
71
- "unifi-protect": "^4.2.4",
71
+ "unifi-protect": "^4.4.0",
72
72
  "ws": "^8.13.0"
73
73
  },
74
74
  "devDependencies": {
75
- "@types/node": "^20.2.5",
76
- "@types/ws": "^8.5.4",
77
- "@typescript-eslint/eslint-plugin": "^5.59.8",
78
- "@typescript-eslint/parser": "^5.59.8",
79
- "eslint": "^8.42.0",
75
+ "@types/node": "^20.3.1",
76
+ "@types/ws": "^8.5.5",
77
+ "@typescript-eslint/eslint-plugin": "^5.60.0",
78
+ "@typescript-eslint/parser": "^5.60.0",
79
+ "eslint": "^8.43.0",
80
80
  "homebridge": "=1.6.1",
81
81
  "nodemon": "^2.0.22",
82
82
  "rimraf": "^5.0.1",