<?php
#file: netzlast.php
header ('Content-Type:text/html; charset="utf-8"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');


$defaultDevice= 'auto';      //config:string: Networkdevice e.g. 'eth0' :: '' or 'auto' set this for the device with highest traffic.
$checkT       = 1000;        //config:int   : Time in ms between ticks ( waiting in JS ). If you doubt set 1000 (1s)
$defTickWith  = 5;           //config:int   : size (width of a tick in px). 5 is a good value. $maxTicks (see below) can setthis higher.
$maxTicks     = 'auto';         //config:int   : max. number of ticks on to the "canvas". If you doubt set to 'auto' or 0.
$maxDefault   = 0;           //config:int   : First max value of bytes/s. see below.
$max['eth0']  = 0;           //config:int   : First maximal value of bytes/s for named device. If you doubt set 0.
                             //example: This device can work with 100 MBit. Set this value to 100000000 / 8 = 12500000
$TxTickColor  = '#ffb300';   //config:string: CSS-color for Tx.
$RxTickColor  = '#00b3ff';   //config:string: CSS-color for Rx.
$denySearchM  = true;        //config:bolean: Send <meta name="robots" value="noindex"> ?.
$showTimeDiff = false;       //config:bolean: Show the real time between 2 ticks?.

//config:string: Title to show. You can use [DEVICE] as placeholder for the (auto)selected device.
$siteTitle    =  htmlspecialchars( $_SERVER['SERVER_NAME'] . '::' . '[DEVICE]'); 

require 'netzlast.inc.php';
$oNetzlast = new Netzlast();

if ('' == $defaultDevice || 'auto' == $defaultDevice ) {
    $defaultDevice = $oNetzlast -> getHighTrafficDevice();
}

if ( isset( $_GET['device'] ) ) {
    $device = $_GET['device'];
} else {
    $device = $defaultDevice;
}
if ( isset( $max[$device] ) ) {
    $maxDefault = $max[$device];
}

if ( ('auto') == $maxTicks or 1 > $maxTicks ) { 
    $maxTicks = 0;
}
$siteTitle = str_replace( '[DEVICE]', htmlspecialchars( $device ), $siteTitle );



?><!DOCTYPE html>
<html>
    <head>
        <title><?=$siteTitle;?></title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <?php  
        if ( $denySearchM ) {
            echo '<meta name="robots" content="noindex">';
        } 
        ?>
        <style type="text/css">
        html,body { margin:0; padding: 0; background-color:#fafafa; font-family: serif,times,roman; color:black; }
        h1 { margin:0; padding:.3em .5em .3em 2.5em; background-color:#ffb300; border-bottom:3px solid gray; font-size:1.5em; white-space:nowrap; background-image: url("logo_80x80.png"); background-repeat:no-repeat; background-size: 1.5em 1.5em; background-position:.5em .25em;}            
        main          { padding: 0 1rem 1rem 1rem; }
        #Controls     { position:absolute; top: 4rem; }
        #NtCanvasRX   { position: absolute; top: 7rem; left: 1rem; height: 400px; right: 1em; border: 1px solid black; text-align: right; overflow: hidden; background-color:rgba(240,240,240,0) }        
        #NtCanvasTX   { position: absolute; top: 7rem; left: 1rem; height: 400px; right: 1em; border: 1px solid black; text-align: right; overflow: hidden;}        
        #maximum      { position:absolute; top: 5.5rem; padding: .25rem .5rem ; left: 2rem; background-color:#fafafa; border: 1px solid black;  z-index:100; background-color:rgb(250,250,250); }
        #ticker       { position:absolute; top: 8.5rem; left: 2.5rem;z-index:99 }
        .NtCanvasItem {  position:relative; top: 0px; display:inline-block; background-color:rgba(240,240,240,.5) };
        .controls     { height: 1.8rem; border: 1px solid gray;}
        .RxBg         { background-color: <?=$RxTickColor;?>; }
        .TxBg         { background-color: <?=$TxTickColor;?>; }
        
        </style>
        <script>
        var device       = '<?= htmlspecialchars( $device );?>';
        var checkT       =  <?= intval( $checkT );?>;
        var maxTicks     =  <?= intval( $maxTicks );?>;
        var maxDefault   =  <?= intval( $maxDefault );?>;
        
        var max      = maxDefault;
        var oldData = JSON.parse('<?=$oNetzlast -> getNetzlastAsJson(); ?>');
        var newData = new Array();
        var arTicker  = new Array();
        var devicesSelector = '';
        var run;

       
        function changeDevice () {
            document.location.href='?device=' + document.getElementById( 'devicesSelector' ).value;
        }
        
        function resetTicker() {
            document.location.reload();
        }

        function getData() {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if ( this.readyState == 4 && this.status == 200 ) {
                    ticker( xhttp.responseText );
                }
            };
            xhttp.open( "GET", "netzlast-api.php?device=" + device, true );
            xhttp.send();
        }

        
        function ticker( json ) {
            var newData        = JSON.parse( json );
            var NtCanvasHeight = document.getElementById('NtCanvasTX').offsetHeight;
            var NtCanvasWidth  = document.getElementById('NtCanvasTX').offsetWidth;
            var maxTicks       = Math.round( NtCanvasWidth / <?=$defTickWith;?> ) + 1;
            if ( <?=$maxTicks;?> > 0 ) {
                if ( maxTicks > <?=$maxTicks;?> ) {
                    maxTicks = <?=$maxTicks;?>;
                }
            }
            var tickWidth      = Math.round( NtCanvasWidth / maxTicks );
            if ( tickWidth < 1 ) {
                tickWidth = 1;
                maxTicks  = NtCanvasWidth;
            }
            var rx             = 0; 
            var tx             = 0;
            var out            = '';
            for ( key in newData ) {
                if ( "time" != key && 'error' != key ) {
                    var timeDiff = newData['time'] - oldData['time'];
<?php
if( $showTimeDiff ) {
    echo 'out = out + "ZeitDiff:   " + timeDiff + "\n";';
}
?>
                    
                    rx  = Math.abs( Math.round( ( newData[key]['RX'] - oldData[key]['RX'] ) / timeDiff ) );
                    tx  = Math.abs(Math.round( ( newData[key]['TX']  - oldData[key]['TX'] ) / timeDiff ) );
                    
                    if ( max < rx ) { max = rx; } 
                    if ( max < tx ) { max = tx; } 

                    out = out + "Rx (Empfangen): " +  humanBytes( rx ) + "/s\n";
                    out = out + "Tx (Gesendet):  " +  humanBytes( tx ) + "/s\n";
                }
            }
            
            document.getElementById("ticker").innerHTML = out;
            
            oldData = newData;
            
            arTicker.push( [rx, tx] );
            if ( maxTicks < arTicker.length ) {
                arTicker.shift(); 
            }
            
            document.getElementById('maximumValue').innerHTML = humanBytes( max );
            
            var itemFaktor = NtCanvasHeight / max;
            
            var s = '<span style="display:inline-block; width:0px; height:' + NtCanvasHeight + 'px;"></span>';
            for ( i=0; i < arTicker.length; i++ ) {
                item = arTicker[i];
                zIndex = ( item[0] < item[1] )? 25 : 20;
                s = s + '<span class="NtCanvasItem RxBg" style="z-index: ' + zIndex + '; width:' +  tickWidth + 'px; height:' + (item[0] * itemFaktor) + 'px;"></span>';
            }
            document.getElementById( 'NtCanvasRX' ).innerHTML = s;
            
            s = '<span style="display:inline-block; width:0px; height:' + NtCanvasHeight + 'px;"></span>';
            for (i=0; i < arTicker.length; i++ ) {
                item = arTicker[i];
                zIndex = ( item[0] < item[1] ) ? 20 : 25;
                s = s + '<span class="NtCanvasItem TxBg" style="z-index: ' + zIndex + '; width:' +  tickWidth + 'px; height:' + (item[1] * itemFaktor) + 'px;"></span>';
            }
            document.getElementById( 'NtCanvasTX' ).innerHTML = s;
            run = window.setTimeout( "getData();", checkT );
        }

        function humanBytes(z) {
            var s = '';
            var ar = ['', 'Kilo', 'Mega', 'Giga', 'Terra', 'Peta'];
            i = 0;
            while ( z >= 1000 ) {
                z = z / 1000;
                i++;
            }
            return ( Math.round( z * 100 ) / 100 ).toString() + ' ' + ar[i] + 'Bytes';
        }
        
        </script>
    </head>
    <body>
        <header>
            <h1 id="title"><?=$siteTitle;?></h1>
        </header>
        <main>
            <div id="Controls">
                <select class="controls" id="devicesSelector" onChange="changeDevice();">
<?php
    foreach( $oNetzlast -> getDevicesAsArray() as $optDevice ) {
        if ( $optDevice == $device ) {
            echo '<option selected="selected" value="' .  htmlspecialchars( $optDevice ) . '">' . htmlspecialchars( $optDevice ) . '</option>';
        } else {
            echo '<option value="' .  htmlspecialchars( $optDevice ) . '">' . htmlspecialchars( $optDevice ) . '</option>';
        }
    }
?>
                </select> <button class="controls" onClick="resetTicker();">Reset</button>
            </div>        
            <div id="NtCanvasTX" role="img"></div>        
            <div id="NtCanvasRX" role="img"></div>
            <pre id="maximum">Maximum: <span id="maximumValue"></span>/s <span class="RxBg"> Rx </span> <span class="TxBg"> Tx </span></pre>
            <pre id="ticker" style="height:6rem">Wird initialisiert…</pre>
            <script>
                document.getElementById( 'maximumValue' ).innerHTML = humanBytes( max );
                run = window.setTimeout( "getData();", 100 );
            </script>
        </main>
    </body>
</html>