up to $maxMatches matching lines */ function pistar_log_tail_match($path, $matchRegex, $excludeRegex, $maxMatches, $stripFirstField = false, $reverse = false) { $bufSize = 262144; // 256 KB tail window — see docblock above $fp = @fopen($path, 'rb'); if ($fp === false) { return array(); } if (fseek($fp, 0, SEEK_END) !== 0) { fclose($fp); return array(); } $fileSize = ftell($fp); if ($fileSize === false || $fileSize === 0) { fclose($fp); return array(); } $readSize = min($bufSize, $fileSize); $readFrom = $fileSize - $readSize; if (fseek($fp, $readFrom, SEEK_SET) !== 0) { fclose($fp); return array(); } $buf = fread($fp, $readSize); fclose($fp); if ($buf === false || $buf === '') { return array(); } // If we started reading mid-file, the first line in $buf is // almost certainly cut by the chunk boundary. Drop bytes up // to and including the first newline so we never feed a // partial line to the regex pass. (When $readFrom == 0 we're // at the start of the file — the first line is real, keep it.) if ($readFrom > 0) { $nl = strpos($buf, "\n"); if ($nl === false) { return array(); } $buf = substr($buf, $nl + 1); } $matched = array(); $lines = explode("\n", $buf); foreach ($lines as $line) { if ($line === '') continue; if (!preg_match($matchRegex, $line)) continue; if ($excludeRegex !== '' && preg_match($excludeRegex, $line)) continue; $matched[] = $line; } if (count($matched) > $maxMatches) { $matched = array_slice($matched, -$maxMatches); } if ($stripFirstField) { foreach ($matched as &$mline) { $sp = strpos($mline, ' '); if ($sp !== false) { $mline = substr($mline, $sp + 1); } } unset($mline); } if ($reverse) { $matched = array_reverse($matched); } return $matched; } function getMMDVMConfig() { // /etc/mmdvmhost is read once per request and cached for the // remainder. The top-level init at the bottom of this file // calls us once, and getDSTARLinks() calls us again on D-Star // hosts — same request, same file, identical result. The // static cache resets at request shutdown (PHP-FPM does not // preserve userland state between requests), so this is purely // an in-request dedup, not a cross-request cache. static $cached; if ($cached !== null) { return $cached; } $cached = array(); if ($configs = @fopen(MMDVMINIPATH."/".MMDVMINIFILENAME, 'r')) { while ($config = fgets($configs)) { array_push($cached, trim($config, " \t\n\r\0\x0B")); } fclose($configs); } return $cached; } function getDMRHostsLines() { // /usr/local/etc/DMR_Hosts.txt is the BrandMeister master list, // typically 3-6K lines on SD storage. repeaterinfo.php scans it // twice per request when both DMR and YSF2DMR are enabled (lines // 243-282 and 379-389) — both consumers iterate the same lines // looking for an IP→name match. Read once into an in-memory // line array; foreach() across it is free. // // Per-request scope only (PHP-FPM resets userland state between // requests). file() loads the whole file in one syscall, which // is cheaper than ~6K fgets() calls and roughly the same memory // (~400-800 KB for the typical hosts file — fine on the 512 MB+ // Pi-Star supports). static $cached; if ($cached !== null) { return $cached; } $cached = @file('/usr/local/etc/DMR_Hosts.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if ($cached === false) { $cached = array(); } return $cached; } function getTGNameMap() { // /usr/local/etc/TGList_CN.json is this operator's own domestic // talkgroup registry, synced once a day by pistar-cn-tglist-sync // from https://860.radiowo.com/api/v1/talkgroups. MMDVMHost's log // only ever prints the numeric ID ("to TG 86990"), never a name, // so lh.php needs this map to show what that network's own // dashboard shows for free. // // Deliberately CN-only: BrandMeister's global TGList_BM.txt is NOT // read/merged here — this operator's TG IDs are a private/domestic // numbering space, and mixing in BM's global names would show the // wrong name for an ID that means something else on this network. // // Per-request scope only (PHP-FPM resets userland state between // requests); cheap enough (a few dozen entries) to re-parse each // request. static $cached; if ($cached !== null) { return $cached; } $cached = array(); $json = @file_get_contents('/usr/local/etc/TGList_CN.json'); if ($json !== false) { $rows = json_decode($json, true); if (is_array($rows)) { foreach ($rows as $row) { if (!is_array($row)) { continue; } if (!isset($row['tg_id'], $row['name'])) { continue; } if (!is_numeric($row['tg_id'])) { continue; } $cached[(int)$row['tg_id']] = (string)$row['name']; } } } return $cached; } function getYSFGatewayConfig() { // loads /etc/ysfgateway into array for further use $conf = array(); if ($configs = @fopen(YSFGATEWAYINIPATH."/".YSFGATEWAYINIFILENAME, 'r')) { while ($config = fgets($configs)) { array_push($conf, trim ( $config, " \t\n\r\0\x0B")); } fclose($configs); } return $conf; } function getP25GatewayConfig() { // loads /etc/p25gateway into array for further use $conf = array(); if ($configs = @fopen(P25GATEWAYINIPATH."/".P25GATEWAYINIFILENAME, 'r')) { while ($config = fgets($configs)) { array_push($conf, trim ( $config, " \t\n\r\0\x0B")); } fclose($configs); } return $conf; } function getNXDNGatewayConfig() { // loads /etc/nxdngateway into array for further use $conf = array(); if ($configs = @fopen('/etc/nxdngateway', 'r')) { while ($config = fgets($configs)) { array_push($conf, trim ( $config, " \t\n\r\0\x0B")); } fclose($configs); } return $conf; } function getM17GatewayConfig() { // loads /etc/m17gateway into array for further use $conf = array(); if ($configs = @fopen('/etc/m17gateway', 'r')) { while ($config = fgets($configs)) { array_push($conf, trim ( $config, " \t\n\r\0\x0B")); } fclose($configs); } return $conf; } function getDAPNETGatewayConfig() { // loads /etc/dapnetgateway into array for further use $conf = array(); if ($configs = @fopen('/etc/dapnetgateway', 'r')) { while ($config = fgets($configs)) { array_push($conf, trim ( $config, " \t\n\r\0\x0B")); } fclose($configs); } return $conf; } function getConfigItem($section, $key, $configs) { // retrieves the corresponding config-entry within a [section] $sectionpos = array_search("[" . $section . "]", $configs) + 1; $len = count($configs); while(startsWith($configs[$sectionpos],$key."=") === false && $sectionpos <= ($len) ) { if (startsWith($configs[$sectionpos],"[")) { return null; } $sectionpos++; } return substr($configs[$sectionpos], strlen($key) + 1); } function getEnabled ($mode, $mmdvmconfigs) { // returns enabled/disabled-State of mode return getConfigItem($mode, "Enable", $mmdvmconfigs); } function checkDMRLogin ($dmrDaemon) { if ($dmrDaemon == "MMDVMHost") { if (file_exists(MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log")) { $logPath = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; $logCheckMMDVMHostDMRLogin = `tail -n 5 $logPath | awk '/master/ && /successfully/ || /master/ && /failed/' | tail -n 1`; if (strpos($logCheckMMDVMHostDMRLogin, "success")) { return 0; } elseif (strpos($logCheckMMDVMHostDMRLogin, "fail")) { return 1; } else { return 0; } } } elseif ($dmrDaemon == "DMRGateway") { if (file_exists("/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log")) { $logPath = "/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log"; $logCheckDMRGatewayDMRLogin = `tail -n 5 $logPath | awk '/master/ && /successfully/ || /master/ && /failed/' | tail -n 1`; if (strpos($logCheckDMRGatewayDMRLogin, "success")) { return 0; } elseif (strpos($logCheckDMRGatewayDMRLogin, "fail")) { return 1; } else { return 0; } } } else { return 0; } } function showMode($mode, $mmdvmconfigs) { // shows if mode is enabled or not. if (getEnabled($mode, $mmdvmconfigs) == 1) { if ($mode == "D-Star Network") { if (isProcessRunning("ircddbgatewayd")) { echo ""; } else { echo ""; } } elseif ($mode == "System Fusion Network") { if (isProcessRunning("YSFGateway")) { echo ""; } else { echo ""; } } elseif ($mode == "P25 Network") { if (isProcessRunning("P25Gateway")) { echo ""; } else { echo ""; } } elseif ($mode == "NXDN Network") { if (isProcessRunning("NXDNGateway")) { echo ""; } else { echo ""; } } elseif ($mode == "M17 Network") { if (isProcessRunning("M17Gateway")) { echo ""; } else { echo ""; } } elseif ($mode == "POCSAG Network") { if (isProcessRunning("DAPNETGateway")) { echo ""; } else { echo ""; } } elseif ($mode == "DMR Network") { if (getConfigItem("DMR Network", "Address", $mmdvmconfigs) == '127.0.0.1') { if (isProcessRunning("DMRGateway")) { if (checkDMRLogin("DMRGateway") > 0) { echo ""; } else { echo ""; } } else { echo ""; } } else { if (isProcessRunning("MMDVMHost")) { if (checkDMRLogin("MMDVMHost") > 0) { echo ""; } else { echo ""; } } else { echo ""; } } } else { if ($mode == "D-Star" || $mode == "DMR" || $mode == "System Fusion" || $mode == "P25" || $mode == "NXDN" || $mode == "M17" || $mode == "FM" || $mode == "POCSAG") { if (isProcessRunning("MMDVMHost")) { echo ""; } else { echo ""; } } } } elseif ( ($mode == "YSF XMode") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { if ( (isProcessRunning("MMDVMHost")) && (isProcessRunning("YSF2DMR") || isProcessRunning("YSF2NXDN") || isProcessRunning("YSF2P25")) ) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "DMR XMode") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { if ( (isProcessRunning("MMDVMHost")) && (isProcessRunning("DMR2YSF") || isProcessRunning("DMR2NXDN")) ) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "YSF2DMR Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { if (isProcessRunning("YSF2DMR")) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "YSF2NXDN Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { if (isProcessRunning("YSF2NXDN")) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "YSF2P25 Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { if (isProcessRunning("YSF2P25")) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "DMR2NXDN Network") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { if (isProcessRunning("DMR2NXDN")) { echo ""; } else { echo "\">"; } } elseif ( ($mode == "DMR2YSF Network") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { if (isProcessRunning("DMR2YSF")) { echo ""; } else { echo "\">"; } } else { echo "\">"; } $mode = str_replace("System Fusion", "YSF", $mode); $mode = str_replace("Network", "Net", $mode); if (strpos($mode, 'YSF2') > -1) { $mode = str_replace(" Net", "", $mode); } if (strpos($mode, 'DMR2') > -1) { $mode = str_replace(" Net", "", $mode); } echo $mode."\n"; } function getMMDVMLog() { // Last 250 dashboard-relevant lines from today's MMDVM log, // falling back to yesterday's tail if today is sparse (just- // past-midnight case). The egrep|sed|tail shell pipeline that // used to live here forked three processes per call AND // streamed the whole day's log through them on every poll — // see pistar_log_tail_match() for the rationale. $logToday = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; $logYstday = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(from|end|watchdog|lost|slow data)/'; $excR = '/(CSBK|overflow|Downlink)/'; $logLines1 = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, $excR, 250) : array(); $logLines2 = array(); if (sizeof($logLines1) < 250 && file_exists($logYstday)) { $logLines2 = pistar_log_tail_match($logYstday, $matchR, $excR, 250); } // Preserve the original union-by-key + final tail-slice // semantics: today's matches take the low indices, yesterday's // fill any higher slots up to 250 total. $logLines = $logLines1 + $logLines2; return array_slice($logLines, -250); } function getYSFGatewayLog() { // Last 1 link-state line from today's YSFGateway log, falling // back to yesterday if today has none. $logToday = YSFGATEWAYLOGPATH."/".YSFGATEWAYLOGPREFIX."-".gmdate("Y-m-d").".log"; $logYstday = YSFGATEWAYLOGPATH."/".YSFGATEWAYLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(onnection to|onnect to|inked|isconnect|Opening YSF network)/'; $excR = '/(Linked to MMDVM|Link successful to MMDVM|\*Link)/'; $logLines = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, $excR, 1) : array(); if (sizeof($logLines) === 0 && file_exists($logYstday)) { $logLines = pistar_log_tail_match($logYstday, $matchR, $excR, 1); } return $logLines; } function getP25GatewayLog() { // Last 1 link-state line from today's P25Gateway log, falling // back to yesterday if today has none. The first space- // delimited field (severity letter) is stripped to match the // original `cut -d" " -f2-` step. $logToday = P25GATEWAYLOGPATH."/".P25GATEWAYLOGPREFIX."-".gmdate("Y-m-d").".log"; $logYstday = P25GATEWAYLOGPATH."/".P25GATEWAYLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(ink|Starting|witched)/'; $logLines = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, '', 1, true) : array(); if (sizeof($logLines) === 0 && file_exists($logYstday)) { $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); } return $logLines; } function getNXDNGatewayLog() { // Last 1 link-state line from today's NXDNGateway log; see // getP25GatewayLog for the full rationale (same shape). $logToday = "/var/log/pi-star/NXDNGateway-".gmdate("Y-m-d").".log"; $logYstday = "/var/log/pi-star/NXDNGateway-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(ink|Starting|witched)/'; $logLines = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, '', 1, true) : array(); if (sizeof($logLines) === 0 && file_exists($logYstday)) { $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); } return $logLines; } function getM17GatewayLog() { // Last 1 link-state line from today's M17Gateway log; see // getP25GatewayLog for the full rationale (same shape). $logToday = "/var/log/pi-star/M17Gateway-".gmdate("Y-m-d").".log"; $logYstday = "/var/log/pi-star/M17Gateway-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(ink|Starting|witched)/'; $logLines = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, '', 1, true) : array(); if (sizeof($logLines) === 0 && file_exists($logYstday)) { $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); } return $logLines; } function getDAPNETGatewayLog() { // Last 20 "Sending message" lines from today's DAPNETGateway // log (or yesterday's if today is silent), reversed so the // most recent message appears first. The original pipeline // ended with `tail -n 20 | tac`; the helper does both. $logToday = "/var/log/pi-star/DAPNETGateway-".gmdate("Y-m-d").".log"; $logYstday = "/var/log/pi-star/DAPNETGateway-".gmdate("Y-m-d", time() - 86340).".log"; $matchR = '/^M.*(Sending message)/'; $logLines = file_exists($logToday) ? pistar_log_tail_match($logToday, $matchR, '', 20, true, true) : array(); if (sizeof($logLines) === 0 && file_exists($logYstday)) { $logLines = pistar_log_tail_match($logYstday, $matchR, '', 20, true, true); } return $logLines; } // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: DVMEGA HR3.14 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS-ADF7021 20170414 (D-Star/DMR/YSF/P25) (Build: 20:16:25 May 20 2017) // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM 20170206 TCXO (D-Star/DMR/System Fusion/P25/RSSI/CW Id) // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: ZUMspot ADF7021 v1.0.0 20170728 (DStar/DMR/YSF/P25) GitID #c16dd5a // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_MDO ADF7021 v1.0.1 20170826 (DStar/DMR/YSF/P25) GitID #BD7KLE // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: ZUMspot-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS_Hat-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS_Dual_Hat-v1.3.6 20180521 dual ADF7021 FW by CA6JAU GitID #bd6217a // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: D2RG_MMDVM_HS-v1.4.17 20190529 14.7456MHz ADF7021 FW by CA6JAU GitID #cc451c4 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano_hotSPOT-v1.3.3 20180224 ADF7021 FW by CA6JAU GitID #62323e7 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano-Spot-v1.3.3 20180224 ADF7021 FW by CA6JAU GitID #62323e7 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano_DV-v1.4.3 20180716 12.2880MHz ADF7021 FW by CA6JAU GitID #6729d23 // I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: SkyBridge-v1.5.2 20201108 14.7456MHz ADF7021 FW by CA6JAU GitID #89daa20 function getDVModemFirmware() { $logMMDVMNow = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; $logMMDVMPrevious = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; $logSearchString = "MMDVM protocol version"; $logLine = ''; $modemFirmware = ''; $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMNow." | tail -1"); if (!$logLine) { $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMPrevious." | tail -1"); } if ($logLine) { if (strpos($logLine, 'DVMEGA')) { $modemFirmware = substr($logLine, 67, 15); } if (strpos($logLine, 'description: MMDVM_HS')) { $modemFirmware = "MMDVM_HS:".ltrim(substr($logLine, 84, 8), 'v'); } if (strpos($logLine, 'description: MMDVM ')) { $modemFirmware = "MMDVM:".substr($logLine, 73, 8); } if (strpos($logLine, 'description: ZUMspot ')) { $modemFirmware = "ZUMspot:".strtok(substr($logLine, 83, 12), ' '); } if (strpos($logLine, 'description: MMDVM_MDO ')) { $modemFirmware = "MMDVM_MDO:".ltrim(strtok(substr($logLine, 85, 12), ' '), 'v'); } if (strpos($logLine, 'description: ZUMspot-')) { $modemFirmware = "ZUMspot:".strtok(substr($logLine, 75, 12), ' '); } if (strpos($logLine, 'description: MMDVM_HS_Hat-')) { $modemFirmware = "HS_Hat:".strtok(substr($logLine, 80, 12), ' '); } if (strpos($logLine, 'description: MMDVM_HS_Dual_Hat-')) { $modemFirmware = "HS_Hat:".strtok(substr($logLine, 85, 12), ' '); } if (strpos($logLine, 'description: D2RG_MMDVM_HS-')) { $modemFirmware = "HS_Hat:".strtok(substr($logLine, 81, 12), ' '); } if (strpos($logLine, 'description: MMDVM_HS-')) { $modemFirmware = "MMDVM_HS:".ltrim(strtok(substr($logLine, 76, 12), ' '), 'v'); } if (strpos($logLine, 'description: Nano_hotSPOT-')) { $modemFirmware = "MMDVM_HS:".ltrim(strtok(substr($logLine, 80, 12), ' '), 'v'); } if (strpos($logLine, 'description: Nano-Spot-')) { $modemFirmware = "NanoSpot:".strtok(substr($logLine, 77, 12), ' '); } if (strpos($logLine, 'description: Nano_DV-')) { $modemFirmware = "NanoDV:".strtok(substr($logLine, 75, 12), ' '); } if (strpos($logLine, 'description: OpenGD77 Hotspot')) { $modemFirmware = "OpenGD77:".strtok(substr($logLine, 83, 12), ' '); } if (strpos($logLine, 'description: OpenGD77_HS ')) { $modemFirmware = "OpenGD77:".strtok(substr($logLine, 79, 12), ' '); } if (strpos($logLine, 'description: SkyBridge-')) { $modemFirmware = "SkyBrg:".strtok(substr($logLine, 77, 12), ' '); } } return $modemFirmware; } function getDVModemTCXOFreq() { $logMMDVMNow = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; $logMMDVMPrevious = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; $logSearchString = "MMDVM protocol version"; $logLine = ''; $modemTCXOFreq = ''; $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMNow." | tail -1"); if (!$logLine) { $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMPrevious." | tail -1"); } if ($logLine) { if ((strpos($logLine, 'Mhz') !== false) or (strpos($logLine, 'MHz') !== false)) { $modemTCXOFreq = $logLine; $modemTCXOFreq = preg_replace('/.*(\d{2}\.\d{3,4}\s{0,1}M[Hh]z).*/', "$1", $modemTCXOFreq); $modemTCXOFreq = str_replace("MHz"," MHz", $modemTCXOFreq); } } return $modemTCXOFreq; } // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // M: 2000-00-00 00:00:00.000 Mode set to D-Star // M: 2000-00-00 00:00:00.000 D-Star, received RF header from M1ABC /ABCD to CQCQCQ // M: 2000-00-00 00:00:00.000 D-Star, received RF end of transmission from M1ABC /ABCD to CQCQCQ , 00.0 seconds, BER: 0.0%, RSSI: -43/-43/-43 dBm // M: 2000-00-00 00:00:00.000 D-Star, received network header from M1ABC /ABCD to CQCQCQ via REF000 A // M: 2000-00-00 00:00:00.000 D-Star, received network end of transmission from M1ABC /ABCD to CQCQCQ , 0.0 seconds, 0% packet loss, BER: 0.0% // M: 2000-00-00 00:00:00.000 D-Star, starting fast data mode // M: 2000-00-00 00:00:00.000 D-Star, leaving fast data mode // M: 2000-00-00 00:00:00.000 D-Star, invalid slow data header // M: 2000-00-00 00:00:00.000 DMR Slot 2, received network voice header from M1ABC to TG 1 // M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF voice header from M1ABC to 5000 // M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF end of voice transmission, 1.8 seconds, BER: 3.9% // M: 2000-00-00 00:00:00.000 DMR Slot 2, received network end of voice transmission from M1ABC to TG 2, 0.0 seconds, 0% packet loss, BER: 0.0% // M: 2000-00-00 00:00:00.000 DMR Slot 2, RF voice transmission lost, 1.1 seconds, BER: 6.5% // M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF CSBK Preamble CSBK (1 to follow) from M1ABC to TG 1 // M: 2000-00-00 00:00:00.000 DMR Slot 2, received network Data Preamble VSBK (11 to follow) from 123456 to TG 123456 // M: 2000-00-00 00:00:00.000 DMR Talker Alias (Data Format 1, Received 24/24 char): 'Hide the bottle from Ont' // M: 2000-00-00 00:00:00.000 0000: 07 00 20 4F 6E 74 00 00 00 *.. Ont...* // M: 2000-00-00 00:00:00.000 DMR Slot 2, Embedded Talker Alias Block 3 // M: 2000-00-00 00:00:00.000 DMR Slot 2, received network data header from 123999 to M1ABC, 0 blocks // M: 2000-00-00 00:00:00.000 DMR Slot 2, ended network data transmission from 123999 to M1ABC // M: 2000-00-00 00:00:00.000 P25, received RF transmission from M1ABC to TG 10200 // M: 2000-00-00 00:00:00.000 Debug: P25RX: pos/neg/centre/threshold 106 -105 0 106 // M: 2000-00-00 00:00:00.000 Debug: P25RX: sync found in Ldu pos/centre/threshold 3986 9 104 // M: 2000-00-00 00:00:00.000 Debug: P25RX: pos/neg/centre/threshold 267 -222 22 245 // M: 2000-00-00 00:00:00.000 Debug: P25RX: sync found in Ldu pos/centre/threshold 3986 10 112 // M: 2000-00-00 00:00:00.000 P25, received RF end of transmission, 0.4 seconds, BER: 0.0% // M: 2000-00-00 00:00:00.000 P25, received network transmission from 10999 to TG 10200 // M: 2000-00-00 00:00:00.000 P25, network end of transmission, 1.8 seconds, 0% packet loss // M: 2000-00-00 00:00:00.000 YSF, received RF data from MW0MWZ to ALL // M: 2000-00-00 00:00:00.000 YSF, received RF end of transmission, 5.1 seconds, BER: 3.8% // M: 2000-00-00 00:00:00.000 YSF, received network data from M1ABC to ALL at MB6IBK // M: 2000-00-00 00:00:00.000 YSF, network watchdog has expired, 5.0 seconds, 0% packet loss, BER: 0.0% // M: 2000-00-00 00:00:00.000 NXDN, received RF transmission from MW0MWZ to TG 65000 // M: 2000-00-00 00:00:00.000 Debug: NXDNRX: pos/neg/centre/threshold 106 -105 0 106 // M: 2000-00-00 00:00:00.000 Debug: NXDNRX: sync found in Ldu pos/centre/threshold 3986 9 104 // M: 2000-00-00 00:00:00.000 Debug: NXDNRX: pos/neg/centre/threshold 267 -222 22 245 // M: 2000-00-00 00:00:00.000 Debug: NXDNRX: sync found in Ldu pos/centre/threshold 3986 10 112 // M: 2000-00-00 00:00:00.000 NXDN, received RF end of transmission, 0.4 seconds, BER: 0.0% // M: 2000-00-00 00:00:00.000 NXDN, received network transmission from 10999 to TG 65000 // M: 2000-00-00 00:00:00.000 NXDN, network end of transmission, 1.8 seconds, 0% packet loss // M: 2000-00-00 00:00:00.000 M17, received RF late entry voice transmission from M1ABC to INFO // M: 2000-00-00 00:00:00.000 M17, received RF end of transmission from M1ABC to INFO, 2.1 seconds, BER: 0.2%, RSSI: -60/-60/-60 dBm // M: 2000-00-00 00:00:00.000 M17, received network voice transmission from M1ABC to ECHO // M: 2000-00-00 00:00:00.000 M17, received network end of transmission from M1ABC to ECHO, 0.0 seconds // M: 2000-00-00 00:00:00.000 POCSAG, transmitted 1 frame(s) of data from 1 message(s) // M: 2000-00-00 00:00:00.000 Mode set to Idle function getHeardList($logLines) { //array_multisort($logLines,SORT_DESC); $heardList = array(); $ts1duration = ""; $ts1loss = ""; $ts1ber = ""; $ts1rssi = ""; $ts2duration = ""; $ts2loss = ""; $ts2ber = ""; $ts2rssi = ""; $dstarduration = ""; $dstarloss = ""; $dstarber = ""; $dstarrssi = ""; $ysfduration = ""; $ysfloss = ""; $ysfber = ""; $ysfrssi = ""; $p25duration = ""; $p25loss = ""; $p25ber = ""; $p25rssi = ""; $nxdnduration = ""; $nxdnloss = ""; $nxdnber = ""; $nxdnrssi = ""; $pocsagduration = ""; foreach ($logLines as $logLine) { $duration = ""; $loss = ""; $ber = ""; $rssi = ""; //removing invalid lines if(strpos($logLine,"BS_Dwn_Act")) { continue; } else if(strpos($logLine,"invalid access")) { continue; } else if(strpos($logLine,"received RF header for wrong repeater")) { continue; } else if(strpos($logLine,"unable to decode the network CSBK")) { continue; } else if(strpos($logLine,"overflow in the DMR slot RF queue")) { continue; } else if(strpos($logLine,"overflow in the M17 RF queue")) { continue; } else if(strpos($logLine,"non repeater RF header received")) { continue; } else if(strpos($logLine,"Embedded Talker Alias")) { continue; } else if(strpos($logLine,"DMR Talker Alias")) { continue; } else if(strpos($logLine,", Talker Alias ")) { continue; } else if(strpos($logLine,", text Data: ")) { continue; } else if(strpos($logLine,"CSBK Preamble")) { continue; } else if(strpos($logLine,"Preamble CSBK")) { continue; } if(strpos($logLine, "end of") || strpos($logLine, "watchdog has expired") || strpos($logLine, "invalid slow data header") || strpos($logLine, "ended RF data") || strpos($logLine, "d network data") || strpos($logLine, "RF user has timed out") || strpos($logLine, "transmission lost") || strpos($logLine, "POCSAG")) { $lineTokens = explode(", ",$logLine); if (array_key_exists(2,$lineTokens)) { $duration = strtok($lineTokens[2], " "); } if (array_key_exists(3,$lineTokens)) { $loss = $lineTokens[3]; } // The change to this code was causing all FCS traffic to always show TOut rather than the timer. // This version should still show time-out when needed, AND show the time if it exists. if (strpos($logLine,"RF user has timed out") || strpos($logLine,"watchdog has expired") || strpos($logLine, "invalid slow data header")) { if (array_key_exists(2,$lineTokens) && strpos($lineTokens[2], "seconds")) { $duration = strtok($lineTokens[2], " "); } else { $duration = "TOut"; } $ber = "??%"; } // if RF-Packet with no BER reported (e.g. YSF Wires-X commands) then RSSI is in LOSS position if (startsWith($loss,"RSSI")) { $lineTokens[4] = $loss; //move RSSI to the position expected on code below $loss = 'BER: ??%'; } // if RF-Packet, no LOSS would be reported, so BER is in LOSS position if (startsWith($loss,"BER")) { $ber = substr($loss, 5); $loss = "0%"; if (array_key_exists(4,$lineTokens) && startsWith($lineTokens[4],"RSSI")) { $rssi = substr($lineTokens[4], 6); $dBraw = substr($rssi, strrpos($rssi,'/')+1); //average only $relint = intval($dBraw) + 93; $signal = round(($relint/6)+9, 0); if ($signal < 0) $signal = 0; if ($signal > 9) $signal = 9; if ($relint > 0) { $rssi = "S{$signal}+{$relint}dB ({$dBraw})"; } else { $rssi = "S{$signal} ({$dBraw})"; } } } else { $loss = strtok($loss, " "); if (array_key_exists(4,$lineTokens)) { $ber = substr($lineTokens[4], 5); } } if (strpos($logLine,"ended RF data") || strpos($logLine,"d network data")) { switch (substr($logLine, 27, strpos($logLine,",") - 27)) { case "DMR Slot 1": $ts1duration = "DMR Data"; break; case "DMR Slot 2": $ts2duration = "DMR Data"; break; } } else { switch (substr($logLine, 27, strpos($logLine,",") - 27)) { case "D-Star": $dstarduration = $duration; $dstarloss = $loss; $dstarber = $ber; $dstarrssi = $rssi; break; case "DMR Slot 1": $ts1duration = $duration; $ts1loss = $loss; $ts1ber = $ber; $ts1rssi = $rssi; break; case "DMR Slot 2": $ts2duration = $duration; $ts2loss = $loss; $ts2ber = $ber; $ts2rssi = $rssi; break; case "YSF": $ysfduration = $duration; $ysfloss = $loss; $ysfber = $ber; $ysfrssi = $rssi; break; case "P25": $p25duration = $duration; $p25loss = $loss; $p25ber = $ber; $p25rssi = $rssi; break; case "NXDN": $nxdnduration = $duration; $nxdnloss = $loss; $nxdnber = $ber; $nxdnrssi = $rssi; break; case "M17": $m17duration = $duration; $m17loss = $loss; $m17ber = $ber; $m17rssi = $rssi; break; case "POCSAG": $pocsagduration = "POCSAG Data"; break; } } } $timestamp = substr($logLine, 3, 19); $mode = substr($logLine, 27, strpos($logLine,",") - 27); $callsign2 = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"to") - strpos($logLine,"from") - 6); $callsign = $callsign2; if (strpos($callsign2,"/") > 0) { $callsign = substr($callsign2, 0, strpos($callsign2,"/")); } $callsign = trim($callsign); $id =""; if ($mode == "D-Star") { $id = substr($callsign2, strpos($callsign2,"/") + 1); } $target = trim(substr($logLine, strpos($logLine, "to") + 3)); // Handle more verbose logging from MMDVMHost if (strpos($target,",") !== 'false') { $target = explode(",", $target)[0]; } $source = "RF"; if (strpos($logLine,"network") > 0 || strpos($logLine,"POCSAG") > 0) { $source = "Net"; } switch ($mode) { case "D-Star": $duration = $dstarduration; $loss = $dstarloss; $ber = $dstarber; $rssi = $dstarrssi; break; case "DMR Slot 1": $duration = $ts1duration; $loss = $ts1loss; $ber = $ts1ber; $rssi = $ts1rssi; break; case "DMR Slot 2": $duration = $ts2duration; $loss = $ts2loss; $ber = $ts2ber; $rssi = $ts2rssi; break; case "YSF": $duration = $ysfduration; $loss = $ysfloss; $ber = $ysfber; $rssi = $ysfrssi; $target = preg_replace('!\s+!', ' ', $target); break; case "P25": if ($source == "Net" && $target == "TG 10") {$callsign = "PARROT";} if ($source == "Net" && $callsign == "10999") {$callsign = "MMDVM";} $duration = $p25duration; $loss = $p25loss; $ber = $p25ber; $rssi = $p25rssi; break; case "NXDN": if ($source == "Net" && $target == "TG 10") {$callsign = "PARROT";} $duration = $nxdnduration; $loss = $nxdnloss; $ber = $nxdnber; $rssi = $nxdnrssi; break; case "M17": $duration = $m17duration; $loss = $m17loss; $ber = $m17ber; $rssi = $m17rssi; break; case "POCSAG": $callsign = "DAPNET"; $target = "DAPNET User"; $duration = "POCSAG Data"; break; } // Callsign or ID should be less than 11 chars long, otherwise it could be errorneous if ( strlen($callsign) < 11 ) { array_push($heardList, array($timestamp, $mode, $callsign, $id, $target, $source, $duration, $loss, $ber, $rssi)); $duration = ""; $loss =""; $ber = ""; $rssi = ""; } } return $heardList; } function getLastHeard($logLines) { //returns last heard list from log $lastHeard = array(); $heardCalls = array(); $heardList = getHeardList($logLines); $counter = 0; foreach ($heardList as $listElem) { if ( ($listElem[1] == "D-Star") || ($listElem[1] == "YSF") || ($listElem[1] == "P25") || ($listElem[1] == "NXDN") || ($listElem[1] == "M17") || ($listElem[1] == "POCSAG") || (startsWith($listElem[1], "DMR")) ) { $callUuid = $listElem[2]."#".$listElem[1].$listElem[3].$listElem[5]; if(!(array_search($callUuid, $heardCalls) > -1)) { array_push($heardCalls, $callUuid); array_push($lastHeard, $listElem); $counter++; } } } return $lastHeard; } function getActualMode($metaLastHeard, $mmdvmconfigs) { // returns mode of repeater actual working in $utc_tz = new DateTimeZone('UTC'); $local_tz = new DateTimeZone(date_default_timezone_get ()); $listElem = $metaLastHeard[0]; $timestamp = new DateTime($listElem[0], $utc_tz); $timestamp->setTimeZone($local_tz); $mode = $listElem[1]; if (startsWith($mode, "DMR")) { $mode = "DMR"; } $now = new DateTime(); $hangtime = getConfigItem("General", "ModeHang", $mmdvmconfigs); if ($hangtime != "") { $timestamp->add(new DateInterval('PT' . $hangtime . 'S')); } else { $source = $listElem[5]; if ($source == "RF" && $mode === "D-Star") { $hangtime = getConfigItem("D-Star", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "D-Star") { $hangtime = getConfigItem("D-Star Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "DMR") { $hangtime = getConfigItem("DMR", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "DMR") { $hangtime = getConfigItem("DMR Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "YSF") { $hangtime = getConfigItem("System Fusion", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "YSF") { $hangtime = getConfigItem("System Fusion Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "P25") { $hangtime = getConfigItem("P25", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "P25") { $hangtime = getConfigItem("P25 Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "NXDN") { $hangtime = getConfigItem("NXDN", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "NXDN") { $hangtime = getConfigItem("NXDN Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "M17") { $hangtime = getConfigItem("M17", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "M17") { $hangtime = getConfigItem("M17 Network", "ModeHang", $mmdvmconfigs); } else if ($source == "RF" && $mode === "FM") { $hangtime = getConfigItem("FM", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "FM") { $hangtime = getConfigItem("FM Network", "ModeHang", $mmdvmconfigs); } else if ($source == "Net" && $mode === "POCSAG") { $hangtime = getConfigItem("POCSAG Network", "ModeHang", $mmdvmconfigs); } else { $hangtime = getConfigItem("General", "RFModeHang", $mmdvmconfigs); } $timestamp->add(new DateInterval('PT' . $hangtime . 'S')); } if ($listElem[6] != null) { //if terminated, hangtime counts after end of transmission $seconds = is_numeric($listElem[6]) ? ceil((float)$listElem[6]) : 0; $timestamp->add(new DateInterval('PT' . $seconds . 'S')); //$timestamp->add(new DateInterval('PT' . ceil($listElem[6]) . 'S')); } else { //if not terminated, always return mode return $mode; } if ($now->format('U') > $timestamp->format('U')) { return "idle"; } else { return $mode; } } function getDSTARLinks() { // Get our current configured callsign / module $mmdvmconfigs = getMMDVMConfig(); $dstarCallsign = str_pad(getConfigItem("General", "Callsign", $mmdvmconfigs), 7, " ", STR_PAD_RIGHT).getConfigItem("D-Star", "Module", $mmdvmconfigs); // returns link-states of all D-Star-modules if (filesize(LINKLOGPATH."/Links.log") == 0) { return "Not Linked"; } if ($linkLog = fopen(LINKLOGPATH."/Links.log",'r')) { while ($linkLine = fgets($linkLog)) { $linkDate = " "; $protocol = " "; $linkType = " "; $linkSource = " "; $linkDest = " "; $linkDir = " "; // Reflector-Link, sample: // 2011-09-22 02:15:06: DExtra link - Type: Repeater Rptr: DB0LJ B Refl: XRF023 A Dir: Outgoing // 2012-04-03 08:40:07: DPlus link - Type: Dongle Rptr: DB0ERK B Refl: REF006 D Dir: Outgoing // 2012-04-03 08:40:07: DCS link - Type: Repeater Rptr: DB0ERK C Refl: DCS001 C Dir: Outgoing if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: (.{8})/',$linkLine,$linx) > 0){ $linkDate = $linx[1][0]; $protocol = $linx[2][0]; $linkType = $linx[3][0]; $linkSource = $linx[4][0]; $linkDest = $linx[5][0]; $linkDir = $linx[6][0]; if ($linkSource != $dstarCallsign) { $linkDate = " "; $protocol = " "; $linkType = " "; $linkSource = " "; $linkDest = " "; $linkDir = " "; } } // CCS-Link, sample: // 2013-03-30 23:21:53: CCS link - Rptr: PE1AGO C Remote: PE1KZU Dir: Incoming if(preg_match_all('/^(.{19}).*(CC[A-Za-z]*).*Rptr: (.{8}).*Remote: (.{8}).*Dir: (.{8})/',$linkLine,$linx) > 0){ $linkDate = $linx[1][0]; $protocol = $linx[2][0]; $linkType = $linx[2][0]; $linkSource = $linx[3][0]; $linkDest = $linx[4][0]; $linkDir = $linx[5][0]; } // Dongle-Link, sample: // 2011-09-24 07:26:59: DPlus link - Type: Dongle User: DC1PIA Dir: Incoming // 2012-03-14 21:32:18: DPlus link - Type: Dongle User: DC1PIA Dir: Incoming if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*User: (.{6,8}).*Dir: (.*)$/',$linkLine,$linx) > 0){ $linkDate = $linx[1][0]; $protocol = $linx[2][0]; $linkType = $linx[3][0]; $linkSource = " "; $linkDest = $linx[4][0]; $linkDir = $linx[5][0]; } if (strtolower(substr($linkDir, 0, 2)) == "in") { $linkDir = "In"; } if (strtolower(substr($linkDir, 0, 3)) == "out") { $linkDir = "Out"; } $out = $linkDest." ".$protocol."/".$linkDir; } } fclose($linkLog); return $out; } function getActualLink($logLines, $mode) { // returns actual link state of specific mode //M: 2016-05-02 07:04:10.504 D-Star link status set to "Verlinkt zu DCS002 S" //M: 2016-04-03 16:16:18.638 DMR Slot 2, received network voice header from 4000 to 2625094 //M: 2016-04-03 19:30:03.099 DMR Slot 2, received network voice header from 4020 to 2625094 //M: 2017-09-03 08:10:42.862 DMR Slot 2, received network data header from M6JQD to TG 9, 5 blocks switch ($mode) { case "D-Star": if (isProcessRunning(IRCDDBGATEWAY)) { return getDSTARLinks(); } else { return "No D-Star Network"; } break; case "DMR Slot 1": foreach ($logLines as $logLine) { if(strpos($logLine,"unable to decode the network CSBK")) { continue; } else if(substr($logLine, 27, strpos($logLine,",") - 27) == "DMR Slot 1") { $to = ""; if (strpos($logLine,"to")) { $to = trim(substr($logLine, strpos($logLine,"to") + 3)); } if ($to !== "") { if (substr($to, 0, 3) !== 'TG ') { continue; } if ($to === "TG 4000") { return "No TG"; } if (strpos($to, ',') !== false) { $to = substr($to, 0, strpos($to, ',')); } return $to; } } } return "No TG"; break; case "DMR Slot 2": foreach ($logLines as $logLine) { if(strpos($logLine,"unable to decode the network CSBK")) { continue; } else if(substr($logLine, 27, strpos($logLine,",") - 27) == "DMR Slot 2") { $to = ""; if (strpos($logLine,"to")) { $to = trim(substr($logLine, strpos($logLine,"to") + 3)); } if ($to !== "") { if (substr($to, 0, 3) !== 'TG ') { continue; } if ($to === "TG 4000") { return "No TG"; } if (strpos($to, ',') !== false) { $to = substr($to, 0, strpos($to, ',')); } return $to; } } } return "No TG"; break; case "YSF": // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // M: 0000-00-00 00:00:00.000 Connect to 62829 has been requested by M1ABC // M: 0000-00-00 00:00:00.000 Automatic connection to 62829 // New YSFGateway Format // M: 0000-00-00 00:00:00.000 Opening YSF network connection // M: 0000-00-00 00:00:00.000 Automatic (re-)connection to 16710 - "GB SOUTH WEST " // M: 0000-00-00 00:00:00.000 Automatic (re-)connection to FCS00290 // M: 0000-00-00 00:00:00.000 Linked to GB SOUTH WEST // M: 0000-00-00 00:00:00.000 Linked to FCS002-90 // M: 0000-00-00 00:00:00.000 Disconnect via DTMF has been requested by M1ABC // M: 0000-00-00 00:00:00.000 Connect to 00003 - "YSF2NXDN " has been requested by M1ABC // M: 0000-00-00 00:00:00.000 Link has failed, polls lost if (isProcessRunning("YSFGateway")) { $to = ""; foreach($logLines as $logLine) { if ( (strpos($logLine,"Linked to")) && (!strpos($logLine,"Linked to MMDVM")) ) { $to = trim(substr($logLine, 37, 16)); if (substr($to, 0, 3) === "FCS") { $to = str_replace(' ', '', str_replace('-', '', $to)); } } if (strpos($logLine,"Automatic (re-)connection to")) { if (strpos($logLine,"Automatic (re-)connection to FCS")) { $to = substr($logLine, 56, 8); } else { $to = substr($logLine, 56, 5); } } if (strpos($logLine,"Connect to")) { $to = substr($logLine, 38, 5); } if (strpos($logLine,"Automatic connection to")) { $to = substr($logLine, 51, 5); } if (strpos($logLine,"Disconnect via DTMF")) { $to = "Not Linked"; } if (strpos($logLine,"Opening YSF network connection")) { $to = "Not Linked"; } if (strpos($logLine,"Link has failed")) { $to = "Not Linked"; } if (strpos($logLine,"DISCONNECT Reply")) { $to = "Not Linked"; } if ($to !== "") { return $to; } } return "Not Linked"; } else { return "Service Not Started"; } break; case "NXDN": // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // 2000-01-01 00:00:00.000 Linked at startup to reflector 10100 // 2000-01-01 00:00:00.000 Unlinked from reflector 10100 by M1ABC // 2000-01-01 00:00:00.000 Linked to reflector 10100 by M1ABC // 2000-01-01 00:00:00.000 No response from 10200, unlinking // 2000-01-01 00:00:00.000 Switched to reflector 10100 by remote command // 2000-01-01 00:00:00.000 Unlinking from 10100 due to inactivity // 2000-01-01 00:00:00.000 Statically linked to reflector 10100 if (isProcessRunning("NXDNGateway")) { foreach($logLines as $logLine) { $to = ""; if (strpos($logLine,"Linked to")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 44, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Linked at start")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Statically linked to reflector")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Switched to reflector")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 46, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Starting NXDNGateway")) { return "Not Linked"; } if (strpos($logLine,"unlinking")) { return "Not Linked"; } if (strpos($logLine,"Unlinked from")) { return "Not Linked"; } if (strpos($logLine,"Unlinking from")) { return "Not Linked"; } } return "Not Linked"; } else { return "Service Not Started"; } break; case "M17": // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 if (isProcessRunning("M17Gateway")) { foreach($logLines as $logLine) { if(preg_match_all('/Linked .* reflector (M17-.{3} [A-Z])/',$logLine,$linx) > 0){ return $linx[1][0]; } if (strpos($logLine,"Starting M17Gateway")) { return "Not Linked"; } if (strpos($logLine,"unlinking")) { return "Not Linked"; } if (strpos($logLine,"Unlinking")) { return "Not Linked"; } if (strpos($logLine,"Unlinked")) { return "Not Linked"; } } return "Not Linked"; } else { return "Service Not Started"; } break; case "P25": // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // 2000-01-01 00:00:00.000 Linked at startup to reflector 10100 // 2000-01-01 00:00:00.000 Unlinked from reflector 10100 by M1ABC // 2000-01-01 00:00:00.000 Linked to reflector 10100 by M1ABC // 2000-01-01 00:00:00.000 No response from 10100, unlinking // 2000-01-01 00:00:00.000 Switched to reflector 10100 due to RF activity from 12345 // 2000-01-01 00:00:00.000 Unlinking from reflector 10100 by 12345 // 2000-01-01 00:00:00.000 Switched to reflector 10100 by remote command if (isProcessRunning("P25Gateway")) { foreach($logLines as $logLine) { $to = ""; if (strpos($logLine,"Linked to")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 44, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Linked at startup to")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Statically linked to reflector")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Switched to reflector")) { $to = preg_replace('/[^0-9]/', '', substr($logLine, 46, 5)); $to = preg_replace('/[^0-9]/', '', $to); return "TG ".$to; } if (strpos($logLine,"Starting P25Gateway")) { return "Not Linked"; } if (strpos($logLine,"unlinking")) { return "Not Linked"; } if (strpos($logLine,"Unlinking")) { return "Not Linked"; } if (strpos($logLine,"Unlinked")) { return "Not Linked"; } } return "Not Linked"; } else { return "Service Not Started"; } break; } return "Service Not Started"; } function getActualReflector($logLines, $mode) { // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // M: 2016-05-02 07:04:10.504 D-Star link status set to "Verlinkt zu DCS002 S" // M: 2016-04-03 16:16:18.638 DMR Slot 2, received network voice header from 4000 to 2625094 // M: 2016-04-03 19:30:03.099 DMR Slot 2, received network voice header from 4020 to 2625094 foreach ($logLines as $logLine) { if (substr($logLine, 27, strpos($logLine,",") - 27) == $mode) { $from = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"to") - strpos($logLine,"from") - 6); if (strlen($from) == 4 && startsWith($from,"4")) { if ($from == "4000") { return "No Ref"; } else { return "Ref ".$from; } } } } return "No Ref"; } //Some basic inits $mmdvmconfigs = getMMDVMConfig(); if (!in_array($_SERVER["PHP_SELF"],array('/mmdvmhost/bm_links.php','/mmdvmhost/bm_manager.php'),true)) { $logLinesMMDVM = getMMDVMLog(); $reverseLogLinesMMDVM = $logLinesMMDVM; array_multisort($reverseLogLinesMMDVM,SORT_DESC); $lastHeard = getLastHeard($reverseLogLinesMMDVM); // Only need these in repeaterinfo.php if (strpos($_SERVER["PHP_SELF"], 'repeaterinfo.php') !== false || strpos($_SERVER["PHP_SELF"], 'index.php') !== false) { $logLinesYSFGateway = getYSFGatewayLog(); $reverseLogLinesYSFGateway = $logLinesYSFGateway; array_multisort($reverseLogLinesYSFGateway,SORT_DESC); $logLinesP25Gateway = getP25GatewayLog(); $logLinesNXDNGateway = getNXDNGatewayLog(); $logLinesM17Gateway = getM17GatewayLog(); } // Only need these in index.php if (strpos($_SERVER["PHP_SELF"], 'index.php') !== false || strpos($_SERVER["PHP_SELF"], 'pages.php') !== false) { $logLinesDAPNETGateway = getDAPNETGatewayLog(); } }