#!/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 ;
    ×tamp_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; }
}