Cablemodem template & perl script

Templates, scripts for templates, scripts and requests for templates.

Moderators: Developers, Moderators

Sleeplesss
Posts: 1
Joined: Fri Jan 28, 2011 3:31 pm

Re: Cablemodem template & perl script

Post by Sleeplesss »

I've tried changing the scripts provided to make this work with my SMC3DGN, but it's not working. Quite certain it's something I'm doing wrong, but it's just plain beyond me.

Really appreciate it if someone could help me with it.

Modem requires UN/PW

The status page is http://192.168.0.1/admin/status_c.asp

Model Name: SMCD3GN
Software Version: 1.4.0.42-RRR
Rogers modem.

Ok sorry, but the file upload thinks the txt doc is an attack vector so I have to put it all in here.


<html>
<head>
<title>Cable Status</title>
<link rel=stylesheet href=../css/form.css>
<script language=JavaScript>
<!--
var CmDownstreamFrequencyBase = "609.000000|591.000000|597.000000|603.000000|";
var CmDownstreamFrequency= CmDownstreamFrequencyBase.split("|");
var CmDownstreamFrequencyNum = (CmDownstreamFrequency.length-1)/2;

var CmDownstreamDSLockStatusBase="1|1|1|1";
var CmDownstreamDSLockStatus=CmDownstreamDSLockStatusBase.split("|");
var CmDownstreamDSLockStatusNum=(CmDownstreamDSLockStatus.length-1)/2;

var CmDownstreamQamBase = "256 QAM|256 QAM|256 QAM|256 QAM|";
var CmDownstreamQam= CmDownstreamQamBase.split("|");
var CmDownstreamQamNum = (CmDownstreamQam.length-1)/2;

var CmDownstreamChannelPowerdBmVBase = "-2.803356|-4.132573|-2.026209|-1.616522";
var CmDownstreamChannelPowerdBmV= CmDownstreamChannelPowerdBmVBase.split("|");
var CmDownstreamChannelPowerdBmVNum = (CmDownstreamChannelPowerdBmV.length-1)/2;

var CmDownstreamSnrBase = " 36.844463| 35.972961| 37.092701| 37.355988";
var CmDownstreamSnr= CmDownstreamSnrBase.split("|");
var CmDownstreamSnrNum = (CmDownstreamSnr.length-1)/2;

var CmUpstreamChannelIdBase = "2|0|0|0|";
var CmUpstreamChannelId= CmUpstreamChannelIdBase.split("|");
var CmUpstreamChannelIdNum = (CmUpstreamChannelId.length-1)/2;

var CmUpstreamFrequencyBase = "25296000|10000000|10000000|10000000|";
var CmUpstreamFrequency= CmUpstreamFrequencyBase.split("|");
var CmUpstreamFrequencyNum = (CmUpstreamFrequency.length-1)/2;

var CmUpstreamLockStatusBase="1|0|0|0";
var CmUpstreamLockStatus=CmUpstreamLockStatusBase.split("|");
var CmUpstreamLockStatusNum=(CmUpstreamLockStatus.length-1)/2;

var CmUpstreamBwBase = "2560|5120|5120|5120";
var CmUpstreamBw= CmUpstreamBwBase.split("|");
var CmUpstreamBwNum = (CmUpstreamBw.length-1)/2;

var CmUpstreamChannelPowerBase = " 40.2500| -1.0000| -1.0000| -1.0000";
var CmUpstreamChannelPower= CmUpstreamChannelPowerBase.split("|");
var CmUpstreamChannelPowerNum = (CmUpstreamChannelPower.length-1)/2;

var CmUpstreamModuBase="16QAM|ERR|ERR|ERR";
var CmUpstreamModu=CmUpstreamModuBase.split("|");
var CmUpstreamModuNum=(CmUpstreamModu.length-1)/2;



var cable_status=12;
cable_status&=0xffff;
var TodSuccess = 1;
//-->
</script>
</head>
<body>
<table width=100% border=0 cellspacing=0 cellpadding=10 align=center>
<tr>
<td valign=top>
<h1>Cable Status</h1>
<p>Cable status shows the users the cable initialization procedures, also the
cable downstream and upstream status.<p>

<ul>
<table cellpadding=2 width=60%>
<b>Initialization Procedure</b>
<tr>
<td class="headerR">Initialize Hardware</td>
<td class="contentL">
<script>
if(cable_status<=2)
document.write("<i>Process...</i>");
if(cable_status>=3)
document.write("Success");
</script>
</td>
</tr>
<tr>
<td class="headerR">Acquire Downstream Channel</td>
<td class="contentL">
<script>
if(cable_status==3)
document.write("<i>Process...</i>");
if(cable_status>=4)
document.write("Success");

</script>
</td>
</tr>
<tr>
<td class="headerR">Upstream Ranging</td>
<td class="contentL">
<script>
if(cable_status==4 || cable_status==5)
document.write("<i>Process...</i>");
if(cable_status>=6)
document.write("Success");
</script>
</td>
</tr>
<tr>
<td class="headerR">DHCP Bound</td>
<td class="contentL">
<script>
if(cable_status==6)
document.write("<i>Process...</i>");
if(cable_status>=7)
document.write("Success");
</script>

</td>
</tr>
<tr>
<td class="headerR">Set Time-of-Day</td>
<td class="contentL">
<script>
if(cable_status==7)
document.write("<i>Process...</i>");
if(cable_status>=8)
{
if (TodSuccess=="1")
document.write("Success");
else
document.write("ToD Server Not Found");
}
</script>
</td>
</tr>
<tr>
<td class="headerR">Downloading CM Config File</td>
<td class="contentL">
<script>
if(cable_status==8 || cable_status==9)
document.write("<i>Process...</i>");
if(cable_status>=10)
document.write("Success");
</script>
</td>

</tr>
<tr>
<td class="headerR">Registration</td>
<td class="contentL">
<script>
if(cable_status==10)
document.write("<i>Process...</i>");
if(cable_status>=11)
document.write("Success");
if(cable_status==12)
document.write("<tr><td colspan=2><center><b>Traffic Enable!</b></center></td></tr>");
if(cable_status==13)
document.write("<tr><td colspan=2><center><b>Refused By CMTS!</b></center></td></tr>");
</script>
</td>
</tr>
</table>
</ul>

<ul>
<table cellpadding=2 width=60%>
<b>Downstream Channel</b>
<tr>

<td class="headerR" width="20%">ID</td>
<td class="headerR" width="20%">0</td>
<td class="headerR" width="20%">1</td>
<td class="headerR" width="20%">2</td>
<td class="headerR" width="20%">3</td>
</tr>
<tr>
<td class="headerR">Downstream Frequency</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmDownstreamDSLockStatus==1)
document.write('<td class="contentL">'+CmDownstreamFrequency+' MHz'+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>
</tr>

<tr>
<td class="headerR">Lock Status</td>
<script>
for(var i=0;i<4;i++){
if(CmDownstreamDSLockStatus==1)
document.write('<td class="contentL">'+"Locked"+'</td>');
else
document.write('<td class="contentL">'+"Not locked"+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Modulation</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmDownstreamDSLockStatus==1)
document.write('<td class="contentL">'+CmDownstreamQam+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Symbol Rate</td>

<script>
for(var i=0;i<4;i++){
if(CmDownstreamDSLockStatus==1)
if(CmDownstreamQam=="64 QAM")
document.write('<td class="contentL">'+"5.056941"+'Msym/sec'+'</td>');
else
document.write('<td class="contentL">'+"5.360537"+'Msym/sec'+'</td>' );
else
document.write('<td class="contentL">'+'</td>' );
}

</script>

</tr>
<tr>
<td class="headerR">Downstream Power</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmDownstreamDSLockStatus==1)
document.write(' <td class="contentL"> '+CmDownstreamChannelPowerdBmV+' dBmV'+'</td>');
else
document.write('<td class="contentL">'+'</td>' );
}
</script>
</tr>
<tr>
<td class="headerR">SNR</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmDownstreamDSLockStatus==1)
document.write('<td class="contentL">'+CmDownstreamSnr[i]+' dB'+'</td>');
else
document.write('<td class="contentL">'+'</td>' );
}
</script>
</tr>
</table>
</ul>

<ul>
<table cellpadding=2 width=60%>
<b>Upstream Channel</b>
<tr>
<td class="headerR" width="20%">ID</td>
<td class="headerR" width="20%">0</td>
<td class="headerR" width="20%">1</td>
<td class="headerR" width="20%">2</td>
<td class="headerR" width="20%">3</td>
</tr>

<tr>
<td class="headerR">Upstream Frequency</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+CmUpstreamFrequency[i]+' Hz'+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Lock Status</td>
<script>
for(var i=0;i<4;i++){
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+"Locked"+'</td>');
else
document.write('<td class="contentL">'+"Not locked"+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Modulation</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+CmUpstreamModu[i]+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>

</tr>
<tr>
<td class="headerR">Symbol Rate</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+CmUpstreamBw[i]+' sym/sec'+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Upstream Power</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+CmUpstreamChannelPower[i]+' dBmV'+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}
</script>
</tr>
<tr>
<td class="headerR">Channel ID</td>
<script language="javascript">
for (var i=0; i<4; i++)
{
if(CmUpstreamLockStatus[i]==1)
document.write('<td class="contentL">'+CmUpstreamChannelId[i]+'</td>');
else
document.write('<td class="contentL">'+'</td>');
}

</script>
</tr>
</table>
</ul>
</td>
</tr>

<tr>
<td>
<table width=100% border=0>
<tr>
<td align=right>
<a href=javascript:void(0) onClick="window.open('help.asp#cable','help','scrollbars=yes,width=600,height=500')"><img src=../images/help.gif border=0></a>
</td>
</tr>
</table>
</td>

</tr>
</table>

<script language=javascript>
if(cable_status<12)
document.write("<meta http-equiv='refresh' content='5;url=status_c.asp'>")
</script>

</body>
</html>
DervMan
Posts: 25
Joined: Tue Apr 29, 2008 11:11 am

Re: Cablemodem template & perl script

Post by DervMan »

I see to be having a problem with the perl script.

I can access the signal page on the modem. I have a WebStar EPC2100 so the URL is slightly different.

The URL for my modem is http://192.168.100.1/signal.asp

I'm getting the when I run the script

/kits/cacti/cablemodem$ perl sciatl_cable_modem.pl
Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 23.
Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 23.
Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 23.
DownSNR: DownPower: UpPower:

The full script is below but line 23 is

Code: Select all

print "$_:" . $data{$_} . " ";

Code: Select all

#!/usr/bin/perl
use warnings;
use strict;

use LWP::Simple;

my $httpaddr = "http://192.168.100.1/signal.asp";

my %data;
my @keys = qw(DownSNR DownPower UpPower);
my $content = LWP::Simple::get($httpaddr) or die "Couldn't get it!";
$content =~ s/\&nbsp;//g;
$content =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gs;

# regex in html source order
if ($content =~ /Signal to Noise Ratio(.+?) dB/) { $data{DownSNR} = $1; }
if ($content =~ s/Power Level(.+?) dBmV/PowerLevel/) { $data{DownPower} = $1; }
if ($content =~ /Power Level(.+?) dBmV/) { $data{UpPower} = $1; }

#for (@keys) { print "$_:$data{$_} "; }
#for (@keys) { print "$_:$data{$_} "; }
for (@keys) {
print "$_:" . $data{$_} . " ";
}

print "\n";
Here's a snipet of the HTML sent back by the modem, this is the SNR part.

Code: Select all

  <tr>
    <td width="225" bgColor="#078188">
      <p style="MARGIN-LEFT: 5px" align="left"><font face="Arial" color="#FFFFFF" size="2">Signal
      to Noise Ratio</font></p>
    </td>
    <td width="275"><font face="Arial" size="2">&nbsp;40.1 dB
      </font></td>
  </tr>
noname
Cacti Guru User
Posts: 1566
Joined: Thu Aug 05, 2010 2:04 am
Location: Japan

Re: Cablemodem template & perl script

Post by noname »

Maybe..

1) Hash arrays should be initialized
2) Newlines and multiple spaces should be truncated
3) For spine, it should not use "print" multiple times
DervMan
Posts: 25
Joined: Tue Apr 29, 2008 11:11 am

Re: Cablemodem template & perl script

Post by DervMan »

Hi noname!

All I've done is used the Webstar perl script from the first post and changed the URL to reflect my modem. From post one it looks like the script is/was working.

I'm running the perl script from bash to make sure it works before even trying to run it in cacti :-/

OK I'll go and find someone that knows perl and get some assistance.

Thanks
noname
Cacti Guru User
Posts: 1566
Joined: Thu Aug 05, 2010 2:04 am
Location: Japan

Re: Cablemodem template & perl script

Post by noname »

>> 1) Hash arrays should be initialized

Ah, sorry.

Code: Select all

Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 23.
This error was not related with 1).
It occurs because your script couldn't parse the output from web page properly.


>> 2) Newlines and multiple spaces should be truncated

In the script from the first post:

Code: Select all

$content =~ s/\&nbsp;|\n//g;
But yours:

Code: Select all

$content =~ s/\&nbsp;//g;
>> 3) For spine, it should not use "print" multiple times

- Making Your Scripts Work With Cacti
Note: Spine requires, that multiple parameters are spit out by a single “print” statement. Do not print them in a loop!
Good luck!
DervMan
Posts: 25
Joined: Tue Apr 29, 2008 11:11 am

Re: Cablemodem template & perl script

Post by DervMan »

Part of the problem seems to be caused by the html having a new line.

Here's the SNR portion

Code: Select all

  <tr>
    <td width="225" bgColor="#078188">
      <p style="MARGIN-LEFT: 5px" align="left"><font face="Arial" color="#FFFFFF" size="2">Signal
      to Noise Ratio</font></p>
    </td>
    <td width="275"><font face="Arial" size="2">&nbsp;39.1 dB
      </font></td>
  </tr>
You can see it's split between 'Signal' and 'to Noise Ratio'.

So I've amended the perl to

Code: Select all

if ($content =~ /to Noise Ratio(.+?) dB/) { $data{DownSNR} = $1; }
When run I now get

Code: Select all

$ perl sciatl_cable_modem.pl
Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 26.
Use of uninitialized value in concatenation (.) or string at sciatl_cable_modem.pl line 26.
    40.0 DownPower: UpPower:
As you can see I'm getting the value but the prefix is being removed by the perl code.

As for the power levels, here's the html

Code: Select all

  <tr>
    <td width="225" bgColor="#078188">
      <p style="MARGIN-LEFT: 5px" align="left"><font face="Arial" color="#FFFFFF" size="2">Power
      Level</font></p>
    </td>
    <td width="275"><font face="Arial" size="2">&nbsp;8.8 dBmV
      </font></td>
  </tr>
Same again the 'Power Level' is being wrapped.

Here's the perl script after many hours of fiddling!

Code: Select all

#!/usr/bin/perl
use warnings;
use strict;

use LWP::Simple;

my $httpaddr = "http://192.168.100.1/signal.asp";

my %data;
my @keys = qw(DownSNR DownPower UpPower);
my $content = LWP::Simple::get($httpaddr) or die "Couldn't get it!";

$content =~ s/\&nbsp;|\n//g;
$content =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gs;


# regex in html source order
if ($content =~ /to Noise Ratio(.+?) dB/) { $data{DownSNR} = $1; }
if ($content =~ s/Power \n. Level(.+?) dBmV/PowerLevel/) { $data{DownPower} = $1; }
if ($content =~ /Power \n. Level(.+?) dBmV/) { $data{UpPower} = $1; }

#for (@keys) { print "$_:$data{$_} "; }

#   print "$_:" . $data{$_} . " ";
#}
for (@keys) { print "$_:$data{$_} "; }

print "\n";
From what I can make out the perl script is looking for the split '/n' being new line and '.' being anything (I think). So is the problem the '&nbsp;' before the value....

Any thoughts?
noname
Cacti Guru User
Posts: 1566
Joined: Thu Aug 05, 2010 2:04 am
Location: Japan

Re: Cablemodem template & perl script

Post by noname »

Though I didn't test fully, how about this?

Code: Select all

...
$content =~ s/\&nbsp;|\n//g;
$content =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gs;
$content =~ s/\s+/ /g;  # convert multiple spaces to single space

# regex in html source order
if ($content =~ /Signal to Noise Ratio ([\d\.]+) dB/) { $data{DownSNR} = $1; }
if ($content =~ s/Power Level ([\d\.]+) dBmV/PowerLevel/) { $data{DownPower} = $1; }
if ($content =~ /Power Level ([\d\.]+) dBmV/) { $data{UpPower} = $1; }
...
DervMan
Posts: 25
Joined: Tue Apr 29, 2008 11:11 am

Re: Cablemodem template & perl script

Post by DervMan »

Hey noname

I owe you.

$ perl sciatl_cable_modem2.pl
DownSNR:39.9 DownPower:9.4 UpPower:55.0
Hapexamendios
Posts: 1
Joined: Tue Dec 13, 2011 2:48 am

Re: Cablemodem template & perl script

Post by Hapexamendios »

Gravepost aside, I think this type of thing would apply and if this was the first place I went to see if this has already been addressed, odds are someone else will too.

So on my old cable modem ( Cisco 2100 ) you were not able to get more detailed information unless it couldn't get a signal or you unlock the webpage first. I found that if you unlock the admin page, it will remain viable for a few minutes before requiring you to enter authentication information again.

Here is my input string that I ended up using to graph the data. I first call a php script to unlock the admin page, then the standard html perl parser to grab the information.

Code: Select all

php <path_cacti>/scripts/openCableAdmin.php; perl <path_cacti>/scripts/cable_stats.pl
Here is what might be the most useful though, it's my php script to unlock the admin page via post.

Code: Select all

<?PHP

/*
** The function:
*/

function PostRequest($url, $referer, $_data) {

    // convert variables array to string:
    $data = array();
    while(list($n,$v) = each($_data)){
        $data[] = "$n=$v";
    }
    $data = implode('&', $data);
    // format --> test1=a&test2=b etc.

    // parse the given URL
    $url = parse_url($url);
    if ($url['scheme'] != 'http') {
        die('Only HTTP request are supported !');
    }

    // extract host and path:
    $host = $url['host'];
    $path = $url['path'];

    // open a socket connection on port 80
    $fp = fsockopen($host, 80);

    // send the request headers:
    fputs($fp, "POST $path HTTP/1.1\r\n");
    fputs($fp, "Host: $host\r\n");
    fputs($fp, "Referer: $referer\r\n");
    fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
    fputs($fp, "Content-length: ". strlen($data) ."\r\n");
    fputs($fp, "Connection: close\r\n\r\n");
    fputs($fp, $data);

    $result = '';
    while(!feof($fp)) {
        // receive the results of the request
        $result .= fgets($fp, 128);
    }

    // close the socket connection:
    fclose($fp);

    // split the result header from the content
    $result = explode("\r\n\r\n", $result, 2);

    $header = isset($result[0]) ? $result[0] : '';
    $content = isset($result[1]) ? $result[1] : '';
    // return as array:
    return array($header, $content);
}



/*
** The call:
*/

// submit the access level and the default password to the device:
$data = array(
    'SAAccessLevel' => '2',
    'SAPassword' => 'W2402',
);

// send a request to the posting page
list($header, $content) = PostRequest(
    "http://192.168.100.1/goform/_aslvl",
    "http://192.168.100.1/_aslvl.asp",
    $data
);

// print the result, this isn't really important
print $content;

?>
And for continuity, here is my perl script

Code: Select all

#!/usr/bin/perl
use warnings;
use strict;

use LWP::Simple;

my $httpaddr = "http://192.168.100.1/system.asp";


my %data;
my @keys = qw(SNR RxPwr TxPwr);
my $content = LWP::Simple::get($httpaddr) or die "Couldn't get it!";
$content =~ s/\&nbsp;//g;
$content =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gs;
#print $content;
# regex in html source order
if ($content =~ /(.+?)dB\s/) { $data{SNR} = $1; }
if ($content =~ /Receive Power Level.*(\n.*) dBmV/) { $data{RxPwr} = $1; }
if ($content =~ /Transmit Power Level.*(\n.*) dBmV/) { $data{TxPwr} = $1; }

$data{SNR} =~ s/^\s+//;
$data{RxPwr} =~ s/^\s+//;
$data{TxPwr} =~ s/^\s+//;

for (@keys) {
   print "$_:" . $data{$_} . " ";
}

Hopefully this helps someone.
phoenixV
Posts: 1
Joined: Sun Dec 09, 2012 9:57 pm

Re: Cablemodem template & perl script

Post by phoenixV »

I ran into some issues with the Surfboard 5100 data gathering script also reported by others, namely

Code: Select all

Use of uninitialized value in concatenation (.) or string at ./broken.pl line 25.
After looking for a few minutes I saw two things,
1) The regex was no longer working on the webpage of the modem, perhaps due to firmware changes.
2) One of the arrays was uninitialised so when the regex failed the value was indeed empty just as stated.

I've the regexs for this version, and the below snipit will fix the uninitialised bit in all versions. My regex changes
may work, but I am no perl programmer or regex master, YRMV. Note that while it gets rid of the error it doesn't fix
the broken regex, it just returns a 0 instead.

Code: Select all

%data = (
        DownFreq => '0',
        DownSNR => '0',
        UpFreq => '0',
        UpPower => '0'
        );
I've attached the complete file below, which also adds a 10 second time out to the script (the default is 3 minutes)
and strips the whitespace as the adjusted regexes are less exact. Adds complexity but is hopefully more resistant
to ugly HTML in any future firmware updates.
Attachments
moto_surfboard_SB5100.txt
(1.35 KiB) Downloaded 438 times
xfrags
Posts: 7
Joined: Thu Mar 12, 2015 9:18 am

Re: Cablemodem template & perl script

Post by xfrags »

hi,

has someone made scripts for cisco epc 3928 and FRITZ!Box 6490 ? or is there a way to get that info through BSR 64000?

snmp is closed.

thanks
kinimod
Posts: 7
Joined: Sat Jul 11, 2015 2:26 pm

Re: Cablemodem template & perl script

Post by kinimod »

Here's a Motorola SurfBoard SB6141 in Perl. Note it needs some Perl modules to run. Use CPAN to get the required modules.

Supports up to 8 channels Down, 4 channels UP, as the modem.

The script will acquire all currently available channels.
Attachments
Moto_SurfBoard_CM_v2C.pl.txt
(938 Bytes) Downloaded 289 times
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests