Compare commits

..

No commits in common. "master" and "6.83.1" have entirely different histories.

13 changed files with 368 additions and 571 deletions

View File

@ -1,4 +0,0 @@
## fritzbox-munin contributors
- Bob van de Vijver ([bobvandevijver](https://github.com/bobvandevijver))
- Framps ([framps](https://github.com/framps))

View File

@ -1,22 +1,5 @@
# Changelog
## 7.25.0
*2021-03-26*
- Support for FritzOS!7.25 including log in via username password
## 7.0.0
*2018-09-11*
- Support for FritzOS!7.00
## 6.83.2
*2017-09-05*
- Support for German and English user interface (by: [@bobvandevijver](https://github.com/bobvandevijver))
- Support for running Fritzbox as separate host (by: [@bobvandevijver](https://github.com/bobvandevijver))
- Make maximum download and upload optional by config (by: [@bobvandevijver](https://github.com/bobvandevijver))
## 6.83.1
*2017-06-11*

121
README.md
View File

@ -1,136 +1,77 @@
# fritzbox-munin
A collection of munin plugins to monitor your AVM FRITZ!Box router. The scripts have been developed using a [FRITZ!Box 7590](http://geni.us/OO2c7S)(Amazon link) running FRITZ!OS 7.25.
A collection of munin plugins to monitor your AVM FRITZ!Box router. The scripts have been developed using a [FRITZ!Box 7362 SL](http://geni.us/fTyoY)(Amazon link) running FRITZ!OS 06.83. This script also only works if the language of the Fritz!Box is set to German.
If you are using the scripts on a different Fritz!Box model please let me know by
- opening an issue
- submitting a pull request
So far the following models (running FRITZ!OS 06.83) have been confirmed working:
- [FRITZ!Box 3370](http://geni.us/zh3U)
- [FRITZ!Box 5490](http://geni.us/ACtUyFt)
- [FRITZ!Box 7362 SL](http://geni.us/fTyoY)
- [FRITZ!Box 7390](http://geni.us/BlAP)
- [FRITZ!Box 7430](http://geni.us/BlAP)
- [FRITZ!Box 7490](http://geni.us/fTyoY)
- [FRITZ!Box 7530](https://geni.us/h8oqYd)
- [FRITZ!Box 7530 AX](https://geni.us/a4dS5)
- [FRITZ!Box 7560](http://geni.us/6gPZNI)
- [FRITZ!Box 7580](http://geni.us/yUYyQTE)
- [FRITZ!Box 7590](http://geni.us/OO2c7S)
If you are still running an older Fritz!OS version check out the [releases section](https://github.com/Tafkas/fritzbox-munin/releases/).
- opening an issue
- submitting a pull request
## Introduction
These python scripts are [Munin](http://munin-monitoring.org) plugins for monitoring the [Fritz!Box](http://avm.de/produkte/fritzbox/) router by AVM.
## fritzbox\_traffic
fritzbox\_traffic shows you the traffic of the WAN interface (requires fritzconnection)
fritzbox\_traffic shows you the traffic of the WAN interface (requires fritzconnection)
![http://i.imgur.com/8BwNMOL.png](http://i.imgur.com/8BwNMOL.png)
If you do not want to show the interface maximum values, add the following to your plugin-configuration:
env.traffic_remove_max true
## fritzbox\_connection\_uptime
fritzbox\_connection\_uptime shows you the connection uptime in days (requires fritzconnection)
fritzbox\_connection\_uptime shows you the connection uptime in days (requires fritzconnection)
![http://i.imgur.com/8oE1OYL.png](http://i.imgur.com/8oE1OYL.png)
## fritzbox\_cpu\_usage
fritzbox\_cpu\_usage shows you the cpu usage (requires username & password)
fritzbox\_cpu\_usage shows you the cpu usage (requires password)
![http://i.imgur.com/A9uGvWP.png](http://i.imgur.com/A9uGvWP.png)
## fritzbox\_cpu\_temperature
fritzbox\_cpu\_temperature shows you the cpu temperature (requires username & password)
fritzbox\_cpu\_temperature shows you the cpu temperature (requires password)
![http://i.imgur.com/duHYhw6.png](http://i.imgur.com/duHYhw6.png)
## fritzbox\_memory\_usage
fritzbox\_memory\_usage shows you the memory usage (requires username & password)
fritzbox\_memory\_usage shows you the memory usage (requires password)
![http://i.imgur.com/WhxrINK.png](http://i.imgur.com/WhxrINK.png)
## fritzbox\_power\_consumption
fritzbox\_power\_consumption shows you the power consumption (requires username & password)
fritzbox\_power\_consumption shows you the power consumption (requires password)
![http://i.imgur.com/a7uQzn6.png](http://i.imgur.com/a7uQzn6.png)
## fritzbox\_uptime
fritzbox\_uptime shows you the uptime in days (requires username & password) (language dependant, see below).
fritzbox\_uptime shows you the uptime in days (requires password)
![http://i.imgur.com/Jr8OibH.png](http://i.imgur.com/Jr8OibH.png)
## fritzbox\_wifi\_devices
fritzbox\_wifi\_devices shows you the number of connected wifi clients (requires username & password) (language dependant, see below).
fritzbox\_wifi\_devices shows you the number of connected wifi clients (requires password)
![http://i.imgur.com/lqvK1b2.png](http://i.imgur.com/lqvK1b2.png)
## Installation & Configuration
## Installation & Configuration
1. Pre-requesites for the fritzbox\_traffic and fritzbox\_uptime plugins are the [fritzconnection](https://pypi.python.org/pypi/fritzconnection) and [requests](https://pypi.python.org/pypi/requests) package. To install it
0. Pre-requesites for the fritzbox\_traffic and fritzbox\_uptime plugins is the [fritzconnection](https://pypi.python.org/pypi/fritzconnection) package. To install it
pip install fritzconnection
pip install -r requirements.txt
fritzconnection requires python3. Make sure python --version is >= 3.6.
1. Copy all the scripts to =/usr/share/munin/plugins
2. Create entry in /etc/munin/plugin-conf.d/munin-node:
[fritzbox_*]
env.fritzbox_ip <ip_address_to_your_fritzbox>
env.fritzbox_password <fritzbox_password>
2. Make sure the FritzBox has UPnP status information enabled. (German interface: Heimnetz > Heimnetzübersicht > Netzwerkeinstellungen > Statusinformationen über UPnP übertragen)
3. Create symbolic links to /etc/munin/plugins.
3. Copy all the scripts to `/usr/share/munin/plugins`
4. Restart the munin-node daemon: /etc/init.d/munin-node restart.
4. Create entry in `/etc/munin/plugin-conf.d/munin-node`:
[fritzbox_*]
env.fritzbox_ip <ip_address_to_your_fritzbox>
env.fritzbox_username <fritzbox_username>
env.fritzbox_password <fritzbox_password>
env.traffic_remove_max true # if you do not want the possible max values
host_name fritzbox
5. Create symbolic links to `/etc/munin/plugins`.
6. Restart the munin-node daemon: `/etc/init.d/munin-node restart`.
7. Done. You should now start to see the charts on the Munin pages.
## Localization
Two scripts depend on the language selected in your fritzbox: the uptime and wifi\_devices. Currently, two locales are
supported:
1. German: `de` (default)
2. English: `en`
You can change the used locale by setting an environment variable in your plugin configuration:
env.locale en
## Different hosts for the fritzbox and your system
You can split the graphs of your fritzbox from the localhost graphs by following the next steps:
1. Use the following as your host configuration in `/etc/munin/munin.conf`
[home.yourhost.net;server]
address 127.0.0.1
use_node_name yes
[home.yourhost.net;fritzbox]
address 127.0.0.1
use_node_name no
2. Add the following to your munin-node configuration
env.host_name fritzbox
3. Restart your munin-node: `systemctl restart munin-node`
5. Done. You should now start to see the charts on the Munin pages.
## Environment Settings
Do not forget to restart the munin-node daemon as described in step 3 of the installation instructions above.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_connection_uptime - A munin plugin for Linux to monitor AVM Fritzbox connection uptime
Copyright (C) 2015 Christian Stade-Schuldt
@ -10,12 +10,6 @@
This plugin requires the fritzconnection plugin. To install it using pip:
pip install fritzconnection
This plugin supports the following munin configuration parameters:
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
#%# family=auto contrib
#%# capabilities=autoconf
"""
@ -23,41 +17,35 @@
import os
import sys
from fritzconnection.lib.fritzstatus import FritzStatus
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
from fritzconnection import FritzConnection
def print_values():
try:
fs = FritzStatus(address=server, user=username, password=password)
conn = FritzConnection(address=os.environ['fritzbox_ip'])
except Exception as e:
sys.exit("Couldn't get connection uptime")
uptime = fs.uptime
print("uptime.value %.2f" % (int(uptime) / 86400.0))
uptime = conn.call_action('WANIPConnection', 'GetStatusInfo')['NewUptime']
print ('uptime.value %.2f' % (int(uptime) / 86400.0))
def print_config():
print("graph_title AVM Fritz!Box Connection Uptime")
print("graph_args --base 1000 -l 0")
print("graph_vlabel uptime in days")
print("graph_scale no'")
print("graph_category network")
print("uptime.label uptime")
print("uptime.draw AREA")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box Connection Uptime"
print "graph_args --base 1000 -l 0"
print 'graph_vlabel uptime in days'
print "graph_scale no'"
print "graph_category network"
print "uptime.label uptime"
print "uptime.draw AREA"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes") # Some docs say it'll be called with fetch, some say no arg at all
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == "fetch"):
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print "yes" # Some docs say it'll be called with fetch, some say no arg at all
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == 'fetch'):
try:
print_values()
except:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_cpu_temperature - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,54 +9,57 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import re
import sys
import fritzbox_helper as fh
PAGE = "ecoStat"
PAGE = '/system/ecostat.lua'
pattern = re.compile('Query\s=\s"(\d{1,3})')
def get_cpu_temperature():
"""get the current cpu temperature"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
print("temp.value %d" % (int(data["data"]["cputemp"]["series"][0][-1])))
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
m = re.search(pattern, data)
if m:
print 'temp.value %d' % (int(m.group(1)))
def print_config():
print("graph_title AVM Fritz!Box CPU temperature")
print("graph_vlabel degrees Celsius")
print("graph_category sensors")
print("graph_order tmp")
print("graph_scale no")
print("temp.label CPU temperature")
print("temp.type GAUGE")
print("temp.graph LINE1")
print("temp.min 0")
print("temp.info Fritzbox CPU temperature")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box CPU temperature"
print "graph_vlabel degrees Celsius"
print "graph_category sensors"
print "graph_order tmp"
print "graph_scale no"
print "temp.label CPU temperature"
print "temp.type GAUGE"
print "temp.graph LINE1"
print "temp.min 0"
print "temp.info Fritzbox CPU temperature"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
get_cpu_temperature()
try:
get_cpu_temperature()
except:
sys.exit("Couldn't retrieve fritzbox cpu temperature")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_cpu_usage - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,55 +9,55 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import re
import sys
import fritzbox_helper as fh
PAGE = "ecoStat"
PAGE = '/system/ecostat.lua'
pattern = re.compile('Query1\s=\s"(\d{1,3})')
def get_cpu_usage():
"""get the current cpu usage"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
print("cpu.value %d" % (int(data["data"]["cpuutil"]["series"][0][-1])))
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
m = re.search(pattern, data)
if m:
print 'cpu.value %d' % (int(m.group(1)))
def print_config():
print("graph_title AVM Fritz!Box CPU usage")
print("graph_vlabel %")
print("graph_category system")
print("graph_order cpu")
print("graph_scale no")
print("cpu.label system")
print("cpu.type GAUGE")
print("cpu.graph AREA")
print("cpu.min 0")
print("cpu.info Fritzbox CPU usage")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box CPU usage"
print "graph_vlabel %"
print "graph_category system"
print "graph_order cpu"
print "graph_scale no"
print "cpu.label system"
print "cpu.type GAUGE"
print "cpu.graph AREA"
print "cpu.min 0"
print "cpu.info Fritzbox CPU usage"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
try:
get_cpu_usage()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_helper - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,157 +9,85 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
The initial script was inspired by
https://www.linux-tips-and-tricks.de/en/programming/389-read-data-from-a-fritzbox-7390-with-python-and-bash
framp at linux-tips-and-tricks dot de
New authentication supporting username and password, as well as PBKDF2 support, has been inspired by
https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM%20Technical%20Note%20-%20Session%20ID_englisch.pdf
"""
import hashlib
import httplib
import re
import sys
import time
from xml.dom import minidom
import requests
from lxml import etree
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0"
LOGIN_SID_ROUTE = "/login_sid.lua?version=2"
USER_AGENT = "Mozilla/5.0 (U; Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0"
class LoginState:
def __init__(self, challenge, blocktime):
self.challenge = challenge
self.blocktime = blocktime
self.is_pbkdf2 = challenge.startswith("2$")
def get_sid(server, password, port=80):
"""Obtains the sid after login into the fritzbox"""
conn = httplib.HTTPConnection(server + ':' + str(port))
headers = {"Accept": "application/xml",
"Content-Type": "text/plain",
"User-Agent": USER_AGENT}
def get_session_id(server, username, password, port=80):
""" Get a sid by solving the PBKDF2 (or MD5) challenge-response process. """
box_url = "http://{}:{}".format(server, port)
try:
state = get_login_state(box_url)
except Exception as ex:
raise Exception("failed to get challenge")
if state.is_pbkdf2:
# print("PBKDF2 supported")
challenge_response = calculate_pbkdf2_response(state.challenge, password)
initial_page = '/login_sid.lua'
conn.request("GET", initial_page, '', headers)
response = conn.getresponse()
data = response.read()
if response.status != 200:
print "%s %s" % (response.status, response.reason)
sys.exit(0)
else:
# print("Falling back to MD5")
challenge_response = calculate_md5_response(state.challenge, password)
if state.blocktime > 0:
# print(f"Waiting for {state.blocktime} seconds...")
time.sleep(state.blocktime)
try:
sid = send_response(box_url, username, challenge_response)
except Exception as ex:
raise Exception("failed to login") from ex
if sid == "0000000000000000":
raise Exception("wrong username or password")
return sid
xml_data = minidom.parseString(data)
sid_info = xml_data.getElementsByTagName('SID')
sid = sid_info[0].firstChild.data
if sid == "0000000000000000":
challenge_info = xml_data.getElementsByTagName('Challenge')
challenge = challenge_info[0].firstChild.data
challenge_bf = (challenge + '-' + password).decode('iso-8859-1').encode('utf-16le')
m = hashlib.md5()
m.update(challenge_bf)
response_bf = challenge + '-' + m.hexdigest().lower()
else:
return sid
headers = {"Accept": "text/html,application/xhtml+xml,application/xml",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": USER_AGENT}
login_page = "/login_sid.lua?&response=" + response_bf
conn.request("GET", login_page, '', headers)
response = conn.getresponse()
data = response.read()
if response.status != 200:
print "%s %s" % (response.status, response.reason)
sys.exit(0)
else:
sid = re.search("<SID>(.*?)</SID>", data).group(1)
if sid == "0000000000000000":
print "ERROR - No SID received because of invalid password"
sys.exit(0)
return sid
def get_login_state(box_url):
""" Get login state from FRITZ!Box using login_sid.lua?version=2 """
url = box_url + LOGIN_SID_ROUTE
r = requests.get(url)
xml = etree.fromstring(r.content)
challenge = xml.find("Challenge").text
blocktime = int(xml.find("BlockTime").text)
return LoginState(challenge, blocktime)
def get_page(server, sid, page, port=80):
"""Fetches a page from the Fritzbox and returns its content"""
conn = httplib.HTTPConnection(server + ':' + str(port))
headers = {"Accept": "application/xml",
"Content-Type": "text/plain",
"User-Agent": USER_AGENT}
def calculate_pbkdf2_response(challenge, password):
""" Calculate the response for a given challenge via PBKDF2 """
challenge_parts = challenge.split("$")
# Extract all necessary values encoded into the challenge
iter1 = int(challenge_parts[1])
salt1 = bytes.fromhex(challenge_parts[2])
iter2 = int(challenge_parts[3])
salt2 = bytes.fromhex(challenge_parts[4])
# Hash twice, once with static salt...
# Once with dynamic salt.
hash1 = hashlib.pbkdf2_hmac("sha256", password.encode(), salt1, iter1)
hash2 = hashlib.pbkdf2_hmac("sha256", hash1, salt2, iter2)
return "{}${}".format(challenge_parts[4], hash2.hex())
def calculate_md5_response(challenge, password):
""" Calculate the response for a challenge using legacy MD5 """
response = challenge + "-" + password
# the legacy response needs utf_16_le encoding
response = response.encode("utf_16_le")
md5_sum = hashlib.md5()
md5_sum.update(response)
response = challenge + "-" + md5_sum.hexdigest()
return response
def send_response(box_url, username, challenge_response):
""" Send the response and return the parsed sid. raises an Exception on error """
# Build response params
post_data = {"username": username, "response": challenge_response}
# post_data = urllib.parse.urlencode(post_data_dict).encode()
headers = {"Content-Type": "application/x-www-form-urlencoded"}
url = box_url + LOGIN_SID_ROUTE
r = requests.post(url, headers=headers, data=post_data)
# Parse SID from resulting XML.
xml = etree.fromstring(r.content)
return xml.find("SID").text
def get_page_content(server, session_id, page, port=80):
"""Fetches a page from the Fritzbox and returns its content
:param server: the ip address of the Fritzbox
:param session_id: a valid session id
:param page: the page you are regquesting
:param port: the port the Fritzbox webserver runs on
:return: the content of the page
"""
headers = {"Accept": "application/xml", "Content-Type": "text/plain", "User-Agent": USER_AGENT}
url = "http://{}:{}/{}?sid={}".format(server, port, page, session_id)
try:
r = requests.get(url, headers=headers)
r.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
sys.exit(1)
return r.content
def get_xhr_content(server, session_id, page, port=80):
"""Fetches the xhr content from the Fritzbox and returns its content
:param server: the ip address of the Fritzbox
:param session_id: a valid session id
:param page: the page you are regquesting
:param port: the port the Fritzbox webserver runs on
:return: the content of the page
"""
headers = {
"Accept": "application/xml",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": USER_AGENT,
}
url = "http://{}:{}/data.lua".format(server, port)
data = {"xhr": 1, "sid": session_id, "lang": "en", "page": page, "xhrId": "all", "no_sidrenew": ""}
try:
r = requests.post(url, data=data, headers=headers)
except requests.exceptions.HTTPError as err:
print(err)
sys.exit(1)
return r.content
page_with_sid = page + "?sid=" + sid
conn.request("GET", page_with_sid, '', headers)
response = conn.getresponse()
data = response.read()
if response.status != 200:
print "%s %s" % (response.status, response.reason)
print data
sys.exit(0)
else:
return data

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_memory_usage - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,63 +9,63 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import re
import sys
import fritzbox_helper as fh
PAGE = "ecoStat"
USAGE = ["strict", "cache", "free"]
PAGE = '/system/ecostat.lua'
pattern = re.compile('Query[1-3]\s="(\d{1,3})')
USAGE = ['free', 'cache', 'strict']
def get_memory_usage():
"""get the current memory usage"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
for i, usage in enumerate(USAGE):
print("%s.value %s" % (usage, data["data"]["ramusage"]["series"][i][-1]))
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
matches = re.finditer(pattern, data)
if matches:
data = zip(USAGE, [m.group(1) for m in matches])
for d in data:
print'%s.value %s' % (d[0], d[1])
def print_config():
print("graph_title AVM Fritz!Box Memory")
print("graph_vlabel %")
print("graph_args --base 1000 -r --lower-limit 0 --upper-limit 100")
print("graph_category system")
print("graph_order strict cache free")
print("graph_info This graph shows what the Fritzbox uses memory for.")
print("graph_scale no")
print("strict.label strict")
print("strict.type GAUGE")
print("strict.draw AREA")
print("cache.label cache")
print("cache.type GAUGE")
print("cache.draw STACK")
print("free.label free")
print("free.type GAUGE")
print("free.draw STACK")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box Memory"
print "graph_vlabel %"
print "graph_args --base 1000 -r --lower-limit 0 --upper-limit 100"
print "graph_category system"
print "graph_order strict cache free"
print "graph_info This graph shows what the Fritzbox uses memory for."
print "graph_scale no"
print "strict.label strict"
print "strict.type GAUGE"
print "strict.draw AREA"
print "cache.label cache"
print "cache.type GAUGE"
print "cache.draw STACK"
print "free.label free"
print "free.type GAUGE"
print "free.draw STACK"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
try:
get_memory_usage()

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# coding=utf-8
#!/usr/bin/env python
"""
fritzbox_power_consumption - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -10,89 +9,87 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import sys
import os
import re
import sys
import fritzbox_helper as fh
PAGE = "energy"
DEVICES = ["system", "cpu", "wifi", "dsl", "ab", "usb"]
PAGE = '/system/energy.lua'
pattern = re.compile('<td>(.+?)"bar\s(act|fillonly)"(.+?)\s(\d{1,3})\s%')
DEVICES = ['system', 'cpu', 'wifi', 'dsl', 'ab', 'usb']
def get_power_consumption():
"""get the current power consumption usage"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
devices = data["data"]["drain"]
for i, device in enumerate(DEVICES):
print("%s.value %s" % (device, devices[i]["actPerc"]))
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
matches = re.finditer(pattern, data)
if matches:
data = zip(DEVICES, [m.group(4) for m in matches])
for d in data:
print'%s.value %s' % (d[0], d[1])
def print_config():
print("graph_title AVM Fritz!Box Power Consumption")
print("graph_vlabel %")
print("graph_category system")
print("graph_order system cpu wifi dsl ab usb")
print("system.label system")
print("system.type GAUGE")
print("system.graph LINE12")
print("system.min 0")
print("system.max 100")
print("system.info Fritzbox overall power consumption")
print("cpu.label cpu")
print("cpu.type GAUGE")
print("cpu.graph LINE1")
print("cpu.min 0")
print("cpu.max 100")
print("cpu.info Fritzbox central processor power consumption")
print("wifi.label wifi")
print("wifi.type GAUGE")
print("wifi.graph LINE1")
print("wifi.min 0")
print("wifi.max 100")
print("wifi.info Fritzbox wifi power consumption")
print("dsl.label dsl")
print("dsl.type GAUGE")
print("dsl.graph LINE1")
print("dsl.min 0")
print("dsl.max 100")
print("dsl.info Fritzbox dsl power consumption")
print("ab.label ab")
print("ab.type GAUGE")
print("ab.graph LINE1")
print("ab.min 0")
print("ab.max 100")
print("ab.info Fritzbox analog phone ports power consumption")
print("usb.label usb")
print("usb.type GAUGE")
print("usb.graph LINE1")
print("usb.min 0")
print("usb.max 100")
print("usb.info Fritzbox usb devices power consumption")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box Power Consumption"
print "graph_vlabel %"
print "graph_category network"
print "graph_order system cpu wifi dsl ab usb"
print "system.label system"
print "system.type GAUGE"
print "system.graph LINE12"
print "system.min 0"
print "system.max 100"
print "system.info Fritzbox overall power consumption"
print "cpu.label cpu"
print "cpu.type GAUGE"
print "cpu.graph LINE1"
print "cpu.min 0"
print "cpu.max 100"
print "cpu.info Fritzbox central processor power consumption"
print "wifi.label wifi"
print "wifi.type GAUGE"
print "wifi.graph LINE1"
print "wifi.min 0"
print "wifi.max 100"
print "wifi.info Fritzbox wifi power consumption"
print "dsl.label dsl"
print "dsl.type GAUGE"
print "dsl.graph LINE1"
print "dsl.min 0"
print "dsl.max 100"
print "dsl.info Fritzbox dsl power consumption"
print "ab.label ab"
print "ab.type GAUGE"
print "ab.graph LINE1"
print "ab.min 0"
print "ab.max 100"
print "ab.info Fritzbox analog phone ports power consumption"
print "usb.label usb"
print "usb.type GAUGE"
print "usb.graph LINE1"
print "usb.min 0"
print "usb.max 100"
print "usb.info Fritzbox usb devices power consumption"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
try:
get_power_consumption()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_traffic - A munin plugin for Linux to monitor AVM Fritzbox WAN traffic
Copyright (C) 2015 Christian Stade-Schuldt
@ -10,12 +10,6 @@
This plugin requires the fritzconnection plugin. To install it using pip:
pip install fritzconnection
This plugin supports the following munin configuration parameters:
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
#%# family=auto contrib
#%# capabilities=autoconf
"""
@ -23,73 +17,66 @@
import os
import sys
from fritzconnection.lib.fritzstatus import FritzStatus
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
from fritzconnection import FritzConnection
def print_values():
try:
fs = FritzStatus(address=server, user=username, password=password)
conn = FritzConnection(address=os.environ['fritzbox_ip'])
except Exception as e:
sys.exit("Couldn't get WAN traffic")
down_traffic = fs.bytes_received
print("down.value %d" % down_traffic)
down_traffic = conn.call_action('WANCommonInterfaceConfig', 'GetTotalBytesReceived')['NewTotalBytesReceived']
print ('down.value %d' % down_traffic)
up_traffic = fs.bytes_sent
print("up.value %d" % up_traffic)
up_traffic = conn.call_action('WANCommonInterfaceConfig', 'GetTotalBytesSent')['NewTotalBytesSent']
print ('up.value %d' % up_traffic)
if not os.environ.get("traffic_remove_max"):
max_traffic = fs.max_bit_rate
max_down_traffic = max_traffic[1]
print("maxdown.value %d" % max_down_traffic)
max_down_traffic = conn.call_action('WANCommonInterfaceConfig', 'GetCommonLinkProperties')[
'NewLayer1DownstreamMaxBitRate']
print ('maxdown.value %d' % max_down_traffic)
max_up_traffic = max_traffic[0]
print("maxup.value %d" % max_up_traffic)
max_up_traffic = conn.call_action('WANCommonInterfaceConfig', 'GetCommonLinkProperties')[
'NewLayer1UpstreamMaxBitRate']
print ('maxup.value %d' % max_up_traffic)
def print_config():
print("graph_title AVM Fritz!Box WAN traffic")
print("graph_args --base 1000")
print("graph_vlabel bits in (-) / out (+) per \${graph_period}")
print("graph_category network")
print("graph_order down up maxdown maxup")
print("down.label received")
print("down.type DERIVE")
print("down.graph no")
print("down.cdef down,8,*")
print("down.min 0")
print("down.max 1000000000")
print("up.label bps")
print("up.type DERIVE")
print("up.draw AREA")
print("up.cdef up,8,*")
print("up.min 0")
print("up.max 1000000000")
print("up.negative down")
print("up.info Traffic of the WAN interface.")
if not os.environ.get("traffic_remove_max"):
print("maxdown.label received")
print("maxdown.type GAUGE")
print("maxdown.graph no")
print("maxup.label MAX")
print("maxup.type GAUGE")
print("maxup.negative maxdown")
print("maxup.draw LINE1")
print("maxup.info Maximum speed of the WAN interface.")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box WAN traffic"
print "graph_args --base 1000"
print "graph_vlabel bits in (-) / out (+) per \${graph_period}"
print "graph_category network"
print "graph_order down up maxdown maxup"
print "down.label received"
print "down.type DERIVE"
print "down.graph no"
print "down.cdef down,8,*"
print "down.min 0"
print "down.max 1000000000"
print "up.label bps"
print "up.type DERIVE"
print "up.draw AREA"
print "up.cdef up,8,*"
print "up.min 0"
print "up.max 1000000000"
print "up.negative down"
print "up.info Traffic of the WAN interface."
print "maxdown.label received"
print "maxdown.type GAUGE"
print "maxdown.graph no"
print "maxup.label MAX"
print "maxup.type GAUGE"
print "maxup.negative maxdown"
print "maxup.draw LINE1"
print "maxup.info Maximum speed of the WAN interface."
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes") # Some docs say it'll be called with fetch, some say no arg at all
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == "fetch"):
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print "yes" # Some docs say it'll be called with fetch, some say no arg at all
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == 'fetch'):
try:
print_values()
except:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_uptime - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,74 +9,60 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import re
import sys
import fritzbox_helper as fh
locale = os.environ.get("locale", "de")
patternLoc = {"de": r"(\d+)\s(Tag|Stunden|Minuten)", "en": r"(\d+)\s(days|hours|minutes)"}
dayLoc = {"de": "Tag", "en": "days"}
hourLoc = {"de": "Stunden", "en": "hours"}
minutesLoc = {"de": "Minuten", "en": "minutes"}
PAGE = "energy"
pattern = re.compile(patternLoc[locale])
PAGE = '/system/energy.lua'
pattern = re.compile("(\d+)\s(Tag|Stunden|Minuten)")
def get_uptime():
"""get the current uptime"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
for d in data["data"]["drain"]:
if "aktiv" in d["statuses"]:
matches = re.finditer(pattern, d["statuses"])
if matches:
hours = 0.0
for m in matches:
if m.group(2) == dayLoc[locale]:
hours += 24 * int(m.group(1))
if m.group(2) == hourLoc[locale]:
hours += int(m.group(1))
if m.group(2) == minutesLoc[locale]:
hours += int(m.group(1)) / 60.0
uptime = hours / 24
print("uptime.value %.2f" % uptime)
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
matches = re.finditer(pattern, data)
if matches:
hours = 0.0
for m in matches:
if m.group(2) == 'Tag':
hours += 24 * int(m.group(1))
if m.group(2) == "Stunden":
hours += int(m.group(1))
if m.group(2) == "Minuten":
hours += int(m.group(1)) / 60.0
uptime = hours / 24
print "uptime.value %.2f" % uptime
def print_config():
print("graph_title AVM Fritz!Box Uptime")
print("graph_args --base 1000 -l 0")
print("graph_vlabel uptime in days")
print("graph_scale no'")
print("graph_category system")
print("uptime.label uptime")
print("uptime.draw AREA")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print "graph_title AVM Fritz!Box Uptime"
print "graph_args --base 1000 -l 0"
print 'graph_vlabel uptime in days'
print "graph_scale no'"
print "graph_category system"
print "uptime.label uptime"
print "uptime.draw AREA"
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
try:
get_uptime()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
"""
fritzbox_wifi_devices - A munin plugin for Linux to monitor AVM Fritzbox
Copyright (C) 2015 Christian Stade-Schuldt
@ -9,63 +9,54 @@
[fritzbox_*]
env.fritzbox_ip [ip address of the fritzbox]
env.fritzbox_username [fritzbox username]
env.fritzbox_password [fritzbox password]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import json
import os
import re
import sys
import fritzbox_helper as fh
locale = os.environ.get("locale", "de")
patternLoc = {"de": r"(\d+) WLAN", "en": r"(\d+) wireless LAN"}
PAGE = "energy"
pattern = re.compile(patternLoc[locale])
PAGE = '/system/energy.lua'
pattern = re.compile("(\d+) WLAN")
def get_connected_wifi_devices():
"""gets the numbrer of currently connected wifi devices"""
server = os.environ["fritzbox_ip"]
username = os.environ["fritzbox_username"]
password = os.environ["fritzbox_password"]
server = os.environ['fritzbox_ip']
password = os.environ['fritzbox_password']
session_id = fh.get_session_id(server, username, password)
xhr_data = fh.get_xhr_content(server, session_id, PAGE)
data = json.loads(xhr_data)
m = re.search(pattern, data["data"]["drain"][2]["statuses"][-1])
sid = fh.get_sid(server, password)
data = fh.get_page(server, sid, PAGE)
m = re.search(pattern, data)
if m:
connected_devices = int(m.group(1))
print("wifi.value %d" % connected_devices)
print 'wifi.value %d' % connected_devices
def print_config():
print("graph_title AVM Fritz!Box Connected Wifi Devices")
print("graph_vlabel Number of devices")
print("graph_args --base 1000")
print("graph_category network")
print("graph_order wifi")
print("wifi.label Wifi Connections on 2.4 & 5 Ghz")
print("wifi.type GAUGE")
print("wifi.graph LINE1")
print("wifi.info Wifi Connections on 2.4 & 5 Ghz")
if os.environ.get("host_name"):
print("host_name " + os.environ["host_name"])
print 'graph_title AVM Fritz!Box Connected Wifi Devices'
print 'graph_vlabel Number of devices'
print 'graph_args --base 1000'
print 'graph_category network'
print 'graph_order wifi'
print 'wifi.label Wifi Connections on 2.4 & 5 Ghz'
print 'wifi.type GAUGE'
print 'wifi.graph LINE1'
print 'wifi.info Wifi Connections on 2.4 & 5 Ghz'
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "config":
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == "autoconf":
print("yes")
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == "fetch":
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
print 'yes'
elif len(sys.argv) == 1 or len(sys.argv) == 2 and sys.argv[1] == 'fetch':
# Some docs say it'll be called with fetch, some say no arg at all
try:
get_connected_wifi_devices()

View File

@ -1,3 +0,0 @@
fritzconnection
lxml
requests