[Galaxy Ace S5830 General] ino-xda:
[script] reliable interface stats

pro: reliable, works on any Linux; low battery consumption; runs only when necessary

contra: no GUI

prerequisites: script manager able to trigger on network changes

root is not needed, because the script uses the readable-for-all /proc/net/dev interface to gather statistics.

My problem was that I could not find any app that would give me the megabytes sent from/to the device. They would either ignore GPRS, WiFi or count from reboot to reboot, display stupid ads or cost even money without delivering. I'm on a data flatrate with throttling from 200MB up, and I only want to know how much I already "spent".

The following script should run on network changes, but it can be run at any time. You get more data entries in the log files for the various active interfaces when running it more often.

EDIT: it turns out the "network change" event works perfectly for interface wlan0, but not for pdp0, which happens to be the GPRS/G2/G3/G4 packet interface. Maybe "Tasker" does better than "Script Manager" with this, try and find out. What will always work is manual mode: after using an interface, run the script. This will enter the numbers from any interface that traffic into the respective log.

The script is run with zero or one argument. If given, it can be the name of an interface or the string "all" to get just a readout of the current counters of all interfaces that had traffic without logging anything.

The output is lines with bytes, data packets, errornous and dropped packets for "rx" (received) and "tx" (transmitted) for all or the selected interfaces. Without arguments all active interfaces are logged to separate files in /sdcard/. If you want to change this directory or the names or the date format, well, it should be easy to adapt.

Note that this first script does only data gathering as to the byte counts and it must run on network events. See below for the script(s) that do evaluation according to date to find out how much to go until throttling.

#!/system/bin/sh
want_if="${1:-*}"
all=""
case "-${want_if}" in
-all)
want_if="*"; all=all;
;;
esac
log_prefix="/mnt/sdcard/interface-stats"
now="$(date '+%d.%m.%y-%H:%M:%S')"
# rx: bytes packets errs drop fifo frame compressed multicast
# tx: bytes packets errs drop fifo colls carrier compressed
# lo: 4944 74 0 0 0 0 0 0 4944 74 0 0 0 0 0 0
# wlan0: 42447725 41554 302 0 0 0 0 0 3280981 33753 0 0 0 0 0 0
while read intf rb rp re rd x x x x tb tp te td rest
do
case "-${intf}" in
-${want_if:-*}:)
case "${rb}--${tb}" in
0--0) continue;;
esac
stats="rx: $rb $rp $re $rd tx: $tb $tp $te $td"
intf_="${intf%:}"
echo "${intf} ${stats}"
[ -z "${all}" ] &&
echo "${now} ${stats}" >> "${log_prefix}-${intf_}.txt"
;;
esac
done < /proc/net/dev
exit 0

Here's the script to output the megabytes. It gets zero, one or two arguments, the first being a date pattern that needs to match the dates in the log file, the second the name of said logg.

An optional third argument, if given, gives debug output. Use only if the number doesn't look plausible.

It doesn't need any special privileges and can be run anytime.

If less than one megabyte has been hit so far, then the output is the number of bytes. Due to limitations of "awk" there can still be decimals in the output!

# /home/ino/interface-stats.sh _date: 20120225-2103_
# vim: set filetype=sh ts=4:
# -*- mode: sh; -*-
#
# <url:man:1 awk>

# sample:
#
# 25.02.12-02:28:28 rx: 182909647 374371 462 0 tx: 681742703 542899 0 0
# 25.02.12-12:15:00 rx: 3 374464 494 0 tx: 5 542974 0 0
#
# at around noon the device was rebooted, so the stats start at low
# values.
#
# algorithm:
#
# initialize old-accumulator and offset to zero.
#
# since received and transmitted bytes are accumulated by the kernel,
# the script has to just store the sum of the received and transmitted
# bytes into an accumulator, unless the current value is less than the
# running count. this happens after a reboot. so store this first low
# value into $offset, store the old accumulator and keep the running game
# until either the next reboot or EOF. now
# accumulator = old-accumulator + accumulator - offset.

awk_prog='
BEGIN {
debug = debug > 0
accu=0
accu_old=0
offset=0
accu_sum=0
# megabytes
mb_scaler=1024*1024
# field definitions
rx_bytes=3
rx_packets=4
rx_errors=5
rx_dropped=6
tx_bytes=8
tx_packets=9
tx_errors=10
tx_dropped=11
# date pattern
# 25.02.12-12:15:00 rx: 3 374464 494 0 tx: 5 542974 0 0
pat_date_dflt = "[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]-[0-9][0-9]:[0-9][0-9]:[0-9][0-9]"
pat_date = length(pat_date) == 0 ? pat_date_dflt : pat_date
}

function dbg(x) {
if (debug > 0) print("debug: " x);
}

# no particular validity check: if there are 11 fields and the first one
# matches the date the user is after, we will use the record.

(NF == 11) && ($1 ~ pat_date) {
dbg("select line: " $0)
accu_sum = $rx_bytes + $tx_bytes
if (accu_sum < accu) {
dbg("break: accu_sum=" accu_sum "; accu_old=" accu_old "; accu=" accu "; offset=" offset);
accu = accu_old + accu - offset
accu_old = accu
offset = accu_sum
accu = accu_sum
} else {
accu = accu_sum
}
}

END {
dbg("eof: accu_sum=" accu_sum "; accu_old=" accu_old "; accu=" accu "; offset=" offset);
accu = accu_old + accu - offset
if (accu > mb_scaler) accu = (accu / mb_scaler) "MB"
print(accu)
}
'
debug=0
log_prefix="/mnt/sdcard/interface-stats"
dates="${1:-.}"
want_if="${2:-wlan0}"
debug="${3+1}"
input="${log_prefix}-${want_if}.txt"
awk -v pat_date="${dates}" -v debug="${debug}" "${awk_prog}" "${input}"

And finally this one is for quick inspection of a logg. Gets the name of an interface as argument if needed. Again it needs no privileges and is appropriate for use as a SMwidget.

#!/system/bin/sh
want_if="${1:-wlan0}"
log_prefix="/mnt/sdcard/interface-stats"
logg="${log_prefix}-${want_if}.txt"
[ -r "${logg}" ] &&
while read tim rx rb rp re rd tx tb tp te td rest
do
case "${rb}--${tb}" in
0--0) continue;;
esac
stats="rx: $rb $rp $re $rd tx: $tb $tp $te $td"
echo "${tim} ${stats}"
done < "${logg}"
exit 0