From 323bb568117a335939ce6fbe3057cb4672a0fb32 Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 11:47:52 -0500 Subject: [PATCH 1/7] Fix #70 --- purpleair/network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/purpleair/network.py b/purpleair/network.py index d40e86d..74c4237 100644 --- a/purpleair/network.py +++ b/purpleair/network.py @@ -70,8 +70,9 @@ def parse_raw_result(self, flat_sensor_data: dict) -> None: parent_sensor_id = child_map[child_sensor_id]['ParentID'] if parent_sensor_id not in parent_map: # pylint: disable=line-too-long - raise ValueError( + print( f'Child {child_sensor_id} lists parent {parent_sensor_id}, but parent does not exist!') + continue channels = [ parent_map[parent_sensor_id], child_map[child_sensor_id] From 954e325d2623aef69eafa5e7d006fbd152c48a89 Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 11:48:05 -0500 Subject: [PATCH 2/7] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 329b737..85de957 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name='purpleair', - version='1.2.2', + version='1.2.3', description='Python API Client to get and transform PurpleAir data.', long_description=LONG_DESCRIPTION, long_description_content_type="text/markdown", From 898ac1b8a70462dafcf2b789c36300f58866593a Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 11:48:18 -0500 Subject: [PATCH 3/7] Support #71 --- purpleair/channel.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/purpleair/channel.py b/purpleair/channel.py index 6705802..1e3e181 100644 --- a/purpleair/channel.py +++ b/purpleair/channel.py @@ -152,7 +152,8 @@ def setup(self) -> None: def get_historical(self, weeks_to_get: int, - thingspeak_field: str) -> pd.DataFrame: + thingspeak_field: str, + start_date: Optional[datetime] = datetime.now()) -> pd.DataFrame: """ Get data from the ThingSpeak API one week at a time up to weeks_to_get weeks in the past """ @@ -173,17 +174,16 @@ def get_historical(self, child_cols = CHILD_PRIMARY_COLS if thingspeak_field == 'primary' else CHILD_SECONDARY_COLS columns = parent_cols if self.type == 'parent' else child_cols - from_week = datetime.now() - to_week = from_week - timedelta(weeks=1) + to_week = start_date - timedelta(weeks=1) # pylint: disable=line-too-long - url = f'https://thingspeak.com/channels/{channel}/feed.csv?api_key={key}&offset=0&average=&round=2&start={to_week.strftime("%Y-%m-%d")}%2000:00:00&end={from_week.strftime("%Y-%m-%d")}%2000:00:00' + url = f'https://thingspeak.com/channels/{channel}/feed.csv?api_key={key}&offset=0&average=&round=2&start={to_week.strftime("%Y-%m-%d")}%2000:00:00&end={start_date.strftime("%Y-%m-%d")}%2000:00:00' weekly_data = pd.read_csv(url) if weeks_to_get > 1: for _ in range(weeks_to_get): - from_week = to_week # DateTimes are immutable so this reference is not a problem + start_date = to_week # DateTimes are immutable so this reference is not a problem to_week = to_week - timedelta(weeks=1) # pylint: disable=line-too-long - url = f'https://thingspeak.com/channels/{channel}/feed.csv?api_key={key}&offset=0&average=&round=2&start={to_week.strftime("%Y-%m-%d")}%2000:00:00&end={from_week.strftime("%Y-%m-%d")}%2000:00:00' + url = f'https://thingspeak.com/channels/{channel}/feed.csv?api_key={key}&offset=0&average=&round=2&start={to_week.strftime("%Y-%m-%d")}%2000:00:00&end={start_date.strftime("%Y-%m-%d")}%2000:00:00' weekly_data = pd.concat([weekly_data, pd.read_csv(url)]) # Handle formatting the DataFrame From f19d7d3165818df8b8c5dcde1a9a3fc2ed74e331 Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 11:48:26 -0500 Subject: [PATCH 4/7] Update docs for #71 --- docs/api/channel_methods.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/channel_methods.md b/docs/api/channel_methods.md index 7c4ad2f..be41992 100644 --- a/docs/api/channel_methods.md +++ b/docs/api/channel_methods.md @@ -117,12 +117,14 @@ The data is shaped like this: } ``` -## `get_historical(weeks_to_get: int, thingspeak_field: str) -> pd.DataFrame` +## `get_historical(weeks_to_get: int, thingspeak_field: str, start_date: Optional[datetime] = None) -> pd.DataFrame` Get data from the ThingSpeak API from field `thingspeak_field` one week at a time up to `weeks_to_get` weeks in the past. `thingspeak_field` is one of `{'primary', 'secondary'}`. +`start_date` is an optional field to supply a start date. `weeks_to_get` is relative to this value. If not set, it defaults to `datetime.now()` + Parent Primary: * `created_at` From 2d859a28f63ab0758fca10ba372b3f7a31215368 Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 12:00:10 -0500 Subject: [PATCH 5/7] Fix #73 --- docs/api/sensor_methods.md | 2 +- purpleair/sensor.py | 2 +- scripts/run.py | 4 ++-- tests/test_sensor.py | 16 ++++++++-------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/api/sensor_methods.md b/docs/api/sensor_methods.md index 90ef1f8..1acbea9 100644 --- a/docs/api/sensor_methods.md +++ b/docs/api/sensor_methods.md @@ -86,7 +86,7 @@ The JSON data contains a `results` array where the 0th index is the parent senso } ``` -## `get_field('field': str)` +## `get_field(field: int)` Gets the ThingSpeak data from `field` for a sensor. Sets the properties `channel_a` and `channel_b` to the data returned by ThingSpeak. diff --git a/purpleair/sensor.py b/purpleair/sensor.py index 94bbde7..480b50e 100644 --- a/purpleair/sensor.py +++ b/purpleair/sensor.py @@ -77,7 +77,7 @@ def get_data(self) -> Optional[list]: f'More than 2 channels found for {self.identifier}') return channel_data - def get_field(self, field) -> None: + def get_field(self, field: int) -> None: """ Gets the thingspeak data for a sensor, setting None if the data is missing """ diff --git a/scripts/run.py b/scripts/run.py index 20b2995..959944d 100644 --- a/scripts/run.py +++ b/scripts/run.py @@ -19,8 +19,8 @@ print(se.parent) print(se.child) print(se.parent.as_flat_dict()) -se.get_field('field3') -se.get_field('field4') +se.get_field(3) +se.get_field(4) print(se.thingspeak_data.keys()) df = se.parent.get_historical(weeks_to_get=1, thingspeak_field='secondary') diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 7ffe2b2..83d8891 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -23,15 +23,15 @@ def test_can_get_field(self): Test that we can get data from the ThingSpeak API """ se = sensor.Sensor(7423, parse_location=True) - se.get_field('field3') - self.assertIn('field3', se.thingspeak_data) - self.assertIn('primary', se.thingspeak_data['field3']) - self.assertIn('feeds', se.thingspeak_data['field3']['primary']['channel_a']) - self.assertIn('feeds', se.thingspeak_data['field3']['primary']['channel_b']) - self.assertIn('feeds', se.thingspeak_data['field3']['secondary']['channel_a']) - self.assertIn('feeds', se.thingspeak_data['field3']['secondary']['channel_b']) + se.get_field(3) + self.assertIn(3, se.thingspeak_data) + self.assertIn('primary', se.thingspeak_data[3]) + self.assertIn('feeds', se.thingspeak_data[3]['primary']['channel_a']) + self.assertIn('feeds', se.thingspeak_data[3]['primary']['channel_b']) + self.assertIn('feeds', se.thingspeak_data[3]['secondary']['channel_a']) + self.assertIn('feeds', se.thingspeak_data[3]['secondary']['channel_b']) self.assertGreater( - len(se.thingspeak_data['field3']['primary']['channel_a']['feeds']), + len(se.thingspeak_data[3]['primary']['channel_a']['feeds']), 0 ) From a3b643e72be0fe95c1100d400211945a7b6e1ce0 Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 12:08:12 -0500 Subject: [PATCH 6/7] Fix types --- purpleair/channel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/purpleair/channel.py b/purpleair/channel.py index 1e3e181..01bffdc 100644 --- a/purpleair/channel.py +++ b/purpleair/channel.py @@ -3,7 +3,7 @@ """ import json -from datetime import datetime, timedelta +from datetime import date, datetime, timedelta from typing import Optional import pandas as pd @@ -153,7 +153,7 @@ def setup(self) -> None: def get_historical(self, weeks_to_get: int, thingspeak_field: str, - start_date: Optional[datetime] = datetime.now()) -> pd.DataFrame: + start_date: datetime = datetime.now()) -> pd.DataFrame: """ Get data from the ThingSpeak API one week at a time up to weeks_to_get weeks in the past """ From 7cab34abb3e1b56537a713b6b84685e0bfc9808f Mon Sep 17 00:00:00 2001 From: Christopher Sardegna Date: Sun, 14 Feb 2021 12:09:28 -0500 Subject: [PATCH 7/7] fix pylint --- purpleair/channel.py | 2 +- setup.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/purpleair/channel.py b/purpleair/channel.py index 01bffdc..51d64ec 100644 --- a/purpleair/channel.py +++ b/purpleair/channel.py @@ -3,7 +3,7 @@ """ import json -from datetime import date, datetime, timedelta +from datetime import datetime, timedelta from typing import Optional import pandas as pd diff --git a/setup.py b/setup.py index 85de957..2eddd42 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,8 @@ author_email='purpleair@reagentx.net', url='https://github.com/ReagentX/purple_air_api/', packages=find_packages(), - install_requires=['requests', 'requests_cache', 'thingspeak', 'geopy', 'pandas'], + install_requires=['requests', 'requests_cache', + 'thingspeak', 'geopy', 'pandas'], python_requires='>=3.6', classifiers=[ 'Development Status :: 5 - Production/Stable',