diff options
Diffstat (limited to 'thinkwatt')
-rwxr-xr-x | thinkwatt | 304 |
1 files changed, 0 insertions, 304 deletions
diff --git a/thinkwatt b/thinkwatt deleted file mode 100755 index aa408b9..0000000 --- a/thinkwatt +++ /dev/null @@ -1,304 +0,0 @@ -#!/bin/bash -# -# thinkwatt: -# record power consumption, calculate average and create a gnuplot graph -# -# TO-DO: -# * add more options (e.g. for specifying a different gnuplot title or png output) -# * allow time input in minutes and hours - -# utilities {{{ -message() { - cat << EOF -usage: thinkwatt -r (seconds) (-q) (-o file) - thinkwatt [ -p | -a ] (-q) file - -options: - -r, --record record power consumption and optionally create a graph from the gathered data - -p, --plot create a plot image from a specified data file - -a, --average calculate the average power consumption from a specified data file - -q, --quiet makes thinkwatt less chatty - -o, --output the output file. can be prepended by a path. - -h, --help show this help text - -examples: - thinkwatt -r (will record to a temp file until cancelled) - thinkwatt -r 300 -o /foo/bar/consumption.dat (will record for 5 minutes to the specified file) - thinkwatt -p /foo/bar/consumption.dat (will create a graph from the specified file) -EOF - exit 1 -} - -errorout() { echo "error: $*" >&2; exit 1; } - -check_ac() { - [[ "$quiet" ]] && return 0 - [[ $(cat /sys/class/power_supply/*/online) = 0 ]] || echo 'it seems your AC adapter is plugged in' -} -check_datafile() { - [[ -f "$@" ]] || errorout "$@ does not exist" - local valid_file=$(file "$@" | grep -s "^$@: ASCII text$") - [[ "$valid_file" ]] || errorout "$@ is not a valid data file" - local valid_data=$(cat "$@" | grep -s '^[0-9]*[,.]\?.*[0-9]$') - [[ "$valid_data" ]] || errorout "$@ does not contain valid data" -} -countdown() { - [[ "$quiet" ]] || echo "ctrl+c to plot/exit" - if [[ "$seconds" =~ ^[0-9]+$ ]];then - # count down - secs="$seconds" - while [ "$secs" -gt 0 ];do - [[ "$die" == yes ]] && return 0 - sleep 1 & - cat "$powerfile" >> "$tmpfile1" - printf "\rrecording (%02d/$seconds)" $((secs)) - secs=$(( $secs - 1 )) - wait - done - else - # count up - secs=1 - while true;do - [[ "$die" == yes ]] && return 0 - sleep 1 & - cat "$powerfile" >> "$tmpfile1" - printf "\rrecording ($secs)" - secs=$(( $secs + 1 )) - wait - done - fi - echo -} -# if we abort the recording process with ctrl+c this will give the option to plot the already recorded data -trap ctrl_c INT -function ctrl_c() { - echo - read -p "plot data? y/n " - [[ "$REPLY" = "y" ]] && die=yes || exit 0 -} -# }}} - -# default output dir and png file {{{ -# use $TDIR to have thinkwatt save files in a different directory. -# thinkwatt will save two files: -# 1) a .plt file (containing plot instructions) in case you want to reuse/modify it -# 2) a .png file (the plot graphic) -TDIR="/tmp/thinkwatt" -PLOTFILE="$TDIR"/$$.plt -# }}} - -# record {{{ -record() { - - local seconds="$1" - - #[[ "$seconds" =~ ^[0-9]+$ ]] || errorout 'please specify the time in seconds" - [[ -d "$output" ]] && errorout "$output is a directory" - [[ -d "$TDIR" ]] || mkdir -p "$TDIR" 2>/dev/null || errorout "could not create $TDIR" - - if [[ -f "$output" ]];then - read -p "overwrite $output? y/n " - [[ "$REPLY" = "y" ]] || exit 0 - elif [[ -e "$output" ]];then - errorout "$output exists and can/should not be written to" - fi - - local tmpfile1=/tmp/$$.dat - local tmpfile="$TDIR"/$$.dat - - if [[ "$output" ]];then - local dir=$(dirname "$output") - local file=$(basename "$output") - [[ -d "$dir" ]] || mkdir -p "$dir" - [[ -w "$dir" ]] || errorout "you don't have permissions to write to $dir" - - outputfile="$output" - [[ "$dir" ]] && TDIR="$dir" - PNGFILE="$TDIR"/$(basename "$file" .dat).png - #PLOTFILE="$TDIR"/$(basename "$output" .dat).plt - else - [[ -w "$(pwd)" ]] || errorout "you don't have permissions to write to $(pwd)" - local file=$(basename "$tmpfile") - outputfile="$tmpfile" - local istemp=true - fi - - SMAPI=$(lsmod | grep -s tp_smapi) - if [[ "$SMAPI" ]];then - local powerfile=/sys/devices/platform/smapi/BAT0/power_now - else - echo "for more accurate results with thinkpads use tp_smapi" - local powerfile=/sys/class/power_supply/BAT0/power_now - fi - - touch "$tmpfile1" || errorout "could not create $tmpfile1" - trap "rm $tmpfile1" EXIT - - # do the actual recording included in countdown() - countdown - - # file formatting - if [[ "$SMAPI" ]];then - # we strip the leading "-" from the data file - sed -i 's/-//g' "$tmpfile1" - else - # strip the trailing last 3 characters - sed -i 's/.\{3\}$//' "$tmpfile1" - fi - # and divide by 1000 to convert from mW to W - cat "$tmpfile1" | awk '{print $1/1000}' > "$tmpfile" - - [[ "$output" ]] && mv "$tmpfile" "$output" - - [[ "$quiet" ]] || echo average was $(average "$outputfile") W - - plot "$outputfile" - -} -# }}} - -# calculate average {{{ -average() { - - [[ "$@" ]] || errorout 'please specify a file to read from.' - [[ -f "$@" ]] || errorout 'file not found.' - check_datafile "$@" - - awk 'BEGIN{s=0;}{s+=($1);}END{print s/NR;}' "$@" - -} -# }}} - -# make the plot file {{{ -makeplotfile() { - - cat << EOF -# gnuplot file -# created by thinkwatt -# $DATE - -set title "$TITLE" -set xlabel "$XLABEL" -set ylabel "$YLABEL" -set terminal $TERMINAL -set output "$PNGFILE" -EOF - [[ "$YRANGE" ]] && echo "set yrange $YRANGE" - [[ "$XRANGE" ]] && echo "set yrange $YRANGE" - [[ "$GRID" == yes ]] && echo "set grid" - [[ "$YTICS" ]] && echo "set ytics $YTICS" - [[ "$MYTICS" ]] && echo "set mytics $MYTICS" - [[ "$XTICS" ]] && echo "set xtics $XTICS" - [[ "$MXTICS" ]] && echo "set mxtics $MXTICS" - [[ "$GRIDSET" ]] && echo "set grid $GRIDSET" - - echo - if [[ "$TITLE1" ]];then - echo "plot \"$datafile\" using (\$1) with lines title \"$TITLE1\" lt 2, \\" - else - echo "plot \"$datafile\" using (\$1) with lines lt 2, \\" - fi - - if [[ "$TITLE2" ]];then - if [[ "$avg" ]];then - echo "\"$datafile\" using (\$1) smooth bezier title \"$TITLE2\" lt 1, \\" - else - echo "\"$datafile\" using (\$1) smooth bezier title \"$TITLE2\" lt 1" - fi - else - if [[ "$avg" ]];then - echo "\"$datafile\" using (\$1) smooth bezier lt 1, \\" - else - echo "\"$datafile\" using (\$1) smooth bezier lt 1" - fi - fi - - [[ "$avg" ]] && echo "$avg title \"$file (average, $avg W)\"" - -} -# }}} - -# do the plotting -plot() { - - # check if we have gnuplot and $TDIR is present - have_gnuplot=$(find $(sed 's/:/ /g' <<<$PATH) 2>/dev/null | grep -is gnuplot) - [[ "$have_gnuplot" ]] || errorout 'please install gnuplot first' - [[ -d "$TDIR" ]] || mkdir -p "$TDIR" || errorout "could not create $TDIR" - - # is input file a valid data file? - local datafile="$@" - check_datafile "$datafile" - [[ "$datafile" ]] || errorout 'please specify a file to read from.' - [[ -f "$datafile" ]] || errorout 'filplotfilee not found.' - - # define some of the variables for the plot file - DATE=$(date +%Y-%m-%d,\ %T) - TITLE="power consumption of my laptop, created by thinkwatt on $DATE" - XLABEL="sec (seconds)" - YLABEL="W (Watt)" - TERMINAL="png" - GRID=yes - #TITLE1="your custom title for line1" - #TITLE2="your custom title for line2" - #TITLE3="your custom title for line3" - # some more options for gnuplot, enable and modify them here if you like - MYTICS=2 - MXTICS=2 - #YTICS=1 - #XTICS=(better leave this alone) - GRIDSET="mytics" - #YRANGE="[4000:16000]" - #XRANGE="[0:2000]" - # moar - local avg=$(average "$datafile" | cut -c1-4) - local dir=$(dirname "$datafile") - local file=$(basename "$datafile") - [[ -z "$TITLE1" ]] && local TITLE1="$file (actual)" - [[ -z "$TITLE2" ]] && local TITLE2="$file (trend)" - [[ "$PNGFILE" ]] || PNGFILE=$(basename "$datafile" .dat).png - - # now we can plot - makeplotfile > "$PLOTFILE" || errorout "could not write the plotfile (permission issue?)" - gnuplot "$PLOTFILE" || errorout "could now write graph (permission issue?)" - - [[ "$quiet" ]] || echo "graph saved as $PNGFILE" - -} - -# parse options {{{ -parse_options() { - - [[ -z "$1" ]] && message - - while [[ -n "$1" ]];do - case "$1" in - -h|--help) message ;; - -q|--quiet) quiet=true ;; - -o|--output) output="$2" ;; - -r|--record) mode='record' ;; - -p|--plot) mode='plot' ;; - -a|--average) mode='average' ;; - *) args+=( "$1" ) ;; - esac - shift - done -} -# }}} - -# main {{{ -main() { - - case "$mode" in - record) record "${args[@]}" ;; - average) average "${args[@]}" ;; - plot) plot "${args[@]}" ;; - *) errorout 'invalid mode. use -r, -p or -a.' ;; - esac - -} -# }}} - -parse_options "$@" -check_ac -main |