#!/usr/bin/perl # # modem.pl - Report the status a Motorola 'SURFboard' cable modem # (models: SB5101, SB5100E) # # copyright(C) 2007 Scott Mazur # GNU General Public License # -------------------------------------------------------------------- # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA # requires: # Time::Local; # LWP::Simple; my $ver = '0.11'; # Version 0.11 # - now handles SB5100E model as well # The Motorola 'SURFboard' cable modem includes a built in web # interface that contains useful information like signal to noise # ratios and power levels. # # This script uses LWP:Simple to scrape the status page from the # modem and report the most useful information in a single line: # Down power, Signal to Noise, Up power # # If the script is not running interactively (like say from a cron # job) the output line is prefixed with a standard log time stamp # and Errors/warnings are duplicated to STDOUT and STDERR. This # is so that cron jobs can report errors while still sending # output to a log file use strict; use warnings; use Time::Local; use LWP::Simple; use constant SB5101_URL => 'http://192.168.100.1/RgSignal.asp'; use constant SB5100E_URL => 'http://192.168.100.1/signaldata.html'; # are we running from a shell or maybe crond? use constant I_am_interactive => (-t STDIN and -t STDOUT); # format current time into standard system log file format my $tm_str = localtime; $tm_str = sprintf("$1 % 2d $3", $2) if $tm_str =~ m/^\S+\s+(\S+)\s+(\S+)\s+(\S+)/; # print message in addition to die unless interactive # This lets you pipe STDOUT to a file yet still get # a message on the console (or from cron) sub My_Die { my $msg = shift; print "$tm_str $msg\n" unless I_am_interactive; die "$msg\n"; } # main script ############# # get the modem status page my $content = get(SB5101_URL) || get(SB5100E_URL) || My_Die("Couldn't get modem signal page!"); # clean up the html a bit for parsing $content =~ s/\n//g; # drop new lines $content =~ s!! !ig; # strip table tags $content =~ s/\s\s+/ /g; # reduce double spaces # check that the page has what we expect $content =~ m{ Frequency \s (\d+\s Hz) \s (Locked\s)? Signal \s To \s Noise \s Ratio \s ([\d.]+\s dB) \s Power \s Level \s ([\d.-]+\s dBmV) }xi or My_Die('content failed!'); # build a hash of signal strength values my %results = ( DownStream => {freq => $1, sn => $3, power => $4}, UpStream => {channel => '?', freq => '? Hz', power => '0 dBmV'} ); # get the upstream values $results{UpStream} = {channel => $1, freq => $2, power => $5} if $content =~ m/ID (\d+) Frequency (\d+ Hz)( Ranged)? Power( Level)? ([\d.-]+ dBmV)/i; # create the result message my $msg = "Down Power: $results{DownStream}->{power}" . " S/N: $results{DownStream}->{sn}" . " Up Power: $results{UpStream}->{power}"; # check up power for reasonable range my $power = $results{UpStream}->{power}; # strip down to raw number my ($stripped) = $power =~ m/^([\d.-]+)/; my $status = ''; $status = 'Up Power high!' if $stripped > 54; $status = 'Up Power low!' if $stripped < 36; # better call the cable guy! if ($status) { warn "$status $power\n"; $msg .= " warning: $status"; } # check down power for reasonable range $power = $results{DownStream}->{power}; # strip down to raw number ($stripped) = $power =~ m/^([\d.-]+)/; $status = ''; $status = 'Down Power high!' if $stripped > 10; $status = 'Down Power low!' if $stripped < -10; # not good either! if ($status) { warn "$status $power\n"; $msg .= " warning: $status"; } $msg = "$tm_str $msg" unless I_am_interactive; print "$msg\n"; # debug dump all values # foreach (qw(DownStream UpStream)) { # print "$_ - "; # my $hash = $results{$_}; # foreach (sort keys %$hash) { # print " $_: $hash->{$_}"; # } # print "\n"; # } exit;