#!/usr/bin/perl
#
#1234567890123456789012345678901234567890123456789012345678901234567890123456789

use Device::Quasar3108        ;
use   Time::HiRes qw( sleep ) ;
use Data::Dumper              ;
use Device::SerialPort 0.12   ;
use SOAP::Lite            ;


$alarm_period = 15 ;
$sec = 1 ;

# Init stuff
&timeread ;
&initiate_serial_relays ;
&initiate_serial_temp ;
&log_stuff ( " ***********************" ) ;
&log_stuff ( " * HA SCRIPT RESTARTED *" ) ;
&log_stuff ( " ***********************" ) ;

&restore_my_vars ;
&print_firmware_versions ;
&print_firmware_versions ;
&print_firmware_versions ;

&send_relay_commands(off,5,8) ;
&send_relay_commands(off,3,3) ;
&send_relay_commands(off,3,2) ;
&send_relay_commands(on,2,8) ; #ems spare socket

# Main Loop
while ( $sec != 100 ) {

    &timeread ;
    $epoch = time() ;
    &critical_sys ;
    &write_out_old_vars ;
    &assign_variables ;
    &timestamp_changes ;
    &house_heating ;
    #&write_data_to_files ;
    &garage_automation ;
&send_relay_commands(off,5,8) ;

    &house_dhw ;
    &house_firealarm ;
    &house_alarm ;
    &em_minis ;
    &dan_bed_lights ;
    &spare_bed_lights ;
    &lounge_sockets ;
    &dining_sockets ;
    &kitchen_lights ;
    &dining_lights ;
    &garden_automation ;
    &bathroom_heating ;
    &front_door ;
    &dining_kitchen_floor ;
    &create_html ;
    &shutdown_when_out ;
    &check_shutdown ;
    &ping_check ;
    &debug_tests ;
    if ( $sec == 59 ) {
        &serial_port_temps ;
        &initiate_serial_relays ;
        &initiate_serial_temp ;
    }
    #&send_relay_commands(off,3,2) ;
}

 ##############################################################################
#                                                                              #
#                        Subroutines Below                                     #
#                        +=-=-=-=-=-=-=-=+                                     #
#                                                                              #
 ##############################################################################

#
## Time read sub
#
sub timeread {
        ( $sec , $min , $hour ,
          $mday , $mon , $year ,
          $wday , $yday , $isdst ) = localtime(time) ;
}


#
## Initiate serial port for use with temperature sensor
#
sub initiate_serial_temp {

    $PORT = "/dev/ttyS0" ;
    $ob = Device::SerialPort->new ($PORT) || die "Can't Open $PORT: $!";
    $ob->baudrate(2400)    || die "failed setting baudrate";
    $ob->parity("none")    || die "failed setting parity";
    $ob->databits(8)       || die "failed setting databits";
    $ob->handshake("none") || die "failed setting handshake";
    $ob->write_settings    || die "no settings";

    open(DEV, "<$PORT") || die "Cannot open $PORT: $_";

}


#
## Initiate serial port(s) for use with relay moudule(s)
#
sub initiate_serial_relays {

    $io1 = new Device::Quasar3108( '/dev/ttyS1' ) ;
    $io1->ping() ;
    $io1->ping() ;
    $io1->ping() or die   "Module 1 isn't there." ;

    $io2 = new Device::Quasar3108( '/dev/ttyS5' ) ;
    $io2->ping() ;
    $io2->ping() ;
    $io2->ping() or die   "Module 2 isn't there." ;

    $io3 = new Device::Quasar3108( '/dev/ttyS6' ) ;
    $io3->ping() ;
    $io3->ping() ;
    $io3->ping() or die   "Module 3 isn't there." ;
   
    $io4 = new Device::Quasar3108( '/dev/ttyS3' ) ;
    $io4->ping() ;
    $io4->ping() ;
    $io4->ping() or die   "Module 4 isn't there." ;

    $io5 = new Device::Quasar3108( '/dev/ttyS2' ) ;
    $io5->ping() ;
    $io5->ping() ;
    $io5->ping() or die   "Module 5 isn't there." ;

}


#
## Return relay unit firmware version
#
sub print_firmware_versions {

    $version = $io1->firmware_version()    ;
    print "1 Firmware Version: $version\n" ;
    &log_stuff( "Module 1 Firmware version $version" );
 
    $version = $io2->firmware_version()    ;
    print "2 Firmware Version: $version\n" ;
    &log_stuff( "Module 2 Firmware version $version" );
 
    $version = $io3->firmware_version()    ;
    print "3 Firmware Version: $version\n" ;
    &log_stuff( "Module 3 Firmware version $version" );
 
    $version = $io4->firmware_version()    ;
    print "4 Firmware Version: $version\n" ;
    &log_stuff( "Module 4 Firmware version $version" );
 
    $version = $io5->firmware_version()    ;
    print "5 Firmware Version: $version\n" ;
    &log_stuff( "Module 5 Firmware version $version" );

}

#
## Print relay unit status
#
sub print_status {

    print "Out Status 11 (Dining Room U/F)      :"
                 . $io1->relay_status(1) . "\n" ;
    print "Out Status 12 (Kitchen U/F)          :"
                 . $io1->relay_status(2) . "\n" ;
    print "Out Status 13 (Bathroom U/F)         :"
                . $io1->relay_status(3) . "\n" ;
    print "Out Status 14 (Bathroom Towel Rail)  :"
                . $io1->relay_status(4) . "\n" ;
    print "Out Status 15 (D/S Central Heating)  :"
                . $io1->relay_status(5) . "\n" ;
    print "Out Status 16 (U/S Central Heating)  :"
                . $io1->relay_status(6) . "\n" ;
    print "Out Status 17 (Domestic Hot Water)   :"
                . $io1->relay_status(7) . "\n" ;
    print "Out Status 18 (Dan Bedside Table)    :"
                . $io1->relay_status(8) . "\n" ;
    print "Out Status 21 (Lounge Fire Right)    :"
                . $io2->relay_status(1) . "\n" ;
    print "Out Status 22 (Lounge Air Con)       :"
                . $io2->relay_status(2) . "\n" ;
    print "Out Status 23 (Sairee Bedside Table) :"
                . $io2->relay_status(3) . "\n" ;
    print "Out Status 24 (Lounge Rear Sofe Door):"
                . $io2->relay_status(4) . "\n" ;
    print "Out Status 25 (Lounge Window Shelves):"
                . $io2->relay_status(5) . "\n" ;
    print "Out Status 26 (Lounge Sofa Shelves)  :"
                . $io2->relay_status(6) . "\n" ;
    print "Out Status 27 (Baby Room Mini Lights):"
                . $io2->relay_status(7) . "\n" ;
    print "Out Status 28 (Baby Room Window Left):"
                . $io2->relay_status(8) . "\n" ;
    print "Out Status 31 (Spare Room by Door)   :"
                . $io3->relay_status(1) . "\n" ;
    print "Out Status 32 (Internal Chime Siren) :"
                . $io3->relay_status(2) . "\n" ;
    print "Out Status 33 (Internal Loud Siren)  :"
                . $io3->relay_status(3) . "\n" ;
    print "Out Status 34 (ADT Siren Front)      :"
                . $io3->relay_status(4) . "\n" ;
    print "Out Status 35 (Lounge Side Sofa Door):"
                . $io3->relay_status(5) . "\n" ;
    print "Out Status 36 (n/c)                  :"
                . $io3->relay_status(6) . "\n" ;
    print "Out Status 37 (n/c)                  :"
                . $io3->relay_status(7) . "\n" ;
    print "Out Status 38 (n/c)                  :"
                . $io3->relay_status(8) . "\n" ;
    print "Out Status 41 (Spare Room Desk)      :"
                . $io4->relay_status(1) . "\n" ;
    print "Out Status 42 (Master Bed Tallboy)   :"
                . $io4->relay_status(2) . "\n" ;
    print "Out Status 43 (Master Bedroom TV)    :"
                . $io4->relay_status(3) . "\n" ;
    print "Out Status 44 (Dining Room Freezer)  :"
                . $io4->relay_status(4) . "\n" ;
    print "Out Status 45 (Front Door Light)     :"
                . $io4->relay_status(5) . "\n" ;
    print "Out Status 46 (Spare Room Cupboard)  :"
                . $io4->relay_status(6) . "\n" ;
    print "Out Status 47 (Dining Room Window)   :"
                . $io4->relay_status(7) . "\n" ;
    print "Out Status 48 (Dining Room Piano)    :"
                . $io4->relay_status(8) . "\n" ;
    print "Out Status 51 (n/c)                  :"
                . $io5->relay_status(1) . "\n" ;
    print "Out Status 52 (Garden Rear Flood)    :"
                . $io5->relay_status(2) . "\n" ;
    print "Out Status 53 (Garden 3 Light)       :"
                . $io5->relay_status(3) . "\n" ;
    print "Out Status 54 (Garden 2 Light)       :"
                . $io5->relay_status(4) . "\n" ;
    print "Out Status 55 (Garage Lights)        :"
                . $io5->relay_status(5) . "\n" ;
    print "Out Status 56 (Drive Light)          :"
                . $io5->relay_status(6) . "\n" ;
    print "Out Status 57 (Garage Clock)         :"
                . $io5->relay_status(7) . "\n" ;
    print "Out Status 58 (Garage Internal Siren):"
                . $io5->relay_status(8) . "\n" ;

    print  "In Status 11 (Kitchen PIR)          :"
                . $io1->input_status(1) . "\n" ;
    print  "In Status 12 (Upstairs Landing PIR) :"
                . $io1->input_status(2) . "\n" ;
    print  "In Status 13 (Dining Room PIR)      :"
                . $io1->input_status(3) . "\n" ;
    print  "In Status 14 (Master Bedroom PIR)   :"
                . $io1->input_status(4) . "\n" ;
    print  "In Status 21 (Spare Bedroom PIR)    :"
                . $io2->input_status(1) . "\n" ;
    print  "In Status 22 (Lounge PIR)           :"
                . $io2->input_status(2) . "\n" ;
    print  "In Status 23 (Downstairs Hall PIR)  :"
                . $io2->input_status(3) . "\n" ;
    print  "In Status 24 (Baby Bedroom PIR)     :"
                . $io2->input_status(4) . "\n" ;
    print  "In Status 31 (Hallway Smoke/Heat)   :"
                . $io3->input_status(1) . "\n" ;
    print  "In Status 32 (Kitchen Heat Sensor)  :"
                . $io3->input_status(2) . "\n" ;
    print  "In Status 33 (n/c)                  :"
                . $io3->input_status(3) . "\n" ;
    print  "In Status 34 (Front Door)           :"
                . $io3->input_status(4) . "\n" ;
    print  "In Status 41 (Landing Smoke/Heat)   :"
                . $io4->input_status(1) . "\n" ;
    print  "In Status 42 (Back Door)            :"
                . $io4->input_status(2) . "\n" ;
    print  "In Status 43 (n/c)                  :"
                . $io4->input_status(3) . "\n" ;
    print  "In Status 44 (n/c)                  :"
                . $io4->input_status(4) . "\n" ;
    print  "In Status 51 (Garage Roller Door)   :"
                . $io5->input_status(1) . "\n" ;
    print  "In Status 52 (Garage Back Door)     :"
                . $io5->input_status(2) . "\n" ;
    print  "In Status 53 (Shed Doors)           :"
                . $io5->input_status(3) . "\n" ;
    print  "In Status 54 (Light/Dark Sensor)    :"
                . $io5->input_status(4) . "\n" ;
#DMX Channels
#1 -
#2 - Dining Room
#3 -
#4 - Lounge
#5 - Spare Room
#6 - Bath Room
#7 - Dan & Sairee
#8 - Emily

}


#
## Read in serial port input status and assign variables
#
sub assign_variables {

    $in11  = $io1->input_status(1) ;
    $in12  = $io1->input_status(2) ;
    $in13  = $io1->input_status(3) ;
    $in14  = $io1->input_status(4) ;
    $in21  = $io2->input_status(1) ;
    $in22  = $io2->input_status(2) ;
    $in23  = $io2->input_status(3) ;
    $in24  = $io2->input_status(4) ;
    $in31  = $io3->input_status(1) ;
    $in32  = $io3->input_status(2) ;
    $in33  = $io3->input_status(3) ;
    $in34  = $io3->input_status(4) ;
    $in41  = $io4->input_status(1) ;
    $in42  = $io4->input_status(2) ;
    $in43  = $io4->input_status(3) ;
    $in44  = $io4->input_status(4) ;
    $in51  = $io5->input_status(1) ;
    $in52  = $io5->input_status(2) ;
    $in53  = $io5->input_status(3) ;
   
    # This is annoying, the light/dark sensor fluctuates wildly
    # at the point where it is just light or dark
    # don't read for 30mins after making a transition
    # also don't let stuff like the garden floods affect it
    # so don't take a reading for 3 mins after opening any garden
    # facing doors
    if ( $epoch - $lightdarkchange > 1800 &&
         $epoch - $in51_lastmove > 180 &&
         $epoch - $in52_lastmove > 180 &&
         $epoch - $in53_lastmove > 180 &&
         $epoch - $in42_lastmove > 180 ) {
        $in54  = $io5->input_status(4) ;
        if ( $in54 != $in54old ) {
            $lightdarkchange = $epoch ;
        }
    }

    $out11 = $io1->relay_status(1) ;
    $out12 = $io1->relay_status(2) ;
    $out13 = $io1->relay_status(3) ;
    $out14 = $io1->relay_status(4) ;
    $out15 = $io1->relay_status(5) ;
    $out16 = $io1->relay_status(6) ;
    $out17 = $io1->relay_status(7) ;
    $out18 = $io1->relay_status(8) ;
    $out21 = $io2->relay_status(1) ;
    $out22 = $io2->relay_status(2) ;
    $out23 = $io2->relay_status(3) ;
    $out24 = $io2->relay_status(4) ;
    $out25 = $io2->relay_status(5) ;
    $out26 = $io2->relay_status(6) ;
    $out27 = $io2->relay_status(7) ;
    $out28 = $io2->relay_status(8) ;
    $out31 = $io3->relay_status(1) ;
    $out32 = $io3->relay_status(2) ;
    $out33 = $io3->relay_status(3) ;
    $out34 = $io3->relay_status(4) ;
    $out35 = $io3->relay_status(5) ;
    $out36 = $io3->relay_status(6) ;
    $out37 = $io3->relay_status(7) ;
    $out38 = $io3->relay_status(8) ;
    $out41 = $io4->relay_status(1) ;
    $out42 = $io4->relay_status(2) ;
    $out43 = $io4->relay_status(3) ;
    $out44 = $io4->relay_status(4) ;
    $out45 = $io4->relay_status(5) ;
    $out46 = $io4->relay_status(6) ;
    $out47 = $io4->relay_status(7) ;
    $out48 = $io4->relay_status(8) ;
    $out51 = $io5->relay_status(1) ;
    $out52 = $io5->relay_status(2) ;
    $out53 = $io5->relay_status(3) ;
    $out54 = $io5->relay_status(4) ;
    $out55 = $io5->relay_status(5) ;
    $out56 = $io5->relay_status(6) ;
    $out57 = $io5->relay_status(7) ;
    $out58 = $io5->relay_status(8) ;

}


#
## Set 'old' variables to match current status
#
sub write_out_old_vars {
$out = out ;
$old = old ;
$in = in ;
    # This is a cleverer version of what used to read:
    # $in11old  = $in11  ;
        # $out11old = $out11 ;
        # $in12old  = $in12  ;
    # $out12old = $out12 ;

    for ($unit = 1; $unit <= 5; $unit++) {
        for ($output = 1; $output <= 8; $output++) {
            ${$out.$unit.$output.$old} = ${$out.$unit.$output} ;
            if ( $output <= 4 ) {
                ${$in.$unit.$output.$old} = ${$in.$unit.$output} ;
            }
            }
    }
}


#
## Timestamp any changes to inputs
#
sub timestamp_changes {

    if ( $in11 == 0  ) {
        $in11_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in11old == 1 ) {
            $in11_trig = $epoch ;
            &log_stuff ( "Kitchen Movement" ) ;
        }
    }

    if ( $in12 == 0  ) {
        $in12_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in12old == 1 ) {
            $in12_trig = $epoch ;
            &log_stuff ( "Landing Movement" ) ;
        }
    }

    if ( $in13 == 0  ) {
        $in13_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in13old == 1 ) {
            $in13_trig = $epoch ;
            &log_stuff ( "Dining Room Movement" ) ;
        }
    }

    if ( $in14 == 0  ) {
        $in14_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in14old == 1 ) {
            $in14_trig = $epoch ;
            &log_stuff ( "Master Bedroom Movement" ) ;
        }
    }

    if ( $in21 == 0  ) {
        $in21_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in21old == 1 ) {
            $in21_trig = $epoch ;
            &log_stuff ( "Spare Bedroom Movement" ) ;
        }
    }

    if ( $in22 == 0  ) {
        $in22_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in22old == 1 ) {
            $in22_trig = $epoch ;
            &log_stuff ( "Lounge Movement" ) ;
        }
    }

    if ( $in23 == 0  ) {
        $in23_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in23old == 1 ) {
            $in23_trig = $epoch ;
            &log_stuff ( "Hallway Movement" ) ;
        }
    }

    if ( $in24 == 0  ) {
        $in24_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in24old == 1 ) {
            $in24_trig = $epoch ;
            &log_stuff ( "Emily Bedroom Movement" ) ;
        }
    }

    if ( $in31 == 0  ) {
        $in31_lastmove = $epoch ;
        #$lastmove      = $epoch ;
        if ( $in31old == 1 ) {
            $in31_trig = $epoch ;
            &log_stuff ( "Downstairs Fire!!" ) ;
        }
    }

    if ( $in32 == 0  ) {
        $in32_lastmove = $epoch ;
        #$lastmove      = $epoch ;
        if ( $in32old == 1 ) {
            $in32_trig = $epoch ;
            &log_stuff ( "Kitchen Fire!!" ) ;
        }
    }

    #if ( $in33 == 0  ) {
        #$in33_lastmove = $epoch ;
        #$lastmove      = $epoch ;
        #if ( $in33old == 1 ) {
            #$in33_trig = $epoch ;
            #&log_stuff ( "nc Movement" ) ;
        #}
    #}

    if ( $in34 == 0  ) {
        $in34_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in34old == 1 ) {
            $in34_trig = $epoch ;
            &log_stuff ( "Front Door Opened" ) ;
        }
    }

        if ( $in34 == 1  ) {
                if ( $in34old == 0 ) {
                        $in34_trig = $epoch ;
                        &log_stuff ( "Front Door Closed" ) ;
                }
        }


    if ( $in41 == 0  ) {
        $in41_lastmove = $epoch ;
        #$lastmove      = $epoch ;
        if ( $in41old == 1 ) {
            $in41_trig = $epoch ;
            &log_stuff ( "Upstairs Fire!!" ) ;
        }
    }

    if ( $in42 == 0  ) {
        $in42_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in42old == 1 ) {
            $in42_trig = $epoch ;
            &log_stuff ( "Back Door Opened" ) ;
        }
    }

        if ( $in42 == 1  ) {
                if ( $in42old == 0 ) {
                        $in42_trig = $epoch ;
                        &log_stuff ( "Back Door Closed" ) ;
                }
        }


    #if ( $in43 == 0  ) {
        #$in43_lastmove = $epoch ;
        #$lastmove      = $epoch ;
        #if ( $in43old == 1 ) {
            #$in43_trig = $epoch ;
            #&log_stuff ( "nc Movement" ) ;
        #}
    #}

    #if ( $in44 == 0  ) {
        #$in44_lastmove = $epoch ;
        # $lastmove      = $epoch ;
        #if ( $in44old == 1 ) {
            #$in44_trig = $epoch ;
            #&log_stuff ( "nc Movement" ) ;
        #}
    #}

    if ( $in51 == 0  ) {
        $in51_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in51old == 1 ) {
            $in51_trig = $epoch ;
            &log_stuff ( "Garage Roller Door Opened" ) ;
        }
    }

        if ( $in51 == 1  ) {
                if ( $in51old == 0 ) {
                        $in51_trig = $epoch ;
                        &log_stuff ( "Garage Roller Door Closed" ) ;
                }
        }

    if ( $in52 == 0  ) {
        $in52_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in52old == 1 ) {
            $in52_trig = $epoch ;
            &log_stuff ( "Garage Small Door Opened" ) ;
        }
    }

        if ( $in52 == 1  ) {
                if ( $in52old == 0 ) {
                        $in52_trig = $epoch ;
                        &log_stuff ( "Garage Small Door Closed" ) ;
                }
        }


    if ( $in53 == 0  ) {
        $in53_lastmove = $epoch ;
        $lastmove      = $epoch ;
        if ( $in53old == 1 ) {
            $in53_trig = $epoch ;
            &log_stuff ( "Shed Door Opened" ) ;
        }
    }

        if ( $in53 == 1  ) {
                if ( $in53old == 0 ) {
                        $in53_trig = $epoch ;
                        &log_stuff ( "Shed Door Closed" ) ;
                }
        }


    if ( $in54 == 0 ) {
        #$in54_lastmove = $epoch ;
        #$lastmove      = $epoch ;  # dark doesn't constitute motion!
        if ( $in54old == 1 ) {
            $in54_trig = $epoch ;
            $in54_lastmove = $epoch ;
            &log_stuff ( "Dark Outside" ) ;
        }
    }

        if ( $in54 == 1 ) {
                #$in54_lastmove = $epoch ;
                #$lastmove      = $epoch ;  # light doesn't constitute motion!
                if ( $in54old == 0 ) {
                        $in54_trig = $epoch ;
            $in54_lastmove = $epoch ;
                        &log_stuff ( "Light Outside" ) ;
                }
        }


}


#
## Obtain current temperatures from Quasar 3145 temp module
#
sub serial_port_temps {

    #while($_ = <DEV>){

    for ($dan=0 ; $dan<8 ; $dan++) {
        $_=<DEV> ;
        if ( $_ =~ /1 00/ ) {
            $temp1temp = $_ ;
            $temp1temp =~ s/[0-9]\ //g ;
            $temp1temp = $temp1temp + 0 ;
                if ( $temp1temp < 40 && $temp1temp > 1) {
                    $temp1 = $temp1temp ;
                }
        }

        if ( $_ =~ /2 00/ ) {
            $temp2temp = $_ ;
            $temp2temp =~ s/[0-9]\ //g ;
            $temp2temp = $temp2temp + 0 ;
                if ( $temp2temp < 40 && $temp2temp > 1) {
                                        $temp2 = $temp2temp ;
                                }
        }

        if ( $_ =~ /3 00/ ) {
            $temp3temp = $_ ;
            $temp3temp =~ s/[0-9]\ //g ;
            $temp3temp = $temp3temp + 0 ;
                if ( $temp3temp < 40 && $temp3temp > 1) {
                                        $temp3 = $temp3temp ;
                                }

        }

        if ( $_ =~ /4 00/ ) {
            $temp4temp = $_ ;
            $temp4temp =~ s/[0-9]\ //g ;
            $temp4temp = $temp4temp + 0 ;
                if ( $temp4temp < 40 && $temp4temp > 1) {
                                        $temp4 = $temp4temp ;
                                }
        }
    }
    undef $ob;

    &log_stuff ( "<temp> Master Bed Temp = $temp1 </temp>" )    ;
    &log_stuff ( "<temp> Emily Bedroom Temp = $temp2 </temp>" ) ;
    &log_stuff ( "<temp> Lounge Temp = $temp3 </temp>" )        ;
    &log_stuff ( "<temp> Dining Room Temp = $temp4 </temp>" )   ;
}

#
## Maintain critcal systems
#
sub critical_sys {

    if ( $sec == "1" ) {
#       &send_relay_commands(on,2,2) ; # Lounge TV
        &send_relay_commands(on,4,4) ; # Freezer
        &send_relay_commands(on,4,3) ; # Bedroom TV
                &send_relay_commands(on,4,8) ; # Dining Piano
                &send_relay_commands(on,2,8) ; #em socket
#       &send_lights_soap(6,255) ;     
    }
}


#
## Send SMS Message
#
sub send_sms {

    #need to put stuff in here to talk to tc35i

}


#
## Garage automation
#
sub garage_automation {

    # Pulse siren if roller opened
    if ($in51 == 0 && $in51old == 1 ) {
        $io5->relay_flash( 8 , 1 ) ;
    }

    # Main lights on in garage in roller or small door open
    if ( $in51 == 0 || $in52 == 0 ) {
        &send_relay_commands(on,5,5) ;

    }

    # Drive light on if roller door open and it's dark
    if ( $in51 == 0 && $in54 == 0 ) {
        &send_relay_commands(on,5,6) ;
    }

    # Garden rear flood on if small garage door open and it's dark
    # or if the roller door has been open for between a second and 60
    # seconds (try to avoid large surge loads of both at once)
    if (( $in54 == 0 && $in52 == 0 ) ||
        ( $in54 == 0 &&
          $epoch - $in51_lastmove >= 1 && $epoch - $in51_lastmove < 61 )) {
        &send_relay_commands(on,5,2) ;
    }

    # Turn off garage lights if both doors are shut for a minute or more
    if (( $epoch - $in52_lastmove > 60 ) &&
        ( $epoch - $in51_lastmove > 60 )) {
        &send_relay_commands(off,5,5) ;
    }

    # Turn off drive floodlight if roller is shut for a minute or more
    if ( $epoch - $in51_lastmove > 60 ) {
        &send_relay_commands(off,5,6) ;
    }

    # Turn off garden flood if smalldoor and roller door have been shut
    # for a minute or more
    if ( $epoch - $in52_lastmove > 60 && $epoch - $in51_lastmove > 60 ) {
        &send_relay_commands(off,5,2) ;
    }
}


#
## Garden automation
#
sub garden_automation {

    # Outside lights on when dark and
    # movement in kitchen, diningroom, spareroom, backdoor open,
    # garage door open or sheddoor open
    if (( $in54 == 0 ) &&
        ( $in11 == 0 || $in13 == 0 || $in21 == 0 || $in42 == 0 ||
          $in52 == 0 || $in53 == 0 )) {
        # &send_relay_commands(on,5,3) ;
        &send_relay_commands(on,5,4) ;
    }
    else {
        if (( $in54 == 1 ) ||
            ( $epoch - $in11_lastmove > 720 &&
              $epoch - $in13_lastmove > 720 &&
              $epoch - $in21_lastmove > 720 &&
              $epoch - $in42_lastmove > 720 &&
              $epoch - $in52_lastmove > 720 &&
              $epoch - $in53_lastmove > 720 )) {
            &send_relay_commands(off,5,3) ;
            &send_relay_commands(off,5,4) ;
        }
    }
}


#
## House heating
#
sub house_heating {

    if ( $dor == 1 ) { &send_relay_commands(on,1,5) ; } # DStairs heat on
    if ( $dor == 0 ) { &send_relay_commands(off,1,5) ; } # DStairs heat off
        if ( $uor == 1 ) { &send_relay_commands(on,1,6) ; } # UStairs heat on
        if ( $uor == 0 ) { &send_relay_commands(off,1,6) ; } # UStairs heat off
        if ( $wor == 1 ) { &send_relay_commands(on,1,7) ; } # DHW heat on
        if ( $wor == 0 ) { &send_relay_commands(off,1,7) ; } # DHW heat off

if ( $dor == 2 && $uor == 2 && $wor == 2 ) {
    if ( $hour >= 6 && $hour <= 21 ) { # Operate this rule between 7-21
        if ( $fullhouse == 1 ) { # House occupied
            if ( $temp3 < 20.00  ) { # Lounge temp under 21C
                &send_relay_commands(on,1,5) ; # DStairs heat on
                if ( $out15old == 0 ) {
                    &log_stuff ( "Downstairs Heat On" ) ;
                }
            }  
            else {
                if ( $fullhouse == 0 || $temp3 > 21.00 ) {
                &send_relay_commands(off,1,5) ; # Dstairs h off
                if ( $out15old == 1 ) {
                    &log_stuff ( "Downstairs Heat Off" ) ;
                }
                }
            }
            if ( $temp1 < 17.00 ) { #DAN TEMP
                &send_relay_commands(on,1,6) ; # Ustairs heat on
                if ( $out16old == 0 ) {
                    &log_stuff ( "Upstairs Heat On" ) ;
                }
            }  
            else {
                if ( $fullhouse == 0 || $temp1 > 18.00 ) {
                &send_relay_commands(off,1,6) ; # Utairs heat off
                if ( $out16old == 1 ) {
                    &log_stuff ( "Upstairs Heat Off" ) ;
                }
                }
            }
        }
        else { # No movement detected
            if ( $temp3 < 17.00 ) {
                &send_relay_commands(on,1,5) ; ; # Dstairs h on
                if ( $out15old == 0 ) {
                    &log_stuff ( "Downstairs Heat On" ) ;
                }
            }  
            else {
                if ( $temp3 > 17.50 ) {
                &send_relay_commands(off,1,5) ; # Dstairs h off
                if ( $out15old == 1 ) {
                    &log_stuff ( "Downstairs Heat Off" ) ;
                }
                }
            }
            if ( $temp1 < 16.00 ) {
                &send_relay_commands(on,1,6) ; # Ustairs heat on
                if ( $out16old == 0 ) {
                    &log_stuff ( "Upstairs Heat On" ) ;
                }  
            }  
            else {
                if ( $temp1 > 16.50 ) {
                &send_relay_commands(off,1,6) ; # Upstairs heat off
                if ( $out16old == 1 ) {
                    &log_stuff ( "Upstairs Heat Off" ) ;
                }
                }
            }    
        }
    }

# Nighttime

    if (( $hour >= 0 && $hour <= 5 ) || ( $hour >= 22 && $hour <= 23 )) {
        if ( $temp3 < 16.50 ) {
            &send_relay_commands(on,1,6) ;  # Upstairs heat on
            if ( $out16old == 0 ) {
                            &log_stuff ( "Upstairs Heat On" ) ;
            }
        }
        else {
            &send_relay_commands(off,1,6) ; # Upstairs heat off
                        if ( $out16old == 1 ) {
                                &log_stuff ( "Upstairs Heat Off" ) ;
                        }

        }
        if ( $temp1 < 15.50 ) {
            &send_relay_commands(on,1,5) ; ;  # Downstairs heat on
                        if ( $out15old == 0 ) {
                                &log_stuff ( "Downstairs Heat On" ) ;
                        }

        }
        else {
            &send_relay_commands(off,1,5) ; # Downstairs heat off
                        if ( $out15old == 1 ) {
                                &log_stuff ( "Downstairs Heat Off" ) ;
                        }

        }
    }
}
}


#
## House hotwater
#
sub house_dhw {
if ( $dor == 2 && $uor == 2 && $wor == 2 ) {
    if ( $hour >= 5 && $hour <= 22 ) {
        &send_relay_commands(on,1,7) ; # DHW on if between 5-23
        if ( $out17old == 0 ) {
            &log_stuff ( "Hot Water On" ) ;
        }

    }
    else {
        &send_relay_commands(off,1,7) ;
                if ( $out17old == 1 ) {
                        &log_stuff ( "Hot Water Off" ) ;
                }
    }
}
}

#
## House firealarm
#
sub house_firealarm {

    if (  $in31 == 0 || $in32 == 0 || $in41 == 0 ) {
        #$io3->relay_flash( 2 , $alarm_period ) ; # Small siren on
        #$io3->relay_flash( 3 , $alarm_period ) ; # Big Siren on
        if ( $epoch - $last_dialled > 600 ) {
            `echo "ha~gsm~modem~call~~077958####0" >  /root/middleware/production/dangen2test/dansend.txt` ;
            $last_dialled = $epoch ;
        }
    }
    else {
        #&send_relay_commands(off,3,2) ; # Small siren off
        #&send_relay_commands(off,3,3) ; # Big Siren off
    }

}

#
## House alarm
#
sub house_alarm {

    # If shed door or garage small door or roller is opened
        # without first the backdoor being opened in the last 10 mins
    # then trigger the alarm
    if (( $in52 == 0 || $in53 == 0 || $in51 == 0  ) &&
        ( $in42 == 1 ) &&
        ( $epoch - $in42_lastmove > 600 )) {
                if ( $epoch - $last_dialled > 600 ) {
                    `echo "ha~gsm~modem~call~~07795#####0" >  /root/middleware/production/dangen2test/dansend.txt` ;
                        $last_dialled = $epoch ;
                }
        #$io3->relay_flash( 2 , $alarm_period ) ; # Small house siren on
        #$io5->relay_flash( 8 , $alarm_period ) ; # Garage siren on
    }
    else {
        #&send_relay_commands(off,3,2) ; ; # Small house siren off
                #&send_relay_commands(off,5,8) ; # Garage siren off
    }

}

#
# Kitchen and Dining underfloor
#
sub dining_kitchen_floor {
        if ( $dfor == 1 ) { &send_relay_commands(on,1,1) ; } # DF heat on
        if ( $dfor == 0 ) { &send_relay_commands(off,1,1) ; } # DF heat off
        if ( $kfor == 1 ) { &send_relay_commands(on,1,2) ; } # KF heat on
        if ( $kfor == 0 ) { &send_relay_commands(off,1,2) ; } # KF heat off

if ( $dfor == 2 && $kfor == 2 ) {

    # Kitchen and Dining Room Floor
    if ( $hour >= 5 && $hour <= 20 ) { # Operate this rule between 5-20
        if ( $epoch - $lastmove < 600 ) { # Movement in last 10 mins
            if ( $temp4 < 20.00 ) {
                &send_relay_commands(on,1,1) ; # Dining floor heat on
                &send_relay_commands(on,1,2) ; # Kitchen floor heat on
            }
            else {
                &send_relay_commands(off,1,1) ; # Dining floor heat off
                &send_relay_commands(off,1,2) ; # Kitchen floor heat off
            }
        }
        else {
            &send_relay_commands(off,1,1) ; # Dining floor heat off
            &send_relay_commands(off,1,2) ; # Kitchen floor heat off
                }

    }
    else {
        &send_relay_commands(off,1,1) ; # Dining floor heat off
        &send_relay_commands(off,1,2) ; # Kitchen floor heat off
    }
}
}

#
## Em's Minis
#
sub em_minis {

    # Em's mini's on if movement and between 7-20:00
    if ( $in24 == 0 &&
         ($hour * 60 + $min) >= 405 &&  # 6:45
         ($hour * 60 + $min) <= 1170 ) { # 19:30
        &send_relay_commands(on,2,7) ;
#       &send_relay_commands(on,2,8) ;
    }


    # Turn off minis if no movement for a minute
    if ( $epoch - $in24_lastmove > 180 ) {
#       &send_relay_commands(off,2,7) ;
#       &send_relay_commands(off,2,8) ;
    }

}

#
## Dan's bedroom lights
#
sub dan_bed_lights {

    # Bedside sockets only on if movement
    if ( $in14 == 0 ) {
        &send_relay_commands(on,1,8) ; 
        &send_relay_commands(on,2,3) ;
        &send_relay_commands(on,4,2) ;
    }

    # Turn off sockets if no movement for 5 minutes and movement on landing
    # has occured more recently, i.e you've left the room
    if ( $epoch - $in14_lastmove > 600 &&
          $in14_lastmove < $in12_lastmove ) {
        #&send_relay_commands(off,1,8) ;   
        &send_relay_commands(off,2,3) ;
        &send_relay_commands(off,4,2) ;
    }

}

#
## Spare bedroom lights
#
sub spare_bed_lights {

        # Bedside sockets only on if movement
        if ( $in21 == 0 ) {
                &send_relay_commands(on,3,1) ;
               # &send_relay_commands(on,4,1) ;
        &send_relay_commands(on,4,6) ; 
        }

        # Turn off sockets if no movement for 10 minutes and movement on landing
        # has occured more recently, i.e you've left the room
        if ( $epoch - $in21_lastmove > 1800 &&
              $in21_lastmove <= $in12_lastmove ) {
                &send_relay_commands(off,3,1) ;
               #    &send_relay_commands(off,4,1) ;
        &send_relay_commands(off,4,6) ;
        }

#Fish tank on most of the day
    if ( $hour >= 8 && $hour <= 19 ) {
                &send_relay_commands(on,4,1) ; # DHW on if between 5-23
                if ( $out41old == 0 ) {
                        &log_stuff ( "Fish Tank On" ) ;
                }

        }
        else {
                #&send_relay_commands(off,4,1) ;
                if ( $out41old == 1 ) {
    #                    &log_stuff ( "Fish Tank Off" ) ;
                }
        }


        # Lights only on if movement
        if ( $in21 == 0 && $in21old == 1 && $sparelights == 0 && $hour > 13 && $hour < 19 ) {
                #&send_lights_soap(1,80) ;
                &send_lights_soap(5,255) ;
                $sparelights = 1 ;
        }
    if ( $hour >= 19 && $sparelights == 1) {
        &send_lights_soap(5,0) ;
                $sparelights = 0 ;
    }

        # Lights off if no movement for ten minutes
        #
        if ( $epoch - $in21_lastmove > 600 &&
             $sparelights == 1 ) {
                &send_lights_soap(5,0) ;
                $sparelights = 0 ;
        }

}



#
## Lounge sockets
#
sub lounge_sockets {

    # lounge sockets only on if movement
    if ( $in22 == 0 ) {
        &send_relay_commands(on,2,2) ;
        &send_relay_commands(on,2,4) ;
        &send_relay_commands(on,2,5) ;
        &send_relay_commands(on,2,6) ;
        &send_relay_commands(on,3,5) ;
    }


    # Sockets off if no movement for ten minutes and movement more recently
    # in the hallway
    if ( $epoch - $in22_lastmove > 600 &&
         $in22_lastmove < $in23_lastmove ) {
        &send_relay_commands(off,2,4) ;
        &send_relay_commands(off,2,5) ;
        &send_relay_commands(off,2,6) ;
        &send_relay_commands(off,3,5) ;
    }

}

#
## Dining sockets
#
sub dining_sockets {

        # Dining Room sockets only on if movement
        if ( $in13 == 0 ) {
                &send_relay_commands(on,4,7) ;
                #&send_relay_commands(on,4,8) ;
        }


        # Sockets off if no movement for ten minutes and movement more recently
        # in the hallway
        if ( $epoch - $in13_lastmove > 600 &&
             $in13_lastmove < $in23_lastmove ) {
                &send_relay_commands(off,4,7) ;
                #&send_relay_commands(off,4,8) ;
        }
}

#
## Kitchen Lights
#
sub kitchen_lights {

        # Kitchen lights only on if movement and dark (in54==0)
        if ( $in11 == 0 && $in11old == 1 && $kitchenlights == 0 && $in54 == 0 ) {
                &send_lights_soap(1,180) ;
        &send_lights_soap(1,180) ; #Dim after 22:00 and before 8:00
        if ( $hour >= 8 && $hour <= 21 ) {
                    &send_lights_soap(1,255) ;
            &send_lights_soap(1,255) ;
        }
        $kitchenlights = 1 ;
        }


        # Lights off if no movement for ten minutes
        #
        if ( $epoch - $in11_lastmove > 600 &&
         $kitchenlights == 1 ) {
                &send_lights_soap(1,0) ;
        &send_lights_soap(1,0) ;
        $kitchenlights = 0 ;
        }
}

#
## Dining Lights
#

sub dining_lights {

        # Dining lights only on if movement and dark outside (in54==0)
        if ( $in13 == 0 && $in13old == 1 && $dininglights == 0 && $in54 == 0 ) {
                &send_lights_soap(2,180) ; #Dim after 22:00 and before 8:00
        &send_lights_soap(2,180) ;
        if ( $hour >= 8 && $hour <= 21 ) {
                    &send_lights_soap(2,255) ;
                    &send_lights_soap(2,255) ;
        }
                $dininglights = 1 ;
        }


        # Lights off if no movement for ten minutes
        #
        if ( $epoch - $in13_lastmove > 600 &&
             $dininglights == 1 ) {
                &send_lights_soap(2,0) ;
                $dininglights = 0 ;
        }


}


#
## Bathroom heating
#
sub bathroom_heating {

    # Heated towel rail on if times match and heating off upstairs
    if ( (( $hour >= 5 && $hour <= 7 && $out16 == 0 ) ||
        ( $hour >= 16 && $hour <= 19 && $out16 == 0 )) &&
            ( $temp1 < 21 && $min <= 35 )) {
        &send_relay_commands(on,1,4) ; 
    }
    elsif ( $hour >= 12 && $hour <= 13 && $min <= 35 ) {
        &send_relay_commands(on,1,4) ;
    }
    else
    {
        &send_relay_commands(off,1,4) ;
    }

    # Bathroom Floor
        if ( $hour >= 5 && $hour <= 20 && $out16 == 0 ) { # Operate this rule between 6-20pm
                if ( $epoch - $lastmove < 600 ) { # Movement in last 10 mins
                        if ( $temp1 < 19.50 ) {
                                &send_relay_commands(on,1,3) ; # Bath floor heat on
                        }
                        else {
                                &send_relay_commands(off,1,3) ; # Bath floor heat off
                        }
        }
        else {
            &send_relay_commands(off,1,3) ; # Bath floor heat off
        }
        }
        else {
                &send_relay_commands(off,1,3) ; # Bath floor heat off
        }

}

#
## Front Door
#
sub front_door {

    if (( $in34 == 0 && $in54 == 0 ) ||
        ( $in23 == 0 && $in54 == 0 )) {
        &send_relay_commands(on,4,5) ;
    }

    if (( $in54 == 1 ) ||
        ( $epoch - $in34_lastmove > 600 &&
          $epoch - $in23_lastmove > 600 )) {
        &send_relay_commands(off,4,5) ;
    }
}

#
## Shutdown when out
#
sub shutdown_when_out {

    if (( $epoch - $lastmove > 300 &&
          $in34_lastmove >= $in11_lastmove &&
          $in34_lastmove >= $in13_lastmove &&
          $in34_lastmove >= $in14_lastmove &&
          $in34_lastmove >= $in21_lastmove &&
          $in34_lastmove >= $in22_lastmove &&
          $in34_lastmove >= $in24_lastmove ) ||
        ( $epoch - $lastmove > 300 &&
              #$in42_lastmove >= $in11_lastmove &&
              $in42_lastmove >= $in13_lastmove &&
              $in42_lastmove >= $in14_lastmove &&
              $in42_lastmove >= $in21_lastmove &&
              $in42_lastmove >= $in22_lastmove &&
              $in42_lastmove >= $in24_lastmove )) {
        if ( $fullhouse == 1 ) {
            &log_stuff ( "House Empty I Think!" ) ;
            $fullhouse = 0 ;
        # Might as well turn everything off then..
               #&send_relay_commands(off,1,1) ;
               #&send_relay_commands(off,1,2) ;
               #&send_relay_commands(off,1,3) ;
               #&send_relay_commands(off,1,4) ;
               #&send_relay_commands(off,1,5) ;
               #&send_relay_commands(off,1,6) ;
               #&send_relay_commands(off,1,7) ;
               # &send_relay_commands(off,1,8) ;
                &send_relay_commands(off,2,1) ;
               #&send_relay_commands(off,2,2) ;
                &send_relay_commands(off,2,3) ;
                &send_relay_commands(off,2,4) ;
                &send_relay_commands(off,2,5) ;
                &send_relay_commands(off,2,6) ;
                &send_relay_commands(off,2,7) ;
                &send_relay_commands(off,2,8) ;
                &send_relay_commands(off,3,1) ;
               #&send_relay_commands(off,3,2) ;
               #&send_relay_commands(off,3,3) ;
               #&send_relay_commands(off,3,4) ;
                &send_relay_commands(off,3,5) ;
                &send_relay_commands(off,3,6) ;
                &send_relay_commands(off,3,7) ;
                &send_relay_commands(off,3,8) ;
               #&send_relay_commands(off,4,1) ;
                &send_relay_commands(off,4,2) ;
               #&send_relay_commands(off,4,3) ;
               #&send_relay_commands(off,4,4) ;
                &send_relay_commands(off,4,5) ;
                &send_relay_commands(off,4,6) ;
                &send_relay_commands(off,4,7) ;
               # &send_relay_commands(off,4,8) ;
        }
        }
    else {
        #&send_relay_commands(on,4,1) ;
                #&log_stuff ( "<status> relay41 on </status>" ) ;
        if ( $fullhouse == 0 ) {
            &log_stuff ( "House Occupied I Think!" ) ;
            $fullhouse = 1 ;
            system ("/spare/houseemail") ;
        }
    }
}


#
## Log stuff to a logfile
#
sub log_stuff {
    $cyear = $year + 1900 ;
    $cmon = $mon + 1 ;
    open ( HALOG , ">>ha_log.xml" ) || die ( "Cannot Open Log File" ) ;
    print HALOG " $mday/$cmon/$cyear:$hour:$min:$sec  - @_ \n " ;
    close ( HALOG ) ;

}

#
## Send relay commands
#
sub send_relay_commands { #call as on/off/flash 1-5 1-8

    $relay_command = "relay_" . @_[0] ;
    $relay_unit = "io" . @_[1] ;
    $relay_number = @_[2];

    ${$relay_unit}->$relay_command( $relay_number ) ;

    if (( ${out.@_[1].$relay_number} == 1 &&
          $relay_command eq "relay_off" ) ||
        ( ${out.@_[1].$relay_number} == 0 &&
          $relay_command eq "relay_on" )) {
&log_stuff ("<status>relay @_[1]@_[2] switched @_[0] </status>");
    }
}

#
## Create html
#
sub create_html {

    open ( LASTMOVE , ">/var/www/html/lastmove.html" ) ||
        die ( "Cannot Open lastmove.html File" ) ;
    print LASTMOVE "<html> \n" ;
    print LASTMOVE "<body> \n" ;

    print LASTMOVE "<h4>Inputs</h4> \n" ;
    print LASTMOVE "<table border=\"1\"> \n" ;
    print LASTMOVE "<tr> \n" ;
    print LASTMOVE "<td><b> NAME </td><td><b> ID</td><td><b>STATUS</td> \n" ;
    print LASTMOVE "</tr> \n " ;

    &sensible_times( $epoch - $in11_lastmove );
        print LASTMOVE  "<td>Kitchen PIR</td><td>IN11</td><td> $sensible ago </td></tr>" ;
    &sensible_times( $epoch - $in12_lastmove ) ;
        print LASTMOVE  "<td>Landing PIR</td><td>IN12</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in13_lastmove ) ;
        print LASTMOVE  "<td>Dining Room PIR</td><td>IN13</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in14_lastmove ) ;
        print LASTMOVE  "<td>Master Bed PIR</td><td>IN14</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in21_lastmove ) ;
        print LASTMOVE  "<td>Spare Room PIR</td><td>IN21</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in22_lastmove ) ;
        print LASTMOVE  "<td>Lounge PIR</td><td>IN22</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in23_lastmove ) ;
        print LASTMOVE  "<td>Hallway PIR</td><td>IN23</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in24_lastmove ) ;
        print LASTMOVE  "<td>Em Bedroom PIR</td><td>IN24</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in31_lastmove ) ;
        print LASTMOVE  "<td>Hallway Smoke</td><td>IN31</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in32_lastmove ) ;
        print LASTMOVE  "<td>Kitchen Smoke/Heat</td><td>IN32</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in33_lastmove ) ;
        #print LASTMOVE  "Unused              :" . $sensible . " ago. <br>" ;
        &sensible_times( $epoch - $in34_lastmove ) ;
        print LASTMOVE  "<td>Front Door</td><td>IN34</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in41_lastmove ) ;
        print LASTMOVE  "<td>Landing Smoke</td><td>IN41</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in42_lastmove ) ;
        print LASTMOVE  "<td>Back Door</td><td>IN42</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in43_lastmove ) ;
        #print LASTMOVE  "Unused              :" . $sensible . " ago. <br>" ;
        &sensible_times( $epoch - $in44_lastmove ) ;
        #print LASTMOVE  "Unused              :" . $sensible . " ago. <br>" ;
        &sensible_times( $epoch - $in51_lastmove ) ;
        print LASTMOVE  "<td>Garage Roller</td><td>IN51</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in52_lastmove ) ;
        print LASTMOVE  "<td>Garage Back</td><td>IN52</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in53_lastmove ) ;
        print LASTMOVE  "<td>Shed Doors</td><td>IN53</td><td> $sensible ago </td></tr>" ;
        &sensible_times( $epoch - $in54_lastmove ) ;
        print LASTMOVE  "<td>Light Sensor</td><td>IN54</td><td> $sensible ago </td></tr>" ;

        print LASTMOVE " </table> " ;

        print LASTMOVE "<p>" ;
        print LASTMOVE "<h4>Outputs</h4> \n" ;
        print LASTMOVE "<table border=\"1\"> \n" ;
        print LASTMOVE "<tr> \n" ;
        print LASTMOVE "<td><b> NAME </td><td><b> ID</td><td><b>STATUS</td> \n" ;
        print LASTMOVE "</tr> \n " ;

        print LASTMOVE "<td>Dining Room U/F</td><td>OUT11</td><td> $out11 </td></tr>" ;
    print LASTMOVE "<td>Kitchen U/F</td><td>OUT12</td><td> $out12 </td></tr>" ;
    print LASTMOVE "<td>Bathroom U/F</td><td>OUT13</td><td> $out13 </td></tr>" ;
    print LASTMOVE "<td>Bathroom Towel Rail</td><td>OUT14</td><td> $out14 </td></tr>" ;
    print LASTMOVE "<td>D/S Central Heating</td><td>OUT15</td><td> $out15 </td></tr>" ;
    print LASTMOVE "<td>U/S Central Heating</td><td>OUT16</td><td> $out16 </td></tr>" ;
    print LASTMOVE "<td>Domestic Hot Water</td><td>OUT17</td><td> $out17 </td></tr>" ;
    print LASTMOVE "<td>Dan Bedside Table</td><td>OUT18</td><td> $out18 </td></tr>" ;
    print LASTMOVE "<td>Lounge Fire Right</td><td>OUT21</td><td> $out21 </td></tr>" ;
    print LASTMOVE "<td>Lounge Air Con</td><td>OUT22</td><td> $out22 </td></tr>" ;
    print LASTMOVE "<td>Sairee Bedside Table</td><td>OUT23</td><td> $out23 </td></tr>" ;
    print LASTMOVE "<td>Lounge Rear Sofa Door</td><td>OUT24</td><td> $out24 </td></tr>" ;
    print LASTMOVE "<td>Lounge Window Shelves</td><td>OUT25</td><td> $out25 </td></tr>" ;
    print LASTMOVE "<td>Lounge Sofa Shelves</td><td>OUT26</td><td> $out26 </td></tr>" ;
    print LASTMOVE "<td>Baby Room Mini Lights</td><td>OUT27</td><td> $out27 </td></tr>" ;
    print LASTMOVE "<td>Baby Room Window Left</td><td>OUT28</td><td> $out28 </td></tr>" ;
    print LASTMOVE "<td>Spare Room by Door</td><td>OUT31</td><td> $out31 </td></tr>" ;
    print LASTMOVE "<td>Internal Chime Siren</td><td>OUT32</td><td> $out32 </td></tr>" ;
    print LASTMOVE "<td>Internal Loud Siren</td><td>OUT33</td><td> $out33 </td></tr>" ;
    print LASTMOVE "<td>ADT Siren Front</td><td>OUT34</td><td> $out34 </td></tr>" ;
    print LASTMOVE "<td>Lounge Side Sofa Door</td><td>OUT35</td><td> $out35 </td></tr>" ;
    # print LASTMOVE "n/c                  :"  . $out36 . "<br>" ;
    # print LASTMOVE "n/c                  :"  . $out37 . "<br>" ;
    # print LASTMOVE "n/c                  :"  . $out38 . "<br>" ;
    print LASTMOVE "<td>Spare Room Desk</td><td>OUT41</td><td> $out41 </td></tr>" ;
    print LASTMOVE "<td>Master Bed Tallboy</td><td>OUT42</td><td> $out42 </td></tr>" ;
    print LASTMOVE "<td>Master Bedroom TV</td><td>OUT43</td><td> $out43 </td></tr>" ;
    print LASTMOVE "<td>Dining Room Freezer</td><td>OUT44</td><td> $out44 </td></tr>" ;
    print LASTMOVE "<td>Front Door Light</td><td>OUT45</td><td> $out45 </td></tr>" ;
    print LASTMOVE "<td>Spare Room Cupboard</td><td>OUT46</td><td> $out46 </td></tr>" ;
    print LASTMOVE "<td>Dining Room Window</td><td>OUT47</td><td> $out47 </td></tr>" ;
    print LASTMOVE "<td>Dining Room Piano</td><td>OUT48</td><td> $out48 </td></tr>" ;
    # print LASTMOVE "n/c                  :"  . $out51 . "<br>" ;
    print LASTMOVE "<td>Garden Rear Flood</td><td>OUT52</td><td> $out52 </td></tr>" ;
    print LASTMOVE "<td>Garden 3 Light</td><td>OUT53</td><td> $out53 </td></tr>" ;
    print LASTMOVE "<td>Garden 2 Light</td><td>OUT54</td><td> $out54 </td></tr>" ;
    print LASTMOVE "<td>Garage Lights</td><td>OUT55</td><td> $out55 </td></tr>" ;
    print LASTMOVE "<td>Drive Light</td><td>OUT56</td><td> $out56 </td></tr>" ;
    print LASTMOVE "<td>Garage Clock</td><td>OUT57</td><td> $out57 </td></tr>" ;
    print LASTMOVE "<td>Garage Internal Siren</td><td>OUT58</td><td> $out58 </td></tr>" ;
        print LASTMOVE " </table> " ;

        print LASTMOVE "<p>" ;
        print LASTMOVE "<h4>Temps</h4> \n" ;
        print LASTMOVE "<table border=\"1\"> \n" ;
        print LASTMOVE "<tr> \n" ;
        print LASTMOVE "<td><b>ROOM</td><td><b>ID</td><td><b>TEMP</td> \n" ;
        print LASTMOVE "</tr> \n " ;

        print LASTMOVE "<td>Dan Bed</td><td>T11</td><td> $temp1 C </td></tr>" ;
    print LASTMOVE "<td>Em Bed</td><td>T12</td><td> $temp2 C </td></tr>" ;
    print LASTMOVE "<td>Lounge</td><td>T13</td><td> $temp3 C </td></tr>" ;
    print LASTMOVE "<td>Dining Room</td><td>T14</td><td> $temp4 C </td></tr>" ;
        print LASTMOVE " </table> " ;


    print LASTMOVE " <p> <B> Vars </B> <p> " ;
    &sensible_times( $epoch - $lastmove ) ;
        print LASTMOVE "Lastmove          :"  . $sensible . " ago <br>" ;

        close ( LASTMOVE ) ;


}

#
# Sub to turn all this talk of seconds into proper time
#

sub sensible_times {

        if ( @_[0] < 60 ) {
                $sensible = "@_[0] secs" ;
        }
        if ( @_[0] >= 60 && @_[0] < 3600 ) { # Up to 2 hours as mins
                $sensible = int(@_[0]/60 + 0.5) . " mins" ; # perl no rounding
        }
        if ( @_[0] >= 3600 && @_[0] < 86400 ) { # Up to 1 day as hours
                $sensible = int(@_[0]/3600 + 0.5) . " hours" ;
        }
        if ( @_[0] >= 86400 && @_[0] < 1209600 ) { # Up to 2 weeks as days
                $sensible = int(@_[0]/86400 + 0.5) . " days" ;
        }
        if ( @_[0] >= 1209600 && @_[0] < 4838400 ) { # Up to 8 weeks as weeks
                $sensible = int(@_[0]/604800 + 0.5) . " weeks" ;
        }
    if ( @_[0] >= 4838400 && @_[0] < 84384000 ) { # Up to 80 weeks as month
                $sensible = int(@_[0]/2629800 + 0.5) . " months" ;
        }
    if ( @_[0] >= 84384000 ) { # More than 80 weeks as years
                $sensible = int(@_[0]/31557600 + 0.5) . " years" ;
        }



}


#
## This subroutine will ensure that when gracefully shutting down all
## variables are saved
#
sub keep_my_vars {

      @array_of_vars = (lastmove , fullhouse ,
            temp1 , temp2 , temp3 , temp4 ,
                        out11_lastmove , out11old , out11_trig , out11 ,
                        out12_lastmove , out12old , out12_trig , out12 ,
                        out13_lastmove , out13old , out13_trig , out13 ,
                        out14_lastmove , out14old , out14_trig , out14 ,
                        out15_lastmove , out15old , out15_trig , out15 ,
                        out16_lastmove , out16old , out16_trig , out16 ,
                        out17_lastmove , out17old , out17_trig , out17 ,
                        out18_lastmove , out18old , out18_trig , out18 ,
                        out21_lastmove , out21old , out21_trig , out21 ,
                        out22_lastmove , out22old , out22_trig , out22 ,
                        out23_lastmove , out23old , out23_trig , out23 ,
                        out24_lastmove , out24old , out24_trig , out24 ,
                        out25_lastmove , out25old , out25_trig , out25 ,
                        out26_lastmove , out26old , out26_trig , out26 ,
                        out27_lastmove , out27old , out27_trig , out27 ,
                        out28_lastmove , out28old , out28_trig , out28 ,
                        out31_lastmove , out31old , out31_trig , out31 ,
                        out32_lastmove , out32old , out32_trig , out32 ,
                        out33_lastmove , out33old , out33_trig , out33 ,
                        out34_lastmove , out34old , out34_trig , out34 ,
                        out35_lastmove , out35old , out35_trig , out35 ,
                        out36_lastmove , out36old , out36_trig , out36 ,
                        out37_lastmove , out37old , out37_trig , out37 ,
                        out38_lastmove , out38old , out38_trig , out38 ,
                        out41_lastmove , out41old , out41_trig , out41 ,
                        out42_lastmove , out42old , out42_trig , out42 ,
                        out43_lastmove , out43old , out43_trig , out43 ,
                        out44_lastmove , out44old , out44_trig , out44 ,
                        out45_lastmove , out45old , out45_trig , out45 ,
                        out46_lastmove , out46old , out46_trig , out46 ,
                        out47_lastmove , out47old , out47_trig , out47 ,
                        out48_lastmove , out48old , out48_trig , out48 ,
                        out51_lastmove , out51old , out51_trig , out51 ,
                        out52_lastmove , out52old , out52_trig , out52 ,
                        out53_lastmove , out53old , out53_trig , out53 ,
                        out54_lastmove , out54old , out54_trig , out54 ,
                        out55_lastmove , out55old , out55_trig , out55 ,
                        out56_lastmove , out56old , out56_trig , out56 ,
                        out57_lastmove , out57old , out57_trig , out57 ,
                        out58_lastmove , out58old , out58_trig , out58 ,
            in11_lastmove , in11old , in11_trig , in11 ,
                        in12_lastmove , in12old , in12_trig , in12 ,
                        in13_lastmove , in13old , in13_trig , in13 ,
                        in14_lastmove , in14old , in14_trig , in14 ,
                        in21_lastmove , in21old , in21_trig , in21 ,
                        in22_lastmove , in22old , in22_trig , in22 ,
                        in23_lastmove , in23old , in23_trig , in23 ,
                        in24_lastmove , in24old , in24_trig , in24 ,
                        in31_lastmove , in31old , in31_trig , in31 ,
                        in32_lastmove , in32old , in32_trig , in32 ,
                        in33_lastmove , in33old , in33_trig , in33 ,
                        in34_lastmove , in34old , in34_trig , in34 ,
                        in41_lastmove , in41old , in41_trig , in41 ,
                        in42_lastmove , in42old , in42_trig , in42 ,
                        in43_lastmove , in43old , in43_trig , in43 ,
                        in44_lastmove , in44old , in44_trig , in44 ,
                        in51_lastmove , in51old , in51_trig , in51 ,
                        in52_lastmove , in52old , in52_trig , in52 ,
                        in53_lastmove , in53old , in53_trig , in53 ,
                        in54_lastmove , in54old , in54_trig , in54     ) ;


    foreach ( @array_of_vars ) {
            open( HAVARS , ">varstore/$_" ) ||
        die("Cannot Open File varstore/$_") ;
            print HAVARS $$_ ;
            close(HAVARS) ;
        &log_stuff( "<varsave>Saving \$$_ as $$_ </varsave>" );
    }
}


#
## This subroutine is used to restores a copy of all desired varaibles on
## restarting the application
#
sub restore_my_vars {

    opendir(VARDIR, "varstore/" ) or die "Unable to open dir varstore/" ;
    @array_of_vars = readdir(VARDIR) ;
    close(VARDIR) ;
   
    foreach ( @array_of_vars ) {
                open( HAVARS , "varstore/$_" ) ||
                die("Cannot Open File varstore/$_") ;
                $$_ = <HAVARS> ;
                close(HAVARS) ;
        &log_stuff( "<varload>Restoring \$$_ as $$_ </varload>" );
        $$_ = $$_ + 0 ;
        }

}


#
## This subroutine is used to gracefully shutdown this process
#
sub check_shutdown {

    if ( -e "stop_ha" ) {
        &keep_my_vars ;
            unlink( "stop_ha" ) ;
        exit
    }

}


sub ping_check {

        if ( -e "ping_ha" ) {

        $pingcheck = $io1->ping() ;
        &log_stuff( "Module 1 Ping $pingcheck" );

        $pingcheck = $io2->ping() ;
        &log_stuff( "Module 2 Ping $pingcheck" );

        $pingcheck = $io3->ping() ;
        &log_stuff( "Module 3 Ping $pingcheck" );

        $pingcheck = $io4->ping() ;
        &log_stuff( "Module 4 Ping $pingcheck" );

    $pingcheck = $io5->ping() ;
        &log_stuff( "Module 5 Ping $pingcheck" );

        &print_firmware_versions;
        }
}


sub send_lights_soap {

#   $soap_response = SOAP::Lite
#       -> uri('http://192.168.101.172/Lights')
#       -> proxy('http://192.168.101.172/cgi-bin/lights')
#       -> send( "$_[0]" , "$_[1]" ) ;
#
#   $res = $soap_response->result ;
#   &log_stuff( " $res " );
    log_stuff(" lights on channel " . $_[0] . " intens " . $_[1]);
    `echo "ha~dmx~lighting~~$_[0]~$_[1]" > /root/middleware/production/dangen2test/dansend.txt`
}


sub debug_tests {
    #Side Gate shenanegans!
    if ( -e "/cgihomedir/log/lastcode.log" ) {
        open (INFILE, "/cgihomedir/log/lastcode.log") or die "Can't open!" ;
        while (<INFILE>) {
                    $KEYCODE = $_ ;
    }
    close INFILE ;
    if ( $KEYCODE == "8088" ) {
                        &log_stuff ( "Side Gate Released" ) ;
            &send_relay_commands(on,3,2) ; 
            `rm /cgihomedir/log/lastcode.log` ;
            $out32_lastmove = $epoch ;
        }
    }
        if ( $epoch - $out32_lastmove > 15 ) {
            &send_relay_commands(off,3,2) ;
        }


        if ( -e "debug_ha" ) {

    open (FILE, "debug_ha") or die "Can't open debug_ha!" ;
        while (<FILE>) {
        @ARRAY = split(/,/, $_);

        $relay_unit = "io" . @ARRAY[0] ;
        $relay_number = @ARRAY[1] ;
        #${$relay_unit}->$relay_command( $relay_number ) ;

    ${$relay_unit}->relay_flash( $relay_number , 15 ) ; #Flash the relay

        close FILE;
        }
    }
#sleep 5 ;
$uor=2; $dor=2; $wor=2; $dfor=2 ; $kfor=2;
if ( -e "uor_on" ) { $uor=1; }
if ( -e "uor_off" ) { $uor=0; }
if ( -e "dor_on" ) { $dor=1; }
if ( -e "dor_off" ) { $dor=0; }
if ( -e "wor_on" ) { $wor=1; }
if ( -e "wor_off" ) { $wor=0; }
if ( -e "kfor_on" ) { $kfor=1; }
if ( -e "kfor_off" ) { $kfor=0; }
if ( -e "dfor_on" ) { $dfor=1; }
if ( -e "dfor_off" ) { $dfor=0; }

}