2222import logging
2323from datetime import datetime
2424from enum import Enum
25- from typing import List
2625
2726from .soapclient import MethodCallError , SoapClient
2827
@@ -66,7 +65,7 @@ def DeviceFactory(
6665
6766
6867class Device :
69- REQUIRED_MODULE_TYPES : List [ str ] = []
68+ MODULE_TYPE : str
7069
7170 def __init__ (
7271 self ,
@@ -80,6 +79,34 @@ def __init__(
8079 self .client = client or SoapClient (
8180 hostname = hostname , password = password , username = username , port = port
8281 )
82+ self ._info = None
83+ self ._module_id = None
84+ self ._controller = None
85+
86+ @property
87+ def info (self ):
88+ if not self ._info :
89+ self ._info = self .client .device_info ()
90+
91+ return self ._info
92+
93+ @property
94+ def module_id (self ):
95+ if not self ._module_id :
96+ self ._module_id = self .info ["ModuleTypes" ].find (self .MODULE_TYPE ) + 1
97+
98+ return self ._module_id
99+
100+ @property
101+ def controller (self ):
102+ # NOTE: not sure about this
103+ return self .module_id
104+
105+ def call (self , * args , ** kwargs ):
106+ kwargs ["ModuleID" ] = kwargs .get ("ModuleID" ) or self .module_id
107+ kwargs ["Controller" ] = kwargs .get ("Controller" ) or self .controller
108+
109+ return self .client .call (* args , ** kwargs )
83110
84111 # def get_info(self):
85112 # info = self.client.device_info()
@@ -99,7 +126,7 @@ def __init__(
99126
100127
101128class Camera (Device ):
102- REQUIRED_MODULE_TYPES = [ "Camera" ]
129+ MODULE_TYPE = "Camera"
103130
104131 def __init__ (self , * args , ** kwargs ):
105132 super ().__init__ (* args , ** kwargs )
@@ -119,7 +146,7 @@ def picture_url(self):
119146
120147
121148class Motion (Device ):
122- REQUIRED_MODULE_TYPES = [ "Motion Sensor" ]
149+ MODULE_TYPE = "Motion Sensor"
123150
124151 def __init__ (self , * args , ** kwargs ):
125152 super ().__init__ (* args , ** kwargs )
@@ -128,7 +155,7 @@ def __init__(self, *args, **kwargs):
128155 @property
129156 def backoff (self ):
130157 if self ._backoff is None :
131- resp = self .client . call ("GetMotionDetectorSettings" , ModuleID = 1 )
158+ resp = self .call ("GetMotionDetectorSettings" )
132159 try :
133160 self ._backoff = int (resp ["Backoff" ])
134161 except (KeyError , ValueError , TypeError ):
@@ -156,7 +183,7 @@ def backoff(self):
156183
157184 @auth_required
158185 def get_latest_detection (self ):
159- res = self .client . call ("GetLatestDetection" , ModuleID = 1 )
186+ res = self .call ("GetLatestDetection" )
160187 return datetime .fromtimestamp (float (res ["LatestDetectTime" ]))
161188
162189 @auth_required
@@ -170,11 +197,11 @@ def is_active(self):
170197class Router (Device ):
171198 # NOT tested
172199 # See https://github.com/waffelheld/dlink-device-tracker/blob/master/custom_components/dlink_device_tracker/dlink_hnap.py#L95 # noqa: E501
173- REQUIRED_MODULE_TYPES = [ "check-module-types-for-router" ]
200+ MODULE_TYPE = "check-module-types-for-router"
174201
175202 @auth_required
176203 def get_clients (self ):
177- res = self .client . call ("GetClientInfo" , ModuleID = 1 , Controller = 1 )
204+ res = self .call ("GetClientInfo" )
178205 clients = res ["ClientInfoLists" ]["ClientInfo" ]
179206
180207 # Filter out offline clients
@@ -210,19 +237,17 @@ def fromstring(cls, s):
210237
211238
212239class Siren (Device ):
213- REQUIRED_MODULE_TYPES = [ "Audio Renderer" ]
240+ MODULE_TYPE = "Audio Renderer"
214241
215242 @auth_required
216243 def is_playing (self ):
217- res = self .client . call ("GetSirenAlarmSettings" , ModuleID = 1 , Controller = 1 )
244+ res = self .call ("GetSirenAlarmSettings" )
218245 return res ["IsSounding" ] == "true"
219246
220247 @auth_required
221248 def play (self , sound = SirenSound .EMERGENCY , volume = 100 , duration = 60 ):
222- ret = self .client . call (
249+ ret = self .call (
223250 "SetSoundPlay" ,
224- ModuleID = 1 ,
225- Controller = 1 ,
226251 SoundType = sound .value ,
227252 Volume = volume ,
228253 Duration = duration ,
@@ -236,17 +261,17 @@ def beep(self, volume=100, duration=1):
236261
237262 @auth_required
238263 def stop (self ):
239- ret = self .client . call ("SetAlarmDismissed" , ModuleID = 1 , Controller = 1 )
264+ ret = self .call ("SetAlarmDismissed" )
240265
241266 if ret ["SetAlarmDismissedResult" ] != "OK" :
242267 raise MethodCallError (f"Unable to stop. Response: { ret } " )
243268
244269
245270class Water (Device ):
246271 # NOT tested
247- REQUIRED_MODULE_TYPES = [ "check-module-types-for-water-detector" ]
272+ MODULE_TYPE = "check-module-types-for-water-detector"
248273
249274 @auth_required
250275 def is_active (self ):
251- ret = self .client . call ("GetWaterDetectorState" , ModuleID = 1 )
276+ ret = self .call ("GetWaterDetectorState" )
252277 return ret .get ("IsWater" ) == "true"
0 commit comments