On Sat 27 May 2017 at 21:55:06 (-0300), Daniel Bareiro wrote: > Hi, David. > > On 24/05/17 22:23, David Wright wrote: > > >> When you talk about "the numbers", do you mean to see by the console the > >> values that are obtained for both batteries (voltage, for example) to > >> make a comparison? > > > Yes, the bash function I use is: > > > > battery () > > { > > local BATTERYFILE="/sys/class/power_supply/BAT0/uevent"; > > [ ! -r $BATTERYFILE ] && printf '%s\n' "$BATTERYFILE not found!" && > > return 1; > > date +%Y-%m-%d-%H-%M-%S; > > cat $BATTERYFILE; > > local FILEBATNOW="/sys/class/power_supply/BAT0/charge_now"; > > local FILEBATPREV="/sys/class/power_supply/BAT0/charge_full"; > > local CHARGE=$(( 100 * $(< $FILEBATNOW) / $(< $FILEBATPREV) )); > > [ $CHARGE -lt 100 ] && printf '%s\n' "Charge: $CHARGE%" > > } > > Interesting... thanks for sharing :-) > > I had to modify it because in my case I don't have "BAT0/charge_full" > and "BAT0/charge_now". I have "BAT0/energy_now" and "BAT0/energy_full". > Maybe you're using Stretch or a Backports kernel?
I get the same filenames on my systems with wheezy, jessie, and the latter using a backported 4.9 kernel. But I've never investigated where these decisions are made. Similarly it's a mystery to me why wheezy gives one laptop two sound controls, whereas jessie gives it five. > > (I run a slightly more sophisticated version that also > > reads the CPU temperature, has error trapping, and changes > > the root window colour according to battery state and, > > if frying, temperature.) > > It would be interesting to see it :-) Sure. Feel free to modify it to your taste. The laptop I wrote it for has one critical temperature point (99), hence the two headroom values which are arbitrary. The first would be reached at such times as playing videos, so it warned me in case it was lying on a soft surface, which interferes with its ventilation. This laptop, which is older, appears to be more sophisticated, having four trip point temperatures, and also a battery temperature. But it doesn't overheat so I've never bothered to modify the code. The charge colours are more useful most of the time, especially when the batteries are as old as these are. Cheers, David.
#!/usr/bin/env python3 ## ## background-changer.py for python 3.4 ## ## Changes the X background according to various parameters. ## In this case, it's the thermal state and battery status according ## to the list below. Note that running with -? tests whether the ## colours are specified precisely (including correct capitalisation). ## ## Started from ~/.xsession-1-$HOST for appropriate machines and ## run in the background with &. ## ## Converted from a shell script because it seems to need error processing ## to work with 3.x kernels: /sys/class/power_supply/BAT0/current_now ## can disappear immediately after its existence has just been tested. ## ## Written by David Wright, Copyright © 2013--2015 David Wright VERSION = '2015 May 08 10:00' COLURGENTTHETA = 'brown' # Temperature emergency as very high COLHIGHTHETA = 'red' # Temperature warning as quite high COLACOK = 'green' # AC and OK; if charging, then only a trickle COLLOPUMP = 'DarkTurquoise' # Charging a little COLMEDPUMP = 'DarkGreen' # Charging COLHIPUMP = 'blue' # Charging a lot COLONBATTERY = 'yellow' # Plenty of charge, but running on battery power COLLOWBATTERY = 'DeepPink' # Battery getting low COLDEADBATTERY = 'DarkViolet' # Battery almost flat REPETITION = 5 HEADROOMERR = 15 # this is bad and shouldn't ever be seen HEADROOMWARN = 20 # this is normal when compiling kernel or playing video HImA = 1000 # Charging a lot MEDmA = 400 # Charging LOmA = 150 # Charging a little LOWBATT = 25 # Battery getting low FLATBATT = 10 # Battery almost flat ## File locations and values to test: THETAMON = '.theta-monitor' BATTMON = '.charge-state' FILETHETA = '/sys/class/thermal/thermal_zone0/temp' FILETRIP = '/sys/class/thermal/thermal_zone0/trip_point_0_temp' MINVALIDTHETA = 10000 # make sure we're reading m°, not ° FILEBATNOW = '/sys/class/power_supply/BAT0/charge_now' FILEBATPREV = '/sys/class/power_supply/BAT0/charge_full' FILEBATCURR = '/sys/class/power_supply/BAT0/current_now' FILEBATSTAT = '/sys/class/power_supply/BAT0/status' STRMORE = 'Charging' STRLESS = 'Discharging' COLOURS = 'xcolors' PAINT = 'xsetroot' RGBFILE = '/etc/X11/rgb.txt' FONT = '12x24' SIZE = '500' GETOPT = 'd?' import getopt import os import shutil # skip testing for which when python3.2 is history import subprocess import sys import tempfile import time # main program opts = {} try: optlist, args = getopt.getopt(sys.argv[1:], GETOPT) for (o, d) in optlist: opts[o] = d except: opts['-?'] = None progname = os.path.basename(sys.argv[0]) debug = '-d' in opts if '-?' in opts or len(args): colours = open(RGBFILE).readlines() colourdict = {} for j in colours: if j[0] == '!': continue k = j.split(None, 3) colourdict[k[3][:-1]] = k colourset = [] for j in [COLURGENTTHETA, COLHIGHTHETA, COLACOK, COLLOPUMP, COLMEDPUMP, COLHIPUMP, COLONBATTERY, COLLOWBATTERY, COLDEADBATTERY]: colourset.append(' '.join(colourdict[j])) if debug: print(colourset, file=sys.stderr) if 'which' in dir(shutil) and not shutil.which(COLOURS): print('Program {} is missing!'.format(COLOURS), file=sys.stderr) sys.exit(1) rgbfile = tempfile.NamedTemporaryFile(mode='w') rgbfile.writelines(colourset) rgbfile.flush() subprocess.check_call([ 'xcolors', '-rgbfile', rgbfile.name, '-xrm', '*Label.Font:{}'.format(FONT), '-xrm', '*panes.Width:{}'.format(SIZE), '-xrm', 'Xcolors*{}*Label:EmergencyTheta'.format(COLURGENTTHETA), '-xrm', 'Xcolors*{}*Label:WarningTheta'.format(COLHIGHTHETA), '-xrm', 'Xcolors*{}*Label:AC/ok'.format(COLACOK), '-xrm', 'Xcolors*{}*Label:LoCharging'.format(COLLOPUMP), '-xrm', 'Xcolors*{}*Label:MedCharging'.format(COLMEDPUMP), '-xrm', 'Xcolors*{}*Label:HiCharging'.format(COLHIPUMP), '-xrm', 'Xcolors*{}*Label:onBattery'.format(COLONBATTERY), '-xrm', 'Xcolors*{}*Label:LowBattery'.format(COLLOWBATTERY), '-xrm', 'Xcolors*{}*Label:DeadBattery'.format(COLDEADBATTERY), '-xrm', 'Xcolors*sample*String:. Colours correspond to the states shown. Press q in the coloured area to quit']) sys.exit(0) if os.environ['DISPLAY'] != ':0': print('Running {} on DISPLAY "{}" may have odd consequences'.format(progname, os.environ['DISPLAY']), file=sys.stderr) if 'which' in dir(shutil) and not shutil.which(PAINT): print('Program {} is missing!'.format(PAINT), file=sys.stderr) sys.exit(1) state = 'bisque2' if debug: print('Starting with {}'.format(state), file=sys.stderr) subprocess.check_call([PAINT, '-solid', state]) if debug: print('Started with {}'.format(state), file=sys.stderr) THETAMON = os.path.join(os.environ['HOME'], THETAMON) BATTMON = os.path.join(os.environ['HOME'], BATTMON) fd = open(BATTMON, mode='w') fd.writelines('') fd.close() REP = 0 STATE = COLURGENTTHETA # start in worst possible state while 1: if debug: if REP: print('Restarting loop', file=sys.stderr) else: print('First time through loop', file=sys.stderr) subprocess.check_call([PAINT, '-solid', STATE]) # don't wait the first time through time.sleep(REP) REP = REPETITION # Temperature if debug: print('Temperature', file=sys.stderr) STATE = COLURGENTTHETA # indicates thermal emergency try: THETA = open(FILETHETA).readline()[:-1] if debug: print('Got temperature {}'.format(THETA), file=sys.stderr) fmt = '{} %b%d %H:%M\n'.format(THETA) fd = open(THETAMON, mode='a') fd.writelines(time.strftime(fmt)) fd.close() if debug: print('Written tmperature', file=sys.stderr) except: pass try: THETA = open(FILETRIP).readline()[:-1] if debug: print('Got trip {}'.format(THETA), file=sys.stderr) if THETA <= MINVALIDTHETA: continue THDIFF = (THETRIP - THETA) / 1000 if THDIFF <= HEADROOMERR: continue STATE = COLHIGHTHETA # indicates thermal warning if THDIFF <= HEADROOMWARN: continue except: pass # Battery STATE = COLDEADBATTERY # indicates problem reading battery if debug: print('Battery', file=sys.stderr) try: BATTSTATUS = open(FILEBATSTAT).readline()[:-1] RATE = open(FILEBATCURR).readline()[:-1] BATNOW = open(FILEBATNOW).readline()[:-1] BATPREV = open(FILEBATPREV).readline()[:-1] if debug: print('Got battery {}{}{}{}'.format( repr(BATTSTATUS), repr(RATE), repr(BATNOW), repr(BATPREV)) , file=sys.stderr) fmt = '{} {} {}%% %b%d %H:%M\n'.format( BATTSTATUS[0], int(int(RATE)/100000), min(100, int(100*int(BATNOW)/int(BATPREV)))) fd = open(BATTMON, mode='a') fd.writelines(time.strftime(fmt)) fd.close() if BATTSTATUS == STRMORE: RATE = int(RATE) / 1000 STATE = COLHIPUMP if RATE > HImA: continue STATE = COLMEDPUMP if RATE > MEDmA: continue STATE = COLLOPUMP if RATE > LOmA: continue STATE = COLACOK elif BATTSTATUS == STRLESS: PROP = 100 * int(BATNOW) / int(BATPREV) STATE = COLONBATTERY if PROP > LOWBATT: continue STATE = COLLOWBATTERY if PROP > FLATBATT: continue STATE = COLDEADBATTERY else: STATE = COLACOK # even if status is unknown except: pass