Ankündigung

Einklappen
Keine Ankündigung bisher.

Wetteranzeige für denro one

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [WireGate-Plugin] Wetteranzeige für denro one

    Für alle die einen Denro One besitzen ist dieses Plugin gedacht.

    Hintergrund:
    Der Denro One bietet die Möglichkeit eine Wettervorhersage anzuzeigen. Die Wettervorhersage-Daten erhält er über den KNX-Bus von einem Server. Dieses Plugin macht das WireGate Multifunktionsgateway zum Server.

    Wie funktioniert das Plugin?
    Das Plugin ruft die Wetterdaten von wetter.com über die zur Verfügung stehende Api ab (ein Account muss erstellt und ein Projekt erzeugt werden, der Link zur Api findet sich ganz unten rechts) und schickt die Daten für den Denro One aufbereitet auf den KNX-Bus.

    Es müssen zwei GAs angegeben werden, wie in der Doku zum Denro One beschrieben.

    Die restlichen Angaben beziehen sich auf die Wetterabfrage bei wetter.com und sind in den Kommentaren erläutert.

    Zeitweise werden einzelne Wettertelegramme vom Denro One nicht akzeptiert. In diesem Fall werden die Demo-Werte angezeigt, aber eine richtige Lösung habe ich nicht gefunden.

    Inspiriert hat mich das Misterhouse Plugin von uxilef, ein paar Codezeilen sind auch daraus entnommen, ich hoffe das ist in Ordnung.

    Code:
    # Plugin für die Denro One Wettervorhersage
    #
    
    ### Definitionen
    my $wetter_anfordern_ga = "5/0/2"; # Gruppenadresse für Objekt 109 Wetterdaten anfordern
    my $wetterdaten_ga = "5/0/3";      # Gruppenadresse für Objekt 110 Wetterdaten
    
    my $abend_daten = "Nacht"; # Entweder "Nacht" oder "Abend" eintragen (Groß- und Kleinschreibung beachten!), 
                               # bei Abend wird die durchschnittliche Temperatur zwischen 17:00 Uhr und 23:00 Uhr
                               # und bei Nacht zwischen 23:00 Uhr und 6:00 Uhr ausgegeben
    my $temp_ausgabe = "Mittel"; # Darstellung der Temperaturanzeige (Groß- und Kleinschreibung beachten!)
                                 # Möglich ist: Mittel - Mittelwert zwischen der minimalen und maximalen Temperatur
                                 #              Min    - Minimale Temperatur
                                 #              Max    - Maximale Temperatur
                                 #              Extrem - Bei postiven Temperaturwerten die höchste und
                                 #                       bei negativen Temperaturen die tiefste Temperatur
    
    # Benötigte Daten für die Webabfrage bei wetter.com (Der Link zur API ist ganz unten rechts auf der Seite) 
    my $ProjektName = "denro";  # Name des Projekts bei wetter.com
    my $ApiKey      = "36e8ab1b118408f7ed3a4d9319823621"; # API Key des Projektes
    my $StadtCode    = "DE0001020"; # Stadt-Code z.B. durch Suchen einer Stadt und Kopieren des Codes aus der URL von wetter.com
    ### Ende Definitionen
    
    #   XML-Tags von wetter.com
    #    <du>	UTC Zeit (Unix Timestamp)
    #    <d>	Lokale Zeit (Unix Timestamp)
    #    <dhu>	UTC Zeit (ISO 8601)
    #    <dhl> 	Lokale Zeit (ISO 8601)
    #    <p>	Gültigkeitszeitraum der Prognose
    #    <w> 	Code fuer den Wetterzustand
    #    <pc> 	Niederschlagswahrscheinlichkeit in Prozent
    #    <tn> 	Minimaltemperatur in Grad Celsius
    #    <tx> 	Maximaltemperatur in Grad Celsius
    #    <wd> 	Windrichtung in Grad
    #    <ws> 	Windgeschwindigkeit in km/h
    #    <w_txt> 	Wetter in Textform
    #    <wd_txt> 	Windrichtung Text
    #
    #   Aufbau des 14Bytes Datentys (DPT16)
    #    Byte Wert 			Typ
    #    1 	Tag-Id 			INTEGER
    #    2 	01 			fest
    #    3 	Temperatur Früh		INTEGER
    #    4 	Temperatur Mittag 	INTEGER
    #    5 	Temperatur Abend 	INTEGER
    #    6 	02 			fest
    #    7 	Icon-Id Früh 		INTEGER
    #    8 	Icon-Id Mittag 		INTEGER
    #    9 	Icon-Id Abend 		INTEGER
    #    10 04 			fest
    #    11 00 			fest
    #    12 FF 			fest
    #
    
    use LWP::Simple;
    use XML::Simple;
    use Digest::MD5 "md5_hex";
    
    # Plugin an Gruppenadresse "anmelden"
    $plugin_subscribe{$wetter_anfordern_ga}{$plugname} = 1;
    
    # Eigenen Aufruf-Zyklus auf 3 Stunden setzen
    # der Aufrufzyklus ist unabhängig von der Taktzeit und muss kürzer sein!
    $plugin_info{$plugname.'_cycle'} = 10800;
    
    my $SeitenURL     = "http://api.wetter.com/forecast/weather";
    # Generieren der Checksumme, diese wird für jede Stadt neu berechnet
    my $Checksumme    = md5_hex($ProjektName.$ApiKey.$StadtCode); # Berechnen der Checksumme
    my $URL         = $SeitenURL."/city/".$StadtCode."/project/".$ProjektName."/cs/".$Checksumme; # Komplette URL zum Abruf der XML-Infos
    my $xml         = XMLin( get($URL) ); # Globales Array das die abgerufenen Wetterinformationen enthält
    
    # Wetterauswertung heute
    my $denro_heute = wetter_heute();
    knx_write($wetterdaten_ga,$denro_heute,16);
    
    # Wetterauswertung morgen
    my $denro_morgen = wetter_morgen();
    knx_write($wetterdaten_ga,$denro_morgen,16);
    
    # Wetterauswertung übermorgen
    my $denro_uebermorgen = wetter_uebermorgen();
    knx_write($wetterdaten_ga,$denro_uebermorgen,16);
    
    # Wiederholen des Sendens nach fünf Sekunden, da manchmal Werte "verschluckt" werden
    sleep(5);
    # Wetterauswertung heute
    my $denro_heute = wetter_heute();
    knx_write($wetterdaten_ga,$denro_heute,16);
    
    # Wetterauswertung morgen
    my $denro_morgen = wetter_morgen();
    knx_write($wetterdaten_ga,$denro_morgen,16);
    
    # Wetterauswertung übermorgen
    my $denro_uebermorgen = wetter_uebermorgen();
    knx_write($wetterdaten_ga,$denro_uebermorgen,16);
    
    return 0;
    
    sub wetter_heute {
      my $temp;
      my $tag_id = "00"; # heute
      # Früh
      my $code = substr($xml->{forecast}->{date}->[0]->{time}->[0]->{w},0,1);
      my $id_frueh = weatherCode_translation( $code );
      my $temp_min_frueh = $xml->{forecast}->{date}->[0]->{time}->[0]->{tn};
      my $temp_max_frueh =  $xml->{forecast}->{date}->[0]->{time}->[0]->{tx};
      my $temp_frueh = denro_temp($temp_min_frueh, $temp_max_frueh);
      # Nachnmittag
      $code = substr($xml->{forecast}->{date}->[0]->{time}->[1]->{w},0,1);
      my $id_mittag = weatherCode_translation( $code );
      my $temp_min_mittag = $xml->{forecast}->{date}->[0]->{time}->[1]->{tn};
      my $temp_max_mittag =  $xml->{forecast}->{date}->[0]->{time}->[1]->{tx};
      my $temp_mittag = denro_temp($temp_min_mittag, $temp_max_mittag);  
      # Abend 
      my $id_abend;
      my $temp_min_abend;
      my $temp_max_abend;
      if ( $abend_daten == "Abend" )
      {
         # Abends
         $code = substr($xml->{forecast}->{date}->[0]->{time}->[2]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[0]->{time}->[2]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[0]->{time}->[2]->{tx};
         
      } 
      else
      {
         # Nachts
         $code = substr($xml->{forecast}->{date}->[0]->{time}->[3]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[0]->{time}->[3]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[0]->{time}->[3]->{tx}; 
      }
      my $temp_abend = denro_temp($temp_min_abend, $temp_max_abend);   
    
      my $denro_value = chr($tag_id).chr(01).chr($temp_frueh).chr($temp_mittag).chr($temp_abend).chr(02).chr($id_frueh).chr($id_mittag).chr($id_abend).chr(04).chr(00).chr(255);
      return $denro_value; 
    }
    
    sub wetter_morgen {
      my $temp;
      my $tag_id = "01"; # morgen
      # Früh
      my $code = substr($xml->{forecast}->{date}->[1]->{time}->[0]->{w},0,1);
      my $id_frueh = weatherCode_translation( $code );
      my $temp_min_frueh = $xml->{forecast}->{date}->[1]->{time}->[0]->{tn};
      my $temp_max_frueh =  $xml->{forecast}->{date}->[1]->{time}->[0]->{tx};
      my $temp_frueh = denro_temp($temp_min_frueh, $temp_max_frueh);
      # Nachnmittag
      $code = substr($xml->{forecast}->{date}->[1]->{time}->[1]->{w},0,1);
      my $id_mittag = weatherCode_translation( $code );
      my $temp_min_mittag = $xml->{forecast}->{date}->[1]->{time}->[1]->{tn};
      my $temp_max_mittag =  $xml->{forecast}->{date}->[1]->{time}->[1]->{tx};
      my $temp_mittag = denro_temp($temp_min_mittag, $temp_max_mittag);  
      # Abend
      my $id_abend;
      my $temp_min_abend;
      my $temp_max_abend;
      if ( $abend_daten == "Abend" )
      {
         # Abends
         $code = substr($xml->{forecast}->{date}->[1]->{time}->[2]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[1]->{time}->[2]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[1]->{time}->[2]->{tx};
    
      }
      else
      {
         # Nachts
         $code = substr($xml->{forecast}->{date}->[1]->{time}->[3]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[1]->{time}->[3]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[1]->{time}->[3]->{tx};
      }
      my $temp_abend = denro_temp($temp_min_abend, $temp_max_abend);  
    
      my $denro_value = chr($tag_id).chr(01).chr($temp_frueh).chr($temp_mittag).chr($temp_abend).chr(02).chr($id_frueh).chr($id_mittag).chr($id_abend).chr(04).chr(00).chr(255);
      return $denro_value; 
    }
    
    sub wetter_uebermorgen {
      my $temp;
      my $tag_id = "02"; # übermorgen
      # Früh
      my $code = substr($xml->{forecast}->{date}->[2]->{time}->[0]->{w},0,1);
      my $id_frueh = weatherCode_translation( $code );
      my $temp_min_frueh = $xml->{forecast}->{date}->[2]->{time}->[0]->{tn};
      my $temp_max_frueh =  $xml->{forecast}->{date}->[2]->{time}->[0]->{tx};
      my $temp_frueh = denro_temp($temp_min_frueh, $temp_max_frueh);
      # Nachnmittag
      $code = substr($xml->{forecast}->{date}->[2]->{time}->[1]->{w},0,1);
      my $id_mittag = weatherCode_translation( $code );
      my $temp_min_mittag = $xml->{forecast}->{date}->[2]->{time}->[1]->{tn};
      my $temp_max_mittag =  $xml->{forecast}->{date}->[2]->{time}->[1]->{tx};
      my $temp_mittag = denro_temp($temp_min_mittag, $temp_max_mittag);  
      # Abend
      my $id_abend;
      my $temp_min_abend;
      my $temp_max_abend;
      if ( $abend_daten == "Abend" )
      { 
         # Abends
         $code = substr($xml->{forecast}->{date}->[2]->{time}->[2]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[2]->{time}->[2]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[2]->{time}->[2]->{tx};
      }
      else
      {
         # Nachts
         $code = substr($xml->{forecast}->{date}->[2]->{time}->[3]->{w},0,1);
         $id_abend = weatherCode_translation( $code );
         $temp_min_abend = $xml->{forecast}->{date}->[2]->{time}->[3]->{tn};
         $temp_max_abend =  $xml->{forecast}->{date}->[2]->{time}->[3]->{tx};
      }
      my $temp_abend = denro_temp($temp_min_abend, $temp_max_abend); 
    
      my $denro_value = chr($tag_id).chr(01).chr($temp_frueh).chr($temp_mittag).chr($temp_abend).chr(02).chr($id_frueh).chr($id_mittag).chr($id_abend).chr(04).chr(00).chr(255);
    
      return $denro_value; 
    }
    
    sub denro_temp {
        my $temp_min = shift;
        my $temp_max = shift;
        my $denro_temp_value;
        my $temp;
        # Abfrage welche Temperaturen der denro one anzeigen soll
        if ( $temp_ausgabe eq "Max" ) { $temp = $temp_max; }
        elsif ($temp_ausgabe eq "Min" ) { $temp = $temp_min; }
        elsif ($temp_ausgabe eq "Extrem" ) 
        {
           if ( abs( $temp_min ) >= abs( $temp_max ) ) { $temp = $temp_min; }
           else { $temp = $temp_max; }
        }
        else { $temp = round ( ($temp_min + $temp_max) / 2 ); }
        # Aufbereiten der negativen Temperaturwerte für den denro one
        if ( $temp < 0 ) { $denro_temp_value = 256 + $temp; } 
        else { $denro_temp_value = $temp; }
        return $denro_temp_value;
    }
    
    sub round {
        my $value = shift;          # 1. Wert enthält die Zahl die gerundet werden soll
        my $precision = int(shift); # 2. Wert enthält die Anzahl der Stellen nach dem Komma, auf die gerundet werden soll.
    
        # Speichert das Vorzeichen und setzt value auf den Absolutwert.
        my $sign = 1;
        if($value < 0) 
            { $sign = -1; }
        $value = abs($value);
    
        # Berrechnet den Genauigkeitsfaktor
        my $pFactor = 10 ** $precision;
        
        # Rundet den Wert
        $value = int(($value * $pFactor) + 0.5) / $pFactor;
        
        # Berücksichtigt das ursprüngliche Vorzeichen
        $value *= $sign;
        
        return $value;
    }
    
    sub weatherCode_translation {
      my $wether_code = shift;
      my $denro_id;
      # See denro documentation for codes: http://denro.com/media/files/handbuch_de/KNX-Telegramme_Wetter_de.pdf
      if    ( $wether_code == "0" ) { $denro_id = "01"; } # heiter
      elsif ( $wether_code == "1" ) { $denro_id = "02"; } # leicht bewölkt
      elsif ( $wether_code == "2" ) { $denro_id = "03"; } # partiell bewölkt
      elsif ( $wether_code == "3" ) { $denro_id = "04"; } # bewölkt
      elsif ( $wether_code == "4" ) { $denro_id = "12"; } # neblig
      elsif ( $wether_code == "5" ) { $denro_id = "16"; } # Nieselregen
      elsif ( $wether_code == "6" ) { $denro_id = "05"; } # Regen
      elsif ( $wether_code == "7" ) { $denro_id = "07"; } # Schnee
      elsif ( $wether_code == "8" ) { $denro_id = "09"; } # Regenschauer
      elsif ( $wether_code == "9" ) { $denro_id = "15"; } # Gewitter
      else                          { $denro_id = "02"; } # leicht bewölkt als default Wert 
      
      return $denro_id;
    }
    
    sub dec2hex {
       my $dec_value = shift;
       my $hex_value = sprintf("%02x", abs($dec_value));
       return $hex_value;
    }

    #2
    Wow, gerade erst gesehen; ich hab zwar keinen denro one aber das sieht sehr ordentlich aus!

    Kann man sicherlich auch gut als Basis für anderes verwenden.

    Makki
    EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
    -> Bitte KEINE PNs!

    Kommentar

    Lädt...
    X