Skip to content
This repository has been archived by the owner on Jun 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #74 from ReagentX/feat/cs/get_historical_start_date
Browse files Browse the repository at this point in the history
Feat/cs/get historical start date
  • Loading branch information
ReagentX authored Feb 14, 2021
2 parents df0d7cd + 7cab34a commit 0636de2
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 22 deletions.
4 changes: 3 additions & 1 deletion docs/api/channel_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion docs/api/sensor_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
12 changes: 6 additions & 6 deletions purpleair/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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: 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
"""
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion purpleair/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion purpleair/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
Expand Down
4 changes: 2 additions & 2 deletions scripts/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@

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",
author='Christopher Sardegna',
author_email='[email protected]',
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',
Expand Down
16 changes: 8 additions & 8 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down

0 comments on commit 0636de2

Please sign in to comment.