2020
2121import datetime
2222import enum
23+ import logging
2324
2425from .soapclient import MethodCallError , SoapClient
2526
27+ _LOGGER = logging .getLogger (__name__ )
2628
27- def DeviceFactory (hostname , password , username = "Admin" , port = 80 , ** kwargs ):
28- device = SoapClient (hostname , password , username , port )
29- device .authenticate ()
30- info = device .device_info ()
29+
30+ class Sound (enum .Enum ):
31+ EMERGENCY = 1
32+ FIRE = 2
33+ AMBULANCE = 3
34+ POLICE = 4
35+ DOOR_CHIME = 5
36+ BEEP = 6
37+
38+ @classmethod
39+ def fromstring (cls , s ):
40+ s = s .upper ()
41+ for c in ["-" , " " , "." ]:
42+ s = s .replace (c , "_" )
43+
44+ return getattr (cls , s )
45+
46+
47+ class Device :
48+ def __init__ (
49+ self ,
50+ * ,
51+ client = None ,
52+ hostname = None ,
53+ password = None ,
54+ username = "Admin" ,
55+ port = 80 ,
56+ ):
57+ self .client = client or SoapClient (
58+ hostname = hostname , password = password , username = username , port = port
59+ )
60+ self ._info = None
61+
62+ def authenticate (self ):
63+ self .client .authenticate ()
64+ info = dict (self .client .call ("GetDeviceSettings" ))
65+ for k in ["@xmlns" , "SOAPActions" , "GetDeviceSettingsResult" ]:
66+ info .pop (k , None )
67+
68+ try :
69+ info ["ModuleTypes" ] = info ["ModuleTypes" ]["string" ]
70+ except KeyError :
71+ pass
72+
73+ self ._info = info
74+
75+ @property
76+ def info (self ):
77+ return self ._info
78+
79+
80+ def DeviceFactory (
81+ * , client = None , hostname = None , password = None , username = "Admin" , port = 80
82+ ):
83+ client = client or SoapClient (
84+ hostname = hostname , password = password , username = username , port = port
85+ )
86+ client .authenticate ()
87+ info = client .device_info ()
3188
3289 module_types = info ["ModuleTypes" ]
3390 if not isinstance (module_types , list ):
@@ -43,47 +100,40 @@ def DeviceFactory(hostname, password, username="Admin", port=80, **kwargs):
43100 else :
44101 raise TypeError (module_types )
45102
46- return cls (hostname , password , username = username , port = port , ** kwargs )
47-
48-
49- class _Device (SoapClient ):
50- def __init__ (self , * args , ** kwargs ):
51- super ().__init__ (* args , ** kwargs )
52- self ._info = None
53-
54- def authenticate (self ):
55- super ().authenticate ()
56- self ._info = self .device_info ()
57-
58- @property
59- def info (self ):
60- return self ._info
103+ return cls (client = client )
61104
62105
63- class Camera (_Device ):
106+ class Camera (Device ):
64107 pass
65108
66109
67- class Motion (_Device ):
68- def __init__ (self , * args , delta = 30 , ** kwargs ):
110+ class Motion (Device ):
111+ def __init__ (self , * args , ** kwargs ):
69112 super ().__init__ (* args , ** kwargs )
70- self .delta = delta
113+ self ._delta = None
71114
72- def login (self ):
73- super ().login ()
115+ @property
116+ def delta (self ):
117+ return self ._delta
74118
75- # Auto-adjust delta
76- res = self .call (
77- "SetMotionDetectorSettings" , ModuleID = 1 , Backoff = self .delta
119+ @delta .setter
120+ def delta (self , seconds ):
121+ self .client .call (
122+ "SetMotionDetectorSettings" , ModuleID = 1 , Backoff = self ._delta
78123 )
79- res = self .call ("GetMotionDetectorSettings" , ModuleID = 1 )
124+ _LOGGER .warning ("set delta property has no effect" )
125+
126+ def authenticate (self ):
127+ super ().authenticate ()
128+
129+ res = self .client .call ("GetMotionDetectorSettings" , ModuleID = 1 )
80130 try :
81- self .delta = int (res ["Backoff" ])
82- except (ValueError , TypeError ):
83- self . delta = 30
131+ self ._delta = int (res ["Backoff" ])
132+ except (ValueError , TypeError , KeyError ):
133+ _LOGGER . warning ( "Unable to get delta from device" )
84134
85135 def get_latest_detection (self ):
86- res = self .call ("GetLatestDetection" , ModuleID = 1 )
136+ res = self .client . call ("GetLatestDetection" , ModuleID = 1 )
87137 return datetime .datetime .fromtimestamp (float (res ["LatestDetectTime" ]))
88138
89139 def is_active (self ):
@@ -93,7 +143,7 @@ def is_active(self):
93143 return delta <= self .delta
94144
95145
96- class Router (SoapClient ):
146+ class Router (Device ):
97147 # NOT tested
98148 # See https://github.com/waffelheld/dlink-device-tracker/blob/master/custom_components/dlink_device_tracker/dlink_hnap.py#L95
99149
@@ -116,30 +166,15 @@ def get_clients(self):
116166 return ret
117167
118168
119- class Sound (enum .Enum ):
120- EMERGENCY = 1
121- FIRE = 2
122- AMBULANCE = 3
123- POLICE = 4
124- DOOR_CHIME = 5
125- BEEP = 6
126-
127- @classmethod
128- def fromstring (cls , s ):
129- s = s .upper ()
130- for c in ["-" , " " , "." ]:
131- s = s .replace (c , "_" )
132-
133- return getattr (cls , s )
134-
135-
136- class Siren (_Device ):
169+ class Siren (Device ):
137170 def is_playing (self ):
138- res = self .call ("GetSirenAlarmSettings" , ModuleID = 1 , Controller = 1 )
171+ res = self .client .call (
172+ "GetSirenAlarmSettings" , ModuleID = 1 , Controller = 1
173+ )
139174 return res ["IsSounding" ] == "true"
140175
141176 def play (self , sound = Sound .EMERGENCY , volume = 100 , duration = 60 ):
142- ret = self .call (
177+ ret = self .client . call (
143178 "SetSoundPlay" ,
144179 ModuleID = 1 ,
145180 Controller = 1 ,
@@ -151,16 +186,18 @@ def play(self, sound=Sound.EMERGENCY, volume=100, duration=60):
151186 raise MethodCallError (f"Unable to play. Response: { ret } " )
152187
153188 def beep (self , volume = 100 , duration = 1 ):
154- return self .play (sound = Sound .BEEP , duration = duration , volume = volume )
189+ return self .client .play (
190+ sound = Sound .BEEP , duration = duration , volume = volume
191+ )
155192
156193 def stop (self ):
157- ret = self .call ("SetAlarmDismissed" , ModuleID = 1 , Controller = 1 )
194+ ret = self .client . call ("SetAlarmDismissed" , ModuleID = 1 , Controller = 1 )
158195
159196 if ret ["SetAlarmDismissedResult" ] != "OK" :
160197 raise MethodCallError (f"Unable to stop. Response: { ret } " )
161198
162199
163- class Water (_Device ):
200+ class Water (Device ):
164201 def is_active (self ):
165202 ret = self .call ("GetWaterDetectorState" , ModuleID = 1 )
166203 return ret .get ("IsWater" ) == "true"
0 commit comments