#! /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