diff --git a/obelisk/obeliskclient.py b/obelisk/obeliskclient.py index 367a5ca..4310e4c 100644 --- a/obelisk/obeliskclient.py +++ b/obelisk/obeliskclient.py @@ -13,6 +13,8 @@ class ObeliskError(Exception): pass +class ObeliskDateTimeTypeError(Exception): + pass class ObeliskPrecisions(Enum): MILLISECONDS = 1 @@ -130,3 +132,78 @@ def send_to_obelisk(self, data, refresh_rpt=False): except requests.exceptions.HTTPError as e: logger.error(e) raise ObeliskError("Could not send data to Obelisk.") + + @retry_timeout + def retrieve_last_value_from_obelisk(self, metrics_id, thing_id, refresh_rpt=False): + try: + # Check the need to refresh the rpt token + if refresh_rpt: + if not self._rpt_refresh_token_expire_date or self._rpt_refresh_token_expire_date < datetime.utcnow(): + self.__request_rpt_token() + else: + self.__refresh_rpt_token() + + # Specify necessary request information + headers = {'Content-Type': 'application/json', + 'Authorization': 'Bearer {}'.format(self._rpt_token)} + url = "{}/api/{}/scopes/{}/metrics/{}/events/latest?filter=sourceId%3D{}".format(self._base_url, self._version, self._scope_id, metrics_id,thing_id) + + # The request + resp = requests.get(url, headers=headers, timeout=10) + # In case of issues with the token refresh and retry + if resp.status_code == 403 or resp.status_code == 401: + logger.debug("Requesting/renewing RPT token") + respjson=self.retrieve_last_value_from_obelisk(metrics_id, thing_id, refresh_rpt=True) + else: + resp.raise_for_status() + respjson=resp.json() + + # Return the result + return respjson + + except requests.exceptions.HTTPError as e: + logger.error(e) + raise ObeliskError("Could not retrieve last value for thing {} from Obelisk.".format(thing_id)) + + @retry_timeout + def retrieve_series_from_obelisk(self, metrics_id, thing_id, from_datetime, to_datetime=datetime.now(), refresh_rpt=False): + try: + # first check if the dates are provide in the proper datetime format + if not isinstance(from_datetime,datetime): + raise ObeliskDateTimeTypeError("From date is not of the correct type. Should be datetime.datetime") + else: + FromDateTimestamp=round(from_datetime.timestamp()*1000) + if not isinstance(to_datetime,datetime): + raise ObeliskDateTimeTypeError("To date is not of the correct type. Should be datetime.datetime") + else: + ToDateTimestamp=round(to_datetime.timestamp()*1000) + + # Check the need to refresh the rpt token + if refresh_rpt: + if not self._rpt_refresh_token_expire_date or self._rpt_refresh_token_expire_date < datetime.utcnow(): + self.__request_rpt_token() + else: + self.__refresh_rpt_token() + + # Specify necessary request information + headers = {'Content-Type': 'application/json', + 'Authorization': 'Bearer {}'.format(self._rpt_token)} + + url = "{}/api/{}/scopes/{}/metrics/{}/events?filter=sourceId%3D{}&from={}&to={}".format(self._base_url, self._version, self._scope_id,metrics_id,thing_id,FromDateTimestamp,ToDateTimestamp) + + # The request + resp = requests.get(url, headers=headers, timeout=10) + # In case of issues with the token refresh and retry + if resp.status_code == 403 or resp.status_code == 401: + logger.debug("Requesting/renewing RPT token") + respjson=self.retrieve_series_from_obelisk(metrics_id, thing_id, from_datetime, to_datetime, refresh_rpt=True) + else: + resp.raise_for_status() + respjson=resp.json() + + # Return the result + return respjson + + except requests.exceptions.HTTPError as e: + logger.error(e) + raise ObeliskError("Could not retrieve values for thing {} for the specified period from Obelisk.".format(thing_id))