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.
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;
}


Kommentar