#!/usr/bin/perl

use utf8;
use strict;
use warnings;
use feature qw(switch);
use POSIX;
use Data::Dump qw(pp);

use Protocol::Modbus::PowerMod qw(modbus _MB_DEFAULT_PORT_ :FC :FUNC);
use Getopt::Long;

# Exit codes
use constant _OKAY_ => 0;
use constant _WARN_ => 1;
use constant _CRIT_ => 2;
use constant _UNKN_ => 3;

use constant WARN => 0;
use constant CRIT => 1;

my $addr = {
    'standby'     => 1,
    'auto'        => 4,
    'circuit'     => 7,
    'flowcontrol' => 9,
    'fancontrol'  => 17,
    'compressor'  => 82,
    'coolingpump' => 84,
    'water-out'   => 20,
    'delta-t'     => 19,
    };


my @val;
my $sleep = 1;
my $exit = _UNKN_;

##########################################################
# parsing options
#

GetOptions(
    'help'     => sub {exec perldoc => -F => $0 or die "Can not execute perldoc: $!\n";},
    'h=s'      => \my $host,      # host address or FQDN
    'p=i'      => \my $_port_,      # TCP-Port for ModbusTCP
    'w=s'      => \ $val[WARN],     # start address of lower warning  values
    'c=s'      => \ $val[CRIT],     # start address of lower critical values
);

my $port       = $_port_ || _MB_DEFAULT_PORT_;

my $message = "";

$message .= " # ( Option -h  ): Unknown Host.\n"
    if ( not defined $host or $host eq "" );

sub print_help
{
    print <<__;

    $0 -h HOST COMMAND [-p PORT] [-w WARNING] [-c CRITICAL]

__
}

sub print_error($)
{
    my ( $_message_ ) = @_;

    print STDERR "UNKNOWN: One or more Options failure.\n$_message_";
    exit _UNKN_;
}

sub say_unkn()
{
    print "check_aermec: Unknown Status! Check Script or Network Connectivity!";
    exit _UNKN_;
}

sub say_okay()
{
    print "No Alarm for any Cooling System.";
    exit _OKAY_;
}



sub eval_values($$)
{
    if ( $_[0] and $_[1] )
    {  
        return ("Alarm - Cooling System 1 and 2.");
        $exit = _CRIT_;
    }

    elsif ( !$_[0] and $_[1]  )
    {
        return ("Alarm - Cooling System 2.");
        $exit = _CRIT_;
    }

    elsif ( $_[0] and !$_[1]  )
    {
        return ("Alarm - Cooling System 1.");
        $exit = _CRIT_;
    }

    elsif ( !$_[0] and !$_[1]  )
    {
        say_okay();
    }

    else 
    {
        say_unkn();
    }
}


if ( $message ne "" )
{
    print_help();
    print_error("$message");
}

my $command = $ARGV[0];



# Daten abrufen
my $connect = {
                  'proto'  => "tcp",
                  'host'   => $host,
                  'port'   => $port,
              };


given ($command)
{

    when ("standby")
    {
        my $id = 0;
        my @status;


        foreach my $unit (1,2)
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'count'    => 1,
            };

            $connect->{'slave'} = $unit;

            ( $status[$id++] ) = modbus
            (
                $connect,
                _MB_RCS_,
                $access
            );

            sleep $sleep;

        }


        #####################################
        # Printing Status And Exit
        #

        if ( $status[0] and $status[1] )
        {
            print "Cooling System 1 and 2 are running - Changing time? Please Check again!";
            $exit = _WARN_;
        }

        elsif ( $status[0] and !$status[1] )
        {
            print "Cooling System 1 is running - System 2 on Standby.";
            $exit = _OKAY_;
        }

        elsif ( !$status[0] and $status[1] )
        {
            print "Cooling System 2 is running - System 1 on Standby.";
            $exit = _OKAY_;
        }

        elsif ( !$status[0] and !$status[1] ) 
        {
            print "No Cooling Systems are running - Missing System 1 or 2!";
            $exit = _CRIT_;
        }
        else
        {
            say_unkn();
        }

    }

    when ("auto")
    {

        my $id = 0;
        my @status;


        foreach my $unit (1,2)
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'count'    => 1,
            };

            $connect->{'slave'} = $unit;

            ( $status[$id++] ) = modbus
            (
                $connect,
                _MB_RCS_,
                $access
            );

            sleep $sleep;

        }


        #####################################
        # Printing Status And Exit
        #
        my $nr;

        if ( $status[0] and $status[1] )
        {
            print "Remote Control for Cooling System 1 and 2 aktiv.";
            $exit = _OKAY_;
        }

        elsif ( $status[0] or $status[1] )
        {
            print "Only Remote Control for Cooling System 1 aktiv - Missing System 2!"
                if ( $status[0] );

            print "Only Remote Control for Cooling System 2 aktiv - Missing System 1!"
                if ( $status[1] );

            $exit = _WARN_;
        }
        elsif ( !$status[0] and !$status[1] )
        {
            print "Remote Control for Cooling System 1 & 2 NOT aktiv!";
            $exit = _CRIT_;
        }
        else
        {
            say_unkn();
        }

    }

    when (["circuit","compressor","coolingpump"])
    {
        my @message;
        my @status;

        $exit = _OKAY_;
        foreach my $unit ( 1, 2 )
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'count'    => 2,
            };


            $connect->{'slave'} = $unit;

            ( $status[0] , $status[1] ) = modbus
            (
                $connect,
                _MB_RCS_,
                $access
            );

            sleep $sleep;


            #####################################
            # Evaluate Resolve Values
            #
 
            if ( $status[0]  )
            {
                push (@message ,  "Cooling System $unit / No. 1" );
                $exit = _CRIT_;
            }
            if ( $status[1]  )
            {
                push (@message ,  "Cooling System $unit / No. 2" );
                $exit = _CRIT_;
            }
        }

        #####################################
        # Printing Status And Exit
        #

        if ( $exit eq _CRIT_ )
        {
            print "Alarm:\n";

            foreach my $line (@message)
            {
                print "$line\n";
            }
        }
        elsif ( $exit eq _OKAY_ )
        {
            say_okay();
        }

        else
        {
            say_unkn();
        }

    }

    when (["flowcontrol","fancontrol"])
    {
        my $id = 0;
        my @status;

        foreach my $unit ( 1, 2 )
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'count'    => 1,
            };

            $connect->{'slave'} = $unit;

            ( $status[$id++] ) = modbus
            (
                $connect,
                _MB_RCS_,
                $access
            );

            sleep $sleep;

        }

        print eval_values($status[0],$status[1]);

    }

    when ("water-out")
    {
        print_error("Check Options -c and/or -w")
            if (
                ( !defined $val[WARN] or $val[WARN] eq "" )
                or
                ( !defined $val[CRIT] or $val[CRIT] eq "" )
               );

        my $id = 0;
        my @values;

        foreach my $unit ( 1, 2 )
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'datatype' => 'int',
                'count'    => 1,
            };

            $connect->{'slave'} = $unit;

            ( $values[$id] ) = modbus
            (
                $connect,
                _MB_RHR_,
                $access
            );
            $values[$id++] /= 10.0;

            sleep $sleep;

        }

        if ( $values[0] > $val[WARN] and $values[1] > $val[WARN] )
        {

            $exit = _WARN_;

            if ( $values[0] > $val[CRIT] and $values[1] > $val[CRIT] )
            {
                $exit = _CRIT_;
            }
        }
        elsif ( $values[0] <= $val[WARN] or $values[1] <= $val[WARN] )
        {
            $exit = _OKAY_;
        }
        else
        {
            say_unkn();
        }

        print "T1/T2 = $values[0]°C / $values[1]°C";

    }

    when ("delta-t")
    {

        print_error("Check Options -c and/or -w")
            if (
                ( !defined $val[WARN] or $val[WARN] eq "" )
                or
                ( !defined $val[CRIT] or $val[CRIT] eq "" )
               );

        my $id = 0;
        my @values;

        foreach my $unit ( 1, 2 )
        {
            my $access  =
            {
                'dataaddr' => $addr->{$command},
                'datatype' => 'int',
                'count'    => 2,
            };

            $connect->{'slave'} = $unit;
            my ( @tmp ) = modbus
            (
                $connect,
                _MB_RHR_,
                $access
            );

            $values[$id++] = ($tmp[0] - $tmp[1]) / 10.0;

            sleep $sleep;

        }

        if ( $values[0] < $val[WARN] and $values[1] < $val[WARN] )
        {
            $exit = _WARN_;

            if ( $values[0] < $val[CRIT] and $values[1] < $val[CRIT] )
            {
                $exit = _CRIT_;
            }
        }
        elsif ( $values[0] >= $val[WARN] or $values[1] >= $val[WARN] ) 
        {
            $exit = _OKAY_;
        }
        else
        {
            say_unkn();
        }
        print "Delta T1/T2 = $values[0]°C / $values[1]°C";


    }

    default
    {
        ( !defined $command or $command eq "" ) ?
        ( print "Missing Command for Status Check.\n" ) :
        ( print "Wrong Command given.\n" );
        print "Use 'standby', 'auto', 'circuit', 'flowcontrol', 'fancontrol', 'compressor' or 'coolingpump'.\n";

        exit _UNKN_;
    }

}

exit $exit;
