Skip to content

Instantly share code, notes, and snippets.

@Freaky
Created December 28, 2018 19:56
Show Gist options
  • Save Freaky/0a28a3504804e4ca6936efd897ea7bd4 to your computer and use it in GitHub Desktop.
Save Freaky/0a28a3504804e4ca6936efd897ea7bd4 to your computer and use it in GitHub Desktop.
Munin plugin for Virgin Media Superhub
#!/usr/local/bin/ruby
Host = '192.168.100.1'
require 'net/http'
require 'timeout'
def get(page)
Timeout.timeout(5) { Net::HTTP.get(Host, page) }
rescue => e
STDERR.puts "GET http://#{Host}/#{page} failure: #{e.class}: #{e.message}"
nil
end
def nums_from_table(html, heading)
if html and html =~ /#{Regexp.escape(heading)}<\/td>\s+(.+?)<\/tr>/im
$1.scan(/(?<=<td>)\s*-?[0-9]+(?:\.[0-9]+)?/im).map(&:to_f)
else
[]
end
end
which = $0
category = /(?:downstream_(?:power|mer)|upstream_power)$/.match(which)[0] rescue
abort("Invalid name '#{$0}': must be one of downstream_power, downstream_mer, upstream_power")
Value = Struct.new(:name, :type, :label, :value)
values = []
title = nil
vlabel = nil
info = nil
max_down = 8
max_up = 4
if category.start_with? 'downstream_'
html = get('/cgi-bin/VmRouterStatusDownstreamCfgCgi')
case category
when 'downstream_power'
title = "Downstream Power Levels"
info = "Downstream power levels in dBmV. Closer to zero is better, must be within +/- 15."
vlabel = "dBmV"
chans = nums_from_table(html, "Power Level (dBmV)")
max_down.times do |chan|
val = chans[chan] || 'U'
values << Value.new("down_dbmv#{chan+1}", 'GAUGE', "DS-#{chan+1} Power (dBmV)", val)
end
when 'downstream_mer'
title = "Downstream MER"
info = "Downstream modulation error ratio. 30dB minimum, ideally 33+." # (with 256 QAM)
vlabel = "dB"
chans = nums_from_table(html, "RxMER (dB)")
max_down.times do |chan|
val = chans[chan] || 'U'
values << Value.new("down_mer#{chan+1}", 'GAUGE', "DS-#{chan+1} MER (dB)", val)
end
end
elsif category == 'upstream_power'
title = "Upstream Power Level"
vlabel = "dBmV"
info = "Upstream power levels in dBmV. Lower the better, must be under 55."
html = get('/cgi-bin/VmRouterStatusUpstreamCfgCgi')
chans = nums_from_table(html, "Power Level (dBmV)")#.each_with_index do |val,chan|
max_up.times do |chan|
val = chans[chan] || 'U'
values << Value.new("up_dbmv#{chan+1}", 'GAUGE', "US-#{chan+1} Power (dBmV)", val)
end
end
case ARGV.first
when 'config'
puts <<EOC
graph_title Cable Modem #{title}
graph_vlabel #{vlabel}
graph_category cablemodem
graph_info #{info}
graph_order #{values.map(&:name).join ' '}}
EOC
values.each do |v|
puts <<EOC
#{v.name}.label #{v.label}
#{v.name}.type #{v.type}
EOC
end
when 'autoconfig'
puts(values.any? ? 'yes' : 'no')
else
exit 1 unless values.any?
values.each {|v| puts "#{v.name}.value #{v.value}"}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment