66
77import datetime
88import hashlib
9- import json
109import time
1110import uuid
1211from calendar import monthrange
1312
14- import dateutil .parser
15- import requests
16-
1713from ._e3dc_rscp_local import (
1814 E3DC_RSCP_local ,
1915 RSCPAuthenticationError ,
2420from ._rscpLib import rscpFindTag , rscpFindTagIndex
2521from ._rscpTags import RscpTag , RscpType , getStrPowermeterType , getStrPviType
2622
27- REMOTE_ADDRESS = "https://s10.e3dc.com/s10/phpcmd/cmd.php"
28- REQUEST_INTERVAL_SEC = 10 # minimum interval between requests
29- REQUEST_INTERVAL_SEC_LOCAL = 1 # minimum interval between requests
30-
3123
3224class AuthenticationError (Exception ):
3325 """Class for Authentication Error Exception."""
@@ -125,7 +117,6 @@ def __init__(self, connectType, **kwargs):
125117 self .key = kwargs ["key" ]
126118 self .password = kwargs ["password" ]
127119 self .rscp = E3DC_RSCP_local (self .username , self .password , self .ip , self .key )
128- self .poll = self .poll_rscp
129120 else :
130121 self ._set_serial (kwargs ["serialNumber" ])
131122 if "isPasswordMd5" in kwargs and not kwargs ["isPasswordMd5" ]:
@@ -139,7 +130,6 @@ def __init__(self, connectType, **kwargs):
139130 self .password ,
140131 "{}{}" .format (self .serialNumberPrefix , self .serialNumber ),
141132 )
142- self .poll = self .poll_ajax
143133
144134 self .get_system_info_static (keepAlive = True )
145135
@@ -200,157 +190,7 @@ def _set_serial(self, serial):
200190 self .powermeters = self .powermeters or [{"index" : 0 }]
201191 self .pvis = self .pvis or [{"index" : 0 }]
202192
203- def connect_web (self ):
204- """Connects to the E3DC portal and opens a session.
205-
206- Raises:
207- e3dc.AuthenticationError: login error
208- """
209- # login request
210- loginPayload = {
211- "DO" : "LOGIN" ,
212- "USERNAME" : self .username ,
213- "PASSWD" : self .password ,
214- }
215- headers = {"Window-Id" : self .guid }
216-
217- try :
218- r = requests .post (REMOTE_ADDRESS , data = loginPayload , headers = headers )
219- jsonResponse = r .json ()
220- except :
221- raise AuthenticationError ("Error communicating with server" )
222- if jsonResponse ["ERRNO" ] != 0 :
223- raise AuthenticationError ("Login error" )
224-
225- # get cookies
226- self .jar = r .cookies
227-
228- # set the proper device
229- deviceSelectPayload = {
230- "DO" : "GETCONTENT" ,
231- "MODID" : "IDOVERVIEWUNITMAIN" ,
232- "ARG0" : self .serialNumber ,
233- "TOS" : - 7200 ,
234- }
235-
236- try :
237- r = requests .post (
238- REMOTE_ADDRESS ,
239- data = deviceSelectPayload ,
240- cookies = self .jar ,
241- headers = headers ,
242- )
243- jsonResponse = r .json ()
244- except :
245- raise AuthenticationError ("Error communicating with server" )
246- if jsonResponse ["ERRNO" ] != 0 :
247- raise AuthenticationError ("Error selecting device" )
248- self .connected = True
249-
250- def poll_ajax_raw (self ):
251- """Polls the portal for the current status.
252-
253- Returns:
254- dict: Dictionary containing the status information in raw format as returned by the portal
255-
256- Raises:
257- e3dc.PollError in case of problems polling
258- """
259- if not self .connected :
260- self .connect_web ()
261-
262- pollPayload = {"DO" : "LIVEUNITDATA" }
263- pollHeaders = {
264- "Pragma" : "no-cache" ,
265- "Cache-Control" : "no-store" ,
266- "Window-Id" : self .guid ,
267- }
268-
269- try :
270- r = requests .post (
271- REMOTE_ADDRESS , data = pollPayload , cookies = self .jar , headers = pollHeaders
272- )
273- jsonResponse = r .json ()
274- except :
275- self .connected = False
276- raise PollError ("Error communicating with server" )
277-
278- if jsonResponse ["ERRNO" ] != 0 :
279- raise PollError ("Error polling: %d" % (jsonResponse ["ERRNO" ]))
280-
281- return json .loads (jsonResponse ["CONTENT" ])
282-
283- def poll_ajax (self , ** kwargs ):
284- """Polls the portal for the current status and returns a digest.
285-
286- Args:
287- **kwars: argument list
288-
289- Returns:
290- dict: Dictionary containing the condensed status information structured as follows::
291-
292- {
293- "autarky": <autarky in %>,
294- "consumption": {
295- "battery": <power entering battery (positive: charging, negative: discharging)>,
296- "house": <house consumption>,
297- "wallbox": <wallbox consumption>
298- }
299- "production": {
300- "solar" : <production from solar in W>,
301- "add" : <additional external power in W>,
302- "grid" : <absorption from grid in W>
303- }
304- "stateOfCharge": <battery charge status in %>,
305- "selfConsumption": <self consumed power in %>,
306- "time": <datetime object containing the timestamp>
307- }
308-
309- Raises:
310- e3dc.PollError in case of problems polling
311- """
312- if (
313- self .lastRequest is not None
314- and (time .time () - self .lastRequestTime ) < REQUEST_INTERVAL_SEC
315- ):
316- return self .lastRequest
317-
318- raw = self .poll_ajax_raw ()
319- strPmIndex = str (self .pmIndexExt )
320- outObj = {
321- "time" : dateutil .parser .parse (raw ["time" ]).replace (
322- tzinfo = datetime .timezone .utc
323- ),
324- "sysStatus" : raw ["SYSSTATUS" ],
325- "stateOfCharge" : int (raw ["SOC" ]),
326- "production" : {
327- "solar" : int (raw ["POWER_PV_S1" ])
328- + int (raw ["POWER_PV_S2" ])
329- + int (raw ["POWER_PV_S3" ]),
330- "add" : - (
331- int (raw ["PM" + strPmIndex + "_L1" ])
332- + int (raw ["PM" + strPmIndex + "_L2" ])
333- + int (raw ["PM" + strPmIndex + "_L3" ])
334- ),
335- "grid" : int (raw ["POWER_LM_L1" ])
336- + int (raw ["POWER_LM_L2" ])
337- + int (raw ["POWER_LM_L3" ]),
338- },
339- "consumption" : {
340- "battery" : int (raw ["POWER_BAT" ]),
341- "house" : int (raw ["POWER_C_L1" ])
342- + int (raw ["POWER_C_L2" ])
343- + int (raw ["POWER_C_L3" ]),
344- "wallbox" : int (raw ["POWER_WALLBOX" ]),
345- },
346- }
347-
348- self .lastRequest = outObj
349- self .lastRequestTime = time .time ()
350-
351- return outObj
352-
353- def poll_rscp (self , keepAlive = False ):
193+ def poll (self , keepAlive = False ):
354194 """Polls via rscp protocol locally.
355195
356196 Args:
@@ -376,12 +216,6 @@ def poll_rscp(self, keepAlive=False):
376216 "time": <datetime object containing the timestamp>
377217 }
378218 """
379- if (
380- self .lastRequest is not None
381- and (time .time () - self .lastRequestTime ) < REQUEST_INTERVAL_SEC_LOCAL
382- ):
383- return self .lastRequest
384-
385219 ts = self .sendRequestTag (RscpTag .INFO_REQ_UTC_TIME , keepAlive = True )
386220 soc = self .sendRequestTag (RscpTag .EMS_REQ_BAT_SOC , keepAlive = True )
387221 solar = self .sendRequestTag (RscpTag .EMS_REQ_POWER_PV , keepAlive = True )
@@ -405,8 +239,6 @@ def poll_rscp(self, keepAlive=False):
405239 ),
406240 }
407241
408- self .lastRequest = outObj
409- self .lastRequestTime = time .time ()
410242 return outObj
411243
412244 def poll_switches (self , keepAlive = False ):
0 commit comments