Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
wetter:ws500:das_perl-script [08.03.2011 12:59. ] djangowetter:ws500:das_perl-script [31.10.2023 18:33. ] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +====== Das Perl-Scriptchen ======
 +
 +Zum Auslesen der [[wetter:ws500:stationsbeschreibung|Wetterstation]] und zum Befüllen der MySQL-Datenbank verwendete ich nachfolgendes Perl-Script:
 +
 +<code perl| ws500.pl>#!/usr/bin/perl -w
 +#
 +# ws500.pl: Ausleseprogramm fuer die WS500 von elv
 +#
 +# Copyright (C) 2006 Jochen, Basti, Django
 +#
 +# This program is free software; you can redistribute it and/or
 +# modify it under the terms of the GNU General Public License
 +# as published by the Free Software Foundation; either version 2
 +# of the License, or (at your option) any later version.
 +#
 +# This program is distributed in the hope that it will be useful,
 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +# GNU General Public License for more details.
 +#
 +# You should have received a copy of the GNU General Public License
 +# along with this program; if not, write to the Free Software
 +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 +# Or, point your browser to https://www.gnu.org/copyleft/gpl.html
 +#
 +# The author can be reached at  django[aett]mnet-mail[punkt]de
 +#
 +# The project's page is at https://omni128.de/dokuwiki/doku.php?id=ws:ws500
 +#
 +
 +use Device::SerialPort;
 +use POSIX qw(locale_h);                                          
 +use locale;
 +use DBI;
 +use DBD::mysql;
 +use IO::File;
 +
 +use strict;                                                             # Nur sauber programmierter Perlcode wird akzeptiert
 +use warnings;                                                           # Aktivierung des Warnmechanismus von Perl
 +use diagnostics;                                                        # Aktivierung zusaetzlicher Informationen bei Fehlermeldungen
 +
 +
 +# --- Definition der Systemeinstellungen --- #
 +
 +our $dev;
 +our $lastcount;
 +our $debug;
 +our $reporting;
 +our $mailinfo;
 +our $mailto;
 +our $mailfrom;
 +our $Sendmail_Prog;
 +our $logfile;
 +our $writeToFile;
 +our $recordFile;
 +our $statusFile;
 +our $server;
 +our $mysqlusage;
 +our $dbhost;
 +our $dbuser;
 +our $dbpasswd;
 +our $dbdatabase;
 +#our $sqllogger;
 +
 +# --- Definition der Systemvariablen --- #
 +
 +my @sensoren_status;
 +my @empfausfall;                                                        # Zaehler fuer Empfangsausfaelle der Station
 +my @RXBuffer;
 +my @TXBuffer;
 +my @feuchte;
 +my @temperatur;
 +my @csvzeile;
 +my @sensor_db;
 +
 +
 +my $FTDI;
 +my $absdruck;
 +my $charakter;
 +my $commandstring;
 +my $druck;
 +my $errorcount;
 +my $firmware = 2.50;                                                    # test
 +my $firstrun;
 +my $framelaenge = 0;
 +my $hexcharakter;
 +my $hoehe;
 +my $i;
 +my $input;
 +my $intervall;
 +my $is_offline;
 +my $is_raining;
 +my $korrhoehe = "50";
 +my $meterbytehigh;
 +my $meterbytelow;
 +my $newmysqltime;
 +my $offset = 0;
 +my $oldIntervall;
 +my $oldmysqltime;
 +my $online;
 +my $paniccount;
 +my $recordtime;
 +my $sensor_db;
 +my ( $regen,$regen_alt,$regen_delta,$regen_menge,$regen_db );
 +my ( $sonne,$sonne_alt,$sonne_delta,$sonne_menge,$sonne_ok,$sonne_db );
 +my ($sth,$sqlstate,$sqllogger,$sql,$query,$dbh);                        # MySQL-Variablen
 +my $time_next_record;
 +my $time_next_developstatus;
 +my $time_nr;
 +my $tmp;
 +my $tmpstring;
 +my $type;
 +my $Version = "0.1.2";
 +my $wettervorhersage;
 +my ( $wind_geschwindigkeit,$wind_richtung,$wind_schwankung );
 +my $wippe;
 +my $wippebytehigh;
 +my $wippebytelow;
 +my $writeString;
 +
 +
 +require '/etc/ws500/ws500.conf';                                        # Dateiname und Pfad für die Konfigurationsdatei
 +
 +##########################################################################################################################################################
 +# *** START *** Hauptprogramm
 +##########################################################################################################################################################
 +
 +write_Log ("====================================================\n                          Programm $0: Version $Version gestartet.\n                          ====================================================");                                     # Programmstart dokumentieren#
 +print STDERR "\nProgramm $0: Version: $Version zum Auslesen der WS500 wird gestartet:\n\n";
 +get_lastcount();                                                        # letzten Zaehlerstaende fuer light und rain wieder zurueckholen
 +connect_MySQL () if ($mysqlusage == 1);                                 # MySQL-Datenbankanbindung herstellen, sofern gewuenscht
 +
 +$time_next_developstatus = time();
 +$time_next_record = time();                                             # Versuchsballon!
 +$intervall = 0;
 +$is_offline = 0;
 +$firstrun = 1;
 +
 +while ( 1 ) {                                                           # "Endlosschleife"
 +        my $theMessage = shift;
 +
 +        if ($time_next_developstatus <= time()) {
 +                $paniccount = 0;
 +                $oldIntervall = $intervall;
 +                init_USB();
 +                write_Log ("get_DEVELOP_STATUS()");
 +                $tmp = get_DEVELOP_STATUS();
 +                while (!$tmp && ($paniccount < 5)) {                    # 5x Versuchen den Status der Station abzufragen
 +                        $paniccount++;
 +                        $tmp = get_DEVELOP_STATUS();
 +                }
 +                close_USB();
 +                if ($paniccount >= 5){                                  # sind die 5 Versuche Fehlgeschlagen, dann hier weiter
 +                        print "1.Warnung: Verbindung zur WS500 gestoert! \nMoegliche Ursachen koennten sein:\n";
 +                        print "  ° USB Verbindung wurde unterbrochen\n";
 +                        print "  ° Station gerade in Sync-Modus\n";
 +                        print "Verbindungsaufbau erfolgt automatisch erneut in einer Minute!\n";
 +                        write_Log ("USB-Verbindung gestoert!");
 +                        $theMessage = "Warnung: Verbindung zur WS500 gestoert! \nVerbindungsaufbau erfolgt automatisch erneut in einer Minute!\n";
 +                        send_Mail($theMessage);
 +
 +                        $is_offline = 1;
 +                        if ($firstrun == 1) {
 +                                sleep 60;                               # beim ersten Mal müssen erst die kritischen Variablen befüllt werden!
 +
 +                ####TEST####
 +                                init_USB();
 +                                write_Log ("2nd try to get_DEVEOLOP_STATUS()");
 +                                $tmp = get_DEVELOP_STATUS();
 +                                while (!$tmp && ($paniccount < 5)) {    # 5x Versuchen den Status der Station abzufragen
 +                                        $paniccount++;
 +                                        $tmp = get_DEVEOLOP_STATUS();
 +                                }
 +                        close_USB();
 +                ####TEST####
 +
 +                        }
 +                        else {
 +                                $time_next_developstatus =  time() + 60;# einfach in einer Minute noch mal versuchen.
 +                        }
 +                        $paniccount = 0;
 +                }
 +
 +                if (($tmp == 1) && ($is_offline == 1)) {
 +                        $is_offline = 0;
 +                        write_Log ("USB-Verbindung wiederhergestellt!");
 +                        $theMessage = "Information: Verbindung zur WS500 besteht wieder! Werde nun die Konfiguration auslesen.\n";
 +                        send_Mail($theMessage)
 +                }
 +
 +                if ($is_offline == 0) {
 +                        if ($oldIntervall != $intervall) {
 +                                $firstrun = 0;
 +                                $time_next_record = time();
 +                                write_Log ("naechste Record(next)-Abfrage: ".localtime($time_next_record));
 +                        }
 +
 +                        write_Status_To_File();
 +                        $time_next_developstatus =  time() + $intervall*60 if ($is_offline == 0);
 +                        write_Log ("naechste Konfig-Abfrage: ".localtime($time_next_developstatus));
 +                }
 +        }
 +
 +        if ($time_next_record <= time()) {
 +                write_Log ("entering next_record()");
 +                init_USB();
 +                if (get_CURRENT_RECORD()) {
 +                        if ($is_offline == 1) {
 +                                $is_offline = 0;
 +                                write_Log ("Verbindung wiederhergestellt!");
 +                        }
 +                }
 +
 +                $errorcount = 0;
 +
 +                do {                                                    #solange noch Daten gespeichert sind
 +                        write_Log ("checking next record...()");
 +
 +                        if (get_NEXT_RECORD() == 1) {
 +                                write_Log ("get_NEXT_RECORD()");
 +                                if ($is_offline == 1) {
 +                                        $is_offline = 0;
 +                                        write_Log ("Verbindung wiederhergestellt!");
 +                                }
 +                                prozess_DATA();                         # Weitere Bearbeitung der Datensaetze
 +                        }
 +
 +                        if ($framelaenge == 0) {
 +                                $paniccount++;
 +                        }
 +                        if ($framelaenge < 5) {
 +                                $errorcount++;
 +                        }
 +                        else
 +                        {
 +                                $errorcount = 0;
 +                                $paniccount = 0;
 +                        }
 +                } until (($framelaenge < 5) && ($errorcount > 5) );
 +                close_USB();
 +                if ($paniccount >= 5){
 +                        print "2.Warnung: Verbindung zur WS500 gestoert! \nMoegliche Ursachen koennten sein:\n";
 +                        print "  ° USB Verbindung wurde unterbrochen\n";
 +                        print "  ° Station gerade in Sync-Modus\n";
 +                        print "Verbindungsaufbau erfolgt automatisch erneut in einer Minute!\n";
 +                        write_Log ("USB-Verbindung gestoert!");
 +                        $theMessage = "Warnung: Verbindung zur WS500 gestoert! \nVerbindungsaufbau erfolgt automatisch erneut in einer Minute!\n";
 +                        send_Mail($theMessage);
 +                        
 +                        $paniccount = 0;
 +                        $time_next_record =  time() + 60;               #in 60 sekunden noch mal nachschauen
 +                        $is_offline = 1;
 +                }
 +                $time_next_record =  time() + $intervall*60 if ($is_offline == 0);
 +                write_Log ("naechste Record(next)-Abfrage: ".localtime($time_next_record));
 +        }
 +
 +        sleep 1;
 +}
 +
 +##########################################################################################################################################################
 +# *** ENDE *** Hauptprogramm
 +##########################################################################################################################################################
 +
 +
 +##############################################################################
 +### ab hier sind die ueberarbeiteten Unterprogramme alphabetisch abgelegt: ###
 +##############################################################################
 +
 +# *** START *** Unterprogramm "byte2Int" zum Umrechnen eines zwei Bytewertes in eine ganze Zahl
 +sub byte2Int {
 +        my $highbyte = shift;                                           # Variable leeren
 +        my $lowbyte  = shift;                                           # Variable leeren
 +
 +#       if ($highbyte > 127) {
 +#               $highbyte -= 128;
 +#               return(($highbyte*255+$lowbyte)*-1);
 +#       }
 +        if ($highbyte == 255) {                                         # wenn Highbyte gleich "FF" ist, dann ist der Wert
 +#               $highbyte = 0;
 +#               return(($highbyte*-255+$lowbyte)*-1);
 +                return(($lowbyte)-256);                                 # Lowbayte minus 256
 +        }
 +        else
 +        {
 +                return($highbyte*255+$lowbyte);                         # ansonsten ganz "normal" weiterrechnen
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "byte2Int" zum Umrechnen eines zwei Bytewertes in eine ganze Zahl
 +
 +# *** START *** Unterprogramm "close_USB" zum Schliessen der USB-Kommunikationsschnittstelle
 +sub close_USB {
 +        write_Log ("USB-RS232-Port wird geschlossen...\n                          ----------------------------------------------------");
 +#       my $rts=$FTDI->rts_active(0);
 +#       $FTDI->purge_all;
 +               
 +        $FTDI->close || write_Log ("USB-RS232-Port wird geschlossen -> Fehler!");
 +        $online = 0;
 +}
 +# *** ENDE ***  Unterprogramm "close_USB" zum Schliessen der USB-Kommunikationsschnittstelle
 +
 +# *** START *** Unterprogramm "connect_MySQL" zum Herstellen der Datenbankanbindung an die Wetterdatenbank
 +sub connect_MySQL {
 +        my $theMessage = shift;
 +        $dbh = DBI -> connect ("DBI:mysql:$dbdatabase:$dbhost",$dbuser,$dbpasswd,
 +        {
 +        PrintError => 0,
 +        }
 +        );
 +        unless ( $dbh ) {
 +                write_Log ("MySQL-Datenbankverbindungsaufbau fehlgeschlagen!");
 +                $theMessage = "Verbindung zur MySQL-Datenbank $dbdatabase auf $dbhost konnte nicht hergestellt werden!\n";
 +                send_Mail($theMessage);
 +                die ("Verbindung zur MySQL-Datenbank $dbdatabase auf $dbhost konnte nicht hergestellt werden!\n");
 +        }
 +        write_Log ("Verbindung zur MySQL-Datenbank wurde hergestellt.");
 +}
 +# *** ENDE *** Unterprogramm "connect_MySQL" zum Herstellen der Datenbankanbindung an die Wetterdatenbank
 +
 +# *** START *** Unterprogramm "convert_Time" zum Umformatieren von Datum & Uhrzeit
 +sub convert_Time {
 +        my $oldtime = shift;
 +
 +        my $date=gmtime($oldtime);                                      # Datum
 +        my @date=gmtime($oldtime);                                      # Datum
 +        my $sekunde=sprintf("%02d",$date[0]);                           # Sekunden
 +        my $minute=sprintf("%02d",$date[1]);                            # Minuten
 +        my $stunde=sprintf("%02d",$date[2]);                            # Stunden
 +        my $tag=sprintf("%02d",$date[3]);                               # Tag
 +        my $mon=sprintf("%02d",$date[4]+1);                             # Monat korrigiert um "+1", da 0-11
 +        my $jahr=sprintf("%04d",$date[5]+1900);                         # Jahr korrigiert mit "+1900" für 4-stellige Anzeige
 +        my $minus = "-";                                                # Datumstrennzeichen
 +        my $leer = " ";                                                 # Trennzeichen zwischen Datum und Uhrzeit
 +        my $doppelpunkt = ":";                                          # Uhrzeittrennzeichen
 +
 +        $newmysqltime = $jahr.$minus.$mon.$minus.$tag.$leer.$stunde.$doppelpunkt.$minute.$doppelpunkt.$sekunde;
 +
 +#       return ($newmysqltime);
 +}
 +# *** ENDE ***  Unterprogramm "convert_Time" zum Umformatieren von Datum & Uhrzeit
 +
 +# *** START *** Unterprogramm "escapeByte" zum Behandeln des empfangenen Escape-Bytes xF8
 +sub escapeByte {
 +        my $addbyte = shift;
 +        if (is_Escape_Chr($addbyte)) {
 +                write_Log ("byte escaped!: ".$tmpstring);
 +                $commandstring .= "\xF8".chr(($addbyte-1));
 +        }
 +        else {
 +                $commandstring .= chr($addbyte);
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "escapeByte" zum Behandeln des empfangenen Escape-Bytes xF8
 +
 +# *** START *** Unterprogramm "get_CURRENT_RECORD" zum Ausgeben des aktuellen Datensatzes der WS500
 +sub get_CURRENT_RECORD {
 +        write_ws500("\xFE\x33\xFC");
 +        read_ws500();
 +        write_Array();
 +        if ($framelaenge >= 40) {
 +                read_RECORD_Frame();
 +
 +                if ($debug == 1) {
 +                        print "+-------------------------------------------------------+\n";
 +                        print "+\t\taktueller Datensatz\t\t\t|\n";
 +                        print "+-------------------------------------------------------+\n";
 +                        print "|\tRegenmenge: ".$regen." Impulse\t\t\t\t|\n";
 +                        print "|\tWind: ".$wind_geschwindigkeit." km/h\t\t\t\t\t|\n";
 +                        print "|\tWindrichtung: ".$wind_richtung." °\t\t\t\t|\n";
 +                        print "|\tWindschwankung: ".$wind_schwankung." °\t\t\t\t|\n";
 +                        print "|\tLuftdruck (rel.): ".$druck." hPa\t\t\t|\n";
 +                        print "|\tLuftdruck (abs.): ".$absdruck." hPa\t\t\t|\n";
 +                        print "|\tSonnenscheindauer: ".$sonne." Minuten\t\t\t|\n";
 +                        print "|\tWetterstatus:  ".$wettervorhersage."\t\t\t\t|\n";
 +                        for ($i=0; $i < 10; $i++) {
 +                                print "+-------------------------------------------------------+\n";
 +                                print "|\tTemperatur ".$i."= ".$temperatur[$i]."°C\t\t\t\t|\n";
 +                                print "|\tFeuchte ".$i."   = ".$feuchte[$i]."% rel\t\t\t\t|\n";
 +                        }
 +                        print "+-------------------------------------------------------+\n\n\n";
 +                }
 +        }
 +        return ($framelaenge >= 40);
 +}
 +# *** ENDE ***  Unterprogramm "get_CURRENT_RECORD" zum Ausgeben des aktuellen Datensatzes der WS500
 +
 +# *** START *** Unterprogramm "get_DEVEOLOP_STATUS" zum Ausgeben des Konfigurationsdatensatzes der WS500
 +sub get_DEVELOP_STATUS {
 +        my $theMessage = shift;
 +        get_FIRMWARE();
 +#       get_FIRMWARE() if ($firstrun == 1);
 +        write_ws500("\xFE\x32\xFC");
 +        read_ws500();
 +        write_Array();
 +
 +                                                                        # Config auslesen
 +        if ($framelaenge >= 17) {
 +                if ($RXBuffer[1] == 50)                                 # config record
 +                {
 +                        $offset = 2;
 +
 +                        for ($i=1; $i < 10; $i++) {
 +                                $sensoren_status[$i] = unescapeByte() - 16;
 +
 +                                        if ($sensoren_status[$i] < 0) {
 +                                                $sensor_db[$i] = "0";
 +                                        }
 +                                        else {
 +                                                $sensor_db[$i] = "1";
 +                                        }
 +
 +                                        if ($sensoren_status[$i] > 0 ) {
 +                                                $theMessage = "Die Kommunikation der WS500 mit dem Fuehler $i ist unterbrochen! Es sind $sensoren_status[$i] Funkausfaelle zu verzeichnen!\n";
 +                                                send_Mail($theMessage);
 +                                                }
 +                                        }
 +                        }
 +                        $sensor_db[0] = "1";                            # Innensensor ist immer vorhanden
 +
 +                        $intervall = unescapeByte();
 +                        $hoehe = unescapeByte()*255 + unescapeByte();
 +                        $wippe = unescapeByte()*255 + unescapeByte();
 +
 +                        for ($i=1; $i < 10; $i++) {
 +
 +                        if ($debug == 1)
 +                        {
 +                                print "+-------------------------------------------------------+\n";
 +                                print "+\t\t    Stations-Status \t\t\t|\n";
 +                                print "+-------------------------------------------------------+\n";
 +                                print "|\tFirmware: ".$firmware."\t\t\t\t\t|\n";
 +                                print "|\tMessintervall: ".$intervall." Minuten\t\t\t|\n";
 +                                print "|\tHoehe: ".$hoehe." m ue. NN\t\t\t\t|\n";
 +                                print "|\tWippe: ".$wippe." ml/Impuls\t\t\t\t|\n";
 +
 +                                                $sensor_db[0] = "1";
 +
 +                                for ($i=1; $i < 10; $i++) {
 +                                        if ($sensoren_status[$i] < 0) {
 +                                                print "|\tSensor ".$i.": nicht verfuegbar\t\t\t|\n";
 +                                        }
 +                                        else {
 +                                                print "|\tSensor ".$i.": verfuegbar (Empfangsausfaelle: ".$sensoren_status[$i].")\t|\n";
 +                                        }
 +                                }
 +                                print "+-------------------------------------------------------+\n\n\n";
 +                        }
 +                }
 +        }
 +        return ($framelaenge >= 17);
 +}
 +# *** ENDE ***  Unterprogramm "get_DEVEOLOP_STATUS" zum Ausgeben des Konfigurationsdatensatzes der WS500
 +
 +# *** START *** Unterprogramm "get_FIRMWARE" zum Auslesen der Firmwareversion der WS500
 +sub get_FIRMWARE {
 +        write_ws500("\xFE\x34\xFC");
 +        read_ws500();
 +
 +        if ($framelaenge >= 4) {
 +                $firmware = (sprintf("%x",$RXBuffer[2]))/10;
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "get_FIRMWARE" zum Auslesen der Firmwareversion der WS500
 +
 +# *** START *** Unterprogramm "get_lastcount" zum Holen der beiden letzten Zaehlerstaende fuer Regen und Sonnenschein
 +sub get_lastcount {
 +        if(!open(BACKUPFILE, "+<".$lastcount)) {
 +                $reporting = 0;
 +                print "Konnte auf Recorddatei ".$lastcount." nicht zugreifen!\n";
 +        }
 +        print BACKUPFILE "";
 +        close(BACKUPFILE) || warn "close failed";
 +
 +        $sonne_alt = 0;                                                 # Sonnenwert zuruecksetzen
 +        $regen_alt = 0;                                                 # Regenwert zuruecksetzen
 +
 +        open (BACKUPFILE,$lastcount) or die "Fehler beim Oeffnen der CSV-Datei";
 +
 +                while (<BACKUPFILE>) {
 +                if (m/^\s*#/o) {next;};                                 # Kommentazeilen ueberspringen
 +                @csvzeile = split /;/,$_;                               # Zeile aufsplitten und in Array uebergeben
 +                $regen_alt = $csvzeile [0];                             # letzter Regenwert aus Feld/Spalte "1" holen
 +                $sonne_alt = $csvzeile [1];                             # letzter Sonnenwert aus Feld/Spalte "2" holen
 +
 +        }
 +        write_Log ("Letzte Werte fuer Regen und Sonnenschein wurden aus $lastcount gelesen");
 +        close(BACKUPFILE);
 +}
 +# *** ENDE ***  Unterprogramm "get_lastcount" zum Holen der beiden letzten Zaehlerstaende fuer Regen und Sonnenschein
 +
 +# *** START *** Unterprogramm "get_NEXT_RECORD" zum Ausgeben der historischen Datensaetzes der WS500
 +sub get_NEXT_RECORD {
 +        write_ws500("\xFE\x31\xFC");
 +        read_ws500();
 +        if ($framelaenge >= 40) {
 +                write_Array(@RXBuffer);
 +                read_RECORD_Frame();
 +
 +                if ($debug == 1){
 +                        print "+-------------------------------------------------------+\n";
 +                        print "|\t Datensatz - Nummer ".$time_nr." \t\t\t\t|\n";
 +                        print "+-------------------------------------------------------+\n";
 +                        print "|\tRegen (alt): ".$regen_alt." Impulse\t\t\t|\n";
 +                        print "|\tRegen (neu): ".$regen." Impulse\t\t\t|\n";
 +                        print "|\tRegenmenge:  ".$regen_delta." Impulse   \t\t\t|\n";
 +                        print "|\tRegenmenge: ".$regen_menge." ml pro m^2\t\t\t|\n";
 +                        print "|\tWind: ".$wind_geschwindigkeit." km/h\t\t\t\t\t|\n";
 +                        print "|\tWindrichtung: ".$wind_richtung." °\t\t\t\t|\n";
 +                        print "|\tWindschwankung: ".$wind_schwankung." °\t\t\t\t|\n";
 +                        print "|\tLuftdruck (rel.): ".$druck."hPa\t\t\t|\n";
 +                        print "|\tLuftdruck (abs.): ".$absdruck."hPa\t\t\t|\n";
 +                        print "|\tSonne (alt): ".$sonne_alt." Minuten\t\t\t|\n";
 +                        print "|\tSonne (neu): ".$sonne." Minuten\t\t\t|\n";
 +                        print "|\tSonnenscheindauer: ".$sonne_delta." Minuten\t\t\t|\n";
 +                        print "|\tWetterstatus:  ".$wettervorhersage."\t\t\t\t|\n";
 +                                for ($i=0; $i < 10; $i++) {
 +                                        print "+-------------------------------------------------------+\n";
 +                                        print "|\tTemperatur ".$i."= ".$temperatur[$i]."°C\t\t\t\t|\n";
 +                                        print "|\tFeuchte ".$i."   = ".$feuchte[$i]."% rel\t\t\t\t|\n";
 +                                }
 +                                print "+-------------------------------------------------------+\n\n\n";
 +                }
 +        }
 +        else {
 +                write_Log ("Fehler: Framelaenge: ".$framelaenge);
 +        }
 +        return ($framelaenge >= 40);                                    # gibt true zurueck, falls erfolgreich ein Datensatz ausgelesen wurde
 +}
 +# *** ENDE ***  Unterprogramm "get_NEXT_RECORD" zum Ausgeben der historischen Datensaetzes der WS500
 +
 +
 +# *** START *** Unterprogramm "init_USB" zum Konfigurieren der Datenkommunikation mittels FTDI-Treiber mit der WS500
 +sub init_USB {
 +        $FTDI->close if(defined($FTDI));
 +        $FTDI = tie(*FTD, 'Device::SerialPort', $dev) || die "Oeffnen des Geraetes $dev: fehlgeschlagen!\n";
 +        $FTDI->user_msg(1);
 +        $FTDI->reset_error();
 +        my $baud      = $FTDI->baudrate(19200);
 +        my $dbits     = $FTDI->databits(8);
 +        my $parity    = $FTDI->parity('even');
 +        my $sbits     = $FTDI->stopbits(1);
 +#       my $handshake = $FTDI->handshake('rts');
 +        my $handshake = $FTDI->handshake('none');
 +        my $rts=$FTDI->rts_active(0);
 +        $FTDI->purge_all;
 +        if ($debug == 1) {
 +                print "Konfiguriere USB-RS232-Port ($dev) ...\n\n\n";
 +                print "+-------------------------------------------------------+\n";
 +                print "   Die Einstellungen zur Datenkommunikation lauten:   |\n";
 +                print "+-------------------------------------------------------+\n";
 +                print "|\t\tBaudrate  : ".$baud."\t\t\t|\n";
 +                print "|\t\tDatenbits : ".$dbits."\t\t\t\t|\n";
 +                print "|\t\tStopbits  : ".$sbits."\t\t\t\t|\n";
 +                print "|\t\tParity    : ".$parity."\t\t\t|\n";
 +                print "|\t\tHandshake : ".$handshake."\t\t\t|\n";
 +                print "|\t\tRTS       : ".$rts."\t\t\t\t|\n";
 +                print "+-------------------------------------------------------+\n\n\n";
 +        }
 +        $online = 1;
 +        write_Log ("----------------------------------------------------\n                          USB-RS232-Port wird geoeffnet...");
 +        select(undef, undef, undef, 0.25);                              # warte 0,25 Sekunden und mache dann weiter
 +}
 +# *** ENDE ***  Unterprogramm "init_USB" zum Konfigurieren der Datenkommunikation mittels FTDI-Treiber mit der WS500
 +
 +# *** START *** Unterprogramm "is_Escape_Chr" 
 +sub is_Escape_Chr {
 +        my $theChr = shift;
 +        return (($theChr == 0xF8 || $theChr == 0xF8 || $theChr == 0xF8) );
 +}
 +# *** START *** Unterprogramm "is_Escape_Chr"
 +
 +# *** START *** Unterprogramm "prozess_DATA" zum Uebertragen der Daten in die Datenbanken und Dateien
 +sub prozess_DATA {
 +
 +        write_lastcount();                                              # Zaehlerstaende "sun & rain" sichern
 +        write_MySQL() if ($mysqlusage == 1);                            # MySQL-Datenbank "wetter" befuellen, falls gewuenscht
 +        write_Record_to_File() if ($writeToFile == 1);                  # Wetterdaten in CSV-Datei schreiben, falls gewuenscht
 +        $regen_alt = $regen;                                            # neuer "alte Wert" = aktueller Wert
 +        $sonne_alt = $sonne;                                            # neuer "alte Wert" = aktueller Wert
 +        print "ausglesn und weggschrim is'\n";                          # Fortschrittsbalken andeuten                                                               
 +
 +}
 +# *** ENDE *** Unterprogramm "prozess_DATA" zum Uebertragen der Daten in die Datenbanken und Dateien
 +
 +# *** START *** Unterprogramm "read_RECORD_Frame" zum Auslesen und Auswerten des Empfangspuffers
 +sub read_RECORD_Frame {
 +        if ((($RXBuffer[1] == 49) || ($RXBuffer[1] == 51)) && ($framelaenge >= 40))  
 +        {
 +                if ($RXBuffer[1] == 51) {                               # aktueller Datensatz
 +                        $offset   = 2;
 +                        $time_nr  = 0;
 +                        $type     = "c";
 +                }
 +                else {                                                  # naechster Datensatz
 +                        $offset   = 4;
 +                        $time_nr  = unescapeByte()*255 + unescapeByte();
 +                        $type     = "n";
 +                }
 +
 +                $recordtime = time()-($time_nr*60);                     # Alter des Datensatzes rueckrechnen
 +                $oldmysqltime = ( gmtime($recordtime) );
 +                convert_Time ( $recordtime );
 +
 +                undef @temperatur;
 +                undef @feuchte;
 +                for (my $i=1; $i < 10; $i++) {
 +                        $temperatur[$i]= (byte2Int(unescapeByte(),unescapeByte())) / 10;
 +                        $feuchte[$i]= unescapeByte();
 +                }
 +
 +                $regen = (unescapeByte()*255 + unescapeByte());
 +                $regen_delta = $regen - $regen_alt;
 +                $regen_menge = $regen_delta * $wippe;
 +                if( $regen_delta eq "0") {
 +                        $regen_db = "0";
 +                        }
 +                else {
 +                       $regen_db = "1";
 +                }
 +                $wind_geschwindigkeit = (unescapeByte()*255 + unescapeByte()) / 10; 
 +                $wind_richtung = (unescapeByte() * 5);
 +                $wind_schwankung = (unescapeByte() * 5);
 +                $sonne = (unescapeByte()*255 + unescapeByte());
 +                $sonne_delta = $sonne - $sonne_alt;
 +                if( $sonne_delta eq "0") {
 +                        $sonne_ok = 0;
 +                        $sonne_db = "0";
 +                        }
 +                else {
 +                       $sonne_ok = 1;
 +                       $sonne_db = "1";
 +                }
 +
 +                $temperatur[0] = ( byte2Int(unescapeByte(),unescapeByte())) / 10; 
 +                $feuchte[0] = unescapeByte();
 +                $druck = (unescapeByte()*255 + unescapeByte());
 +                $absdruck = $druck; 
 +                $druck = $druck * ( 2.718 ** ( ( ( $hoehe + $korrhoehe ) * 9.8066 ) / ( 287.05 * ( $temperatur[0] + 273.15 )  ) ) ) ; 
 +                $druck = sprintf ("%.0f", $druck);                      # Umrechnung des relativen ind den absoluten Luftdruck ohne Nachkommastellen runden
 +
 +                if ($type eq "c") {
 +                        $wettervorhersage = unescapeByte();
 +                                                                        # 3 = schwuel, 
 +                        $is_raining = ($wettervorhersage > 120);
 +                }
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "read_RECORD_Frame" zum Auslesen und Auswerten des Empfangspuffers
 +
 +# *** START *** Unterprogramm "read_ws500" zum Auswerten des Empfangspuffers und in einzelne Bytes aufteilen
 +sub read_ws500 {
 +        my $i = 0;
 +        $input = $FTDI->input();
 +        $framelaenge = length($input);
 +        undef @RXBuffer;                                                # Die Ergebnisse werden in @RXBuffer gespeichert 
 +        foreach $charakter (split(//,$input)) {                         # Datenbytes in Array lesen 
 +                $RXBuffer[$i] = ord($charakter);                        # in Bytes umwandeln
 +                $i++;
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "read_ws500" zum Auswerten des Empfangspuffers und in einzelne Bytes aufteilen
 +
 +# *** START *** Unterprogramm "send_Mail" zum Schicken von Warn-/Fehlermeldung an den WS-User
 +sub send_Mail {
 +        my $theMessage = shift;
 +        if ($mailinfo == 1) {
 +                open(MAIL,"|$Sendmail_Prog -t") || print STDERR "Mailprogramm konnte nicht gestartet werden\n";
 +                print MAIL "From: $mailfrom\n";
 +                print MAIL "To: $mailto\n";
 +                print MAIL "Subject: WS500-Errormeldung\n\n";
 +                print MAIL ".$theMessage.\n";
 +                close(MAIL);
 +        }
 +        return 0;
 +}
 +# *** ENDE ***  Unterprogramm "send_Mail" zum Schicken von Warn-/Fehlermeldung an den WS-User
 +
 +# *** START *** Unterprogramm "sqlquery" zum Vorbereiten und Loggen der SQL-Queries
 +sub sqlquery {
 +        $query=shift();
 +        $sth=$dbh->prepare($query);
 +        $sth->execute();
 +        $sqlstate = $dbh->state;
 +        unless ($sqlstate) {$sqlstate='00000';};
 +        $sqllogger .= "executed '$query' result '$sqlstate' \n";
 +        sysopen(FHNEW,"sqllog1.txt",O_CREAT|O_WRONLY|O_APPEND) || die "can't open logger file: $!";
 +        syswrite(FHNEW,$sqllogger,length($sqllogger));
 +        close(FHNEW);
 +        $sqllogger = '';
 +}
 +# *** START *** Unterprogramm "sqlquery" zum Vorbereiten und Loggen der SQL-Queries
 +
 +# *** START *** Unterprogramm "unescapeByte" zum Behandeln des empfangenen Bytes
 +sub unescapeByte {
 +        my $tmp = 0;
 +        if (is_Escape_Chr($RXBuffer[$offset])) {
 +                $offset++;
 +                $tmp = $RXBuffer[$offset] - 1;
 +        }
 +        else {
 +
 +                $tmp = $RXBuffer[$offset];
 +        }
 +        $offset++;
 +        return( $tmp );
 +}
 +# *** STOP ***  Unterprogramm "unescapeByte" zum Behandeln des empfangenen Bytes
 +
 +# *** START *** Unterprogramm "write_Array" zum Ausgeben der empfangenen Bytes (hexadezimal und dezimal)
 +sub write_Array {
 +        if ($debug == 1){
 +                print "Der empfangene Datensatz lautet:\n";
 +                foreach $charakter (@RXBuffer) {
 +                        $hexcharakter = sprintf("%x", $charakter );
 +                        print $hexcharakter.", ";                
 +                }
 +                print "\nbzw.:\n";
 +                foreach $charakter (@RXBuffer) {
 +                        print $charakter.", ";
 +                }
 +                print "\n\n\n";
 +        }
 +        return 0;
 +}
 +# *** ENDE ***  Unterprogramm "write_Array" zum Ausgeben der empfangenen Bytes (hexadezimal und dezimal)
 +
 +# *** START *** Unterprogramm "write_Config" zum Uebertragen der Konfiguration in Richtung WS500
 +sub write_Config { 
 +        my $zeit = shift;
 +        my $meter = shift;
 +        my $mmwippe = shift;
 +
 +        if (($zeit >= 5) && ($zeit < 100) && ($meter >= 0) && ($meter < 2000) && ($mmwippe >= 200) && ($mmwippe < 400)) {
 +                $meterbytehigh = int($meter / 255);
 +                $meterbytelow = $meter % 255;
 +                $wippebytehigh = int($mmwippe / 255);
 +                $wippebytelow = $mmwippe % 255;
 +                write_Log ("Werte: meter:".$meter."(h:".$meterbytehigh." l:".$meterbytelow.") mmwippe:".$mmwippe."(h:".$wippebytehigh." l:".$wippebytelow.") zeit:".$zeit);
 +                $commandstring = "\xFE\x30\xFC\xFE\x30".chr($zeit);
 +                escapeByte($meterbytehigh);
 +                escapeByte($meterbytelow);
 +                escapeByte($wippebytehigh);
 +                escapeByte($wippebytelow);
 +                $commandstring .= "\xFC";
 +                #achtung:
 +                #$commandstring = "\xFE\x30\xFC\xFE\x30\x5\x0\x89\x1\x27\xFC";
 +                if ($reporting == 1) {
 +                        $tmpstring = "";
 +                        foreach $charakter (split (//,$commandstring)) {
 +                                $tmpstring .= ord($charakter).", ";
 +                        }
 +                        write_Log ("schreibe Commandstring: ".$tmpstring);
 +                }
 +                write_Log ("Schnittstellenstatus:  ".$online);
 +                my $laststatus = $online;
 +                init_USB() if(!$laststatus);
 +        #####   WS500_write($commandstring);
 +                close_USB() if(!$laststatus);
 +
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "write_Config" zum Uebertragen der Konfiguration in Richtung WS500
 +
 +# *** START *** Unterprogramm "write_dev_2_MySQL" zum Uebertragen der Wetterdaten in die MySQL-Datenbank
 +sub write_dev_2_MySQL {
 +        $sql="INSERT INTO $dbdatabase.rain VALUES ('','$newmysqltime','1','1','$regen','$regen_menge','1')";
 +        sqlquery($sql);
 +
 +        write_Log ("aktuelle Konfigurationsdaten in die MySQL-Datenbank eingetragen");
 +}
 +# *** ENDE ***  Unterprogramm "write_dev_2_MySQL" zum Uebertragen der Wetterdaten in die MySQL-Datenbank
 +
 +# *** START *** Unterprogramm "write_lastcount" zum Speichern der letzten Zaehlerstaende fuer Regen und Licht
 +sub write_lastcount {
 +        if(!open(BACKUPFILE, ">".$lastcount)) {                         # Datei zum "Schreiben" oeffnen
 +                $writeToFile = 0;
 +                print "Schreiben der Backupdatei ".$recordFile." zum Sichern der beiden Zaehlerstaende fuer rain und light iat fehlgeschlagen! Neue Datei wurde angelegt!\n";
 +        }
 +
 +        print BACKUPFILE $regen.";";                                    # letzten Zaehlerstand "Regen" sichern
 +        print BACKUPFILE $sonne.";";                                    # letzten Zaehlerstand "Sonne" sichern
 +        close(BACKUPFILE) || warn "close failed";
 +
 +}
 +# *** ENDE *** Unterprogramm "write_lastcount" zum Schreiben der Wetterdaten in eine CSV-Datei fuer eine optionale weitere Bearbeitung
 +
 +# *** START *** Unterprogramm "write_Log" zum Schreiben der Statusinformationen in die Logdatei ($logfile)
 +sub write_Log {
 +        my $theMessage = shift;
 +        my $newtime;
 +        if ( $reporting == 1 ){
 +                if(!open(LOGFILE, ">>".$logfile)) {                     # Datei zum "Anfuegen" oeffnen
 +                        print "Konnte die Logdatei ".$logfile." nicht finden. Eine neue wurde angelegt!\n";
 +                        }
 +                print LOGFILE localtime(time()).": ".$theMessage."\n";  # Meldung mit Zeitstempel in die Logdatei schreiben
 +                close(LOGFILE) || warn "close failed";
 +                }
 +        return 0;
 +}
 +# *** ENDE ***  Unterprogramm "write_Log" zum Schreiben der Statusinformationen in die Logdatei ($logfile)
 +
 +# *** START *** Unterprogramm "write_MySQL" zum Uebertragen der Wetterdaten in die MySQL-Datenbank
 +sub write_MySQL {
 +
 +        # Luftdruck in der Datenbank ablegen
 +        $sql="INSERT INTO $dbdatabase.pressure VALUES ('','$newmysqltime','1','20','$druck','1')";
 +        sqlquery($sql);
 +
 +        # Windwerte in der Datenbank ablegen
 +        $sql="INSERT INTO $dbdatabase.wind VALUES ('','$newmysqltime','1','30','$wind_geschwindigkeit','$wind_richtung','$wind_schwankung','1')";
 +        sqlquery($sql);
 +
 +        # Regenwerte in der Datenbank ablegen
 +        if( $regen_db == 1 ) {
 +                $sql="INSERT INTO $dbdatabase.rain VALUES ('','$newmysqltime','1','40','$regen','$regen_menge','1')";
 +                sqlquery($sql);
 +        }
 +
 +        # Sonnenscheinwerte in der Datenbank ablegen
 +        if( $sonne_db == 1 ) {
 +                $sql="INSERT INTO $dbdatabase.light VALUES ('','$newmysqltime','1','50','$sonne_ok','$sonne_delta','','','1')";
 +                sqlquery($sql);
 +        }
 +
 +        # Temperatur + Feuchtewerte der Sensoren 1 bis 9 in der Datenbank ablegen
 +        for ($i=1; $i < 10; $i++) {
 +                if( $sensor_db[$i] == 1 ) {
 +                        $sql="INSERT INTO $dbdatabase.th_sensors VALUES ('','$newmysqltime','1','$i','$temperatur[$i]','$feuchte[$i]','1')";
 +                        sqlquery($sql);
 +                }
 +        }
 +
 +        # Temperatur + Feuchtewerte des Innensensors in der Datenbank ablegen
 +        if( $sensor_db[0] == 1 ) {
 +                $sql="INSERT INTO $dbdatabase.th_sensors VALUES ('','$newmysqltime','1','10','$temperatur[0]','$feuchte[0]','1')";
 +                sqlquery($sql);
 +                }
 +
 +        write_Log ("historische Wetterdaten in die MySQL-Datenbank eingetragen");
 +}
 +# *** ENDE *** Unterprogramm "write_MySQL" zum Uebertragen der Wetterdaten in die MySQL-Datenbank
 +
 +# *** START *** Unterprogramm "write_Record_to_File" zum Schreiben der Wetterdaten in eine CSV-Datei fuer eine optionale weitere Bearbeitung
 +sub write_Record_to_File {
 +        if(!open(RECORDFILE, ">>".$recordFile)) {
 +                $writeToFile = 0;
 +                print "Schreiben der neuen Datensaetze in die CSV-Datei ".$recordFile." fehlgeschlagen! Neue Datei wurde angelegt!\n";
 +        }
 +                                                                        # "Satz-Beschreibung" der CSV-Datei 
 +        print RECORDFILE $newmysqltime.";";                             # Datensatzzeitstempel im MySQL-Format abspeichern
 +        print RECORDFILE $regen_alt.";";                                # Regenzaehler "alter Stand"
 +        print RECORDFILE $regen.";";                                    # Regenzaehler "neuer Stand"
 +        print RECORDFILE $regen_delta.";";                              # Regenzaehler "Delta"
 +        print RECORDFILE $regen_menge.";";                              # Regenmenge in ml pro Quadratmeter
 +        print RECORDFILE $wind_geschwindigkeit.";";                     # Windgeschwindigkeit im km/h
 +        print RECORDFILE $wind_richtung.";";                            # Windrichtung in Grad
 +        print RECORDFILE $wind_schwankung.";";                          # Windschwankung +/- in Grad
 +        print RECORDFILE $druck.";";                                    # relativen Luftdruck (gemessen)
 +        print RECORDFILE $absdruck.";";                                 # absoluter Luftdruck (umgerechnet)
 +        print RECORDFILE $sonne_alt.";";                                # Sonnenscheinzaehler "alter Stand"
 +        print RECORDFILE $sonne.";";                                    # Sonnenscheinzaehler "neuer Stand"
 +        print RECORDFILE $sonne_delta.";";                              # Sonnenscheindauer in Minuten
 +        print RECORDFILE $sonne_ok.";";                                 # Sonne scheint == 1 / Sonnescheint nicht == 0
 +        print RECORDFILE $wettervorhersage.";";                         # Wettervorhersage (noch zu klären!!!!)
 +        for ($i=1; $i < 10; $i++) {
 +                if( $sensor_db[$i] == 1 ) {
 +                print RECORDFILE $temperatur[$i].";";                   # Temperaturwerte der Fuehler 1 bis 9
 +                print RECORDFILE $feuchte[$i].";";                      # Luftfeuchtewerte der Fuehler 1 bis 9
 +                }
 +        }
 +        print RECORDFILE $temperatur[0].";";                            # Temperaturwert des Innenfuehlers (10)
 +        print RECORDFILE $feuchte[0].";";                               # Luftfeuchtewert des Innenfuehlers (10)
 +        print RECORDFILE "\n";                                          # CSV-Zeile abschließen
 +        close(RECORDFILE) || warn "close failed";
 +}
 +# *** ENDE *** Unterprogramm "write_Record_to_File" zum Schreiben der Wetterdaten in eine CSV-Datei fuer eine optionale weitere Bearbeitung
 +
 +# *** START *** Unterprogramm "write_ws500" zum Uebertragen von Steuerungsinformationen (3 Bytes) zur WS500
 +sub write_ws500
 +{
 +        my $command = shift;
 +        if ($command ne "") {
 +                $FTDI->purge_all;                                       # Sende- und Empfangspuffer leeren
 +                syswrite FTD,  $command, length($command), 0;           # 3 Bytes in Richtunf WS500 schieben
 +                select(undef, undef, undef, 0.5);                       # 0.5 sec warten
 +                $FTDI->purge_tx;                                        # Sendepuffer leeren
 +        }
 +}
 +# *** ENDE ***  Unterprogramm "write_ws500" zum Uebertragen von Steuerungsinformationen (3 Bytes) zur WS500
 +
 +# *** START *** Unterprogramm "write_Status_To_File" zum Schreiben der Stationsdaten in die Datei ($statusFile)
 +sub write_Status_To_File {
 +        my $theMessage = shift;
 +        if(!open(STATUSFILE, ">".$statusFile)) {
 +                print "Schreiben der Wetterstationsdaten in die Datei ".$statusFile." fehlgeschlagen! Neue Datei wurde angelegt!\n";
 +        }
 +        else {
 +                print STATUSFILE "Firmware-Version: ".$firmware."\n";
 +                print STATUSFILE "Messintervall: ".$intervall." Minuten.\n";
 +                print STATUSFILE "Hoehe: ".$hoehe." m ue.NN.\n";
 +                print STATUSFILE "Wippe: ".$wippe." ml/Impuls\n";
 +                for ($i=1; $i < 10; $i++) {
 +                        if ($sensoren_status[$i] < 0) {
 +                                print STATUSFILE "Sensor ".$i.": nicht verfuegbar.\n";
 +                        }
 +                        else {
 +                                print STATUSFILE "Sensor ".$i.": verfuegbar (Empfangsausfaelle: ".$sensoren_status[$i].")\n";
 +                        }
 +                }
 +                close (STATUSFILE);
 +        }
 + }
 +# *** ENDE ***  Unterprogramm "write_Status_To_File" zum Schreiben der Stationsdaten in die Datei ($statusFile)
 +</code>
 +[[wetter:ws500:start|Inhaltsverzeichnis der WS500 Beschreibung]]