Pandbatt
Descripción del contenido de la página
Programa en Forth para mostrar el estado de la batería de una Pandora.
Tras el éxito del programa xbattbar-check-sysfs, el paso obligado era hacer un programa que proporcionara el resto de la información útil de la batería (tiempo estimado de carga o descarga).
Código fuente
Igual que en el caso de xbattbar-check-sysfs, Pandbatt es más largo de lo que podría ser debido a que la palabra slurp-file
de Gforth, que devuelve el contenido de un fichero a partir de su nombre, no funciona con los ficheros virtuales del sistema sysfs; tampoco funciona la palabra clásica de ANS Forth read-file
. Por ello escribí una alternativa, la palabra content
, para leer la primera línea de cada fichero, que en realidad es todo su contenido.
#! /usr/bin/env gforth
\ pandbatt.fs
\ Pandbatt (version A-00-20130822)
\ This program, 'Pandbatt', prints the attributes of the
\ Pandora's battery. It's written in Forth with Gforth.
\ Copyright (C) 2012 Marcos Cruz (programandala.net)
\ 'Pandbatt' 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. See:
\
\ http://gnu.org/licenses/
\ http://gnu.org/licenses/gpl-2.0.html
\ History
\
\ 2012-11-04 First version.
\ 2012-11-05 New: 'time_to_empty_avg' attribute.
\ 2013-08-22 Fix: stack notation in 'sconstant'.
\ 2013-08-22 Change: stack notation of strings.
warnings off
: sconstant ( ca1 len1 "name" -- )
create s,
does> ( -- a2 u1 ) ( dfa ) count
;
s" /sys/class/power_supply/bq27500-0/" sconstant sys_dir
sys_dir s" status" s+ sconstant status_file
sys_dir s" capacity" s+ sconstant capacity_file
sys_dir s" time_to_full_now" s+ sconstant time_to_full_file
sys_dir s" time_to_empty_now" s+ sconstant time_to_empty_file
sys_dir s" time_to_empty_avg" s+ sconstant time_to_empty_avg_file
variable charging?
variable full?
false [if] \ use Gforth's 'slurp-file'
\ 'slurp-file' does not work with files under /sys/,
\ it causes the error "could not read whole file".
' slurp-file alias content
[else] \ alternative to 'slurp-file'
variable fid \ file id
256 constant max_line
create line_buffer max_line 2 + allot
\ When the battery status changes (beetwen charging and
\ discharging or vice versa), the reading of the time files
\ fails during some seconds, until the OS updates them. This
\ causes a fatal error because its content is supposed to be a
\ number and EVALUATed. In order to detect this error and print
\ a question mark instead, a flag is used:
variable failed? \ flag for file reading
: open_file ( ca len -- )
\ ca len = file name
r/o open-file throw fid !
;
: close_file ( -- )
fid @ close-file throw
;
: read_file ( -- ca len )
\ Get the content of the open file (only its first line).
\ ca len = file content (first line)
line_buffer dup max_line fid @ read-line
failed? ! and
;
: content ( ca1 len1 -- ca2 len2 )
\ Get file content; an alternative to 'slurp-file'.
\ ca1 len1 = file name
\ ca2 len2 = file content (first line)
open_file read_file close_file
;
[then]
\ Printing of attributes by type
: ((.attribute)) ( ca1 len1 ca2 len2 -- ca3 len3 )
\ Print an attribute label and return the attribute.
\ ca1 len1 = file name
\ ca2 len2 = attribute label
\ ca3 len3 = file content
type ." : " content
;
: (.attribute) ( ca1 len1 ca2 len2 -- )
\ Print a text attribute.
\ ca1 len1 = file name
\ ca2 len2 = attribute label
((.attribute)) type
;
: .attribute ( ca1 len1 ca2 len2 -- )
\ Print a text attribute and finish the line.
\ ca1 len1 = file name
\ ca2 len2 = attribute label
(.attribute) cr
;
: .00 ( n -- )
\ Print a number with two digits.
s>d <# # # #> type
;
: seconds>hours ( n1 -- n2 )
\ Convert seconds to hours.
3600 /
;
: seconds>minutes ( n1 -- n2 )
\ Convert seconds to the minutes remaining after converting
\ them to hours.
3600 mod 60 /
;
: .hh:mm ( n -- )
\ Print seconds in the format "hh:mm".
dup seconds>hours .00 ." :" seconds>minutes .00
;
: .time_attribute ( ca1 len1 ca2 len2 -- )
\ Print a time attribute (stored in seconds).
\ ca1 len1 = file name
\ ca2 len2 = attribute label
((.attribute)) failed? @
if 2drop ." ?"
else evaluate .hh:mm
then cr
;
: .percent_attribute ( ca1 len1 ca2 len2 -- )
\ Print a percent attribute.
\ ca1 len1 = file name
\ ca2 len2 = attribute label
(.attribute) ." %" cr
;
\ Printing of attributes by name
: .capacity ( -- )
\ Print the capacity of the battery.
capacity_file s" Capacity" .percent_attribute
;
: flags! ( ca len -- )
\ Update the status flags with the content of the status
\ attribute.
\ ca len = content of the status attribute
2dup s" Full" compare 0= full? !
s" Discharging" compare charging? !
;
: .status ( -- )
\ Print the status of the battery.
status_file s" Status" ((.attribute))
2dup flags! type cr
;
: (.time_to_full) ( -- )
\ Print the time to full.
time_to_full_file s" Time to full" .time_attribute
;
: .time_to_full ( -- )
\ Print the time to full if needed.
full? @ 0= if (.time_to_full) then
;
: .time_to_empty ( -- )
\ Print the time to empty.
time_to_empty_file s" Time to empty" .time_attribute
;
: .time_to_empty_avg ( -- )
\ Print the average time to empty.
time_to_empty_avg_file s" Time to empty (average)" .time_attribute
;
: .time ( -- )
\ Print the time to full or the time to empty, depending on
\ the charging status.
charging? @
if .time_to_full
else .time_to_empty .time_to_empty_avg
then
;
: .battery ( -- )
\ Print all battery info.
cr .status .capacity .time
;
.battery bye