Fritzbox call overview

Hi, thank you for that tutorial and all your work!
I changed the script for me to use items (updated via REST api). By that, I do not need the extra html file and also not the habpanel-reload.js for the reload. And for me it get’s easier to understand what happens :smiley:
Another advantage (and the reason I changed it) is that I can use my standard widget with 4 rows, which you can see here:

New messages are shown by a blinking icon, playback works and after playing, the icon stops blinking and gets grey.
I only want to show the missed calls and the recorded messages (the last 4 events).
Here are the items:

String AbMessage
Call   fboxIncomingCall    "Incoming call: [%1$s to %2$s]"     {fritzboxtr064="callmonitor_ringing" } 
Call   fboxOutgoingCall    "Outgoing call: [%1$s to %2$s]"     {fritzboxtr064="callmonitor_outgoing" }
String Anruf_1_Name "Anruf 1 Name [%s]"
String Anruf_2_Name "Anruf 2 Name [%s]"
String Anruf_3_Name "Anruf 3 Name [%s]"
String Anruf_4_Name "Anruf 4 Name [%s]"
String Anruf_1_DatumZeit "Anruf 1 Zeit [%s]"
String Anruf_2_DatumZeit "Anruf 2 Zeit [%s]"
String Anruf_3_DatumZeit "Anruf 3 Zeit [%s]"
String Anruf_4_DatumZeit "Anruf 4 Zeit [%s]"
String Nachricht_1_Datei "Nachricht 1 Datei [%s]"
String Nachricht_2_Datei "Nachricht 2 Datei [%s]"
String Nachricht_3_Datei "Nachricht 3 Datei [%s]"
String Nachricht_4_Datei "Nachricht 4 Datei [%s]"
Switch Nachricht_1_Neu "Nachricht 1 Neu"
Switch Nachricht_2_Neu "Nachricht 2 Neu"
Switch Nachricht_3_Neu "Nachricht 3 Neu"
Switch Nachricht_4_Neu "Nachricht 4 Neu"

Here’s the script:

#!/bin/bash
#
# Check and adapt the following environment variables to your needs:

# fritzbox URL for tr-064 calls
BASEURL="http://fritz.box:49000"
# user:password used to authenticate
USER="user:pw"
# openhab directory containing sounds subdirectory
OPENHAB_DIR=/etc/openhab2
# temporary directory
TMP=/tmp

# number of calls to show
COUNT=40
# number of answering machines
TAM_COUNT=1


### Function definitions ###

function getElement() {
  text=$1
  name=$2
 
  echo "$text" | sed -e "s/.*<$name>//" -e "s#</$name>.*##"
}

function arrayContains() {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

function soapCall() {

  URL=$1
  URN=$2
  ACTION=$3
  ELEMENT=$4
  PARAMETERS=${5:-}

  cat >$TMP/soapEnvelope-$$ <<EOF
<?xml version='1.0' encoding='utf-8'?>
<s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>
 <s:Body>
  <u:$ACTION xmlns:u='$URN'>${PARAMETERS}</u:$ACTION>
 </s:Body>
</s:Envelope>
EOF

  RESPONSE=$(curl -s --anyauth --user $USER $URL -H 'Content-Type: text/xml; charset="utf-8"' -H "SoapAction:$URN#$ACTION" --data @$TMP/soapEnvelope-$$)

  rm $TMP/soapEnvelope-$$

  if [ "x${ELEMENT}x" != "xx" ]; then
    echo $RESPONSE | grep $ELEMENT | sed -e "s/.*<$ELEMENT>//" -e "s#</$ELEMENT>.*##"
  else 
    echo $RESPONSE
  fi
}

function removeTamMessages() {
  rm $TMP/tam${1:-[0-9]}.xml 2>/dev/null
}

function downloadMissingTamMessages() {
  tamidx=0
  while [ $tamidx -lt $TAM_COUNT ]; do 
    if [ ! -f $TMP/tam${tamidx}.xml ]; then
      echo -n "downloading message list for TAM $tamidx..."
      URL=$(soapCall "$BASEURL/upnp/control/x_tam" "urn:dslforum-org:service:X_AVM-DE_TAM:1" GetMessageList NewURL "<NewIndex>${tamidx}</NewIndex>")
	  wget --quiet -O - $URL | awk '/<Message>/,/<\/Message>/ { printf $0 } /<\/Message>/ { print }'>$TMP/tam${tamidx}.xml 
      echo "$(stat -c%s $TMP/tam${tamidx}.xml) bytes."
    fi

    tamidx=$(expr $tamidx + 1)
  done
}

function getTamMsg() {
  mdate=$1

  for tamxml in $TMP/tam${2:-[0-9]}.xml; do
    while read message; do
      date=$(getElement "$message" Date)

      if [ "${date}" == "${mdate}" ]; then
        echo "$message"
        return 0
      fi
    done < $tamxml
  done

  return 1
}

function updateCallOverview() {
  downloadMissingTamMessages

  URL=$(soapCall "$BASEURL/upnp/control/x_contact" "urn:dslforum-org:service:X_AVM-DE_OnTel:1" GetCallList NewCallListURL)

  callidx=0
  echo -n "downloading call list..."
  wget --quiet -O - $URL | grep Call > $TMP/calls.xml
  echo "$(stat -c%s $TMP/calls.xml) bytes."

  zaehler=0
  while read call; do
    type=$(getElement "$call" Type)
    caller=$(getElement "$call" Caller)
    called=$(getElement "$call" Called)
    name=$(getElement "$call" Name)
    date=$(getElement "$call" Date)
    duration=$(getElement "$call" Duration)
    path=$(getElement "$call" Path)

    message=$(getTamMsg "$date")

    [ "x${message}x" != "xx" ] && isTamMsg=1 || isTamMsg=0
    [ "x$(getElement "$message" New)x" == "x1x" ] && isNewTamMsg=1 || isNewTamMsg=0

    echo "processing call $date (isTamMsg=$isTamMsg isNewTamMsg=$isNewTamMsg)..."

    if [ "$path" == "$call" ]; then
      path=""

      # in case this call has no associated recording, check if there is a TAM message with the
      # same time and skip this call 
      if [ $isTamMsg -eq 1 ]; then
        echo "skipped (also has a TAM message)."
        continue
      fi

    else 
      soundfile=${OPENHAB_DIR}/sounds/`basename $path`.wav
	  soundfilename=`basename $path`

      # collect all current soundfiles to be able to delete the old ones
      files[callidx]=$soundfile

      if [ ! -f $soundfile ]; then
        echo -n "fetching ${soundfile}..."

        curl -o $soundfile "${BASEURL}$path&$SID"

        echo "$(stat -c%s $soundfile) bytes."
      fi
	  
    fi

    # 1 incoming
    # 2 missed
    # 3 outgoing
    # 9 active incoming
    #10 rejected incoming
    #11 active outgoing 
    if [ "x${path}x" != "xx" ]; then
	  zaehler=$((zaehler+1))
      if [ $isNewTamMsg -eq 1 ]; then
		curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "ON" "http://openhabianpi:8080/rest/items/Nachricht_${zaehler}_Neu/state"
	  else
		curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "OFF" "http://openhabianpi:8080/rest/items/Nachricht_${zaehler}_Neu/state"
	  fi
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "$soundfilename" "http://openhabianpi:8080/rest/items/Nachricht_${zaehler}_Datei/state"
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "${name:-$caller}" "http://openhabianpi:8080/rest/items/Anruf_${zaehler}_Name/state"
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "$date" "http://openhabianpi:8080/rest/items/Anruf_${zaehler}_DatumZeit/state"
    elif [ $type -eq 2 ]; then
	  zaehler=$((zaehler+1))
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "OFF" "http://openhabianpi:8080/rest/items/Nachricht_${zaehler}_Neu/state"
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "none" "http://openhabianpi:8080/rest/items/Nachricht_${zaehler}_Datei/state"
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "${name:-$caller}" "http://openhabianpi:8080/rest/items/Anruf_${zaehler}_Name/state"
	  curl -s -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "$date" "http://openhabianpi:8080/rest/items/Anruf_${zaehler}_DatumZeit/state"
    fi
    
    callidx=$(expr $callidx + 1)
    if [ $callidx -eq $COUNT ]; then
      break
    fi
    if [ $zaehler -eq 4 ]; then
	  break
	fi
  done < $TMP/calls.xml
  rm $TMP/calls.xml
  echo $zeile

  # remove old files
  for file in ${OPENHAB_DIR}/sounds/rec.[0-9].[0-9][0-9][0-9].wav; do
    arrayContains "$file" "${files[@]}"
    if [ $? -ne 0 -a -f $file ]; then
      rm ${file} 2>/dev/null
      echo "removed old recording $file."
    fi 
  done
}

function mark() {
  file=${OPENHAB_DIR}/sounds/$1

  tam=$(echo $1 | cut -d "." -f 2)
  index=$(echo $1 | cut -d "." -f 3)

  soapCall "$BASEURL/upnp/control/x_tam" "urn:dslforum-org:service:X_AVM-DE_TAM:1" MarkMessage dummy "<NewIndex>$tam</NewIndex><NewMessageIndex>$index</NewMessageIndex>"
}

### the fun starts here ###
source `dirname $0`/lockRoutines
exlock_now || exit 1

echo "lock obtained"

SID=$(soapCall "$BASEURL/upnp/control/deviceconfig" "urn:dslforum-org:service:DeviceConfig:1" "X_AVM-DE_CreateUrlSID" NewX_AVM-DE_UrlSID)

removeTamMessages

if [ $# -eq 1 -a "$1" == "update" ]; then
  updateCallOverview
elif [ $# -eq 2 -a "$1" == "mark" ]; then
  mark $2
  updateCallOverview
else
  echo "`basename $0` update | mark <file>"
  exit 1
fi

removeTamMessages

And I needed to change the “play recorded call” rule:

rule "Play recorded call"
when
   Item AbMessage received command
then
   if (receivedCommand.toString == "1") {
      playSound(Nachricht_1_Datei.toString)
	  executeCommandLine("/etc/openhab2/scripts/fritzbox.sh mark " + Nachricht_1_Datei.toString)
   }
   if (receivedCommand.toString == "2") {
      playSound(Nachricht_2_Datei.toString)
	  executeCommandLine("/etc/openhab2/scripts/fritzbox.sh mark " + Nachricht_2_Datei.toString)
   }
   if (receivedCommand.toString == "3") {
      playSound(Nachricht_3_Datei.toString)
	  executeCommandLine("/etc/openhab2/scripts/fritzbox.sh mark " + Nachricht_3_Datei.toString)
   }
   if (receivedCommand.toString == "4") {
      playSound(Nachricht_4_Datei.toString)
	  executeCommandLine("/etc/openhab2/scripts/fritzbox.sh mark " + Nachricht_4_Datei.toString)
   }
   
end

And the items are shown in a widget:
anrufe.widget.json (4.5 KB)
(preview please see my first link in this post)

Maybe that helps one of you… Have fun :grinning:

1 Like