Auto-Cutoff to Prevent Overages on 3G/4G WiFi...

First off a disclaimer - this is only going to work for Snow Leopard and below (the root app is not Universal) and it can only monitor the usage of a single device. OK, with that out of the way - here is what it does…

A customer recently asked if there was anyway to cut-off a computer from the internet once a certain amount of bandwidth had been reached because they kept going-over every month, and it was getting expensive. He was especially concerned because they were going over by just a few megabytes each time (they are on a Verizon Jetpack WiFi Hotspot - the totals it displays on the LCD are often a few hours off/delayed each day - very tough to be accurate). They were getting charged for an additional GB whether they used it or not.

I did some research, and it turned out that there was an old free-app called SurplusMeter http://www.skoobysoft.com/utilities/utilities.html that is able to keep track of usage up and down for a single device (with a Mac in line as an internet server, it could function for a few devices, just as easily). As is, was perfect for them, because the wife’s laptop is the only device using it. The user can set the monthly limit and day of the month that it rolls over. A bit more technical than these customers needed, but it does gather readable-data to implement control over usage.

Note: Saved these as Application Bundles and edited the info.plist files inside the bundles to make them hidden, so the user didn’t have to see them or chance incidentally closing them. Used this method: http://www.macosxtips.co.uk/index_files/disable-the-dock-icon-for-any-application.php

The following three scripts (mapped here to a folder in Utilities called Jetpack Helpers) work together to pull data-totals from SurplusMeter to control internet usage automatically.

The first, called Jetpack Controller starts on login, and scans constantly looking for the particular network SSID in question - let’s call it “homeNetwork”. When it detects that Airport is attached it it, it starts SurplusMeter, and the second stay-open script called Jetpack Cutoff that disables internet use once the limit is reached. The best part is that if they are away from home, using another network or hotspot, it is not counting against their home totals, as SurplusMeter is then disengaged.



-- Jetpack Controller (WiFi Monitor Script).

on idle
	set jetpackTest to do shell script "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'"
	set airportConnected to jetpackTest
	if airportConnected is "homeNetwork" then  -- Replace "homeNetwork" with whatever your home WiFi is called.
		tell application "System Events"
			set surplusMeterAgentRunning to count of (every process whose name is "SurplusMeterAgent")
			if surplusMeterAgentRunning is 0 then
				do shell script "open /Applications/Utilities/Jetpack\\ Helpers/JetPack\\ Cutoff.app"
				do shell script "open /Applications/SurplusMeter.app/Contents/Resources/SurplusMeterAgent.app"
			end if
		end tell
	else
		try
			do shell script "killall SurplusMeter"
		end try
		delay 0.5
		try
			do shell script "killall SurplusMeterAgent"
		end try
		try
			quit application "Jetpack Cutoff"
		end try
	end if
	return 1
end idle

This second script reads from surplusmeter_data every 5 seconds when active checking on usage up + usage down vs the monthly limit. When that limit is reached, it turns Airport off and displays the dialog “Your monthly bandwidth limit has been reached. Please try again when the term renews.”

If they attempt to turn Airport back on, while the same network is attached, it will turn it back off in just a few seconds. As stated above, this behavior completely disengages if they are attached to a different network or hotspot.



-- Jetpack Cutoff (WiFi Cutoff Script).

on idle
	set surplusMeterPlist to "surplusmeter_data"
	set surplusMeterPlistPath to ((path to application support folder from user domain as Unicode text) & "SurplusMeter:" & surplusMeterPlist & ".plist")
	tell application "System Events"
		set readBytesDown to value of property list item "bytesDown" of property list file surplusMeterPlistPath
		set readBytesUp to value of property list item "bytesUp" of property list file surplusMeterPlistPath
		set readBytesLimit to value of property list item "downloadLimit" of property list file surplusMeterPlistPath
		set byteLimit to readBytesLimit * 1.0E+9
	end tell
	set bytesTotal to readBytesDown + readBytesUp
	if bytesTotal > byteLimit then
		beep
		do shell script "networksetup -setairportpower en1 off"
		tell application "SystemUIServer"
			activate
			display dialog " Your monthly bandwidth limit has been reached. 
 
 Please try again when the term renews." buttons {"OK"} default button "OK"
		end tell
		quit
	end if
	return 5
end idle

The last script is launched by iCal to reset the surplusmeter_data plist each month when the service term resets (in their case on the 3rd of each month). When they login on or after the reset date, the following dialog is displayed: “Your monthly bandwidth limit has been Reset!”, and all totals in the counter are put back to zero.

Would require a different base app to collect network data on a modern version of OSX, but for older machines on 10.6 or before (like maybe a kid’s machine, or backup travel unit) is quite useful for people in rual areas who have to watch their usage.



-- Monthly Bandwidth Reset.

try
	do shell script "networksetup -setairportpower en1 off"
end try
delay 0.5
try
	do shell script "killall SurplusMeter"
end try
delay 0.5
try
	do shell script "killall SurplusMeterAgent"
end try
delay 0.5
set surplusMeterPlist to "~/Library/Application\\ Support/SurplusMeter/surplusmeter_data"
set resetVAlue to "0"
do shell script "defaults write " & surplusMeterPlist & " bytesDown -int " & resetVAlue
do shell script "defaults write " & surplusMeterPlist & " bytesUp -int " & resetVAlue
beep
tell application "SystemUIServer"
	activate
	display dialog "   Your monthly bandwidth limit has been Reset!
	" buttons {"OK"} default button "OK"
end tell