1
1
"""Update coordinator for TAURON sensors."""
2
2
import datetime
3
3
import logging
4
- import re
5
4
import ssl
5
+ import re
6
6
from typing import Optional , Tuple
7
7
8
8
import requests
9
- from requests import adapters
9
+ from requests import adapters , Response , Session
10
10
from urllib3 import poolmanager
11
11
12
- from .const import (CONST_DATE_FORMAT , CONST_MAX_LOOKUP_RANGE , CONST_REQUEST_HEADERS , CONST_URL_ENERGY , CONST_URL_LOGIN ,
13
- CONST_URL_READINGS , CONST_URL_SELECT_METER , CONST_URL_SERVICE )
12
+ from .const import (CONST_DATE_FORMAT , CONST_MAX_LOOKUP_RANGE , CONST_REQUEST_HEADERS , CONST_URL_ENERGY ,
13
+ CONST_URL_ENERGY_BUSINESS , CONST_URL_LOGIN , CONST_URL_LOGIN_MOJ_TAURON , CONST_URL_READINGS ,
14
+ CONST_URL_SELECT_METER , CONST_URL_SERVICE , CONST_URL_SERVICE_MOJ_TAURON )
14
15
15
16
_LOGGER = logging .getLogger (__name__ )
16
17
@@ -36,6 +37,8 @@ def __init__(self):
36
37
self .tariff = None
37
38
self .consumption : Optional [TauronAmiplusDataSet ] = None
38
39
self .generation : Optional [TauronAmiplusDataSet ] = None
40
+ self .amount_value : Optional [float ] = None
41
+ self .amount_status : Optional [str ] = None
39
42
40
43
def data_unavailable (self ):
41
44
return self .consumption is None or self .generation is None
@@ -98,6 +101,7 @@ def __init__(self, username, password, meter_id, show_generation=False, show_12_
98
101
self .username = username
99
102
self .password = password
100
103
self .meter_id = meter_id
104
+ self .is_business = False
101
105
self .meters = []
102
106
self .show_generation = show_generation
103
107
self .show_12_months = show_12_months
@@ -110,15 +114,16 @@ def __init__(self, username, password, meter_id, show_generation=False, show_12_
110
114
111
115
def get_raw_data (self ) -> TauronAmiplusRawData :
112
116
data = TauronAmiplusRawData ()
113
- self .login ()
117
+ # amount_value, amount_status = self.get_moj_tauron()
118
+ # data.amount_value = amount_value
119
+ # data.amount_status = amount_status
120
+ data .tariff = self .login ()
114
121
generation_max_cache = datetime .datetime .now ()
115
122
data .consumption , consumption_max_cache = self .get_data_set (generation = False )
116
123
if self .show_generation or self .show_balanced :
117
124
data .generation , generation_max_cache = self .get_data_set (generation = True )
118
125
else :
119
126
data .generation = TauronAmiplusDataSet ()
120
- if data .consumption .json_yearly is not None :
121
- data .tariff = data .consumption .json_yearly ["data" ]["tariff" ]
122
127
self ._cache .delete_older_than (min (consumption_max_cache , generation_max_cache ))
123
128
return data
124
129
@@ -149,68 +154,77 @@ def get_data_set(self, generation) -> Tuple[TauronAmiplusDataSet, datetime.datet
149
154
cache_max = potential_max
150
155
return dataset , cache_max
151
156
152
- def login (self ) :
157
+ def login_service (self , login_url : str , service : str ) -> tuple [ Session , Response ] :
153
158
payload_login = {
154
159
"username" : self .username ,
155
160
"password" : self .password ,
156
- "service" : CONST_URL_SERVICE ,
161
+ "service" : service ,
157
162
}
158
163
session = requests .session ()
159
164
session .mount ("https://" , TLSAdapter ())
160
- self .log ("Logging in..." )
161
- session .request (
165
+ self .log (f "Logging in... ( { service } ) " )
166
+ r1 = session .request (
162
167
"POST" ,
163
- CONST_URL_LOGIN ,
168
+ login_url ,
164
169
data = payload_login ,
165
170
headers = CONST_REQUEST_HEADERS ,
166
171
)
172
+ if "Przekroczono maksymalną liczbę logowań." in r1 .text :
173
+ self .log ("Too many login attempts" )
174
+ raise Exception ("Too many login attempts" )
167
175
r2 = session .request (
168
176
"POST" ,
169
- CONST_URL_LOGIN ,
177
+ login_url ,
170
178
data = payload_login ,
171
179
headers = CONST_REQUEST_HEADERS ,
172
180
)
181
+ if "Przekroczono maksymalną liczbę logowań." in r2 .text :
182
+ self .log ("Too many login attempts" )
183
+ raise Exception ("Too many login attempts" )
173
184
if "Login lub hasło są nieprawidłowe." in r2 .text :
174
185
self .log ("Invalid credentials" )
175
186
raise Exception ("Invalid credentials" )
176
- if self .username not in r2 .text :
187
+ if ( self .username not in r2 .text ) and ( self . username . upper () not in r2 . text ) :
177
188
self .log ("Failed to login" )
178
189
raise Exception ("Failed to login" )
190
+ return session , r2
191
+
192
+ def login (self ):
193
+ session , login_response = self .login_service (CONST_URL_LOGIN , CONST_URL_SERVICE )
194
+ self .session = session
179
195
self .log ("Logged in." )
180
- self .meters = self ._get_meters (r2 .text )
196
+ self .meters = self ._get_meters (login_response .text )
181
197
payload_select_meter = {"site[client]" : self .meter_id }
198
+ selected_meter_info = list (filter (lambda m : m ["meter_id" ] == self .meter_id , self .meters ))
199
+ if len (selected_meter_info ) > 0 :
200
+ self .is_business = selected_meter_info [0 ]["meter_type" ] == "WO"
201
+ else :
202
+ self .is_business = False
182
203
self .log (f"Selecting meter: { self .meter_id } " )
183
- session .request ("POST" , CONST_URL_SELECT_METER , data = payload_select_meter , headers = CONST_REQUEST_HEADERS )
184
- self .session = session
204
+ select_response = self .session .request ("POST" , CONST_URL_SELECT_METER , data = payload_select_meter , headers = CONST_REQUEST_HEADERS )
205
+ tariff_search = re .findall (r"'Tariff' : '(.*)'," , select_response .text )
206
+ if len (tariff_search ) > 0 :
207
+ tariff = tariff_search [0 ]
208
+ return tariff
209
+ return "unknown"
185
210
186
211
@staticmethod
187
- def _get_meters (text ) :
212
+ def _get_meters (text : str ) -> list :
188
213
regex = r".*data-data='{\"type\": \".*\"}'>.*"
189
214
matches = list (re .finditer (regex , text ))
190
215
meters = []
191
216
for match in matches :
192
217
m1 = re .match (r".*value=\"([\d\_]+)\".*" , match .group ())
193
218
m2 = re .match (r".*\"}'>(.*)</option>" , match .group ())
194
- if m1 is None or m2 is None :
219
+ m3 = re .match (r".*data-data='{\"type\": \"(.*)\"}'>.*" , match .group ())
220
+ if m1 is None or m2 is None or m3 is None :
195
221
continue
196
222
meter_id = m1 .groups ()[0 ]
197
223
display_name = m2 .groups ()[0 ]
198
- meters .append ({"meter_id" : meter_id , "meter_name" : display_name })
224
+ meter_type = m3 .groups ()[0 ]
225
+ meters .append ({"meter_id" : meter_id , "meter_name" : display_name , "meter_type" : meter_type })
199
226
return meters
200
227
201
- def calculate_configuration (self , days_before = 2 , throw_on_empty = True ):
202
- self .log ("Calculating configuration..." )
203
- json_data , _ = self .get_raw_values_daily (days_before , generation = False )
204
- if json_data is None :
205
- self .log ("Failed to calculate configuration" )
206
- if throw_on_empty :
207
- raise Exception ("Failed to login" )
208
- else :
209
- return None
210
- tariff = json_data ["data" ]["tariff" ]
211
- self .log (f"Calculated configuration: { tariff } " )
212
- return tariff
213
-
214
228
def get_values_yearly (self , generation ):
215
229
now = datetime .datetime .now ()
216
230
first_day_of_year = now .replace (day = 1 , month = 1 )
@@ -220,6 +234,7 @@ def get_values_yearly(self, generation):
220
234
"to" : TauronAmiplusConnector .format_date (last_day_of_year ),
221
235
"profile" : "year" ,
222
236
"type" : "oze" if generation else "consum" ,
237
+ "energy" : 2 if generation else 1 ,
223
238
}
224
239
self .log (f"Downloading yearly data for year: { now .year } , generation: { generation } " )
225
240
values = self .get_chart_values (payload )
@@ -240,6 +255,7 @@ def get_values_monthly(self, generation):
240
255
"to" : TauronAmiplusConnector .format_date (last_day_of_month ),
241
256
"profile" : "month" ,
242
257
"type" : "oze" if generation else "consum" ,
258
+ "energy" : 2 if generation else 1 ,
243
259
}
244
260
values = self .get_chart_values (payload )
245
261
if values is not None :
@@ -293,7 +309,8 @@ def get_raw_values_daily_for_range(self, day_from: datetime.date, day_to: dateti
293
309
data ["data" ]["allData" ].extend (day_data ["data" ]["allData" ])
294
310
data ["data" ]["sum" ] += day_data ["data" ]["sum" ]
295
311
data ["data" ]["zonesName" ] = day_data ["data" ]["zonesName" ]
296
- data ["data" ]["tariff" ] = day_data ["data" ]["tariff" ]
312
+ if "tariff" in day_data ["data" ]:
313
+ data ["data" ]["tariff" ] = day_data ["data" ]["tariff" ]
297
314
for z , v in day_data ["data" ]["zones" ].items ():
298
315
if z in data ["data" ]["zones" ]:
299
316
data ["data" ]["zones" ][z ] += v
@@ -316,6 +333,7 @@ def get_raw_values_daily_for_day(self, day, generation):
316
333
"to" : day_str ,
317
334
"profile" : "full time" ,
318
335
"type" : "oze" if generation else "consum" ,
336
+ "energy" : 2 if generation else 1 ,
319
337
}
320
338
self .log (f"Downloading daily data for day: { day_str } , generation: { generation } " )
321
339
values = self .get_chart_values (payload )
@@ -346,15 +364,20 @@ def get_reading(self, generation):
346
364
return post
347
365
348
366
def get_chart_values (self , payload ):
349
- return self .execute_post (CONST_URL_ENERGY , payload )
367
+ return self .execute_post (CONST_URL_ENERGY_BUSINESS if self . is_business else CONST_URL_ENERGY , payload )
350
368
351
369
def execute_post (self , url , payload ):
370
+ self .log (f"EXECUTING: { url } with payload: { payload } " )
352
371
response = self .session .request (
353
372
"POST" ,
354
373
url ,
355
374
data = payload ,
356
375
headers = CONST_REQUEST_HEADERS ,
357
376
)
377
+ self .log (f"RESPONSE: { response .text } " )
378
+ if "Przekroczono maksymalną liczbę logowań." in response .text :
379
+ self .log ("Too many login attempts" )
380
+ raise Exception ("Too many login attempts" )
358
381
if response .status_code == 200 and response .text .startswith ('{"success":true' ):
359
382
json_data = response .json ()
360
383
return json_data
@@ -363,6 +386,41 @@ def execute_post(self, url, payload):
363
386
def log (self , msg ):
364
387
_LOGGER .debug (f"[{ self .meter_id } ]: { msg } " )
365
388
389
+ def get_moj_tauron (self ):
390
+ session , response = self .login_service (CONST_URL_LOGIN_MOJ_TAURON , CONST_URL_SERVICE_MOJ_TAURON )
391
+
392
+ if response is None :
393
+ return None , "unknown"
394
+ find_1_1 = re .findall (r".*class=\"amount-value\".*" , response .text )
395
+ find_2_1 = re .findall (r".*class=\"amount-status\".*" , response .text )
396
+ if len (find_1_1 ) > 0 and len (find_2_1 ) > 0 :
397
+ amount_value = float (
398
+ find_1_1 [0 ].strip ()
399
+ .replace ("<span class=\" amount-value\" >" , "" )
400
+ .replace ("zł" , "" )
401
+ .replace ("</span>" , "" )
402
+ .replace ("," , "." ).strip ())
403
+ amount_status = (find_2_1 [0 ].strip ()
404
+ .replace ("<span class=\" amount-status\" >" , "" )
405
+ .replace ("</span>" , "" ).strip ())
406
+ return amount_value , amount_status
407
+
408
+ find_1_2 = re .findall (r".*class=\"amount\".*\s*.*\s*</div>" , response .text )
409
+ find_2_2 = re .findall (r".*class=\"date\".*" , response .text )
410
+ if len (find_1_2 ) > 0 and len (find_2_2 ) > 0 :
411
+ amount_value = float (
412
+ find_1_2 [0 ].strip ()
413
+ .replace ("<div class=\" amount\" >" , "" )
414
+ .replace ("zł" , "" )
415
+ .replace ("</div>" , "" )
416
+ .replace ("," , "." ).strip ())
417
+ amount_status = (find_2_2 [0 ].strip ()
418
+ .replace ("<div class=\" date\" >" , "" )
419
+ .replace ("</div>" , "" ).strip ())
420
+ return amount_value , amount_status
421
+
422
+ return None , "unknown"
423
+
366
424
@staticmethod
367
425
def format_date (date ):
368
426
return date .strftime (CONST_DATE_FORMAT )
@@ -373,16 +431,15 @@ def get_available_meters(username, password):
373
431
connector .login ()
374
432
if connector .meters is not None and len (connector .meters ) > 0 :
375
433
return connector .meters
376
- raise Exception ("Failed to login " )
434
+ raise Exception ("Failed to retrieve energy meters " )
377
435
378
436
@staticmethod
379
437
def calculate_tariff (username , password , meter_id ):
380
438
connector = TauronAmiplusConnector (username , password , meter_id )
381
- connector .login ()
382
- config = connector .calculate_configuration ()
383
- if config is not None :
384
- return config
385
- raise Exception ("Failed to login" )
439
+ tariff = connector .login ()
440
+ if tariff is not None :
441
+ return tariff
442
+ raise Exception ("Failed to calculate configuration" )
386
443
387
444
@staticmethod
388
445
def add_all_data (data : dict , date ):
0 commit comments