Merge pull request from dadav/develop

Some fixes
This commit is contained in:
Simone Margaritelli 2020-04-03 14:49:17 +02:00 committed by GitHub
commit 1360c734ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 241 additions and 123 deletions

1
.gitignore vendored

@ -17,3 +17,4 @@ dist
pwnagotchi.egg-info pwnagotchi.egg-info
*backup*.tgz *backup*.tgz
*backup*.gz *backup*.gz
.vscode

@ -14,9 +14,11 @@ from pwnagotchi import plugins
from pwnagotchi import log from pwnagotchi import log
from pwnagotchi.identity import KeyPair from pwnagotchi.identity import KeyPair
from pwnagotchi.agent import Agent from pwnagotchi.agent import Agent
from pwnagotchi.ui import fonts
from pwnagotchi.ui.display import Display from pwnagotchi.ui.display import Display
from pwnagotchi import restart from pwnagotchi import restart
from pwnagotchi import fs from pwnagotchi import fs
from pwnagotchi.utils import DottedTomlEncoder
def do_clear(display): def do_clear(display):
@ -122,11 +124,13 @@ if __name__ == '__main__':
config = utils.load_config(args) config = utils.load_config(args)
if args.print_config: if args.print_config:
print(toml.dumps(config)) print(toml.dumps(config, encoder=DottedTomlEncoder()))
sys.exit(0) sys.exit(0)
pwnagotchi.config = config
fs.setup_mounts(config) fs.setup_mounts(config)
log.setup_logging(args, config) log.setup_logging(args, config)
fonts.init(config)
pwnagotchi.set_name(config['main']['name']) pwnagotchi.set_name(config['main']['name'])

@ -104,6 +104,7 @@
- python3-flask - python3-flask
- python3-flask-cors - python3-flask-cors
- python3-flaskext.wtf - python3-flaskext.wtf
- fonts-ipaexfont-gothic
tasks: tasks:
- name: change hostname - name: change hostname

@ -10,6 +10,7 @@ from pwnagotchi import fs
from pwnagotchi._version import __version__ from pwnagotchi._version import __version__
_name = None _name = None
config = None
def set_name(new_name): def set_name(new_name):
@ -66,8 +67,6 @@ def mem_usage():
kb_mem_total = int(line.split()[1]) kb_mem_total = int(line.split()[1])
if line.startswith("MemFree:"): if line.startswith("MemFree:"):
kb_mem_free = int(line.split()[1]) kb_mem_free = int(line.split()[1])
if line.startswith("MemAvailable:"):
kb_mem_available = int(line.split()[1])
if line.startswith("Buffers:"): if line.startswith("Buffers:"):
kb_main_buffers = int(line.split()[1]) kb_main_buffers = int(line.split()[1])
if line.startswith("Cached:"): if line.startswith("Cached:"):
@ -78,18 +77,27 @@ def mem_usage():
return 0 return 0
def cpu_load(): def _cpu_stat():
"""
Returns the splitted first line of the /proc/stat file
"""
with open('/proc/stat', 'rt') as fp: with open('/proc/stat', 'rt') as fp:
for line in fp: return list(map(int,fp.readline().split()[1:]))
line = line.strip()
if line.startswith('cpu '):
parts = list(map(int, line.split()[1:])) def cpu_load():
user_n = parts[0] """
sys_n = parts[2] Returns the current cpuload
idle_n = parts[3] """
tot = user_n + sys_n + idle_n parts0 = _cpu_stat()
return (user_n + sys_n) / tot time.sleep(0.1)
return 0 parts1 = _cpu_stat()
parts_diff = [p1 - p0 for (p0, p1) in zip(parts0, parts1)]
user, nice, sys, idle, iowait, irq, softirq, steal, _guest, _guest_nice = parts_diff
idle_sum = idle + iowait
non_idle_sum = user + nice + sys + irq + softirq + steal
total = idle_sum + non_idle_sum
return non_idle_sum / total
def temperature(celsius=True): def temperature(celsius=True):

@ -148,6 +148,8 @@ personality.sad_num_epochs = 25
personality.bond_encounters_factor = 20000 personality.bond_encounters_factor = 20000
ui.fps = 0.0 ui.fps = 0.0
ui.font.name = "DejaVuSansMono" # for japanese: fonts-japanese-gothic
ui.font.size_offset = 0 # will be added to the font size
ui.faces.look_r = "( ⚆_⚆)" ui.faces.look_r = "( ⚆_⚆)"
ui.faces.look_l = "(☉_☉ )" ui.faces.look_l = "(☉_☉ )"

Binary file not shown.

@ -3,12 +3,11 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR 24534649+wytshadow@users.noreply.github.com, 2019. # FIRST AUTHOR 24534649+wytshadow@users.noreply.github.com, 2019.
# #
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 0.0.1\n" "Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-10-16 15:05+0200\n" "POT-Creation-Date: 2020-01-25 21:57+0900\n"
"PO-Revision-Date: 2019-10-16 15:05+0200\n" "PO-Revision-Date: 2019-10-16 15:05+0200\n"
"Last-Translator: wytshadow <24534649+wytshadow@users.noreply.github.com>\n" "Last-Translator: wytshadow <24534649+wytshadow@users.noreply.github.com>\n"
"Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\n" "Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\n"
@ -21,170 +20,207 @@ msgid "ZzzzZZzzzzZzzz"
msgstr "すやすや〜" msgstr "すやすや〜"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "こんにちは、ポウナゴッチです!始めている。。。" msgstr "僕、 ポーナゴッチです!"
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "" msgstr "ポーンしようよ。"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "ハックザプラネット!" msgstr "ハックザプラネット!"
msgid "AI ready." msgid "AI ready."
msgstr "人工知能の準備ができました。" msgstr "AIの準備ができました。"
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "ニューラルネットワークの準備ができました。" msgstr "ニューラルネットワークの\n準備ができました。"
msgid "Generating keys, do not turn off ..."
msgstr "鍵生成をしてます。\n電源を落とさないでね。"
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "ねえ、チャンネル{channel}は無料です! キミのAPは感謝を言います。" msgstr "チャンネル\n {channel} \nはfreeだよ。ありがとうね。"
msgid "Reading last session logs ..."
msgstr "session log を読んでます。"
#, python-brace-format
msgid "Read {lines_so_far} log lines so far ..."
msgstr "{lines_so_far} 行目長いよぉ。"
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "退屈です。。。" msgstr "退屈だぁ。。。"
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "散歩に行きましょう!" msgstr "散歩に行こうよ"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "今日は私の人生で最高の日です" msgstr "人生最高の日だよ"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "" msgstr "がっかりな日だよ。orz"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "とても退屈です。" msgstr "退屈だね。"
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "とても悲しいです。。。" msgstr "あ~悲しいよぉ。"
msgid "I'm sad" msgid "I'm sad"
msgstr "悲しいです。" msgstr "悲しいね。"
msgid "Leave me alone ..."
msgstr "ひとりぼっちだよ。"
msgid "I'm mad at you!"
msgstr "怒っちゃうよ。"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "人生を生きている!" msgstr "わくわくするね。"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "" msgstr "ポーンしてこそのオレ。"
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "たくさんネットワークがある!!" msgstr "たくさん\nWiFiが飛んでるよ"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "とても楽しんでいます" msgstr "楽しいよぉ"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "" msgstr "APに興味津々..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you. {name}" msgid "Hello {name}! Nice to meet you."
msgstr "こんにちは{name}!初めまして。{name}" msgstr "こんにちは{name}\n初めまして。{name}"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby! {name}" msgid "Yo {name}! Sup?"
msgstr "" msgstr "ねぇねぇ、\n{name} どうしたの?"
#, python-brace-format
msgid "Hey {name} how are you doing?"
msgstr "{name} こんにちは"
#, python-brace-format
msgid "Unit {name} is nearby!"
msgstr "{name} が近くにいるよ。"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "ええと。。。さようなら{name}" msgstr "じゃあね、さようなら {name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "{name}がなくなった。。。" msgstr "{name}\nがいなくなったよ。"
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "おっと。。。{name}がなくなった。" msgstr "あらら、\n{name}\nがいなくなったね。"
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "{name}逃した!" msgstr "{name} が逃げた!"
msgid "Missed!" msgid "Missed!"
msgstr "逃した!" msgstr "残念、逃した!"
msgid "Good friends are a blessing!"
msgstr "良い仲間にめぐりあえたよ。"
msgid "I love my friends!"
msgstr "友達は大好きだよ。"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "誰も僕と一緒にプレーしたくない。。。" msgstr "誰も僕と一緒に\nあそんでくれない。"
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "僕は孤独を感じる。。。" msgstr "ひとりぼっちだよ。"
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "みんなどこ?!" msgstr "みんなどこにいるの"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "{secs}寝ている。" msgstr "{secs}秒 寝ます。"
msgid "Zzzzz" msgid "Zzzzz"
msgstr "すや〜" msgstr "ぐぅ〜"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "すやすや〜 ({secs})" msgstr "すやすや〜 ({secs}秒)"
msgid "Good night." msgid "Good night."
msgstr "おみなさい。" msgstr "おやすみなさい。"
msgid "Zzz" msgid "Zzz"
msgstr "す〜" msgstr "ぐぅ~"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "{secs}を待っている。。。" msgstr "{secs}秒 待ちです。"
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "{secs}を探している。" msgstr "{secs}秒 探してます。"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "ちょっと{what}友だちになりましょう!" msgstr "ねぇねぇ\n{what} \n友だちになろうよ。"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "" msgstr "{what} \nとつながるかな"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "よー{what}!" msgstr "ねぇねぇ\n{what}"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "" msgstr "{mac}\nはWiFiじゃないのね。"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "" msgstr "{mac}\nの認証取得中..."
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "" msgstr "{mac}\nに拒否られた。"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "よし、{num}新しいハンドシェイクがある" msgstr "おぉ、\n{num}回\nハンドシェイクがあったよ"
msgid "Oops, something went wrong ... Rebooting ..." #, python-brace-format
msgstr "おっと!何かが間違っていた。。。リブートしている。。。" msgid "You have {count} new message{plural}!"
msgstr "おぉ、\n{count}個メッセージがあるよ!"
msgid "Ops, something went wrong ... Rebooting ..."
msgstr "何か間違った。\nリブートしている。"
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "" msgstr "{num}回拒否された。\n"
msgid "Made >999 new friends\n"
msgstr "1000人以上友達ができた。\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "{num}人の新しい友達を作りました\n" msgstr "{num}人友達ができた。\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "{num}ハンドシェイクがある。\n" msgstr "{num}回ハンドシェイクした。\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "1人の仲間を会いました。" msgstr "1人 仲間に会いました。"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "{num}人の仲間を会いました。" msgstr "{num}人 仲間に会いました。"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
@ -192,6 +228,9 @@ msgid ""
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"{duration}中{deauted}のAPに拒否されたけど、{associated}回チャンスがあって"
"{handshakes}回ハンドシェイクがあったよ。。 #pownagotchi #pwnlog #pwnlife "
"#hacktheplanet #skynet"
msgid "hours" msgid "hours"
msgstr "時間" msgstr "時間"
@ -203,7 +242,7 @@ msgid "seconds"
msgstr "秒" msgstr "秒"
msgid "hour" msgid "hour"
msgstr "時" msgstr "時"
msgid "minute" msgid "minute"
msgstr "分" msgstr "分"

@ -4,7 +4,10 @@ import _thread
import threading import threading
import importlib, importlib.util import importlib, importlib.util
import logging import logging
import pwnagotchi
from pwnagotchi.ui import view from pwnagotchi.ui import view
from pwnagotchi.utils import save_config
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 = {}
@ -37,10 +40,16 @@ def toggle_plugin(name, enable=True):
returns True if changed, otherwise False returns True if changed, otherwise False
""" """
global loaded, database global loaded, database
if pwnagotchi.config:
pwnagotchi.config['main']['plugins'][name]['enabled'] = enable
save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml')
if not enable and name in loaded: if not enable and name in loaded:
if getattr(loaded[name], 'on_unload', None): if getattr(loaded[name], 'on_unload', None):
loaded[name].on_unload(view.ROOT) loaded[name].on_unload(view.ROOT)
del loaded[name] del loaded[name]
return True return True
if enable and name in database and name not in loaded: if enable and name in database and name not in loaded:

@ -2,8 +2,8 @@ import logging
import json import json
import toml import toml
import _thread import _thread
import pwnagotchi.plugins as plugins from pwnagotchi import restart, plugins
from pwnagotchi import restart from pwnagotchi.utils import save_config
from flask import abort from flask import abort
from flask import render_template_string from flask import render_template_string
@ -499,13 +499,10 @@ class WebConfig(plugins.Plugin):
elif request.method == "POST": elif request.method == "POST":
if path == "save-config": if path == "save-config":
try: try:
parsed_toml = toml.loads(request.get_json()) save_config(request.get_json(), '/etc/pwnagotchi/config.toml') # test
with open('/etc/pwnagotchi/config.toml') as config_file:
toml.dump(parsed_toml, config_file)
_thread.start_new_thread(restart, (self.mode,)) _thread.start_new_thread(restart, (self.mode,))
return "success" return "success"
except Exception as ex: except Exception as ex:
logging.error(ex) logging.error(ex)
return "config error" return "config error", 500
abort(404) abort(404)

@ -1,18 +1,38 @@
from PIL import ImageFont from PIL import ImageFont
PATH = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono' # should not be changed
FONT_NAME = 'DejaVuSansMono'
Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, 10) # can be changed
BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, 8) STATUS_FONT_NAME = None
BoldBig = ImageFont.truetype("%s-Bold.ttf" % PATH, 25) SIZE_OFFSET = 0
Medium = ImageFont.truetype("%s.ttf" % PATH, 10)
Small = ImageFont.truetype("%s.ttf" % PATH, 9) Bold = None
Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, 25) BoldSmall = None
BoldBig = None
Medium = None
Small = None
Huge = None
def setup(bold, bold_small, medium, huge): def init(config):
global PATH, Bold, BoldSmall, Medium, Huge global STATUS_FONT_NAME, SIZE_OFFSET
Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, bold) STATUS_FONT_NAME = config['ui']['font']['name']
BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, bold_small) SIZE_OFFSET = config['ui']['font']['size_offset']
Medium = ImageFont.truetype("%s.ttf" % PATH, medium) setup(10, 8, 10, 25, 25, 9)
Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, huge)
def status_font(old_font):
global STATUS_FONT_NAME, SIZE_OFFSET
return ImageFont.truetype(STATUS_FONT_NAME, size=old_font.size + SIZE_OFFSET)
def setup(bold, bold_small, medium, huge, bold_big, small):
global Bold, BoldSmall, Medium, Huge, BoldBig, Small, FONT_NAME
Small = ImageFont.truetype(FONT_NAME, small)
Medium = ImageFont.truetype(FONT_NAME, medium)
BoldSmall = ImageFont.truetype("%s-Bold" % FONT_NAME, bold_small)
Bold = ImageFont.truetype("%s-Bold" % FONT_NAME, bold)
BoldBig = ImageFont.truetype("%s-Bold" % FONT_NAME, bold_big)
Huge = ImageFont.truetype("%s-Bold" % FONT_NAME, huge)

@ -22,7 +22,7 @@ class DisplayImpl(object):
# status is special :D # status is special :D
'status': { 'status': {
'pos': (0, 0), 'pos': (0, 0),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
} }

@ -9,7 +9,7 @@ class DFRobot(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250 self._layout['width'] = 250
self._layout['height'] = 122 self._layout['height'] = 122
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -25,7 +25,7 @@ class DFRobot(DisplayImpl):
self._layout['mode'] = (225, 109) self._layout['mode'] = (225, 109)
self._layout['status'] = { self._layout['status'] = {
'pos': (125, 20), 'pos': (125, 20),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
return self._layout return self._layout
@ -40,4 +40,4 @@ class DFRobot(DisplayImpl):
self._display.display(buf) self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear(0xFF) self._display.Clear(0xFF)

@ -10,7 +10,7 @@ class Inky(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 28) fonts.setup(10, 8, 10, 28, 25, 9)
self._layout['width'] = 212 self._layout['width'] = 212
self._layout['height'] = 104 self._layout['height'] = 104
self._layout['face'] = (0, 37) self._layout['face'] = (0, 37)
@ -26,7 +26,7 @@ class Inky(DisplayImpl):
self._layout['mode'] = (187, 93) self._layout['mode'] = (187, 93)
self._layout['status'] = { self._layout['status'] = {
'pos': (102, 18), 'pos': (102, 18),
'font': fonts.Small, 'font': fonts.status_font(fonts.Small),
'max': 20 'max': 20
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class LcdHat(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 240 self._layout['width'] = 240
self._layout['height'] = 240 self._layout['height'] = 240
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -26,7 +26,7 @@ class LcdHat(DisplayImpl):
self._layout['mode'] = (215, 109) self._layout['mode'] = (215, 109)
self._layout['status'] = { self._layout['status'] = {
'pos': (125, 20), 'pos': (125, 20),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }

@ -10,7 +10,7 @@ class OledHat(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(8, 8, 8, 8) fonts.setup(8, 8, 8, 8, 25, 9)
self._layout['width'] = 128 self._layout['width'] = 128
self._layout['height'] = 64 self._layout['height'] = 64
self._layout['face'] = (0, 32) self._layout['face'] = (0, 32)
@ -26,7 +26,7 @@ class OledHat(DisplayImpl):
self._layout['mode'] = (103, 10) self._layout['mode'] = (103, 10)
self._layout['status'] = { self._layout['status'] = {
'pos': (30, 18), 'pos': (30, 18),
'font': fonts.Small, 'font': fonts.status_font(fonts.Small),
'max': 18 'max': 18
} }
return self._layout return self._layout

@ -11,7 +11,7 @@ class Papirus(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 23) fonts.setup(10, 8, 10, 23, 25, 9)
self._layout['width'] = 200 self._layout['width'] = 200
self._layout['height'] = 96 self._layout['height'] = 96
self._layout['face'] = (0, 24) self._layout['face'] = (0, 24)
@ -27,7 +27,7 @@ class Papirus(DisplayImpl):
self._layout['mode'] = (175, 86) self._layout['mode'] = (175, 86)
self._layout['status'] = { self._layout['status'] = {
'pos': (85, 14), 'pos': (85, 14),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 16 'max': 16
} }
return self._layout return self._layout

@ -11,7 +11,7 @@ class Spotpear24inch(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(12, 10, 12, 70) fonts.setup(12, 10, 12, 70, 25, 9)
self._layout['width'] = 320 self._layout['width'] = 320
self._layout['height'] = 240 self._layout['height'] = 240
self._layout['face'] = (35, 50) self._layout['face'] = (35, 50)
@ -27,7 +27,7 @@ class Spotpear24inch(DisplayImpl):
self._layout['mode'] = (280, 220) self._layout['mode'] = (280, 220)
self._layout['status'] = { self._layout['status'] = {
'pos': (80, 160), 'pos': (80, 160),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }

@ -11,7 +11,7 @@ class WaveshareV1(DisplayImpl):
def layout(self): def layout(self):
if self.config['color'] == 'black': if self.config['color'] == 'black':
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250 self._layout['width'] = 250
self._layout['height'] = 122 self._layout['height'] = 122
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -27,11 +27,11 @@ class WaveshareV1(DisplayImpl):
self._layout['mode'] = (225, 109) self._layout['mode'] = (225, 109)
self._layout['status'] = { self._layout['status'] = {
'pos': (125, 20), 'pos': (125, 20),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
else: else:
fonts.setup(10, 8, 10, 25) fonts.setup(10, 8, 10, 25, 25, 9)
self._layout['width'] = 212 self._layout['width'] = 212
self._layout['height'] = 104 self._layout['height'] = 104
self._layout['face'] = (0, 26) self._layout['face'] = (0, 26)
@ -47,7 +47,7 @@ class WaveshareV1(DisplayImpl):
self._layout['mode'] = (187, 93) self._layout['mode'] = (187, 93)
self._layout['status'] = { self._layout['status'] = {
'pos': (91, 15), 'pos': (91, 15),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare144lcd(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 18) fonts.setup(10, 8, 10, 18, 25, 9)
self._layout['width'] = 128 self._layout['width'] = 128
self._layout['height'] = 128 self._layout['height'] = 128
self._layout['face'] = (0, 43) self._layout['face'] = (0, 43)
@ -26,7 +26,7 @@ class Waveshare144lcd(DisplayImpl):
self._layout['mode'] = (0, 117) self._layout['mode'] = (0, 117)
self._layout['status'] = { self._layout['status'] = {
'pos': (65, 26), 'pos': (65, 26),
'font': fonts.Small, 'font': fonts.status_font(fonts.Small),
'max': 12 'max': 12
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare154inch(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 200 self._layout['width'] = 200
self._layout['height'] = 200 self._layout['height'] = 200
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -26,7 +26,7 @@ class Waveshare154inch(DisplayImpl):
self._layout['mode'] = (170, 187) self._layout['mode'] = (170, 187)
self._layout['status'] = { self._layout['status'] = {
'pos': (5, 90), 'pos': (5, 90),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
return self._layout return self._layout

@ -11,7 +11,7 @@ class WaveshareV2(DisplayImpl):
def layout(self): def layout(self):
if self.config['color'] == 'black': if self.config['color'] == 'black':
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250 self._layout['width'] = 250
self._layout['height'] = 122 self._layout['height'] = 122
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -27,11 +27,11 @@ class WaveshareV2(DisplayImpl):
self._layout['mode'] = (225, 109) self._layout['mode'] = (225, 109)
self._layout['status'] = { self._layout['status'] = {
'pos': (125, 20), 'pos': (125, 20),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
else: else:
fonts.setup(10, 8, 10, 25) fonts.setup(10, 8, 10, 25, 25, 9)
self._layout['width'] = 212 self._layout['width'] = 212
self._layout['height'] = 104 self._layout['height'] = 104
self._layout['face'] = (0, 26) self._layout['face'] = (0, 26)
@ -48,7 +48,7 @@ class WaveshareV2(DisplayImpl):
self._layout['mode'] = (187, 93) self._layout['mode'] = (187, 93)
self._layout['status'] = { self._layout['status'] = {
'pos': (125, 20), 'pos': (125, 20),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 14 'max': 14
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare213bc(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 25) fonts.setup(10, 8, 10, 25, 25, 9)
self._layout['width'] = 212 self._layout['width'] = 212
self._layout['height'] = 104 self._layout['height'] = 104
self._layout['face'] = (0, 26) self._layout['face'] = (0, 26)
@ -26,7 +26,7 @@ class Waveshare213bc(DisplayImpl):
self._layout['mode'] = (187, 93) self._layout['mode'] = (187, 93)
self._layout['status'] = { self._layout['status'] = {
'pos': (91, 15), 'pos': (91, 15),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare213d(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 25) fonts.setup(10, 8, 10, 25, 25, 9)
self._layout['width'] = 212 self._layout['width'] = 212
self._layout['height'] = 104 self._layout['height'] = 104
self._layout['face'] = (0, 26) self._layout['face'] = (0, 26)
@ -26,7 +26,7 @@ class Waveshare213d(DisplayImpl):
self._layout['mode'] = (187, 93) self._layout['mode'] = (187, 93)
self._layout['status'] = { self._layout['status'] = {
'pos': (91, 15), 'pos': (91, 15),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 20 'max': 20
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare27inch(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 264 self._layout['width'] = 264
self._layout['height'] = 176 self._layout['height'] = 176
self._layout['face'] = (66, 27) self._layout['face'] = (66, 27)
@ -26,7 +26,7 @@ class Waveshare27inch(DisplayImpl):
self._layout['mode'] = (239, 163) self._layout['mode'] = (239, 163)
self._layout['status'] = { self._layout['status'] = {
'pos': (38, 93), 'pos': (38, 93),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 40 'max': 40
} }
return self._layout return self._layout

@ -10,7 +10,7 @@ class Waveshare29inch(DisplayImpl):
self._display = None self._display = None
def layout(self): def layout(self):
fonts.setup(10, 9, 10, 35) fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 296 self._layout['width'] = 296
self._layout['height'] = 128 self._layout['height'] = 128
self._layout['face'] = (0, 40) self._layout['face'] = (0, 40)
@ -26,7 +26,7 @@ class Waveshare29inch(DisplayImpl):
self._layout['mode'] = (268, 114) self._layout['mode'] = (268, 114)
self._layout['status'] = { self._layout['status'] = {
'pos': (130, 25), 'pos': (130, 25),
'font': fonts.Medium, 'font': fonts.status_font(fonts.Medium),
'max': 28 'max': 28
} }
return self._layout return self._layout

@ -10,11 +10,43 @@ import json
import shutil import shutil
import toml import toml
import sys import sys
import re
import pwnagotchi import pwnagotchi
from toml.encoder import TomlEncoder, _dump_str
from pwnagotchi.fs import ensure_write from pwnagotchi.fs import ensure_write
class DottedTomlEncoder(TomlEncoder):
"""
Dumps the toml into the dotted-key format
"""
def __init__(self, _dict=dict):
super(DottedTomlEncoder, self).__init__(_dict)
def dump_sections(self, o, sup):
retstr = ""
pre = ""
if sup:
pre = sup + "."
for section, value in o.items():
section = str(section)
qsection = section
if not re.match(r'^[A-Za-z0-9_-]+$', section):
qsection = _dump_str(section)
if value is not None:
if isinstance(value, dict):
toadd, _ = self.dump_sections(value, pre + qsection)
retstr += toadd
else:
retstr += (pre + qsection + " = " +
str(self.dump_value(value)) + '\n')
return (retstr, self._dict())
# https://stackoverflow.com/questions/823196/yaml-merge-in-python # https://stackoverflow.com/questions/823196/yaml-merge-in-python
def merge_config(user, default): def merge_config(user, default):
if isinstance(user, dict) and isinstance(default, dict): if isinstance(user, dict) and isinstance(default, dict):
@ -44,6 +76,11 @@ def keys_to_str(data):
return converted_dict return converted_dict
def save_config(config, target):
with open(target, 'wt') as fp:
fp.write(toml.dumps(config, encoder=DottedTomlEncoder()))
return True
def load_config(args): def load_config(args):
default_config_path = os.path.dirname(args.config) default_config_path = os.path.dirname(args.config)
if not os.path.exists(default_config_path): if not os.path.exists(default_config_path):

@ -1,6 +1,6 @@
pycryptodome==3.9.4 pycryptodome==3.9.4
requests==2.21.0 requests==2.21.0
PyYAML==5.1 PyYAML==5.3.1
scapy==2.4.3 scapy==2.4.3
gym==0.14.0 gym==0.14.0
scipy==1.3.1 scipy==1.3.1
@ -17,7 +17,7 @@ spidev==3.4
gast==0.2.2 gast==0.2.2
flask==1.0.2 flask==1.0.2
flask-cors==3.0.7 flask-cors==3.0.7
flask-wtf==0.14.2 flask-wtf==0.14.3
dbus-python==1.2.12 dbus-python==1.2.12
toml==0.10.0 toml==0.10.0
python-dateutil==2.8.1 python-dateutil==2.8.1