Wer sich jetzt nicht direkt eine Wetterstation von Homematic für ca 250€ kaufen möchte, nur um zu wissen, ob es draußen regnet, den kann ich verstehen. Aber das müsst ihr auch nicht, denn man kann in der Zentrale von Wunderground Homematic Wetter-Daten online abrufen!
Dabei rufen wird über Homematic das Wetter online über wunderground.com ab. Auf dieser Internetseite werden Daten von Wetterstationen kostenfrei zur Verfügung gestellt und dank eines Homematic Wetter Skripts aus dem Homematic Forum ist die Implementierung denkbar einfach.
Also, wenn du Wetter-Daten aus dem Internet in deiner CCU3 oder CCU2 benutzen und anzeigen lassen möchtest, bitte einfach der Schritt-für-Schritt-Anleitung folgen 😉
Alternativ kannst du Homematic auch über Apple HomeKit steuern und in der Homebridge Wetterdaten-Plugins einbinden. Somit bist du unabhängig, von der CCU 😉
Voraussetzungen
Homematic Komponenten
Zusatzsoftware auf der Homematic Zentrale
KEINE, auch kein CUX Daemon!
Arbeiten auf Wunderground.com
Account erstellen
Zuerst müssen wir uns auf wunderground einen Account erstellen, von dieser Webseite beziehen wir unsere Homematic Wetter-Internet-Daten.
Anschließend erhaltet ihr eine Bestätigungs-E-Mail. Das heißt ihr müsst euren Account mit dem Link in der E-Mail aktivieren, da ihr sonst keine API Keys erstellen könnt!
API KEY erstellen, um über Wunderground Homematic Wetter-Daten abzufragen
Nachdem ihr eure E-Mail-Adresse validiert habt, müsst ihr euch einen API Key erstellen
Anschließend gelangt ihr auf eine Seite, auf der ihr eure persönlichen Daten eintragen müsst. Danach gelangt ihr auf die Seite, von der ihr euch euren eigenen API KEY kopieren könnt.
Arbeiten auf der Homematic Zentrale
Systemvariablen anlegen
Rufe nun die Web-Oberfläche deiner Zentrale über deine Homematic IP Adresse auf.
Ihr müsst nun in der Homematic WebUI folgende Systemvariablen für die Homematic Wetter-Daten anlegen. Wenn ihr eine Variable vergesst oder Schreibfehler eingebaut habt, funktioniert das Skript nicht mehr!
Name | Typ | Einheit |
W_Station | Zeichenkette | |
W_Aktualisierung | Zeichenkette | |
W_Bedingungen | Zeichenkette | |
W_Temperatur | Zahl | °C |
W_Luftfeuchte | Zahl | % |
W_Windbedingungen | Zeichenkette | |
W_Windrichtung | Zeichenkette | |
W_Windrichtg | Zahl | ° |
W_Windgeschwindigkeit | Zahl | km/h |
W_Windboeen | Zahl | km/h |
W_Luftdruck | Zahl | mb |
W_Luftdrucktrend | Zeichenkette | |
W_Taupunkt | Zahl | °C |
W_UV | Zeichenkette |
Hier ein Beispiel anhand der Variable W_Temperatur
Programm erstellen
Zuletzt müssen wird noch das Programm erstellen, das die Variablen fürs Wetter in Homematic mit Daten füllt.
Neues Programm in der WebUI anlegen
Übersicht des Programms W_Wunderground zum Homematic Wetter-Daten online abrufen
Zeitsteuerung von W_Wunderground
Skriptcode von W_Wunderground
Schlussendlich findet ihr hier das Skript vom Programm W_Wunderground. Dieses Skript ist für die Befüllung der Homematic Wetter-Daten Variablen mit den Daten von Wunderground verantwortlich.
Vergesst bitte nicht in Zeile 19:
- XXXXXXXXXXXXXXXX durch euren API KEY zu ersetzen
- MEINESTADT.xml durch eure Heimatstadt zu ersetzen, zum Beispiel Frankfurt.xml22
!Stand 03.04.2014 http://homematic-forum.de/forum/viewtopic.php?f=31&t=17209
!zuerst folgende Systemvariablen anlegen
!Achtung: keine vergessen und exakte Schreibweise mit Drag&Drop
!W_Station Zeichenkette
!W_Aktualisierung Zeichenkette
!W_Bedingungen Zeichenkette
!W_Temperatur Zahl °C
!W_Luftfeuchte Zahl %
!W_Windbedingungen Zeichenkette
!W_Windrichtung Zeichenkette
!W_Windrichtg Zahl °
!W_Windgeschwindigkeit Zahl km/h
!W_Windboeen Zahl km/h
!W_Luftdruck Zahl mb
!W_Luftdrucktrend Zeichenkette
!W_Taupunkt Zahl °C
!W_UV Zeichenkette
var url = "http://api.wunderground.com/api/XXXXXXXXXXXXXXXX/conditions/lang:DL/q/Germany/MEINESTADT.xml";
!hier ist die Abfrage mit CUxD
!dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#url#"'");
!dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
!string wetter_xml = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
!hier ist die Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
WriteLine(stdout);
string wetter_xml = stdout;
WriteLine(wetter_xml);
!Beim XML-File den ueberfluessigen Header entfernen
integer laenge = wetter_xml.Length();
integer wort_position = wetter_xml.Find("display_location");
wetter_xml = wetter_xml.Substr(wort_position, (laenge - wort_position));
!WriteLine(wetter_xml);
!Daten mit Suchworten aus XML-File ausfiltern:
!string word = "full";
string word = "city";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
dom.GetObject("W_Station").State(daten);
!string word = "observation_time";
string word = "observation_time_rfc822";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
!daten = daten.Substr(0, (word_position -2));
daten = daten.Substr(0, (word_position -11));
dom.GetObject("W_Aktualisierung").State(daten);
string word = "weather";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
dom.GetObject("W_Bedingungen").State(daten);
string word = "temp_c";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
dom.GetObject("W_Temperatur").State(zahl);
string word = "relative_humidity";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
dom.GetObject("W_Luftfeuchte").State(zahl);
string word = "wind_string";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
dom.GetObject("W_Windbedingungen").State(daten);
string word = "wind_dir";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
word_laenge =daten.Length();
string anfangsbuchstabe = daten.Substr(0,1);
! Umlaute korrigieren
!
! N # Nord ***
if (anfangsbuchstabe == "N") {
!
if (daten == "Nordwest") {daten = "Nord-West" ;}
}
! S # Süd ***
if (anfangsbuchstabe == "S") {
! 4 # Süd
if (word_laenge == 4) {daten = "Süd";}
! 8 # Südwest
if (word_laenge == 8) {daten = "Süd-West";}
! 12 # Süd-Südost
if (word_laenge == 12) {daten = "Süd-Süd-Ost" ;}
! 13
if (word_laenge == 13) {daten = "Süd-Süd-West" ;}
}
! W # Westen
if (anfangsbuchstabe == "W") {
! 13 # West-Südwest
if (word_laenge == 13) {daten = "West-Süd-West" ;}
}
! O # Osten
if (anfangsbuchstabe == "O") {
! 11 # Ost-Südost
if (word_laenge == 11) {daten = "Ost-Süd-Ost" ;}
}
dom.GetObject("W_Windrichtung").State(daten);
!WriteLine(daten);
string word = "wind_degrees";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
dom.GetObject("W_Windrichtg").State(zahl);
string word = "wind_kph";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
dom.GetObject("W_Windgeschwindigkeit").State(zahl);
string word = "wind_gust_kph";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
dom.GetObject("W_Windboeen").State(zahl);
string word = "pressure_mb";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
dom.GetObject("W_Luftdruck").State(zahl);
string word = "pressure_trend";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
dom.GetObject("W_Luftdrucktrend").State(daten);
string word = "dewpoint_c";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
dom.GetObject("W_Taupunkt").State(zahl);
string word = "UV";
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
dom.GetObject("W_UV").State(zahl);
Viel Spaß beim Nachmachen!
hallo entscheidende frage: das mit wunderground ? ich dachte das ist vorbei?
oder
wie ist der stand der dinge mit dem API
So ist es leider 🙁
Also, ich habe am 8.12.23 meine Wetterstation, eine Bresser 7 in 1 Clearview, da angemeldet und konnte einen API Key erstellen.
Damit sollte die Methode theoretisch noch funktionieren.
ich werde das am Wochenende mal ausprobieren und das Ergebnis hier posten.
Wenn jemand einen alternativen Vorschlag hat; immer her damit.
Also, ich habe es ausprobiert und natürlich keinen Erfolg gehabt. 😭
Dann habe ich das hier entdeckt:
https://spitzenit.freshdesk.com/support/solutions/articles/48001180248
Dort wird folgender Link verwendet:
“var url = “https://api.weather.com/v2/pws/observations/current?stationId=MEINESTAION&format=xml&units=m&apiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”;
Wenn ich das neue Script auf meiner Raspberrymatic ausführe, bekomme ich eine xml Ausgabe angezeigt, in der meine Sensorwerte stehen.
Das sieht doch schon einmal recht vielversprechend aus. 😁
Die Entitäten erscheinen auch in der Raspberrymatic, scheinen aber deaktiv zu sein.
Nachdem ich die dann aktiviert habe lassen sich die sich sogar alle einbinden zeigen aber alle “0” an.
Ich werde morgen weiter experimentieren…
𝓛𝓮𝓾𝓽𝓮, 𝓶𝓲𝓽 𝓯𝓸𝓵𝓰𝓮𝓷𝓭𝓮𝓶 𝓢𝓬𝓻𝓲𝓹𝓽 𝓯𝓾𝓷𝔃𝓽 𝓮𝓼!!!
!Stand 7.04.2021 https://homematic-forum.de/forum/viewtopic.php?f=18&t=17209&hilit=senden&start=690
! Wetter api: stationID=𝐃𝐞𝐢𝐧𝐞𝐖𝐞𝐭𝐭𝐞𝐫𝐬𝐭𝐚𝐭𝐢𝐨𝐧𝐬𝐈𝐃, apiKey=𝐃𝐞𝐢𝐧𝐚𝐩𝐢𝐊𝐞𝐲 der Wetterstation, units: m (metrisch) oder e(englisch), format: xml (gibt es auch als json)
var url = “https://api.weather.com/v2/pws/observations/current?stationId=𝐃𝐞𝐢𝐧𝐞𝐖𝐞𝐭𝐭𝐞𝐫𝐬𝐭𝐚𝐭𝐢𝐨𝐧𝐬𝐈𝐃&format=xml&units=m&apiKey=𝐃𝐞𝐢𝐧𝐚𝐩𝐢𝐊𝐞𝐲 “;
string stdout;
string stderr;
system.Exec(“wget -q -O – ‘”#url#”‘”, &stdout, &stderr);
WriteLine(stdout);
string wetter_xml = stdout;
WriteLine(wetter_xml);
!Daten mit Suchworten aus XML-File ausfiltern:
string word = “neighborhood”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
daten = daten;
WriteLine(daten);
dom.GetObject(“W_Station”).State(daten);
string word =”obsTimeLocal”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
!daten = daten.Substr(0, (word_position -11));
WriteLine(daten);
dom.GetObject(“W_Aktualisierung”).State(daten);
string word = “temp”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Temperatur”).State(zahl);
! *****
! Temperatur real in string umwandeln und anschliessend den Dezimalpunkt gegen ein Komma austauschen
string TextTemp = zahl.ToString(2);
integer TPunkt = TextTemp.Find(“.”);
string TextTemp1 = TextTemp.Substr(0, TPunkt);
TextTemp1 = TextTemp1 # “,”# TextTemp.Substr(TPunkt +1, 2) # ” Grad Celsius”;
TextTemp = TextTemp1;
dom.GetObject(‘Aussentemperatur’).Variable(TextTemp);
WriteLine(dom.GetObject(‘Aussentemperatur’).Variable());
! *****
string word = “humidity”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Luftfeuchte”).State(zahl);
! *****
string TextHumi = zahl.ToString(1);
integer TPunkt = TextHumi.Find(“.”);
string TextHumi1 = TextHumi.Substr(0, TPunkt);
TextHumi1 = TextHumi1 # “,”# TextHumi.Substr(TPunkt +1, 2) # ” %”;
TextHumi = TextHumi1;
dom.GetObject(‘Luftfeuchtigkeit’).Variable(TextHumi);
WriteLine(dom.GetObject(‘Luftfeuchtigkeit’).Variable());
! *****
string word = “winddir”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
if (daten == -9999) {
daten = “0”;
}
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Windrichtg”).State(zahl);
string word = “windSpeed”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Windgeschwindigkeit”).State(zahl);
string word = “windGust”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Windboeen”).State(zahl);
string word = “pressure”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Luftdruck”).State(zahl);
string word = “dewpt”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Taupunkt”).State(zahl);
string word = “windChill”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Temp_gefuehlt”).State(zahl);
string word = “heatIndex”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Hitzeindex”).State(zahl);
string word = “uv”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
integer zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_UV”).State(zahl);
string word = “precipRate”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Regenrate”).State(zahl);
string word = “precipTotal”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Regensumme”).State(zahl);
string word = “solarRadiation”;
integer word_laenge = word.Length();
integer word_position = wetter_xml.Find(word);
string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
integer word_position = daten.Find(word);
daten = daten.Substr(0, (word_position -2));
real zahl = daten.ToFloat();
WriteLine(zahl);
dom.GetObject(“W_Solar”).State(zahl);
Hi Simon
Danke für die geniale Anleitung. Leider klappt es bei mir nicht. Kann es sein, dass Wunderground da etwas an der API geändert hat?
In der API Dokumentation steht was von “HTTPS is required to be used for all requests to the APIs.” Weather Company Data | API Common Usage Guide – Google Docs
Zudem bin ich mir nicht sicher ob in Zeile 19 die 22 hinter MEINESTADT muss.
LG Christian
Hi Christian,
danke für den Hinweis, ich schaue mir das mal an. HTTPS macht ja Sinn, aber kaum zu glauben wie alt mein Beitrag (und ich) inzwischen geworden ist xD
So wie es aussieht, hat wunderground seine API am 23.11.2021 abgeschaltet, von daher wird das auch mit HTTPS nicht funktionieren. Es wird lediglich noch das Wetter der eigenen Wetterstation (sollte man die haben) ausgelesen, aber auch nicht direkt über wunderground, sondern über api.weather.com, siehe hier. Ich werde bei Gelegenheit eine Anleitung für die OpenWeatherMap Api & Homematic schreiben 😉
Beste Grüße & bis bald
So alles getan aber wie rufe ich die daten nun ab??
Hi Celli,
die Daten werden mit dem Programm in die vorher angelegten Variablen in der CCU3 geschrieben, und können ggf. von dir in Programmen verwendet werden.
Beantwortet das die Frage?
Beste Grüße
Simon
Funktioniert einwandfrei, vielen Dank.
Freut mich, dass es bei dir geklappt hat Jürgen. Vielen Dank für das Feedback.