Browse Source

Initial Commit

server-live
Andrew Lynch 9 months ago
commit
85b4e1d96e
35 changed files with 2342 additions and 0 deletions
  1. +368
    -0
      index.html
  2. BIN
      nxdn-dash/DVSwitch.png
  3. +116
    -0
      nxdn-dash/LICENSE
  4. +15
    -0
      nxdn-dash/config/config.php
  5. BIN
      nxdn-dash/favicon.ico
  6. BIN
      nxdn-dash/favicontx.ico
  7. +42
    -0
      nxdn-dash/include/allheard.php
  8. +87
    -0
      nxdn-dash/include/disk.php
  9. +195
    -0
      nxdn-dash/include/functions.php
  10. +36
    -0
      nxdn-dash/include/gateways.php
  11. +12
    -0
      nxdn-dash/include/init.php
  12. +42
    -0
      nxdn-dash/include/lh.php
  13. +166
    -0
      nxdn-dash/include/sysinfo.php
  14. +89
    -0
      nxdn-dash/include/tools.php
  15. +80
    -0
      nxdn-dash/include/txinfo.php
  16. +72
    -0
      nxdn-dash/index.php
  17. +35
    -0
      nxdn-dash/txinfo.php
  18. +3
    -0
      nxdn-dash/version.php
  19. BIN
      p25-dash/DVSwitch.png
  20. +116
    -0
      p25-dash/LICENSE
  21. +16
    -0
      p25-dash/config/config.php
  22. BIN
      p25-dash/favicon.ico
  23. +42
    -0
      p25-dash/include/allheard.php
  24. +87
    -0
      p25-dash/include/disk.php
  25. +203
    -0
      p25-dash/include/functions.php
  26. +36
    -0
      p25-dash/include/gateways.php
  27. +12
    -0
      p25-dash/include/init.php
  28. +42
    -0
      p25-dash/include/lh.php
  29. +166
    -0
      p25-dash/include/sysinfo.php
  30. +89
    -0
      p25-dash/include/tools.php
  31. +61
    -0
      p25-dash/include/txinfo.php
  32. +75
    -0
      p25-dash/index.php
  33. +35
    -0
      p25-dash/txinfo.php
  34. +3
    -0
      p25-dash/version.php
  35. +1
    -0
      ysf-dash

+ 368
- 0
index.html View File

@@ -0,0 +1,368 @@

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Apache2 Debian Default Page: It works</title>
<style type="text/css" media="screen">
* {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}

body, html {
padding: 3px 3px 3px 3px;

background-color: #D8DBE2;

font-family: Verdana, sans-serif;
font-size: 11pt;
text-align: center;
}

div.main_page {
position: relative;
display: table;

width: 800px;

margin-bottom: 3px;
margin-left: auto;
margin-right: auto;
padding: 0px 0px 0px 0px;

border-width: 2px;
border-color: #212738;
border-style: solid;

background-color: #FFFFFF;

text-align: center;
}

div.page_header {
height: 99px;
width: 100%;

background-color: #F5F6F7;
}

div.page_header span {
margin: 15px 0px 0px 50px;

font-size: 180%;
font-weight: bold;
}

div.page_header img {
margin: 3px 0px 0px 40px;

border: 0px 0px 0px;
}

div.table_of_contents {
clear: left;

min-width: 200px;

margin: 3px 3px 3px 3px;

background-color: #FFFFFF;

text-align: left;
}

div.table_of_contents_item {
clear: left;

width: 100%;

margin: 4px 0px 0px 0px;

background-color: #FFFFFF;

color: #000000;
text-align: left;
}

div.table_of_contents_item a {
margin: 6px 0px 0px 6px;
}

div.content_section {
margin: 3px 3px 3px 3px;

background-color: #FFFFFF;

text-align: left;
}

div.content_section_text {
padding: 4px 8px 4px 8px;

color: #000000;
font-size: 100%;
}

div.content_section_text pre {
margin: 8px 0px 8px 0px;
padding: 8px 8px 8px 8px;

border-width: 1px;
border-style: dotted;
border-color: #000000;

background-color: #F5F6F7;

font-style: italic;
}

div.content_section_text p {
margin-bottom: 6px;
}

div.content_section_text ul, div.content_section_text li {
padding: 4px 8px 4px 16px;
}

div.section_header {
padding: 3px 6px 3px 6px;

background-color: #8E9CB2;

color: #FFFFFF;
font-weight: bold;
font-size: 112%;
text-align: center;
}

div.section_header_red {
background-color: #CD214F;
}

div.section_header_grey {
background-color: #9F9386;
}

.floating_element {
position: relative;
float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
text-decoration: none;
font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
color: #000000;
}

div.table_of_contents_item a:hover {
background-color: #000000;

color: #FFFFFF;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
background-color: #DCDFE6;

color: #000000;
}

div.content_section_text a:hover {
background-color: #000000;

color: #DCDFE6;
}

div.validator {
}
</style>
</head>
<body>
<div class="main_page">
<div class="page_header floating_element">
<img src="/icons/openlogo-75.png" alt="Debian Logo" class="floating_element"/>
<span class="floating_element">
Apache2 Debian Default Page
</span>
</div>
<!-- <div class="table_of_contents floating_element">
<div class="section_header section_header_grey">
TABLE OF CONTENTS
</div>
<div class="table_of_contents_item floating_element">
<a href="#about">About</a>
</div>
<div class="table_of_contents_item floating_element">
<a href="#changes">Changes</a>
</div>
<div class="table_of_contents_item floating_element">
<a href="#scope">Scope</a>
</div>
<div class="table_of_contents_item floating_element">
<a href="#files">Config files</a>
</div>
</div>
-->
<div class="content_section floating_element">


<div class="section_header section_header_red">
<div id="about"></div>
It works!
</div>
<div class="content_section_text">
<p>
This is the default welcome page used to test the correct
operation of the Apache2 server after installation on Debian systems.
If you can read this page, it means that the Apache HTTP server installed at
this site is working properly. You should <b>replace this file</b> (located at
<tt>/var/www/html/index.html</tt>) before continuing to operate your HTTP server.
</p>


<p>
If you are a normal user of this web site and don't know what this page is
about, this probably means that the site is currently unavailable due to
maintenance.
If the problem persists, please contact the site's administrator.
</p>

</div>
<div class="section_header">
<div id="changes"></div>
Configuration Overview
</div>
<div class="content_section_text">
<p>
Debian's Apache2 default configuration is different from the
upstream default configuration, and split into several files optimized for
interaction with Debian tools. The configuration system is
<b>fully documented in
/usr/share/doc/apache2/README.Debian.gz</b>. Refer to this for the full
documentation. Documentation for the web server itself can be
found by accessing the <a href="/manual">manual</a> if the <tt>apache2-doc</tt>
package was installed on this server.

</p>
<p>
The configuration layout for an Apache2 web server installation on Debian systems is as follows:
</p>
<pre>
/etc/apache2/
|-- apache2.conf
| `-- ports.conf
|-- mods-enabled
| |-- *.load
| `-- *.conf
|-- conf-enabled
| `-- *.conf
|-- sites-enabled
| `-- *.conf
</pre>
<ul>
<li>
<tt>apache2.conf</tt> is the main configuration
file. It puts the pieces together by including all remaining configuration
files when starting up the web server.
</li>

<li>
<tt>ports.conf</tt> is always included from the
main configuration file. It is used to determine the listening ports for
incoming connections, and this file can be customized anytime.
</li>

<li>
Configuration files in the <tt>mods-enabled/</tt>,
<tt>conf-enabled/</tt> and <tt>sites-enabled/</tt> directories contain
particular configuration snippets which manage modules, global configuration
fragments, or virtual host configurations, respectively.
</li>

<li>
They are activated by symlinking available
configuration files from their respective
*-available/ counterparts. These should be managed
by using our helpers
<tt>
a2enmod,
a2dismod,
</tt>
<tt>
a2ensite,
a2dissite,
</tt>
and
<tt>
a2enconf,
a2disconf
</tt>. See their respective man pages for detailed information.
</li>

<li>
The binary is called apache2. Due to the use of
environment variables, in the default configuration, apache2 needs to be
started/stopped with <tt>/etc/init.d/apache2</tt> or <tt>apache2ctl</tt>.
<b>Calling <tt>/usr/bin/apache2</tt> directly will not work</b> with the
default configuration.
</li>
</ul>
</div>

<div class="section_header">
<div id="docroot"></div>
Document Roots
</div>

<div class="content_section_text">
<p>
By default, Debian does not allow access through the web browser to
<em>any</em> file apart of those located in <tt>/var/www</tt>,
<a href="http://httpd.apache.org/docs/2.4/mod/mod_userdir.html" rel="nofollow">public_html</a>
directories (when enabled) and <tt>/usr/share</tt> (for web
applications). If your site is using a web document root
located elsewhere (such as in <tt>/srv</tt>) you may need to whitelist your
document root directory in <tt>/etc/apache2/apache2.conf</tt>.
</p>
<p>
The default Debian document root is <tt>/var/www/html</tt>. You
can make your own virtual hosts under /var/www. This is different
to previous releases which provides better security out of the box.
</p>
</div>

<div class="section_header">
<div id="bugs"></div>
Reporting Problems
</div>
<div class="content_section_text">
<p>
Please use the <tt>reportbug</tt> tool to report bugs in the
Apache2 package with Debian. However, check <a
href="http://bugs.debian.org/cgi-bin/pkgreport.cgi?ordering=normal;archive=0;src=apache2;repeatmerged=0"
rel="nofollow">existing bug reports</a> before reporting a new bug.
</p>
<p>
Please report bugs specific to modules (such as PHP and others)
to respective packages, not to the web server itself.
</p>
</div>




</div>
</div>
<div class="validator">
</div>
</body>
</html>


BIN
nxdn-dash/DVSwitch.png View File

Before After
Width: 259  |  Height: 171  |  Size: 8.5 KiB

+ 116
- 0
nxdn-dash/LICENSE View File

@@ -0,0 +1,116 @@
CC0 1.0 Universal

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.

For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:

i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;

ii. moral rights retained by the original author(s) and/or performer(s);

iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;

iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;

v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;

vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and

vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.

4. Limitations and Disclaimers.

a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.

b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.

c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.

d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.

For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

+ 15
- 0
nxdn-dash/config/config.php View File

@@ -0,0 +1,15 @@
<?php
# This is an auto-generated config-file!
# Be careful, when manual editing this!

date_default_timezone_set('UTC');
define("NXDNREFLECTORLOGPATH", "/var/log/NXDNReflector");
define("NXDNREFLECTORLOGPREFIX", "NXDNReflector");
define("NXDNREFLECTORINIPATH", "/opt/NXDNReflector");
define("NXDNREFLECTORINIFILENAME", "NXDNReflector.ini");
define("NXDNREFLECTORPATH", "/opt/NXDNReflector/");
define("TIMEZONE", "America/Chicago");
define("LOGO", "");
define("REFRESHAFTER", "60");
define("TEMPERATUREHIGHLEVEL", "60");
?>

BIN
nxdn-dash/favicon.ico View File

Before After

BIN
nxdn-dash/favicontx.ico View File

Before After

+ 42
- 0
nxdn-dash/include/allheard.php View File

@@ -0,0 +1,42 @@
<?php
?>
<div class="panel panel-default panel-info">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">All Heard List</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="allHeard" class="table table-condensed">
<thead>
<tr>
<th>Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
<th>Target</th>
<th>Gateway</th>
<th>Dur (s)</th>
</tr>
</thead>
<tbody>
<?php
for ($i = 0; $i < count($allHeard); $i++) {
$listElem = $allHeard[$i];
echo"<tr>";
echo"<td>$listElem[0]</td>";
echo"<td>$listElem[1]</td>";
echo"<td>$listElem[2]</td>";
echo"<td>$listElem[3]</td>";
echo"<td>$listElem[4]</td>";
echo"</tr>\n";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#allHeard').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 87
- 0
nxdn-dash/include/disk.php View File

@@ -0,0 +1,87 @@
<div class="panel panel-default">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Disk use</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="diskuse" class="table table-condensed table-striped table-hover">

<thead>
<tr>
<th class="w10p filesystem">Filesystem</th>
<th class="w20p">Mount</th>
<th>Use</th>
<th class="w15p">Free</th>
<th class="w15p">Used</th>
<th class="w15p">Total</th>
</tr>
</thead>
<tbody>
<?php

error_reporting(E_ERROR | E_WARNING | E_PARSE);

//include "./functions.php";
try{

$datas = array();

if (!(exec('/bin/df -T | awk -v c=`/bin/df -T | grep -bo "Type" | awk -F: \'{print $2}\'` \'{print substr($0,c);}\' | tail -n +2 | awk \'{print $1","$2","$3","$4","$5","$6","$7}\'', $df)))
{
$datas[] = array(
'total' => 'N.A',
'used' => 'N.A',
'free' => 'N.A',
'percent_used' => 0,
'mount' => 'N.A',
'filesystem' => 'N.A',
);
}
else
{
$mounted_points = array();
$key = 0;

foreach ($df as $mounted)
{
list($filesystem, $type, $total, $used, $free, $percent, $mount) = explode(',', $mounted);

if (strpos($type, 'tmpfs') !== false )
continue;


?>

<tr>
<td><?php echo $filesystem ?></td>
<td><?php echo $mount ?></td>
<td><div class="progress"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo trim($percent, '%') ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo trim($percent, '%') ?>%;"><?php echo trim($percent, '%') ?>%</div></div></td>
<td><?php echo getSize($free * 1024) ?></td>
<td><?php echo getSize($used * 1024) ?></td>
<td><?php echo getSize($total * 1024) ?></td>
</tr>
<?php
$key++;
}

}



} catch (Exception $e) {
return false;
}

?>

</tbody>
</table>
</div>
</div>


+ 195
- 0
nxdn-dash/include/functions.php View File

@@ -0,0 +1,195 @@
<?php
function getNXDNReflectorVersion() {
// returns creation-time of NXDNReflector as version-number
$filename = NXDNREFLECTORPATH."/NXDNReflector";
exec($filename." -v 2>&1", $output);
if (!startsWith(substr($output[0],21,8),"20")) {
return getNXDNReflectorFileVersion();
} else {
return substr($output[0],21,8)." (compiled ".getNXDNReflectorFileVersion().")";
}
}


function getNXDNReflectorFileVersion() {
// returns creation-time of NXDNReflector as version-number
$filename = NXDNREFLECTORPATH."/NXDNReflector";
if (file_exists($filename)) {
return date("d M Y", filectime($filename));
}
}

function getNXDNReflectorConfig() {
// loads NXDNReflector.ini into array for further use
$conf = array();
if ($configs = fopen(NXDNREFLECTORINIPATH."/".NXDNREFLECTORINIFILENAME, '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 getNXDNReflectorLog() {
// Open Logfile and copy loglines into LogLines-Array()
$logLines = array();
if ($log = fopen(NXDNREFLECTORLOGPATH."/".NXDNREFLECTORLOGPREFIX."-".date("Y-m-d").".log", 'r')) {
while ($logLine = fgets($log)) {
array_push($logLines, $logLine);
}
fclose($log);
}
return $logLines;
}

function getShortNXDNReflectorLog() {
// Open Logfile and copy loglines into LogLines-Array()
$logPath = NXDNREFLECTORLOGPATH."/".NXDNREFLECTORLOGPREFIX."-".date("Y-m-d").".log";
//$logLines = explode("\n", `tail -n100 $logPath`);
$logLines = explode("\n", `egrep -h "Transmission|Received|watchdog" $logPath | tail -1`);
return $logLines;
}

function getConnectedGateways($logLines) {
$gateways = Array();
foreach ($logLines as $logLine) {
if(strpos($logLine,"NXDNReflector")){
$gateways = Array();
}
if(strpos($logLine,"Adding")) {
$lineParts = explode(" ", $logLine);
if (!array_search($gateways, $lineParts[4])) {
array_push($gateways, Array('callsign'=>$lineParts[4],'timestamp'=>convertTimezone($lineParts[1]." ".substr($lineParts[2],0,8))));
}
}
if(strpos($logLine,"Removing")) {
$lineParts = explode(" ", $logLine);
$pos = array_search($lineParts[4],array_column($gateways, 'callsign'));
array_splice($gateways, $pos, 1);
}
}
return $gateways;
}

function getLinkedGateways($logLines) {
// YSF
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-06-24 11:11:41.787 Currently linked repeaters/gateways:
//M: 2016-06-24 11:11:41.787 GATEWAY : 217.82.212.214:42000 2/60
//M: 2016-06-24 11:11:41.787 DM0GER : 217.251.59.165:42000 5/60

// P25
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-10-11 19:47:19.081 Currently linked repeaters:
//M: 2016-10-11 19:47:19.081 GB7KH (178.21.236.222:42010) 2/120
//M: 2016-10-11 19:47:19.081 DL5BQ (178.201.193.183:42010) 10/120

$gateways = Array();
for ($i = count($logLines); $i>0; $i--) {
if(isset($logLines[$i])){
$logLine = $logLines[$i];

if (strpos($logLine, "Starting NXDNReflector")) {
return $gateways;
}
if (strpos($logLine, "No repeaters/gateways linked")) {
return $gateways;
}
if (strpos($logLine, "Currently linked repeaters")) {
for ($j = $i+1; $j <= count($logLines); $j++) {
if(isset($logLines[$j])){
$logLine = $logLines[$j];
if (!startsWith(substr($logLine,27), " ")) {
return $gateways;
} else {
$timestamp = substr($logLine, 3, 19);
$callsign = substr($logLine, 31, 11);
$ipport = substr($logLine, 43);
$key = searchForKey("ipport",$ipport, $gateways);
if ($key === NULL) {
array_push($gateways, Array('callsign'=>$callsign,'timestamp'=>$timestamp,'ipport'=>$ipport));
}
}
}
}
}
}
}
return $gateways;
}

function getHeardList($logLines) {
// P25
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-10-11 19:45:38.033 Transmission from DL5BQ at DL5BQ to TG 10100

$heardList = array();
$dttxend = "";
foreach ($logLines as $logLine) {
$duration = "transmitting";
$timestamp = substr($logLine, 3, 19);
$dttimestamp = new DateTime($timestamp);
if ($dttxend !== "") {
$duration = $dttimestamp->diff($dttxend)->format("%s");
}
$callsign2 = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"at") - strpos($logLine,"from") - 6);
$callsign = trim($callsign2);
$target = substr($logLine, strpos($logLine, "to") + 3);
$gateway = trim(substr($logLine, strpos($logLine,"at") + 3, strpos($logLine,"to") - strpos($logLine,"at") - 4));
// Callsign or ID should be less than 11 chars long, otherwise it could be errorneous
if ( (strlen($callsign) < 11) && (strlen($callsign) > 0) ) {
array_push($heardList, array(convertTimezone($timestamp), $callsign, $target, $gateway, $duration));
}
if(strpos($logLine,"end of") || strpos($logLine,"watchdog has expired") || strpos($logLine,"ended RF data") || strpos($logLine,"ended network") || strpos($logLine,"end of transmission")) {
$txend = substr($logLine, 3, 19);
$dttxend = new DateTime($txend);
}
}
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(!(array_search($listElem[1], $heardCalls) > -1)) {
array_push($heardCalls, $listElem[1]);
array_push($lastHeard, $listElem);
$counter++;
}
}
return $lastHeard;
}

function getSize($filesize, $precision = 2) {
$units = array('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y');
foreach ($units as $idUnit => $unit) {
if ($filesize > 1024)
$filesize /= 1024;
else
break;
}
return round($filesize, $precision).' '.$units[$idUnit].'B';
}
?>

+ 36
- 0
nxdn-dash/include/gateways.php View File

@@ -0,0 +1,36 @@
<?php
?>
<div class="panel panel-default">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Connected NXDNGateways</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="gateways" class="table table-condensed">
<thead>
<tr>
<th>Reporting Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
</tr>
</thead>
<tbody>
<?php
//$gateways = getConnectedGateways($logLines);
$gateways = getLinkedGateways($logLines);
foreach ($gateways as $gateway) {
echo "<tr>";
echo "<td>".convertTimezone($gateway[timestamp])."</td><td>$gateway[callsign]</td>";
echo "</tr>";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#gateways').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 12
- 0
nxdn-dash/include/init.php View File

@@ -0,0 +1,12 @@
<?php
//Some basic inits
$configs = getNXDNReflectorConfig();
if (!defined("TIMEZONE"))
define("TIMEZONE", "UTC");
$logLines = getNXDNReflectorLog();

$reverseLogLines = $logLines;
array_multisort($reverseLogLines,SORT_DESC);
$lastHeard = getLastHeard($reverseLogLines);
$allHeard = getHeardList($reverseLogLines);
?>

+ 42
- 0
nxdn-dash/include/lh.php View File

@@ -0,0 +1,42 @@
<?php
?>
<div class="panel panel-default panel-success">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Last Heard List</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="lh" class="table table-condensed">
<thead>
<tr>
<th>Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
<th>Target</th>
<th>Gateway</th>
<th>Dur (s)</th>
</tr>
</thead>
<tbody>
<?php
for ($i = 0; $i < count($lastHeard); $i++) {
$listElem = $lastHeard[$i];
echo"<tr>";
echo"<td>$listElem[0]</td>";
echo"<td>$listElem[1]</td>";
echo"<td>$listElem[2]</td>";
echo"<td>$listElem[3]</td>";
echo"<td>$listElem[4]</td>";
echo"</tr>\n";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#lh').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 166
- 0
nxdn-dash/include/sysinfo.php View File

@@ -0,0 +1,166 @@
<?php
$cputemp = NULL;
$cpufreq = NULL;
if (file_exists ("/sys/class/thermal/thermal_zone0/temp")) {
exec("cat /sys/class/thermal/thermal_zone0/temp", $cputemp);
$cputemp = $cputemp[0] / 1000;
}
if (file_exists ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq")) {
exec("cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", $cpufreq);
$cpufreq = $cpufreq[0] / 1000;
}
if (defined("TEMPERATUREALERT") && $cputemp > TEMPERATUREHIGHLEVEL && $cputemp !== NULL) {
?>
<script>
function deleteLayer(id) {
if (document.getElementById && document.getElementById(id)) {
var theNode = document.getElementById(id);
theNode.parentNode.removeChild(theNode);
}
else if (document.all && document.all[id]) {
document.all[id].innerHTML='';
document.all[id].outerHTML='';
}
// OBSOLETE CODE FOR NETSCAPE 4
else if (document.layers && document.layers[id]) {
document.layers[id].visibility='hide';
delete document.layers[id];
}
}

function makeLayer(id,L,T,W,H,bgColor,visible,zIndex) {
if (document.getElementById) {
if (document.getElementById(id)) {
alert ('Layer with this ID already exists!');
return;
}
var ST = 'position:absolute; text-align:center;padding-top:20px;'
+'; left:'+L+'px'
+'; top:'+T+'px'
+'; width:'+W+'px'
+'; height:'+H+'px'
+'; clip:rect(0,'+W+','+H+',0)'
+'; visibility:'
+(null==visible || 1==visible ? 'visible':'hidden')
+(null==zIndex ? '' : '; z-index:'+zIndex)
+(null==bgColor ? '' : '; background-color:'+bgColor);

var LR = '<DIV id='+id+' style="'+ST+'">CPU-Temperature is very high!<br><input type="button" value="Close" onclick="deleteLayer(\'LYR1\')"></DIV>';

if (document.body) {
if (document.body.insertAdjacentHTML)
document.body.insertAdjacentHTML("BeforeEnd",LR);
else if (document.createElement && document.body.appendChild) {
var newNode = document.createElement('div');
newNode.setAttribute('id',id);
newNode.setAttribute('style',ST);
document.body.appendChild(newNode);
}
}
}
}
var audio = new Audio('sounds/alert.mp3');
audio.play();
var x = window.innerWidth/2-100;
var y = window.innerHeight/2-50;

makeLayer('LYR1',x,y,200,100,'red',1,1);
</script>
<?php
}

$output = shell_exec('cat /proc/loadavg');
$sysload = substr($output,0,strpos($output," "))*100;

$stat1 = file('/proc/stat');
sleep(1);
$stat2 = file('/proc/stat');
$info1 = explode(" ", preg_replace("!cpu +!", "", $stat1[0]));
$info2 = explode(" ", preg_replace("!cpu +!", "", $stat2[0]));
$dif = array();
$dif['user'] = $info2[0] - $info1[0];
$dif['nice'] = $info2[1] - $info1[1];
$dif['sys'] = $info2[2] - $info1[2];
$dif['idle'] = $info2[3] - $info1[3];
$total = array_sum($dif);
$cpu = array();
foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 1);
$cpuusage = round($cpu['user'] + $cpu['sys'], 2);
$output = shell_exec('grep -c processor /proc/cpuinfo');
$cpucores = $output;

$output = shell_exec('cat /proc/uptime');
$uptime = format_time(substr($output,0,strpos($output," ")));
$idletime = format_time((substr($output,strpos($output," ")))/$cpucores);

?>
<div class="panel panel-default">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">System Info</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="sysinfo" class="table table-condensed">
<tbody>
<tr>
<?php
if ($cputemp !== NULL) {
?>
<th>CPU-Temperature</th>
<?php
}
?>
<?php
if ($cpufreq !== NULL) {
?>
<th>CPU-Frequency</th>
<?php
}
?>
<th>System-Load</th>
<th>CPU-Usage</th>
<th>Uptime</th>
<th>Idle</th>
</tr>
<tr class="gatewayinfo">
<?php
if ($cputemp !== NULL) {
?>
<td><?php echo $cputemp; ?> &deg;C</td>
<?php
}
?>
<?php
if ($cpufreq !== NULL) {
?>
<td><?php echo $cpufreq; ?> MHz</td>
<?php
}
?>
<td><?php echo $sysload; ?> %</td>
<td>
<?php
if (defined("SHOWPROGRESSBARS")) {
?>
<div class="progress"><div class="progress-bar <?php
if ($cpuusage < 30)
echo "progress-bar-success";
if ($cpuusage >= 30 and $cpuusage < 60)
echo "progress-bar-warning";
if ($cpuusage >= 60)
echo "progress-bar-danger";
?>" role="progressbar" aria-valuenow="<?php echo $cpuusage; ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $cpuusage; ?>%;"><?php echo $cpuusage; ?>%</div></div>
<?php
} else {
echo $cpuusage." %";
}
?>
</td>
<td><?php echo $uptime; ?></td>
<td><?php echo $idletime; ?></td>
</tr>
</tbody>
</table>
</div>
</div>

+ 89
- 0
nxdn-dash/include/tools.php View File

@@ -0,0 +1,89 @@
<?php
function format_time($seconds) {
$secs = intval($seconds % 60);
$mins = intval($seconds / 60 % 60);
$hours = intval($seconds / 3600 % 24);
$days = intval($seconds / 86400);
$uptimeString = "";

if ($days > 0) {
$uptimeString .= $days;
$uptimeString .= (($days == 1) ? "&nbsp;day" : "&nbsp;days");
}
if ($hours > 0) {
$uptimeString .= (($days > 0) ? ", " : "") . $hours;
$uptimeString .= (($hours == 1) ? "&nbsp;hr" : "&nbsp;hrs");
}
if ($mins > 0) {
$uptimeString .= (($days > 0 || $hours > 0) ? ", " : "") . $mins;
$uptimeString .= (($mins == 1) ? "&nbsp;min" : "&nbsp;mins");
}
if ($secs > 0) {
$uptimeString .= (($days > 0 || $hours > 0 || $mins > 0) ? ", " : "") . $secs;
$uptimeString .= (($secs == 1) ? "&nbsp;s" : "&nbsp;s");
}
return $uptimeString;
}

function startsWith($haystack, $needle) {
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false;
}

function searchForKey($field, $needle, $array) {
foreach ($array as $key => $val) {
if ($val[$field] === $needle) {
return $key;
}
}
return null;
}

function getMHZ($freq) {
return substr($freq,0,3) . "." . substr($freq,3,3) . "." . substr($freq,6) . " Mhz";
}

function isProcessRunning($processname) {
exec("pgrep " . $processname, $pids);
if(empty($pids)) {
// process not running!
return false;
} else {
// process running!
return true;
}
}

function createConfigLines() {
$out ="";
foreach($_GET as $key=>$val) {
if($key != "cmd") {
$out .= "define(\"$key\", \"$val\");"."\n";
}
}
return $out;
}

function checkSetup() {
$el = error_reporting();
error_reporting(E_ERROR | E_WARNING | E_PARSE);
if (defined(DISTRIBUTION)) {
?>
<div class="alert alert-danger" role="alert">You are using an old config.php. Please configure your Dashboard by calling <a href="setup.php">setup.php</a>!</div>
<?php
} else {
if (file_exists ("setup.php")) {
?>
<div class="alert alert-danger" role="alert">You forgot to remove setup.php in root-directory of your dashboard or you forgot to configure it! Please delete the file or configure your Dashboard by calling <a href="setup.php">setup.php</a>!</div>
<?php
}
}
error_reporting($el);
}
function convertTimezone($timestamp) {
$date = new DateTime($timestamp);
$date->setTimezone(new DateTimeZone(TIMEZONE));
return $date->format('Y-m-d H:i:s');
}

?>

+ 80
- 0
nxdn-dash/include/txinfo.php View File

@@ -0,0 +1,80 @@
<div class="panel panel-default panel-danger">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Currently Transmitting</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="currtx" class="table table-condensed table-striped table-hover">
<thead>
<tr>
<th>Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
<th>Target</th>
<th>Gateway</th>
<th>TX-Time</th>
</tr>
</thead>
<tbody id="txline">
</tbody>
</table>
</div>
</div>
<script>
function ChangeFavicon(url) {
var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = url; //path to your icon
document.getElementsByTagName('head')[0].appendChild(link);
}
function doXMLHTTPRequest(scriptname, elem) {
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById(elem).innerHTML=xmlhttp.responseText;
if (xmlhttp.responseText.includes("tr")) {
ChangeFavicon("favicontx.ico");
} else {
ChangeFavicon("favicon.ico");
}
}
}
xmlhttp.open("GET",scriptname,true);
xmlhttp.send();
}
function refreshInQSOAndLastHeardList() {
doXMLHTTPRequest("txinfo.php","txline");
}
var transmitting = false;
function loadXMLDoc() {
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("txline").innerHTML=xmlhttp.responseText;
if (xmlhttp.responseText.includes("tr")) {
ChangeFavicon("favicontx.ico");
} else {
ChangeFavicon("favicon.ico");
}
}
}
xmlhttp.open("GET","txinfo.php",true);
xmlhttp.send();
var timeout = window.setTimeout("loadXMLDoc()", 1000);
}
loadXMLDoc();
</script>

+ 72
- 0
nxdn-dash/index.php View File

@@ -0,0 +1,72 @@
<?php
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
// do not touch this includes!!! Never ever!!!
include "config/config.php";
include "include/tools.php";
include "include/functions.php";
include "include/init.php";
include "version.php";
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--<meta name="viewport" content="width=device-width, initial-scale=1.0">
-->
<meta name="viewport" content="width=device-width, initial-scale=0.6,maximum-scale=1, user-scalable=yes">
<meta http-equiv="refresh" content="<?php echo REFRESHAFTER?>">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
<!-- Das neueste kompilierte und minimierte CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!-- Optionales Theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css">
<!-- Das neueste kompilierte und minimierte JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- Datatables -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css">
<script type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<style>
h4 {
display: inline
}
body {padding: 10px;}
</style>
<title>[NXDN] 707 RuralMN Dashboard</title>
</head>
<body>
<div class="page-header" style="position:relative;">
<h1><center>707 RuralMN NXDN Reflector</center></h1>
</div>
<?php
checkSetup();
// Here you can feel free to disable info-sections by commenting out with // before include
include "include/txinfo.php";
//include "include/sysinfo.php";
//include "include/disk.php";
//include "include/gateways.php";
include "include/lh.php";
include "include/allheard.php";
include "include/gateways.php";
?>
<div class="panel panel-info">
<?php
$lastReload = new DateTime();
$lastReload->setTimezone(new DateTimeZone(TIMEZONE));
echo "NXDNReflector-Dashboard V ".VERSION." | N4IRS/N2NUO | Last Reload ".$lastReload->format('Y-m-d, H:i:s')." (".TIMEZONE.")";
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 4);
echo '<!--Page generated in '.$total_time.' seconds.-->';
?> | get your own at: <a href="https://github.com/dg9vh/YSFReflector-Dashboard">https://github.com/dg9vh/YSFReflector-Dashboard</a>
</div>
</body>
</html>

+ 35
- 0
nxdn-dash/txinfo.php View File

@@ -0,0 +1,35 @@
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
include "config/config.php";
include "include/tools.php";
include "include/functions.php";
$configs = getNXDNReflectorConfig();
$logLines = getShortNXDNReflectorLog();
$reverseLogLines = $logLines;
array_multisort($reverseLogLines,SORT_DESC);
$lastHeard = getLastHeard($reverseLogLines, True);
if(isset($lastHeard[0])){
$listElem = $lastHeard[0];
if (strlen($listElem[0]) !== 0) {
echo "<tr>";
echo"<td nowrap>$listElem[0]</td>";
if (constant("SHOWQRZ") && $listElem[1] !== "??????????" && !is_numeric($listElem[1])) {
echo"<td nowrap><a target=\"_new\" href=\"https://qrz.com/db/$listElem[1]\">".str_replace("0","&Oslash;",$listElem[1])."</a></td>";
} else {
echo"<td nowrap>".str_replace("0","&Oslash;",$listElem[1])."</td>";
}
echo"<td nowrap>$listElem[2]</td>";
echo"<td nowrap>$listElem[3]</td>";
$local = new DateTimeZone(TIMEZONE);
$UTC = new DateTimeZone("UTC");
$d1 = new DateTime($listElem[0], $local);
$d2 = new DateTime('now', $UTC);
$diff = $d2->getTimestamp() - $d1->getTimestamp();
echo"<td nowrap>$diff s</td>";
echo "</tr>";
}
}
?>



+ 3
- 0
nxdn-dash/version.php View File

@@ -0,0 +1,3 @@
<?php
define("VERSION", "20160930-HACK");
?>

BIN
p25-dash/DVSwitch.png View File

Before After
Width: 259  |  Height: 171  |  Size: 8.5 KiB

+ 116
- 0
p25-dash/LICENSE View File

@@ -0,0 +1,116 @@
CC0 1.0 Universal

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.

For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:

i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;

ii. moral rights retained by the original author(s) and/or performer(s);

iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;

iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;

v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;

vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and

vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.

4. Limitations and Disclaimers.

a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.

b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.

c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.

d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.

For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

+ 16
- 0
p25-dash/config/config.php View File

@@ -0,0 +1,16 @@
<?php
# This is an auto-generated config-file!
# Be careful, when manual editing this!

date_default_timezone_set('UTC');
define("P25REFLECTORLOGPATH", "/var/log/P25Reflector");
define("P25REFLECTORLOGPREFIX", "P25Reflector");
define("P25REFLECTORINIPATH", "/etc/");
define("P25REFLECTORINIFILENAME", "P25Reflector.ini");
define("P25REFLECTORPATH", "/usr/local/bin/");
define("TIMEZONE", "America/Chicago");
define("LOGO", "DVSwitch.png");
define("REFRESHAFTER", "60");
define("TEMPERATUREHIGHLEVEL", "60");
define("SHOWQRZ", "");
?>

BIN
p25-dash/favicon.ico View File

Before After

+ 42
- 0
p25-dash/include/allheard.php View File

@@ -0,0 +1,42 @@
<?php
?>
<div class="panel panel-default panel-info">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">All Heard List</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="allHeard" class="table table-condensed">
<thead>
<tr>
<th>Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
<th>Target</th>
<th>Gateway</th>
<th>Dur (s)</th>
</tr>
</thead>
<tbody>
<?php
for ($i = 0; $i < count($allHeard); $i++) {
$listElem = $allHeard[$i];
echo"<tr>";
echo"<td>$listElem[0]</td>";
echo"<td>$listElem[1]</td>";
echo"<td>$listElem[2]</td>";
echo"<td>$listElem[3]</td>";
echo"<td>$listElem[4]</td>";
echo"</tr>\n";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#allHeard').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 87
- 0
p25-dash/include/disk.php View File

@@ -0,0 +1,87 @@
<div class="panel panel-default">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Disk use</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="diskuse" class="table table-condensed table-striped table-hover">

<thead>
<tr>
<th class="w10p filesystem">Filesystem</th>
<th class="w20p">Mount</th>
<th>Use</th>
<th class="w15p">Free</th>
<th class="w15p">Used</th>
<th class="w15p">Total</th>
</tr>
</thead>
<tbody>
<?php

error_reporting(E_ERROR | E_WARNING | E_PARSE);

//include "./functions.php";
try{

$datas = array();

if (!(exec('/bin/df -T | awk -v c=`/bin/df -T | grep -bo "Type" | awk -F: \'{print $2}\'` \'{print substr($0,c);}\' | tail -n +2 | awk \'{print $1","$2","$3","$4","$5","$6","$7}\'', $df)))
{
$datas[] = array(
'total' => 'N.A',
'used' => 'N.A',
'free' => 'N.A',
'percent_used' => 0,
'mount' => 'N.A',
'filesystem' => 'N.A',
);
}
else
{
$mounted_points = array();
$key = 0;

foreach ($df as $mounted)
{
list($filesystem, $type, $total, $used, $free, $percent, $mount) = explode(',', $mounted);

if (strpos($type, 'tmpfs') !== false )
continue;


?>

<tr>
<td><?php echo $filesystem ?></td>
<td><?php echo $mount ?></td>
<td><div class="progress"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo trim($percent, '%') ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo trim($percent, '%') ?>%;"><?php echo trim($percent, '%') ?>%</div></div></td>
<td><?php echo getSize($free * 1024) ?></td>
<td><?php echo getSize($used * 1024) ?></td>
<td><?php echo getSize($total * 1024) ?></td>
</tr>
<?php
$key++;
}

}



} catch (Exception $e) {
return false;
}

?>

</tbody>
</table>
</div>
</div>


+ 203
- 0
p25-dash/include/functions.php View File

@@ -0,0 +1,203 @@
<?php
function getP25ReflectorVersion() {
// returns creation-time of P25Reflector as version-number
$filename = P25REFLECTORPATH."/P25Reflector";
exec($filename." -v 2>&1", $output);
if (!startsWith(substr($output[0],21,8),"20")) {
return getP25ReflectorFileVersion();
} else {
return substr($output[0],21,8)." (compiled ".getP25ReflectorFileVersion().")";
}
}


function getP25ReflectorFileVersion() {
// returns creation-time of P25Reflector as version-number
$filename = P25REFLECTORPATH."/P25Reflector";
if (file_exists($filename)) {
return date("d M Y", filectime($filename));
}
}

function getP25ReflectorConfig() {
// loads P25Reflector.ini into array for further use
$conf = array();
if ($configs = fopen(P25REFLECTORINIPATH."/".P25REFLECTORINIFILENAME, '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 getP25ReflectorLog() {
// Open Logfile and copy loglines into LogLines-Array()
$logLines = array();
if ($log = fopen(P25REFLECTORLOGPATH."/".P25REFLECTORLOGPREFIX."-".date("Y-m-d").".log", 'r')) {
while ($logLine = fgets($log)) {
array_push($logLines, $logLine);
}
fclose($log);
}
return $logLines;
}

function getShortP25ReflectorLog() {
// YSF
//M: 2018-04-12 18:11:10.807 Received data from N4IRS to ALL at N4IRS
//M: 2018-04-12 18:11:11.602 Received end of transmission
// P25
//M: 2018-04-12 18:39:20.784 Transmission started from KC5MMW (166.173.61.41:6247)
//M: 2018-04-12 18:39:20.795 Transmission from K5BRM at KC5MMW to TG 10200
//M: 2018-04-12 18:39:23.455 Received end of transmission

// Open Logfile and copy loglines into LogLines-Array()
$logPath = P25REFLECTORLOGPATH."/".P25REFLECTORLOGPREFIX."-".date("Y-m-d").".log";
//$logLines = explode("\n", `tail -n100 $logPath`);
$logLines = explode("\n", `egrep -h "Transmission|Received|watchdog" $logPath | tail -1`);
return $logLines;
}

function getConnectedGateways($logLines) {
$gateways = Array();
foreach ($logLines as $logLine) {
if(strpos($logLine,"P25Reflector")){
$gateways = Array();
}
if(strpos($logLine,"Adding")) {
$lineParts = explode(" ", $logLine);
if (!array_search($gateways, $lineParts[4])) {
array_push($gateways, Array('callsign'=>$lineParts[4],'timestamp'=>$lineParts[1]." ".substr($lineParts[2],0,8)));
}
}
if(strpos($logLine,"Removing")) {
$lineParts = explode(" ", $logLine);
$pos = array_search($lineParts[4],array_column($gateways, 'callsign'));
array_splice($gateways, $pos, 1);
}
}
return $gateways;
}

function getLinkedGateways($logLines) {
// YSF
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-06-24 11:11:41.787 Currently linked repeaters/gateways:
//M: 2016-06-24 11:11:41.787 GATEWAY : 217.82.212.214:42000 2/60
//M: 2016-06-24 11:11:41.787 DM0GER : 217.251.59.165:42000 5/60

// P25
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-10-11 19:47:19.081 Currently linked repeaters:
//M: 2016-10-11 19:47:19.081 GB7KH (178.21.236.222:42010) 2/120
//M: 2016-10-11 19:47:19.081 DL5BQ (178.201.193.183:42010) 10/120

$gateways = Array();
for ($i = count($logLines); $i>0; $i--) {
if(isset($logLines[$i])){
$logLine = $logLines[$i];

if (strpos($logLine, "Starting P25Reflector")) {
return $gateways;
}
if (strpos($logLine, "No repeaters/gateways linked")) {
return $gateways;
}
if (strpos($logLine, "Currently linked repeaters")) {
for ($j = $i+1; $j <= count($logLines); $j++) {
if(isset($logLines[$j])){
$logLine = $logLines[$j];
if (!startsWith(substr($logLine,27), " ")) {
return $gateways;
} else {
$timestamp = substr($logLine, 3, 19);
$callsign = substr($logLine, 31, 11);
$ipport = substr($logLine, 43);
$key = searchForKey("ipport",$ipport, $gateways);
if ($key === NULL) {
array_push($gateways, Array('callsign'=>$callsign,'timestamp'=>$timestamp,'ipport'=>$ipport));
}
}
}
}
}
}
}
return $gateways;
}

function getHeardList($logLines) {
// P25
//0000000000111111111122222222223333333333444444444455555555556666666666
//0123456789012345678901234567890123456789012345678901234567890123456789
//M: 2016-10-11 19:45:38.033 Transmission from DL5BQ at DL5BQ to TG 10100

$heardList = array();
$dttxend = "";
foreach ($logLines as $logLine) {
$duration = "transmitting";
$timestamp = substr($logLine, 3, 19);
$dttimestamp = new DateTime($timestamp);
if ($dttxend !== "") {
$duration = $dttimestamp->diff($dttxend)->format("%s");
}
$callsign2 = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"at") - strpos($logLine,"from") - 6);
$callsign = trim($callsign2);
$target = substr($logLine, strpos($logLine, "to") + 3);
$gateway = trim(substr($logLine, strpos($logLine,"at") + 3, strpos($logLine,"to") - strpos($logLine,"at") - 4));
// Callsign or ID should be less than 11 chars long, otherwise it could be errorneous
if ( (strlen($callsign) < 11) && (strlen($callsign) > 0) ) {
array_push($heardList, array(convertTimezone($timestamp), $callsign, $target, $gateway, $duration));
}
if(strpos($logLine,"end of") || strpos($logLine,"watchdog has expired") || strpos($logLine,"ended RF data") || strpos($logLine,"ended network") || strpos($logLine,"end of transmission")) {
$txend = substr($logLine, 3, 19);
$dttxend = new DateTime($txend);
}
}
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(!(array_search($listElem[1], $heardCalls) > -1)) {
array_push($heardCalls, $listElem[1]);
array_push($lastHeard, $listElem);
$counter++;
}
}
return $lastHeard;
}

function getSize($filesize, $precision = 2) {
$units = array('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y');
foreach ($units as $idUnit => $unit) {
if ($filesize > 1024)
$filesize /= 1024;
else
break;
}
return round($filesize, $precision).' '.$units[$idUnit].'B';
}
?>

+ 36
- 0
p25-dash/include/gateways.php View File

@@ -0,0 +1,36 @@
<?php
?>
<div class="panel panel-default" >
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Connected P25 Gateways</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="gateways" class="table table-condensed">
<thead>
<tr>
<th>Reporting Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
</tr>
</thead>
<tbody>
<?php
//$gateways = getConnectedGateways($logLines);
$gateways = getLinkedGateways($logLines);
foreach ($gateways as $gateway) {
echo "<tr>";
echo "<td>".convertTimezone($gateway[timestamp])."</td><td>$gateway[callsign]</td>";
echo "</tr>";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#gateways').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 12
- 0
p25-dash/include/init.php View File

@@ -0,0 +1,12 @@
<?php
//Some basic inits
$configs = getP25ReflectorConfig();
if (!defined("TIMEZONE"))
define("TIMEZONE", "UTC");
$logLines = getP25ReflectorLog();

$reverseLogLines = $logLines;
array_multisort($reverseLogLines,SORT_DESC);
$lastHeard = getLastHeard($reverseLogLines);
$allHeard = getHeardList($reverseLogLines);
?>

+ 42
- 0
p25-dash/include/lh.php View File

@@ -0,0 +1,42 @@
<?php
?>
<div class="panel panel-default panel-success">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">Last Heard List</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="lh" class="table table-condensed">
<thead>
<tr>
<th>Time (<?php echo(TIMEZONE) ?>)</th>
<th>Callsign</th>
<th>Target</th>
<th>Gateway</th>
<th>Dur (s)</th>
</tr>
</thead>
<tbody>
<?php
for ($i = 0; $i < count($lastHeard); $i++) {
$listElem = $lastHeard[$i];
echo"<tr>";
echo"<td>$listElem[0]</td>";
echo"<td>$listElem[1]</td>";
echo"<td>$listElem[2]</td>";
echo"<td>$listElem[3]</td>";
echo"<td>$listElem[4]</td>";
echo"</tr>\n";
}
?>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$('#lh').dataTable( {
"aaSorting": [[0,'desc']]
} );
});
</script>
</div>

+ 166
- 0
p25-dash/include/sysinfo.php View File

@@ -0,0 +1,166 @@
<?php
$cputemp = NULL;
$cpufreq = NULL;
if (file_exists ("/sys/class/thermal/thermal_zone0/temp")) {
exec("cat /sys/class/thermal/thermal_zone0/temp", $cputemp);
$cputemp = $cputemp[0] / 1000;
}
if (file_exists ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq")) {
exec("cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", $cpufreq);
$cpufreq = $cpufreq[0] / 1000;
}
if (defined("TEMPERATUREALERT") && $cputemp > TEMPERATUREHIGHLEVEL && $cputemp !== NULL) {
?>
<script>
function deleteLayer(id) {
if (document.getElementById && document.getElementById(id)) {
var theNode = document.getElementById(id);
theNode.parentNode.removeChild(theNode);
}
else if (document.all && document.all[id]) {
document.all[id].innerHTML='';
document.all[id].outerHTML='';
}
// OBSOLETE CODE FOR NETSCAPE 4
else if (document.layers && document.layers[id]) {
document.layers[id].visibility='hide';
delete document.layers[id];
}
}

function makeLayer(id,L,T,W,H,bgColor,visible,zIndex) {
if (document.getElementById) {
if (document.getElementById(id)) {
alert ('Layer with this ID already exists!');
return;
}
var ST = 'position:absolute; text-align:center;padding-top:20px;'
+'; left:'+L+'px'
+'; top:'+T+'px'
+'; width:'+W+'px'
+'; height:'+H+'px'
+'; clip:rect(0,'+W+','+H+',0)'
+'; visibility:'
+(null==visible || 1==visible ? 'visible':'hidden')
+(null==zIndex ? '' : '; z-index:'+zIndex)
+(null==bgColor ? '' : '; background-color:'+bgColor);

var LR = '<DIV id='+id+' style="'+ST+'">CPU-Temperature is very high!<br><input type="button" value="Close" onclick="deleteLayer(\'LYR1\')"></DIV>';

if (document.body) {
if (document.body.insertAdjacentHTML)
document.body.insertAdjacentHTML("BeforeEnd",LR);
else if (document.createElement && document.body.appendChild) {
var newNode = document.createElement('div');
newNode.setAttribute('id',id);
newNode.setAttribute('style',ST);
document.body.appendChild(newNode);
}
}
}
}
var audio = new Audio('sounds/alert.mp3');
audio.play();
var x = window.innerWidth/2-100;
var y = window.innerHeight/2-50;

makeLayer('LYR1',x,y,200,100,'red',1,1);
</script>
<?php
}

$output = shell_exec('cat /proc/loadavg');
$sysload = substr($output,0,strpos($output," "))*100;

$stat1 = file('/proc/stat');
sleep(1);
$stat2 = file('/proc/stat');
$info1 = explode(" ", preg_replace("!cpu +!", "", $stat1[0]));
$info2 = explode(" ", preg_replace("!cpu +!", "", $stat2[0]));
$dif = array();
$dif['user'] = $info2[0] - $info1[0];
$dif['nice'] = $info2[1] - $info1[1];
$dif['sys'] = $info2[2] - $info1[2];
$dif['idle'] = $info2[3] - $info1[3];
$total = array_sum($dif);
$cpu = array();
foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 1);
$cpuusage = round($cpu['user'] + $cpu['sys'], 2);
$output = shell_exec('grep -c processor /proc/cpuinfo');
$cpucores = $output;

$output = shell_exec('cat /proc/uptime');
$uptime = format_time(substr($output,0,strpos($output," ")));
$idletime = format_time((substr($output,strpos($output," ")))/$cpucores);

?>
<div class="panel panel-default">
<!-- Standard-Panel-Inhalt -->
<div class="panel-heading">System Info</div>
<!-- Tabelle -->
<div class="table-responsive">
<table id="sysinfo" class="table table-condensed">
<tbody>
<tr>
<?php
if ($cputemp !== NULL) {
?>
<th>CPU-Temperature</th>
<?php
}
?>
<?php
if ($cpufreq !== NULL) {
?>
<th>CPU-Frequency</th>
<?php
}
?>
<th>System-Load</th>
<th>CPU-Usage</th>
<th>Uptime</th>
<th>Idle</th>
</tr>
<tr class="gatewayinfo">
<?php
if ($cputemp !== NULL) {
?>
<td><?php echo $cputemp; ?> &deg;C</td>
<?php
}
?>
<?php
if ($cpufreq !== NULL) {
?>
<td><?php echo $cpufreq; ?> MHz</td>
<?php
}
?>
<td><?php echo $sysload; ?> %</td>
<td>
<?php
if (defined("SHOWPROGRESSBARS")) {