Re: Issue with notebook (maybe the battery?)
- To: debian-user@lists.debian.org
- Subject: Re: Issue with notebook (maybe the battery?)
- From: David Wright <deblis@lionunicorn.co.uk>
- Date: Fri, 2 Jun 2017 14:29:48 -0500
- Message-id: <[🔎] 20170602192948.GB18650@alum>
- Reply-to: debian-user@lists.debian.org
- In-reply-to: <e63d35d8-5658-9f77-fec2-76df3213b18d@gmx.net>
- References: <20170326114948.0bde5b38@jresid.jretrading.com> <cbb9a6ca-c850-eb75-1b96-2a8d7debd802@gmx.net> <20170327030809.GA18231@alum> <6459afd0-944e-3af6-e244-253b0f0a2dd6@gmx.net> <20170328192453.GA13687@alum> <3325d28b-85e6-fee7-1ed8-145e5f89ea21@gmx.net> <20170525002247.GC16933@alum> <1909fdac-fbe3-1c7a-893c-77da105efd5b@gmx.net> <20170525012356.GA18124@alum> <e63d35d8-5658-9f77-fec2-76df3213b18d@gmx.net>
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
Reply to: