Skip to content

Commit 2b2aa90

Browse files
authored
Merge pull request #69 from JurgenLB/master
adding Homesdata and Homecoach
2 parents 9f87b57 + f57f5eb commit 2b2aa90

File tree

1 file changed

+178
-6
lines changed

1 file changed

+178
-6
lines changed

lnetatmo.py

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ def getParameter(key, default):
8787
_GETHOMEDATA_REQ = _BASE_URL + "api/gethomedata"
8888
_GETCAMERAPICTURE_REQ = _BASE_URL + "api/getcamerapicture"
8989
_GETEVENTSUNTIL_REQ = _BASE_URL + "api/geteventsuntil"
90-
_HOME_STATUS = _BASE_URL + "api/homestatus" # Used for Home+ Control Devices
91-
90+
_HOME_STATUS = _BASE_URL + "api/homestatus" # Used for Home+ Control Devices
91+
_GETHOMES_DATA = _BASE_URL + "api/homesdata" # New API
92+
_GETHOMECOACH = _BASE_URL + "api/gethomecoachsdata" #
9293

9394
#TODO# Undocumented (but would be very usefull) API : Access currently forbidden (403)
9495

@@ -121,6 +122,59 @@ def getParameter(key, default):
121122
# Not working yet
122123
#_CAM_FTP_ACTIVE = "/command/ftp_set_config?config=on_off:%s" # "on"|"off"
123124

125+
#Known TYPE used by Netatmo services + API, there can be more types possible
126+
TYPES = {
127+
'BFII' : ["Bticino IP Indoor unit", 'Home + Security'],
128+
'BFIC' : ["Bticino IP Guard station", 'Home + Security'],
129+
'BFIO' : ["Bticino IP Entrance panel", 'Home + Security'],
130+
'BFIS' : ["Bticino Server DES", 'Home + Security'],
131+
'BNS' : ["Smarther with Netatmo Thermostat", 'Home+Control'],
132+
'BNCU' : ["Bticino Bticino Alarm Central Unit", 'Home + Security'],
133+
'BNCS' : ["Bticino module Controlled Socket", 'Home+Control'],
134+
'BNCX' : ["Bticino Class 300 EOS", 'Home + Security'],
135+
'BNDL' : ["Bticino Doorlock", 'Home + Security'],
136+
'BNEU' : ["Bticino external unit", 'Home + Security'],
137+
'BNFC' : ["Bticino Thermostat", 'Home+Control'],
138+
'BNMH' : ["Bticino My Home Server 1", 'Home + Security'], # also API Home+Control GATEWAY
139+
'BNSE' : ["Bticino Alarm Sensor", 'Home + Security'],
140+
'BNSL' : ["Bticino Staircase Light", 'Home + Security'],
141+
'BNTH' : ["Bticino Thermostat", 'Home+Control'],
142+
'BNTR' : ["Bticino module towel rail", 'Home+Control'],
143+
'BNXM' : ["Bticino X meter", 'Home+Control'],
144+
145+
'NACamera' : ["indoor camera", 'Home + Security'],
146+
'NACamDoorTag' : ["door tag", 'Home + Security'],
147+
'NAMain' : ["weather station", 'Weather'],
148+
'NAModule1' : ["outdoor unit", 'Weather'],
149+
'NAModule2' : ["wind unit", 'Weather'],
150+
'NAModule3' : ["rain unit", 'Weather'],
151+
'NAModule4' : ["indoor unit", 'Weather'],
152+
'NAPlug' : ["thermostat relais station", 'Energy'], # A smart thermostat exist of a thermostat$
153+
# The relais module is also the bridge bet$
154+
'NATherm1' : ["thermostat", 'Energy'],
155+
'NCO' : ["co2 sensor", 'Home + Security'], # The same API as smoke sensor
156+
'NDB' : ["doorbell", 'Home + Security'],
157+
'NOC' : ["outdoor camera", 'Home + Security'],
158+
'NRV' : ["thermostat valves", 'Energy'], # also API Home+Control
159+
'NSD' : ["smoke sensor", 'Home + Security'],
160+
'NHC' : ["home coach", 'Aircare'],
161+
'NIS' : ["indoor sirene", 'Home + Security'],
162+
163+
'NLC' : ["Cable Outlet", 'Home+Control'],
164+
'NLE' : ["Ecometer", 'Home+Control'],
165+
'NLG' : ["Gateway", 'Home+Control'],
166+
'NLGS' : ["Standard DIN Gateway", 'Home+Control'],
167+
'NLP' : ["Power Outlet", 'Home+Control'],
168+
'NLPC' : ["DIN Energy meter", 'Home+Control'],
169+
'NLPD' : ["Dry contact", 'Home+Control'],
170+
'NLPM' : ["Mobile Socket", 'Home+Control'],
171+
'NLPO' : ["Contactor", 'Home+Control'],
172+
'NLPT' : ["Teleruptor", 'Home+Control'],
173+
174+
'OTH' : ["Opentherm Thermostat Relay", 'Home+Control'],
175+
'OTM' : ["Smart modulating Thermostat", 'Home+Control']
176+
}
177+
124178
# UNITS used by Netatmo services
125179
UNITS = {
126180
"unit" : {
@@ -138,6 +192,18 @@ def getParameter(key, default):
138192
0: "mbar",
139193
1: "inHg",
140194
2: "mmHg"
195+
},
196+
"Health index" : { # Homecoach
197+
0: "Healthy",
198+
1: "Fine",
199+
2: "Fair",
200+
3: "Poor",
201+
4: "Unhealthy"
202+
},
203+
"Wifi status" : { # Wifi Signal quality
204+
86: "Bad",
205+
71: "Average",
206+
56: "Good"
141207
}
142208
}
143209

@@ -317,11 +383,11 @@ def getThermostat(self, name=None):
317383
else: return
318384
return self.thermostat[self.defaultThermostatId]
319385

320-
def moduleNamesList(self, name=None, tid=None):
386+
def moduleNamesList(self, name=None, tid=None): # ERROR getThermostat() got an unexpected keyword argument 'tid'
321387
thermostat = self.getThermostat(name=name, tid=tid)
322388
return [m['name'] for m in thermostat['modules']] if thermostat else None
323389

324-
def getModuleByName(self, name, thermostatId=None):
390+
def getModuleByName(self, name, thermostatId=None): # ERROR 'NoneType' object is not subscriptable
325391
thermostat = self.getThermostat(tid=thermostatId)
326392
for m in thermostat['modules']:
327393
if m['name'] == name: return m
@@ -792,6 +858,87 @@ class WelcomeData(HomeData):
792858
warnings.warn("The 'WelcomeData' class was renamed 'HomeData' to handle new Netatmo Home capabilities",
793859
DeprecationWarning )
794860
pass
861+
862+
class HomesData:
863+
"""
864+
List the Netatmo actual topology and static information of all devices present
865+
into a user account. It is also possible to specify a home_id to focus on one home.
866+
867+
Args:
868+
authData (clientAuth): Authentication information with a working access Token
869+
home : Home name or id of the home who's module belongs to
870+
"""
871+
def __init__(self, authData, home=None):
872+
#
873+
self.getAuthToken = authData.accessToken
874+
postParams = {
875+
"access_token" : self.getAuthToken,
876+
"home_id": home
877+
}
878+
#
879+
resp = postRequest("Module", _GETHOMES_DATA, postParams)
880+
# self.rawData = resp['body']['devices']
881+
self.rawData = resp['body']['homes']
882+
if not self.rawData : raise NoHome("No home %s found" % home)
883+
#
884+
if home:
885+
# Find a home who's home id or name is the one requested
886+
for h in self.rawData:
887+
#print (h.keys())
888+
if h["name"] == home or h["id"] == home:
889+
self.Homes_Data = h
890+
# print (self.Homes_Data)
891+
if not self.Homes_Data : raise NoDevice("No Devices available")
892+
893+
class HomeCoach:
894+
"""
895+
List the HomeCoach modules
896+
897+
Args:
898+
authData (clientAuth): Authentication information with a working access Token
899+
home : Home name or id of the home who's HomeCoach belongs to
900+
"""
901+
def __init__(self, authData, home=None):
902+
# I don't own a HomeCoach thus I am not able to test the HomeCoach support
903+
904+
# warnings.warn("The HomeCoach code is not tested due to the lack of test environment.\n", RuntimeWarning )
905+
# "As Netatmo is continuously breaking API compatibility, risk that current bindings are wrong is h$
906+
# "Please report found issues (https://github.com/philippelt/netatmo-api-python/issues)"
907+
908+
self.getAuthToken = authData.accessToken
909+
postParams = {
910+
"access_token" : self.getAuthToken
911+
}
912+
resp = postRequest("HomeCoach", _GETHOMECOACH, postParams)
913+
self.rawData = resp['body']['devices']
914+
# homecoach data
915+
if not self.rawData : raise NoDevice("No HomeCoach available")
916+
917+
for i in range(len(self.rawData)):
918+
#
919+
self.HomecoachDevice = self.rawData[i]
920+
# print ('Homecoach = ', self.HomecoachDevice)
921+
# print (' ')
922+
# print ('Homecoach_data = ', self.rawData[i]['dashboard_data'])
923+
# print (' ')
924+
925+
def lastData(self, _id=None, exclude=0):
926+
s = self.HomecoachDevice['dashboard_data']['time_utc']
927+
_id = self.HomecoachDevice['_id']
928+
return {'When':s}, {'_id':_id}
929+
930+
def checkNotUpdated(self, delay=3600):
931+
res = self.lastData()
932+
ret = []
933+
if time.time()-res['When'] > delay : ret.update({_id['_id']: 'Device Not Updated')
934+
return ret if ret else None
935+
936+
def checkUpdated(self, delay=3600):
937+
res = self.lastData()
938+
ret = []
939+
if time.time()-res['When'] < delay : rret.update({_id['_id']: 'Device up-to-date')
940+
return ret if ret else None
941+
795942
# Utilities routines
796943

797944
def rawAPI(authData, url, parameters={}):
@@ -902,17 +1049,30 @@ def getStationMinMaxTH(station=None, module=None, home=None):
9021049
stderr.write("Library source missing identification arguments to check lnetatmo.py (user/password/etc...)")
9031050
exit(1)
9041051

905-
authorization = ClientAuth() # Test authentication method
1052+
authorization = ClientAuth() # Test authentication method
9061053

9071054
try:
9081055
weatherStation = WeatherStationData(authorization) # Test DEVICELIST
9091056
except NoDevice:
9101057
logger.warning("No weather station available for testing")
9111058
else:
912-
weatherStation.MinMaxTH() # Test GETMEASUR
1059+
weatherStation.MinMaxTH() # Test GETMEASUR
9131060

9141061
try:
9151062
homes = HomeData(authorization)
1063+
for k, v in homes.homes.items():
1064+
#print (v)
1065+
C = v.pop('cameras')
1066+
P = v.pop('persons')
1067+
S = v.pop('smokedetectors')
1068+
#
1069+
if C == [] and P == [] and S == []:
1070+
#print (v)
1071+
logger.info("No Cameras, Persons, Smokedetectors found")
1072+
#
1073+
else:
1074+
homeid = k
1075+
#
9161076
except NoDevice :
9171077
logger.warning("No home available for testing")
9181078

@@ -921,6 +1081,18 @@ def getStationMinMaxTH(station=None, module=None, home=None):
9211081
except NoDevice:
9221082
logger.warning("No thermostat avaible for testing")
9231083

1084+
try:
1085+
# homesdata = lnetatmo.HomesData(authorization)
1086+
# ERROR ; Your current token scope do not allow access to Module ? - No Home ID given !
1087+
homesdata = HomesData(authorization, homeid)
1088+
except NoDevice:
1089+
logger.warning("No HomesData avaible for testing")
1090+
1091+
try:
1092+
Homecoach = HomeCoach(authorization)
1093+
except NoDevice:
1094+
logger.warning("No HomeCoach avaible for testing")
1095+
9241096
# If we reach this line, all is OK
9251097
logger.info("OK")
9261098

0 commit comments

Comments
 (0)