Skip to content

Commit 85b075b

Browse files
committed
Improved credentials handling to ease library upgrade
1 parent a8178cc commit 85b075b

7 files changed

Lines changed: 764 additions & 31 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ dist/
55

66
lnetatmo.egg-info/
77

8-
*.pyc
8+
*.pyc
9+
10+
__pycache__/

.netatmo.credentials

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"CLIENT_ID" : "",
3+
"CLIENT_SECRET" : "",
4+
"USERNAME" : "",
5+
"PASSWORD" : ""
6+
}
7+

LICENSE.txt

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,3 @@ Depending on your permissions you might be required to use sudo.
1717
Once installed you can simple add latmo to your python scripts by including:
1818

1919
import lnetatmo
20-
21-
### Note ###
22-
23-
this release is an interim release waiting for Netatmo dashboard finalization. As any work in progress, it can stop to work at any time if serious changes occurs.

lnetatmo.py

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Published Jan 2013
22
# Revised Jan 2014 (to add new modules data)
3-
# Author : Philippe Larduinat, philippelt@users.sourceforge.net
4-
# Public domain source code
3+
# Revised 2016 (to add camera support)
4+
# Author : Philippe Larduinat, ph.larduinat@wanadoo.fr
5+
# Multiple contributors : see https://github.com/philippelt/netatmo-api-python
6+
# License : GPL V3
57
"""
68
This API provides access to the Netatmo weather station or/and the Welcome camera
79
This package can be used with Python2 or Python3 applications and do not
@@ -11,6 +13,8 @@
1113
coding=utf-8
1214
"""
1315
from sys import version_info
16+
from os import getenv
17+
from os.path import expanduser, exists
1418
import json, time
1519
import imghdr
1620
import warnings
@@ -22,29 +26,59 @@
2226
from urllib import urlencode
2327
import urllib2
2428

25-
######################## USER SPECIFIC INFORMATION ######################
29+
######################## AUTHENTICATION INFORMATION ######################
2630

2731
# To be able to have a program accessing your netatmo data, you have to register your program as
2832
# a Netatmo app in your Netatmo account. All you have to do is to give it a name (whatever) and you will be
2933
# returned a client_id and secret that your app has to supply to access netatmo servers.
3034

31-
_CLIENT_ID = "" # Your client ID from Netatmo app registration at http://dev.netatmo.com/dev/listapps
32-
_CLIENT_SECRET = "" # Your client app secret ' '
33-
_USERNAME = "" # Your netatmo account username
34-
_PASSWORD = "" # Your netatmo account password
35+
# To ease Docker packaging of your application, you can setup your authentication parameters through env variables
36+
37+
# Authentication use :
38+
# 1 - Values hard coded in the library
39+
# 2 - The .netatmo.credentials file in JSON format in your home directory
40+
# 3 - Values defined in environment variables : CLIENT_ID, CLIENT_SECRET, USERNAME, PASSWORD
41+
42+
# Each level override values defined in the previous level. You could define CLIENT_ID and CLIENT_SECRET hard coded in the library
43+
# and username/password in .netatmo.credentials or environment variables
44+
45+
cred = { # You can hard code authentication information in the following lines
46+
"CLIENT_ID" : "", # Your client ID from Netatmo app registration at http://dev.netatmo.com/dev/listapps
47+
"CLIENT_SECRET" : "", # Your client app secret ' '
48+
"USERNAME" : "", # Your netatmo account username
49+
"PASSWORD" : "" # Your netatmo account password
50+
}
51+
52+
# Other authentication setup management (optionals)
53+
54+
CREDENTIALS = expanduser("~/.netatmo.credentials")
55+
56+
def getParameter(key, default):
57+
return getenv(key, default[key])
58+
59+
# 2 : Override hard coded values with credentials file if any
60+
if exists(CREDENTIALS) :
61+
with open(CREDENTIALS, "r") as f: cred = json.loads(f.read())
62+
63+
# 3 : Override final value with content of env variables if defined
64+
_CLIENT_ID = getParameter("CLIENT_ID", cred)
65+
_CLIENT_SECRET = getParameter("CLIENT_SECRET", cred)
66+
_USERNAME = getParameter("USERNAME", cred)
67+
_PASSWORD = getParameter("PASSWORD", cred)
3568

3669
#########################################################################
3770

3871

3972
# Common definitions
4073

41-
_BASE_URL = "https://api.netatmo.com/"
42-
_AUTH_REQ = _BASE_URL + "oauth2/token"
43-
_GETMEASURE_REQ = _BASE_URL + "api/getmeasure"
44-
_GETSTATIONDATA_REQ = _BASE_URL + "api/getstationsdata"
45-
_GETHOMEDATA_REQ = _BASE_URL + "api/gethomedata"
74+
_BASE_URL = "https://api.netatmo.com/"
75+
_AUTH_REQ = _BASE_URL + "oauth2/token"
76+
_GETMEASURE_REQ = _BASE_URL + "api/getmeasure"
77+
_GETSTATIONDATA_REQ = _BASE_URL + "api/getstationsdata"
78+
_GETHOMEDATA_REQ = _BASE_URL + "api/gethomedata"
4679
_GETCAMERAPICTURE_REQ = _BASE_URL + "api/getcamerapicture"
47-
_GETEVENTSUNTIL_REQ = _BASE_URL + "api/geteventsuntil"
80+
_GETEVENTSUNTIL_REQ = _BASE_URL + "api/geteventsuntil"
81+
4882

4983

5084
class NoDevice( Exception ):
@@ -72,6 +106,7 @@ def __init__(self, clientId=_CLIENT_ID,
72106
username=_USERNAME,
73107
password=_PASSWORD,
74108
scope="read_station"):
109+
75110
postParams = {
76111
"grant_type" : "password",
77112
"client_id" : clientId,
@@ -166,7 +201,7 @@ def moduleByName(self, module, station=None):
166201
for m in self.modules:
167202
mod = self.modules[m]
168203
if mod['module_name'] == module :
169-
if not s or mod['main_device'] == s['_id'] : return mod
204+
return mod
170205
return None
171206

172207
def moduleById(self, mid, sid=None):
@@ -548,6 +583,7 @@ def getStationMinMaxTH(station=None, module=None):
548583
result.extend(devList.MinMaxTH(station, mname))
549584
return result
550585

586+
551587
# auto-test when executed directly
552588

553589
if __name__ == "__main__":

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[metadata]
2+
description-file = README.md
3+

usage.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Python Netatmo API programmers guide
99
1010
>2016-06-25 Update documentation for Netatmo Welcome
1111
12+
>2017-01-09 Minor updates to packaging info
1213
1314
No additional library other than standard Python library is required.
1415

@@ -34,26 +35,41 @@ In the netatmo philosophy, both the application itself and the user have to be r
3435

3536

3637

37-
### 2 Setup your library ###
38+
### 2 Setup your authentication information ###
3839

3940

4041

4142
Copy the lnetatmo.py file in your work directory (or your platform choice of user libraries or virtualenv or ...).
4243

43-
To ease future uses, I suggest that you hardcode in the library your application and user credentials. This is not mandatory as this parameters can be explicitly passed at authentication phase but will save you parameters each time you write a new tool.
44-
45-
If you want to do it, just edit the source file and hard code required values for :
46-
44+
Authentication data can be supplied with 4 different methods :
4745

46+
1. Some or all values can be hard coded in the library source (and default to empty strings). If you use this method, you are back to the initial suggested method. It would be nice to switch to other methods to isolate credentials and ease library upgrades.
47+
2. Some or all values can be overriden in a ~/.netatmo.credentials file containing the keys in JSON format
48+
```bash
49+
$ cat .netatmo.credentials # Here all values are defined but it is not mandatory
50+
{
51+
"CLIENT_ID" : "`xxx",
52+
"CLIENT_SECRET" : "xxx",
53+
"USERNAME" : "xxx",
54+
"PASSWORD" : "xxx"
55+
}
56+
$
57+
```
58+
3. Some or all values can be overriden by environment variables. This is the easiest method if your are packaging your application with Docker.
59+
```bash
60+
$ export USERNAME=newUsername
61+
$ export PASSWORD=password
62+
$ python3 MyCodeUsingLnetatmo.py
63+
...
64+
```
65+
4. Some or all values can be overriden by explicit call to initializer of ClientAuth class
4866
```python
49-
_CLIENT_ID = "<your client_id>"
50-
_CLIENT_SECRET = "<your client_secret>"
51-
_USERNAME = "<netatmo username>"
52-
_PASSWORD = "<netatmo user password>"
67+
# Example: CLIENT_ID and CLIENT_SECRET supposed to be defined by one of the previous methods
68+
authData = lnetatmo.ClientAuth( username="newUsername",
69+
password="password" )
5370
```
5471
55-
56-
If you provide all the values, you can test that everything is working properly by simply running the package as a standalone program.
72+
If you provide all the values, using any method or mix except 4, you can test that everything is working properly by simply running the package as a standalone program.
5773
5874
This will run a full access test to the account and stations and return 0 as return code if everything works well. If run interactively, it will also display an OK message.
5975
@@ -65,7 +81,6 @@ $ echo $?
6581
```
6682
6783
68-
6984
### 3 Package guide ###
7085
7186

0 commit comments

Comments
 (0)