#!/bin/ruby

# Script to log information from my Qwest Century-Link
# Actiontek PK5000 modem.
# Every 10 seconds this gets data via the web interface.
#
# Tom Trebisky  5-29-2013
#
# The Web interface shows two status fields that directly
# mimic the lights on the modem.  So if you are too lazy
# (I mean, it is too inconvenient) to physically look at
# the modem if you have them on the phone, here is how it
# goes:
#
# Look at "Connection Status" section at the top of the
# Connection Status or WAN Status page.
# When all is well there are two green fields that say "CONNECTED".
#
# The top field (Qwest Broadband) corresponds to the "DSL" light.
# The second field (Internet Service Provider (ISP))
#     corresponds to the "Internet" light.
#
# When either field is red "NOT CONNECTED" that is the same as the light off.
# When either field is yellow "CONNECTING" that is the same as the light blinking.
# When either field is green "CONNECTED" that is the same as the light on steady.
#
# The normal sequence is that we start with both lights off.
# Then the top light blinks, and eventually goes on solid.
# Then the second light blinks, and eventually goes on solid.

# --------------------------------
# Here are some variables you may need to tailor to your
# specific setup

$log_file = "/home/tom/bin/modem.log"

$modem_host = "192.168.0.1"

$debug = false
$noisy = false

# You should not need to fiddle below here. -----
# -----------------------------------------------

$wan_file = "wan_status.html"

# This file actually in turn fetches two others
#$stat_file0 = "status.html"
#$stat_file1 = "status_hide.html"
#$stat_file2 = "modemstatus_real.html"
$stat_file = "modemstatus_real.html"

def log ( msg )
	ts = `date`.chomp

	lmsg = "#{ts} #{msg}\n"

	print lmsg if $noisy

	return if $debug

	File.open($log_file,"a") { |f|
		f.print lmsg
	}
end

def getmodem ( file )
	url = "http://#{$modem_host}/cgi-bin/webcm?getpage=../html/#{file}"
	cmd = "curl -s --connect-timeout 8 -m 16 -o #{file} #{url}"
	system cmd
end

def proc_line ( l )
	rv = l.chomp
	rv.gsub! /.*\("/, ''
	rv.gsub! /"\).*/, ''

	#rv.gsub! /&#..;/, ''
	rv.gsub! /&#60;/, '<'
	rv.gsub! /&#62;/, '>'
	rv.gsub! /<[^>]+>/, ''
	rv
end

def proc_inner ( l )
	rv = l.chomp
	rv.gsub! /.*= "/, ''
	rv.gsub! /";.*/, ''
	rv.gsub! /<[^>]+>/, ''
	rv
end

def proc_rate ( l )
	rv = l.chomp
	rv.gsub! /<[^>]+>/, ''
	rv.gsub! /.*Rate:\s*/, ''
	rv.gsub! /\s*Kbps.*/, ''
	rv
end

def process ( wfile, sfile )

	con = "----"
	isp = "----"
	uptime = "?"
	ipaddr = nil
	up = "0"
	down = "0"

	File.new(wfile).each_line { |l|
		if l =~ /var con_state/
			con = proc_line l
		end
		if l =~ /var isp_status/
			isp = proc_line l
		end
		if l =~ /getElementById.*sts2_pppuptime/
			uptime = proc_inner l
		end
	}

	File.new(sfile).each_line { |l|
		if l =~ /getElementById.*WAN_IPaddress/
			unless ipaddr
				v = proc_inner l
				ipaddr = v if v != ""
			end
		end
		if l =~ /Downstream/
			down = proc_rate l
		end
		if l =~ /Upstream/
			up = proc_rate l
		end
	}

	ipaddr = "0.0.0.0" unless ipaddr

	log "#{con} #{isp} #{uptime} (#{ipaddr}) #{down}/#{up} Kbps"
end

def probe_once
	unless system "ping -q -c 1 -W 2 #{$modem_host} > /dev/null"
		log "Cannot reach modem"
		return
	end
	unless getmodem $wan_file
		log "Failed to get WAN status"
		return
	end
	unless getmodem $stat_file
		log "Failed to get MODEM status"
		return
	end

	process $wan_file, $stat_file
end

if $debug
	probe_once
	exit
end

loop {
	probe_once
	sleep 10.0
}

# THE END