Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / network / motorola_sb6141 @ 99542938

Historique | Voir | Annoter | Télécharger (7,15 ko)

1 2bb6892e Kenyon Ralph
#!/usr/bin/env python3
2
3
# This plugin graphs the following values of the Motorola SB6141 cable
4
# modem:
5
#
6
# * upstream and downstream power levels
7
# * downstream signal to noise ratio
8
# * downstream signal statistics (codeword counts)
9
#
10
# The values are retrieved from the cable modem's status web pages at
11
# 192.168.100.1. So, this plugin must be installed on a munin node
12
# which can access those pages.
13
#
14
# To install, place this plugin in the node's plugins directory,
15
# /etc/munin/plugins and restart munin-node.
16
#
17
# Developed and tested with firmware SB_KOMODO-1.0.6.16-SCM00-NOSH
18
# (build time Feb 16 2016 11:28:04), hardware version 7.0, boot
19
# version PSPU-Boot(25CLK) 1.0.12.18m3.
20
#
21
# Requires the multigraph and dirtyconfig capabilities available in
22
# munin 2.0 and newer.
23
#
24
# Copyright © 2016 Kenyon Ralph <kenyon@kenyonralph.com>
25
#
26
# This program is free software. It comes without any warranty, to the
27
# extent permitted by applicable law. You can redistribute it and/or
28
# modify it under the terms of the Do What The Fuck You Want To Public
29
# License, Version 2, as published by Sam Hocevar. See
30
# http://www.wtfpl.net/ for more details.
31
#
32
# The latest version of this plugin can be found in the munin contrib
33
# repository at https://github.com/munin-monitoring/contrib. Issues
34
# with this plugin may be reported there. Patches accepted through the
35
# normal github process of forking the repository and submitting a
36
# pull request with your commits.
37
38
import html.parser
39
import urllib.request
40
import sys
41
42
class MotorolaHTMLParser(html.parser.HTMLParser):
43
    def __init__(self):
44
        html.parser.HTMLParser.__init__(self)
45
        self.signaldatapage = list()
46
        self.downstream_channels = list()
47
        self.downstream_SNRs = list()
48
        self.downstream_powers = list()
49
        self.upstream_channels = list()
50
        self.upstream_powers = list()
51
        self.unerrored_codewords = list()
52
        self.correctable_codewords = list()
53
        self.uncorrectable_codewords = list()
54
55
    def handle_data(self, data):
56
        data = data.strip()
57
        if data != '': self.signaldatapage.append(data)
58
59
    def process(self):
60
        # first and last elements are just javascript
61
        del self.signaldatapage[0]
62
        del self.signaldatapage[-1]
63
64
        di = iter(self.signaldatapage)
65
66
        element = next(di)
67
        while element != 'Channel ID': element = next(di)
68
69
        while element != 'Frequency':
70
            element = next(di)
71
            if element != 'Frequency': self.downstream_channels.append(element)
72
73
        while element != 'Signal to Noise Ratio': element = next(di)
74
75
        while element != 'Downstream Modulation':
76
            element = next(di)
77
            if element != 'Downstream Modulation': self.downstream_SNRs.append(element.split()[0])
78
79
        while element != 'The Downstream Power Level reading is a             snapshot taken at the time this page was requested. Please             Reload/Refresh this Page for a new reading': element = next(di)
80
81
        while element != 'Upstream':
82
            element = next(di)
83
            if element != 'Upstream': self.downstream_powers.append(element.split()[0])
84
85
        while element != 'Channel ID': element = next(di)
86
87
        while element != 'Frequency':
88
            element = next(di)
89
            if element != 'Frequency': self.upstream_channels.append(element)
90
91
        while element != 'Power Level': element = next(di)
92
93
        while element != 'Upstream Modulation':
94
            element = next(di)
95
            if element != 'Upstream Modulation': self.upstream_powers.append(element.split()[0])
96
97
        while element != 'Total Unerrored Codewords': element = next(di)
98
99
        while element != 'Total Correctable Codewords':
100
            element = next(di)
101
            if element != 'Total Correctable Codewords': self.unerrored_codewords.append(element)
102
103
        while element != 'Total Uncorrectable Codewords':
104
            element = next(di)
105
            if element != 'Total Uncorrectable Codewords': self.correctable_codewords.append(element)
106
107
        while True:
108
            try:
109
                element = next(di)
110
                self.uncorrectable_codewords.append(element)
111
            except StopIteration:
112
                break
113
114
def main():
115
    if len(sys.argv) != 2 or sys.argv[1] != 'config':
116
        print('Error: plugin designed for the dirtyconfig protocol, must be run with the config argument')
117
        sys.exit(1)
118
119
    parser = MotorolaHTMLParser()
120
    for line in urllib.request.urlopen("http://192.168.100.1/cmSignalData.htm"):
121
        parser.feed(line.decode())
122
    parser.process()
123
124
    print('multigraph motorola_sb6141_power')
125
    print('graph_title Motorola SB6141 Cable Modem Power')
126
    print('graph_vlabel Signal Strength (dBmV)')
127
    print('graph_info This graph shows the downstream and upstream power reported by a Motorola SB6141 cable modem.')
128
    print('graph_category network')
129
    for c, p in zip(parser.downstream_channels, parser.downstream_powers):
130
        print('ds_power_{0}.label Channel {0} Downstream Power'.format(c))
131
        print('ds_power_{0}.type GAUGE'.format(c))
132
        print('ds_power_{0}.value {1}'.format(c, p))
133
    for c, p in zip(parser.upstream_channels, parser.upstream_powers):
134
        print('us_power_{0}.label Channel {0} Upstream Power'.format(c))
135
        print('us_power_{0}.type GAUGE'.format(c))
136
        print('us_power_{0}.value {1}'.format(c, p))
137
138
    print('multigraph motorola_sb6141_snr')
139
    print('graph_title Motorola SB6141 Cable Modem SNR')
140
    print('graph_vlabel Signal-to-Noise Ratio (dB)')
141
    print('graph_info This graph shows the downstream signal-to-noise ratio reported by a Motorola SB6141 cable modem.')
142
    print('graph_category network')
143
    for c, snr in zip(parser.downstream_channels, parser.downstream_SNRs):
144
        print('snr_chan_{0}.label Channel {0} SNR'.format(c))
145
        print('snr_chan_{0}.type GAUGE'.format(c))
146
        print('snr_chan_{0}.value {1}'.format(c, snr))
147
148
    print('multigraph motorola_sb6141_codewords')
149
    print('graph_title Motorola SB6141 Cable Modem Codewords')
150
    print('graph_vlabel Codewords/${graph_period}')
151
    print('graph_info This graph shows the downstream codeword rates reported by a Motorola SB6141 cable modem.')
152
    print('graph_category network')
153
    for c, unerr in zip(parser.downstream_channels, parser.unerrored_codewords):
154
        print('unerr_chan_{0}.label Channel {0} Unerrored Codewords'.format(c))
155
        print('unerr_chan_{0}.type DERIVE'.format(c))
156
        print('unerr_chan_{0}.min 0'.format(c))
157
        print('unerr_chan_{0}.value {1}'.format(c, unerr))
158
    for c, corr in zip(parser.downstream_channels, parser.correctable_codewords):
159
        print('corr_chan_{0}.label Channel {0} Correctable Codewords'.format(c))
160
        print('corr_chan_{0}.type DERIVE'.format(c))
161
        print('corr_chan_{0}.min 0'.format(c))
162
        print('corr_chan_{0}.value {1}'.format(c, corr))
163
    for c, uncorr in zip(parser.downstream_channels, parser.uncorrectable_codewords):
164
        print('uncorr_chan_{0}.label Channel {0} Uncorrectable Codewords'.format(c))
165
        print('uncorr_chan_{0}.type DERIVE'.format(c))
166
        print('uncorr_chan_{0}.min 0'.format(c))
167
        print('uncorr_chan_{0}.value {1}'.format(c, uncorr))
168
169
if __name__ == "__main__":
170
    main()