Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>

Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>
This commit is contained in:
Jeroen Oudshoorn
2023-08-30 16:46:59 +02:00
parent d4e6972a7f
commit cf22cea18f
3 changed files with 2 additions and 439 deletions

View File

@ -28,8 +28,8 @@ main.plugins.grid.exclude = [
"YourHomeNetworkHere"
]
main.plugins.auto-update.enabled = false
main.plugins.auto-update.install = false
main.plugins.auto-update.enabled = true
main.plugins.auto-update.install = true
main.plugins.auto-update.interval = 24
main.plugins.net-pos.enabled = false
@ -39,13 +39,6 @@ main.plugins.gps.enabled = false
main.plugins.gps.speed = 19200
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.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
@ -146,12 +139,6 @@ main.log.path = "/var/log/pwnagotchi.log"
main.log.rotation.enabled = true
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.path = "/root/brain.nn"
ai.laziness = 0.1

View File

@ -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']

View File

@ -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)