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