Merge pull request from dadav/feature/session_log

add session functionality to session-stats
This commit is contained in:
Simone Margaritelli 2020-01-19 14:17:28 +01:00 committed by GitHub
commit 67bbcfef9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 139 additions and 81 deletions
pwnagotchi

@ -105,6 +105,7 @@ main.plugins.led.patterns.peer_detected = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.peer_lost = "oo oo oo oo oo oo oo" main.plugins.led.patterns.peer_lost = "oo oo oo oo oo oo oo"
main.plugins.session-stats.enabled = true main.plugins.session-stats.enabled = true
main.plugins.session-stats.save_directory = "/var/tmp/pwnagotchi/sessions/"
main.log.path = "/var/log/pwnagotchi.log" main.log.path = "/var/log/pwnagotchi.log"
main.log.rotation.enabled = true main.log.rotation.enabled = true

@ -1,8 +1,10 @@
import os import os
import logging import logging
import threading import threading
from datetime import datetime from time import sleep
from datetime import datetime,timedelta
from pwnagotchi import plugins from pwnagotchi import plugins
from pwnagotchi.utils import StatusFile
from flask import render_template_string from flask import render_template_string
from flask import jsonify from flask import jsonify
@ -44,15 +46,25 @@ TEMPLATE = """
return ret; return ret;
}; };
function loadData(url, elm, title) { function loadFiles(url, elm) {
var data = ajaxDataRenderer(url);
var x = document.getElementById(elm);
$.each(data['files'], function( index, value ) {
var option = document.createElement("option");
option.text = value;
x.add(option);
});
}
function loadData(url, elm, title, fill) {
var data = ajaxDataRenderer(url); var data = ajaxDataRenderer(url);
var plot_os = $.jqplot(elm, data.values,{ var plot_os = $.jqplot(elm, data.values,{
title: title, title: title,
stackSeries: true, stackSeries: fill,
seriesDefaults: { seriesDefaults: {
showMarker: false, showMarker: !fill,
fill: true, fill: fill,
fillAndStroke: true fillAndStroke: fill
}, },
legend: { legend: {
show: true, show: true,
@ -97,20 +109,34 @@ TEMPLATE = """
}); });
} }
function loadAll() { function loadSessionFiles() {
loadData('/plugins/session-stats/os', 'chart_os', 'OS') loadFiles('/plugins/session-stats/session', 'session');
loadData('/plugins/session-stats/temp', 'chart_temp', 'Temp') $("#session").change(function() {
loadData('/plugins/session-stats/nums', 'chart_nums', 'Wifi') loadSessionData();
loadData('/plugins/session-stats/duration', 'chart_duration', 'Sleeping') });
loadData('/plugins/session-stats/epoch', 'chart_epoch', 'Epochs')
} }
loadAll(); function loadSessionData() {
setInterval(loadAll, 60000); var x = document.getElementById("session");
var session = x.options[x.selectedIndex].text;
loadData('/plugins/session-stats/os' + '?session=' + session, 'chart_os', 'OS', false)
loadData('/plugins/session-stats/temp' + '?session=' + session, 'chart_temp', 'Temp', false)
loadData('/plugins/session-stats/nums' + '?session=' + session, 'chart_nums', 'Wifi', true)
loadData('/plugins/session-stats/duration' + '?session=' + session, 'chart_duration', 'Sleeping', true)
loadData('/plugins/session-stats/epoch' + '?session=' + session, 'chart_epoch', 'Epochs', false)
}
loadSessionFiles();
loadSessionData();
setInterval(loadSessionData, 60000);
}); });
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<select id="session" style="width:100%;">
<option selected>Current</option>
</select>
<div id="chart_os" style="height:400px;width:100%; "></div> <div id="chart_os" style="height:400px;width:100%; "></div>
<div id="chart_temp" style="height:400px;width:100%; "></div> <div id="chart_temp" style="height:400px;width:100%; "></div>
<div id="chart_nums" style="height:400px;width:100%; "></div> <div id="chart_nums" style="height:400px;width:100%; "></div>
@ -119,6 +145,25 @@ TEMPLATE = """
{% endblock %} {% endblock %}
""" """
class GhettoClock:
def __init__(self):
self.lock = threading.Lock()
self._track = datetime.now()
self._counter_thread = threading.Thread(target=self.counter)
self._counter_thread.daemon = True
self._counter_thread.start()
def counter(self):
while True:
with self.lock:
self._track += timedelta(seconds=1)
sleep(1)
def now(self):
with self.lock:
return self._track
class SessionStats(plugins.Plugin): class SessionStats(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com' __author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '0.1.0' __version__ = '0.1.0'
@ -126,17 +171,23 @@ class SessionStats(plugins.Plugin):
__description__ = 'This plugin displays stats of the current session.' __description__ = 'This plugin displays stats of the current session.'
def __init__(self): def __init__(self):
self.ready = False
self.lock = threading.Lock() self.lock = threading.Lock()
self.options = dict() self.options = dict()
self.stats = dict() self.stats = dict()
self.clock = GhettoClock()
def on_loaded(self): def on_loaded(self):
""" """
Gets called when the plugin gets loaded Gets called when the plugin gets loaded
""" """
# this has to happen in "loaded" because the options are not yet
# available in the __init__
os.makedirs(self.options['save_directory'], exist_ok=True)
self.session_name = "stats_{}.json".format(self.clock.now().strftime("%Y_%m_%d_%H_%M"))
self.session = StatusFile(os.path.join(self.options['save_directory'],
self.session_name),
data_format='json')
logging.info("Session-stats plugin loaded.") logging.info("Session-stats plugin loaded.")
self.ready = True
def on_unloaded(self, ui): def on_unloaded(self, ui):
pass pass
@ -146,7 +197,8 @@ class SessionStats(plugins.Plugin):
Save the epoch_data to self.stats Save the epoch_data to self.stats
""" """
with self.lock: with self.lock:
self.stats[datetime.now().strftime("%H:%M:%S")] = epoch_data self.stats[self.clock.now().strftime("%H:%M:%S")] = epoch_data
self.session.update(data={'data': self.stats})
@staticmethod @staticmethod
def extract_key_values(data, subkeys): def extract_key_values(data, subkeys):
@ -162,6 +214,8 @@ class SessionStats(plugins.Plugin):
if not path or path == "/": if not path or path == "/":
return render_template_string(TEMPLATE) return render_template_string(TEMPLATE)
session_param = request.args.get('session')
if path == "os": if path == "os":
extract_keys = ['cpu_load','mem_usage',] extract_keys = ['cpu_load','mem_usage',]
elif path == "temp": elif path == "temp":
@ -184,12 +238,15 @@ class SessionStats(plugins.Plugin):
] ]
elif path == "epoch": elif path == "epoch":
extract_keys = [ extract_keys = [
'blind_for_epochs',
'inactive_for_epochs',
'active_for_epochs', 'active_for_epochs',
'blind_for_epochs',
] ]
elif path == "session":
return jsonify({'files': os.listdir(self.options['save_directory'])})
with self.lock: with self.lock:
return jsonify(SessionStats.extract_key_values(self.stats, extract_keys)) data = self.stats
if session_param and session_param != 'Current':
file_stats = StatusFile(os.path.join(self.options['save_directory'], session_param), data_format='json')
data = file_stats.data_field_or('data', default=dict())
return jsonify(SessionStats.extract_key_values(data, extract_keys))