From 301a3d99cf42c1583c310c3f4dbc590e1da168b7 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sun, 19 Jan 2020 11:11:13 +0100 Subject: [PATCH 1/2] add session logs --- pwnagotchi/plugins/default/session-stats.py | 219 ++++++++++++-------- 1 file changed, 138 insertions(+), 81 deletions(-) diff --git a/pwnagotchi/plugins/default/session-stats.py b/pwnagotchi/plugins/default/session-stats.py index 96a9d50..2d4a6d9 100644 --- a/pwnagotchi/plugins/default/session-stats.py +++ b/pwnagotchi/plugins/default/session-stats.py @@ -1,8 +1,10 @@ import os import logging import threading -from datetime import datetime +from time import sleep +from datetime import datetime,timedelta from pwnagotchi import plugins +from pwnagotchi.utils import StatusFile from flask import render_template_string from flask import jsonify @@ -31,86 +33,110 @@ TEMPLATE = """ {% block script %} $(document).ready(function(){ - var ajaxDataRenderer = function(url, plot, options) { - var ret = null; - $.ajax({ - async: false, - url: url, - dataType:"json", - success: function(data) { - ret = data; - } - }); - return ret; - }; - - function loadData(url, elm, title) { - var data = ajaxDataRenderer(url); - var plot_os = $.jqplot(elm, data.values,{ - title: title, - stackSeries: true, - seriesDefaults: { - showMarker: false, - fill: true, - fillAndStroke: true - }, - legend: { - show: true, - renderer: $.jqplot.EnhancedLegendRenderer, - placement: 'outsideGrid', - labels: data.labels, - location: 's', - rendererOptions: { - numberRows: '2', - }, - rowSpacing: '0px' - }, - axes:{ - xaxis:{ - renderer:$.jqplot.DateAxisRenderer, - tickOptions:{formatString:'%H:%M:%S'} - }, - yaxis:{ - min: 0, - tickOptions:{formatString:'%.2f'} - } - }, - highlighter: { - show: true, - sizeAdjust: 7.5 - }, - cursor:{ - show: true, - tooltipLocation:'sw' + var ajaxDataRenderer = function(url, plot, options) { + var ret = null; + $.ajax({ + async: false, + url: url, + dataType:"json", + success: function(data) { + ret = data; } - }).replot({ - axes:{ - xaxis:{ - renderer:$.jqplot.DateAxisRenderer, - tickOptions:{formatString:'%H:%M:%S'} - }, - yaxis:{ - min: 0, - tickOptions:{formatString:'%.2f'} - } + }); + return ret; + }; + + 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 plot_os = $.jqplot(elm, data.values,{ + title: title, + stackSeries: fill, + seriesDefaults: { + showMarker: !fill, + fill: fill, + fillAndStroke: fill + }, + legend: { + show: true, + renderer: $.jqplot.EnhancedLegendRenderer, + placement: 'outsideGrid', + labels: data.labels, + location: 's', + rendererOptions: { + numberRows: '2', + }, + rowSpacing: '0px' + }, + axes:{ + xaxis:{ + renderer:$.jqplot.DateAxisRenderer, + tickOptions:{formatString:'%H:%M:%S'} + }, + yaxis:{ + min: 0, + tickOptions:{formatString:'%.2f'} } - }); - } + }, + highlighter: { + show: true, + sizeAdjust: 7.5 + }, + cursor:{ + show: true, + tooltipLocation:'sw' + } + }).replot({ + axes:{ + xaxis:{ + renderer:$.jqplot.DateAxisRenderer, + tickOptions:{formatString:'%H:%M:%S'} + }, + yaxis:{ + min: 0, + tickOptions:{formatString:'%.2f'} + } + } + }); + } - function loadAll() { - loadData('/plugins/session-stats/os', 'chart_os', 'OS') - loadData('/plugins/session-stats/temp', 'chart_temp', 'Temp') - loadData('/plugins/session-stats/nums', 'chart_nums', 'Wifi') - loadData('/plugins/session-stats/duration', 'chart_duration', 'Sleeping') - loadData('/plugins/session-stats/epoch', 'chart_epoch', 'Epochs') - } + function loadSessionFiles() { + loadFiles('/plugins/session-stats/session', 'session'); + $("#session").change(function() { + loadSessionData(); + }); + } - loadAll(); - setInterval(loadAll, 60000); + function loadSessionData() { + 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 %} {% block content %} +
@@ -119,6 +145,25 @@ TEMPLATE = """ {% 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): __author__ = '33197631+dadav@users.noreply.github.com' __version__ = '0.1.0' @@ -126,17 +171,23 @@ class SessionStats(plugins.Plugin): __description__ = 'This plugin displays stats of the current session.' def __init__(self): - self.ready = False self.lock = threading.Lock() self.options = dict() self.stats = dict() + self.clock = GhettoClock() def on_loaded(self): """ 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.") - self.ready = True def on_unloaded(self, ui): pass @@ -146,7 +197,8 @@ class SessionStats(plugins.Plugin): Save the epoch_data to self.stats """ 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 def extract_key_values(data, subkeys): @@ -162,6 +214,8 @@ class SessionStats(plugins.Plugin): if not path or path == "/": return render_template_string(TEMPLATE) + session_param = request.args.get('session') + if path == "os": extract_keys = ['cpu_load','mem_usage',] elif path == "temp": @@ -184,12 +238,15 @@ class SessionStats(plugins.Plugin): ] elif path == "epoch": extract_keys = [ - 'blind_for_epochs', - 'inactive_for_epochs', 'active_for_epochs', + 'blind_for_epochs', ] - - + elif path == "session": + return jsonify({'files': os.listdir(self.options['save_directory'])}) 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)) From 665ad938b4c512de9c4419e073a4d30ecac883f2 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sun, 19 Jan 2020 11:14:05 +0100 Subject: [PATCH 2/2] add save_directory variable --- pwnagotchi/defaults.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml index 45cff59..5f2137f 100644 --- a/pwnagotchi/defaults.toml +++ b/pwnagotchi/defaults.toml @@ -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.session-stats.enabled = true +main.plugins.session-stats.save_directory = "/var/tmp/pwnagotchi/sessions/" main.log.path = "/var/log/pwnagotchi.log" main.log.rotation.enabled = true