#!/usr/bin/perl

# Dieses Script importiert Instanzen und erstellt "Messstellen", "Messtypen",
# "Messgeräte", "Messgerättypen" und "Messverbraucher"
#
# Durch die Angabe von Instanzlisten unter Berücksichtigung von
# Namenkonventionen können hiermit einfach und schnell neue Instanzen in der
# Datenbank hinzugefügt werden. Wenn bereits diverse Typen schon vorhanden sind,
# werden diese verlinkt, ansonsten neue angelegt.
#
# Stefan Steiner in Zusammenarbeit mit Martin H. Sluka (fany)

##############################################################################################################
#       Argumente, Variablen und Bibliotheken                                                                #
##############################################################################################################
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> Bibliotheken                                                                                           #
#                                                                                                            #
use utf8;
use strict;
use warnings;

BEGIN {
    unshift( @INC, ( $ENV{POPHOME} || '@POPHOME@' ) . '/lib' )
      unless $ENV{'KUNDE_NO_PERLPATH'};
}

use Dbase::Getopt qw/GetOptions/;
use Dbase::Globals qw/find_descr/;
use Dbase::Help qw/Do DoFn DoSelect DoTrans qquote/;
use Umlaut qw/textmodus/;
use UTFkram qw/decode_anything/;

# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> Globale Variablen und Parameter-Indizes für SQL-Statements                                             #
#                                                                                                            #

our %oid_bank = (    # Konvertiert die Beschreibung der OID einer PDU von APC
    1 => 'gesamt',    # Hinter der OID 1 verbirgt sich der gesamte Strom
    2 => 'bank-1',    # Hinter der OID 2 fließt der Strom aus Bank 1
    3 => 'bank-2',    # Hinter der OID 3 fließt der Strom aus Bank 2
);

sub print_warnung($) {
    my $message = shift;
    $message .= "\n" if $message !~ /\n\z/;
    print "WARNUNG: $message";
}

sub get_host_id_by_name($) {
    my $host = shift;
    defined( my $host_id = DoFn(<<1) ) or die <<2;
    SELECT id
    FROM   ipkunde
    WHERE  name = ${\ qquote($host) }
       AND ( ende IS NULL OR ende >= UNIX_TIMESTAMP(NOW()) )
1
FEHLER: Hosteintrag - Host/IP-Objekt '$host' in Datenbank nicht gefunden!
2
    return $host_id;
}

{
    my %server_typ = (
        CSIBBSPX => {
            oid_pf => 'SNMPv2-SMI::enterprises.3815.1.2.2.1.1.1.1.1.2.',
            desc   => 'Babel Buster SPX von CSI',
        },
        WAGOIOS750 => {
            oid_pf => 'SNMPv2-SMI::enterprises.13576.10.1.100.1.1.3.',
            desc   => 'I/O-System 750 von WAGO',
        },
        APCSRPDU => {
            oid_pf => 'SNMPv2-SMI::enterprises.318.1.1.12.2.3.1.1.2.',
            desc   => 'Switched Rack PDU von APC',
        },
    );

    sub list_server_typen() {
        map "\t\t$_ \t\t$server_typ{$_}{desc}\n", sort keys %server_typ;
    }

    sub get_server_typ($) {
        my $server_typ = shift;
        my $h          = $server_typ{$server_typ}
          or die <<_, list_server_typen();
FEHLER: Unbekanntes Gerät: $server_typ.
Mögliche Werte:
_
        print "Server-Typ      OK: $server_typ\n";
        return $h;
    }
}

{
    my %messstelle_typ = (
        EMS30C => {
            pulsrate => 100,
            overflow => 100000,
            desc     => 'EMS30-C von Circutor',
        },
        AAD1D5F10KR3A00 => {
            pulsrate => 1000,
            overflow => 1000000,
            desc     => 'AAD1D5F10KR3A00 von saia-burgess',
        },
    );

    sub list_messstellen_typen() {
        map "\t\t$_ \t\t$messstelle_typ{$_}{desc}\n", sort keys %messstelle_typ;
    }

    sub get_messstelle_typ($) {
        my $messstelle_typ = shift;
        my $typ            = $messstelle_typ{$messstelle_typ}
          or die <<_, list_messstellen_typen();
FEHLER: Unbekanntes Gerät: $messstelle_typ.
Mögliche Werte:
_
        print "Messstellen-Typ OK: $messstelle_typ\n";
        return $typ;
    }
}

sub get_hardware_and_kunde($) {
    my ( $hw_id ) = @_;
    DoFn( "SELECT id, kunde FROM hardware WHERE hardware_id = ".qquote($hw_id));
}

{
    my %einheit_konvert =
      (    # Konvertierung der Einheiten-Namen in die Einheitenabkürzungen
        voltage => 'V',  # Relevant für Deskriptoren und den RRD-Grafiken
        current => 'A',  # Reduziert if-elsif-else-Anweisungen um ein vielfaches
        power   => 'W',
        work    => 'Wh',
        frequency   => 'Hz',
        temperature => '°C',
        angle       => '°',
      );

    # Werte für mess_typ.rrd_m{in,ax} laut SSteiner, s. Ticket 1007030:
    my %mess_typ_defaults =
      map {
        my %attr;
        ( my $typ, @attr{qw/rrd_min rrd_max/} ) = split;
        $typ => \%attr;
      } split /\n/, <<_;
voltage                 -1000          1000
current                 -160000        160000
frequency               -60            60
power                   -35000000      35000000
temperature             -273.16        5000
work                    0              1
cosphi                  -100.1         100.1
crestfact               -100.1         100.1
angle                   -360.1         360.1
thd                     -100.1         100.1
rotsym                  -100.1         100.1
flicker                 -100.1         100.1
powerfact               -100.1         100.1
_

    sub find_or_create_mess_typ($$$) {
        my ( $server_typ, $mess_typ_name, $record ) = @_;
        {
            my $einheit_name = $einheit_konvert{$mess_typ_name};
            $einheit_name = 'einheitenlos' unless defined $einheit_name;
            defined( $record->{einheit} =
                  find_descr( 'einheit', $einheit_name ) )
              or die <<_;
FEHLER: Einheit '$einheit_name' in der Deskriptoren-Tabelle 'einheit' nicht definiert.
_
        }
        {
            my $rrdtyp_name = $mess_typ_name eq 'work' ? 'COUNTER' : 'GAUGE';
            defined( $record->{rrd_typ} =
                  find_descr( 'rrd_typ', $rrdtyp_name ) )
              or die <<_;
FEHLER: RRD-Typ '$rrdtyp_name' in der Deskriptoren-Tabelle 'rrd_typ' nicht definiert.
_
        }
        exists $record->{$_}
          or $record->{$_} = 1
          for qw/rrd_faktor snmp_faktor/;

        if ( my $defaults = $mess_typ_defaults{$mess_typ_name} ) {
            %$record = ( %$defaults, %$record );
        }

        # Eintrag in die Tabelle 'mess_typ'
        return find_or_create_record(
            mess_typ => $record,
            sub {
                print <<_;
Erstelle neuen Mess-Typ für Server '$server_typ' ($record->{name}).
_
            },
        );
    }
}

sub create_record {
    my ( $table, $record ) = @_;
    Do(     "INSERT INTO $table ("
          . join( ',', keys %$record )
          . ') VALUES ('
          . join( ',', map qquote($_), values %$record )
          . ')' );
}

sub find_or_create_record($$;$) {
    my ( $table, $record, $sub_info ) = @_;

    if (
        defined(
            my $id = DoFn(
                    "SELECT id FROM $table WHERE name = "
                  . qquote( $record->{name} )
                  . ' FOR UPDATE'
            )
        )
      )
    {
        return $id;
    }

    $sub_info->() if $sub_info;
    return create_record( $table, $record );
}

sub create_mess_verbraucher { create_record( mess_verbraucher => shift ) }

sub do_file(&) {
    my ($do_line) = @_;

    while ( defined( my $line = <> ) ) {
        $line = decode_anything($line);    # Workaround für #10066267
        if ( $line =~ /^;/ ) {
            print_warnung("Keine Instanz in Zeile $. gefunden.");
        }
        else {
            $do_line->($line)
              or die <<_;
SYNTAX-FEHLER: Zeile $. fehlerhaft! Was hasch da wieder angerichtet?
_
        }
    }
}

### Parsen der Optionen:

our $JobType;

sub getopt_jobtype {
    my ($option) = uc shift;
    die <<_ if defined $JobType && $JobType ne $option;
Ja was nun? Willst Du eine $JobType- oder eine $option-Datei verarbeiten?
_
    $JobType = $option;
}

@ARGV = GetOptions(
    'help|?'           => sub {exec perldoc => -F => $0 or die "Kann perldoc nicht ausführen: $!\n";},
    'host=s'           => \our $Host,
    'intervall=i'      => \our $CollectdIntervall,
    'list-messstellen' => sub { print list_messstellen_typen(); exit },
    'list-server'      => sub { print list_server_typen(); exit },
    'messstelle=s'     => \our $Messstelle,
    'mgw'              => \&getopt_jobtype,
    'pdu'              => \&getopt_jobtype,
    'rms'              => \&getopt_jobtype,
    'rz=s'             => \our $RZ,
    'server=s'         => \our $ServerTyp,
) or exit 1;

die <<_ unless defined $JobType;
USAGE: $0 { -mgw | -pdu | -rms } -intervall ...

Weitere Informationen mit "$0 -help".
_

die "Für $JobType-Jobs eine -host angegeben werden.\n"
  if !defined $Host and $JobType eq 'MGW' || $JobType eq 'RMS';

die "Es muss ein -server angegeben werden.\n" unless defined $ServerTyp;
my $server_typ = get_server_typ($ServerTyp);

my $messstelle;
if ( $JobType eq 'RMS' ) {
    die "Für RMS-Instanzlisten muss eine -messstelle angegeben werden.\n"
      unless defined $Messstelle;
    $messstelle = get_messstelle_typ($Messstelle);
}

die "Es muss ein -intervall für collectd angegeben werden.\n"
  unless defined $CollectdIntervall && $CollectdIntervall =~ /^\d+\z/;

DoTrans {
    {
##############################################################################################################
#       Datenbankeinträge                                                                                    #
##############################################################################################################
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> RMS-Instanzlisten (Parameterübergabe)                                                                  #
#                                                                                                            #
        RMS => sub {    # rms1-nbg4.hsmuc.noris.de
            my $host_id    = get_host_id_by_name($Host);
            my $rrd_faktor = 60 * 60 * 1000 / $messstelle->{pulsrate};

# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> RMS-Instanzlisten                                                                                      #
#                                                                                                            #

            print <<_;
Erstelle RMS-Datensätze für Server '$ServerTyp' und Messstellen für '$Messstelle' mit $CollectdIntervall Sekunden Abfrageintervall
_

            # mess_geraet_typ finden oder anlegen:
            my $mess_geraet_typ_id = find_or_create_record(
                mess_geraet_typ => {
                    name           => $Messstelle,
                    ueberlauf_wert => $messstelle->{overflow},
                },
            );

            my ( $rz_id, $rz_name );
            if ( defined $RZ ) {
                ( $rz_id, $rz_name ) =
                  DoFn( 'SELECT id, name FROM rz WHERE name = ' . qquote($RZ) )
                  or die qq/FEHLER: RZ "$RZ" nicht gefunden./;
            }
            else {
                ( $rz_id, $rz_name ) =
                  DoFn( 'SELECT id, name FROM rz WHERE '
                      . qquote($Host)
                      . " RLIKE CONCAT( '[[:<:]]', name, '[[:>:]]' )" )
                  or die "FEHLER: Rechenzentrum für $Host nicht gefunden!\n";
            }

            do_file {
                my $line = shift;
                if (
                    my ( $mess_typ_name, $mess_stelle_name, $housing_id ) =
                    $line =~ /
                        ^
                        ( [a-z]+ )                  # [work]_12F4;D012345;
                        _
                        ( [a-z0-9]+ )               # work_[12F4];D012345;
                        ;
                        ( D\d{6} )                  # work_12F4;[D012345];
                        ;
                    /ix
                  )
                {

                    my $mess_typ_id = find_or_create_mess_typ(
                        $ServerTyp,
                        $mess_typ_name,
                        {
                            name => "$mess_typ_name $Messstelle "
                              . "$rrd_faktor/$CollectdIntervall",
                            collectd_typ       => $mess_typ_name,
                            collectd_intervall => $CollectdIntervall,
                            rrd_faktor         => $rrd_faktor,
                            oid_praefix        => $server_typ->{oid_pf},
                        }
                    );

                    # Eintrag in die Tabelle 'mess_stelle'
                    my $mess_stelle_id = create_record(
                        mess_stelle => {
                            name       => $mess_stelle_name,
                            typ        => $mess_typ_id,
                            snmp_host  => $host_id,
                            oid_suffix => $.,
                        }
                    );

                    # Eintrag in die Tabelle 'mess_geraet_id'
                    create_record(
                        mess_geraet => {
                            typ         => $mess_geraet_typ_id,
                            mess_stelle => $mess_stelle_id,
                        }
                    );

                    # Eintrag in die Tabelle 'mess_verbraucher'
                    if ( my ( $hw_id, $kunde_id ) =
                        get_hardware_and_kunde( $housing_id ) )
                    {
                        create_mess_verbraucher(
                            {
                                mess_stelle => $mess_stelle_id,
                                hardware    => $hw_id,
                                kunde       => $kunde_id,
                            }
                        );
                    }
                    else {
                        print_warnung(<<_);
Keine Sicherungs-Zuordnung? No Hardware => No Client - PECH! Zeile $..
_
                    }

                    return 1;
                }

                elsif ( $line =~ /^[a-z]+_[a-zA-Z0-9]+;;/ ) {
                    print_warnung(<<_);
Keine Sicherungs-Zuordnung? No Hardware => No Client - PECH! Zeile $..
_
                    return 1;
                }

                return;
            };
        },

##############################################################################################################
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> MGW-Instanzlisten                                                                                      #
#                                                                                                            #
        MGW => sub {    # mgw1-muc6.hsmuc.noris.de
            my $host_id = get_host_id_by_name($Host);

            print <<_;
Erstelle MGW-Datensätze für Server '$ServerTyp' mit $CollectdIntervall Sekunden Abfrageintervall
_

            do_file {
                my $line = shift;
                my ( $mess_typ_name, $mess_stelle_name, $snmp_faktor ) =
                  $line =~ /
                        ^
                        ( [a-z]+ )            # [voltage]_L2-L3_testfeld-foo1;0.001;  [power]_active_L3_field4;0.1;
                        _
                        ( [a-z0-9_-]+ )       # voltage_[L2-L3_testfeld-foo1];0.001;  power_[active_L3_field4];0.1;
                        ;
                        ( \d+ \.? \d* )       # voltage_L2-L3_testfeld-foo1;[0.001];
                        ;
                    /ix or return;

                my $mess_typ_id = find_or_create_mess_typ(
                    $ServerTyp,
                    $mess_typ_name,
                    {
                        name => "$mess_typ_name $ServerTyp "
                          . "$snmp_faktor/$CollectdIntervall",
                        collectd_typ       => $mess_typ_name,
                        collectd_intervall => $CollectdIntervall,
                        snmp_faktor        => $snmp_faktor,
                        oid_praefix        => $server_typ->{oid_pf},
                    }
                );

                # Eintrag erzeugen: Tabelle 'mess_stelle'
                create_record(
                    mess_stelle => {
                        name       => $mess_stelle_name,
                        typ        => $mess_typ_id,
                        snmp_host  => $host_id,
                        oid_suffix => $.,
                    }
                );

                return 1;
            };
        },

##############################################################################################################
# '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' #
# --> PDU-Instanzlisten                                                                                      #
#                                                                                                            #
        PDU => sub {    # pdu-nbg.hs.noris.de oder pdus-muc.hsmuc.noris.de
            print <<_;
Erstelle PDU-Datensätze für Server '$ServerTyp' mit $CollectdIntervall Sekunden Abfrageintervall
_

            do_file {
                my $line = shift;
                my ( $mess_typ_name, $host_name, $pdu, $rack_name, $rz_name,
                    $snmp_faktor, $oids, $housing_id )
                  = $line =~ /
                        ^
                        ( [a-z]+ )                            # [current]_pdua1-vt101u-muc7a.hsmuc.noris.de;0.1;3;D012345;
                        _
                        (                                     # current_[pdua1-vt101u-muc7a.hsmuc.noris.de];0.1;3;D012345;
                            ( pdu[a-z0-9]+ )                  # current_[pdua1]-vt101u-muc7a.hsmuc.noris.de;0.1;3;D012345;
                            -
                            ( [a-z0-9]+ )                     # current_pdua1-[vt101u]-muc7a.hsmuc.noris.de;0.1;3;D012345;
                            -
                            ( [a-z0-9] [a-z0-9-]+ )           # current_pdua1-vt101u-[muc7a].hsmuc.noris.de;0.1;3;D012345;
                            (?: \. [a-z0-9]+ )*               # current_pdua1-vt101u-muc7a.[hsmuc.noris.de];0.1;3;D012345;
                        )                                     #            (?: ... heisst:  +- nur matchen - nicht speichern
                        ;
                        ( \d+ \.? \d* )                       # current_pdua1-vt101u-muc7a.hsmuc.noris.de;[0.1];3;D012345;
                        ;
                        ( \d+ )                               # current_pdua1-vt101u-muc7a.hsmuc.noris.de;0.1;[3];D012345;
                        ;
                        ( D\d{6} )                            # current_pdua1-vt101u-muc7a.hsmuc.noris.de;0.1;3;[D012345];
                        ;
                    /ix or return;

                my $rz_id =
                  DoFn( 'SELECT id FROM rz WHERE name = ' . qquote($rz_name) )
                  or
                  print_warnung("Rechenzentrum aus Zeile $. nicht gefunden!\n");

                my $mess_typ_id = find_or_create_mess_typ(
                    $ServerTyp,
                    $mess_typ_name,
                    {
                        name => "$mess_typ_name $ServerTyp "
                          . "$snmp_faktor/$CollectdIntervall",
                        collectd_typ       => $mess_typ_name,
                        collectd_intervall => $CollectdIntervall,
                        snmp_faktor        => $snmp_faktor,
                        oid_praefix        => $server_typ->{oid_pf},
                    }
                );

                # Eintrag in die Tabelle 'mess_stelle'
                if (
                    defined(
                        my $host_id = eval { get_host_id_by_name($host_name) }
                    )
                  )
                {

                    my ( $hw_id, $kunde_id ) =
                         get_hardware_and_kunde( $housing_id )
                      or print_warnung(<<_);
No Hardware <=> No Client - Kunde und Housing-ID aus Zeile $. nicht gefunden.
_

                    for my $oid ( 1 .. $oids ) {

                        my $mess_stelle_id = create_record(
                            mess_stelle => {
                                name       => "$pdu-$rack_name\_$oid_bank{$oid}",
                                typ        => $mess_typ_id,
                                snmp_host  => $host_id,
                                oid_suffix => $oid,
                            }
                        );

                        create_mess_verbraucher(
                            {
                                mess_stelle => $mess_stelle_id,
                                hardware    => $hw_id,
                                kunde       => $kunde_id,
                            }
                        ) if defined $housing_id && defined $kunde_id;
                    }
                }

                return 1;
            };
        }, }->{$JobType}->();
};

__END__

=encoding utf8

=head1 NAME

import_mess_system - Ein Tool zum einlesen von Stammdaten für das Elektronische Energiemanagement-System (EEMS).

=head1 SYNOPSE

    import_mess_system -mgw        [mgw-datei] \
                       -host       mgw1-nbg4.hs.noris.de \
                       -server     CSIBBSPX \
                       -intervall  120

    import_mess_system -pdu        [pdu-datei] \
                       -server     APCSRPDU \
                       -intervall  10

    import_mess_system -rms        [rms-datei] \
                       -host       rms1-uv1-nbg4.hs.noris.de \
                       -server     WAGOIOS750 \
                       -messstelle EMS30C \
                       -intervall  40

=head1 BESCHREIBUNG

Mit diesem Tool werden neue Messstellenobjekte in die Messdatenbank eingetragen. Die Datensätze
dienen für das Stromaccounting und dem Elektronischen Energiemanagement-System (EEMS). Die Namen
der Messstellen sind in den jeweiligen rms-, pdu- und mgw-Dateien gespeichert. Die Dateien (auch
Instanzlisten genannt) müssen inhaltlich einen definierten Syntax entsprechen und enthalten unter
anderem auch die Namen der Messstellenobjekte. Beim Ausführen des Skripts werden Einträge in den

Tabellen ... erstellt und auf Informationen der Tabellen ... zugegriffen.
        \   /                                           \   /
   . mess_stelle                                     . ipkunde
   . mess_typ                                        . hardware
   . mess_verbraucher                                . rz
   . mess_geraet                                     . einheit (descriptor)
   . mess_geraet_typ                                 . rrd_typ (descriptor)


=head1 OPTIONEN

Um auszuwählen, welche Art von Instanzliste verarbeitet werden soll,
muss genau eines dieser folgenden Optionen [-mgw | -pdu | -rms] angegeben werden.

=over 4

=item B<-mgw>
Deklaration neuer Instanzen (Messtellen) I<eines> 'Modbus-Gateways'. Der Inhalt einer Instanzliste vom Typ 'mgw'
muss einen bestimmten Syntax entsprechen.

I<Synopse_einer_mgw-Instanz:>

    <messtyp>_<messstellenname>;<auflösung>;

I<Beispiel_einer_Instanzliste_vom_Typ_'mgw'_[mgw-datei]:>

   +---------------------------------------+
   | current_L1_field5;0.01;               |
   | voltage_L2-L3_field1;0.001;           |
   | ;                                     |
   | thd_current_L3_field1;0.001;          |
   | crestfact_voltage_L2_testfeld1;0.001; |
   +---------------------------------------+

Hier finden sich 4 Messstellenobjekte. Der Zeilenindex definiert zugleich die OID für die SNMP-Abfrage.
   - Zeile 1: Messtyp          'current'
              Messstellenname  'L1_field5'
              Auflösung        '0.01'
              OID              1

   - Zeile 2: Messtyp          'voltage'
              Messstellenname  'L2-L3_field1'
              Auflösung        '0.001'
              OID              2

   - Zeile 3: (keine Messstelle vorhanden)

   - Zeile 4: Messtyp          'thd'
              Messstellenname  'current_L3_field3'
              Auflösung         '0.001'
              OID              4

   - Zeile 5: Messtyp          'crestfact'
              Messstellenname  'voltage_L2_testfelt1'
              Auflösung        '0.001'
              OID              5

=item B<-pdu>
Deklaration neuer Instanzen (Messstellen) I<mehrerer> 'Power Distribution Units'. Hierbei handelt es sich um eine auslaufende Variante der Messwerterhebung.
Daher wurde bei der Umsetung des Tool lediglich der aktuelle Bestand der PDUs ermittelt und nur die vorhandenen APC-Steckdosenleisten 'Switched Rack PDU'
berücksichtigt. Diese Art an PDUs besitzen 3 OID's für die Ermittlung des aktuellen Gesamtstromes und der Teilströme in Bank 1 und Bank 2. Der Inhalt einer
Instanzliste vom Typ 'pdu' muss ebenfalls einen bestimmten Syntax entsprechen.

I<Synopse_einer_pdu-Instanz:>

    <messtyp>_<snmp-host>;<auflösung>;<OIDs>;

I<Beispiel_einer_Instanzliste_vom_Typ_'pdu'_[pdu-datei]:>

   +-------------------------------------------------------+
   | current_pdu1-g02-nbg3.hs.noris.de;0.1;3;D012345;      |
   | current_pdu2-a01-muc6.hsmuc.noris.net;0.01;3;D123456; |
   | current_pdu1-2005-nbg4.hs.noris.de;0.1;3;D098765;     |
   +-------------------------------------------------------+

Hier finden sich 3 SNMP-Hosts mit je '3' OIDs und alle vom Messtyp 'current'.
   - Zeile 1: SNMP-Host   'pdu1-g02-nbg3.hs.noris.de'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu1-g02_gesamt'
                            |     Auflösung        '0.1'
                            |     HousingID        'D012345'
                            |     OID              '1'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu1-g02_bank-1'
                            |     Auflösung        '0.1'
                            |     HousingID        'D012345'
                            |     OID              '2'
                            |
                            +---- Messtyp          'current'
                                  Messstellenname  'pdu1-g02_bank-2'
                                  Auflösung        '0.1'
                                  HousingID        'D012345'
                                  OID              '3'

   - Zeile 2: SNMP-Host   'pdu2-a01-muc6.hsmuc.noris.de'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu2-a01_gesamt'
                            |     Auflösung        '0.01'
                            |     HousingID        'D123456'
                            |     OID              '1'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu2-a01_bank-1'
                            |     Auflösung        '0.01'
                            |     HousingID        'D123456'
                            |     OID              '2'
                            |
                            +---- Messtyp          'current'
                                  Messstellenname  'pdu2-a01_bank-2'
                                  Auflösung        '0.01'
                                  HousingID        'D123456'
                                  OID              '3'

   - Zeile 3: SNMP-Host   'pdu1-2005-nbg4.hs.noris.de'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu1-h05_gesamt'
                            |     Auflösung        '0.1'
                            |     HousingID        'D098765'
                            |     OID              '1'
                            |
                            +---- Messtyp          'current'
                            |     Messstellenname  'pdu1-h05_bank-1'
                            |     Auflösung        '0.1'
                            |     HousingID        'D098765'
                            |     OID              '2'
                            |
                            +---- Messtyp          'current'
                                  Messstellenname  'pdu1-h05_bank-2'
                                  Auflösung        '0.1'
                                  HousingID        'D098765'
                                  OID              '3'

=item B<-rms>
Deklaration neuer Instanzen (Messstellen) I<eines> 'Rack Management Systems'. Der Inhalt einer Instanzliste vom Typ 'rms' muss einen bestimmten Syntax entsprechen.

I<Synopse_einer_rms-Instanz:>

    <messtyp>_<messstellenname>;<Rack-HousingID>;

I<Beispiel_einer_Instanzliste_vom_Typ_'rms'_[rms-datei]:>

    +-----------------------+
    | work_123F456;;        |
    | work_52F123;D008898;  |
    | ;                     |
    | work_70F16;D003410;   |
    | work_12F123;D011770;  |
    +-----------------------+

Hier finden sich insgesamt 4 Sicherungen, wobei 3 davon jeweils einem Hardwareobjekt (i. d. R. ein Rack) zugeordnet ist.
Die Messstelle als Sicherung zu bezeichnen ist eigentlich nicht ganz korrekt. Jede Sicherung besitzt jedoch in einem Unterverteiler (Schaltschrank, bei dem
der Strom an die Racks verteilt wird) stehts einen Wirkarbeitszähler und umgekehrt. Aufgrund dieser 1:1-Zuordnung (Sicheung:Wirkarbeitszähler) meint man mit der Sicherung '123F567' stehts die selbe Messstelle, nämlich einen bestimmten Wirkarbeitszähler. Der Zeilenindex definiert zugleich die OID für die SNMP-Abfrage. Der Inhalt dieser Datei gibt folgende Informationen:

    - Zeile 1: Messtyp          'work'
               Messstellenname  '123F456'
               HousingID        (keine Zuordnung)
               OID              1

    - Zeile 2: Messtyp          'work'
               Messstellenname  '52F123'
               HousingID        'D008898'
               OID              2

    - Zeile 3: (keine Sicherung)

    - Zeile 4: Messtyp          'work'
               Messstellenname  '70F16'
               HousingID        'D003410'
               OID              4

    - Zeile 5: Messtyp          'work'
               Messstellenname  '12F123'
               HousingID        'D011770'
               OID              5

=item B<-server> <SNMP-gerätetyp>

Ohne diese Angabe geht überhaupt nichts. Egal von welchem Typ an Geräte die Daten abgerufen werden, da die Abfrage auf SNMP stattfindet
wird immer ein OID-Präfix benötigt, das den einzelnen OIDs der Messstellen vorangestellt wird. Abhängig von dem Typ des Geräts, liegen
nämlich unterschiedliche OID-Präfixe vor. Daher: Für alle Verarbeitungsarten erforderlich.

=item B<-intervall> <sekunden>

Abfrageintervall für collectd. Dieser Parameter ist genau so wichtig wie L<-server>, denn ohne ein Abfrageintervall macht es ja nicht
einmal Sinn überhaupt anzufangen :)
Muss also für alle Verarbeitungsarten angegeben werden.

=item B<-host> <FQDN>

Um festzulegen, welchem Host die Daten zuzurechnen sind. Die FQDN ist somit der Name des SNMP-fähigen Gerätes, von 
dem collectd die Daten abholt. Dies ist nur erforderlich für die Verarbeitung von L<MGW|/-mgw>- und L<RMS|/-rms>-Instanzlisten.
Da der Inhalt einer L<PDU|/-pdu>-Instanzliste selbst die FQND's enthält, wird bei diesen Listen die Option nicht benötigt.

=item B<-messstelle> <messgerätetyp>

Bei dem Messgerättyp handelt es sich um das erste Glied des Mess-Netzwerkes. Je nach Impulszählerrate (Wirkarbeitszähler)
muss der richtige Messgerättyp angegeben werden. Aus diesem Grund nur erforderlich für L<RMS-|/-rms>-Instanzlisten.

=item B<-rz> <rz-name>

Um festzulegen, zu welchem RZ die Daten gehören.
Fehlt diese Angabe, so wird versucht, ihn anhand des L<Hostnamens|/-host FQDN>
zu erraten. (Nur einschlÃ¤gig für L<RMS-Instanzlisten|/-rms>.)

=item B<-help> | B<-?>

um (nur) diese Dokumentation anzeigen zu lassen.

=item B<-list-messstellen>

um (nur) die möglichen Werte für L<-messstelle> anzeigen zu lassen

=item B<-list-server>

um (nur) die möglichen Werte für L<-server> anzeigen zu lassen

=back

