#!/bin/bash
###############################################################################################################
# Titel: mysql
# Autor: Michael Kaden
# Datum: 04.01.2017
#
# Funktion:
# Dieses Skript ist ein Teilprogramm von fdtpoc. Es liest alle im Read-Spooler-Verzeichnis erzeugten Dateien
# in einer Endlosschleife ein. 
# Diese Read-Spooler-Dateien enthalten jeweils eine Zeile, die durch die Read-Spooler (read.ttyXXX) von dem 
# an der jeweiligen Schnittstelle angeschlossenen Gerät empfangen haben.
# Alle empfangenen Zeilen werden, um Log-Informationen erweitert, in ein Logfile geschrieben.
# Empfangene Zeilen, die als Pocsag-Message erkannt werden, werden zusätzlich in eine MySQL-Datenbank geschrieben.
# Zusätzlich kann die Pocsag-Nachricht zur Weiterverarbeitung an ein weiteres Programm weitergeleitet werden.
#
# Zweck:
# Das Script soll als Hintergrundprozess auf einem Funk-Daten-Server laufen, an den ein POCSAG-Decoder (Alphapog 1500) verbunden ist. 
# Die in der MySQL-Datenbank gesammelten Nachrichten können so in anderen Anwendungen, z.B. Einsatzführungssoftware, ausgewertet 
# werden, um z.B. in einem Einsatzführungstool automatisiert Einsätze aus POCSAG-Alarmen zu generieren.
#
# Copyright (C) 2014 Michael Kaden
#
# Dieses Programm ist freie Software. Sie können es unter Beachtung der Nutzungsbedingungen benutzen, 
# weitergeben und modifizieren.
# Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, dass es Ihnen von Nutzen sein wird, 
# aber OHNE IRGENDEINE GARANTIE, sogar ohne die Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN 
# BESTIMMTEN ZWECK. 
###############################################################################################################

# Config-File einlesen
source /usr/local/smi/sub/etc/mysql.conf

# eigenen Dateinamen bestimmen
myname=$(echo "$0" | $awk -F/ '{ print $NF }')



# alle MQTT-Messages in einer Endlosschleife einlesen
while read -r line; do

	# hole aktuellen Timestamp
	now=$(date +%s)
	
	# erzeuge ein assoziatives Array um die Message zu speichern
	declare -A msg

	# notify processing a new JSON-Objekt
	log "$myname" "processing new JSON object"
	
	# erstelle Liste der Keys im JSON-Objekt
	keys=$(echo "$line" | $jq -r 'keys[]')
	
	# übernehme JSON-Objekt in Array
	for i in $keys; do msg[${i}]=$(echo "$line" | $jq -r .${i}); done
	
	# write the array content into the logfile
	for i in $keys; do log "$myname" "  $i: ${msg[${i}]}"; done
		
	case ${msg[type]} in
		monitor)
			case ${msg[sys]} in
				sds)							
					sqlcmd="SELECT radio_time FROM $sds_db_trx WHERE radio_host='$host' and radio_dev='${msg[dev]}'"
					datetimeDB=$(exec_mysql "$sqlcmd" | tail -n +2)
					# Prüfen, ob zu unserem Server bereits ein Eintrag mit der ISSI existiert, in dem wir den Timestamp aus der DB lesen
					if [ -n "$datetimeDB" ]; then
						# Wenn Eintrag vorhanden -> Timestamp auslesen
						timestampDB=$(date --date "$datetimeDB" +%s)
						# Tabelleneintrag aktualisieren wenn timestamp > timestampDB
						if [ ${msg[lv]} -gt $timestampDB ];then
							log "$myname" "aktualisiere Alive-Eintrag für FuG \"${msg[dev]}\" in \"${db}.${sds_db_trx}\""
							exec_mysql "UPDATE $sds_db_trx SET radio_time = now(), radio_opta='${msg[opta]}', radio_gssi='${msg[gssi]}', radio_issi='${msg[issi]}', radio_dBm='${msg[rss]}', radio_MNI='${msg[mni]}', radio_LA='${msg[la]}', radio_reg='${msg[reg]}' WHERE radio_host='$host' and radio_dev='${msg[dev]}'"
							mysqlexit=$?
							if [ $mysqlexit -eq 0 ]; then
								log "$myname" "done"
							else
								log "$myname" "error"
							fi
						fi
					# Wenn kein Eintrag existiert -> Eintrag hinzufügen
					else
						log "$myname" "erstelle Alive-Eintrag für FuG \"${msg[dev]}\" in \"${db}.${sds_db_trx}\""
						exec_mysql "INSERT INTO $sds_db_trx (radio_host,radio_issi,radio_gssi,radio_opta,radio_dev,radio_dBm,radio_MNI,radio_LA,radio_reg,radio_time) values ('$host','${msg[issi]}','${msg[gssi]}','${msg[opta]}','${msg[dev]}','${msg[rss]}','${msg[mni]}','${msg[la]}','${msg[reg]}',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
					
					# Zeitstempel des Statusservers in der monitord-DB setzen
					if [ "$(exec_mysql "SELECT * FROM $sds_db_server WHERE srv_host='$host'" | tail -n +2 | grep -c "$host")" = "1" ]; then
						log "$myname" "aktualisiere Server \"$host\" Alive-Eintrag in \"$db.$sds_db_server\""
						exec_mysql "UPDATE $sds_db_server set srv_time=now() where srv_host='$host'"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					else
						log "$myname" "füge Server \"$host\" Alive-Eintrag in \"$db.$sds_db_server\" hinzu"
						exec_mysql "INSERT INTO $sds_db_server (srv_host,srv_time) values ('$host',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi

				;;
				sms)
					sqlcmd="SELECT mod_time FROM $sms_db_trx WHERE mod_host='$host' and mod_dev='${msg[dev]}'"
					datetimeDB=$(exec_mysql "$sqlcmd" | tail -n +2)
					# Prüfen, ob zu unserem Server bereits ein Eintrag mit der ID existiert, in dem wir den Timestamp aus der DB lesen
					if [ -n "$datetimeDB" ]; then
						# Wenn Eintrag vorhanden -> Eintrag aktualisieren
						timestampDB=$(date --date "$datetimeDB" +%s)
						# Tabelleneintrag aktualisieren wenn timestamp > timestampDB
						if [ ${msg[lv]} -gt $timestampDB ];then
							log "$myname" "aktualisiere Alive-Eintrag für Modem \"${msg[dev]}\" in \"$db.$sms_db_trx\""
							exec_mysql "UPDATE $sms_db_trx SET mod_id='${msg[on]}',mod_dBm='${msg[rss]}',mod_op='${msg[op]}',mod_reg='${msg[reg]}',mod_time=now() WHERE mod_host='$host' and mod_dev='${msg[dev]}'"
							mysqlexit=$?
							if [ $mysqlexit -eq 0 ]; then
								log "$myname" "done"
							else
								log "$myname" "error"
							fi
						fi
					# Wenn kein Eintrag existiert -> Eintrag hinzufügen
					else
						log "$myname" "erstelle Alive-Eintrag für Modem \"${msg[dev]}\" in \"$db.$sms_db_trx\""
						exec_mysql "INSERT INTO $sms_db_trx (mod_host,mod_id,mod_dev,mod_dBm,mod_op,mod_reg,mod_time) values ('$host','${msg[on]}','${msg[dev]}','${msg[rss]}','${msg[op]}','${msg[reg]}',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				
					# Zeitstempel des Statusservers in der monitord-DB setzen
					if [ "$(exec_mysql "SELECT * FROM $sms_db_server WHERE srv_host='$host'" | tail -n +2 | grep -c "$host")" = "1" ]; then
						log "$myname" "aktualisiere Alive-Eintrag für Server \"$host\" in \"$db.$sms_db_server\""
						exec_mysql "UPDATE $sms_db_server set srv_time=now() where srv_host='$host'"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					else
						log "$myname" "erstelle Alive-Eintrag für Server \"$host\"  in \"$db.$sms_db_server\""
						exec_mysql "INSERT INTO $sms_db_server (srv_host,srv_time) values ('$host',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				;;
				poc)
					sqlcmd="SELECT dec_time FROM $poc_db_trx WHERE dec_host='$host' and dec_dev='${msg[dev]}'"
					datetimeDB=$(exec_mysql "$sqlcmd" | tail -n +2)
					# Prüfen, ob zu unserem Server bereits ein Eintrag mit der ISSI existiert, in dem wir den Timestamp aus der DB lesen
					if [ -n "$datetimeDB" ]; then
						# Wenn Eintrag vorhanden -> Timestamp auslesen
						timestampDB=$(date --date "$datetimeDB" +%s)
						# Tabelleneintrag aktualisieren wenn timestamp > timestampDB
						if [ ${msg[lv]} -gt $timestampDB ];then
							log "$myname" "aktualisiere Alive-Eintrag für Decoder \"${msg[dev]}\" in \"$db.$poc_db_trx\""
							exec_mysql "UPDATE $poc_db_trx SET dec_time=now() WHERE dec_host='$host' and dec_dev='${msg[dev]}'"
							mysqlexit=$?
							if [ $mysqlexit -eq 0 ]; then
								log "$myname" "done"
							else
								log "$myname" "error"
							fi
						fi
					# Wenn kein Eintrag existiert -> Eintrag hinzufügen
					else
						log "$myname" "erstelle Alive-Eintrag für Decoder \"${msg[dev]}\" in \"$db.$poc_db_trx\""
						exec_mysql "INSERT INTO $poc_db_trx (dec_host,dec_dev,dec_time) values ('$host','${msg[dev]}',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				
					# Zeitstempel des Statusservers in der monitord-DB setzen
					if [ "$(exec_mysql "SELECT * FROM $poc_db_server WHERE srv_host='$host'" | tail -n +2 | grep -c "$host")" = "1" ]; then
						log "$myname" "aktualisiere Alive-Eintrag für Server \"$host\" in \"$db.$poc_db_server\""
						exec_mysql "UPDATE $poc_db_server set srv_time=now() where srv_host='$host'"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					else
						log "$myname" "erstelle Alive-Eintrag für Server \"$host\"  in \"$db.$poc_db_server\""
						exec_mysql "INSERT INTO $poc_db_server (srv_host,srv_time) values ('$host',now())"
						mysqlexit=$?
						if [ $mysqlexit -eq 0 ]; then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				;;
			esac
			# ist kein "outdated" timestamp vorhanden oder ist er überschritten?
			outdated=$(cat $outdatedTsFile 2>/dev/null)
			
			#log "$myname" "current outdated timestamp is \"$(date -d @${outdated})\""
			#log "$myname" "now timestamp is \"$(date -d @${now})\""
			
			if [ -z "$outdated" ] || [ $now -gt $outdated ]; then
			
				log "$myname" "now timestamp is greater than outdated timestamp or there is no outdated timestamp"
				# Lösche veraltete SDS-Nachrichten aus der Tabelle
				log "$myname" "deleting outdated SDS messages > $sds_msg_max_age days"
				exec_mysql "DELETE FROM $sds_db_message WHERE TIMESTAMPADD(DAY,$sds_msg_max_age,sds_time)<now()"
				mysqlexit=$?
				if [ $mysqlexit -eq 0 ]; then
					log "$myname" "done"
				else
					log "$myname" "error"
				fi

				# Lösche veraltete SMS-Nachrichten aus der Tabelle
				log "$myname" "deleting outdated SMS messages > $sms_msg_max_age days"
				exec_mysql "DELETE FROM $sms_db_message WHERE TIMESTAMPADD(DAY,$sms_msg_max_age,sms_time)<now()"
				mysqlexit=$?
				if [ $mysqlexit -eq 0 ]; then
					log "$myname" "done"
				else
					log "$myname" "error"
				fi
					
				# Lösche veraltete POCSAG-Nachrichten dieses Hosts aus der Tabelle
				log "$myname" "deleting outdated POCSAG messages > $poc_msg_max_age days"
				exec_mysql "DELETE FROM $poc_db_message WHERE TIMESTAMPADD(DAY,$poc_msg_max_age,msg_time)<now()"
				mysqlexit=$?
				if [ $mysqlexit -eq 0 ]; then
					log "$myname" "done"
				else
					log "$myname" "error"
				fi
				
				# setze outdated timestamp auf nächsten Tag 00:00:00
				outdatednew=$(( $(date +%s -d "$(date +%D) 00:00:00") + 86400 ))
				log "$myname" "setting next check outdated timestamp at \"$(date -d @${outdatednew})\""
				echo "$outdatednew" > "$outdatedTsFile"
			fi
		;;
		message)
			case ${msg[sys]} in
				sds)
					if [ "${msg[dir]}" = "rx" ]; then
						# SDS-Datensatz in Datenbank schreiben
						log "$myname" "writing message into \"$db.$sds_db_message\""
						exec_mysql "INSERT INTO $sds_db_message (sds_uid,sds_time,sds_aitype,sds_from,sds_fromtype,sds_to,sds_totype,sds_length,sds_userdata,sds_visible,sds_radio,sds_host) values (MD5(UUID()),NOW(),'${msg[st]}','${msg[from]}','${msg[ft]}','${msg[to]}','${msg[tt]}','${msg[ln]}','${msg[ud]}','1','${msg[dev]}','$host')"
						mysqlexit=$?
						# Debug:
						#echo "\$mysqlexit: $mysqlexit"
						if (( $mysqlexit == 0 )); then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				;;
				sms)
					if [ "${msg[dir]}" = "rx" ]; then
						# Datensatz in Datenbank schreiben
						log "$myname" "writing message into \"$db.$sms_db_message\""
						exec_mysql "INSERT INTO $sms_db_message (sms_uid,sms_time,sms_scts,sms_from,sms_fromtype,sms_to,sms_totype,sms_data,sms_visible,sms_mod,sms_host) values (MD5(UUID()),NOW(),from_unixtime(${msg[scts]}),'${msg[from]}','${msg[ft]}','${msg[to]}','${msg[tt]}','${msg[ud]}','1','${msg[dev]}','$host')"
						mysqlexit=$?
						if (( $mysqlexit == 0 )); then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				;;
				poc)
					if [ "${msg[dir]}" = "rx" ]; then
						# schreibe Datensatz in Datenbank; Decodiere den Message-Text zurück aus "base64"
						log "$myname" "writing message into \"$db.$poc_db_message\""
						exec_mysql "INSERT INTO $poc_db_message (msg_uid,msg_time,msg_dBm,msg_ric,msg_sub,msg_text,msg_visible,msg_dec,msg_host) values (MD5(UUID()),NOW(),'${msg[rss]}','${msg[ric]}','${msg[sub]}','$(echo -n ${msg[txt]} | $base64 -d)','${msg[vis]}','${msg[dev]}','$host')"
						mysqlexit=$?
						if (( $mysqlexit == 0 )); then
							log "$myname" "done"
						else
							log "$myname" "error"
						fi
					fi
				;;
			esac
	esac

	unset msg
	unset outdated
	unset outdatednew
done < <($mosquitto_sub -t "$(eval echo $MqttRead)")
exit 255