changeset 18:ec994073f70a

Gather more stats (not plotted yet). Remove some old modem cruft. Rearrange graphs by item being graphed.
author Daniel O'Connor <darius@dons.net.au>
date Sun, 22 May 2016 15:39:51 +0930
parents 43f54da8baf9
children 5bec78c876db
files adslstats.py
diffstat 1 files changed, 77 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/adslstats.py	Fri May 20 15:18:59 2016 +0930
+++ b/adslstats.py	Sun May 22 15:39:51 2016 +0930
@@ -74,26 +74,24 @@
 
 (options, args) = opts.parse_args()
 
-statsurl = "http://%s/statsadsl.html" % (options.name)
 rrdname = "%s.rrd" % (options.base)
 graphbasename = options.base
 
-matchnum = re.compile('([0-9]+(\.[0-9]+)?)')
-statsdict = {
-    3 : 'Status:',
-    8 : 'SNR Margin (0.1 dB):',
-    9 : 'Attenuation (0.1 dB):',
-    14 : 'Rate (Kbps):',
-}
-
 class DSLStats(object):
     def __str__(self):
-        s = "Line Rate - Up: %d kbits, Down %d kbits\n" % (self.upstream, self.downstream)
-        if hasattr(self, 'upstreammax'):
-            s += "Maximum Rate - Up: %d kbit, Down %s kbit\n" % (self.upstreammax, self.downstreammax)
-        s += """Noise Margin - Up: %.1f dB, Down %.1f dB
-Attenuation - Up: %.1f dB, Down %.1f dB""" % (self.nmup, self.nmdown,
-                                              self.attenup, self.attendown)
+        s = '''Line Rate - Up: %d kbits, Down %d kbits
+Maximum Rate - Up: %d kbit, Down %s kbit
+Noise Margin - Up: %.1f dB, Down %.1f dB
+Attenuation - Up: %.1f dB, Down %.1f dB
+Errors - Up: %d, Down %d
+Power - Up: %.1f dBm, Down %.1f dBm
+Uptime - %d sec''' % (self.upstream, self.downstream,
+                      self.upstreammax, self.downstreammax,
+                      self.nmup, self.nmdown,
+                      self.attenup, self.attendown,
+                      self.fecATUC, self.fecATUR,
+                      self.uppower, self.downpower,
+                      self.uptime)
         return s
 
 def getstats():
@@ -101,11 +99,13 @@
     parser = ConfigParser.ConfigParser()
     base = 'http://%s' % (conf.get('global', 'name'))
     # Gunk extracted from Chrome (what the page is requesting). Note it's sensitive to line ending type...
-    # We could get more data, eg error rates..
-    data = '[WAN_DSL_INTF_CFG#1,0,0,0,0,0#0,0,0,0,0,0]0,12\r\nstatus\r\nmodulationType\r\nX_TP_AdslModulationCfg\r\nupstreamCurrRate\r\ndownstreamCurrRate\r\nX_TP_AnnexType\r\nupstreamMaxRate\r\ndownstreamMaxRate\r\nupstreamNoiseMargin\r\ndownstreamNoiseMargin\r\nupstreamAttenuation\r\ndownstreamAttenuation\r\n[WAN_DSL_INTF_STATS_TOTAL#1,0,0,0,0,0#0,0,0,0,0,0]1,8\r\nATUCCRCErrors\r\nCRCErrors\r\nATUCFECErrors\r\nFECErrors\r\nSeverelyErroredSecs\r\nX_TP_US_SeverelyErroredSecs\r\nerroredSecs\r\nX_TP_US_ErroredSecs\r\n'
+    # Plus information from http://forum.kitz.co.uk/index.php?topic=15738.0
+    # ATUR = ADSL Termination Unit Remote
+    # ATUC = ADSL Termination Unit Central office
+    query = '[WAN_DSL_INTF_CFG#0,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n[WAN_DSL_INTF_STATS_TOTAL#0,0,0,0,0,0#0,0,0,0,0,0]1,0\r\n'
     cookies = {'Authorization' : 'Basic ' + base64.standard_b64encode(conf.get('global', 'username') + ':' + conf.get('global', 'password'))}
     headers = {'Referer' : base}
-    r = requests.post(base + '/cgi?1&5' , data = data, headers = headers, cookies = cookies, stream = True)
+    r = requests.post(base + '/cgi?5&5' , data = query, headers = headers, cookies = cookies, stream = True)
     parser.readfp(r.raw)
     res = {}
     tmp = '1,0,0,0,0,0'
@@ -121,6 +121,11 @@
     stats.nmdown = float(parser.get(tmp, 'downstreamNoiseMargin')) / 10.0
     stats.attenup = float(parser.get(tmp, 'upstreamAttenuation')) / 10.0
     stats.attendown = float(parser.get(tmp, 'downstreamAttenuation')) / 10.0
+    stats.fecATUR = int(parser.get(tmp, 'FECErrors'))
+    stats.fecATUC = int(parser.get(tmp, 'ATUCFECErrors'))
+    stats.uppower = float(parser.get(tmp, 'upstreamPower')) / 10.0 # I think it's tenths of a dBm but who knows
+    stats.downpower = float(parser.get(tmp, 'downstreamPower')) / 10.0
+    stats.uptime = int(parser.get(tmp, 'showtimeStart'))
 
     return stats
 
@@ -140,6 +145,11 @@
                    'DS:nmdown:GAUGE:3600:0:100',        # Downstream Noise margin (dB)
                    'DS:attenup:GAUGE:3600:0:100',       # Upstream Attenuation (dB)
                    'DS:attendown:GAUGE:3600:0:100',     # Downstream Attenuation (dB)
+                   'DS:fecATUC:DERIVE:3600:0:U',		# Upstream FEC error count
+                   'DS:fecATUR:DERIVE:3600:0:U',		# Downstream FEC error count
+                   'DS:powerup:GAUGE:3600:-100:100',    # Upstream Power (dBm)
+                   'DS:powerdown:GAUGE:3600:-100:100',  # Downstream Power (dBm)
+                   'DS:uptime:DERIVE:3600:0:U',			# Uptime (seconds)
                    'RRA:AVERAGE:0.1:12:168',
                    'RRA:AVERAGE:0.1:288:1825',
                    'RRA:MIN:0.1:12:168',
@@ -148,15 +158,21 @@
 # Update the RRD (format stats as expected)
 def updaterrd(filename, tstamp, stats):
     rrdtool.update(filename,
-                   '%d:%d:%d:%d:%d:%f:%f:%f:%f' % (tstamp,
-                                             stats.upstream,
-                                             stats.downstream,
-                                             stats.upstreammax,
-                                             stats.downstreammax,
-                                             stats.nmup,
-                                             stats.nmdown,
-                                             stats.attenup,
-                                             stats.attendown))
+                   '%d:%d:%d:%d:%d:%f:%f:%f:%f:%d:%d:%f:%f:%d' % (
+                       tstamp,
+                       stats.upstream,
+                       stats.downstream,
+                       stats.upstreammax,
+                       stats.downstreammax,
+                       stats.nmup,
+                       stats.nmdown,
+                       stats.attenup,
+                       stats.attendown,
+                       stats.fecATUC,
+                       stats.fecATUR,
+                       stats.uppower,
+                       stats.downpower,
+                       stats.uptime))
 
 # Open the URL and call the parser
 def getdata():
@@ -176,26 +192,25 @@
         'DEF:upstream=%s:upstream:AVERAGE' % rrdname,
         'DEF:upstreammin=%s:upstream:MIN' % rrdname,
         'DEF:upstreammax=%s:upstream:MAX' % rrdname,
-
-        'DEF:downstream=%s:downstream:AVERAGE' % rrdname,
-        'DEF:downstreammin=%s:downstream:MIN' % rrdname,
-        'DEF:downstreammax=%s:downstream:MAX' % rrdname,
-
         'CDEF:upstreamdif=upstreammax,upstreammin,-',
-        'CDEF:downstreamdif=downstreammax,downstreammin,-',
-
         'DEF:maxupstream=%s:upstreammax:AVERAGE' % rrdname,
-        'DEF:maxdownstream=%s:downstreammax:AVERAGE' % rrdname,
 
         'LINE0:upstreammin#000000:',
         'AREA:upstreamdif#00dc76::STACK',
         'LINE1:upstream#00ff00:Upstream',
 
+        'LINE1:maxupstream#0000ff:Upstream (maximum)',
+
+        'DEF:downstream=%s:downstream:AVERAGE' % rrdname,
+        'DEF:downstreammin=%s:downstream:MIN' % rrdname,
+        'DEF:downstreammax=%s:downstream:MAX' % rrdname,
+        'CDEF:downstreamdif=downstreammax,downstreammin,-',
+        'DEF:maxdownstream=%s:downstreammax:AVERAGE' % rrdname,
+
         'LINE0:downstreammin#000000:',
         'AREA:downstreamdif#ff8686::STACK',
         'LINE1:downstream#ff0000:Downstream',
 
-        'LINE1:maxupstream#0000ff:Upstream (maximum)',
         'LINE1:maxdownstream#000000:Downstream (maximum)'
     )
 
@@ -205,42 +220,48 @@
         '--slope-mode',
         '-l', '0',
 
-        'DEF:upstream=%s:upstream:AVERAGE' % rrdname,
-        'DEF:downstream=%s:downstream:AVERAGE' % rrdname,
-
         'DEF:nmup_=%s:nmup:AVERAGE' % rrdname,
         'DEF:nmupmin_=%s:nmup:MIN' % rrdname,
         'DEF:nmupmax_=%s:nmup:MAX' % rrdname,
 
-        'DEF:nmdown_=%s:nmdown:AVERAGE' % rrdname,
-        'DEF:nmdownmin_=%s:nmdown:MIN' % rrdname,
-        'DEF:nmdownmax_=%s:nmdown:MAX' % rrdname,
-
-        'DEF:attenup=%s:attenup:AVERAGE' % rrdname,
-        'DEF:attenupmin=%s:attenup:MIN' % rrdname,
-        'DEF:attenupmax=%s:attenup:MAX' % rrdname,
-
-        'DEF:attendown=%s:attendown:AVERAGE' % rrdname,
-        'DEF:attendownmin=%s:attendown:MIN' % rrdname,
-        'DEF:attendownmax=%s:attendown:MAX' % rrdname,
-
         'CDEF:nmup=nmup_,10,*',
         'CDEF:nmupmin=nmupmin_,10,*',
         'CDEF:nmupmax=nmupmax_,10,*',
         'CDEF:nmupdif=nmupmax,nmupmin,-',
 
+        'LINE0:nmupmin#000000:',
+        'AREA:nmupdif#5c5cff::STACK',
+        'LINE1:nmup#0000ff:Noise Margin - Up (1/10 dB)',
+
+        'DEF:nmdown_=%s:nmdown:AVERAGE' % rrdname,
+        'DEF:nmdownmin_=%s:nmdown:MIN' % rrdname,
+        'DEF:nmdownmax_=%s:nmdown:MAX' % rrdname,
+
         'CDEF:nmdown=nmdown_,10,*',
         'CDEF:nmdownmin=nmdownmin_,10,*',
         'CDEF:nmdownmax=nmdownmax_,10,*',
         'CDEF:nmdowndif=nmdownmax,nmdownmin,-',
 
+        'DEF:attenup=%s:attenup:AVERAGE' % rrdname,
+        'DEF:attenupmin=%s:attenup:MIN' % rrdname,
+        'DEF:attenupmax=%s:attenup:MAX' % rrdname,
+
         'CDEF:attenupdif=attenupmax,attenupmin,-',
 
+        'DEF:attendown=%s:attendown:AVERAGE' % rrdname,
+        'DEF:attendownmin=%s:attendown:MIN' % rrdname,
+        'DEF:attendownmax=%s:attendown:MAX' % rrdname,
+
         'CDEF:attendowndif=attendownmax,attendownmin,-',
 
-        'LINE0:nmupmin#000000:',
-        'AREA:nmupdif#5c5cff::STACK',
-        'LINE1:nmup#0000ff:Noise Margin - Up (1/10 dB)',
+        'DEF:powerup_=%s:powerup:AVERAGE' % rrdname,
+        'DEF:powerupmin_=%s:powerup:MIN' % rrdname,
+        'DEF:powerupmax_=%s:powerup:MAX' % rrdname,
+
+        'DEF:powerdown_=%s:powerdown:AVERAGE' % rrdname,
+        'DEF:powerdownmin_=%s:powerdown:MIN' % rrdname,
+        'DEF:powerdownmax_=%s:powerdown:MAX' % rrdname,
+
 
         'LINE0:nmdownmin#000000:',
         'AREA:nmdowndif#009a00::STACK',
@@ -319,11 +340,11 @@
 down.type GAUGE
 down.max 15000
 down.min 0
-upmax.label Up
+upmax.label Up (max)
 upmax.type GAUGE
 upmax.max 150000
 upmax.min 0
-downmax.label Down
+downmax.label Down (max)
 downmax.type GAUGE
 downmax.max 150000
 downmax.min 0'''