#!/usr/bin/perl #----------------------------------------------------------------- # By: johns@msli.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 # # REFERENCE: http://www.intel.com/support/processors/pentiumiii/sb/cs-007589.htm # CPU MODEL: Intel(R) Pentium(R) III CPU - S 1266MHz # Min temp: 45 #----------------------------------------------------------------- my $debug= "1"; # debug 1=on, 0=off my $graph= "1"; # graph 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 $time=time( ); my $Speed= "100" ; # Setting default fan speed. my $TargetTmp_upper="44"; # Target temp for CPU my $TargetTmp_lower="42"; # Target temp for CPU my $ProcFile= "/sys/devices/platform/i2c-9191/9191-1410/pwm2"; my $rrd_file= "/root/rrd/fan_temp.rrd"; my $graph_file_2hr= "/root/rrd/fan_temp_2hr.png"; my $graph_file_12hr="/root/rrd/fan_temp_12hr.png"; my $graph_file_1wk="/root/rrd/fan_temp_1wk.png"; #----------------------------------------------------------------- # 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"; } } # # Create RRD file, if it does not exist # if ( ! -e "$rrd_file" ){ &create_graph($rrd_file); }; # # Record Fan speed # my $NewSpeed=&record_fanspeed($Temp,$Speed,$rrd_file); # # Graph from rrd # &graph_fanspeed($rrd_file,$graph_file_2hr,$graph_file_12hr,$graph_file_1wk); # # # 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 create_graph { chomp ( my $rrd_file=shift ); # rrdtool create $rrd_directory/fan_temp.rrd \ # --step 1 \ # 1 sec steps for RRA's blow # DS:Temp:GAUGE:10:0:U \ # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data # DS:Speed:GAUGE:10:0:U \ # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data # RRA:AVERAGE:0.5:1:10 \ # Archive: Average over 1 measurement (10 sec), 10 values should be stroed # RRA:AVERAGE:0.5:6:60 \ # Archive: Average over 6 measurements (1 min), 60 values should be stroed # RRA:AVERAGE:0.5:24:240 \ # Archive: Average over 24 measurements (4 min), 240 values should be stroed # RRA:AVERAGE:0.5:288:2880 \ # Archive: Average over 288 measurements (42 min),2880 values should be stroed # RRA:MAX:0.5:1:10 \ # Archive: MAX over 1 measurements (10 sec), 10 values should be stroed # RRA:MAX:0.5:6:60 \ # Archive: MAX over 6 measurements (1 min), 60 values should be stroed # RRA:MAX:0.5:24:240 \ # Archive: MAX over 24 measurements (4 min), 240 values should be stroed # RRA:MAX:0.5:288:2880 \ # Archive: MAX over 288 measurements (42 min),2880 values should be stroed # RRA:LAST:0.5:1:10 \ # Archive: Last over 1 measurement (10 sec), 10 values should be stored # RRA:LAST:0.5:6:60 \ # Archive: MAX over 6 measurements (1 min), 60 values should be stroed # RRA:LAST:0.5:24:240 \ # Archive: MAX over 24 measurements (4 min), 240 values should be stroed # RRA:LAST:0.5:288:2880 \ # Archive: MAX over 288 measurements (42 min),2880 values should be stroed system( qq{rrdtool create $rrd_file \\ --step 1 \\ DS:Temp:GAUGE:10:0:U \\ DS:Speed:GAUGE:10:0:U \\ RRA:AVERAGE:0.5:1:10 \\ RRA:AVERAGE:0.5:6:60 \\ RRA:AVERAGE:0.5:24:240 \\ RRA:AVERAGE:0.5:288:2880 \\ RRA:MAX:0.5:1:10 \\ RRA:MAX:0.5:6:60 \\ RRA:MAX:0.5:24:240 \\ RRA:MAX:0.5:288:2880 \\ RRA:LAST:0.5:1:10 \\ RRA:LAST:0.5:6:60 \\ RRA:LAST:0.5:24:240 \\ RRA:LAST:0.5:288:2880} ); } #----------------------------------------------------------------- sub record_fanspeed{ my $temp=shift; my $speed=shift; my $rrd_file=shift ; system ( "rrdtool update $rrd_file --template Temp:Speed N:$temp:$speed" ); } #----------------------------------------------------------------- sub graph_fanspeed { my $rrd_file=shift; my $graph_file_2hr=shift; my $graph_file_12hr=shift; my $graph_file_1wk=shift; ##################################### # For the graph: # Temp a=ave b=max c=last # Speed d=ave e=max f=last ##################################### # # Draw 2 Hour png # system( "rrdtool", "graph", "$graph_file_2hr", "--imgformat=PNG", "--start=-2880", "-c", "BACK#343435", "-c", "FONT#ffffff", "-c", "CANVAS#605f60", "--title=2 Hour Fanspeed Tmp", "--height=150", "--width=400", "--vertical-label=Red=degreeC, Yellow=speed", "--step", "10", "DEF:a=$rrd_file:Temp:AVERAGE", "DEF:b=$rrd_file:Temp:MAX", "DEF:c=$rrd_file:Temp:LAST", "DEF:d=$rrd_file:Speed:AVERAGE", "DEF:e=$rrd_file:Speed:MAX", "DEF:f=$rrd_file:Speed:LAST", "LINE1:c#ea0e2b:Temp\\r:", "GPRINT:a:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:b:MAX:Max\\t%6.0lf%s\\r", "GPRINT:c:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n", "LINE1:f#EACC00:Speed\\r:", "GPRINT:d:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:e:MAX:Max\\t%6.0lf%s\\r", "GPRINT:f:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n" ); # # Draw 12 Hour png # system( "rrdtool", "graph", "$graph_file_12hr", "--imgformat=PNG", "--start=-86400", "-c", "BACK#343435", "-c", "FONT#ffffff", "-c", "CANVAS#605f60", "--title=12 Hour Fanspeed Tmp", "--height=150", "--width=400", "--vertical-label=Red=degreeC, Yellow=speed", "--step", "10", "DEF:a=$rrd_file:Temp:AVERAGE", "DEF:b=$rrd_file:Temp:MAX", "DEF:c=$rrd_file:Temp:LAST", "DEF:d=$rrd_file:Speed:AVERAGE", "DEF:e=$rrd_file:Speed:MAX", "DEF:f=$rrd_file:Speed:LAST", "LINE1:c#ea0e2b:Temp\\r:", "GPRINT:a:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:b:MAX:Max\\t%6.0lf%s\\r", "GPRINT:c:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n", "LINE1:f#EACC00:Speed\\r:", "GPRINT:d:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:e:MAX:Max\\t%6.0lf%s\\r", "GPRINT:f:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n" ); # # Draw 1week png # system( "rrdtool", "graph", "$graph_file_1wk", "--imgformat=PNG", "--start=-604800", "-c", "BACK#343435", "-c", "FONT#ffffff", "-c", "CANVAS#605f60", "--title=1 Week Fanspeed Tmp", "--height=150", "--width=400", "--vertical-label=Red=degreeC, Yellow=speed", "--step", "10", "DEF:a=$rrd_file:Temp:AVERAGE", "DEF:b=$rrd_file:Temp:MAX", "DEF:c=$rrd_file:Temp:LAST", "DEF:d=$rrd_file:Speed:AVERAGE", "DEF:e=$rrd_file:Speed:MAX", "DEF:f=$rrd_file:Speed:LAST", "LINE1:c#ea0e2b:Temp\\r:", "GPRINT:a:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:b:MAX:Max\\t%6.0lf%s\\r", "GPRINT:c:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n", "LINE1:f#EACC00:Speed\\r:", "GPRINT:d:AVERAGE:Average\\t%6.0lf%s\\r", "GPRINT:e:MAX:Max\\t%6.0lf%s\\r", "GPRINT:f:LAST:Last\\t%6.0lf%s\\r", "COMMENT:\\n" ); } #----------------------------------------------------------------- sub update_fanspeed { my $NewSpeed=shift; open ( FANSPEED, ">>$ProcFile") || 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 ){ unless( $Speed eq 255){ ++$Speed ; } } # # If temp is under 42, decrement fan speed. # if ( $Temp < $TargetTmp_lower ){ unless( $Speed eq 0 ){ --$Speed ; } } # # Return the new speed # return ( $Speed ); } #----------------------------------------------------------------- sub get_fanspeed { open ( FANSPEED, "<$ProcFile") || die "Cannot read fanspeed file: $?\n"; chomp ( my $Speed= ); 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 (){ ######################################## # 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); } #-----------------------------------------------------------------