[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Issue with notebook (maybe the battery?)



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: