Difference between revisions of "Code/tp power monitor.py"
Matt garman (Talk | contribs) |
m |
||
Line 1: | Line 1: | ||
− | #!/usr/bin/python | + | <pre>#!/usr/bin/python |
# COPYRIGHT (C) 2006 Matthew Garman | # COPYRIGHT (C) 2006 Matthew Garman | ||
Line 323: | Line 323: | ||
if __name__ == '__main__': | if __name__ == '__main__': | ||
main() | main() | ||
+ | </pre> |
Revision as of 07:21, 9 September 2006
#!/usr/bin/python # COPYRIGHT (C) 2006 Matthew Garman # matthew (dot) garman (at) gmail (dot) com # License: MIT <http://www.opensource.org/licenses/mit-license.php> import sys, time, getopt, os, re class tpPowerMonitorDataSource: # The name of the file to parse for needed data (data_source_file) OR # the name of a command whose output will be read as a file # (os.popen(shell_command)). # # Typically, data_source_file will be something from /proc (or # possibly /sys), and shell_command will be a utility+arguments such # as "iwconfig eth1 power". # # Note that you should set EITHER data_source_file OR shell_command, # but not both. data_source_file = None shell_command = None # The line number of the data file containing our data OR the string # that marks the beginning of the line in which we're interested # (startswith_string) OR a regular expression to key the data for # which we're looking (regexp_pattern). line_number = None startswith_string = None regexp_pattern = None # The string that delimits the line containing our data. This will be # used as the parameter to split(). Note that you can leave this as # None to split on whitespace. split_string = None # A mapping of data names to indices in the split string. name_index_map = dict() def __init__(self, file, cmd, line, swstr, pat, splstr, map): self.data_source_file = file self.shell_command = cmd self.line_number = line self.startswith_string = swstr self.regexp_pattern = pat self.split_string = splstr self.name_index_map = map def printMembers(self): print "\t" + 'self.data_source_file = ' + str(self.data_source_file) print "\t" + 'self.shell_command = ' + str(self.shell_command) print "\t" + 'self.line_number = ' + str(self.line_number) print "\t" + 'self.startswith_string = ' + str(self.startswith_string) print "\t" + 'self.regexp_pattern = ' + str(self.regexp_pattern) print "\t" + 'self.split_string = ' + str(self.split_string) print "\t" + 'self.name_index_map = ' + str(self.name_index_map) def readData(self, d): # open the data source file or run the command that will produce # the data file = None if self.data_source_file: file = open(self.data_source_file, 'r') elif self.shell_command: file = os.popen(self.shell_command) else: print 'error: no data source defined' self.printMembers() # read the contents of the file into a list and close the file lines = None if file: lines = file.readlines() file.close() else: print 'error: data file not opened' self.printMembers() # now get the line in the file with our data line = None if lines: if None != self.line_number: line = lines[self.line_number] elif self.startswith_string: for l in lines: if l.startswith(self.startswith_string): line = l break elif self.regexp_pattern: for l in lines: if re.compile(self.regexp_pattern).match(l): line = l break else: print 'error: no lines in data file' self.printMembers() # now get the data we want from the line itself if line: fields = line.split(self.split_string) for key in self.name_index_map.keys(): d[key] = fields[self.name_index_map[key]].strip() else: print 'error: could not find line with data in file' self.printMembers() # END --- class tpPowerMonitorDataSource tp_data_sources = [ tpPowerMonitorDataSource( '/proc/cpuinfo', # data file None, # shell command None, # line index 'cpu MHz', # startswith() string None, # regexp pattern ':', # split string {'proc_cpuinfo_cpu_mhz': 1} # name-to-index map ), # http://thinkwiki.org/wiki/Ipw2200#Power_Management tpPowerMonitorDataSource( None, # data file '/sbin/iwpriv eth1 get_power', # shell command 0, # line index None, # startswith() string None, # regexp pattern ':', # split string {'iwpriv_get_power': 2} # name-to-index map ), # http://forums.gentoo.org/viewtopic-t-447841.html # see post from ruben on Wed Mar 29, 2006 4:09 am tpPowerMonitorDataSource( None, '/usr/bin/sudo /sbin/hdparm -C /dev/sda', None, ' drive state is', None, ':', {'hard_drive_power_state': 1} ), # http://thinkwiki.org/wiki/Thermal_sensors tpPowerMonitorDataSource( '/proc/acpi/ibm/thermal', None, 0, None, None, None, {'ibm_thermal_cpu': 1, 'ibm_thermal_hdaps': 2, 'ibm_thermal_pmcia': 3, 'ibm_thermal_gpu': 4, 'ibm_thermal_batt_fl': 5, 'ibm_thermal_batt_br': 7 } ), # http://mailman.linux-thinkpad.org/pipermail/linux-thinkpad/2006-July/034738.html tpPowerMonitorDataSource( '/proc/acpi/processor/CPU/power', None, None, 'bus master activity', None, ':', {'bus_master_activity': 1} ), tpPowerMonitorDataSource( '/proc/acpi/battery/BAT0/state', None, None, 'present rate:', None, None, {'battery0_state_present_rate': 2} ), tpPowerMonitorDataSource( None, '/usr/bin/sudo /usr/sbin/radeontool dac', 0, None, None, None, {'radeontool_dac_ext_vga': -1} ), tpPowerMonitorDataSource( None, '/usr/bin/sudo /usr/sbin/radeontool light', 0, None, None, None, {'radeontool_light_lcd': -1} ), # http://forums.gentoo.org/viewtopic-t-343029-highlight-rovclock.html tpPowerMonitorDataSource( None, '/usr/bin/sudo /usr/sbin/rovclock -i', None, 'Core: ', None, None, {'rovclock_gpu_clock': 1, 'rovclock_mem_clock': 4 } ), tpPowerMonitorDataSource( None, '/sbin/iwconfig eth1', None, None, '.*Power Management.*', ':', {'wireless_power_mgmt_state': 1} ), tpPowerMonitorDataSource( '/proc/loadavg', None, 0, None, None, None, {'proc_loadavg_1min': 0, 'proc_loadavg_5min': 1, 'proc_loadavg_15min': 2 } ), ] log_data = list() poll_freq_hz = 1 run_time_sec = 60*60 logfile = None def collectPowerData(): global run_time_sec global poll_freq_hz global log_data global logfile global tp_data_sources log = None if logfile: log = open(logfile, 'w') log.write("time, data\n") end_t = time.time()+run_time_sec while time.time() < end_t: datum = dict() for dsrc in tp_data_sources: dsrc.readData(datum) log_data.append(datum) if log: log.write(str(time.time()) + ', ' + str(datum) + "\n") time.sleep(1.0/float(poll_freq_hz)) if log: log.close() def createStats(): global log_data global logfile log = None if logfile: log = open(logfile, 'a') if log: log.close() def usage(): print 'Usage: ' + sys.argv[0] + \ '[-h] [-f freq_hz] [-t time_min] [-l logfile]' print "\t-h Display this help" print "\t-f freq_hz The polling frequency in Hertz, default=" \ + str(poll_freq_hz) print "\t-t time_min Total poll time in minutes, default=" \ + str(run_time_sec/60) print "\t-l logfile Write poll data to indicated log file" def main(): global poll_freq_hz global run_time_sec global logfile # parse options # see: http://docs.python.org/lib/module-getopt.html try: opts, args = getopt.getopt(sys.argv[1:], "hf:t:l:") except getopt.GetoptError: usage() sys.exit(2) for o, a in opts: if '-h' == o: usage() sys.exit() if '-f' == o: poll_freq_hz = int(a) if '-t' == o: run_time_sec = int(a)*60 if '-l' == o: logfile = a # do stuff print 'running for ' + str(run_time_sec/60) + ' minutes' print 'poll rate: ' + str(poll_freq_hz) + ' Hz' print 'logfile: ' + str(logfile) collectPowerData() print '...done!' print 'Data points collected: ' + str(len(log_data)) sum = 0 for d in log_data: sum += int(d['battery0_state_present_rate']) avg = float(sum) / float(len(log_data)) print 'Average power draw: ' + str(avg) if logfile: log = open(logfile, 'a') if log: log.write('Average power draw: ' + str(avg)) log.close() if __name__ == '__main__': main()