#!/bin/bash
# checklivechannels.sh
# RD 22.12.2013
# v0.02

# Historie:
# RD 21.12.2013 v0.01 Initial
# RD 21.12.2013 v0.02 Fehlerhandling

# Prüft ob ein Sender ein bewegtes Bild hat
# Sender die keins haben sind potentiell
# - Tote Sender
# - Mosaik Bilder
# - Testkanäle
# - Radiosender
# - Verschlüsselte Sender, die dieses System auch nicht entschlüsseln kann

# Konzept-Test; Es wird nur eine Meldung ausgegeben.
# Diese könnte man dann in einem seperaten Programm weiterverarbeiten und die channels.conf ändern

# Aufräumen der tempörären Dateien in /tmp manuell, wenn mit crtl-c abgebrochen wird.
# Aufruf mit: ./checklivechannels.sh | 2>&1 tee -a check1.log

# Auswerten der Ergebnisse mit:
# grep "Kanal:" check1.log
# grep "Live-Bild" check1.log
# grep "Standbild" check1.log


# Parameter zum einstellen----------------------------------------------------------------------------
CHANNELSCONF='/var/lib/vdr/channels.conf'
TMP='/tmp'
# hier ggf. den remote-pfad eintragen (-d <host>)
SVDRP='svdrpsend'
# Kanalnummer, bei der begonnen / wiederaufgesetzt werden soll, da man die untersten eh von Hand gepflegt hat
START_CHANNEL=153
# Hier die Wartezeit nach dem Kanalwechsel einstellen, das Bild muss stabil sein
DELAY_STABLE_PICTURE=5
# Zeit in sec, die der vdr für einen restart braucht - ich habe _einige_ Kanäle die den vdr rebooten lassen
# mit "time restart vdr" min. ermitteln, Zeit für dump hinzurechnen
# Kurze Zeiten haben sich nicht bewährt, dann wird der Folgekanal fälschlich als 'killer' ausgegeben.
# "time restart vdr" ergibt bei mir 25 sec, trotzdem sind > 60 sec. nötig!
RESTART_DELAY=120
# Zusätzliches Logfile
LOGFILE='/var/log/checklivechannels.log'

DEBUG=0
# ----------------------------------------------------------------------------------------------------

# If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.
set -o pipefail

RUNDATE=$(date "+%d.%m.%Y %R")          # Aktuelles Datum und Zeit

# Funktionen
function log() {     # Gibt die Meldung auf der Konsole und im Syslog aus
  logger -s -t $(basename ${0%.*}) "$*"
  [ -n "${LOGFILE}" ] && echo "$*" >> ${LOGFILE}
}

function DEBUG() {
  if [ "$DEBUG" == "1" ]; then
    echo DEBUG "$*"
  fi
}

# Skript start!
echo
echo Läuft bis zum letzten Kanal, abbruch möglich mit ctrl-c
echo


[ -n "${LOGFILE}" ] && log "${RUNDATE} - $(basename $0) - Start..."
echo

if [ ! -e ${CHANNELSCONF} ] ; then        # Prüfen, ob die channels.conf existiert
   log "FATAL: ${CHANNELSCONF} nicht gefunden!"
   exit 1
fi

echo "Cleanup: Alte temporäre Snapshots löschen"
echo
rm $TMP/grab_*.pnm > /dev/null 2>&1

CURRENT_CHANNEL=$START_CHANNEL
RUN=1


while [ "$RUN" == "1" ] ; do
  # echo current_channel: $CURRENT_CHANNEL

  # tune zum Sender
  # Dem string ist ein "return" angehängt, dieses filtern. Sonst wird der string verstümmelt
  # Das entfernen muss direkt geschehen, später in einer Variable fkt. es nicht mehr (Daten überschrieben)
  # Damit der retcode von svdrp ausgewertet werden kann muss "set -o pipefail" gesetzt sein. ($PIPESTATUS war nicht erfolgreich.)
  # STR=$(svdrpsend CHAN $CURRENT_CHANNEL | tr -d '\r')
  DEBUG Schalte zu Kanal $CURRENT_CHANNEL

  STR=$(svdrpsend CHAN $CURRENT_CHANNEL 2> /dev/null | tr -d '\r')
  # STR=$(svdrpsend CHAN $CURRENT_CHANNEL | tr -d '\r')
  RET=$?
  DEBUG svdrp Ergebnis: $STR
  DEBUG svdrp Retcode : $RET
  # Results:
  # $STR:
  # 220 media-sack2 SVDRP VideoDiskRecorder 2.0.3; Sun Dec 22 11:27:34 2013; UTF-8 250 1443 [checkignore]Canal Algerie 221 media-sack2 closing connection
  # 220 media-sack2 SVDRP VideoDiskRecorder 2.0.3; Sun Dec 22 11:28:18 2013; UTF-8 501 Undefined channel "1450" 221 media-sack2 closing connection
  # $RET
  # 0 wenn die wenn die Verbindnung zum vdr ok ist (Auch wenn das tunen etc fehllschlägt)
  # 1 wenn connect: Verbindungsaufbau abgelehnt

  # Check ob Verbindung zum vdr ok
  if [ "$RET" != "0" ]; then
    DEBUG ERROR: svdrp connect: Verbindungsaufbau abgelehnt
    # echo WARNING: vdr könnte abgestürzt sein / rebooten
    echo Kanal: $CURRENT_CHANNEL : WARNING: vdr reboot?
    # warte, überspringe den Kanal
    echo Warte $RESTART_DELAY sec auf vdr
    sleep $RESTART_DELAY
    # zum nächsten Kanal
    let CURRENT_CHANNEL=$CURRENT_CHANNEL+1
    continue
  fi
  
  # Ende wenn Kanal undefiniert (> letzter Kanal)
  BREAKSTR=$(echo $STR | grep "501 Undefined channel")
  # $BREAKSTR ist nicht leer wenn der Kanal undefiniert ist
  # echo Breakstr: $BREAKSTR
  if [ ! -z "$BREAKSTR" ]; then # Breakstr gefüllt => Undefined channel
    echo "Kanal" $CURRENT_CHANNEL "ist nicht definiert. Ende der Kanalliste erreicht"
    # DEBUG $BREAKSTR
    # Schleifenende
    RUN=0 
    break
  fi

  # extrahiere Kanalnamen
  # echo $STR
  CHANNEL_NAME=$(echo $STR | cut -d ";" -f 3|sed -e "s/.* 250 \(.*\) 221 .*/\1/" )

  # Nun Bildvergleich
  # Warte auf stabiles Bild
  sleep $DELAY_STABLE_PICTURE

  # vdr ist nun auf den Kanal eingestellt (oder abgestürzt)
  # Check ob vdr noch läuft
  STR=$(svdrpsend CHAN 2> /dev/null | tr -d '\r')
  RET=$?
  if [ "$RET" != "0" ]; then
    DEBUG ERROR: svdrp check connect: Verbindungsaufbau abgelehnt
    # echo WARNING: vdr könnte abgestürzt sein / rebooten
    echo Kanal: $CURRENT_CHANNEL : ERROR: Annahme dass vdr rebootet!
    # warte, überspringe den Kanal
    echo Warte $RESTART_DELAY sec auf vdr
    sleep $RESTART_DELAY
    # zum nächsten Kanal
    let CURRENT_CHANNEL=$CURRENT_CHANNEL+1
    continue
  fi

  # 2 Schnappschüsse
  svdrpsend GRAB $TMP/grab_"$CURRENT_CHANNEL"_1.pnm > /dev/null 2>&1
  RET=$?
  if [ "$RET" != "0" ]; then
    echo ERROR: svdrp grab für Kanal $CHANNEL_NAME, Bild Nr. 1: Verbindungsaufbau abgelehnt
  else
    svdrpsend GRAB $TMP/grab_"$CURRENT_CHANNEL"_2.pnm > /dev/null 2>&1
    RET=$?
    if [ "$RET" != "0" ]; then
      echo ERROR: svdrp grab für Kanal $CHANNEL_NAME, Bild Nr. 2: Verbindungsaufbau abgelehnt
    fi
  fi   

  # Schnappschüsse vergleichen bzw. Fehler ausgeben
  cmp $TMP/grab_"$CURRENT_CHANNEL"_1.pnm $TMP/grab_"$CURRENT_CHANNEL"_2.pnm > /dev/null 2>&1
  RET=$?
  # Exit status is 0 if inputs are the same, 1 if different, 2 if trouble.
  # echo diff-ret: $RET
  # Ausgabe zur Auswertung
  echo -n "Kanal: " $CHANNEL_NAME ": "
  if [ "$RET" == "0" ]; then
    echo "Standbild"
  else
    if [ "$RET" == "1" ]; then
      echo "Live-Bild"
    else
      echo "ERROR: Bild-Vergleich, Fehler: " $RET
    fi
  fi
  let CURRENT_CHANNEL=$CURRENT_CHANNEL+1
done

echo "Cleanup: Temporäre Snapshots löschen"
rm $TMP/grab_*.pnm

echo "Ende script"
