diff --git a/pcomfortcloud/constants.py b/pcomfortcloud/constants.py index 6e625d7..2eb926a 100644 --- a/pcomfortcloud/constants.py +++ b/pcomfortcloud/constants.py @@ -58,3 +58,11 @@ class NanoeMode(Enum): On = 2 ModeG = 3 All = 4 + +DEFAULT_X_APP_VERSION = "1.12.0" + +MAX_VERSION_AGE = 5 + +SETTING_TOKEN = "token" +SETTING_VERSION = "version" +SETTING_VERSION_DATE = "versionDate" \ No newline at end of file diff --git a/pcomfortcloud/session.py b/pcomfortcloud/session.py index 957a3f2..85bb5bf 100644 --- a/pcomfortcloud/session.py +++ b/pcomfortcloud/session.py @@ -8,8 +8,10 @@ import urllib3 import hashlib + from . import urls from . import constants +from .settings import PanasonicSettings def _validate_response(response): """ Verify that response is OK """ @@ -52,11 +54,13 @@ class Session(object): """ - def __init__(self, username, password, tokenFileName='~/.panasonic-token', raw=False, verifySsl=True): + def __init__(self, username, password, settingsFileName='~/.panasonic-settings', raw=False, verifySsl=True): self._username = username self._password = password - self._tokenFileName = os.path.expanduser(tokenFileName) + self._settings = PanasonicSettings(os.path.expanduser(settingsFileName)) self._vid = None + + self._appVersion = self._settings._version self._groups = None self._devices = None self._deviceIndexer = {} @@ -69,6 +73,9 @@ def __init__(self, username, password, tokenFileName='~/.panasonic-token', raw=F self._verifySsl = os.path.join(os.path.dirname(__file__), "certificatechain.pem") + if self._settings.version_expired: + self._updateAppVersion() + def __enter__(self): self.login() return self @@ -79,10 +86,8 @@ def __exit__(self, exc_type, exc_val, exc_tb): def login(self): """ Login to verisure app api """ - if os.path.exists(self._tokenFileName): - with open(self._tokenFileName, 'r') as cookieFile: - self._vid = cookieFile.read().strip() - + if self._settings.token is not None: + self._vid = self._settings.token if self._raw: print("--- token found") try: @@ -93,12 +98,11 @@ def login(self): self._vid = None self._devices = None - os.remove(self._tokenFileName) + self._settings.token = None if self._vid is None: self._create_token() - with open(self._tokenFileName, 'w') as tokenFile: - tokenFile.write(self._vid) + self._settings.token = self._vid self._get_groups() @@ -108,13 +112,28 @@ def logout(self): def _headers(self): return { "X-APP-TYPE": "1", - "X-APP-VERSION": "1.20.0", + "X-APP-VERSION": self._appVersion, "X-User-Authorization": self._vid, "User-Agent": "G-RAC", "Accept": "application/json", "Content-Type": "application/json" } + def _updateAppVersion(self): + + if self._raw: print("--- auto detecting latest app version") + try: + data = requests.get("https://itunes.apple.com/lookup?id=1348640525").json() + version = data['results'][0]['version'] + if version is not None: + if self._raw: print("--- found version: {}".format(version)) + self._appVersion = version + self._settings.version = version + return + except: + pass + if self._raw: print("--- failed to detect app version using version: {}".format(self._appVersion)) + def _create_token(self): response = None diff --git a/pcomfortcloud/settings.py b/pcomfortcloud/settings.py new file mode 100644 index 0000000..f4e44c5 --- /dev/null +++ b/pcomfortcloud/settings.py @@ -0,0 +1,80 @@ +import json +import os +from datetime import date +from packaging import version + +from .constants import ( + SETTING_TOKEN, + SETTING_VERSION, + SETTING_VERSION_DATE, + + DEFAULT_X_APP_VERSION, + MAX_VERSION_AGE +) + +class PanasonicSettings: + + def __init__(self, fileName): + self._fileName = fileName + self._token = None + self._version = None + self._versionDate = None + self._load() + + def _load(self): + if not os.path.exists(self._fileName): + return + try: + with open(self._fileName) as json_file: + data = json.load(json_file) + self._token = data[SETTING_TOKEN] + self._version = data[SETTING_VERSION] + self._versionDate = date.fromisoformat(data[SETTING_VERSION_DATE]) + except: + pass + + def _save(self): + data = {} + data[SETTING_TOKEN] = self._token + data[SETTING_VERSION] = self._version + data[SETTING_VERSION_DATE] = self._versionDate.isoformat() + with open(self._fileName, 'w') as outfile: + json.dump(data, outfile) + + @property + def token(self): + return self._token + + @token.setter + def token(self, value): + if self._token == value: + return + self._token = value + self._save() + + @property + def version(self): + if self._version is None: + return DEFAULT_X_APP_VERSION + return self._version + + @version.setter + def version(self,value): + if value is None: + return + if (self._version is None + or version.parse(self._version) < version.parse(value)): + self._version = value + self._versionDate = date.today() + self._save() + + @property + def version_expired(self): + if self._version is None: + return True + if self._versionDate is None: + return True + delta = date.today() - self._versionDate + if (delta.days < MAX_VERSION_AGE): + return False + return True