mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2025-07-01 18:37:27 -04:00
Merge remote-tracking branch 'origin/pwnagotchi-torch' into pwnagotchi-torch
# Conflicts: # builder/pwnagotchi.yml
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pwnagotchi)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
2
.idea/pwnagotchi.iml
generated
2
.idea/pwnagotchi.iml
generated
@ -4,7 +4,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyDocumentationSettings">
|
<component name="PyDocumentationSettings">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import gym
|
import gymnasium
|
||||||
from gym import spaces
|
from gymnasium import spaces
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import pwnagotchi.ai.featurizer as featurizer
|
import pwnagotchi.ai.featurizer as featurizer
|
||||||
@ -8,7 +8,7 @@ import pwnagotchi.ai.reward as reward
|
|||||||
from pwnagotchi.ai.parameter import Parameter
|
from pwnagotchi.ai.parameter import Parameter
|
||||||
|
|
||||||
|
|
||||||
class Environment(gym.Env):
|
class Environment(gymnasium.Env):
|
||||||
metadata = {'render.modes': ['human']}
|
metadata = {'render.modes': ['human']}
|
||||||
params = [
|
params = [
|
||||||
Parameter('min_rssi', min_value=-200, max_value=-50),
|
Parameter('min_rssi', min_value=-200, max_value=-50),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from gym import spaces
|
from gymnasium import spaces
|
||||||
|
|
||||||
|
|
||||||
class Parameter(object):
|
class Parameter(object):
|
||||||
|
@ -181,7 +181,7 @@ class AsyncTrainer(object):
|
|||||||
if os.path.isfile(self._nn_path):
|
if os.path.isfile(self._nn_path):
|
||||||
back = "%s.bak" % self._nn_path
|
back = "%s.bak" % self._nn_path
|
||||||
os.replace(self._nn_path, back)
|
os.replace(self._nn_path, back)
|
||||||
self._view.set("mode", "AI")
|
self._view.set("mode", " AI")
|
||||||
self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step)
|
self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception("[ai] error while training (%s)", e)
|
logging.exception("[ai] error while training (%s)", e)
|
||||||
|
@ -28,8 +28,8 @@ main.plugins.grid.exclude = [
|
|||||||
"YourHomeNetworkHere"
|
"YourHomeNetworkHere"
|
||||||
]
|
]
|
||||||
|
|
||||||
main.plugins.auto-update.enabled = false
|
main.plugins.auto-update.enabled = true
|
||||||
main.plugins.auto-update.install = false
|
main.plugins.auto-update.install = true
|
||||||
main.plugins.auto-update.interval = 24
|
main.plugins.auto-update.interval = 24
|
||||||
|
|
||||||
main.plugins.net-pos.enabled = false
|
main.plugins.net-pos.enabled = false
|
||||||
@ -39,13 +39,6 @@ main.plugins.gps.enabled = false
|
|||||||
main.plugins.gps.speed = 19200
|
main.plugins.gps.speed = 19200
|
||||||
main.plugins.gps.device = "/dev/ttyUSB0"
|
main.plugins.gps.device = "/dev/ttyUSB0"
|
||||||
|
|
||||||
main.plugins.exp.enabled = true
|
|
||||||
main.plugins.exp.lvl_x_coord = 0
|
|
||||||
main.plugins.exp.lvl_y_coord = 81
|
|
||||||
main.plugins.exp.exp_x_coord = 38
|
|
||||||
main.plugins.exp.exp_y_coord = 81
|
|
||||||
main.plugins.exp.bar_symbols_count = 12
|
|
||||||
|
|
||||||
main.plugins.bluetoothsniffer.enabled = false
|
main.plugins.bluetoothsniffer.enabled = false
|
||||||
main.plugins.bluetoothsniffer.timer = 45 # On how may seconds to scan for bluetooth devices
|
main.plugins.bluetoothsniffer.timer = 45 # On how may seconds to scan for bluetooth devices
|
||||||
main.plugins.bluetoothsniffer.devices_file = "/root/handshakes/bluetooth_devices.json" # Path to the JSON file with bluetooth devices
|
main.plugins.bluetoothsniffer.devices_file = "/root/handshakes/bluetooth_devices.json" # Path to the JSON file with bluetooth devices
|
||||||
@ -146,12 +139,6 @@ main.log.path = "/var/log/pwnagotchi.log"
|
|||||||
main.log.rotation.enabled = true
|
main.log.rotation.enabled = true
|
||||||
main.log.rotation.size = "10M"
|
main.log.rotation.size = "10M"
|
||||||
|
|
||||||
main.plugins.age.enabled = false
|
|
||||||
main.plugins.age.age_x_coord = 0
|
|
||||||
main.plugins.age.age_y_coord = 32
|
|
||||||
main.plugins.age.str_x_coord = 67
|
|
||||||
main.plugins.age.str_y_coord = 32
|
|
||||||
|
|
||||||
ai.enabled = true
|
ai.enabled = true
|
||||||
ai.path = "/root/brain.nn"
|
ai.path = "/root/brain.nn"
|
||||||
ai.laziness = 0.1
|
ai.laziness = 0.1
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
import _thread
|
||||||
import threading
|
import threading
|
||||||
import importlib, importlib.util
|
import importlib, importlib.util
|
||||||
import logging
|
import logging
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
|
||||||
|
|
||||||
default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
|
default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
|
||||||
loaded = {}
|
loaded = {}
|
||||||
database = {}
|
database = {}
|
||||||
locks = {}
|
locks = {}
|
||||||
|
|
||||||
THREAD_POOL_SIZE = 10
|
|
||||||
executor = ThreadPoolExecutor(max_workers=THREAD_POOL_SIZE)
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin:
|
class Plugin:
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -45,7 +42,7 @@ def toggle_plugin(name, enable=True):
|
|||||||
global loaded, database
|
global loaded, database
|
||||||
|
|
||||||
if pwnagotchi.config:
|
if pwnagotchi.config:
|
||||||
if name not in pwnagotchi.config['main']['plugins']:
|
if not name in pwnagotchi.config['main']['plugins']:
|
||||||
pwnagotchi.config['main']['plugins'][name] = dict()
|
pwnagotchi.config['main']['plugins'][name] = dict()
|
||||||
pwnagotchi.config['main']['plugins'][name]['enabled'] = enable
|
pwnagotchi.config['main']['plugins'][name]['enabled'] = enable
|
||||||
save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml')
|
save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml')
|
||||||
@ -97,7 +94,7 @@ def one(plugin_name, event_name, *args, **kwargs):
|
|||||||
try:
|
try:
|
||||||
lock_name = "%s::%s" % (plugin_name, cb_name)
|
lock_name = "%s::%s" % (plugin_name, cb_name)
|
||||||
locked_cb_args = (lock_name, callback, *args, *kwargs)
|
locked_cb_args = (lock_name, callback, *args, *kwargs)
|
||||||
executor.submit(locked_cb, *locked_cb_args)
|
_thread.start_new_thread(locked_cb, locked_cb_args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e))
|
logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e))
|
||||||
logging.error(e, exc_info=True)
|
logging.error(e, exc_info=True)
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import pwnagotchi
|
|
||||||
import pwnagotchi.plugins as plugins
|
|
||||||
import pwnagotchi.ui.faces as faces
|
|
||||||
import pwnagotchi.ui.fonts as fonts
|
|
||||||
from pwnagotchi.ui.components import LabeledValue
|
|
||||||
from pwnagotchi.ui.view import BLACK
|
|
||||||
|
|
||||||
|
|
||||||
class Age(plugins.Plugin):
|
|
||||||
__author__ = 'HannaDiamond'
|
|
||||||
__version__ = '1.0.1'
|
|
||||||
__license__ = 'MIT'
|
|
||||||
__description__ = 'A plugin that will add age and strength stats based on epochs and trained epochs'
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.epochs = 0
|
|
||||||
self.train_epochs = 0
|
|
||||||
|
|
||||||
def on_loaded(self):
|
|
||||||
data_path = '/root/brain.json'
|
|
||||||
self.load_data(data_path)
|
|
||||||
|
|
||||||
|
|
||||||
def on_ui_setup(self, ui):
|
|
||||||
ui.add_element('Age', LabeledValue(color=BLACK, label='♥ Age', value=0,
|
|
||||||
position=(int(self.options["age_x_coord"]),
|
|
||||||
int(self.options["age_y_coord"])),
|
|
||||||
label_font=fonts.Bold, text_font=fonts.Medium))
|
|
||||||
ui.add_element('Strength', LabeledValue(color=BLACK, label='Str', value=0,
|
|
||||||
position=(int(self.options["str_x_coord"]),
|
|
||||||
int(self.options["str_y_coord"])),
|
|
||||||
label_font=fonts.Bold, text_font=fonts.Medium))
|
|
||||||
|
|
||||||
def on_unload(self, ui):
|
|
||||||
with ui._lock:
|
|
||||||
ui.remove_element('Age')
|
|
||||||
ui.remove_element('Strength')
|
|
||||||
|
|
||||||
def on_ui_update(self, ui):
|
|
||||||
ui.set('Age', str(self.abrev_number(self.epochs)))
|
|
||||||
ui.set('Strength', str(self.abrev_number(self.train_epochs)))
|
|
||||||
|
|
||||||
|
|
||||||
def on_ai_training_step(self, agent, _locals, _globals):
|
|
||||||
self.train_epochs += 1
|
|
||||||
if self.train_epochs % 100 == 0:
|
|
||||||
self.strength_checkpoint(agent)
|
|
||||||
|
|
||||||
def on_epoch(self, agent, epoch, epoch_data):
|
|
||||||
self.epochs += 1
|
|
||||||
if self.epochs % 100 == 0:
|
|
||||||
self.age_checkpoint(agent)
|
|
||||||
|
|
||||||
def abrev_number(self, num):
|
|
||||||
if num < 100000:
|
|
||||||
return str(num)
|
|
||||||
else:
|
|
||||||
magnitude = 0
|
|
||||||
while abs(num) >= 1000:
|
|
||||||
magnitude += 1
|
|
||||||
num /= 1000.0
|
|
||||||
abbr = ['', 'K', 'M', 'B', 'T', 'P'][magnitude]
|
|
||||||
return '{}{}'.format('{:.2f}'.format(num).rstrip('0').rstrip('.'), abbr)
|
|
||||||
|
|
||||||
def age_checkpoint(self, agent):
|
|
||||||
view = agent.view()
|
|
||||||
view.set('face', faces.HAPPY)
|
|
||||||
view.set('status', "Wow, I've lived for " + str(self.abrev_number(self.epochs)) + " epochs!")
|
|
||||||
view.update(force=True)
|
|
||||||
|
|
||||||
def strength_checkpoint(self, agent):
|
|
||||||
view = agent.view()
|
|
||||||
view.set('face', faces.MOTIVATED)
|
|
||||||
view.set('status', "Look at my strength go up! \n"
|
|
||||||
"I've trained for " + str(self.abrev_number(self.train_epochs)) + " epochs")
|
|
||||||
view.update(force=True)
|
|
||||||
|
|
||||||
def load_data(self, data_path):
|
|
||||||
if os.path.exists(data_path):
|
|
||||||
with open(data_path) as f:
|
|
||||||
data = json.load(f)
|
|
||||||
self.epochs = data['epochs_lived']
|
|
||||||
self.train_epochs = data['epochs_trained']
|
|
||||||
|
|
@ -1,336 +0,0 @@
|
|||||||
import logging
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import json
|
|
||||||
|
|
||||||
import pwnagotchi
|
|
||||||
import pwnagotchi.agent
|
|
||||||
import pwnagotchi.plugins as plugins
|
|
||||||
import pwnagotchi.ui.fonts as fonts
|
|
||||||
from pwnagotchi.ui.components import LabeledValue
|
|
||||||
from pwnagotchi.ui.view import BLACK
|
|
||||||
|
|
||||||
# Static Variables
|
|
||||||
MULTIPLIER_ASSOCIATION = 1
|
|
||||||
MULTIPLIER_DEAUTH = 2
|
|
||||||
MULTIPLIER_HANDSHAKE = 3
|
|
||||||
MULTIPLIER_AI_BEST_REWARD = 5
|
|
||||||
TAG = "[EXP Plugin]"
|
|
||||||
FACE_LEVELUP = '(≧◡◡≦)'
|
|
||||||
BAR_ERROR = "| error |"
|
|
||||||
FILE_SAVE = "exp_stats"
|
|
||||||
FILE_SAVE_LEGACY = "exp"
|
|
||||||
JSON_KEY_LEVEL = "level"
|
|
||||||
JSON_KEY_EXP = "exp"
|
|
||||||
JSON_KEY_EXP_TOT = "exp_tot"
|
|
||||||
|
|
||||||
|
|
||||||
class EXP(plugins.Plugin):
|
|
||||||
__author__ = 'GaelicThunder'
|
|
||||||
__version__ = '1.0.5'
|
|
||||||
__license__ = 'GPL3'
|
|
||||||
__description__ = 'Get exp every time a handshake get captured.'
|
|
||||||
|
|
||||||
# Attention number masking
|
|
||||||
def LogInfo(self, text):
|
|
||||||
logging.info(TAG + " " + text)
|
|
||||||
|
|
||||||
# Attention number masking
|
|
||||||
def LogDebug(self, text):
|
|
||||||
logging.debug(TAG + " " + text)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.percent = 0
|
|
||||||
self.calculateInitialXP = False
|
|
||||||
self.exp = 0
|
|
||||||
self.lv = 1
|
|
||||||
self.exp_tot = 0
|
|
||||||
# Sets the file type I recommend json
|
|
||||||
self.save_file_mode = self.save_file_modes("json")
|
|
||||||
self.save_file = self.getSaveFileName(self.save_file_mode)
|
|
||||||
# Migrate from old save system
|
|
||||||
self.migrateLegacySave()
|
|
||||||
|
|
||||||
# Create save file
|
|
||||||
if not os.path.exists(self.save_file):
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
# Try loading
|
|
||||||
self.Load(self.save_file, self.save_file_mode)
|
|
||||||
except:
|
|
||||||
# Likely throws an exception if json file is corrupted, so we need to calculate from scratch
|
|
||||||
self.calculateInitialXP = True
|
|
||||||
|
|
||||||
# No previous data, try get it
|
|
||||||
if self.lv == 1 and self.exp == 0:
|
|
||||||
self.calculateInitialXP = True
|
|
||||||
if self.exp_tot == 0:
|
|
||||||
self.LogInfo("Need to calculate Total Exp")
|
|
||||||
self.exp_tot = self.calcActualSum(self.lv, self.exp)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
|
|
||||||
self.expneeded = self.calcExpNeeded(self.lv)
|
|
||||||
|
|
||||||
def on_loaded(self):
|
|
||||||
# logging.info("Exp plugin loaded for %s" % self.options['device'])
|
|
||||||
self.LogInfo("Plugin Loaded")
|
|
||||||
|
|
||||||
def save_file_modes(self, argument):
|
|
||||||
switcher = {
|
|
||||||
"txt": 0,
|
|
||||||
"json": 1,
|
|
||||||
}
|
|
||||||
return switcher.get(argument, 0)
|
|
||||||
|
|
||||||
def Save(self, file, save_file_mode):
|
|
||||||
self.LogDebug('Saving Exp')
|
|
||||||
if save_file_mode == 0:
|
|
||||||
self.saveToTxtFile(file)
|
|
||||||
if save_file_mode == 1:
|
|
||||||
self.saveToJsonFile(file)
|
|
||||||
|
|
||||||
def saveToTxtFile(self, file):
|
|
||||||
outfile = open(file, 'w')
|
|
||||||
print(self.exp, file=outfile)
|
|
||||||
print(self.lv, file=outfile)
|
|
||||||
print(self.exp_tot, file=outfile)
|
|
||||||
outfile.close()
|
|
||||||
|
|
||||||
def loadFromTxtFile(self, file):
|
|
||||||
if os.path.exists(file):
|
|
||||||
outfile = open(file, 'r+')
|
|
||||||
lines = outfile.readlines()
|
|
||||||
linecounter = 1
|
|
||||||
for line in lines:
|
|
||||||
if linecounter == 1:
|
|
||||||
self.exp = int(line)
|
|
||||||
elif linecounter == 2:
|
|
||||||
self.lv == int(line)
|
|
||||||
elif linecounter == 3:
|
|
||||||
self.exp_tot == int(line)
|
|
||||||
linecounter += 1
|
|
||||||
outfile.close()
|
|
||||||
|
|
||||||
def saveToJsonFile(self, file):
|
|
||||||
data = {
|
|
||||||
JSON_KEY_LEVEL: self.lv,
|
|
||||||
JSON_KEY_EXP: self.exp,
|
|
||||||
JSON_KEY_EXP_TOT: self.exp_tot
|
|
||||||
}
|
|
||||||
|
|
||||||
with open(file, 'w') as f:
|
|
||||||
f.write(json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')))
|
|
||||||
|
|
||||||
def loadFromJsonFile(self, file):
|
|
||||||
# Tot exp is introduced with json, no check needed
|
|
||||||
data = {}
|
|
||||||
with open(file, 'r') as f:
|
|
||||||
data = json.loads(f.read())
|
|
||||||
|
|
||||||
if bool(data):
|
|
||||||
self.lv = data[JSON_KEY_LEVEL]
|
|
||||||
self.exp = data[JSON_KEY_EXP]
|
|
||||||
self.exp_tot = data[JSON_KEY_EXP_TOT]
|
|
||||||
else:
|
|
||||||
self.LogInfo("Empty json")
|
|
||||||
|
|
||||||
# TODO: one day change save file mode to file date
|
|
||||||
def Load(self, file, save_file_mode):
|
|
||||||
self.LogDebug('Loading Exp')
|
|
||||||
if save_file_mode == 0:
|
|
||||||
self.loadFromTxtFile(file)
|
|
||||||
if save_file_mode == 1:
|
|
||||||
self.loadFromJsonFile(file)
|
|
||||||
|
|
||||||
def getSaveFileName(self, save_file_mode):
|
|
||||||
file = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
file = file + "/" + FILE_SAVE
|
|
||||||
if save_file_mode == 0:
|
|
||||||
file = file + ".txt"
|
|
||||||
elif save_file_mode == 1:
|
|
||||||
file = file + ".json"
|
|
||||||
else:
|
|
||||||
# See switcher
|
|
||||||
file = file + ".txt"
|
|
||||||
return file
|
|
||||||
|
|
||||||
def migrateLegacySave(self):
|
|
||||||
legacyFile = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
legacyFile = legacyFile + "/" + FILE_SAVE_LEGACY + ".txt"
|
|
||||||
if os.path.exists(legacyFile):
|
|
||||||
self.loadFromTxtFile(legacyFile)
|
|
||||||
self.LogInfo("Migrating Legacy Save...")
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
os.remove(legacyFile)
|
|
||||||
|
|
||||||
def barString(self, symbols_count, p):
|
|
||||||
if p > 100:
|
|
||||||
return BAR_ERROR
|
|
||||||
length = symbols_count - 2
|
|
||||||
bar_char = '▥'
|
|
||||||
blank_char = ' '
|
|
||||||
bar_length = int(round((length / 100) * p))
|
|
||||||
blank_length = length - bar_length
|
|
||||||
res = '|' + bar_char * bar_length + blank_char * blank_length + '|'
|
|
||||||
return res
|
|
||||||
|
|
||||||
def on_ui_setup(self, ui):
|
|
||||||
ui.add_element('Lv', LabeledValue(color=BLACK, label='Lv', value=0,
|
|
||||||
position=(int(self.options["lvl_x_coord"]),
|
|
||||||
int(self.options["lvl_y_coord"])),
|
|
||||||
label_font=fonts.Bold, text_font=fonts.Medium))
|
|
||||||
ui.add_element('Exp', LabeledValue(color=BLACK, label='Exp', value=0,
|
|
||||||
position=(int(self.options["exp_x_coord"]),
|
|
||||||
int(self.options["exp_y_coord"])),
|
|
||||||
label_font=fonts.Bold, text_font=fonts.Medium))
|
|
||||||
|
|
||||||
def on_ui_update(self, ui):
|
|
||||||
self.expneeded = self.calcExpNeeded(self.lv)
|
|
||||||
self.percent = int((self.exp / self.expneeded) * 100)
|
|
||||||
symbols_count = int(self.options["bar_symbols_count"])
|
|
||||||
bar = self.barString(symbols_count, self.percent)
|
|
||||||
ui.set('Lv', "%d" % self.lv)
|
|
||||||
ui.set('Exp', "%s" % bar)
|
|
||||||
|
|
||||||
def calcExpNeeded(self, level):
|
|
||||||
# If the pwnagotchi is lvl <1 it causes the keys to be deleted
|
|
||||||
if level == 1:
|
|
||||||
return 5
|
|
||||||
return int((level ** 3) / 2)
|
|
||||||
|
|
||||||
def exp_check(self, agent):
|
|
||||||
self.LogDebug("EXP CHECK")
|
|
||||||
if self.exp >= self.expneeded:
|
|
||||||
self.exp = 1
|
|
||||||
self.lv = self.lv + 1
|
|
||||||
self.expneeded = self.calcExpNeeded(self.lv)
|
|
||||||
self.displayLevelUp(agent)
|
|
||||||
|
|
||||||
def parseSessionStats(self):
|
|
||||||
sum = 0
|
|
||||||
dir = pwnagotchi.config['main']['plugins']['session-stats']['save_directory']
|
|
||||||
# TODO: remove
|
|
||||||
self.LogInfo("Session-Stats dir: " + dir)
|
|
||||||
for filename in os.listdir(dir):
|
|
||||||
self.LogInfo("Parsing " + filename + "...")
|
|
||||||
if filename.endswith(".json") & filename.startswith("stats"):
|
|
||||||
try:
|
|
||||||
sum += self.parseSessionStatsFile(os.path.join(dir, filename))
|
|
||||||
except:
|
|
||||||
self.LogInfo("ERROR parsing File: " + filename)
|
|
||||||
|
|
||||||
return sum
|
|
||||||
|
|
||||||
def parseSessionStatsFile(self, path):
|
|
||||||
sum = 0
|
|
||||||
deauths = 0
|
|
||||||
handshakes = 0
|
|
||||||
associations = 0
|
|
||||||
with open(path) as json_file:
|
|
||||||
data = json.load(json_file)
|
|
||||||
for entry in data["data"]:
|
|
||||||
deauths += data["data"][entry]["num_deauths"]
|
|
||||||
handshakes += data["data"][entry]["num_handshakes"]
|
|
||||||
associations += data["data"][entry]["num_associations"]
|
|
||||||
|
|
||||||
sum += deauths * MULTIPLIER_DEAUTH
|
|
||||||
sum += handshakes * MULTIPLIER_HANDSHAKE
|
|
||||||
sum += associations * MULTIPLIER_ASSOCIATION
|
|
||||||
|
|
||||||
return sum
|
|
||||||
|
|
||||||
# If initial sum is 0, we try to parse it
|
|
||||||
def calculateInitialSum(self, agent):
|
|
||||||
sessionStatsActive = False
|
|
||||||
sum = 0
|
|
||||||
# Check if session stats is loaded
|
|
||||||
for plugin in pwnagotchi.plugins.loaded:
|
|
||||||
if plugin == "session-stats":
|
|
||||||
sessionStatsActive = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if sessionStatsActive:
|
|
||||||
try:
|
|
||||||
self.LogInfo("parsing session-stats")
|
|
||||||
sum = self.parseSessionStats()
|
|
||||||
except:
|
|
||||||
self.LogInfo("Error parsing session-stats")
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.LogInfo("parsing last session")
|
|
||||||
sum = self.lastSessionPoints(agent)
|
|
||||||
|
|
||||||
self.LogInfo(str(sum) + " Points calculated")
|
|
||||||
return sum
|
|
||||||
|
|
||||||
# Get Last Sessions Points
|
|
||||||
def lastSessionPoints(self, agent):
|
|
||||||
summary = 0
|
|
||||||
summary += agent.LastSession.handshakes * MULTIPLIER_HANDSHAKE
|
|
||||||
summary += agent.LastSession.associated * MULTIPLIER_ASSOCIATION
|
|
||||||
summary += agent.LastSession.deauthed * MULTIPLIER_DEAUTH
|
|
||||||
return summary
|
|
||||||
|
|
||||||
# Helper function to calculate multiple Levels from a sum of EXPs
|
|
||||||
def calcLevelFromSum(self, sum, agent):
|
|
||||||
sum1 = sum
|
|
||||||
level = 1
|
|
||||||
while sum1 > self.calcExpNeeded(level):
|
|
||||||
sum1 -= self.calcExpNeeded(level)
|
|
||||||
level += 1
|
|
||||||
self.lv = level
|
|
||||||
self.exp = sum1
|
|
||||||
self.expneeded = self.calcExpNeeded(level) - sum1
|
|
||||||
if level > 1:
|
|
||||||
# get Excited ;-)
|
|
||||||
self.displayLevelUp(agent)
|
|
||||||
|
|
||||||
def calcActualSum(self, level, exp):
|
|
||||||
lvlCounter = 1
|
|
||||||
sum = exp
|
|
||||||
# I know it wouldn't work if you change the lvl algorithm
|
|
||||||
while lvlCounter < level:
|
|
||||||
sum += self.calcExpNeeded(lvlCounter)
|
|
||||||
lvlCounter += 1
|
|
||||||
return sum
|
|
||||||
|
|
||||||
def displayLevelUp(self, agent):
|
|
||||||
view = agent.view()
|
|
||||||
view.set('face', FACE_LEVELUP)
|
|
||||||
view.set('status', "Level Up!")
|
|
||||||
view.update(force=True)
|
|
||||||
|
|
||||||
# Event Handling
|
|
||||||
def on_association(self, agent, access_point):
|
|
||||||
self.exp += MULTIPLIER_ASSOCIATION
|
|
||||||
self.exp_tot += MULTIPLIER_ASSOCIATION
|
|
||||||
self.exp_check(agent)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
|
|
||||||
def on_deauthentication(self, agent, access_point, client_station):
|
|
||||||
self.exp += MULTIPLIER_DEAUTH
|
|
||||||
self.exp_tot += MULTIPLIER_DEAUTH
|
|
||||||
self.exp_check(agent)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
|
|
||||||
def on_handshake(self, agent, filename, access_point, client_station):
|
|
||||||
self.exp += MULTIPLIER_HANDSHAKE
|
|
||||||
self.exp_tot += MULTIPLIER_HANDSHAKE
|
|
||||||
self.exp_check(agent)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
|
|
||||||
def on_ai_best_reward(self, agent, reward):
|
|
||||||
self.exp += MULTIPLIER_AI_BEST_REWARD
|
|
||||||
self.exp_tot += MULTIPLIER_AI_BEST_REWARD
|
|
||||||
self.exp_check(agent)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
||||||
|
|
||||||
def on_ready(self, agent):
|
|
||||||
if self.calculateInitialXP:
|
|
||||||
self.LogInfo("Initial point calculation")
|
|
||||||
sum = self.calculateInitialSum(agent)
|
|
||||||
self.exp_tot = sum
|
|
||||||
self.calcLevelFromSum(sum, agent)
|
|
||||||
self.Save(self.save_file, self.save_file_mode)
|
|
@ -226,7 +226,7 @@ class Fix_BRCMF(plugins.Plugin):
|
|||||||
logging.info("[FixBRCMF] recon paused. Now trying wlan0mon reload")
|
logging.info("[FixBRCMF] recon paused. Now trying wlan0mon reload")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cmd_output = subprocess.check_output("sudo ifconfig wlan0mon down && sudo iw dev wlan0mon del", shell=True)
|
cmd_output = subprocess.check_output("sudo airmon-ng stop wlan0mon", shell=True)
|
||||||
self._status = "dn"
|
self._status = "dn"
|
||||||
self.logPrintView("info", "[FixBRCMF] wlan0mon down and deleted: %s" % cmd_output,
|
self.logPrintView("info", "[FixBRCMF] wlan0mon down and deleted: %s" % cmd_output,
|
||||||
display, {"status": "wlan0mon d-d-d-down!", "face": faces.BORED})
|
display, {"status": "wlan0mon d-d-d-down!", "face": faces.BORED})
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
gym
|
Gymnasium
|
||||||
shimmy
|
shimmy
|
||||||
pycryptodome>=3.9.4
|
pycryptodome
|
||||||
requests>=2.21.0
|
requests
|
||||||
PyYAML>=5.3.1
|
PyYAML
|
||||||
scapy>=2.4.3
|
scapy
|
||||||
tweepy>=3.7.0
|
tweepy
|
||||||
file-read-backwards>=2.0.0
|
file-read-backwards
|
||||||
inky>=1.2.0
|
inky
|
||||||
smbus2>=0.3.0
|
smbus2
|
||||||
Pillow>=5.4.1
|
Pillow
|
||||||
spidev>=3.4
|
spidev
|
||||||
gast>=0.2.2
|
gast
|
||||||
flask>=1.0.2
|
flask
|
||||||
flask-cors>=3.0.7
|
flask-cors
|
||||||
flask-wtf>=0.14.3
|
flask-wtf
|
||||||
dbus-python>=1.2.12
|
dbus-python
|
||||||
toml>=0.10.0
|
toml
|
||||||
python-dateutil>=2.8.1
|
python-dateutil
|
||||||
websockets>=8.1
|
websockets
|
||||||
torch>=2.0.1
|
torch
|
||||||
torchvision>=0.15.2
|
torchvision
|
||||||
stable-baselines3>=1.4.0
|
stable_baselines3
|
||||||
RPi.GPIO
|
RPi.GPIO
|
||||||
|
Reference in New Issue
Block a user