#!/usr/bin/python## battstat## Copyright (C) 2006 by Tyler Gates <TGates81@gmail.com># # This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.# # This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.# # You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA.#import os, sys, re# globalsif os.path.isdir("/proc/acpi/battery"): batt_basedir = "/proc/acpi/battery"else: batt_basedir = "/proc/apm/battery"def get_batts(): """ return an array of all available batteries in batt_basedir """ try: return os.listdir(batt_basedir) except Exception, e: print >>sys.stderr.write("Unable to find a battery in '"+batt_basedir+"'") return Nonedef read_lines(file): """ read file contents and return readlines() """ try: f = open(file) string = f.readlines() f.close() return string except Exception, e: print >>sys.stderr.write("Unable to open '"+file+"':\n" +str(e)) return Nonedef get_value(contents, property): """ return value of property from file contents (readlines) """ for c in contents: if property in c: try: return c.split(':')[1].strip() except IndexError, e: print >>sys.stderr.write("Unable to parse file contents: "+str(e)) return None return Nonedef batt_percent(design_capacity, remaining_capacity): """ calculate and return remaining battery percentage as a string """ # strip out units design_capacity = float(re.sub('\D', '', design_capacity)) remaining_capacity = float(re.sub('\D', '', remaining_capacity)) # convert to float and caclulate percent = float((remaining_capacity * 100) / design_capacity) # round to hundredths. 23.3524 || 23.3245 -> 23.35999 || 23.35000 + 0.001 = 23.360 || 23.350 percent = round(percent, 2) + 0.001 percent = str(percent) # remove extra thousandths place from rounding percent = percent[:(len(percent)-1)] return percentdef time_left(remaining_capacity, present_rate): """ calculate and return remaining time in 00:00 hours units """ # strip units remaining_capacity = float(re.sub('\D', '', remaining_capacity)) present_rate = float(re.sub('\D', '', present_rate)) # get decimal time i.e. 1.34 hours decimal_time = remaining_capacity / present_rate # round to hundreths (see batt_percent() for more info) decimal_time = round(decimal_time, 2) + 0.001 decimal_time = str(decimal_time) decimal_time = decimal_time[:(len(decimal_time)-1)] # split to the left and right of the decimal and convert the right (hundredths) to minutes whole = decimal_time.split('.')[0] # pad <num> to 0<num> if len(whole) == 1: whole = '0'+whole hundredths = decimal_time.split('.')[1] # convert hundredths place to minutes minutes = (int(hundredths) * 60) / 100 minutes = str(minutes) if len(minutes) == 1: minutes = '0'+minutes return whole+':'+minutesdef main(battery): batt_dir = os.path.join(batt_basedir, battery) # info data info_file = os.path.join(batt_dir, 'info') info_contents = read_lines(info_file) if not info_contents: sys.exit(1) # state data state_file = os.path.join(batt_dir, 'state') state_contents = read_lines(state_file) if not state_contents: sys.exit(1) charging_state = get_value(state_contents, 'charging state') design_capacity = get_value(info_contents, 'design capacity') remaining_capacity = get_value(state_contents, 'remaining capacity') percent_left = batt_percent(design_capacity, remaining_capacity) present_rate = get_value(state_contents, 'present rate') capacity_low = get_value(info_contents, 'design capacity low') capacity_warning = get_value(info_contents, 'design capacity warning') manufacturer = get_value(info_contents, 'OEM info') model_number = get_value(info_contents, 'model number') battery_type = get_value(info_contents, 'battery type') battery_tech = get_value(info_contents, 'battery technology') if charging_state == 'discharging': # time left to discharge time_remaining = time_left(remaining_capacity, present_rate) elif charging_state == 'charging': # time left to charge # use the difference between total capacity and remaining capacity remaining = int(re.sub('\D', '', remaining_capacity)) design = int(re.sub('\D', '', design_capacity)) net = design - remaining net = str(net) time_remaining = time_left(net, remaining_capacity) else: # nothing to calculate; ACPWR time_remaining = "--:--" # manufacturer, model number and battery technology may not have values; use N/A for screen output if not manufacturer: manufacturer = 'N/A' if not model_number: model_number = 'N/A' if not battery_tech: batter_tech = 'N/A' # output to screen print " << "+battery+" >>" print manufacturer+' - '+model_number+' | '+battery_type+' | '+battery_tech print "Remaining Charge : "+percent_left+" %" print "Time Left : "+time_remaining+' Hrs' print "Charging State : "+charging_state if remaining_capacity == capacity_low: alert = 'LOW!' elif remaining_capacity == capacity_warning: alert = 'WARNING!' else: alert = 'None' print "Charge Alert : "+alertif __name__ == "__main__": batteries = get_batts() if not batteries: sys.exit(1) for battery in batteries: main(battery)