[OT: Perl/Linux] Stimare tempi di carica e scarica delle batterie

Prendiamo in considerazione il generico caso di un notebook dotato di sottosistema ACPI con un numero di batterie non prestabilito (ok, nella maggior parte dei casi sarà una, talvolta due), su cui gira un sistema Linux 2.6.x correttamente configurato. Le informazioni necessarie si trovano nel filesystem virtuale procfs, generalmente montato nel percorso /proc. In particolare, nel path /proc/acpi/battery troviamo una directory per ogni batteria presente nel nostro notebook. Ciascuna di queste directory contiene due file, info e state. All'interno di questi file, in formato chiave valore separati da due punti e spazi, troviamo diversi parametri riguardanti rispettivamente le informazioni "di fabbricazione" della batteria e quelle relative al suo stato attuale.

Ecco uno script in Perl in grado di calcolare il tempo di carica o scarica relativo a ciascuna batteria e complessivo. Utilizza le informazioni sullo carica attualmente accumulata nella batteria e il tasso con cui essa sta crescendo/decrescendo.

Lo pubblico perchè lo trovo una buona dimostrazione delle possibilità offerte dal linguaggio Perl e dalla sua implementazione delle regular expressions quando ci si trova a manipolare stream di testo (frequente in ambiente Unix).


#!/usr/bin/perl

# Written by Andrea Sansottera. Works on Linux only.

$battery_dir_path = "/proc/acpi/battery";

opendir($battery_dir, $battery_dir_path);

if ($battery_dir) {

 @files = readdir($battery_dir);

 foreach (@files) {

  $battery = $_;

  # do not consider current and parent directory entries
  if ( ($_ ne '.') && ($_ ne '..') ) {

   # read info about the battery
   open ($info_file, '<', "$battery_dir_path/$battery/info") or die $!;
   read ($info_file, $info, 1000) or die $!;
   
   # read the state of the battery
   open ($state_file, '<', "$battery_dir_path/$battery/state") or die $!;
   read ($state_file, $state, 1000) or die $!;
   
   # determine whether the battery is present or not
   $present = ($state =~ /present:[ ]*yes/);
   print ("battery $battery supported", ($present ? " and present" : " but non present"), "");
   
   # if the battery is present, check for current status
   if ($present) {

    # determine whether the battery is in use or not
    ($charging_state) = ( $state =~ /charging state:[ ]*([]*)/ );

    if ($charging_state eq "charged") {
     print "battery $battery is not in use";
    } else {

     # get info on the battery use
     ($present_rate) = ( $state =~ /present rate:[ ]*([]*) mA/ );
     ($remaining_capacity) = ( $state =~ /remaining capacity:[ ]*([]*) mAh/ );
     ($design_capacity) = ( $info =~ /last full capacity:[ ]*([]*) mAh/ );

     if ($present_rate == 0) {
      print "$battery has an undefined present rate";
     } else {
      if ($charging_state eq "charging") {
       $charging_time = ($design_capacity - $remaining_capacity) / ($present_rate/60);
       $total_charging_time += $charging_time;
       print ($battery, " needs other ", int($charging_time), " minutes to charge");
      } elsif ($charging_state eq "discharging") {
       $discharging_time = $remaining_capacity / ($present_rate/60);
       $total_discharging_time += $discharging_time;
       print ($battery, " has ", int($discharging_time), " minutes of life left");
      }
     }
    }
   }
  }
 }

 if ($total_charging_time) {
  print ("your system needs other ", int($total_charging_time), " minutes to charge");
 }
 if ($total_discharging_time) {
  print ("your system has ", int($total_discharging_time), " minutes of life left");
 }
} else {
 print "your system is not supported (maybe you are not using acpi)";
}

Print | posted on sabato 21 maggio 2005 03:19