Coverage for src\tempstick_py\tempstick.py: 82%
88 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-09-11 22:38 -0700
« prev ^ index » next coverage.py v6.4.4, created at 2022-09-11 22:38 -0700
1from datetime import datetime
2import json
3from urllib.error import HTTPError
4import requests
6from benedict import benedict
8from furl import furl
10from .exceptions import FilterRemovesRange, InvalidApiKeyError
12from ._helpers import format_mac, format_datetime, set_attr_from_dict
14GET_SENSORS = "/api/v1/sensors/all"
15GET_SENSOR = "/api/v1/sensors/{}"
16GET_READINGS = "/api/v1/sensors/{}/readings"
17REQUEST_TYPES = [
18 GET_SENSORS,
19 GET_SENSOR,
20 GET_READINGS,
21]
23import logging
25logger = logging.getLogger(__name__)
28class TempStickSensor:
29 # __slots__ = ("id" "sensor_id", "sensor_name", "sensor_mac_address")
31 def __init__(
32 self,
33 id,
34 sensor_id: str,
35 sensor_name: str = None,
36 sensor_mac_addr: str = None,
37 ) -> None:
38 self.id = id
39 self.sensor_id = sensor_id
40 self.sensor_name = sensor_name
41 try:
42 self.sensor_mac_address = format(sensor_mac_addr)
43 except AttributeError:
44 self.sensor_mac_address = None
46 @classmethod
47 def from_get_sensor(cls, sensor: dict):
48 set_attr_from_dict(cls, sensor)
50 return cls
52 @classmethod
53 def get_sensors(cls, api_key: str) -> list:
54 """Return list of 'TempStickSensor's given API key."""
55 data = make_request(GET_SENSORS, api_key)
57 data_b = benedict(data)
59 sensors_list = [cls.from_get_sensor(x) for x in data_b.get_list("data.items")]
61 return sensors_list
63 def get_readings(self, api_key: str, filter_cutoff: datetime = None) -> list:
64 """Return list of readings, optionally filtered cutoff date
66 :param filter_cutoff: Filter all readings older than this datetime
67 :type filter_cutoff: datetime, optional
68 """
69 response = make_request(GET_READINGS, api_key, self.sensor_id)
71 print("response: ".format(response))
73 data = response.get("data")
74 readings = data.get("readings")
76 if filter_cutoff:
77 try:
78 filter_cutoff = format_datetime(filter_cutoff)
79 except TypeError:
80 logger.debug(
81 "Filter cutoff already datetime. [{}]".format(filter_cutoff)
82 )
84 start = format_datetime(data.get("start"))
86 length_before = len(readings)
87 if start < filter_cutoff: 87 ↛ 94line 87 didn't jump to line 94, because the condition on line 87 was never false
88 readings = [
89 x
90 for x in readings
91 if format_datetime(x.get("sensor_time")) > filter_cutoff
92 ]
94 length_after = len(readings)
96 if length_after == 0:
97 raise FilterRemovesRange(
98 filter_cutoff,
99 range_lower=start,
100 range_upper=format_datetime(data.get("end")),
101 )
102 elif (diff := length_before - length_after) > 0: 102 ↛ 105line 102 didn't jump to line 105, because the condition on line 102 was never false
103 print("{} readings removed.".format(diff))
105 return readings
107 def get_sensor(self, api_key: str):
108 """Return sensor values."""
109 sensor = make_request(GET_SENSOR, api_key, self.sensor_id)
111 sensor_obj = self.from_get_sensor(sensor)
113 set_attr_from_dict(self, sensor)
115 return self
118def make_request(request_type: REQUEST_TYPES, api_key: str, sensor_id: str = None):
119 url = furl("https://tempstickapi.com")
120 url_adder = furl(request_type.format(sensor_id))
122 print("Adder: {}".format(url_adder))
123 logger.info("Adder: {}".format(url_adder))
125 url.join(url, url_adder)
127 payload = {}
128 headers = {"X-API-KEY": api_key}
130 url_str = url.tostr()
132 print("URL String: {}".format(url_str))
134 response = requests.get(url_str, headers=headers, data=payload)
136 try:
137 response.raise_for_status()
138 response_json = response.json()
140 print("Response Status: {}".format(response.status_code))
141 except HTTPError as http_err:
142 print("HTTP error occured: {}".format(http_err))
143 raise
144 except Exception as err:
145 print("Other error occured: {}".format(err))
146 raise
148 if not isinstance(response_json, dict): 148 ↛ 154line 148 didn't jump to line 154, because the condition on line 148 was never false
149 try:
150 response_json = json.loads(response_json)
151 except ValueError as val_err:
152 print("Could not parse as JSON: {}".format(response_json))
154 response_type = response_json.get("type")
155 if response_type == "error":
156 raise InvalidApiKeyError(response_type, response_json.get("message"))
158 return response_json