Skip to content

Instantly share code, notes, and snippets.

@Nalorokk
Created April 19, 2020 12:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Nalorokk/b42339200be01c95119b0a8f8d7c50b1 to your computer and use it in GitHub Desktop.
Save Nalorokk/b42339200be01c95119b0a8f8d7c50b1 to your computer and use it in GitHub Desktop.
Keenetic metrics to InfluxDB
#!/bin/php
<?php
ini_set('default_socket_timeout', 15);
ini_set('display_errors', 1);
error_reporting(E_ALL);
define('LOGIN', 'admin');
define('PASSWORD', 'password');
define('INFLUXDB', 'homedb');
define('KEENHOST', '192.168.1.1:81');
define('INFLUXHOST', 'localhost:8086');
$template1 = '{"rrd":[{"attribute":"rxbytes","detail":0},{"attribute":"txbytes","detail":0}],"mac":""}';
$prev_record = query(INFLUXDB, "SELECT * FROM traffic ORDER BY time DESC LIMIT 1");
$prev_time = $prev_record[0][0];
if(keen_auth(LOGIN, PASSWORD)) {
$metrics = keen_request('rci/', '[{"show":{"ip":{"hotspot":{"details":"none"}}}}]');
$data = $metrics[2];
$macTable = array();
foreach ($data[0]['show']['ip']['hotspot']['host'] as $host) {
$name = $host['name'];
if(empty($name)) {
$name = $host['hostname'];
}
$name = preg_replace("/[^A-Za-z0-9А-Яа-я ]/u", '', $name);
$name = preg_replace("/[ ]/u", '\ ', $name);
$macTable[$host['mac']] = $name;
}
$bigRequest = json_decode('{"show":{"ip":{"hotspot":[]}}}', 1);
$macs = array_keys($macTable);
foreach ($macTable as $mac => $_) {
$request = json_decode($template1, 1);
$request['mac'] = $mac;
$bigRequest['show']['ip']['hotspot'][] = $request;
}
$now = microtime(true);
$allMetrics = keen_request('rci/', json_encode($bigRequest));
$parsed = array();
$maxTime = 0;
foreach ($allMetrics[2]['show']['ip']['hotspot'] as $id => $hotspot) {
$mac = $macs[$id];
if (empty($hotspot['rrd'][0]['data'])) {
echo "$mac failed\n";
continue;
}
foreach ($hotspot['rrd'][0]['data'] as $val) {
if($val['t'] > $maxTime) {
$maxTime = $val['t'];
}
@$parsed[$mac][$val['t']]['rxbytes'] = $val['v'];
}
foreach ($hotspot['rrd'][1]['data'] as $val) {
@$parsed[$mac][$val['t']]['txbytes'] = $val['v'];
}
}
$todb = array();
foreach ($parsed as $mac => $macData) {
foreach ($macData as $shift => $v) {
$realtime = $now - $maxTime + $shift;
if($realtime <= $prev_time + 2) {
continue;
}
$todb[] = to_inline('traffic', ['mac' => $mac, 'name' => $macTable[$mac]], ['rxbytes' => $v['rxbytes'].'i', 'txbytes' => $v['txbytes'].'i'], round($realtime * 1000));
}
}
echo "Inserting ".count($todb)." entries\n";
to_db(INFLUXDB, implode("\n", $todb));
}
function keen_auth($login, $password) {
$r = keen_request('auth');
if($r[0]['http_code'] == 401) {
$headers = parse_http($r[1]);
$md5 = md5($login.':'.$headers['X-NDM-Realm'].':'.$password);
$sha = hash('sha256', $headers['X-NDM-Challenge'].$md5);
$r2 = keen_request('auth', json_encode(['login' => $login, 'password' => $sha]));
if($r2[0]['http_code'] == 200) {
return true;
}
} elseif ($r[0]['http_code'] == 200) {
return true;
}
return false;
}
function parse_http($http) {
$result = array();
$lines = explode("\n", $http);
foreach ($lines as $line) {
$line = trim($line);
if(strpos($line, ': ') !== false) {
$line = explode(': ', $line);
$result[$line[0]] = $line[1];
}
}
return $result;
}
function keen_request($query, $post = null) {
$url = 'http://'.KEENHOST.'/'.$query;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__.'/keen_cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__.'/keen_cookie.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json'
));
if($post) {
//echo "\nPost data: ".var_export($post, true)."\n\n";
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
}
$data = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
$json = null;
$notheader = mb_strcut($data, $info['header_size']);
if($query == 'rci/') {
$json = json_decode($notheader, 1);
}
return [$info, $data, $json];
}
function to_inline($table, $tags, $values, $time) {
$inline_values = array();
$inline_tags = array();
foreach($values as $key => $value) {
$inline_values[] = "$key=$value";
}
foreach($tags as $key => $tag) {
$inline_tags[] = "$key=$tag";
}
$inline_values = implode(',', $inline_values);
$inline_tags = implode(',', $inline_tags);
if(empty($inline_tags)) {
return "$table $inline_values $time";
}
return "$table,$inline_tags $inline_values $time";
}
function to_db($db, $points) {
$ch = curl_init();
//var_dump($points);
curl_setopt($ch, CURLOPT_URL, "http://".INFLUXHOST."/write?db=$db&precision=ms");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); //timeout in seconds
curl_setopt($ch, CURLOPT_POST, 1 );
curl_setopt($ch, CURLOPT_POSTFIELDS, $points);
$result = curl_exec($ch);
curl_close($ch);
var_dump($result);
return $result;
}
function query($db, $q) {
$ch = curl_init();
$q = urlencode($q);
curl_setopt($ch, CURLOPT_URL, "http://".INFLUXHOST."/query?db=$db&q=$q&epoch=s");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); //timeout in seconds
$result = curl_exec($ch);
curl_close($ch);
$r = json_decode($result, 1);
return $r['results'][0]['series'][0]['values'];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment