Baue Deinen eigenen Wetterdienst - Dark Sky API

Hallo!

wer kennt das nicht: Das Wetter gehört einfach auf jedes Display :slight_smile:
Es gibt schon eine Reihe von Modulen. Viele haben viele Werte und benötigen daher viele Variablen. Und dennoch fehlt mal hier und da etwas.
Daher meine Idee sich selber was zu erstellen mit darksky.
Darksky ist ein Anbieter, der Informationen diverse Wetter APIs / Stationen aggregiert und abrufbar machet. Der Response erfolgt in JSON und kann daher bequem ausgelesen werden. Ihr könnt Euch auf https://darksky.net/ registrieren und dort mit dem API Key bis zu 1.000 Abfragen am Tag machen.
Ich selber mache eine Abfrage alle 10 Minuten und benötige daher nur 144 Abrufe täglich.

Auf geht’s ans Basteln. Legt Euch für jeden Wert, den ihr aus den Winter Informationen ziehen wollt eine Variable an.

Anbei mein Beispiel.

Um die Variablen zu erstellen erstellt ein Skript mit Timer. In meinem Falle wird das Skript alle 10 Minuten aufgerufen.
Ihr müsst Euch bereits bei darksky registriert haben und Euren API Key bereit halten. Falls Ihr Eure GPS Daten nicht kennt, so schaut bei Google Maps etc. nach. Bei Symcon 5 ist ja eine schöne Suchfunktion dabei.

Skript:

<?

$url = "https://api.darksky.net/forecast/API-KEY-VON-EUCH/48.1111111,14.111111111?exclude=minutely,hourly&lang=de&units=ca";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_URL, $url); 
$output = curl_exec($ch);
curl_close($ch);  
$content = json_decode($output, true);
SetValueFloat(35382, $content['daily']['data'][0]['temperatureHigh']);
SetValueFloat(17472, $content['daily']['data'][0]['temperatureLow']);
SetValueFloat(26163, $content['daily']['data'][0]['humidity']);
SetValueFloat(25659, $content['daily']['data'][0]['windSpeed']);
SetValueFloat(58118, $content['daily']['data'][0]['windGust']);
SetValueFloat(47185, $content['daily']['data'][0]['cloudCover']);
SetValueFloat(43474, $content['daily']['data'][0]['precipProbability']);

SetValue(15572, $content['daily']['data'][0]['summary']);

?>

Anbei ein Beispiel um meine Werte zu füllen.
Ihr müsst Euren API Key eintragen und die korrekten Koordinaten.
Der exclude Parameter in der URL sorgt dafür, dass nur tägliche Wetterberichte abgeholt werden. Minütlich und Stündlich ist hier möglich.
Die gesamte Doku mit Beispiel Response gibt es hier: https://darksky.net/dev/docs
Viel Spass beim Basteln :slight_smile:

Klingt interessant!

Eine Frage habe ich: ist das 1000-Call Limit eine technische Begrenzung die ich nicht überschreiten kann, oder muss ich da selbst drauf achten?

Aus der FAQ wird es mir nicht ersichtlich. Es klingt fast so als müsste ich selbst aufpassen, und wenn ich über die 1000 Calls komme, wird mein Account gesperrt bis ich zahle. Ist das so, oder bekomme ich nach dem 1000ten Call einfach keine Antwort?

Mir ist schon klar dass kein einzelner Nutzer 1000 Aufrufe braucht. Aber mal ne Schleife falsch gesetzt oder den Timer falsch eingestellt… ihr wisst schon.

Ja, laut FAQ ist es tatsächlich so, dass wenn Du mehr als 1.000 Queries am Tag machst und die erzeugen Kosten nicht bezahlst, wird Dein Account gesperrt.

If you have gone over the 1,000 free call limit but have not paid your outstanding balance, we will lock your account. If your account has been locked and you would like it to be unlocked, please contact us at developer@darksky.net.

Entweder schreibst Du dann höflich an die E-Mail Adresse aus der FAQ hin, dass Du ausersehen über dem Limit bist und es sonst nicht kommst oder Du bezahlst oder Du machst Dir nen neuen Account…

Hallo,
habe mal gerade dein Ansatz probiert und klappt soweit sehr gut. Wie bekomme ich den bei Niederschlagstyp die Sprache auf Deutsch? Bei mir steht da rain.

Hallo someone,

vielen Dank für deine „Bastelvorlage“, welche ich erfolgreich umsetzen konnte.

Jetzt fehlt nur noch ein passendes Icon. Wie kann ich ein Wetter Icon im Webfront darstellen? Die Variable „Icon“ habe ich angelegt und diese wird aktuell auch mit „rain“ befüllt. Leider weiß ich nicht, wie ich aus „rain“ ein Icon erstellen kann.

Gruß
AKL

Du brauchst ein Icon Set, in den faq https://darksky.net/dev/docs/faq findest du dazu Hinweise.

Du kannst diese dann z.B. im Profil hinterlegen.

Gruß,
someone

OK, Danke für den Hinweis. Und gleich die nächsten Fragen…

Wo genau muss das Icon Set reinkopiert werden? Habe einen Pi 3 mit Stretch. In dieses Verzeichnis?


/usr/share/symcon/webfront/user/skins/CustomIcons-master/icons

Kommen dann diese Zeilen einfach in dein Skript dazu?


var skycons = new Skycons({"color": "pink"});

skycons.add(document.getElementById("icon1"), Skycons.SUN);
skycons.add(document.getElementById("icon2"), Skycons.RAIN);
usw...

skycons.play();

Gruß vom Ahnungslosen
AKL

wahrscheinlich ist das den meisten klar, aber für aktuelle Werte sollte man currently nehmen:



SetValueFloat(17509 /*[Wetter\DarkSky Wetterdaten\Luftfeuchtigkeit]*/, $content['currently']['humidity']*100);
SetValueFloat(52805 /*[Wetter\DarkSky Wetterdaten\Windgeschwindigkeit]*/, $content['currently']['windSpeed']);
SetValueFloat(40965 /*[Wetter\DarkSky Wetterdaten\aktuelle Temperatur]*/, $content['currently']['temperature']);
SetValueFloat(23473 /*[Wetter\DarkSky Wetterdaten\Luftdruck]*/, $content['currently']['pressure']);

Klasse, vielen Dank für den Hinweis und Code! :slight_smile:
So einfach kann’s sein mit dem Internetwetter, ohne den Overhead eines Moduls!

Hier mein Script wegen der Abschaltung von WeatherUnderground.

Viel Spass!
Sebastian

<?

$api = "yourkey";
$latitude = "45.98";
$longitude = "13.97";

 $today = time();
   $d = date('d', $today);
   $m = date('m', $today);
   $y = date('Y', $today);
$tomorrow = mktime(0, 0, 0, $m, ($d + 1), $y);
   
$heute = (integer) date('d');
$morgen = (integer) date('d', $tomorrow);



$WochenTage = Array('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag');


  $json_string = file_get_contents("https://api.darksky.net/forecast/$api/$latitude,$longitude?exclude=minutely&lang=de&units=si"); 
  $parsed_json = json_decode($json_string);
  $current = $parsed_json->{'currently'};
   $text0 = utf8_decode($current->summary) . "
";
   $text1 = utf8_decode($current->temperature) . "
";
   $text2 = utf8_decode($current->apparentTemperature) . "
";
   $text3 = utf8_decode($current->precipProbability) . "
";
   $text4 = utf8_decode($current->windSpeed) . "
";
   $text5 = utf8_decode($current->windGust) . "
";
   $text6 = utf8_decode($current->cloudCover) . "
";
   @$text7 = utf8_decode($current->precipType) . "
";
   $text8 = utf8_decode($current->humidity);

   $niederschlag = "";
             if ($text7 == "rain") $niederschlag = "Regen";
             if ($text7 == "snow") $niederschlag = "Schnee";
             if ($text7 == "sleet") $niederschlag = "Schneeregen";

   $InsID = @IPS_GetInstanceIDByName("Aktuell", $IPS_SELF);
    if ($InsID === false)
    {
    $InsID = IPS_CreateInstance("{485D0419-BE97-4548-AA9C-C083EB82E61E}");    
    IPS_SetName($InsID, "Aktuell");
    IPS_SetParent($InsID, $IPS_SELF); 
    IPS_ApplyChanges($InsID);
    }
   SetValue(CreateVariableByName($InsID, "Zusammenfassung", 3, "~String"),$text0); 
   SetValue(CreateVariableByName($InsID, "Temperatur", 2, "~Temperature"),$text1);
   SetValue(CreateVariableByName($InsID, "Temperatur gefühlt", 2, "~Temperature"),$text2);
   SetValue(CreateVariableByName($InsID, "Niederschl Wahrsch.", 2, "~Intensity.1"),$text3);
   @SetValue(CreateVariableByName($InsID, "Niederschlag", 3, "~String"),$text7);
   SetValue(CreateVariableByName($InsID, "Windgeschw", 2, "~WindSpeed.ms"),$text4);
   SetValue(CreateVariableByName($InsID, "Wind Böen", 2, "~WindSpeed.ms"),$text5);
   SetValue(CreateVariableByName($InsID, "Wolken", 2, "~Intensity.1"),$text6);
   SetValue(CreateVariableByName($InsID, "Feuchte", 2, "~Intensity.1"),$text8);

   



   
   $daily = $parsed_json->{'daily'};
    $text0 = utf8_decode($daily->summary) . "
";
   $days = $parsed_json->{'daily'}->{'data'};
   $message = array();

		for($i=0;$i<7;$i++)
		 {
             $day = utf8_decode($days[$i]->time);
             $summary = utf8_decode($days[$i]->summary);
	    	 $temphigh = utf8_decode($days[$i]->temperatureHigh);
             $templow = utf8_decode($days[$i]->temperatureLow);
             @$precipType = utf8_decode($days[$i]->precipType);
             $niederschlag = "";
             if ($precipType == "rain") $niederschlag = "Regen";
             if ($precipType == "snow") $niederschlag = "Schnee";
             if ($precipType == "sleet") $niederschlag = "Schneeregen";
             $niedr_prop = utf8_decode($days[$i]->precipProbability);
             $wind = utf8_decode($days[$i]->windSpeed);
             $boen = utf8_decode($days[$i]->windGust);
             $wolken = utf8_decode($days[$i]->cloudCover);
             $humidity = utf8_decode($days[$i]->humidity);
	    	 $tag = (integer) date('d',intval($day));	
             $Wochentag = $WochenTage[date('w',intval($day))];	 
		     $message[$tag] = array(date('d.m',intval($day)),$WochenTage[date('w',intval($day))],$summary,$temphigh,$templow,$niederschlag,$niedr_prop,$wind,$boen,$wolken,$humidity);
             $box[] = "$Wochentag $summary / $niederschlag $niedr_prop % / $temphigh °C $templow °C";
		 }
         
    $InsID = @IPS_GetInstanceIDByName("Heute", $IPS_SELF);
    if ($InsID === false)
    {
    $InsID = IPS_CreateInstance("{485D0419-BE97-4548-AA9C-C083EB82E61E}");    
    IPS_SetName($InsID, "Heute");
    IPS_SetParent($InsID, $IPS_SELF); 
    IPS_ApplyChanges($InsID);
    }
       
 
            SetValue(CreateVariableByName($IPS_SELF, "Woche Zusammenfassung", 3, "~String"),$text0); 
            SetValue(CreateVariableByName($InsID, "Zusammenfassung", 3, "~String"),$message[$heute][2]); 
            SetValue(CreateVariableByName($InsID, "Temp Max", 2, "~Temperature"),$message[$heute][3]);
            SetValue(CreateVariableByName($InsID, "Temp Min", 2, "~Temperature"),$message[$heute][4]);
           @SetValue(CreateVariableByName($InsID, "Niederschlag", 3, "~String"),$message[$heute][5]);
            SetValue(CreateVariableByName($InsID, "Niederschl Wahrsch", 2, "~Intensity.1"),$message[$heute][6]);
            SetValue(CreateVariableByName($InsID, "Wind", 2, "~WindSpeed.ms"),$message[$heute][7]);
            SetValue(CreateVariableByName($InsID, "Wind Böen", 2, "~WindSpeed.ms"),$message[$heute][8]);
            SetValue(CreateVariableByName($InsID, "Wolken", 2, "~Intensity.1"),$message[$heute][9]);
            SetValue(CreateVariableByName($InsID, "Feuchte", 2, "~Intensity.1"),$message[$heute][10]);

            
           

  
   $InsID = @IPS_GetInstanceIDByName("Morgen", $IPS_SELF);
    if ($InsID === false)
    {
    $InsID = IPS_CreateInstance("{485D0419-BE97-4548-AA9C-C083EB82E61E}");    
    IPS_SetName($InsID, "Morgen");
    IPS_SetParent($InsID, $IPS_SELF); 
    IPS_ApplyChanges($InsID);
    }
    
           
            SetValue(CreateVariableByName($InsID, "Zusammenfassung", 3, "~String"),$message[$morgen][2]); 
            SetValue(CreateVariableByName($InsID, "Temp Max ", 2, "~Temperature"),$message[$morgen][3]);
            SetValue(CreateVariableByName($InsID, "Temp Min", 2, "~Temperature"),$message[$morgen][4]);
           @SetValue(CreateVariableByName($InsID, "Niederschlag", 3, "~String"),$message[$morgen][5]);
            SetValue(CreateVariableByName($InsID, "Niederschl Wahrsch", 2, "~Intensity.1"),$message[$morgen][6]);
            SetValue(CreateVariableByName($InsID, "Wind", 2, "~WindSpeed.ms"),$message[$morgen][7]);
            SetValue(CreateVariableByName($InsID, "Wind Böen", 2, "~WindSpeed.ms"),$message[$morgen][8]);
            SetValue(CreateVariableByName($InsID, "Wolken", 2, "~Intensity.1"),$message[$morgen][9]);
            SetValue(CreateVariableByName($InsID, "Feuchte", 2, "~Intensity.1"),$message[$morgen][10]);


            SetValue(CreateVariableByName($IPS_SELF, "Wöchentlich", 3, "~TextBox"), implode("
",$box));


   

$hourly = $parsed_json->{'hourly'}->{'data'};
   $message = array();

		for($i=0;$i<48;$i++)
		 {
             $time = utf8_decode($hourly[$i]->time);
             $summary = utf8_decode($hourly[$i]->summary);
	    	 $temp = utf8_decode($hourly[$i]->temperature);
             $temp2 = utf8_decode($hourly[$i]->apparentTemperature);
             $humidity = utf8_decode($hourly[$i]->humidity);
             @$precipType = utf8_decode($hourly[$i]->precipType);
             $niederschlag = "";
             if ($precipType == "rain") $niederschlag = "Regen";
             if ($precipType == "snow") $niederschlag = "Schnee";
             if ($precipType == "sleet") $niederschlag = "Schneeregen";
             $niedr_prop = utf8_decode($hourly[$i]->precipProbability);
             $wind = utf8_decode($hourly[$i]->windSpeed);
             $boen = utf8_decode($hourly[$i]->windGust);
             $wolken = utf8_decode($hourly[$i]->cloudCover);
             $tag = date('d',intval($time));	
	    	 $stunde = date('H',intval($time));		 
             $Wochentag = $WochenTage[date('w',intval($time))];
		     $message[$stunde] = array(date('d.m',intval($time)),$WochenTage[date('w',intval($time))],date('H',intval($time)),$summary,$temp,$temp2,$niederschlag,$niedr_prop,$wind,$boen,$wolken,$humidity);
             $box2[]="$Wochentag $stunde Uhr $summary / $niederschlag $niedr_prop % / $temp °C";
		 }

    SetValue(CreateVariableByName($IPS_SELF, "Vorhersage", 3, "~TextBox"), implode("
",$box2));


     
     
   
       
  function CreateVariableByName($id, $name, $type, $profile = "")
    {
        //global $_IPS['SELF'];
        $vid = @IPS_GetVariableIDByName($name, $id);
        if($vid === false)
        {
            $vid = IPS_CreateVariable($type);
            IPS_SetParent($vid, $id);
            IPS_SetName($vid, $name);
            IPS_SetInfo($vid, "this variable was created by script #".$_IPS['SELF']);
            if($profile !== "") { IPS_SetVariableCustomProfile($vid, $profile); }
        }
        return $vid;
    }

?>

Hi Sebastian,

funktioniert prima, danke

Oliver

Danke für das Script. //
Hat mir jemand noch einen Tip, wieso mir Aktuell / Heute / Morgen nichts anzeigt im Webfront, aber die Werte sind im Objektbaum vorhanden?

Hallo,

falls Interesse besteht, ich habe mit someone gesprochen und bastel mal ein Modul zusammen. :slight_smile:
Falls jemand Wünsche hat einfach auflisten. :wink:

Der Plan zur Zeit:

[ul]
[li]Splitter für Einstellungen (API Key, Update Timer Intervall)[/li][li]Eine Instanz für die aktuellen Wetterdaten[/li][li]Eine Instanz für die Wochenübersicht[/li][/ul]
Grüße,
Kai

Da wäre ich an Deiner Stelle sehr vorsichtig, aber das must Du wissen, lies Dir doch mal die Nutzungsbedindungen der API durch. Wenn Du ein kostenplichtges Modul zur Verfügung stellen willst mit einem fest hinterlegten API Key sollte das kein Problem sein.

Wenn aber jeder Nutzer selber einen API Key eintragen muss bzw. anlegen dann entspricht das definitiv nicht den Nutzungsbedingungen von Dark Sky
[i]Your permission to use the Service is condition upon your agreement that you will not:

[ul]
[li]direct your end-users to sign up for their own API account (The Dark Sky API not intended to be used directly by end-users);
[/li][/ul]
[/i]

Wie Du das dann letzlich lösen willst must Du wissen, aber das wird dann einfach mit Kosten verbunden sein, wenn alle Anfragen über einen APi Key laufen.

@Fonzo, danke für den Hinweis. Darauf habe ich gar nicht geachtet.

Wird also auf Eis gelegt.

Grüße,
Kai

Gesendet von iPhone mit Tapatalk

Wo ist denn der Unterschied zwischen einem Script und einem kostenlosen Modul?:confused:

Wenn ich ein Script für Dark Sky schreibe und veröffentliche, wer ist denn dann der End-User?
Würde dann nicht auch schon der Script-Ersteller gegen diese Geschäftsbedingungen verstoßen?

Außerdem fehlt in dem Script doch auch folgende Funktion:

You agree that any application or service which incorporates data obtained from the Service shall prominently display the message “Powered by Dark Sky” in a legible manner near the data or any information derived from any data from the Service. This message must, if possible, open a link to https://darksky.net/poweredby/ when clicked or touched.

Wer ist dafür verantwortlich? Der ursprüngliche Scriptersteller oder derjenige, der dieses Script verwendet, ohne den „Powered by Dark Sky“ Hinweis hinzuzufügen?

Ich bin kein IT-Rechtler, mich würde aber mal interessieren, wie diese diesen Sachverhalt beurteilen.

Da musst Du im Zweifelsfall einen Rechtsanwalt fragen ;-). Als Laie würde ich sagen ein Modul ist eine „Anwendung“ (application), bei einem Skript muss man ja noch selber Hand anlegen.

Na der End User ist derjeige, der einen eigenen API Key anlegen muss, sonst kann er das Skript ja auch nicht nutzen. Wenn sich wenige Nutzer als Developer registrieren macht das auch kein Unterschied. Wenn aber grundsätzlich jeder Nutzer von einer Software selber ein API Key anlegen soll, dann wird das so enden wie bei Wunderground, die kostenlosen Kontingente für Developer werden dann abgeschafft werden, da die API nicht direkt für den Endkunden gedacht ist.

Wer will das kontrollieren ob bei Dir zu Hause das angezeigt wird oder nicht? Wenn Du so was auf eine Internetseite stellst ist das schon wieder was anderes. Wenn man letzendlich ein Modul schreibt, was mit einem Klick installiert ist und dazu dient in einer Visualisierung Werte anzuzeigen, dann muss dieser Hinweis sicher auch da hinzugefügt werden.

Aber am Schluss fragt man 3 Anwälte und bekommt 3 unterschiedliche Antworten ;-). Wenn man so ein mögliches PHP Modul später in den Modul Store von IP-Symcon laden sollte, sollte man zumindest zunächst püfen ob alle Nutzungsbedingungen so weit eingehalten werden.

Cool. Vielen Dank.

Funktioniert bei mir auf Anhieb.

Muss ich ein zyklisches Ereignis setzen oder aktualisiert sich dein Skript selber alle x Minuten?

Zyklisches Ereignis nach eigenem Wunsch

Hi Sebastian,

ich bekomme leider folgende Fehlermeldung und die Werte bei „morgen“ sind alle 0:

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 109

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 110

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 111

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 113

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 114

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 115

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 116

Notice:  Undefined offset: 2 in /var/lib/symcon/scripts/10417.ips.php on line 117

Viele Grüße

Götz