Add modules to repository

This commit is contained in:
Sebastian Kinne
2017-11-16 16:42:22 +11:00
commit d0aa1e38ef
707 changed files with 96750 additions and 0 deletions

8
Status/api/fetchcpu.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
$MYDATA=exec("head -n 1 /proc/stat");
$MYDATE=exec("date");
echo $MYDATE."\n".$MYDATA."\n";
?>

8
Status/api/fetchif.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
$MYDATA=exec("grep ".$_GET['if']." /proc/net/dev | tr -s ' ' ' '");
$MYDATE=exec("date");
echo $MYDATE."\n".$MYDATA."\n";
?>

322
Status/api/module.php Normal file
View File

@@ -0,0 +1,322 @@
<?php namespace pineapple;
putenv('LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH').':/sd/lib:/sd/usr/lib');
putenv('PATH='.getenv('PATH').':/sd/usr/bin:/sd/usr/sbin');
class Status extends Module
{
public function route()
{
switch ($this->request->action) {
case 'refreshInfo':
$this->refreshInfo();
break;
case 'getSystem':
$this->getSystem();
break;
case 'getCPU':
$this->getCPU();
break;
case 'getDHCP':
$this->getDHCP();
break;
case 'getMemory':
$this->getMemory();
break;
case 'getWiFi':
$this->getWiFi();
break;
case 'getSwap':
$this->getSwap();
break;
case 'getStorage':
$this->getStorage();
break;
case 'getInterfaces':
$this->getInterfaces();
break;
case 'getMACInfo':
$this->getMACInfo();
break;
case 'getPingInfo':
$this->getPingInfo();
break;
}
}
protected function refreshInfo()
{
$moduleInfo = @json_decode(file_get_contents("/pineapple/modules/Status/module.info"));
$this->response = array('title' => $moduleInfo->title, 'version' => $moduleInfo->version);
}
private function getSystem()
{
$current_time = exec("date");
$up_time = exec("uptime | awk -F, '{sub(\".*up \",x,$1);print $1}'");
$hostname = exec("uci get system.@system[0].hostname");
$machine = $cpu = trim(exec("cat /proc/cpuinfo | grep machine | awk -F: '{print $2}'"));
$info = array(
'currentTime' => $current_time,
'uptime' => $up_time,
'hostname' => $hostname,
'machine' => $machine
);
$this->response = array('info' => $info);
}
private function getCPU()
{
$cpu = trim(exec("cat /proc/cpuinfo | grep cpu | awk -F: '{print $2}'"));
$bogo = trim(exec("cat /proc/cpuinfo | grep Bogo | awk -F: '{print $2}'"));
$type = trim(exec("cat /proc/cpuinfo | grep type | awk -F: '{print $2}'"));
$stat1 = $this->getCoreInformation(); sleep(1); $stat2 = $this->getCoreInformation();
$data = $this->getCpuPercentages($stat1, $stat2);
$cpu_load_ptg = 100 - $data['cpu0']['idle'];
$cpu_load_all = exec("uptime | awk -F 'average:' '{ print $2}'");
$info = array(
'cpuModel' => $cpu,
'bogoMIPS' => $bogo,
'type' => $type,
'loadAveragePourcentage' => $cpu_load_ptg,
'loadAverageAll' => $cpu_load_all
);
$this->response = array('info' => $info);
}
private function getDHCP()
{
$dhcpClients = explode("\n", trim(shell_exec("cat /tmp/dhcp.leases")));
$clientsList = array();
for($i=0;$i<count($dhcpClients);$i++)
{
if($dhcpClients[$i] != "")
{
$dhcp_client = explode(" ", $dhcpClients[$i]);
$mac_address = $dhcp_client[1];
$ip_address = $dhcp_client[2];
$hostname = $dhcp_client[3];
array_push($clientsList, array("hostname" => $hostname, "mac" => $mac_address, "ip" =>$ip_address));
}
}
$info = array(
'clientsList' => $clientsList
);
$this->response = array('info' => $info);
}
private function getMemory()
{
$mem_total = exec("free | grep \"Mem:\" | awk '{ print $2 }'");
$mem_used = exec("free | grep \"Mem:\" | awk '{ print $3 }'");
$mem_free = exec("free | grep \"Mem:\" | awk '{ print $4 }'");
$mem_free_ptg = round(($mem_free / $mem_total) * 100);
$mem_used_ptg = 100 - $mem_free_ptg;
$mem_total = $this->kbytesToString($mem_total);
$mem_used = $this->kbytesToString($mem_used);
$mem_free = $this->kbytesToString($mem_free);
$info = array(
'memoryTotal' => $mem_total,
'memoryFree' => $mem_free,
'memoryFreePourcentage' => $mem_free_ptg,
'memoryUsed' => $mem_used,
'memoryUsedPourcentage' => $mem_used_ptg
);
$this->response = array('info' => $info);
}
private function getWiFi()
{
$wifiClients = explode("\n", trim(shell_exec("iw dev wlan0 station dump | grep \"Station\"")));
$wifiClientsList = array();
for($i=0;$i<count($wifiClients);$i++)
{
if($wifiClients[$i] != "")
{
$wifi_client = explode(" ", $wifiClients[$i]);
$mac_address = $wifi_client[1];
$ip_address = exec("cat /tmp/dhcp.leases | grep \"".$mac_address."\" | awk '{ print $3}'");
$hostname = exec("cat /tmp/dhcp.leases | grep \"".$mac_address."\" | awk '{ print $4}'");
array_push($wifiClientsList, array("hostname" => $hostname, "mac" => $mac_address, "ip" =>$ip_address));
}
}
$info = array(
'wifiClientsList' => $wifiClientsList
);
$this->response = array('info' => $info);
}
private function getSwap()
{
$swap_total = exec("free | grep \"Swap:\" | awk '{ print $2 }'");
$swap_used = exec("free | grep \"Swap:\" | awk '{ print $3 }'");
$swap_free = exec("free | grep \"Swap:\" | awk '{ print $4 }'");
if($swap_total != 0) $swap_available = true; else $swap_available = false;
if($swap_available) $swap_free_ptg = round(($swap_free / $swap_total) * 100); else $swap_free_ptg = 0;
$swap_used_ptg = 100 - $swap_free_ptg;
$swap_total = $this->kbytesToString($swap_total);
$swap_used = $this->kbytesToString($swap_used);
$swap_free = $this->kbytesToString($swap_free);
$info = array(
'swapAvailable' => $swap_available,
'swapTotal' => $swap_total,
'swapFree' => $swap_free,
'swapFreePourcentage' => $swap_free_ptg,
'swapUsed' => $swap_used,
'swapUsedPourcentage' => $swap_used_ptg
);
$this->response = array('info' => $info);
}
private function getStorage()
{
$dfAll = explode("\n", trim(shell_exec("df | grep -v \"Filesystem\"")));
$dfList = array();
for($i=0;$i<count($dfAll);$i++) {
$df_name = exec("df | grep -v \"Filesystem\" | grep \"".$dfAll[$i]."\" | awk '{ print $1}'");
$df_mount = exec("df | grep -v \"Filesystem\" | grep \"".$dfAll[$i]."\" | awk '{ print $6}'");
$df_total = $this->kbytesToString(exec("df | grep -v \"Filesystem\" | grep \"".$dfAll[$i]."\" | awk '{ print $2}'"));
$df_used = $this->kbytesToString(exec("df | grep -v \"Filesystem\" | grep \"".$dfAll[$i]."\" | awk '{ print $3}'"));
$df_used_ptg = exec("df | grep -v \"Filesystem\" | grep \"".$dfAll[$i]."\" | awk '{ print $5}'");
array_push($dfList, array("name" => $df_name, "mount" => $df_mount, "usedPourcentage" =>$df_used_ptg, "used" => $df_used, "total" => $df_total));
}
$info = array(
'storagesList' => $dfList
);
$this->response = array('info' => $info);
}
private function getInterfaces()
{
$interfaces = explode("\n", trim(shell_exec("ifconfig | grep 'encap:Ethernet' | cut -d' ' -f1")));
$interfacesList = array();
for($i=0;$i<count($interfaces);$i++)
{
$interface_name = $interfaces[$i];
$mac_address = exec("ifconfig ".$interfaces[$i]." | grep 'HWaddr' | awk '{ print $5}'"); $mac_address = $mac_address != "" ? $mac_address : "-";
$ip_address = exec("ifconfig ".$interfaces[$i]." | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'"); $ip_address = $ip_address != "" ? $ip_address : "-";
$subnet_mask = exec("ifconfig ".$interfaces[$i]." | grep 'inet addr:' | cut -d: -f4 | awk '{ print $1}'"); $subnet_mask = $subnet_mask != "" ? $subnet_mask : "-";
$gateway = exec("netstat -r | grep 'default' | grep ".$interfaces[$i]." | awk '{ print $2}'"); $gateway = $gateway != "" ? $gateway : "-";
$mode = exec("iwconfig ".$interfaces[$i]." | grep 'Mode:' | cut -d: -f2 | awk '{ print $1}'");
$tx_power = exec("iwconfig ".$interfaces[$i]." | grep 'Tx-Power=' | cut -d= -f2");
array_push($interfacesList, array("name" => $interface_name, "mac" => $mac_address, "ip" =>$ip_address, "subnet" => $subnet_mask, "gateway" => $gateway, "mode" => $mode, "txpower" => $tx_power));
}
$wan = @file_get_contents("http://cloud.wifipineapple.com/ip.php"); $wan = $wan != "" ? $wan : "-";
$gateway = exec("netstat -r | grep 'default' | awk '{ print $2}'"); $gateway = $gateway != "" ? $gateway : "-";
$dnsAll = explode("\n", trim(shell_exec("cat /tmp/resolv.conf.auto | grep nameserver | awk '{ print $2}'")));
$dnsList = array();
for($i=0;$i<count($dnsAll);$i++) {
array_push($dnsList, array("name" => "DNS ".($i+1), "ip" => $dnsAll[$i]));
}
$info = array(
'wanIpAddress' => $wan,
'wanGateway' => $gateway,
'dnsList' => $dnsList,
'interfacesList' => $interfacesList
);
$this->response = array('info' => $info);
}
private function getMACInfo()
{
$content = file_get_contents("http://api.macvendors.com/".$this->request->mac);
$this->response = array('title' => $this->request->mac, "output" => $content);
}
private function getPingInfo()
{
exec ("ping -c4 ".$this->request->ip, $output);
$this->response = array('title' => $this->request->ip, "output" => implode("\n", array_reverse($output)));
}
private function kbytesToString($kb)
{
$units = array('TB','GB','MB','KB');
$scale = 1024*1024*1024;
$ui = 0;
while (($kb < $scale) && ($scale > 1))
{
$ui++;
$scale = $scale / 1024;
}
return sprintf("%0.2f %s", ($kb/$scale),$units[$ui]);
}
private function getCoreInformation()
{
$data = file('/proc/stat');
$cores = array();
foreach( $data as $line )
{
if( preg_match('/^cpu[0-9]/', $line) )
{
$info = explode(' ', $line );
$cores[] = array(
'user' => $info[1],
'nice' => $info[2],
'sys' => $info[3],
'idle' => $info[4]
);
}
}
return $cores;
}
private function getCpuPercentages($stat1, $stat2)
{
if( count($stat1) !== count($stat2) )
{
return;
}
$cpus = array();
for( $i = 0, $l = count($stat1); $i < $l; $i++)
{
$dif = array();
$dif['user'] = $stat2[$i]['user'] - $stat1[$i]['user'];
$dif['nice'] = $stat2[$i]['nice'] - $stat1[$i]['nice'];
$dif['sys'] = $stat2[$i]['sys'] - $stat1[$i]['sys'];
$dif['idle'] = $stat2[$i]['idle'] - $stat1[$i]['idle'];
$total = array_sum($dif);
$cpu = array();
foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 1);
$cpus['cpu' . $i] = $cpu;
}
return $cpus;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

310
Status/js/module.js Normal file
View File

@@ -0,0 +1,310 @@
registerController('Status_Controller', ['$api', '$scope', '$rootScope', '$interval', '$timeout', function($api, $scope, $rootScope, $interval, $timeout) {
$scope.title = "Loading...";
$scope.version = "Loading...";
$scope.refreshInfo = (function() {
$api.request({
module: 'Status',
action: "refreshInfo"
}, function(response) {
$scope.title = response.title;
$scope.version = "v"+response.version;
})
});
$scope.refreshInfo();
}]);
registerController('Status_SystemController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
machine : "Loading...",
currentTime : "Loading...",
uptime : "Loading...",
hostname : "Loading..."
};
$scope.getInfo = function() {
$api.request({
module: 'Status',
action: 'getSystem'
}, function(response) {
$scope.info = response.info;
});
};
$scope.getInfo();
}]);
registerController('Status_CPUController', ['$api', '$scope', '$rootScope', '$filter', '$sce', function($api, $scope, $rootScope, $filter, $sce) {
$scope.info = {
cpuModel : "Loading...",
bogoMIPS : "Loading...",
type : "Loading...",
loadAveragePourcentage : "0",
loadAverageAll : "Loading..."
};
$scope.getInfo = function() {
$api.request({
module: 'Status',
action: 'getCPU'
}, function(response) {
$scope.info = response.info;
});
};
$scope.getSrc = (function() {
$scope.src = $sce.trustAsResourceUrl('/modules/Status/svg/graph_cpu.svg');
});
$scope.setSrc = (function() {
$scope.src = $sce.trustAsResourceUrl('about:blank');
});
$scope.setSrc();
$scope.getInfo();
}]);
registerController('Status_DHCPController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
clientsList : []
};
$scope.title = "Loading...";
$scope.output = "Loading...";
$scope.loading = false;
$scope.getInfo = function() {
$scope.loading = true;
$api.request({
module: 'Status',
action: 'getDHCP'
}, function(response) {
$scope.info = response.info;
$scope.loading = false;
});
};
$scope.getMACInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getMACInfo',
mac: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getPingInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getPingInfo',
ip: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getInfo();
}]);
registerController('Status_MemoryController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
memoryTotal : "Loading...",
memoryFree : "Loading...",
memoryFreePourcentage : "0",
memoryUsed : "Loading...",
memoryUsedPourcentage : "0"
};
$scope.getInfo = function() {
$api.request({
module: 'Status',
action: 'getMemory'
}, function(response) {
$scope.info = response.info;
});
};
$scope.getInfo();
}]);
registerController('Status_WiFiController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
wifiClientsList : []
};
$scope.title = "Loading...";
$scope.output = "Loading...";
$scope.loading = false;
$scope.getInfo = function() {
$scope.loading = true;
$api.request({
module: 'Status',
action: 'getWiFi'
}, function(response) {
$scope.info = response.info;
$scope.loading = false;
});
};
$scope.getMACInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getMACInfo',
mac: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getPingInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getPingInfo',
ip: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getInfo();
}]);
registerController('Status_SwapController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
swapAvailable : false,
swapTotal : "Loading...",
swapFree : "Loading...",
swapFreePourcentage : "0",
swapUsed : "Loading...",
swapUsedPourcentage : "0"
};
$scope.getInfo = function() {
$api.request({
module: 'Status',
action: 'getSwap'
}, function(response) {
$scope.info = response.info;
});
};
$scope.getInfo();
}]);
registerController('Status_StorageController', ['$api', '$scope', '$rootScope', '$filter', function($api, $scope, $rootScope, $filter) {
$scope.info = {
storagesList : []
};
$scope.loading = false;
$scope.getInfo = function() {
$scope.loading = true;
$api.request({
module: 'Status',
action: 'getStorage'
}, function(response) {
$scope.info = response.info;
$scope.loading = false;
});
};
$scope.getInfo();
}]);
registerController('Status_InterfaceController', ['$api', '$scope', '$rootScope', '$filter', '$sce', function($api, $scope, $rootScope, $filter, $sce) {
$scope.info = {
wanIpAddress : "Loading...",
wanGateway : "Loading...",
dnsList : [],
interfacesList : []
};
$scope.title = "Loading...";
$scope.output = "Loading...";
$scope.loading = false;
$scope.getMACInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getMACInfo',
mac: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getPingInfo = function(param) {
$scope.title = "Loading...";
$scope.output = "Loading...";
$api.request({
module: 'Status',
action: 'getPingInfo',
ip: param
}, function(response) {
$scope.title = response.title;
$scope.output = response.output;
});
};
$scope.getInfo = function() {
$scope.loading = true;
$api.request({
module: 'Status',
action: 'getInterfaces'
}, function(response) {
$scope.info = response.info;
$scope.loading = false;
});
};
$scope.getSrc = (function(param) {
$scope.src = $sce.trustAsResourceUrl('/modules/Status/svg/graph_if.svg?'+param);
$scope.interfaceName = param;
});
$scope.setSrc = (function() {
$scope.src = $sce.trustAsResourceUrl('about:blank');
});
$scope.setSrc();
$scope.getInfo();
}]);

460
Status/module.html Normal file
View File

@@ -0,0 +1,460 @@
<div class="panel panel-default" ng-controller="Status_Controller"><div class="panel-heading"><h4 class="panel-title pull-left">{{title}}</h4><span class="pull-right">{{version}}</span><div class="clearfix"></div></div></div>
<div class="row">
<div class="col-md-6" ng-controller="Status_SystemController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">System</h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<span class="col-sm-3"><strong>Machine</strong></span>
<span class="col-sm-5">{{info.machine}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Current Time</strong></span>
<span class="col-sm-5">{{info.currentTime}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Uptime</strong></span>
<span class="col-sm-5">{{info.uptime}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Hostname</strong></span>
<span class="col-sm-5">{{info.hostname}}</span>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6" ng-controller="Status_CPUController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">CPU</h4>
<div class="btn-group pull-right">
<button type="button" class="btn btn-default btn-xs" ng-click="getSrc()" data-toggle="modal" data-target="#CPUModal">Graph</button>
<button type="button" class="btn btn-info btn-xs" ng-click="getInfo()">Refresh</button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<span class="col-sm-3"><strong>CPU Model</strong></span>
<span class="col-sm-5">{{info.cpuModel}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>System Type</strong></span>
<span class="col-sm-5">{{info.type}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Load Average</strong></span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{info.loadAveragePourcentage}}%;">
{{info.loadAveragePourcentage}}%
</div>
</div>
</div>
<span class="col-sm-3">{{info.loadAverageAll}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>BogoMIPS</strong></span>
<span class="col-sm-5">{{info.bogoMIPS}}</span>
</div>
</form>
</div>
</div>
<div class="modal fade" id="CPUModal" tabindex="-1" role="dialog" aria-labelledby="CPUModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="setSrc()" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="CPUModalLabel">CPU Monitoring</h4>
</div>
<div class="modal-body">
<iframe ng-src="{{src}}" width="100%" height="275" frameborder="0" type="image/svg+xml"></iframe>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" ng-click="setSrc()" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" ng-controller="Status_MemoryController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">Memory</h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<span class="col-sm-3"><strong>Total Available</strong></span>
<span class="col-sm-5">{{info.memoryTotal}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Free</strong></span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{info.memoryFreePourcentage}}%;">
{{info.memoryFreePourcentage}}%
</div>
</div>
</div>
<span class="col-sm-3">{{info.memoryFree}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Used</strong></span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{info.memoryUsedPourcentage}}%;">
{{info.memoryUsedPourcentage}}%
</div>
</div>
</div>
<span class="col-sm-3">{{info.memoryUsed}}</span>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6" ng-controller="Status_SwapController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">Swap</h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group" ng-show="(info.swapAvailable)">
<span class="col-sm-3"><strong>Total Available</strong></span>
<span class="col-sm-5">{{info.swapTotal}}</span>
</div>
<div class="form-group" ng-show="(info.swapAvailable)">
<span class="col-sm-3"><strong>Free</strong></span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{info.swapFreePourcentage}}%;">
{{info.swapFreePourcentage}}%
</div>
</div>
</div>
<span class="col-sm-3">{{info.swapFree}}</span>
</div>
<div class="form-group" ng-show="(info.swapAvailable)">
<span class="col-sm-3"><strong>Used</strong></span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{info.swapUsedPourcentage}}%;">
{{info.swapUsedPourcentage}}%
</div>
</div>
</div>
<span class="col-sm-3">{{info.swapUsed}}</span>
</div>
<div class="form-group" ng-show="(!info.swapAvailable)">
<span class="col-sm-3"><strong>Total Available</strong></span>
<span class="col-sm-5"><em>No Swap</em></span>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" ng-controller="Status_WiFiController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">WiFi Clients <span class="badge">{{info.wifiClientsList.length}}</span></h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form ng-hide="loading" class="form-horizontal">
<div ng-repeat="wifiClient in info.wifiClientsList" class="form-group">
<span class="col-sm-4">{{wifiClient['hostname']}}</span>
<span class="col-sm-4">
<button type="button" class="btn btn-default btn-xs" ng-click="getMACInfo(wifiClient['mac'])" data-toggle="modal" data-target="#wiFiModal">{{wifiClient['mac']}}</button>
</span>
<span ng-show="wifiClient['ip'] == '-'" class="col-sm-4">{{wifiClient['ip']}}</span>
<span ng-hide="wifiClient['ip'] == '-'" class="col-sm-4">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(wifiClient['ip'])" data-toggle="modal" data-target="#wiFiModal">{{wifiClient['ip']}}</button>
</span>
</div>
</form>
<span ng-show="(info.wifiClientsList.length === 0 && !loading)">No WiFi Client...</span>
<span ng-show="loading">Loading...</span>
</div>
</div>
<div class="modal fade" id="wiFiModal" tabindex="-1" role="dialog" aria-labelledby="wiFiModal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="wiFiModalLabel">{{title}}</h4>
</div>
<div class="modal-body">
<pre class="scrollable-pre log-pre">{{output}}</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6" ng-controller="Status_DHCPController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">DHCP Clients <span class="badge">{{info.clientsList.length}}</span></h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form ng-hide="loading" class="form-horizontal">
<div ng-repeat="client in info.clientsList" class="form-group">
<span class="col-sm-4">{{client['hostname']}}</span>
<span class="col-sm-4">
<button type="button" class="btn btn-default btn-xs" ng-click="getMACInfo(client['mac'])" data-toggle="modal" data-target="#clientModal">{{client['mac']}}</button>
</span>
<span ng-show="client['ip'] == '-'" class="col-sm-4">{{client['ip']}}</span>
<span ng-hide="client['ip'] == '-'" class="col-sm-4">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(client['ip'])" data-toggle="modal" data-target="#clientModal">{{client['ip']}}</button>
</span>
</div>
</form>
<span ng-show="(info.clientsList.length === 0 && !loading)">No DHCP Client...</span>
<span ng-show="loading">Loading...</span>
</div>
</div>
<div class="modal fade" id="clientModal" tabindex="-1" role="dialog" aria-labelledby="clientModal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="clientModalLabel">{{title}}</h4>
</div>
<div class="modal-body">
<pre class="scrollable-pre log-pre">{{output}}</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" ng-controller="Status_StorageController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">Storage</h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form ng-hide="loading" class="form-horizontal">
<div ng-repeat="storage in info.storagesList" class="form-group">
<span class="col-sm-2"><strong>{{storage['name']}}</strong></span>
<span class="col-sm-2">{{storage['mount']}}</span>
<div class="col-sm-5">
<div class="progress" style="margin-bottom: 0px;">
<div class="progress-bar" role="progressbar" style="min-width: 2em; width: {{storage['usedPourcentage']}};">
{{storage['usedPourcentage']}}
</div>
</div>
</div>
<span class="col-sm-3">{{storage['used']}} / {{storage['total']}}</span>
</div>
</form>
<span ng-show="(info.storagesList.length === 0 && !loading)">No storage...</span>
<span ng-show="loading">Loading...</span>
</div>
</div>
</div>
<div class="col-md-6" ng-controller="Status_InterfaceController">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title pull-left">Interfaces</h4>
<button type="button" class="btn btn-info pull-right btn-xs" ng-click="getInfo()">Refresh</button>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<div ng-hide="loading" class="panel panel-default" >
<div class="panel-heading pointer" data-toggle="collapse" data-target="#wan">wan</div>
<div id="wan" class="panel-collapse collapse">
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<span class="col-sm-3"><strong>IP Address</strong></span>
<span ng-show="info.wanIpAddress == '-'" class="col-sm-5">{{info.wanIpAddress}}</span>
<span ng-hide="info.wanIpAddress == '-'" class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(info.wanIpAddress)" data-toggle="modal" data-target="#interfaceModal">{{info.wanIpAddress}}</button>
</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Gateway</strong></span>
<span ng-show="info.wanGateway == '-'" class="col-sm-5">{{info.wanGateway}}</span>
<span ng-hide="info.wanGateway == '-'" class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(info.wanGateway)" data-toggle="modal" data-target="#interfaceModal">{{info.wanGateway}}</button>
</span>
</div>
<div class="form-group" ng-repeat="dns in info.dnsList">
<span class="col-sm-3"><strong>{{dns['name']}}</strong></span>
<span ng-show="dns['ip'] == '-'" class="col-sm-5">{{dns['ip']}}</span>
<span ng-hide="dns['ip'] == '-'" class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(dns['ip'])" data-toggle="modal" data-target="#interfaceModal">{{dns['ip']}}</button>
</span>
</div>
</form>
</div>
</div>
</div>
<div ng-hide="loading" class="panel panel-default" ng-repeat="interface in info.interfacesList">
<div class="panel-heading pointer" data-toggle="collapse" data-target="#{{interface['name']}}">{{interface['name']}}</div>
<div id="{{interface['name']}}" class="panel-collapse collapse">
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<span class="col-sm-3"><strong>MAC Address</strong></span>
<span class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getMACInfo(interface['mac'])" data-toggle="modal" data-target="#interfaceModal">{{interface['mac']}}</button>
</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>IP Address</strong></span>
<span ng-show="interface['ip'] == '-'" class="col-sm-5">{{interface['ip']}}</span>
<span ng-hide="interface['ip'] == '-'" class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(interface['ip'])" data-toggle="modal" data-target="#interfaceModal">{{interface['ip']}}</button>
</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Subnet Mask</strong></span>
<span class="col-sm-5">{{interface['subnet']}}</span>
</div>
<div class="form-group">
<span class="col-sm-3"><strong>Gateway</strong></span>
<span ng-show="interface['gateway'] == '-'" class="col-sm-5">{{interface['gateway']}}</span>
<span ng-hide="interface['gateway'] == '-'" class="col-sm-5">
<button type="button" class="btn btn-default btn-xs" ng-click="getPingInfo(interface['gateway'])" data-toggle="modal" data-target="#interfaceModal">{{interface['gateway']}}</button>
</span>
</div>
<div class="form-group" ng-show="interface['mode'] != ''">
<span class="col-sm-3"><strong>Mode</strong></span>
<span class="col-sm-5">{{interface['mode']}}</span>
</div>
<div class="form-group" ng-show="interface['mode'] != ''">
<span class="col-sm-3"><strong>TX Power</strong></span>
<span class="col-sm-5">{{interface['txpower']}}</span>
</div>
<button type="button" class="btn btn-default btn-xs" data-toggle="modal" ng-click="getSrc(interface['name'])" data-target="#graphModal">Graph</button>
</form>
</div>
</div>
</div>
<span ng-show="loading">Loading...</span>
</div>
</div>
<div class="modal fade" id="graphModal" tabindex="-1" role="dialog" aria-labelledby="graphModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" ng-click="setSrc()" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="graphModalLabel">{{interfaceName}} Monitoring</h4>
</div>
<div class="modal-body">
<iframe ng-src="{{src}}" width="100%" height="275" frameborder="0" type="image/svg+xml"></iframe>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" ng-click="setSrc()" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="interfaceModal" tabindex="-1" role="dialog" aria-labelledby="interfaceModal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="interfaceModalLabel">{{title}}</h4>
</div>
<div class="modal-body">
<pre class="scrollable-pre log-pre">{{output}}</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>

10
Status/module.info Normal file
View File

@@ -0,0 +1,10 @@
{
"author": "Whistle Master",
"description": "Display status information of the device",
"devices": [
"nano",
"tetra"
],
"title": "Status",
"version": "1.1"
}

199
Status/svg/graph_cpu.svg Normal file
View File

@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
OpenWRT port of this file based originally on the following:
$Id: graph_cpu.php 41 2006-01-12 18:48:27Z mkasper $
part of m0n0wall (http://m0n0.ch/wall)
Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
and Jonathan Watt <jwatt@jwatt.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-->
<svg xml:space='preserve' xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
width='100%' height='100%'
viewBox='0 0 600 300'
preserveAspectRatio='none'
onload='init(evt)'
>
<g id='graph'>
<rect id='bg' x1='0' y1='0' width='600' height='300' fill='white' />
<text id='graph_lbl' x='50' y='15' fill='#435370' text-anchor='end'>CPU</text>
<text id='graph_txt' x='54' y='15' fill='#435370'>--</text>
<text id='error' x='300' y='125' text-anchor='middle' visibility='hidden' fill='blue'>Cannot get data about CPU</text>
<text id='collect_initial' x='300' y='125' text-anchor='middle' visibility='hidden' fill='gray'>Collecting initial data, please wait...</text>
<path id='grid' d='M 2 75 L 600 75 M 2 150 L 600 150 M 2 225 L 600 225' stroke='gray' stroke-opacity='0.5' />
<text id='grid_txt3' x='600' y='223' fill='gray' text-anchor='end'>25%</text>
<text id='grid_txt2' x='600' y='148' fill='gray' text-anchor='end'>50%</text>
<text id='grid_txt1' x='600' y='73' fill='gray' text-anchor='end'>75%</text>
<path id='graph_cpu' d='' fill='none' stroke='#435370' stroke-width='2' stroke-opacity='0.8' />
<line id='axis_x' x1='1' y1='299' x2='600' y2='299' stroke='black' />
<line id='axis_y' x1='1' y1='299.5' x2='1' y2='0' stroke='black' />
</g>
<script type="text/ecmascript">
<![CDATA[
if (typeof getURL == 'undefined') {
getURL = function(url, callback) {
if (!url)
throw '@TR<<graph_No_URL_getURL#No URL for getURL>>';
try {
if (typeof callback.operationComplete == 'function')
callback = callback.operationComplete;
} catch (e) {}
if (typeof callback != 'function')
throw '@TR<<graph_No_callback_function#No callback function for getURL>>';
var http_request = null;
if (typeof XMLHttpRequest != 'undefined') {
http_request = new XMLHttpRequest();
}
else if (typeof ActiveXObject != 'undefined') {
try {
http_request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
http_request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
if (!http_request)
throw '@TR<<graph_Both_undefined#Both getURL and XMLHttpRequest are undefined>>';
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
callback( { success : true,
content : http_request.responseText,
contentType : http_request.getResponseHeader("Content-Type") } );
}
}
http_request.open('GET', url, true);
http_request.send(null);
}
}
var SVGDoc = null;
var last_cpu_total = 0;
var last_cpu_idle = 0;
var cpu_data = new Array();
var max_num_points = 120; // maximum number of plot data points
var step = 600 / max_num_points; // plot X division size
var fetch_url='../api/fetchcpu.php';
function init(evt) {
SVGDoc = evt.target.ownerDocument;
fetch_data();
setInterval('fetch_data()', 1000);
}
function fetch_data() {
if (fetch_url) {
getURL(fetch_url, plot_cpu_data);
} else {
handle_error();
}
}
function plot_cpu_data(obj) {
if (!obj.success || ''==obj.content) {
return handle_error(); // getURL failed to get current CPU load data
}
try {
var data=obj.content.split("\n");
var ugmt=(Date.parse(data[0]))/1000;
data=data[1].split(/\s+/);
var tot=parseInt(data[1])+parseInt(data[2])+parseInt(data[3])+parseInt(data[4]);
var idle=parseInt(data[4]);
} catch (e) {
return;
}
var cpu=0;
if (tot==last_cpu_total) {
cpu=100;
} else {
cpu=100*(idle-last_cpu_idle)/(tot-last_cpu_total);
}
cpu=100-cpu;
last_cpu_idle=idle;
last_cpu_total=tot;
if (!isNumber(cpu)) return handle_error();
switch (cpu_data.length) {
case 0:
SVGDoc.getElementById('collect_initial').setAttributeNS(null, 'visibility', 'visible');
cpu_data[0] = cpu;
fetch_data;
return;
case 1:
SVGDoc.getElementById('collect_initial').setAttributeNS(null, 'visibility', 'hidden');
break;
case max_num_points:
// shift plot to left if the maximum number of plot points has been reached
var i = 0;
while (i < max_num_points) {
cpu_data[i] = cpu_data[++i];
}
--cpu_data.length;
}
cpu_data[cpu_data.length] = cpu;
var path_data = "M 2 " + (298 - cpu_data[0]);
for (var i = 1; i < cpu_data.length; ++i) {
var x = step * i;
var y_cpu = 298 - 2.975*cpu_data[i];
path_data += " L" + x + " " + y_cpu;
}
SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
SVGDoc.getElementById('graph_cpu').setAttributeNS(null, 'd', path_data);
SVGDoc.getElementById('graph_txt').firstChild.data = Math.round(cpu*10)/10 + '%';
}
function handle_error() {
SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
fetch_data();
}
function isNumber(a) {
return typeof a == 'number' && isFinite(a);
}
]]>
</script>
</svg>

335
Status/svg/graph_if.svg Normal file
View File

@@ -0,0 +1,335 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
OpenWRT port of this file based originally on the following:
$Id: graph_cpu.php 41 2006-01-12 18:48:27Z mkasper $
part of m0n0wall (http://m0n0.ch/wall)
Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
and Jonathan Watt <jwatt@jwatt.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributionss in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-->
<svg xml:space='preserve' xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
width='100%' height='100%'
viewBox='0 0 600 300'
preserveAspectRatio='none'
onload='init(evt)'
>
<g id='graph'>
<rect id='bg' x1='0' y1='0' width='600' height='300' fill='white' />
<text id='graph_in_lbl' x='60' y='15' fill='green' text-anchor='end'>In</text>
<text id='graph_out_lbl' x='60' y='35' fill='red' text-anchor='end'>Out</text>
<text id='graph_in_txt' x='70' y='15' fill='green'>--</text>
<text id='graph_out_txt' x='70' y='35' fill='red'>--</text>
<text id='switch_unit' x='250' y='15' fill='#435370' cursor='pointer'>Switch to bytes/s</text>
<text id='switch_scale' x='250' y='35' fill='#435370' cursor='pointer'>Autoscale (follow)</text>
<text id='error' x='300' y='125' text-anchor='middle' visibility='hidden' fill='blue'>Cannot get data about interface</text>
<text id='collect_initial' x='300' y='125' text-anchor='middle' visibility='hidden' fill='gray'>Collecting initial data, please wait...</text>
<path id='grid' d='M 2 75 L 600 75 M 2 150 L 600 150 M 2 225 L 600 225' stroke='gray' stroke-opacity='0.5' />
<text id='grid_txt3' x='600' y='223' fill='gray' text-anchor='end'>--</text>
<text id='grid_txt2' x='600' y='148' fill='gray' text-anchor='end'>--</text>
<text id='grid_txt1' x='600' y='73' fill='gray' text-anchor='end'>--</text>
<path id='graph_out' d='' fill='none' stroke='red' stroke-width='1' stroke-opacity='0.8' />
<path id='graph_in' d='' fill='none' stroke='green' stroke-width='1' stroke-opacity='0.8' />
<line id='axis_x' x1='2' y1='299' x2='600' y2='299' stroke='black' />
<line id='axis_y' x1='1' y1='300' x2='1' y2='0' stroke='black' />
</g>
<script type="text/ecmascript" xlink:href="../js/lang_pack/english.js" />
<script type="text/ecmascript" xlink:href="../js/lang_pack/language.js" />
<script type="text/ecmascript">
<![CDATA[
if (typeof getURL == 'undefined') {
getURL = function(url, callback) {
if (!url) throw 'No URL for getURL';
try {
if (typeof callback.operationComplete == 'function') {
callback = callback.operationComplete;
}
} catch (e) {}
if (typeof callback != 'function') {
throw 'No callback function for getURL';
}
var http_request = null;
if (typeof XMLHttpRequest != 'undefined') {
http_request = new XMLHttpRequest();
} else if (typeof ActiveXObject != 'undefined') {
try {
http_request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
http_request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
if (!http_request) {
throw 'Both getURL and XMLHttpRequest are undefined';
}
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
callback(
{
success : true,
content : http_request.responseText,
contentType : http_request.getResponseHeader("Content-Type")
}
);
}
}
http_request.open('GET', url, true);
http_request.send(null);
}
}
var SVGDoc = null;
var last_ifin = 0;
var last_ifout = 0;
var last_ugmt = 0;
var max = 0;
var plot_in = new Array();
var plot_out = new Array();
var max_num_points = 120; // maximum number of plot data points
var step = 600 / max_num_points ;
var unit = share.bytes;
var scale_type = status_band.follow;
var fetch_url='';
function init(evt) {
/* hacked in fix for all browsers by spectra
* he says is 'ugly', and someone may want to redo the 'right' way */
fetch_url=location.search.split('?');
//fetch_url='/fetchif.cgi?' + fetch_url[fetch_url.length-1];
fetch_url='../api/fetchif.php?if=' + fetch_url[fetch_url.length-1];
/* end hacked in fix */
SVGDoc = evt.target.ownerDocument;
do_translation();
SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
fetch_data();
setInterval('fetch_data()', 1000);
}
function do_translation() {
SVGDoc.getElementById('graph_in_lbl').firstChild.data = status_band.strin;
SVGDoc.getElementById('graph_out_lbl').firstChild.data = status_band.strout;
SVGDoc.getElementById('switch_unit').firstChild.data = status_band.chg_unit + unit + '/s';
SVGDoc.getElementById('switch_scale').firstChild.data = status_band.chg_scale + ' (' + scale_type + ')';
SVGDoc.getElementById('error').firstChild.data = status_band.chg_error;
SVGDoc.getElementById('collect_initial').firstChild.data = status_band.chg_collect_initial;
}
function switch_unit(event) {
unit = (unit == 'bits') ? share.bytes : 'bits';
SVGDoc.getElementById('switch_unit').firstChild.data = status_band.chg_unit + unit + '/s';
}
function switch_scale(event) {
scale_type = (scale_type == status_band.up) ? status_band.follow : status_band.up;
SVGDoc.getElementById('switch_scale').firstChild.data = status_band.chg_scale + ' (' + scale_type + ')';
}
function fetch_data() {
if (fetch_url) {
getURL(fetch_url, plot_data);
} else {
handle_error();
}
}
function plot_data(obj) {
if (!obj.success) return handle_error(); // getURL failed to get data
if (!obj.content) return handle_error(); // getURL get empty data, IE problem
// parse incoming data
// (format: "date" output, newline, proper line of /proc/net/dev)
var data=obj.content.split("\n");
var dateStr=data[0];
//fake timezone cause the real value might confuse JS
dateStr=dateStr.replace(/ [A-Z]+ /, ' GMT ');
var ugmt=(Date.parse(dateStr))/1000;
data=data[1].split(/\s+|:/);
while (data[0]!=parseInt(data[0])) {
data.shift();
if (0==data.length) return;
}
var ifin=parseInt(data[0]);
var ifout=parseInt(data[8]);
if (!isNumber(ifin) || !isNumber(ifout)) {
return handle_error();
}
var diff_ugmt = ugmt - last_ugmt;
var diff_ifin = ifin - last_ifin;
var diff_ifout = ifout - last_ifout;
if (diff_ugmt == 0) diff_ugmt = 1; // avoid division by zero
last_ugmt = ugmt;
last_ifin = ifin;
last_ifout = ifout;
switch (plot_in.length) {
case 0:
SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
plot_in[0] = diff_ifin / diff_ugmt;
plot_out[0] = diff_ifout / diff_ugmt;
return;
case 1:
SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
break;
case max_num_points:
// shift plot to left if the maximum number of plot points has been reached
var i = 0;
while (i < max_num_points) {
plot_in[i] = plot_in[i+1];
plot_out[i] = plot_out[++i];
}
plot_in.length--;
plot_out.length--;
}
plot_in[plot_in.length] = diff_ifin / diff_ugmt;
plot_out[plot_out.length]= diff_ifout / diff_ugmt;
var index_plot = plot_in.length - 1;
SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);
// determine peak for sensible scaling
if (scale_type == status_band.up) {
if (plot_in[index_plot] > max) max = plot_in[index_plot];
if (plot_out[index_plot] > max) max = plot_out[index_plot];
} else if (scale_type == status_band.follow) {
i = 0;
max = 0;
while (i < plot_in.length) {
if (plot_in[i] > max) max = plot_in[i];
if (plot_out[i] > max) max = plot_out[i];
i++;
}
}
var rmax=makeRoundMax(max);
var scale = 298 / rmax;
// change labels accordingly
SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4, unit);
SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4, unit);
SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4, unit);
var path_in = "M 0 " + (298 - (plot_in[0] * scale));
var path_out = "M 0 " + (298 - (plot_out[0] * scale));
for (i = 1; i < plot_in.length; i++) {
var x = step * i;
var y_in = 298 - (plot_in[i] * scale);
var y_out = 298 - (plot_out[i] * scale);
path_in += " L" + x + " " + y_in;
path_out += " L" + x + " " + y_out;
}
SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);
}
function makeRoundMax(max) {
if (unit == share.bytes) {
rmax = 1250;
i = 0;
while (max > rmax) {
//dump(i+'\n');
i++;
if (i && (i % 4 == 0)) {
rmax *= 1.25;
} else {
rmax *= 2;
}
}
} else {
rmax = 1024;
i = 0;
while (max > rmax) {
i++;
if (i && (i % 4 == 0)) {
rmax *= 1.25;
} else {
rmax *= 2;
}
if (i == 8) rmax *= 1.024;
}
}
return rmax;
}
function handle_error() {
SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
}
function isNumber(a) {
return typeof a == 'number' && isFinite(a);
}
function formatSpeed(speed, unit) {
if (unit == 'bits') return formatSpeedBytes(speed);
if (unit == share.bytes) return formatSpeedBits(speed);
}
function formatSpeedBits(speed) {
// format speed in bits/sec, input: bytes/sec
if (speed < 125000) return Math.round(speed / 125) + " Kbps";
if (speed < 125000000) return Math.round(speed / 1250)/100 + " Mbps";
// else
return Math.round(speed / 1250000)/100 + " Gbps"; // wow!
}
function formatSpeedBytes(speed) {
// format speed in bytes/sec, input: bytes/sec
if (speed < 1048576) return Math.round(speed / 10.24)/100 + " " + share.kbytes + "/s";
if (speed < 1073741824) return Math.round(speed / 10485.76)/100 + " " + share.mbytes + "/s";
// else
return Math.round(speed / 10737418.24)/100 + " " + share.mbytes + "/s"; // wow!
}
]]>
</script>
</svg>