Logo


Computer Communication & Consulting

Linux - Perl Scripts

letzte Änderung 20.10.2007

Perl Skript/Programm zur USV-Überwachung


Allgemeine Informationen zu USVs (UPS)

Das Programm fragt die USV über die serielle Schnittstelle alle 10 Sekunden ab. Über den Zeitraum von einer Stunde wird die minimale und die maximale Netzspannung und Netzfrequenz ermittelt. Zu jeder vollen Stunde werden die Werte im SysLog eingetragen.

Fällt die Netzspannung aus, wird nach nach 5 Minuten (Variable $sdown) das Linux shutdown aufgerufen und das System sicher heruntergefahren. Sollte vor Ablauf dieser Zeit die Netzspannung wiederkehren geht das Programm zurück in den normalen Überwachungsmodus. Netzausfall und Netzwiederkehr werden im SysLog vermerkt.

Das Script: usv.pl

#!/usr/bin/perl
# Watch USV on /dev/sttyS0
# Autor: Bernd Holzhauer, www.cc-c.de
#        Version 1.0 - Oct. 2006

use Sys::Syslog;

$port = "/dev/ttyS0";	# Serial Port (Com1)
$wait = 10;		# Loop time in seconds
$debug = 1;		# 0 = silent and shutdown active
                        # higher number gives more output
$sdown = 5;             # Minutes til shutdown if power fails


##### do not edit below #####
system "stty 2400 ixon -echo < $port";
open(COM, "+>$port") or die "can't open $port.";
select(COM);
$| = 1;		# switch off buffering

printf(COM "M\015");
sysread(COM, $line, 2);
sleep(1);
if ($debug > 0) {printf(stderr "M: $line\n");}

$vline_max = 210;
$vline_min = 240;
$freq_max = 45;
$freq_min = 55;
$powerfail = 0;

##### loops here until killed #####
# sleep 1 sec between output and read - 2400bps are pretty slow
while(1) {
  $datum = `date`;
  $datum=~ /(..):(..):(..)/;
  $hour = $1;
  $minute = $2;

  ##### read UPS Rating Info #####
  printf(COM "F\015");
  sleep(1);
  sysread(COM, my ($line), 40);
  $line =~ /\#(.....) ..(.) (.....) (....)/;
  $v_ref = $1;
  $i_max = $2;
  $v_bat = $3;
  $freq = $4;

  ##### read UPS Status #####
  printf(COM "Q1\015");
  sleep(1);
  sysread(COM, my ($line), 50);
  if ($debug > 2) {printf(stderr "Q1: $line\n");}
  $line =~ /\((.....) (.....) (.....) (...) (....) (....) (....) (.)(.)(.)(.)(.)(.)(.)(.)/;
  $v_line = $1;
  $v_max = $2;
  $v_out = $3;
  $load = $4;
  $freqa = $5;
  $va_bat = $6;
  $temp = $7;
  $power = $8;		# Bit7
  $bat_low = $9;	# Bit6
  $standby = $12;	# Bit3
  $test = $13;		# Bit2
  $shutdown = $14;	# Bit1
  $beeper = $15;	# Bit0

  ### min & max per hour
  if ($v_max > $vline_max) {$vline_max=$v_max;}
  if ($v_max < $vline_min) {$vline_min=$v_max;}
  if ($freqa > $freq_max) {$freq_max=$freqa;}
  if ($freqa < $freq_min) {$freq_min=$freqa;}

  if ($debug > 1) { ### more output
    printf(stderr "\n$datum");
    printf(stderr "Nominaldaten:  - Aktuell:\n");
    printf(stderr "                 Vin  = $v_line V\n");
    printf(stderr "Vref = $v_ref V   Vout = $v_out V\n");
    printf(stderr "Imax =     $i_max A   Load = $load   %\n");
    printf(stderr "Batt = $v_bat V   Batt =  $va_bat V\n");
    printf(stderr "Freq =  $freq Hz  Freq =  $freqa Hz\n");
    printf(stderr "                 Temp =  $temp °C\n");
  }

  ##### Power fail #####
  if ($power) {
    if (!$powerfail) {
      if ($debug > 0) {printf(stderr "*** Power failed! ***\n");}
      writelog("Power failed - Batt=$va_bat V - Load=$load %");
      $offline = $sdown;
    }
    $powerfail = 1;
    printstat();
  }

  ##### Power Back #####
  if (!$power && $powerfail) {
    if ($debug > 0) {printf(stderr "*** Power is back online ***\n");}
    writelog("Power back online - $v_line V\n");
    $powerfail = 0;
  }

  ### Job once per Minute
  if ($lastminute ne $minute) {
    #printf(stderr "\n*** Minute ***\n");
    if ($debug > 0) {printstat();}
    if ($power) {
      writelog("Power failed - Batt=$va_bat V - Load=$load %");
      $offline -=1;
      if ($debug > 0) {printf(stderr "Shutdown in $offline minutes\n");}
      if (!$offline) {
        writelog("System will be shutdown by UPS");
        if ($debug > 0) {
          printf(stderr "shutdown -h now\n");
        } else {
          system "shutdown -h now";
        }
      }
    }
  }

  ### Job once per hour
  if ($lasthour ne $hour) {
    if ($debug > 0) {printf(stderr "\n*** HOUR ***\n");}
    if ($lasthour == 0) {
      if ($debug > 0) {printf(stderr "Programm-Start at $datum");}
      writelog ("Programm-Start at $datum");
    }
    if ($debug > 0) {
      printf(stderr "Line max=$vline_max"."V/$freq_max"."Hz");
      printf(stderr " min=$vline_min"."V/$freq_min"."Hz\n");
    }
    writelog("Line max=$vline_max"."V/$freq_max"."Hz - min=$vline_min"."V/$freq_min"."Hz");
    $vline_max = 210;
    $vline_min = 240;
    $freq_min = 55;
    $freq_max = 45;
  }
  $lasthour = $hour;
  $lastminute = $minute;

  sleep($wait-2);
}

close(COM);

################################
#####      Subroutines     #####
################################

sub printstat {
  printf(stderr "$hour:$minute ");
  $mains = "OK";
  if ($power) {$mains = "FAILED"};
  printf(stderr "Netz:$v_line"."V/$freqa"."Hz=$mains");
  $blow = "LOW";
  if (!$bat_low) {$blow = "OK"};
  printf(stderr " - Batterie:$va_bat"."V=$blow");
  $online = "Online";
  if (!$standby) {$online = "OFF"};
  printf(stderr " - USV=$online");
  $beep = "On";
  if (!$beeper) {$beep = "OFF"};
  printf(stderr " - Beeper=$beep");
  printf(stderr "\n");

  return;
}

sub writelog {
  my ($string) =@_;
  openlog "usv.pl", "cons.pid", "USV";
  syslog(LOG_DEBUG, "$string");
  closelog;
  return;
}
Listing 1: usv.pl © Bernd Holzhauer

Das Programm wurde für eine Trust PW-4120M - 1200VA Management UPS entwickelt. Es läßt sich jedoch auch für andere USVs mit Megatec-Protokoll einsetzen.

Das Script ist von root über ./usv.pl & zu starten. Es läuft dann, bis es per kill gestoppt wird. Zum Testen kann über die Variable $debug die Menge der Ausgaben zur Konsole gesteuert werden. Je höher der Wert ist umso mehr Ausgaben werden erzeugt. Ist die Variable $debug ungleich 0, wird kein automatischer Shutdown durchgeführt.

Mit einem einfachen Adapter, wie er unter Serielle Schnittstellen beschrieben ist, kann man mit einem zweiten Rechner die Kommunikation zwischen Programm und USV monitoren.





Home Page
Ranking-Hits
Copyright © 2001-2014 Bernd Holzhauer. Alle Rechte vorbehalten.
Warenzeichen und Marken sind Eigentum der jeweiligen Besitzer.

Das Ing.Büro Bernd Holzhauer distanziert sich grundsätzlich von gesetzeswidrigen und möglicherweise illegalen Inhalten in Seiten, auf die über www.cc-c.de verwiesen wird. Sollte Ihnen diesbezüglich etwas auffallen, melden Sie es uns bitte per email.