Skip to content

Commit fd0f327

Browse files
authored
Merge pull request #39 from joebe975/master
User specific rate limits
2 parents 2331149 + b70b1ea commit fd0f327

File tree

2 files changed

+96
-5
lines changed

2 files changed

+96
-5
lines changed

samples/weather2file

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,30 @@ def valid_datetime_type(arg_datetime_str):
3636
msg = f"Given Date {arg_datetime_str} not valid! Expected format, YYYY-MM-DD_hh:mm!"
3737
raise argparse.ArgumentTypeError(msg)
3838

39+
def valid_hour_limit(hour_limit):
40+
hour_limit = int(hour_limit)
41+
if hour_limit <= 0:
42+
msg = "Hour limit must be larger than 0"
43+
raise argparse.ArgumentTypeError(msg)
44+
elif hour_limit > 500:
45+
msg = "Hour limit cannot be more than 500"
46+
raise argparse.ArgumentTypeError(msg)
47+
48+
return hour_limit
49+
50+
51+
def valid_ten_seconds_limit(ten_sec_limit):
52+
ten_sec_limit = int(ten_sec_limit)
53+
if ten_sec_limit <= 0:
54+
msg = "Ten seconds limit must be larger than 0"
55+
raise argparse.ArgumentTypeError(msg)
56+
elif ten_sec_limit > 50:
57+
msg = "Ten seconds limit cannot be more than 50"
58+
raise argparse.ArgumentTypeError(msg)
59+
60+
return ten_sec_limit
61+
62+
3963
verbose_dict = {
4064
'debug':logging.DEBUG,
4165
'info':logging.INFO,
@@ -270,9 +294,12 @@ class RateLimitHandler:
270294
nr_previous_requests=0):
271295

272296

273-
274297
self._USER_REQUEST_LIMIT_PER_TEN_SECONDS = user_request_limit_per_ten_seconds
275-
self._USER_REQUST_LIMIT_PER_HOUR = user_request_limit_per_hour # Due to the authorization steps
298+
logging.debug(f'Ten second rate limit was set to {user_request_limit_per_ten_seconds}')
299+
300+
self._USER_REQUST_LIMIT_PER_HOUR = user_request_limit_per_hour
301+
logging.debug(f'Hour rate limit was set to {user_request_limit_per_hour}')
302+
276303
self._TEN_SECOND_TIMEDELTA = timedelta(seconds=10)
277304
self._HOUR_TIMEDELTA = timedelta(hours=1)
278305
self._SECOND_TIMEDELTA = timedelta(seconds=1)
@@ -535,6 +562,26 @@ def main():
535562
required=False,
536563
help="Assumes this many previous requests has been done, so that the rate limit is not exceeded (default: 0)")
537564

565+
566+
parser.add_argument(
567+
"-hrl",
568+
"--hour-rate-limit",
569+
type=valid_hour_limit,
570+
default=400,
571+
required=False,
572+
help="Specify the rate limit per hour (default: 400, max: 500)")
573+
574+
575+
576+
parser.add_argument(
577+
"-t",
578+
"--ten-second-rate-limit",
579+
type=valid_ten_seconds_limit,
580+
default=30,
581+
required=False,
582+
help="Specify the rate limit per ten seconds (default: 30, max: 50)")
583+
584+
538585
args = parser.parse_args()
539586

540587

@@ -549,9 +596,10 @@ def main():
549596

550597

551598
# Rate handler to make sure that we don't exceed Netatmos user rate limits
552-
rate_limit_handler = RateLimitHandler(nr_previous_requests=args.previous_requests)
553-
554-
599+
rate_limit_handler = RateLimitHandler(
600+
user_request_limit_per_ten_seconds=args.ten_second_rate_limit,
601+
user_request_limit_per_hour=args.hour_rate_limit,
602+
nr_previous_requests=args.previous_requests)
555603

556604

557605
for station_mac, station_data_overview in rate_limit_handler.get_stations():

samples/weather2file.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# weather2file
2+
The script [weather2file](https://github.com/philippelt/netatmo-api-python/blob/master/samples/weather2file) can be used to save data from [Netatmo](https://www.netatmo.com) to file. The data is extracted through the Netatmo api and is aggregated into a pandas DataFrame which is then saved into one of the possible output formats (-f flag). Each sample/row in the dataframe consists of common columns such as utc_time (int), timestamp (datetime including timezone if supported by output format), type, module_name, module_mac, station_name, station_mac. There are also a number of columns corresponding to the module data such as Temperature, CO2, Humidity, Noise and Pressure. All samples/rows will contain all data columns, however the non-relevant columns (such as pressure for an indoor module) will be set to NaN.
3+
4+
When run, it will check if a data file already exists. If it exists, it will be loaded and only new data will be extracted from Netatmo. It will thus not download duplicates. In case of certain types of errors, it will exit data collection for the current module and save whatever it managed to collect, and then continue with the next module until data has been collected from all modules. This means that even if the data collection fails, you will not have to download that data again, but will continue from whatever data it already has.
5+
6+
The script also handles user specific rate limits such as 50 requests per 10s and 500 requests per hour, by logging the time of the requests and make sure that those are never exceeded by waiting, if necessary. You can specify lower rate limits than the maximum as to not eat up all resources such that other services might not work. This is done with the -hlr flag for the hour limit and the -t flag for the 10 seconds limit. The script does however not keep track of requests between different runs. In such cases, one kan use the -p flag to specify the number of assumed previous requests.
7+
8+
The default name of the output is "weatherdata" followed by the file format ending, but you can change the name with the -n flag. The default output directory is the curent directory. You can change this value with the -o flag (also supports ~).
9+
10+
11+
# How to run
12+
1. Clone or download the repository.
13+
2. Enter credential information according one of the alternatives in [lnetatmo.py](https://github.com/philippelt/netatmo-api-python/blob/master/lnetatmo.py)
14+
3. Enter the directory and run:
15+
```PYTHONPATH=. ./samples/weather2file --format csv``` (change --format if you prefer a different format, and use any of the optional flags)
16+
17+
```sh
18+
$ PYTHONPATH=. ./samples/weather2file -h
19+
usage: weather2file [-h] -f {json,csv,pickle,hdf,feather,parquet,excel} [-e END_DATETIME] [-v {debug,info,warning,error,quiet}] [-n FILE_NAME] [-o OUTPUT_PATH] [-p PREVIOUS_REQUESTS]
20+
[-hrl HOUR_RATE_LIMIT] [-t TEN_SECOND_RATE_LIMIT]
21+
22+
Save historical information for all weather modules from Netatmo to file
23+
24+
optional arguments:
25+
-h, --help show this help message and exit
26+
-f {json,csv,pickle,hdf,feather,parquet,excel}, --format {json,csv,pickle,hdf,feather,parquet,excel}
27+
Format for which the data is to be saved
28+
-e END_DATETIME, --end-datetime END_DATETIME
29+
The end datetime of data to be saved, in the format YYYY-MM-DD_hh:mm (default: now)
30+
-v {debug,info,warning,error,quiet}, --verbose {debug,info,warning,error,quiet}
31+
Verbose level (default: info)
32+
-n FILE_NAME, --file-name FILE_NAME
33+
Name of the output file (default: weatherdata)
34+
-o OUTPUT_PATH, --output-path OUTPUT_PATH
35+
Output location (default: current folder)
36+
-p PREVIOUS_REQUESTS, --previous-requests PREVIOUS_REQUESTS
37+
Assumes this many previous requests has been done, so that the rate limit is not exceeded (default: 0)
38+
-hrl HOUR_RATE_LIMIT, --hour-rate-limit HOUR_RATE_LIMIT
39+
Specify the rate limit per hour (default: 400, max: 500)
40+
-t TEN_SECOND_RATE_LIMIT, --ten-second-rate-limit TEN_SECOND_RATE_LIMIT
41+
Specify the rate limit per ten seconds (default: 30, max: 50)
42+
```
43+

0 commit comments

Comments
 (0)