Wettervorhersage über OpenWeatherMap

User stellen ihre Haussteuerung vor

Moderator: Co-Administratoren

MichaelN
Beiträge: 9562
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von MichaelN » 21.06.2020, 15:12

Hast du einen Vorschlag, wie ich das Anfänger kompatibel formulieren kann, um dieses Missverständnis auszuschließen?
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Tinko
Beiträge: 190
Registriert: 23.10.2016, 10:15
Hat sich bedankt: 53 Mal
Danksagung erhalten: 1 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von Tinko » 26.07.2020, 08:55

Hallo Zusammen

Ich habe das Skript getestet und bei funktioniert es. Vielen Dank dafür @MichaelN.

Ich würde mir für Anfänger noch ein paar mehr Informationen im Post 1 wünschen zur Anlegung der Systemvariablen.

Welche Namen
Welcher Wertebereich (realistische Werte)
Dezimalstellen
Maßeinheiten!

Gruß

MichaelN
Beiträge: 9562
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von MichaelN » 26.07.2020, 09:01

Ich will die Intelligenz der Anwender nicht beleidigen.Du fragst da Wetterdaten ab. Wieviel Lebenserfahrung braucht man um den Wertebereich für Temperatur oder Feuchtigkeit festzulegen?

Aber wenn du mir eine schöne Tabelle zusammenstellst, füge ich die gerne ein.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Tinko
Beiträge: 190
Registriert: 23.10.2016, 10:15
Hat sich bedankt: 53 Mal
Danksagung erhalten: 1 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von Tinko » 26.07.2020, 10:33

Mhh - ich halte mich für ein helles Köpfchen auf meinen Gebieten darum schäme ich mich auch überhaupt nicht zuzugeben, dass mir nicht alles klar war und erst mit API Doku, Vergleichswerte und Beobachtung der Werte sicher war.

Mir war mit deiner tollen Anleitung, für die ich sehr dankbar bin, nicht klar ob das Skript die:

- Luftfeuchtigkeit relativ (%), absolut (g/m^3) oder spezifische (g/kg)
- Niederschlag in (mm) oder (l/m^2) und pro Stunde oder Tag
- Windgeschwindigkeit in (m/s) oder (km/h)

ausgibt.

Selbst wenn die Anfänger die API Dokumentation von OSM studiert könnte es immer noch sein, dass das Skript umrechnet. Was es ja beim Niederschlag pro Tag und der Windgeschwindigkeit tut. Also muss man noch mal in das Skript schauen und ob das jeder Anfänger kann?

Erst aus dem Wissen der Einheit ergeben sich die realistischen Wertebereiche für die Variablen. Wirklich die einzige Variable, die klar sein dürfte ist die Temperatur.

- Temperatur -50-50 (°C)
- Luftfeuchte 0-100 (%)
- Niederschlag 0-1000 (mm)
- Windgeschwindigkeit 0-300 (km/h)

War halt mein Feedback und Wunsch. Jeder darf selbst entscheiden was er damit macht.

PS: absolute oder spezifische Luftfeuchtigkeit ist natürlich für eine Home-Automatisierung besser geeignet. Darum rechne ich die z.B. Bei mir in einem Skript um. Tatsächlich ist mit nicht klar was man mit der relativen LFK automatisieren sollte. Aber off-Topic und gehört nicht hier her.
Zuletzt geändert von Tinko am 28.07.2020, 06:13, insgesamt 4-mal geändert.

MichaelN
Beiträge: 9562
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von MichaelN » 26.07.2020, 10:39

Ok, das ist durchaus ein Punkt. Ich habe da gar nicht drüber nachgedacht, das die Einheiten anders sein könnten, als die Darstellung auf der Website von OWM selbst.

Ich nehme deine Tabelle gerne mit auf.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Tinko
Beiträge: 190
Registriert: 23.10.2016, 10:15
Hat sich bedankt: 53 Mal
Danksagung erhalten: 1 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von Tinko » 26.07.2020, 11:09

Danke.

Off-Topic-Nerd-Anekdote: Tja mit den Wetterdaten ist das so eine Sache. Die Wissenschaft hat bestimmte Werte etabliert, die sich aus der Praktikabilität des Messinstruments ableiten. Für Wissenschaftler ist das ok, Ingenieure rechnen sich das auch ohne Probleme um aber der Leihe kann mit denen meist weniger Anfangen weil sich niemand X g Wasser in Y kg Gas vorstellen kann. Am Beispiel des Niederschlags besonders anschaulich: Weit verbreitet sind günstige Niederschlagsmessgeräte mit Messbehältern, die dann in (ml/Zeiteinheit) messen. Damit ist natürlich fester Niederschlag nicht leicht vergleichbar messbar und muss dann erst umständlich geschmolzen werden (wobei wieder geringe Mengen verdunsten). Darum werden alternativ auch Niederschlagsmessgeräte mit Wagen eingesetzt, die dann in (g/Zeiteinheit) messen.

Gottseidank hat sich die Wissenschaft schon vorher eher zufällig auf Wasser im Normalzustand (bei ca. 4°C) als Umrechnungsmedium zwischen Masse und Volumen geeinigt. Damit ist die Umrechnung beim Niederschlag von (g) auf (ml) vernachlässigbar. Der Grund für die 4°C ist die Anomalie des Wassers, die wiederum eine Anekdote für sich ist.

Larry28
Beiträge: 2
Registriert: 18.08.2020, 19:52
System: Alternative CCU (auf Basis OCCU)

Re: Wettervorhersage über OpenWeatherMap

Beitrag von Larry28 » 18.08.2020, 20:41

Hallo zusammen,

ich habe hier eigentlich nur die Temperaturvorhersage für den heutigen Tag für die Rollosteuerung abfragen wollen. Der Link zu Openweather funktionert. Der eingeschränkte Satz an Systemvariablem ist angelegt.
Ich befürchte meine CUxD-Seriennummer ist ggf. falsch. Im CUxDaemon habe ich auf der Geräteseite unter System (28) CUX2800001 (X) Wetter, mit Fernbedienung 19 Tasten. Das hatte ich im Rahmen eines anderen Scriptes so angelegt. Stimmt da dann

Code: Alles auswählen

string CUXD_Device = "CUxD.CUX2800001:1";
überhaupt?

Beim Testen des Scriptes werden keine AUsgaben gemacht, auch nicht wenn ich ich ein "Hallo Welt" einbaue.

Kann ich ganze XML-Zeilen, die ich nicht benötige löschen oder stimmt das so, wie ich es unten gemacht habe?

Code: Alles auswählen

! Wettervorhersage V4.1a (MichaelN 09.06.2020)
! benötigte Systemvariablen anlegen
! in func bitte unter &id= die Ortskennung und unter &APPID= den API-Schlüssel eintragen
! in CUXD_Device bitte die Kennung des Gerätes eintragen

string func = "wget -q -O - 'http://api.openweathermap.org/data/2.5/forecast?mode=xml&units=metric&id=2941279&APPID=06143e558964de66ea92b8708509c2c6'";
string CUXD_Device = "CUxD.CUX2800001:1";

! === Hier anpassen ===
integer AnzahlTags        = 4; ! Anzahl der eingetragenen XML-Tags
string xmlTagStart        = "windSpeed,temperature unit=,humidity value,precipitation"; ! XML-Start-Tag
string xmlTagEnd          = "/windSpeed,/temperature,/humidity,/precipitation"; ! XML-End-Tag
string xmlWertStart       = "mps=,value=,value=,value="; ! Suchstring vor dem Wert
string xmlWertEnd         = " unit=, min=, unit=, type="; ! Suchstring nach dem Wert - LEERZEICHEN beachten
string xmlWertStartOffset = "5,7,7,7"; ! Länge Wert-Suchstring + Anzahl Zeichen bis zum Wert
string xmlWertEndOffset   = "6,8,8,8"; ! StartOffset + Anzahl Zeichen zwischen Zahl und Ende-String
string NameSVavg0         = ",,,"; ! Namen der Systemvariablen fuer Durchschnitt aktueller Tag
string NameSVmin0         = "FC_Wind_heute_min,FC_Temp_heute_min,FC_Feuchte_heute_min,FC_Regen_heute_min";	     ! Namen der Systemvariablen fuer min-Wert
string NameSVmax0         = "FC_Wind_heute_max,FC_Temp_heute_max,FC_Feuchte_heute_max,FC_Regen_heute_max";	     ! Namen der Systemvariablen fuer max-Wert
string NameSVavg1         = ",,,";  ! Namen der Systemvariablen fuer Durchschnitt nächster Tag
string NameSVmin1         = ",,,";	 ! Namen der Systemvariablen fuer min-Wert
string NameSVmax1         = ",,,";        ! Namen der Systemvariablen fuer max-Wert
integer WindFlag          = 0;    ! Position der Winddaten (zur Umrechnung in km/h) - auf 999 setzen, wenn keine Umrechnung gewünscht oder kein Wind ausgewertet werden soll
integer RegenFlag         = 3;    ! Position der Regendaten zur Ausgabe der Gesamtmenge - auf 999 setzen, wenn stattdessen der Tagesdurchschnitt gewünscht ist

! === ab hier nichts mehr anpassen ===
! Suchstrings und Offset-Werte zum extrahieren der Zeit
string xmlTimeStart               = "time from=";
string xmlTimeEnd                 = " to=";
integer xmlTimeStartOffset        = 11;
integer xmlTimeEndOffset          = 21;
integer xmlSkip                   = 100;

! XML-Antwort von OpenWeatherMaps
string recXML;
string TMPrecXML;

! Arbeitsvariablen
string wert1;
string wert2;
time zeit;
integer counter; ! Sicherheitszaehler gegen Endlosschleife
integer StartPos;
integer EndPos;
integer index;
real Wert_avg;
real Wert_min;
real Wert_max;
real Wert_tmp;
object SV;

! Datumswerte
string Day0; ! heute
string Day1; ! morgen

! Diese Variablen enthalten am Schluss die Ergebnisse
string Day1_avg;     ! Werteliste für morgen
string Day0_avg;	    ! Day0 gibt nur am Tageswechsel korrekte Werte aus


! ENDE Deklarationen und Initialisierungen
! ******************************************************************************************

! Datum als String für die nächsten 3 Tage zum suchen
Day0 = system.Date("%F");     ! Day0 = heute
zeit = Day0.ToTime()+24*3600;
Day1= zeit.Format("%F");      ! Day1 = Datumsstring fuer morgen

! Abruf der Daten
dom.GetObject(CUXD_Device#".CMD_SETS").State(func);
dom.GetObject(CUXD_Device#".CMD_QUERY_RET").State(1);
recXML = dom.GetObject(CUXD_Device#".CMD_RETS").State();
if(!recXML){quit;}
recXML = recXML.Substr(recXML.Find("forecast")); ! nur den Forecast-Teil nutzen
TMPrecXML = recXML;

! Werte auslesen
counter = 0;
index = 0;
StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",0));

while ( (StartPos>=0) && (counter<100) ){
  counter = counter + 1;
  wert1 =  recXML.Substr(recXML.Find(xmlTimeStart)+xmlTimeStartOffset, recXML.Find(xmlTimeEnd)-recXML.Find(xmlTimeStart)+xmlTimeEndOffset);

  ! Day0
  if (wert1==Day0) {
     index = 0;
     while ( index < AnzahlTags ) {
	StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",index));
	EndPos = recXML.Find(xmlTagEnd.StrValueByIndex(",",index));
	wert2 = recXML.Substr(StartPos, EndPos-StartPos); ! nur das relevante Tag
	 WriteLine("DEBUG TAG0: "#wert2);
	StartPos = wert2.Find(xmlWertStart.StrValueByIndex(",",index));
	EndPos = wert2.Find(xmlWertEnd.StrValueByIndex(",",index));
	wert2 =  wert2.Substr(StartPos+xmlWertStartOffset.StrValueByIndex(",",index).ToInteger(),(EndPos-StartPos)-xmlWertEndOffset.StrValueByIndex(",",index).ToInteger());
    	Day0_avg = Day0_avg # wert2 # ",";
	! *** DEBUG
	 WriteLine("c/i/w1/w2:"#counter#"/"#index#"/"#wert1#"    "#wert2);
	index = index + 1;

     }
  }
  ! Day1
  if (wert1==Day1) {
     index = 0;
     while ( index < AnzahlTags ) {
	StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",index));
	EndPos = recXML.Find(xmlTagEnd.StrValueByIndex(",",index));
	wert2 = recXML.Substr(StartPos, EndPos-StartPos); ! nur das relevante Tag
	 WriteLine("DEBUG TAG1: "#wert2);
	StartPos = wert2.Find(xmlWertStart.StrValueByIndex(",",index));
	EndPos = wert2.Find(xmlWertEnd.StrValueByIndex(",",index));
	wert2 =  wert2.Substr(StartPos+xmlWertStartOffset.StrValueByIndex(",",index).ToInteger(),(EndPos-StartPos)-xmlWertEndOffset.StrValueByIndex(",",index).ToInteger());
    	Day1_avg = Day1_avg # wert2 # ",";
	! *** DEBUG
	 WriteLine("c/i/w1/w2:"#counter#"/"#index#"/"#wert1#"    "#wert2);
	index = index + 1;

     }
  }
  xmlSkip = recXML.Find("/time")+5; ! abgearbeiteten Block ausschneiden
  recXML = recXML.Substr(xmlSkip);
  StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",0));
}

! Werte aus Ergebnisliste fischen und wieder richtig zuordnen
counter = 0;
wert1 = "";
while ( counter < AnzahlTags ) {

	! Day0
	index = AnzahlTags;
	Wert_avg = 0.0;
	Wert_min = 1000.0;
	Wert_max = -1000.0;
	EndPos = 0;
	foreach(wert2,Day0_avg.Split(",")) {
		if ( (index % AnzahlTags) == counter ) {
			! jeden x. Eintrag auslesen
			Wert_tmp = wert2.ToFloat();
			! Wind in km/h umrechnen?
			if ( WindFlag == counter ) { Wert_tmp = Wert_tmp*3.6; }
	                Wert_avg = Wert_avg + Wert_tmp;
	                EndPos = EndPos + 1;
	                if (Wert_min>Wert_tmp) {Wert_min=Wert_tmp;}
	                if (Wert_max<Wert_tmp) {Wert_max=Wert_tmp;}
			! *** DEBUG
			WriteLine("c/i/EP/w:"#counter#"/"#index#"/"#EndPos#"/"#Wert_tmp);
		}
		index = index + 1;
	}
	! Durchschnitt berechnen
	if ( RegenFlag <> counter ) {
	Wert_avg = Wert_avg/EndPos; }
	! Werte in die SV schieben
	! *** DEBUG
	WriteLine(NameSVavg0.StrValueByIndex(",",counter));
	WriteLine(Wert_avg);
	WriteLine(NameSVmin0.StrValueByIndex(",",counter));
	WriteLine(Wert_min);
	WriteLine(NameSVmax0.StrValueByIndex(",",counter));
	WriteLine(Wert_max);
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVavg0.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_avg);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmin0.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_min);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmax0.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_max);}
	! *** DEBUG
	wert1 = wert1 #"Day0 "# xmlTagStart.StrValueByIndex(",",counter) #" avg/min/max:"# Wert_avg.ToString(1) #"/"# Wert_min.ToString(1) #"/"# Wert_max.ToString(1) #" +++ ";

         ! Day1
	index = AnzahlTags;
	Wert_avg = 0.0;
	Wert_min = 1000.0;
	Wert_max = -1000.0;
	EndPos = 0;
	foreach(wert2,Day1_avg.Split(",")) {
		if ( (index % AnzahlTags) == counter ) {
			! jeden x. Eintrag auslesen
			Wert_tmp = wert2.ToFloat();
			! Wind in km/h umrechnen?
			if ( WindFlag == counter ) { Wert_tmp = Wert_tmp*3.6; }
	                Wert_avg = Wert_avg + Wert_tmp;
	                EndPos = EndPos + 1;
	                if (Wert_min>Wert_tmp) {Wert_min=Wert_tmp;}
	                if (Wert_max<Wert_tmp) {Wert_max=Wert_tmp;}
			! *** DEBUG
			WriteLine("c/i/EP/w:"#counter#"/"#index#"/"#EndPos#"/"#Wert_tmp);
		}
		index = index + 1;
	}
	! Durchschnitt berechnen
	if ( RegenFlag <> counter ) {
	Wert_avg = Wert_avg/EndPos; }
	! Werte in die SV schieben
	! *** DEBUG
	WriteLine(NameSVavg1.StrValueByIndex(",",counter));
	WriteLine(Wert_avg);
	WriteLine(NameSVmin1.StrValueByIndex(",",counter));
	WriteLine(Wert_min);
	WriteLine(NameSVmax1.StrValueByIndex(",",counter));
	WriteLine(Wert_max);
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVavg1.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_avg);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmin1.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_min);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmax1.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_max);}
	! *** DEBUG
	wert1 = wert1 #"Day1 "# xmlTagStart.StrValueByIndex(",",counter) #" avg/min/max:"# Wert_avg.ToString(1) #"/"# Wert_min.ToString(1) #"/"# Wert_max.ToString(1) #" +++ ";

	counter = counter + 1;
}

! *** DEBUG
WriteLine(wert1);
Besten Dank

MichaelN
Beiträge: 9562
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: Wettervorhersage über OpenWeatherMap

Beitrag von MichaelN » 19.08.2020, 10:35

Larry28 hat geschrieben:
18.08.2020, 20:41
Stimmt da dann

Code: Alles auswählen

string CUXD_Device = "CUxD.CUX2800001:1";
überhaupt?
Das kann ich Dir nicht sagen, ich sitze nicht vor deinem System. Aber wenn Du ein CUxD Device mit der Nummer hast, dann sollte es auch gehen. Ggf. verwendest Du für dieses Skript eine andere Kanalnummer (:2 statt :1) die noch nicht von anderen Skripten genutzt wird. Es kann auch nicht schaden sich den Timeout für den genutzten Kanal anzusehen (Eigenschaft EXEC_TIMEOUT in den Geräteeinstellungen - 1 Minute maximal. Wenn der Server bis dahin keine Antwort geliefert hat, kommt auch keine mehr) .
Beim Testen des Scriptes werden keine AUsgaben gemacht, auch nicht wenn ich ich ein "Hallo Welt" einbaue.
Das ist schlecht, das deutet nämlich auf einen Error hin. Den hatte ich auch mit einer CuxD-Device-Nummer, da es die auf meinem System nicht gibt. Mit der richtigen Nummer lief das Skript, wenn auch ohne Ausgabe durch. Aber da fiel mit auf...

Was habe ich zur URL geschrieben:
kann man dann gleich mal im Browser testen. Wenn das schon nicht klappt, dann braucht man nicht weiter machen...
Falsche URL, kein Output. Das erinnert mich aber daran, das ich eine entsprechende Änderung aus dem Accuweather-Skript noch in dieses übertragen kann. Dann gibt es zumindest eine Fehlermeldung.

Ersetze

Code: Alles auswählen

if(!recXML){quit;}
durch

Code: Alles auswählen

if(!recXML)
  {
  WriteLine("keine gültigen Daten!");
  quit;
  }         
Kann ich ganze XML-Zeilen, die ich nicht benötige löschen oder stimmt das so, wie ich es unten gemacht habe?
Wenn Du ganze Zeilen löscht ohne zu wissen, was Du tust, wird es mit ziemlich großer Wahrscheinlichkeit nicht mehr funktionieren.
Mit deinen Änderungen werden min und max des aktuellen Tages in diese Systemvariablen geschrieben:
FC_Wind_heute_min,FC_Temp_heute_min,FC_Feuchte_heute_min,FC_Regen_heute_min
FC_Wind_heute_max,FC_Temp_heute_max,FC_Feuchte_heute_max,FC_Regen_heute_max

Wenn es das ist, was Du willst, dann hast es richtig gemacht. Wenn Du nur min und max Temperatur willst, reicht auch:

Code: Alles auswählen

! === Hier anpassen ===
integer AnzahlTags        = 1; ! Anzahl der eingetragenen XML-Tags
string xmlTagStart        = "temperature unit="; ! XML-Start-Tag
string xmlTagEnd          = "/temperature"; ! XML-End-Tag
string xmlWertStart       = "value="; ! Suchstring vor dem Wert
string xmlWertEnd         = " min="; ! Suchstring nach dem Wert - LEERZEICHEN beachten
string xmlWertStartOffset = "7"; ! Länge Wert-Suchstring + Anzahl Zeichen bis zum Wert
string xmlWertEndOffset   = "8"; ! StartOffset + Anzahl Zeichen zwischen Zahl und Ende-String
string NameSVavg0         = ""; ! Namen der Systemvariablen fuer Durchschnitt aktueller Tag
string NameSVmin0         = "FC_Temp_heute_min";	     ! Namen der Systemvariablen fuer min-Wert
string NameSVmax0         = "FC_Temp_heute_max";	     ! Namen der Systemvariablen fuer max-Wert
string NameSVavg1         = "";  ! Namen der Systemvariablen fuer Durchschnitt nächster Tag
string NameSVmin1         = "";	 ! Namen der Systemvariablen fuer min-Wert
string NameSVmax1         = "";        ! Namen der Systemvariablen fuer max-Wert
integer WindFlag          = 999;    ! Position der Winddaten (zur Umrechnung in km/h) - auf 999 setzen, wenn keine Umrechnung gewünscht oder kein Wind ausgewertet werden soll
integer RegenFlag         = 999;    ! Position der Regendaten zur Ausgabe der Gesamtmenge - auf 999 setzen, wenn stattdessen der Tagesdurchschnitt gewünscht ist   
Ergebnis:

Code: Alles auswählen

FC_Temp_heute_min
21.360000
FC_Temp_heute_max
26.530000
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Larry28
Beiträge: 2
Registriert: 18.08.2020, 19:52
System: Alternative CCU (auf Basis OCCU)

Re: Wettervorhersage über OpenWeatherMap

Beitrag von Larry28 » 19.08.2020, 14:39

Hallo Michael,

die URL selbst habe ich getestet, die liefert ja Werte. Was ich meinte war das Skript innerhalb der CCU.

Nochmal CUxD für Dummies: Ich lege jetzt nochmal ein neues Gerät an und hoffe die Angaben sind sinnvoll. Wie gesagt, bei mir wird CUxD derzeit für nichts ausser die Wettervorhersage genutzt.
- Ich lege ein Gerät mit Typ (28) System an
- Funktion Exec
- Seriennummer 1
- Name Wetter
- Geräteicon: Steckt da auch etwas Funktionales dahinter oder ist das nur das Erscheinungsbild?
- Control Taster

Ich hoffe die Einstellungen sind sinnvoll.

Der aktuelle Status bei Geräte hat sich geändert auf: "CUX2801001 (?) Wetter - KEY" - muss mich das Fragezeichen irritieren?

Code: Alles auswählen

string CUXD_Device = "CUxD.CUX2801001:2";
So, da war der Wurm drin, wenngleich ich ihn nicht verstehe. Mit dem neu erzeugten Gerät läuft das Skript!

Im Programm habe ich bei Aktivität

Code: Alles auswählen

Aktivität: Dann...Vor dem Ausführen alle laufenden Verzögerungen für diese Aktivitäten beenden (z.B. Retriggern).
das Häkchen gesetzt. Ist die Standardvorgabe.

Danke für die geänderten XML-Strings. Du hast das zwar eingangs gut beschrieben, wenn man zwei Beispiele sieht wird das nochmal plakativer.

Vielen Dank!

iulius.maximilian
Beiträge: 15
Registriert: 20.12.2015, 09:52

Re: Wettervorhersage über OpenWeatherMap

Beitrag von iulius.maximilian » 27.09.2020, 14:17

Ich versuche vergeblich die Werte
symbol number
heraus zu bekommen, um die Jalousien darüber gegen Sonneneinstrahlung zu steuern. Idee was ich falsch machen ?

Bspw.

Code: Alles auswählen

<symbol number="804" name="overcast clouds" var="04d"/>
Das Script habe ich wie folgt angepasst:

Code: Alles auswählen

! Wettervorhersage V4.1b (MichaelN 19.08.2020)
! benötigte Systemvariablen anlegen
! in func bitte unter &id= die Ortskennung und unter &APPID= den API-Schlüssel eintragen
! in CUXD_Device bitte die Kennung des Gerätes eintragen

string func = "wget -q -O - 'http://api.openweathermap.org/data/2.5/forecast?mode=xml&units=metric&id=ABC&APPID=XYZ";
string CUXD_Device = "CUxD.CUX2801001:1";

! === Hier anpassen ===
integer AnzahlTags        = 5; ! Anzahl der eingetragenen XML-Tags
string xmlTagStart        = "symbol,windSpeed,temperature unit=,humidity value,precipitation"; ! XML-Start-Tag
string xmlTagEnd          = "/symbol,/windSpeed,/temperature,/humidity,/precipitation"; ! XML-End-Tag
string xmlWertStart       = "number=,mps=,value=,value=,value="; ! Suchstring vor dem Wert
string xmlWertEnd         = " name=, unit=, min=, unit=, type="; ! Suchstring nach dem Wert - LEERZEICHEN beachten
string xmlWertStartOffset = "8,5,7,7,7"; ! Länge Wert-Suchstring + Anzahl Zeichen bis zum Wert
string xmlWertEndOffset   = "9,6,8,8,8"; ! StartOffset + Anzahl Zeichen zwischen Zahl und Ende-String
string NameSVavg0         = "WetterForecastWolkenHeute,WetterForecastWindHeute,WetterForecastTemperaturHeute,WetterForecastFeuchteHeute,WetterForecastRegenHeuteGesamt"; ! Namen der Systemvariablen fuer Durchschnitt aktueller Tag
string NameSVmin0         = "WetterForecastWolkenHeuteMin,WetterForecastWindHeuteMin,WetterForecastTemperaturHeuteMin,WetterForecastFeuchteHeuteMin,WetterForecastRegenHeuteMin"; ! Namen der Systemvariablen fuer min-Wert
string NameSVmax0         = "WetterForecastWolkenHeuteMax,WetterForecastWindHeuteMax,WetterForecastTemperaturHeuteMax,WetterForecastFeuchteHeuteMax,WetterForecastRegenHeuteMax";	! Namen der Systemvariablen fuer max-Wert
string NameSVavg1         = "WetterForecastWolkenMorgen,WetterForecastWindMorgen,WetterForecastTemperaturMorgen,WetterForecastFeuchteMorgen,WetterForecastRegenMorgenGesamt"; ! Namen der Systemvariablen fuer Durchschnitt nächster Tag
string NameSVmin1         = "WetterForecastWolkenMorgenMin,WetterForecastWindMorgenMin,WetterForecastTemperaturMorgenMin,WetterForecastFeuchteMorgenMin,WetterForecastRegenMorgenMin"; ! Namen der Systemvariablen fuer min-Wert
string NameSVmax1         = "WetterForecastWolkenMorgenMax,WetterForecastWindMorgenMax,WetterForecastTemperaturMorgenMax,WetterForecastFeuchteMorgenMax,WetterForecastRegenMorgenMax"; ! Namen der Systemvariablen fuer max-Wert
integer WindFlag          = 0; ! Position der Winddaten (zur Umrechnung in km/h) - auf 999 setzen, wenn keine Umrechnung gewünscht oder kein Wind ausgewertet werden soll
integer RegenFlag         = 3; ! Position der Regendaten zur Ausgabe der Gesamtmenge - auf 999 setzen, wenn stattdessen der Tagesdurchschnitt gewünscht ist

! === ab hier nichts mehr anpassen ===
! Suchstrings und Offset-Werte zum extrahieren der Zeit
string xmlTimeStart               = "time from=";
string xmlTimeEnd                 = " to=";
integer xmlTimeStartOffset        = 11;
integer xmlTimeEndOffset          = 21;
integer xmlSkip                   = 100;

! XML-Antwort von OpenWeatherMaps
string recXML;
string TMPrecXML;

! Arbeitsvariablen
string wert1;
string wert2;
time zeit;
integer counter; ! Sicherheitszaehler gegen Endlosschleife
integer StartPos;
integer EndPos;
integer index;
real Wert_avg;
real WertMin;
real WertMax;
real Wert_tmp;
object SV;

! Datumswerte
string Day0; ! heute
string Day1; ! morgen

! Diese Variablen enthalten am Schluss die Ergebnisse
string Day1_avg;     ! Werteliste für morgen
string Day0_avg;	    ! Day0 gibt nur am Tageswechsel korrekte Werte aus


! ENDE Deklarationen und Initialisierungen
! ******************************************************************************************

! Datum als String für die nächsten 3 Tage zum suchen
Day0 = system.Date("%F");     ! Day0 = heute
zeit = Day0.ToTime()+24*3600;
Day1= zeit.Format("%F");      ! Day1 = Datumsstring fuer morgen

! Abruf der Daten
dom.GetObject(CUXD_Device#".CMD_SETS").State(func);
dom.GetObject(CUXD_Device#".CMD_QUERY_RET").State(1);
recXML = dom.GetObject(CUXD_Device#".CMD_RETS").State();
if(!recXML)
  {
  (dom.GetObject(ID_DATAPOINTS)).Get(CUXD_Device#".CMD_EXEC").State("logger -t script -p user.debug [MichaelN Script OpenWeatherMap V4.1: keine Antwort vom Wetter-Server!]");
  WriteLine("MichaelN Script OpenWeatherMap V4.1: keine Antwort vom Wetter-Server!");
  quit;
  }
recXML = recXML.Substr(recXML.Find("forecast")); ! nur den Forecast-Teil nutzen
TMPrecXML = recXML;

! Werte auslesen
counter = 0;
index = 0;
StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",0));

while ( (StartPos>=0) && (counter<100) ){
  counter = counter + 1;
  wert1 =  recXML.Substr(recXML.Find(xmlTimeStart)+xmlTimeStartOffset, recXML.Find(xmlTimeEnd)-recXML.Find(xmlTimeStart)+xmlTimeEndOffset);

  ! Day0
  if (wert1==Day0) {
     index = 0;
     while ( index < AnzahlTags ) {
	StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",index));
	EndPos = recXML.Find(xmlTagEnd.StrValueByIndex(",",index));
	wert2 = recXML.Substr(StartPos, EndPos-StartPos); ! nur das relevante Tag
	 WriteLine("DEBUG TAG0: "#wert2);
	StartPos = wert2.Find(xmlWertStart.StrValueByIndex(",",index));
	EndPos = wert2.Find(xmlWertEnd.StrValueByIndex(",",index));
	wert2 =  wert2.Substr(StartPos+xmlWertStartOffset.StrValueByIndex(",",index).ToInteger(),(EndPos-StartPos)-xmlWertEndOffset.StrValueByIndex(",",index).ToInteger());
    	Day0_avg = Day0_avg # wert2 # ",";
	! *** DEBUG
	 WriteLine("c/i/w1/w2:"#counter#"/"#index#"/"#wert1#"    "#wert2);
	index = index + 1;

     }
  }
  ! Day1
  if (wert1==Day1) {
     index = 0;
     while ( index < AnzahlTags ) {
	StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",index));
	EndPos = recXML.Find(xmlTagEnd.StrValueByIndex(",",index));
	wert2 = recXML.Substr(StartPos, EndPos-StartPos); ! nur das relevante Tag
	 WriteLine("DEBUG TAG1: "#wert2);
	StartPos = wert2.Find(xmlWertStart.StrValueByIndex(",",index));
	EndPos = wert2.Find(xmlWertEnd.StrValueByIndex(",",index));
	wert2 =  wert2.Substr(StartPos+xmlWertStartOffset.StrValueByIndex(",",index).ToInteger(),(EndPos-StartPos)-xmlWertEndOffset.StrValueByIndex(",",index).ToInteger());
    	Day1_avg = Day1_avg # wert2 # ",";
	! *** DEBUG
	 WriteLine("c/i/w1/w2:"#counter#"/"#index#"/"#wert1#"    "#wert2);
	index = index + 1;

     }
  }
  xmlSkip = recXML.Find("/time")+5; ! abgearbeiteten Block ausschneiden
  recXML = recXML.Substr(xmlSkip);
  StartPos = recXML.Find(xmlTagStart.StrValueByIndex(",",0));
}

! Werte aus Ergebnisliste fischen und wieder richtig zuordnen
counter = 0;
wert1 = "";
while ( counter < AnzahlTags ) {

	! Day0
	index = AnzahlTags;
	Wert_avg = 0.0;
	WertMin = 1000.0;
	WertMax = -1000.0;
	EndPos = 0;
	foreach(wert2,Day0_avg.Split(",")) {
		if ( (index % AnzahlTags) == counter ) {
			! jeden x. Eintrag auslesen
			Wert_tmp = wert2.ToFloat();
			! Wind in km/h umrechnen?
			if ( WindFlag == counter ) { Wert_tmp = Wert_tmp*3.6; }
	                Wert_avg = Wert_avg + Wert_tmp;
	                EndPos = EndPos + 1;
	                if (WertMin>Wert_tmp) {WertMin=Wert_tmp;}
	                if (WertMax<Wert_tmp) {WertMax=Wert_tmp;}
			! *** DEBUG
			WriteLine("c/i/EP/w:"#counter#"/"#index#"/"#EndPos#"/"#Wert_tmp);
		}
		index = index + 1;
	}
	! Durchschnitt berechnen
	if ( RegenFlag <> counter ) {
	Wert_avg = Wert_avg/EndPos; }
	! Werte in die SV schieben
	! *** DEBUG
	WriteLine(NameSVavg0.StrValueByIndex(",",counter));
	WriteLine(Wert_avg);
	WriteLine(NameSVmin0.StrValueByIndex(",",counter));
	WriteLine(WertMin);
	WriteLine(NameSVmax0.StrValueByIndex(",",counter));
	WriteLine(WertMax);
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVavg0.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_avg);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmin0.StrValueByIndex(",",counter));
	if (SV) {SV.State(WertMin);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmax0.StrValueByIndex(",",counter));
	if (SV) {SV.State(WertMax);}
	! *** DEBUG
	wert1 = wert1 #"Day0 "# xmlTagStart.StrValueByIndex(",",counter) #" avg/min/max:"# Wert_avg.ToString(1) #"/"# WertMin.ToString(1) #"/"# WertMax.ToString(1) #" +++ ";

         ! Day1
	index = AnzahlTags;
	Wert_avg = 0.0;
	WertMin = 1000.0;
	WertMax = -1000.0;
	EndPos = 0;
	foreach(wert2,Day1_avg.Split(",")) {
		if ( (index % AnzahlTags) == counter ) {
			! jeden x. Eintrag auslesen
			Wert_tmp = wert2.ToFloat();
			! Wind in km/h umrechnen?
			if ( WindFlag == counter ) { Wert_tmp = Wert_tmp*3.6; }
	                Wert_avg = Wert_avg + Wert_tmp;
	                EndPos = EndPos + 1;
	                if (WertMin>Wert_tmp) {WertMin=Wert_tmp;}
	                if (WertMax<Wert_tmp) {WertMax=Wert_tmp;}
			! *** DEBUG
			WriteLine("c/i/EP/w:"#counter#"/"#index#"/"#EndPos#"/"#Wert_tmp);
		}
		index = index + 1;
	}
	! Durchschnitt berechnen
	if ( RegenFlag <> counter ) {
	Wert_avg = Wert_avg/EndPos; }
	! Werte in die SV schieben
	! *** DEBUG
	WriteLine(NameSVavg1.StrValueByIndex(",",counter));
	WriteLine(Wert_avg);
	WriteLine(NameSVmin1.StrValueByIndex(",",counter));
	WriteLine(WertMin);
	WriteLine(NameSVmax1.StrValueByIndex(",",counter));
	WriteLine(WertMax);
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVavg1.StrValueByIndex(",",counter));
	if (SV) {SV.State(Wert_avg);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmin1.StrValueByIndex(",",counter));
	if (SV) {SV.State(WertMin);}
	SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(NameSVmax1.StrValueByIndex(",",counter));
	if (SV) {SV.State(WertMax);}
	! *** DEBUG
	wert1 = wert1 #"Day1 "# xmlTagStart.StrValueByIndex(",",counter) #" avg/min/max:"# Wert_avg.ToString(1) #"/"# WertMin.ToString(1) #"/"# WertMax.ToString(1) #" +++ ";

	counter = counter + 1;
}

! *** DEBUG
WriteLine(wert1);

Antworten

Zurück zu „Projektvorstellungen“