Created
December 28, 2021 12:46
-
-
Save Barbayar/71ee77906abc7bcad9f38059e6c0c286 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
# import simplejson | |
# import pickle | |
# from dateutil.relativedelta import relativedelta | |
import requests | |
import logging | |
from fake_useragent import UserAgent | |
# ATOME_COOKIE = "atome_cookies.pickle" | |
# ATOME_USER_ID = "atome_user_id.pickle" | |
# ATOME_USER_REFERENCE = "atome_user_reference.pickle" | |
COOKIE_NAME = "PHPSESSID" | |
API_BASE_URI = "https://esoftlink.esoftthings.com" | |
API_ENDPOINT_LOGIN = "/api/user/login.json" | |
API_ENDPOINT_LIVE = "/measure/live.json" | |
API_ENDPOINT_CONSUMPTION = "/consumption.json" | |
LOGIN_URL = API_BASE_URI + API_ENDPOINT_LOGIN | |
DEFAULT_TIMEOUT = 10 | |
MAX_RETRIES = 3 | |
PERIODS_MAP = { | |
'day' | |
} | |
# LOGIN_URL = "https://espace-client-connexion.enedis.fr/auth/UI/Login" | |
# HOST = "https://espace-client-particuliers.enedis.fr/group/espace-particuliers" | |
# DATA_URL = "{}/suivi-de-consommation".format(HOST) | |
# REQ_PART = "lincspartdisplaycdc_WAR_lincspartcdcportlet" | |
# HOURLY = "hourly" | |
# DAILY = "daily" | |
# MONTHLY = "monthly" | |
# YEARLY = "yearly" | |
# _DELTA = 'delta' | |
# _FORMAT = 'format' | |
# _RESSOURCE = 'ressource' | |
# _DURATION = 'duration' | |
# _MAP = { | |
# _DELTA: {HOURLY: 'hours', DAILY: 'days', MONTHLY: 'months', YEARLY: 'years'}, | |
# _FORMAT: {HOURLY: "%H:%M", DAILY: "%d %b", MONTHLY: "%b", YEARLY: "%Y"}, | |
# _RESSOURCE: {HOURLY: 'urlCdcHeure', DAILY: 'urlCdcJour', MONTHLY: 'urlCdcMois', YEARLY: 'urlCdcAn'}, | |
# _DURATION: {HOURLY: 24, DAILY: 30, MONTHLY: 12, YEARLY: None} | |
# } | |
class PyAtomeError(Exception): | |
pass | |
class AtomeClient(object): | |
def __init__(self, username, password, session=None, timeout=None): | |
"""Initialize the client object.""" | |
self.username = username | |
self.password = password | |
self._user_id = None | |
self._user_reference = None | |
self._session = session | |
self._data = {} | |
self._timeout = timeout | |
def login(self): | |
"""Set http session.""" | |
if self._session is None: | |
self._session = requests.session() | |
# adding fake user-agent header | |
self._session.headers.update({'User-agent': str(UserAgent().random)}) | |
return self._login() | |
def _login(self): | |
"""Login to Atome's API.""" | |
payload = {"email": self.username, "plainPassword": self.password} | |
try: | |
req = self._session.post(LOGIN_URL, | |
json=payload, | |
headers={"content-type": "application/json"}, | |
timeout=self._timeout) | |
except OSError: | |
raise PyAtomeError("Can not login to API") | |
if 'PHPSESSID' not in req.cookies: | |
raise PyAtomeError("Login error: Please check your username/password: %s ", str(req.text)) | |
try: | |
response_json = req.json() | |
user_id = str(response_json["id"]) | |
user_reference = response_json["subscriptions"][0]["reference"] | |
self._user_id = user_id | |
self._user_reference = user_reference | |
except (OSError, json.decoder.JSONDecodeError) as e: | |
raise PyAtomeError("Impossible to decode response: \nResponse was: [%s] %s", str(e), str(req.status_code), str(req.text)) | |
return True | |
def _get_live(self, max_retries=0): | |
"""Get live data.""" | |
if max_retries > MAX_RETRIES: | |
raise PyAtomeError("Can't gather proper data. Max retries exceeded.") | |
live_url = ( | |
API_BASE_URI | |
+ "/api/subscription/" | |
+ self._user_id | |
+ "/" | |
+ self._user_reference | |
+ API_ENDPOINT_LIVE | |
) | |
try: | |
req = self._session.get(live_url, | |
timeout=self._timeout, | |
allow_redirects=False) | |
except OSError as e: | |
raise PyAtomeError("Could not access Atome's API: " + str(e)) | |
if req.status_code == 403 or req.status_code == 302: | |
# session is wrong, need to relogin | |
self.login() | |
logging.info("Got 403, relogging (max retries: %s)",str(max_retries)) | |
return self._get_live(max_retries+1) | |
if req.text is "": | |
raise PyAtomeError("No data") | |
try: | |
json_output = req.json() | |
except Exception as e: | |
raise PyAtomeError("Impossible to decode response: " + str(e) + "\nResponse was: " + str(req.text) + "\nStatus was: " + str(req.status_code)) | |
return json_output | |
def _get_consumption(self, period, max_retries=0): | |
"""Get consumption according to period.""" | |
""" Period can be: day, week, month, year""" | |
if period not in ['day','week','month','year']: | |
raise ValueError("Period %s out of range. Shall be either 'day', 'week', 'month' or 'year'." %s) | |
if max_retries > MAX_RETRIES: | |
raise PyAtomeError("Can't gather proper data. Max retries exceeded.") | |
consumption_url = ( | |
API_BASE_URI | |
+ "/api/subscription/" | |
+ self._user_id | |
+ "/" | |
+ self._user_reference | |
+ API_ENDPOINT_CONSUMPTION | |
+ '?period=so' | |
+ period[:1] | |
) | |
try: | |
req = self._session.get(consumption_url, | |
timeout=self._timeout, | |
allow_redirects=False) | |
except OSError as e: | |
raise PyAtomeError("Could not access Atome's API: " + str(e)) | |
if req.status_code == 403 or req.status_code == 302: | |
# session is wrong, need to relogin | |
self.login() | |
logging.info("Got 403, relogging (max retries: %s)",str(max_retries)) | |
return self._get_consumption(max_retries+1) | |
if req.text is "": | |
raise PyAtomeError("No data") | |
try: | |
json_output = req.json() | |
except Exception as e: | |
raise PyAtomeError("Impossible to decode response: " + str(e) + "\nResponse was: " + str(req.text) + "\nStatus was: " + str(req.status_code)) | |
return json_output | |
def get_live(self): | |
"""Get current data.""" | |
return self._get_live() | |
def get_consumption(self,period): | |
"""Get current data.""" | |
return self._get_consumption(period) | |
def close_session(self): | |
"""Close current session.""" | |
self._session.close() | |
self._session = None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment