Data Plan Throttling

Design

This creates a rudimentary, but stable, data plan throttle that will disable any/all LAN traffic on a device if it detects that it has gone over its monthly data usage limit.  This is achieved by leveraging the data usage API available on aView.  The main benefit is the API tracks data usage across reboots, so we can accurately measure the data usage over time.

This feature is implemented using a custom script.  See example setup below.  Note that the user must specify their API token in the custom script.  They can also adjust the data limit (default is 100MB) and the rollover day for the data plan (default is the first day of the month).

If the data plan limit is reached for the month, this script will disable the LAN interface by default (you can change script to disable passthrough mode instead).  Similarly, when the device is within/under its data plan limit for the month, this script will ensure the LAN (or passthrough, if specified) interface is disabled.

Config Setup

Create a new custom script under System -> Scheduled tasks -> custom scripts, and enter in the following.  The top three lines should be adjusted to put in the users API token from aView, the desired data plan limit in bytes, and the rollover day of the month.

Keep in mind that each user in aView only gets 100 API requests every 15 minutes, so don't adjust this interval down so low to the point that the user runs out of API queries (e.g. running this script on 100 devices every 5 minutes equals 300 requests per 15-min, which is more than the API limit).

usage_limit='100000000'   # 100MB
rollover_day='01'  # pick day of month 01-31 to choose when data plan resets
api_token='xxxxxxxxxx'
mac=$(runt get system.mac)
intf=$(runt dump network.modem | grep intf | tail -n 1 | cut -f2 -d'=') # 18.1 or older firmware
[ "$intf" ] || intf=$(runt dump mm.bearer | grep intf | tail -n 1 | cut -f2 -d'=')  # 18.4 or higher firmware
network_to_enable_disable='network.interface.lan'  # set to modem.passthrough if device in passthrough mode
network_enabled="$(config get $network_to_enable_disable.enable)"

bugout() {
  accns_log w config "$@"
  exit
}

var_is_number(){
  [ "$1" ]  || return 1
  case $1 in
    ''|*[!0-9]*) return 1 ;;
    *) return 0 ;;
  esac
}

# Main
end_date=$(date "+%Y-%m-%d")
cur_year=$(date "+%Y")
cur_month=$(date "+%m")
if [ "$rollover_day" -lt "$(date +%d)" ]; then
  start_date="$cur_year-$cur_month-$rollover_day"
else
  case "$cur_month" in
    01)
      last_year=$((cur_year - 1))
      start_date="$last_year-12-$rollover_day"
      ;;
    02|03|04|05|06|07|08|09|10)
      last_month=$((cur_month - 1))
      start_date="$cur_year-0$last_month-$rollover_day"
      ;;
    *)
      last_month=$((cur_month - 1))
      start_date="$cur_year-$last_month-$rollover_day"
      ;;
  esac
fi

url="https://aview.accns.com/api/v4/devices/usage.json?auth_token=${api_token}&device_id=${mac}&start_date=${start_date}&end_date=${end_date}&interface=${intf}"

request_result=$(curl -kL -w %{http_code} -sfo /tmp/results.txt $url)

[ "$request_result" -eq '200' ] || bugout "error obtaining cellular usage from aView API ($request_result)"

upload_usage=$(grep -o "upload\":[0-9]\{1,12\}"  /tmp/results.txt | cut -f2 -d':' | awk '{s+=$1} END {printf "%.0f", s}')
download_usage=$(grep -o "download\":[0-9]\{1,12\}" /tmp/results.txt | cut -f2 -d':' | awk '{s+=$1} END {printf "%.0f", s}')

usage=$(echo "$upload_usage" "$download_usage" | awk '{printf "%0.f", $1 + $2}')
var_is_number "$usage" || bugout "Usage not available from aView API ($upload_usage, $download_usage)"

if [ "$(echo "$usage $usage_limit" | awk '{print ($1 > $2)}')" = '1' ]; then
  accns_log w config "Data usage limit exceeded ($usage out of $usage_limit bytes).  Disabling LAN traffic until monthly rollover date."
  [ "$network_enabled" = '0' ] || config set $network_to_enable_disable.enable false
else
  accns_log w config "Data usage within monthly limit ($usage out of $usage_limit bytes)."
  [ "$network_enabled" = '0' ] && config set $network_to_enable_disable.enable true
fi

Example alert notifying data plan throttle enable and disable