da die andere Diskussion sehr unübersichtlich geworden ist habe ich heute mal alles wichtige zusamengesucht und erstelle nun ein neues HOWTO.
Bitte hier keine Diskussion beginnen oder Fragen stellen. Das lassen wir in der anderen Diskussion.
Diese findet hier statt: http://homematic-forum.de/forum/viewtop ... &start=100
Ich werde das HOWTO aktuell halten. Für Hinweise bin ich immer dankbar. Ich habe nicht alles neu erstellt sondern mich überall bedient und grösstenteils mit copy-paste zusammengestellt. Vielen Dank an alle die hier dazu beigetragen haben!!
los gehts:
HowTo: Einbindung der Wetterstation NetAtmo
letzte Änderung: 06.01.2016
- Abfrage der Tagesregenwerte angepasst
Voraussetzung:
Wenn ihr auf eurer CCU noch keinen CUx-Daemon installiert habt, müsst ihr das nun erledigen. Hier der Link zum Forum: http://homematic-forum.de/forum/viewtop ... 37&t=15298
Die heruntergeladene Datei könnt ihr über die Homematic WebUI unter Einstellungen - Systemsteuerung - Zusatzsoftware - Datei auswählen und installieren
Nach einem Neustart seht ihr auch dort, dass CUxD installiert ist und könnt über Einstellen die Konfigseite erreichen, diese müsst ihr nun aufrufen
CUxD konfigurieren:
Hier geht ihr nun auf den Reiter Geräte und legt folgende Geräte an:
CUxD Gerätetyp: (90) Universal Wrapper Device
Funktion: Thermostat
Seriennummer: 1 (wenn schon andere Geräte vorhanden sind, bitte im Skript ändern)
Name: NetAtmo Innen
Icon: z.B Temperatursensor Innen
Nach dem Anlegen, wechselt auf die Homematic Oberfläche und klickt Gerät anlernen. Hier findet ihr das Gerät im Posteingang (1), bevor ihr es aber anlegt, ändert noch folgende Eigenschaften:
Mode: TEMP + HUM
WEATHER USE_HMDATAPT: inaktiv (wichtig, sonst werden keine Werte geschrieben)
Zyklische Statusmeldung: aktiv
WEATHER STATISTIC: aktiv, wenn ihr MIN MAX Werte haben wollt 
Wenn das Gerät angelegt ist, kehrt zurück auf die CUxD Oberfläche und legt das Aussenmodul an
CUxD Gerätetyp: (90) Universal Wrapper Device
Funktion: Thermostat
Seriennummer: 2 (wenn schon andere Geräte vorhanden sind, bitte im Skript ändern)
Name: NetAtmo Aussen
Icon: z.B Temperatursensor Aussen
Auch hier wieder folgende Einstellungen ändern:
Mode: TEMP + HUM
WEATHER USE_HMDATAPT: inaktiv (wichtig, sonst werden keine Werte geschrieben)
Zyklische Statusmeldung: aktiv
WEATHER STATISTIC: aktiv, wenn ihr MIN MAX Werte haben wollt
Systemvariable anlegen:
Da die Netatmo nach weitergehende Daten wie Lautstärke und CO2-Wert liefert, brauchten wir zusätzliche Systemvariablen. Legt bitte unter Einstellung - Systemvariable folgendes an:
CO2 Zahl Min:0 Max: 10000 Einheit: ppm Zuordnung: NetAtmo Innen (CUX9002001:1)
Luftdruck Zahl Min:0 Max: 2000 Einheit: mb Zuordnung: NetAtmo Innen (CUX9002001:1)
Sonometer Zahl Min:0 Max: 200 Einheit: dB Zuordnung: NetAtmo Innen (CUX9002001:1)
SyncTime Zeichenkette Zuordnung: NetAtmo Innen (CUX9002001:1)
zusätzlich für den Regensensor (optional):
Regenmenge_1d Zahl Min:0 Max 1000 Einheit: mm Zuordnung: NetAtmo Aussen
Regenmenge_30min Zahl Min:0 Max:1000 Einheit: mm Zuordnung: NetAtmo Aussen
Regen_aktuell Zahl Min:0 Max:1000 Einheit: mm Zuordnung: NetAtmo Aussen
zusätzlich für den Windsensor (optional):
Windrichtung Zahl Min:0 Max 1000 Einheit: ° Zuordnung: NetAtmo Aussen
Windstaerke Zahl Min:0 Max 1000 Einheit: km/h Zuordnung: NetAtmo Aussen
Gustangle Zahl Min:0 Max 1000 Einheit: ° Zuordnung: NetAtmo Aussen
Guststaerke Zahl Min:0 Max 1000 Einheit: km/h Zuordnung: NetAtmo Aussen
NetAtmo API Zugriff:
Meldet euch auf der Entwicklerwebseite von Netatmo: http://dev.netatmo.com/dev/listapps an und legt eine neue App an (Create App) somit erhaltet ihr eure Client ID und euren Client Secret. Diese gut notieren, ihr braucht Sie zur Personalisierung des Skripts!
Modul IDs:
Als nächstes müssen wir die IDs der vorhandenen Module (Innensensor / Aussensensor / Regensensor / Windsensor) herausfinden.
Dazu gibt es zwei Möglichkeiten:
Möglichkeit 1 ("berechnen"):
Innensensor (Hauptstation):
Das ist relativ einfach. Ihr sucht die MAC-Adresse der Station. Ihr findet sie z.B. in den Einstellungen der IOS App.
Diese ist die ID.
übrige Module:
zuerst müsst ihr die Seriennummern suchen. Diese findet ihr auch in den Einstellungen der App.
Aussenmodul: Die ID beginnt mit 02:00:00 dahinter folgen die letzten 6 Ziffern der Seriennummer.
z.B. Seriennummer h123456 --> ID: 02:00:00:12:34:56
Regensensor: Die ID beginnt mit 05:00:00. Rest wie Aussenmodul.
Windsensor: Die ID beginnt mit 06:00:00. Rest wie Aussenmodul.
Möglichkeit 2 (auslesen über Devicelist request):
Den folgenden Code in eine .tcl Datei speichern, Kopf anpassen (clientID, clientSecret, Username, password) auf die CCU kopieren und im Terminalfenster ausführen wie zum Testen der netatmo.tcl Datei (Details wie das geht folgen weiter unten im Abschnitt "Skript anpassen").
Code: Alles auswählen
#!/bin/tclsh
load tclrega.so
#---------------------------------------------------------------------------------------------------------------#
# CONFIG #
#---------------------------------------------------------------------------------------------------------------#
# to obtain your own client ID and API key please register a new app here: http://dev.netatmo.com/dev/listapps
set clientId "XXXXXXXXXXX"
set clientSecret "XXXXXXXXX"
# the following are your normal netatmo credentials (the ones you used to setup your netatmo weather station)
set username "XXXeMailXXX"
set password "XXXXX"
set ::env(LD_LIBRARY_PATH) "/usr/local/addons/cuxd"
set cfgfile "/tmp/netatmo.dat"
set logtag "netatmo.tcl"
set logfacility "local1"
# 0=panic, 1=alert 2=crit 3=err 4=warn 5=notice 6=info 7=debug
set loglevel 7
#---------------------------------------------------------------------------------------------------------------#
#---------------------------------------------------------------------------------------------------------------#
# GLOBAL VARIABLES #
#---------------------------------------------------------------------------------------------------------------#
set accesstoken ""
set refreshtoken ""
set tokenexpires 0
#---------------------------------------------------------------------------------------------------------------#
set loglevels {panic alert crit err warn notice info debug}
proc log {lvl msg} {
global logtag
global logfacility
global loglevel
global loglevels
set lvlnum [lsearch $loglevels $lvl]
if {$lvlnum <= $loglevel} {
if {$lvlnum <= 3} {
catch {exec logger -s -t $logtag -p $logfacility.$lvl $msg}
} else {
puts "$lvl: $msg"
catch {exec logger -t $logtag -p $logfacility.$lvl $msg}
}
}
}
proc refreshToken {rt ci cs} {
log debug "refreshing token"
set url "https://api.netatmo.net/oauth2/token"
set header "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
set parameter "grant_type=refresh_token&refresh_token=$rt&client_id=$ci&client_secret=$cs"
catch {exec /usr/local/addons/cuxd/curl -k -i -H $header -X POST -d $parameter $url} response
log debug "response was $response"
return $response
}
proc requestToken {ci cs un pw} {
log "debug" "requesting new token"
set url "https://api.netatmo.net/oauth2/token"
set header "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
set parameter "grant_type=password&client_id=$ci&client_secret=$cs&username=$un&password=$pw"
catch {exec /usr/local/addons/cuxd/curl -k -i -H $header -X POST -d $parameter $url} response
log debug "response was $response"
return $response
}
proc parseOAuthResponse {input} {
log debug "parsing authentication result"
global accesstoken
global refreshtoken
regexp {HTTP/1.1\s(\d*)} $input dummy returncode
regexp {\"access_token\":\"(.*?)\"} $input dummy accesstoken
regexp {\"refresh_token\":\"(.*?)\"} $input dummy refreshtoken
regexp {\"expires_in\":(.*?)\,} $input dummy expiresin
log debug "returncode is $returncode"
log debug "access token is $accesstoken"
log debug "refresh token is $refreshtoken"
log debug "expires in $expiresin"
if {[expr $returncode]!=200} {
log error "Authentication failed with code $returncode and response $input"
exit 1
}
return $expiresin
}
proc saveAccessToken {expin} {
global accesstoken
global refreshtoken
global tokenexpires
global cfgfile
log debug "saving new access token to $cfgfile"
set fileId [open $cfgfile "w"]
set now [clock seconds]
set tokenexpires [expr $now + $expin]
puts $fileId $accesstoken
puts $fileId $refreshtoken
puts $fileId $tokenexpires
close $fileId
}
proc loadAccessToken {} {
global accesstoken
global refreshtoken
global tokenexpires
global cfgfile
log debug "loading stored credentials from $cfgfile"
set fp [open $cfgfile r]
set file_data [read $fp]
close $fp
log debug "file data is: $file_data"
set data [split $file_data "\n"]
set accesstoken [lindex $data 0]
set refreshtoken [lindex $data 1]
set tokenexpires [lindex $data 2]
}
log debug "script has started"
if { [file exists $cfgfile] == 1} {
log info "found stored credentials"
loadAccessToken
set now [clock seconds]
log debug "current time is [clock format $now -format "%Y-%m-%dT%H:%M:%S"], token is valid until [clock format $tokenexpires -format "%Y-%m-%dT%H:%M:%S"]"
if {[expr $now >= $tokenexpires] == 1} {
log notice "token has already expired"
saveAccessToken [parseOAuthResponse [refreshToken $refreshtoken $clientId $clientSecret]]
log notice "oauth token successfully refreshed"
} else {
log info "token is still valid"
}
} else {
log warn "no stored credentials found"
saveAccessToken [parseOAuthResponse [requestToken $clientId $clientSecret $username $password]]
log notice "oauth token successfully initialized"
}
log debug "getting deviceIDs mit getuser"
set url "https://api.netatmo.net/api/getuser?access_token=$accesstoken"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
log debug "getting DeviceIDs mit devicelist"
set url "https://api.netatmo.net/api/devicelist?access_token=$accesstoken"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
Skript anpassen:
Editiert folgende Zeilen des angefügten Skripts, und setzt dort eure individuellen Daten ein.
Zeile 9: set clientId "0123456789abcd0123456789"
Zeile 10: set clientId "0123456789abcd0123456789"
Zeile 12: set username "name@domain.com"
Zeile 13: set password "password"
Zeile 15: set deviceid "IDdesINNENMODULS"
Zeile 16: set moduleid "IDdesAUSSENMODULS"
Zeile 17: set rainid "IDdesREGENSENSORS"
Zeile 18: set windid "IDdesWINDSENSORS"
Code: Alles auswählen
#!/bin/tclsh
load tclrega.so
#---------------------------------------------------------------------------------------------------------------#
# CONFIG #
#---------------------------------------------------------------------------------------------------------------#
# to obtain your own client ID and API key please register a new app here: http://dev.netatmo.com/dev/listapps
set clientId "XXXXXXX"
set clientSecret "XXXXXXX"
# the following are your normal netatmo credentials (the ones you used to setup your netatmo weather station)
set username "XXXXXXX"
set password "XXXXXXX"
# the following are MAC addresses of your indoor station and the outside module and rain module
set deviceid "XX:XX:XX:XX:XX:XX"
set moduleid "XX:XX:XX:XX:XX:XX"
set rainid "XX:XX:XX:XX:XX:XX"
set windid "XX:XX:XX:XX:XX:XX"
set ::env(LD_LIBRARY_PATH) "/usr/local/addons/cuxd"
set cfgfile "/tmp/netatmo.dat"
set logtag "netatmo.tcl"
set logfacility "local1"
# 0=panic, 1=alert 2=crit 3=err 4=warn 5=notice 6=info 7=debug
set loglevel 6
#---------------------------------------------------------------------------------------------------------------#
#---------------------------------------------------------------------------------------------------------------#
# GLOBAL VARIABLES #
#---------------------------------------------------------------------------------------------------------------#
set accesstoken ""
set refreshtoken ""
set tokenexpires 0
#---------------------------------------------------------------------------------------------------------------#
set loglevels {panic alert crit err warn notice info debug}
proc log {lvl msg} {
global logtag
global logfacility
global loglevel
global loglevels
set lvlnum [lsearch $loglevels $lvl]
if {$lvlnum <= $loglevel} {
if {$lvlnum <= 3} {
catch {exec logger -s -t $logtag -p $logfacility.$lvl $msg}
} else {
puts "$lvl: $msg"
catch {exec logger -t $logtag -p $logfacility.$lvl $msg}
}
}
}
proc refreshToken {rt ci cs} {
log debug "refreshing token"
set url "https://api.netatmo.net/oauth2/token"
set header "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
set parameter "grant_type=refresh_token&refresh_token=$rt&client_id=$ci&client_secret=$cs"
catch {exec /usr/local/addons/cuxd/curl -k -i -H $header -X POST -d $parameter $url} response
log debug "response was $response"
return $response
}
proc requestToken {ci cs un pw} {
log "debug" "requesting new token"
set url "https://api.netatmo.net/oauth2/token"
set header "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
set parameter "grant_type=password&client_id=$ci&client_secret=$cs&username=$un&password=$pw"
catch {exec /usr/local/addons/cuxd/curl -k -i -H $header -X POST -d $parameter $url} response
log debug "response was $response"
return $response
}
proc parseOAuthResponse {input} {
log debug "parsing authentication result"
global accesstoken
global refreshtoken
regexp {HTTP/1.1\s(\d*)} $input dummy returncode
regexp {\"access_token\":\"(.*?)\"} $input dummy accesstoken
regexp {\"refresh_token\":\"(.*?)\"} $input dummy refreshtoken
regexp {\"expires_in\":(.*?)\,} $input dummy expiresin
log debug "returncode is $returncode"
log debug "access token is $accesstoken"
log debug "refresh token is $refreshtoken"
log debug "expires in $expiresin"
if {[expr $returncode]!=200} {
log error "Authentication failed with code $returncode and response $input"
exit 1
}
return $expiresin
}
proc saveAccessToken {expin} {
global accesstoken
global refreshtoken
global tokenexpires
global cfgfile
log debug "saving new access token to $cfgfile"
set fileId [open $cfgfile "w"]
set now [clock seconds]
set tokenexpires [expr $now + $expin]
puts $fileId $accesstoken
puts $fileId $refreshtoken
puts $fileId $tokenexpires
close $fileId
}
proc loadAccessToken {} {
global accesstoken
global refreshtoken
global tokenexpires
global cfgfile
log debug "loading stored credentials from $cfgfile"
set fp [open $cfgfile r]
set file_data [read $fp]
close $fp
log debug "file data is: $file_data"
set data [split $file_data "\n"]
set accesstoken [lindex $data 0]
set refreshtoken [lindex $data 1]
set tokenexpires [lindex $data 2]
}
log debug "script has started"
if { [file exists $cfgfile] == 1} {
log info "found stored credentials"
loadAccessToken
set now [clock seconds]
log debug "current time is [clock format $now -format "%Y-%m-%dT%H:%M:%S"], token is valid until [clock format $tokenexpires -format "%Y-%m-%dT%H:%M:%S"]"
if {[expr $now >= $tokenexpires] == 1} {
log notice "token has already expired"
saveAccessToken [parseOAuthResponse [refreshToken $refreshtoken $clientId $clientSecret]]
log notice "oauth token successfully refreshed"
} else {
log info "token is still valid"
}
} else {
log warn "no stored credentials found"
saveAccessToken [parseOAuthResponse [requestToken $clientId $clientSecret $username $password]]
log notice "oauth token successfully initialized"
}
log debug "polling outdoor module..."
set url "https://api.netatmo.net/api/getmeasure?access_token=$accesstoken&device_id=$deviceid&module_id=$moduleid&scale=max&type=Temperature,Humidity&date_end=last"
log debug "querying $url"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
regexp {\"value\":\[\[(.*?),(.*?)\]} $response dummy otemp ohum
log info "Outside temperature is $otemp"
log info "Outside humidity is $ohum"
log debug "polling main module..."
set url "https://api.netatmo.net/api/getmeasure?access_token=$accesstoken&device_id=$deviceid&scale=max&type=Temperature,Humidity,CO2,Pressure,Noise&date_end=last"
log debug "querying $url"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
regexp {\"value\":\[\[(.*?),(.*?),(.*?),(.*?),(.*?)\]} $response dummy itemp ihum ico2 ipressure inoise
log info "LogI is $response"
log info "Inside temperature is $itemp"
log info "Inside humidity is $ihum"
log info "Inside CO2 level $ico2"
log info "Inside pressure is $ipressure"
log info "Inside noise level is $inoise"
log debug "polling regensensor module...1d"
set url "https://api.netatmo.net/api/getmeasure?access_token=$accesstoken&device_id=$deviceid&module_id=$rainid&scale=1day&type=sum_rain&date_end=last"
log debug "querying $url"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
regexp {\"value\":\[\[(.*?)\]} $response dummy rain1d
log info "LogR is $response"
log info "Outside Regen1d is $rain1d"
log debug "polling regensensor module...30min"
set url "https://api.netatmo.net/api/getmeasure?access_token=$accesstoken&device_id=$deviceid&module_id=$rainid&scale=30min&type=Rain,sum_rain&date_end=last"
log debug "querying $url"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "response is: $response"
regexp {\"value\":\[\[(.*?),(.*?)\]} $response dummy rain2 rain30min
log info "LogR is $response"
log info "Outside rain2 is $rain2"
log info "Outside Regen30min is $rain30min"
log debug "polling wind module..."
set url "https://api.netatmo.net/api/getmeasure?access_token=$accesstoken&device_id=$deviceid&module_id=$windid&scale=max&type=WindAngle,WindStrength,GustAngle,GustStrength&date_end=last"
log debug "quering $url"
catch {exec /usr/local/addons/cuxd/curl -k -# $url} response
log debug "respnose is $response"
regexp {\"value\":\[\[(.*?),(.*?),(.*?),(.*?)\]} $response dummy windangle windstrength gustangle guststrength
log info "WindAngle is $windangle"
log info "Windstrength is $windstrength"
log info "GustAngle is $gustangle"
log info "Guststrength is $guststrength"
#
# set ReGaHss variables
#
set rega_cmd ""
append rega_cmd "var ITemp = dom.GetObject('CUxD.CUX9002001:1.SET_TEMPERATURE');"
append rega_cmd "var IHumi = dom.GetObject('CUxD.CUX9002001:1.SET_HUMIDITY');"
append rega_cmd "var OTemp = dom.GetObject('CUxD.CUX9002002:1.SET_TEMPERATURE');"
append rega_cmd "var OHumi = dom.GetObject('CUxD.CUX9002002:1.SET_HUMIDITY');"
append rega_cmd "var Rain1 = dom.GetObject('Regenmenge_30min');"
append rega_cmd "var Rain2 = dom.GetObject('Regenmenge_1d');"
append rega_cmd "var Rain3 = dom.GetObject('Regen_aktuell');"
append rega_cmd "var IPress = dom.GetObject('Luftdruck');"
append rega_cmd "var ICO2 = dom.GetObject('CO2');"
append rega_cmd "var INoise = dom.GetObject('Sonometer');"
append rega_cmd "var windA = dom.GetObject('Windrichtung');"
append rega_cmd "var windS = dom.GetObject('Windstaerke');"
append rega_cmd "var gustA = dom.GetObject('Gustangle');"
append rega_cmd "var gustS = dom.GetObject('Guststaerke');"
append rega_cmd "OTemp.State('$otemp');"
append rega_cmd "OHumi.State('$ohum');"
append rega_cmd "ITemp.State('$itemp');"
append rega_cmd "IHumi.State('$ihum');"
append rega_cmd "IPress.State('$ipressure');"
append rega_cmd "ICO2.State('$ico2');"
append rega_cmd "INoise.State('$inoise');"
append rega_cmd "Rain1.State('$rain30min');"
append rega_cmd "Rain2.State('$rain1d');"
append rega_cmd "Rain3.State('$rain2');"
append rega_cmd "windA.State('$windangle');"
append rega_cmd "windS.State('$windstrength');"
append rega_cmd "gustA.State('$gustangle');"
append rega_cmd "gustS.State('$guststrength');"
append rega_cmd "var sdatetime = system.Date('%d.%m.%Y %H:%M:%S');"
append rega_cmd "var netatmosynctime = dom.GetObject('SyncTime');"
append rega_cmd "netatmosynctime.Variable(sdatetime.ToString());"
rega_script $rega_cmd
Daher hier eine kurze Erklärung des Skriptes:
Ich kommentiere aber nur die Stellen wo etwas eingetragen werden muss oder etwas gelöscht werfen kann.
Speichert es auf eurem Rechner als netatmo.tcl ab.
Nun kopiert die Datei (z.B. mit Hilfe des Tools WinSCP http://winscp.net) auf eure CCU. Als Protokoll nehmt ihr SCP und zur Verbindung braucht ihr die IP, den Benutzer: root und eurer Passwort vom SSH Zugang, als Ziel erstellt das Verzeichnis /usr/local/addons/netatmo/ und speichert dort die Datei.
Anschließend könnt ihr das Skript testen: Hierzu öffnet ein Terminal (CTRL + T) und geht folgenden Befehl ein:
Code: Alles auswählen
tclsh /usr/local/addons/netatmo/netatmo.tcl
Automatisierung:
Ihr braucht nun ein drittes virtuelles Gerät, welches ihr wieder im CUxD einrichtet:
CUxD Gerätetyp: (28) System
Funktion: Exec
Seriennummer: 1
Name: Zentrale CUxD
Icon: Fernbedienung 19 Tasten
Controll: Taster
Welchsel wieder auf die CCU Oberfläche, lernt das neue Gerät an und macht folgende Einstellungen auf z.B. Channel 1
KEY CMD_SHORT tclsh /usr/local/addons/netatmo/netatmo.tcl
KEY CMD_LONG tclsh /usr/local/addons/netatmo/netatmo.tcl
Damit eure Werte von nun an auch regelmäßig abgeholt werden, erstellt ein neues Programm:
Hier setzt ihr als Bedingung Zeitsteuerung ein Zeitspanne ganztätig, Zeitintervall 15 Minuten, Beginn heutiges Datum und kein Enddatum
Als Aktivität hinterlegt ihr folgendes Skript:
Code: Alles auswählen
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("tclsh /usr/local/addons/netatmo/netatmo.tcl");
var v = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
WriteLine(v);