27
27
class ArloProvider (ScryptedDeviceBase , Settings , DeviceProvider , ScryptedDeviceLoggerMixin , BackgroundTaskMixin ):
28
28
arlo_cameras = None
29
29
arlo_basestations = None
30
+ all_device_ids : set = set ()
30
31
_arlo_mfa_code = None
31
32
scrypted_devices = None
32
- _arlo = None
33
+ _arlo : Arlo = None
33
34
_arlo_mfa_complete_auth = None
34
35
device_discovery_lock : asyncio .Lock = None
35
36
@@ -157,6 +158,23 @@ def imap_mfa_interval(self) -> int:
157
158
self .storage .setItem ("imap_mfa_interval" , interval )
158
159
return int (interval )
159
160
161
+ @property
162
+ def hidden_devices (self ) -> List [str ]:
163
+ hidden = self .storage .getItem ("hidden_devices" )
164
+ if hidden is None :
165
+ hidden = []
166
+ self .storage .setItem ("hidden_devices" , hidden )
167
+ return hidden
168
+
169
+ @property
170
+ def hidden_device_ids (self ) -> List [str ]:
171
+ ids = []
172
+ for id in self .hidden_devices :
173
+ m = re .match (r".*\((.*)\)$" , id )
174
+ if m is not None :
175
+ ids .append (m .group (1 ))
176
+ return ids
177
+
160
178
@property
161
179
def arlo (self ) -> Arlo :
162
180
if self ._arlo is not None :
@@ -530,6 +548,16 @@ async def getSettings(self) -> List[Setting]:
530
548
"value" : self .plugin_verbosity == "Verbose" ,
531
549
"type" : "boolean" ,
532
550
},
551
+ {
552
+ "group" : "General" ,
553
+ "key" : "hidden_devices" ,
554
+ "title" : "Hidden Devices" ,
555
+ "description" : "Select the Arlo devices to hide in this plugin. Hidden devices will be removed from Scrypted and will "
556
+ "not be re-added when the plugin reloads." ,
557
+ "value" : self .hidden_devices ,
558
+ "multiple" : True ,
559
+ "choices" : [id for id in self .all_device_ids ],
560
+ },
533
561
])
534
562
535
563
return results
@@ -573,6 +601,11 @@ async def putSetting(self, key: str, value: SettingValue) -> None:
573
601
elif key .startswith ("imap_mfa" ):
574
602
self .initialize_imap ()
575
603
skip_arlo_client = True
604
+ elif key == "hidden_devices" :
605
+ if self ._arlo is not None and self ._arlo .logged_in :
606
+ self ._arlo .Unsubscribe ()
607
+ await self .do_arlo_setup ()
608
+ skip_arlo_client = True
576
609
else :
577
610
# force arlo client to be invalidated and reloaded
578
611
self .invalidate_arlo_client ()
@@ -618,12 +651,13 @@ async def discover_devices(self) -> None:
618
651
return await self .discover_devices_impl ()
619
652
620
653
async def discover_devices_impl (self ) -> None :
621
- if not self .arlo :
654
+ if not self ._arlo or not self . _arlo . logged_in :
622
655
raise Exception ("Arlo client not connected, cannot discover devices" )
623
656
624
657
self .logger .info ("Discovering devices..." )
625
658
self .arlo_cameras = {}
626
659
self .arlo_basestations = {}
660
+ self .all_device_ids = set ()
627
661
self .scrypted_devices = {}
628
662
629
663
camera_devices = []
@@ -632,13 +666,20 @@ async def discover_devices_impl(self) -> None:
632
666
basestations = self .arlo .GetDevices (['basestation' , 'siren' ])
633
667
for basestation in basestations :
634
668
nativeId = basestation ["deviceId" ]
669
+ self .all_device_ids .add (f"{ basestation ['deviceName' ]} ({ nativeId } )" )
670
+
635
671
self .logger .debug (f"Adding { nativeId } " )
636
672
637
673
if nativeId in self .arlo_basestations :
638
674
self .logger .info (f"Skipping basestation { nativeId } ({ basestation ['modelId' ]} ) as it has already been added" )
639
675
continue
676
+
640
677
self .arlo_basestations [nativeId ] = basestation
641
678
679
+ if nativeId in self .hidden_device_ids :
680
+ self .logger .info (f"Skipping manifest for basestation { nativeId } ({ basestation ['modelId' ]} ) as it is hidden" )
681
+ continue
682
+
642
683
device = await self .getDevice_impl (nativeId )
643
684
scrypted_interfaces = device .get_applicable_interfaces ()
644
685
manifest = device .get_device_manifest ()
@@ -657,11 +698,13 @@ async def discover_devices_impl(self) -> None:
657
698
await scrypted_sdk .deviceManager .onDeviceDiscovered (child_manifest )
658
699
provider_to_device_map .setdefault (child_manifest ["providerNativeId" ], []).append (child_manifest )
659
700
660
- self .logger .info (f"Discovered { len (basestations )} basestations" )
701
+ self .logger .info (f"Discovered { len (self . arlo_basestations )} basestations" )
661
702
662
703
cameras = self .arlo .GetDevices (['camera' , "arloq" , "arloqs" , "doorbell" ])
663
704
for camera in cameras :
664
705
nativeId = camera ["deviceId" ]
706
+ self .all_device_ids .add (f"{ camera ['deviceName' ]} ({ nativeId } )" )
707
+
665
708
self .logger .debug (f"Adding { nativeId } " )
666
709
667
710
if camera ["deviceId" ] != camera ["parentId" ] and camera ["parentId" ] not in self .arlo_basestations :
@@ -671,6 +714,11 @@ async def discover_devices_impl(self) -> None:
671
714
if nativeId in self .arlo_cameras :
672
715
self .logger .info (f"Skipping camera { nativeId } ({ camera ['modelId' ]} ) as it has already been added" )
673
716
continue
717
+
718
+ if nativeId in self .hidden_device_ids :
719
+ self .logger .info (f"Skipping camera { camera ['deviceId' ]} ({ camera ['modelId' ]} ) because it is hidden" )
720
+ continue
721
+
674
722
self .arlo_cameras [nativeId ] = camera
675
723
676
724
if camera ["deviceId" ] == camera ["parentId" ]:
@@ -683,7 +731,7 @@ async def discover_devices_impl(self) -> None:
683
731
manifest = device .get_device_manifest ()
684
732
self .logger .debug (f"Interfaces for { nativeId } ({ camera ['modelId' ]} parent { camera ['parentId' ]} ): { scrypted_interfaces } " )
685
733
686
- if camera ["deviceId" ] == camera ["parentId" ]:
734
+ if camera ["deviceId" ] == camera ["parentId" ] or camera [ "parentId" ] in self . hidden_device_ids :
687
735
provider_to_device_map .setdefault (None , []).append (manifest )
688
736
else :
689
737
provider_to_device_map .setdefault (camera ["parentId" ], []).append (manifest )
@@ -701,7 +749,9 @@ async def discover_devices_impl(self) -> None:
701
749
702
750
if len (cameras ) != len (camera_devices ):
703
751
self .logger .info (f"Discovered { len (cameras )} cameras, but only { len (camera_devices )} are usable" )
704
- self .logger .info (f"Are all cameras shared with admin permissions?" )
752
+ self .logger .info ("This could be because some cameras are hidden." )
753
+ self .logger .info ("If a camera is not hidden but is still missing, ensure all cameras shared with "
754
+ "admin permissions in the Arlo app." )
705
755
else :
706
756
self .logger .info (f"Discovered { len (cameras )} cameras" )
707
757
@@ -726,7 +776,11 @@ async def discover_devices_impl(self) -> None:
726
776
})
727
777
self .logger .debug ("Done discovering devices" )
728
778
779
+ # force a settings refresh so the hidden devices list can be updated
780
+ await self .onDeviceEvent (ScryptedInterface .Settings .value , None )
781
+
729
782
async def getDevice (self , nativeId : str ) -> ArloDeviceBase :
783
+ self .logger .debug (f"Scrypted requested to load device { nativeId } " )
730
784
async with self .device_discovery_lock :
731
785
return await self .getDevice_impl (nativeId )
732
786
0 commit comments