diff --git a/bin/pwnagotchi b/bin/pwnagotchi index aa462297..35a9cf5e 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -69,6 +69,7 @@ def do_auto_mode(agent): # deauth all client stations in order to get a full handshake for sta in ap['clients']: agent.deauth(ap, sta) + time.sleep(1) # delay to not trigger nexmon firmware bugs # An interesting effect of this: # diff --git a/pwnagotchi/__init__.py b/pwnagotchi/__init__.py index 96cdb5c1..447e9833 100644 --- a/pwnagotchi/__init__.py +++ b/pwnagotchi/__init__.py @@ -91,7 +91,7 @@ def cpu_load(tag=None): parts0 = _cpu_stats[tag] else: parts0 = _cpu_stat() - time.sleep(0.1) + time.sleep(0.1) # only need to sleep when no tag parts1 = _cpu_stat() if tag: _cpu_stats[tag] = parts1 @@ -167,3 +167,4 @@ def reboot(mode=None): os.system("sync") os.system("shutdown -r now") + os.system("service pwnagotchi restart") diff --git a/pwnagotchi/ai/train.py b/pwnagotchi/ai/train.py index 2d72e6e6..cba14dfe 100644 --- a/pwnagotchi/ai/train.py +++ b/pwnagotchi/ai/train.py @@ -116,10 +116,7 @@ class AsyncTrainer(object): def _save_ai(self): logging.info("[ai] saving model to %s ..." % self._nn_path) temp = "%s.tmp" % self._nn_path - back = "%s.bak" % self._nn_path self._model.save(temp) - if os.path.isfile(self._nn_path): - os.replace(self._nn_path, back) os.replace(temp, self._nn_path) def on_ai_step(self): @@ -180,7 +177,13 @@ class AsyncTrainer(object): logging.info("[ai] learning for %d epochs ..." % epochs_per_episode) try: self.set_training(True, epochs_per_episode) + # back up brain file before starting new training set + if os.path.isfile(self._nn_path): + back = "%s.bak" % self._nn_path + os.replace(self._nn_path, back) + self._view.set("mode", " ai") self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step) + self._view.set("mode", " AI") except Exception as e: logging.exception("[ai] error while training (%s)", e) finally: diff --git a/pwnagotchi/ui/display.py b/pwnagotchi/ui/display.py index ab0f3a15..f77e002b 100644 --- a/pwnagotchi/ui/display.py +++ b/pwnagotchi/ui/display.py @@ -43,6 +43,9 @@ class Display(View): def is_waveshare27inch(self): return self._implementation.name == 'waveshare27inch' + def is_waveshare27inchPartial(self): + return self._implementation.name == 'waveshare27inchPartial' + def is_waveshare29inch(self): return self._implementation.name == 'waveshare29inch' @@ -101,7 +104,8 @@ class Display(View): while True: self._canvas_next_event.wait() - self._canvas_next_event.clear() + if self._implementation.name != 'waveshare27inchPartial': + self._canvas_next_event.clear() self._implementation.render(self._canvas_next) def _on_view_rendered(self, img): diff --git a/pwnagotchi/ui/hw/__init__.py b/pwnagotchi/ui/hw/__init__.py index eb9beec0..e5d1aec0 100644 --- a/pwnagotchi/ui/hw/__init__.py +++ b/pwnagotchi/ui/hw/__init__.py @@ -8,6 +8,7 @@ from pwnagotchi.ui.hw.waveshare1 import WaveshareV1 from pwnagotchi.ui.hw.waveshare2 import WaveshareV2 from pwnagotchi.ui.hw.waveshare3 import WaveshareV3 from pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch +from pwnagotchi.ui.hw.waveshare27inchPartial import Waveshare27inchPartial from pwnagotchi.ui.hw.waveshare29inch import Waveshare29inch from pwnagotchi.ui.hw.waveshare144lcd import Waveshare144lcd from pwnagotchi.ui.hw.waveshare154inch import Waveshare154inch @@ -48,6 +49,9 @@ def display_for(config): elif config['ui']['display']['type'] == 'waveshare27inch': return Waveshare27inch(config) + elif config['ui']['display']['type'] == 'waveshare27inchPartial': + return Waveshare27inchPartial(config) + elif config['ui']['display']['type'] == 'waveshare29inch': return Waveshare29inch(config) diff --git a/pwnagotchi/ui/hw/waveshare27inchPartial.py b/pwnagotchi/ui/hw/waveshare27inchPartial.py new file mode 100644 index 00000000..e5e3f95f --- /dev/null +++ b/pwnagotchi/ui/hw/waveshare27inchPartial.py @@ -0,0 +1,77 @@ +import logging + +import pwnagotchi.ui.fonts as fonts +from pwnagotchi.ui.hw.base import DisplayImpl +from PIL import Image + + +class Waveshare27inchPartial(DisplayImpl): + def __init__(self, config): + super(Waveshare27inchPartial, self).__init__(config, 'waveshare27inchPartial') + self._display = None + self.counter = 0 + + def layout(self): + fonts.setup(10, 9, 10, 35, 25, 9) + self._layout['width'] = 264 + self._layout['height'] = 176 + self._layout['face'] = (66, 27) + self._layout['name'] = (5, 73) + self._layout['channel'] = (0, 0) + self._layout['aps'] = (28, 0) + self._layout['uptime'] = (199, 0) + self._layout['line1'] = [0, 14, 264, 14] + self._layout['line2'] = [0, 162, 264, 162] + self._layout['friend_face'] = (0, 146) + self._layout['friend_name'] = (40, 146) + self._layout['shakes'] = (0, 163) + self._layout['mode'] = (239, 163) + self._layout['status'] = { + 'pos': (38, 93), + 'font': fonts.status_font(fonts.Medium), + 'max': 40 + } + return self._layout + + + + def initialize(self): + logging.info("initializing waveshare v1 2.7 inch display") + from rpi_epd2in7.epd import EPD + self._display = EPD(fast_refresh=True) + self._display.init() + + + def render(self, canvas): + # have to rotate, because lib work with portrait mode only + # also I have 180 degrees screen rotation inn config, not tested with other valuesjk:w + rotated = canvas.rotate(90, expand=True) + if self.counter == 0: + self._display.smart_update(rotated) + + # print invert + # print true image + elif self.counter % 35 == 0: + inverted_image = rotated.point(lambda x: 255-x) + self._display.display_partial_frame(inverted_image, 0, 0, 264, 176, fast=True) + self._display.display_partial_frame(rotated, 0, 0, 264, 176, fast=True) + + # partial update full screen + elif self.counter % 7 == 0: + # face + text under + #self._display.display_partial_frame(rotated, 35, 35, 190, 115, fast=True) + # full screen partial update + self._display.display_partial_frame(rotated, 0, 0, 264, 176, fast=True) + + # partial update face + self._display.display_partial_frame(rotated, 110, 84, 92, 40, fast=True) + + if self.counter >= 100: + self.counter = 0 + else: + self.counter += 1 + + + def clear(self): + pass + diff --git a/pwnagotchi/ui/hw/waveshare35lcd.py b/pwnagotchi/ui/hw/waveshare35lcd.py index 97011b3a..1c5979b6 100644 --- a/pwnagotchi/ui/hw/waveshare35lcd.py +++ b/pwnagotchi/ui/hw/waveshare35lcd.py @@ -40,7 +40,7 @@ class Waveshare35lcd(DisplayImpl): from pwnagotchi.ui.hw.libs.fb import fb self._display = fb logging.info("initializing waveshare 3,5inch lcd display") - self._display.ready_fb(i=1) + self._display.ready_fb(i=0) self._display.black_scr() def render(self, canvas): diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index 9ecc857f..f452a940 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -16,6 +16,8 @@ from pwnagotchi.ui.components import * from pwnagotchi.ui.state import State from pwnagotchi.voice import Voice +import RPi.GPIO as GPIO + WHITE = 0xff BLACK = 0x00 ROOT = None diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 29c36327..69915c9d 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -254,6 +254,9 @@ def load_config(args): elif config['ui']['display']['type'] in ('ws_27inch', 'ws27inch', 'waveshare_27inch', 'waveshare27inch'): config['ui']['display']['type'] = 'waveshare27inch' + elif config['ui']['display']['type'] in ('ws_27inchPartial', 'ws27inchPartial', 'waveshare_27inchPartial', 'waveshare27inchPartial'): + config['ui']['display']['type'] = 'waveshare27inchPartial' + elif config['ui']['display']['type'] in ('ws_29inch', 'ws29inch', 'waveshare_29inch', 'waveshare29inch'): config['ui']['display']['type'] = 'waveshare29inch' @@ -304,11 +307,13 @@ def total_unique_handshakes(path): def iface_channels(ifname): channels = [] - output = subprocess.getoutput("/sbin/iwlist %s freq" % ifname) + + phy = subprocess.getoutput("/sbin/iw %s info | grep wiphy | cut -d ' ' -f 2" % ifname) + output = subprocess.getoutput("/sbin/iw phy%s channels | grep ' MHz' | sed 's/^.*\[//g' | sed s/\].*\$//g" % phy) for line in output.split("\n"): line = line.strip() - if line.startswith("Channel "): - channels.append(int(line.split()[1])) + channels.append(int(line)) + return channels