#!/usr/bin/perl
#-----------------------------------------------------------------
# By: john@stilen.com
#
# Purpouse: 
#     Keep fan as slow as possible for a given Target CPU Temp.
#
# Some Testing:
#     speed    temp
#     100      40-42
#     255-100  37-39
#-----------------------------------------------------------------
my $debug=        "0";                # debug 1=on, 0=off
my $pause=        "5";                # Time between tests
my $sensors=      "/usr/bin/sensors"; # Binary for sensors
my $Sensor_string="pc87366-isa-1410"; # Header in sensors output
my $Speed=        "100" ;             # Setting default fan speed.
my $TargetTmp_upper=    "40";               # Target temp for CPU
my $TargetTmp_lower=    "39";               # Target temp for CPU
#-----------------------------------------------------------------
# flush the buffer
$| = 1;
#-----------------------------------------------------------------
# daemonize the program
if ( $debug eq "0" ){  &daemonize; }
#-----------------------------------------------------------------
# Set initial fan speed to our base
&update_fanspeed($Speed);
#-----------------------------------------------------------------
# Main Loop, 
# Runs forever
while ( 1 ){
    #
    # Get temp
    #
    chomp ( my $Temp=&get_temp );
    if ( $debug eq "1" ){  print "Temp: $Temp\n"; }
    #
    # Get speed
    #
    chomp ( $Speed=&get_fanspeed );
    if ( $debug eq "1" ){  print "Speed:  $Speed\n"; }
    #
    # Calculate new speed
    #
    my $NewSpeed=&new_fanspeed($Temp,$Speed);
    if ( $debug eq "1" ){  print "NewSpeed:  $NewSpeed\n"; }
    #
    # If Speed and NewSpeed are not equal, update fan speed file.
    #
    if ( $NewSpeed ne $Speed ){ 
        &update_fanspeed($NewSpeed); 
	if ( $debug eq "1" ){  print "Loading new speed\n"; }
    }
    #
    # Sleep
    #
    system ( sleep $pause );
}
#-----------------------------------------------------------------
sub daemonize {
    chdir '/'                 or die "Can't chdir to /: $!";
    open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
    open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
    open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
    defined(my $pid = fork)   or die "Can't fork: $!";
    exit if $pid;
    setsid                    or die "Can't start a new session: $!";
    umask 0;
}
#-----------------------------------------------------------------
sub update_fanspeed {
    my $NewSpeed=shift;
    open ( FANSPEED, ">>/sys/devices/platform/i2c-9191/9191-1410/pwm2") || die "Cannot read fanspeed file: $?\n";
    print FANSPEED "$NewSpeed";
    close ( FANSPEED ) || die "Cannot close fanspeed file: $?\n";
    return;
}    
#-----------------------------------------------------------------
sub new_fanspeed {
    my $Temp=shift;
    my $Speed=shift;    
    #
    # If temp is over 42, increment fan speed.
    #
    if (  "$Temp" > $TargetTmp_upper ){ ++$Speed ; }    
    #
    # If temp is under 42, decrement fan speed.
    #
    if (  $Temp < $TargetTmp_lower ){ --$Speed ; }
    #
    # Return the new speed
    #
    return ( $Speed );
}
#-----------------------------------------------------------------
sub get_fanspeed {
    open ( FANSPEED, "</sys/devices/platform/i2c-9191/9191-1410/pwm2") || die "Cannot read fanspeed file: $?\n";
    chomp ( my $Speed=<FANSPEED> );
    close ( FANSPEED ) || die "Cannot close fanspeed file: $?\n";
    return ( $Speed );
}
#-----------------------------------------------------------------
sub get_temp {
    # Process output of `sensors` one line at a time.
    open ( SENSORS, "$sensors |") || die "Cannot run sensors\n";
    while (<SENSORS>){

      ########################################
      #  Screen for relevent sensor data
      #   - If lm_sensors modules are loade incorrectly,
      #     double output of incorrect values result.
      #   - This allows one to specify which to collect
      ########################################
 
      # Start collecting data when this line is reached
      if ( $_ =~ m/$Sensor_string/ ){
    	  $Start="1";
      # Stop Collecting data when this line is reached
      } elsif ( $_ =~ m/^$/ ) {
    	  $Start="0";
    	  done;
      }
      # If Start is 1, we are working with good data
      if ( $Start eq "1" ){
    	#
	# Example string: CPU0 Temp:   +42 C  (low  =    +0 C, high =   +70 C)
    	#
    	$bla=$_;
	# print "$bla";
    	if ( $bla =~ m{
    			  ^CPU0
			  \W*
			  Temp: 	# Starts with temp:
			  \W*           # NonWord characters
    			  \+
    			  (\d+)		# digits are the temp
			  .*            # Anything up to
    			  \n		# new line
    		      }xig		# allow comments, case insensetive, global
           ) { 
	       #
	       # Debug: Print the captured value
	       #
	       if ( $debug eq "0" ){  print "CPU Tmep:\t$1\n"; }
	       # END of SENSORS data
               close ( SENSORS );
	       return ($1);
	   }
      } 
    }
    # Should never get here.
    close ( SENSORS );
    return (0);
}
#-----------------------------------------------------------------
