Fritzbox Cable Docsis Parameter auslesen

Aus Neobiker\\\'s Wiki
Zur Navigation springen Zur Suche springen

Kleines Shellscript um von einer AVM Fritzbox Cable mit FritzOS 7.20 die Kabel-Informationen (DOCSIS 3.0) auszulesen und in eine Influxdb zu speichern.

Zur Anzeige der Monitoring-Daten in der InfluxxDB verwende ich Grafana. Hier ist mein Grafana Dashboard inklusive Ping Packet Loss als JSON Export.

Cable Ping Status Dashboard

Skript für InfluxDB V2.x: Usage: fritz_docsis_2_influx_lines.sh | influx write -b cable6490

#!/bin/bash
#
# fritz_docsis_2_influx_lines.sh
#
# read DOCSIS Information from Fritzbox Cable Routers
# and write these infos in a format that can be
# written into an influx database
#
# example: fritz_docsis_2_influx_lines.sh | influx write -b <bucket>

# ---------------------------------------------
# please define your settings for your fritzbox
# ---------------------------------------------
fritzbox=192.168.178.1
user=<MyUser>
pass=<MyPassword>

#
# nothing to be changed from here
#

# --------------------
# cache Login with SID
# --------------------
sidfile=/run/shm/$fritzbox.sid
[ ! -f $sidfile ] && echo "0000000000000000" > $sidfile
sid=$(cat $sidfile)

# --------------------
# check Login with SID
# --------------------
result=$(curl -s "http://$fritzbox/login_sid.lua?sid=$sid" | grep -c "0000000000000000")
if [ $result -gt 0 -o $sid = "0000000000000000" ]; then
  challenge=$(curl -s http://$fritzbox/login_sid.lua | grep -o "<Challenge>.*</Challenge>" | sed 's,</*Challenge>,,g')
  hash=$(echo -n "$challenge-$pass" | sed -e 's,.,&\n,g' | tr '\n' '\0' | md5sum | grep -o "[0-9a-z]\{32\}")
  curl -s "http://$fritzbox/login_sid.lua" -d "response=$challenge-$hash" -d 'username='${user} | grep -o "<SID>[a-z0-9]\{16\}" | cut -d'>' -f 2 > $sidfile
fi
sid=$(cat $sidfile)

# --------------------------------
# read DOCSIS-Infos (page=docInfo)
# --------------------------------
docsis=$(curl -s "http://$fritzbox/data.lua" -d "xhr=1&sid=$sid&lang=de&page=docInfo&xhrId=all&no_sidrenew")

# AVM may change the modulation entry from 'type' to 'modulation' in later OS version
if [ "_"$(echo ${docsis} | jq -r ".data.channelUs.docsis30[0].type") = "_null" ]; then
  qam="modulation"
else
  qam="type"
fi

# get nr. of up-/downstream channels
channelUs=$(echo ${docsis} | jq ".data.channelUs.docsis30[].powerLevel" | wc -l)
channelDs=$(echo ${docsis} | jq ".data.channelDs.docsis30[].powerLevel" | wc -l)

# read upstream channels
for (( c=0; c<$channelUs; c++ )); do
  channelID[$c]=$(echo ${docsis}  | jq -r ".data.channelUs.docsis30[$c].channelID")
  channel[$c]=$(echo ${docsis}    | jq -r ".data.channelUs.docsis30[$c].channel")
  modulation[$c]=$(echo ${docsis} | jq -r ".data.channelUs.docsis30[$c].$qam" | sed 's/[^0-9.]//g')
  powerLevel[$c]=$(echo ${docsis} | jq -r ".data.channelUs.docsis30[$c].powerLevel")
  frequency[$c]=$(echo ${docsis}  | jq -r ".data.channelUs.docsis30[$c].frequency")

  echo "docsis,mode=up,channel=${channelID[$c]} Modulation=${modulation[$c]}"
  echo "docsis,mode=up,channel=${channelID[$c]} PowerLevel=${powerLevel[$c]}"
  echo "docsis,mode=up,channel=${channelID[$c]} Frequenz=${frequency[$c]}"
done

# read downstream channels
for (( c=0; c<$channelDs; c++ )); do
  channelID[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].channelID")
  channel[$c]=$(echo ${docsis}    | jq -r ".data.channelDs.docsis30[$c].channel")
  modulation[$c]=$(echo ${docsis} | jq -r ".data.channelDs.docsis30[$c].$qam" | sed 's/[^0-9.]//g')
  powerLevel[$c]=$(echo ${docsis} | jq -r ".data.channelDs.docsis30[$c].powerLevel")
  frequency[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].frequency")
  latency[$c]=$(echo ${docsis}    | jq -r ".data.channelDs.docsis30[$c].latency")
  corrErrors[$c]=$(echo ${docsis} | jq -r ".data.channelDs.docsis30[$c].corrErrors")
  nonCorrErrors[$c]=$(echo ${docsis} | jq -r ".data.channelDs.docsis30[$c].nonCorrErrors")

  echo "docsis,mode=down,channel=${channelID[$c]} Modulation=${modulation[$c]}"
  echo "docsis,mode=down,channel=${channelID[$c]} PowerLevel=${powerLevel[$c]}"
  echo "docsis,mode=down,channel=${channelID[$c]} Frequenz=${frequency[$c]}"
  echo "docsis,mode=down,channel=${channelID[$c]} Latenz=${latency[$c]}"
  echo "docsis,mode=down,channel=${channelID[$c]} korrFehler=${corrErrors[$c]}"
  echo "docsis,mode=down,channel=${channelID[$c]} Fehler=${nonCorrErrors[$c]}"
done

Skript für InfluxDB V1.6:

#!/bin/bash

fritzbox=<fritz.box>
user=<admin>
pass=<password>
influxdb=<influxdb name>

# --------------------
# cache Login with SID
# --------------------
sidfile=/dev/shm/$fritzbox.sid
[ ! -f $sidfile ] && touch $sidfile
sid=$(cat $sidfile)

# --------------------
# check Login with SID
# --------------------
result=$(curl -s "http://$fritzbox/login_sid.lua?sid=$sid" | grep -c "0000000000000000")
if [ $result -gt 0 ]; then
  challenge=$(curl -s http://$fritzbox/login_sid.lua | grep -o "<Challenge>.*</Challenge>" | sed 's,</*Challenge>,,g')
  hash=$(echo -n "$challenge-$pass" | sed -e 's,.,&\n,g' | tr '\n' '\0' | md5sum | grep -o "[0-9a-z]\{32\}")
  curl -s "http://$fritzbox/login_sid.lua" -d "response=$challenge-$hash" -d 'username='${user} | grep -o "<SID>[a-z0-9]\{16\}" | cut -d'>' -f 2 > $sidfile
fi
sid=$(cat $sidfile)

# -----------------
# read DOCSIS-Infos
# -----------------
docsis=$(curl -s "http://$fritzbox/data.lua" -d "xhr=1&sid=$sid&lang=de&page=docInfo&xhrId=all&no_sidrenew")

# function: write data into influxdb
write_influxdb () {
    curl -i -XPOST 'http://127.0.0.1:8086/write?db='$influxdb --data-binary "$1"
}

# get nr. of up-/downstream channels
channelUs=$(echo ${docsis} | jq ".data.channelUs.docsis30[].powerLevel" | wc -l)
channelDs=$(echo ${docsis} | jq ".data.channelDs.docsis30[].powerLevel" | wc -l)

# read upstream channels
for (( c=0; c<$channelUs; c++ )); do
  channelID[$c]=$(echo ${docsis}  | jq -r ".data.channelUs.docsis30[$c].channelID")
  channel[$c]=$(echo ${docsis}    | jq -r ".data.channelUs.docsis30[$c].channel")
  qam[$c]=$(echo ${docsis}        | jq -r ".data.channelUs.docsis30[$c].type" | sed 's/QAM//g')
  powerLevel[$c]=$(echo ${docsis} | jq -r ".data.channelUs.docsis30[$c].powerLevel")
  frequency[$c]=$(echo ${docsis}  | jq -r ".data.channelUs.docsis30[$c].frequency")

  echo "ID ${channelID[$c]}: Channel ${channel[$c]} (${frequency[$c]}) ${qam[$c]} PowerLevel ${powerLevel[$c]}"
  write_influxdb "docsis,mode=up,channel=${channelID[$c]},param=Modulation value=${qam[$c]}"
  write_influxdb "docsis,mode=up,channel=${channelID[$c]},param=Power\ Level\ [dBmV] value=${powerLevel[$c]}"
  write_influxdb "docsis,mode=up,channel=${channelID[$c]},param=Frequenz\ [MHz] value=${frequency[$c]}"
done

# read downstream channels
for (( c=0; c<$channelDs; c++ )); do
  channelID[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].channelID")
  channel[$c]=$(echo ${docsis}    | jq -r ".data.channelDs.docsis30[$c].channel")
  qam[$c]=$(echo ${docsis}        | jq -r ".data.channelDs.docsis30[$c].type" | sed 's/QAM//g')
  powerLevel[$c]=$(echo ${docsis} | jq -r ".data.channelDs.docsis30[$c].powerLevel")
  frequency[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].frequency")
  latency[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].latency")
  corrErrors[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].corrErrors")
  nonCorrErrors[$c]=$(echo ${docsis}  | jq -r ".data.channelDs.docsis30[$c].nonCorrErrors")

  echo "ID ${channelID[$c]}: Channel ${channel[$c]} (${frequency[$c]}) ${qam[$c]} PowerLevel ${powerLevel[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=Modulation value=${qam[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=Power\ Level\ [dBmV] value=${powerLevel[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=Frequenz\ [MHz] value=${frequency[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=Latenz\ [ms] value=${latency[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=korrigierbare\ Fehler value=${corrErrors[$c]}"
  write_influxdb "docsis,mode=down,channel=${channelID[$c]},param=nicht\ korrigierbare\ Fehler value=${nonCorrErrors[$c]}"
done