From 83a6e3f45d68935796a841c220662dfef1e3d8bc Mon Sep 17 00:00:00 2001 From: Cassiano Aquino <cassianoaquino@me.com> Date: Sun, 29 Sep 2019 01:41:49 +0100 Subject: [PATCH 01/10] services cleanup. powersave features and shellcheck fixes --- scripts/create_sibling.sh | 5 ++++- scripts/linux_connection_share.sh | 8 ++++---- sdcard/boot/config.txt | 9 +++++++++ sdcard/rootfs/etc/rc.local | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index 81bff79..d9f1027 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -195,6 +195,9 @@ function provision_raspbian() { # slows down boot systemctl disable apt-daily.timer apt-daily.service apt-daily-upgrade.timer apt-daily-upgrade.service + # unecessary services + systemctl disable triggerhappy bluetooth wpa_supplicant + EOF sed -i'' 's/^#//g' etc/ld.so.preload cd "${REPO_DIR}" @@ -213,7 +216,7 @@ usage: $0 [OPTIONS] -i <file> # Provide the path of an already downloaded raspbian image -o <file> # Name of the img-file (default: pwnagotchi.img) -s <size> # Size which should be added to second partition (in Gigabyte) (default: 4) - -v <version> # Version of raspbian (Supported: $SUPPORTED_RASPBIAN_VERSIONS; default: latest) + -v <version> # Version of raspbian (Supported: ${SUPPORTED_RASPBIAN_VERSIONS[*]}; default: latest) -p # Only run provisioning (assumes the image is already mounted) -d # Only run dependencies checks -h # Show this help diff --git a/scripts/linux_connection_share.sh b/scripts/linux_connection_share.sh index 57fe718..78df842 100755 --- a/scripts/linux_connection_share.sh +++ b/scripts/linux_connection_share.sh @@ -7,12 +7,12 @@ USB_IFACE_NET=10.0.0.0/24 # host interface to use for upstream connection UPSTREAM_IFACE=${2:-enxe4b97aa99867} -ip addr add $USB_IFACE_IP/24 dev $USB_IFACE -ip link set $USB_IFACE up +ip addr add "$USB_IFACE_IP/24" dev "$USB_IFACE" +ip link set "$USB_IFACE" up -iptables -A FORWARD -o $UPSTREAM_IFACE -i $USB_IFACE -s $USB_IFACE_NET -m conntrack --ctstate NEW -j ACCEPT +iptables -A FORWARD -o "$UPSTREAM_IFACE" -i "$USB_IFACE" -s "$USB_IFACE_NET" -m conntrack --ctstate NEW -j ACCEPT iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -t nat -F POSTROUTING -iptables -t nat -A POSTROUTING -o $UPSTREAM_IFACE -j MASQUERADE +iptables -t nat -A POSTROUTING -o "$UPSTREAM_IFACE" -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward diff --git a/sdcard/boot/config.txt b/sdcard/boot/config.txt index 98231bc..9e57de0 100755 --- a/sdcard/boot/config.txt +++ b/sdcard/boot/config.txt @@ -1195,3 +1195,12 @@ dtoverlay=dwc2 dtparam=spi=on dtoverlay=spi1-3cs +# Powersave options +# Disable power LED ~30ma +dtparam=act_led_trigger=none +dtparam=act_led_activelow=on +# Disable bluetooth +dtoverlay=pi3-disable-bt +# Disable audio +dtparam=audio=off + diff --git a/sdcard/rootfs/etc/rc.local b/sdcard/rootfs/etc/rc.local index 15fb894..e93d2d8 100755 --- a/sdcard/rootfs/etc/rc.local +++ b/sdcard/rootfs/etc/rc.local @@ -10,5 +10,7 @@ # bits. # # By default this script does nothing. +# Powersave (Disable HDMI) ~30ma +/opt/vc/bin/tvservice -o /root/pwnagotchi/scripts/startup.sh & exit 0 From 54de337fcd66b2d1bfce25c535d5e179ccc3855d Mon Sep 17 00:00:00 2001 From: Cassiano Aquino <cassianoaquino@me.com> Date: Sun, 29 Sep 2019 02:22:20 +0100 Subject: [PATCH 02/10] add zombie kr option to screen to allow screen to stay open when process dies --- sdcard/rootfs/root/pwnagotchi/data/screenrc.auto | 1 + sdcard/rootfs/root/pwnagotchi/data/screenrc.manual | 1 + 2 files changed, 2 insertions(+) diff --git a/sdcard/rootfs/root/pwnagotchi/data/screenrc.auto b/sdcard/rootfs/root/pwnagotchi/data/screenrc.auto index 0d775f9..9319672 100644 --- a/sdcard/rootfs/root/pwnagotchi/data/screenrc.auto +++ b/sdcard/rootfs/root/pwnagotchi/data/screenrc.auto @@ -5,6 +5,7 @@ defscrollback 1024 startup_message off altscreen on autodetach on +zombie kr activity "activity in %n (%t)" bell_msg "bell in %n (%t)" diff --git a/sdcard/rootfs/root/pwnagotchi/data/screenrc.manual b/sdcard/rootfs/root/pwnagotchi/data/screenrc.manual index 4e66adf..1d62528 100644 --- a/sdcard/rootfs/root/pwnagotchi/data/screenrc.manual +++ b/sdcard/rootfs/root/pwnagotchi/data/screenrc.manual @@ -5,6 +5,7 @@ defscrollback 1024 startup_message off altscreen on autodetach on +zombie kr activity "activity in %n (%t)" bell_msg "bell in %n (%t)" From 43282ad9d6b12240d7ec0bc99854972125ff3bf2 Mon Sep 17 00:00:00 2001 From: Cassiano Aquino <cassianoaquino@me.com> Date: Sun, 29 Sep 2019 11:46:19 +0100 Subject: [PATCH 03/10] disable leds after blink runs to present user feedback --- sdcard/boot/config.txt | 4 ---- sdcard/rootfs/root/pwnagotchi/scripts/blink.sh | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sdcard/boot/config.txt b/sdcard/boot/config.txt index 9e57de0..4d69af8 100755 --- a/sdcard/boot/config.txt +++ b/sdcard/boot/config.txt @@ -1195,10 +1195,6 @@ dtoverlay=dwc2 dtparam=spi=on dtoverlay=spi1-3cs -# Powersave options -# Disable power LED ~30ma -dtparam=act_led_trigger=none -dtparam=act_led_activelow=on # Disable bluetooth dtoverlay=pi3-disable-bt # Disable audio diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh b/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh index 48345ef..b7e8977 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh +++ b/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh @@ -1,6 +1,6 @@ #!/bin/bash -for i in `seq 1 $1`; +for i in $(seq 1 "$1"); do echo 0 >/sys/class/leds/led0/brightness sleep 0.3 @@ -10,3 +10,8 @@ done echo 0 >/sys/class/leds/led0/brightness sleep 0.3 + +# Powersave options +# Disable power LED ~30ma +echo none >/sys/class/leds/led0/trigger +echo 1 >/sys/class/leds/led0/brightness From 32b74285954c2fbc837443033ad778e325cc2a3c Mon Sep 17 00:00:00 2001 From: Frantisek Sindelar <sindelar.fr@gmail.com> Date: Sun, 29 Sep 2019 14:18:33 +0200 Subject: [PATCH 04/10] Adding support for Waveshare V1 displays. Adding support for full refresh after n partial refreshes (for Waveshare displays). --- sdcard/rootfs/root/pwnagotchi/config.yml | 4 +- .../scripts/pwnagotchi/ui/display.py | 36 ++- .../pwnagotchi/scripts/pwnagotchi/ui/view.py | 3 +- .../pwnagotchi/ui/waveshare/__init__.py | 0 .../pwnagotchi/ui/waveshare/v1/__init__.py | 0 .../pwnagotchi/ui/waveshare/v1/epd2in13.py | 218 ++++++++++++++++++ .../pwnagotchi/ui/waveshare/v1/epdconfig.py | 1 + .../pwnagotchi/ui/waveshare/v2/__init__.py | 0 .../ui/{ => waveshare/v2}/waveshare.py | 0 9 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/__init__.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/__init__.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py create mode 120000 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/__init__.py rename sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/{ => waveshare/v2}/waveshare.py (100%) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index e151e63..dee263c 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -93,9 +93,11 @@ ui: enabled: true rotation: 180 # Possible options inkyphat/inky or waveshare/ws - type: 'waveshare' + type: 'waveshare_2' # Possible options red/yellow/black (black used for monocromatic displays) color: 'black' + # How often to do a full refresh + refresh: 10 video: enabled: true address: '10.0.0.2' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 6d821a7..666dca1 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -79,6 +79,9 @@ class Display(View): self._video_address = config['ui']['display']['video']['address'] self._display_type = config['ui']['display']['type'] self._display_color = config['ui']['display']['color'] + self.full_refresh_count = 0 + self.full_refresh_trigger = config['ui']['display']['refresh'] + self._render_cb = None self._display = None self._httpd = None @@ -104,8 +107,11 @@ class Display(View): def _is_inky(self): return self._display_type in ('inkyphat', 'inky') - def _is_waveshare(self): - return self._display_type in ('waveshare', 'ws') + def _is_waveshare1(self): + return self._display_type in ('waveshare_1', 'ws_1', 'waveshare1', 'ws1') + + def _is_waveshare2(self): + return self._display_type in ('waveshare_2', 'ws_2', 'waveshare2', 'ws2') def _init_display(self): if self._is_inky(): @@ -113,8 +119,16 @@ class Display(View): self._display = InkyPHAT(self._display_color) self._display.set_border(InkyPHAT.BLACK) self._render_cb = self._inky_render - elif self._is_waveshare(): - from pwnagotchi.ui.waveshare import EPD + elif self._is_waveshare1(): + from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD + # core.log("display module started") + self._display = EPD() + self._display.init(self._display.lut_full_update) + self._display.Clear(0xFF) + self._display.init(self._display.lut_partial_update) + self._render_cb = self._waveshare_render + elif self._is_waveshare2(): + from pwnagotchi.ui.v2.waveshare import EPD # core.log("display module started") self._display = EPD() self._display.init(self._display.FULL_UPDATE) @@ -165,7 +179,19 @@ class Display(View): def _waveshare_render(self): buf = self._display.getbuffer(self.canvas) - self._display.displayPartial(buf) + if self._is_waveshare1: + if self.full_refresh_count == self.full_refresh_trigger: + self._display.Clear(0x00) + self._display.display(buf) + elif self._is_waveshare2: + if self.full_refresh_count == self.full_refresh_trigger: + self._display.Clear(BLACK) + self._display.displayPartial(buf) + self._display.sleep() + if self.full_refresh_count == self.full_refresh_trigger: + self.full_refresh_count = 0 + else: + self.full_refresh_count += 1 def _on_view_rendered(self, img): # core.log("display::_on_view_rendered") diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index 1c49562..4d727e1 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -31,7 +31,8 @@ def setup_display_specifics(config): face_pos = (0, int(height / 4)) name_pos = (int(width / 2) - 15, int(height * .15)) status_pos = (int(width / 2) - 15, int(height * .30)) - elif config['ui']['display']['type'] in ('ws', 'waveshare'): + elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', + 'ws_2', 'ws2', 'waveshare_2', 'waveshare2'): fonts.setup(10, 9, 10, 35) width = 250 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py new file mode 100644 index 0000000..5805086 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py @@ -0,0 +1,218 @@ +# //***************************************************************************** +# * | File : epd2in13.py +# * | Author : Waveshare team +# * | Function : Electronic paper driver +# * | Info : +# *---------------- +# * | This version: V3.1 +# * | Date : 2019-03-20 +# * | Info : python3 demo +# * fix: TurnOnDisplay() +# ******************************************************************************// +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and//or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + + +from . import epdconfig +from PIL import Image +import RPi.GPIO as GPIO +# import numpy as np + +# Display resolution +EPD_WIDTH = 122 +EPD_HEIGHT = 250 + +class EPD: + def __init__(self): + self.reset_pin = epdconfig.RST_PIN + self.dc_pin = epdconfig.DC_PIN + self.busy_pin = epdconfig.BUSY_PIN + self.width = EPD_WIDTH + self.height = EPD_HEIGHT + lut_full_update = [ + 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + lut_partial_update = [ + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + # Hardware reset + def reset(self): + epdconfig.digital_write(self.reset_pin, GPIO.HIGH) + epdconfig.delay_ms(200) + epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset + epdconfig.delay_ms(200) + epdconfig.digital_write(self.reset_pin, GPIO.HIGH) + epdconfig.delay_ms(200) + + def send_command(self, command): + epdconfig.digital_write(self.dc_pin, GPIO.LOW) + epdconfig.spi_writebyte([command]) + + def send_data(self, data): + epdconfig.digital_write(self.dc_pin, GPIO.HIGH) + epdconfig.spi_writebyte([data]) + + def wait_until_idle(self): + # print("busy") + while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy + epdconfig.delay_ms(100) + # print("free busy") + + def TurnOnDisplay(self): + self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2 + self.send_data(0xC4) + self.send_command(0x20) # MASTER_ACTIVATION + self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE + self.wait_until_idle() + + def init(self, lut): + if (epdconfig.module_init() != 0): + return -1 + # EPD hardware init start + self.reset() + self.send_command(0x01) # DRIVER_OUTPUT_CONTROL + self.send_data((EPD_HEIGHT - 1) & 0xFF) + self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF) + self.send_data(0x00) # GD = 0 SM = 0 TB = 0 + + self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL + self.send_data(0xD7) + self.send_data(0xD6) + self.send_data(0x9D) + + self.send_command(0x2C) # WRITE_VCOM_REGISTER + self.send_data(0xA8) # VCOM 7C + + self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD + self.send_data(0x1A) # 4 dummy lines per gate + + self.send_command(0x3B) # SET_GATE_TIME + self.send_data(0x08) # 2us per line + + self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL + self.send_data(0x03) + + self.send_command(0X11) # DATA_ENTRY_MODE_SETTING + self.send_data(0x03) # X increment; Y increment + + # WRITE_LUT_REGISTER + self.send_command(0x32) + for count in range(30): + self.send_data(lut[count]) + + return 0 + +## + # @brief: specify the memory area for data R//W + ## + def SetWindows(self, x_start, y_start, x_end, y_end): + self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION + self.send_data((x_start >> 3) & 0xFF) + self.send_data((x_end >> 3) & 0xFF) + self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION + self.send_data(y_start & 0xFF) + self.send_data((y_start >> 8) & 0xFF) + self.send_data(y_end & 0xFF) + self.send_data((y_end >> 8) & 0xFF) + +## + # @brief: specify the start point for data R//W + ## + def SetCursor(self, x, y): + self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER + # x point must be the multiple of 8 or the last 3 bits will be ignored + self.send_data((x >> 3) & 0xFF) + self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER + self.send_data(y & 0xFF) + self.send_data((y >> 8) & 0xFF) + self.wait_until_idle() + + def getbuffer(self, image): + if self.width%8 == 0: + linewidth = self.width//8 + else: + linewidth = self.width//8 + 1 + + buf = [0xFF] * (linewidth * self.height) + image_monocolor = image.convert('1') + imwidth, imheight = image_monocolor.size + pixels = image_monocolor.load() + + if(imwidth == self.width and imheight == self.height): + # print("Vertical") + for y in range(imheight): + for x in range(imwidth): + if pixels[x, y] == 0: + # x = imwidth - x + buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8)) + elif(imwidth == self.height and imheight == self.width): + # print("Horizontal") + for y in range(imheight): + for x in range(imwidth): + newx = y + newy = self.height - x - 1 + if pixels[x, y] == 0: + # newy = imwidth - newy - 1 + buf[newx // 8 + newy*linewidth] &= ~(0x80 >> (y % 8)) + return buf + + + def display(self, image): + if self.width%8 == 0: + linewidth = self.width//8 + else: + linewidth = self.width//8 + 1 + + self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(image[i + j * linewidth]) + self.TurnOnDisplay() + + def Clear(self, color): + if self.width%8 == 0: + linewidth = self.width//8 + else: + linewidth = self.width//8 + 1 + + self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(color) + self.TurnOnDisplay() + + def sleep(self): + self.send_command(0x10) #enter deep sleep + # self.send_data(0x01) + epdconfig.delay_ms(100) + +### END OF FILE ### + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py new file mode 120000 index 0000000..7090e2e --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py @@ -0,0 +1 @@ +epdconfig_old.py \ No newline at end of file diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py similarity index 100% rename from sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare.py rename to sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py From 3a8f6920b3048e1799882491710af7db415b4095 Mon Sep 17 00:00:00 2001 From: Frantisek Sindelar <sindelar.fr@gmail.com> Date: Sun, 29 Sep 2019 14:22:38 +0200 Subject: [PATCH 05/10] Replacing symling with file. --- .../pwnagotchi/ui/waveshare/v1/epdconfig.py | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) mode change 120000 => 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py deleted file mode 120000 index 7090e2e..0000000 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py +++ /dev/null @@ -1 +0,0 @@ -epdconfig_old.py \ No newline at end of file diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py new file mode 100644 index 0000000..78ff647 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py @@ -0,0 +1,73 @@ +# /***************************************************************************** +# * | File : EPD_1in54.py +# * | Author : Waveshare team +# * | Function : Hardware underlying interface +# * | Info : +# *---------------- +# * | This version: V2.0 +# * | Date : 2018-11-01 +# * | Info : +# * 1.Remove: +# digital_write(self, pin, value) +# digital_read(self, pin) +# delay_ms(self, delaytime) +# set_lut(self, lut) +# self.lut = self.lut_full_update +# ******************************************************************************/ +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + + +import spidev +import RPi.GPIO as GPIO +import time + +# Pin definition +RST_PIN = 17 +DC_PIN = 25 +CS_PIN = 8 +BUSY_PIN = 24 + +# SPI device, bus = 0, device = 0 +SPI = spidev.SpiDev(0, 0) + +def digital_write(pin, value): + GPIO.output(pin, value) + +def digital_read(pin): + return GPIO.input(BUSY_PIN) + +def delay_ms(delaytime): + time.sleep(delaytime / 1000.0) + +def spi_writebyte(data): + SPI.writebytes(data) + +def module_init(): + GPIO.setmode(GPIO.BCM) + GPIO.setwarnings(False) + GPIO.setup(RST_PIN, GPIO.OUT) + GPIO.setup(DC_PIN, GPIO.OUT) + GPIO.setup(CS_PIN, GPIO.OUT) + GPIO.setup(BUSY_PIN, GPIO.IN) + SPI.max_speed_hz = 2000000 + SPI.mode = 0b00 + return 0; + +### END OF FILE ### From 95a05bf886066e26e50771dc4156950407ef3a40 Mon Sep 17 00:00:00 2001 From: Frantisek Sindelar <sindelar.fr@gmail.com> Date: Sun, 29 Sep 2019 15:27:56 +0200 Subject: [PATCH 06/10] Fixing import path for Waveshare V2. Fixing the full refresh trigger to enable 0 for every time and -1 for never. --- sdcard/rootfs/root/pwnagotchi/config.yml | 4 ++-- .../root/pwnagotchi/scripts/pwnagotchi/ui/display.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index dee263c..8d5c3ac 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -96,8 +96,8 @@ ui: type: 'waveshare_2' # Possible options red/yellow/black (black used for monocromatic displays) color: 'black' - # How often to do a full refresh - refresh: 10 + # How often to do a full refresh 0 all the time, -1 never + refresh: 50 video: enabled: true address: '10.0.0.2' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 666dca1..598ed2c 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -128,7 +128,7 @@ class Display(View): self._display.init(self._display.lut_partial_update) self._render_cb = self._waveshare_render elif self._is_waveshare2(): - from pwnagotchi.ui.v2.waveshare import EPD + from pwnagotchi.ui.waveshare.v2.waveshare import EPD # core.log("display module started") self._display = EPD() self._display.init(self._display.FULL_UPDATE) @@ -180,17 +180,17 @@ class Display(View): def _waveshare_render(self): buf = self._display.getbuffer(self.canvas) if self._is_waveshare1: - if self.full_refresh_count == self.full_refresh_trigger: + if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: self._display.Clear(0x00) self._display.display(buf) elif self._is_waveshare2: - if self.full_refresh_count == self.full_refresh_trigger: + if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: self._display.Clear(BLACK) self._display.displayPartial(buf) self._display.sleep() - if self.full_refresh_count == self.full_refresh_trigger: + if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: self.full_refresh_count = 0 - else: + elif self.full_refresh_trigger >= 0: self.full_refresh_count += 1 def _on_view_rendered(self, img): From 2935d9ccaf486c2cc55134bc7a98aa2c77b48127 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sun, 29 Sep 2019 14:17:02 +0200 Subject: [PATCH 07/10] Add multilanguage support Add german --- README.md | 28 ++ scripts/language.sh | 71 ++++ sdcard/rootfs/root/pwnagotchi/config.yml | 2 + sdcard/rootfs/root/pwnagotchi/scripts/main.py | 4 +- .../pwnagotchi/locale/de/LC_MESSAGES/voice.mo | Bin 0 -> 3919 bytes .../pwnagotchi/locale/de/LC_MESSAGES/voice.po | 344 ++++++++++++++++++ .../scripts/pwnagotchi/locale/voice.pot | 288 +++++++++++++++ .../pwnagotchi/scripts/pwnagotchi/ui/view.py | 47 +-- .../pwnagotchi/scripts/pwnagotchi/voice.py | 213 ++++++----- 9 files changed, 872 insertions(+), 125 deletions(-) create mode 100755 scripts/language.sh create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot diff --git a/README.md b/README.md index bf7fa3b..28bd7c3 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,34 @@ The UI is available either via display if installed, or via http://pwnagotchi.lo * **PWND**: Number of handshakes captured in this session and number of unique networks we own at least one handshake of, from the beginning. * **AUTO**: This indicates that the algorithm is running with AI disabled (or still loading), it disappears once the AI dependencies have been bootrapped and the neural network loaded. +#### Languages + +Pwnagotchi is able to speak multiple languages!! Currently supported is: + +* **english** (default) +* german + +If you want to add a language use the `language.sh` script. +If you want to add for example the language **italian** you would type: + +```shell +./scripts/language.sh add it +# Now make your changes to the file +# sdcard/scripts/rootfs/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po +./scripts/language.sh compile it +# DONE +``` + +If you changed the `voice.py`- File, the translations need an update. Do it like this: + +```shell +./scripts/language.sh update it +# Now make your changes to the file (changed lines are marked with "fuzzy") +# sdcard/scripts/rootfs/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po +./scripts/language.sh compile it +# DONE +``` + ### Random Info - `hostname` sets the unit name. diff --git a/scripts/language.sh b/scripts/language.sh new file mode 100755 index 0000000..192f463 --- /dev/null +++ b/scripts/language.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +set -eu + +DEPENDENCIES=( 'xgettext' 'msgfmt' 'msgmerge' ) +COMMANDS=( 'add' 'update' 'delete' 'compile' ) + +REPO_DIR="$(dirname "$(dirname "$(realpath "$0")")")" +LOCALE_DIR="${REPO_DIR}/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale" +VOICE_FILE="${REPO_DIR}/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py" + +function usage() { +cat <<EOF + +usage: $0 <command> [options] + + Commands: + add <language> # Adds a new language + delete <language> # Deletes a language + compile <language> # Compiles a language + update # Update + +EOF +} + +for REQ in "${DEPENDENCIES[@]}"; do + if ! type "$REQ" >/dev/null 2>&1; then + echo "Dependency check failed for ${REQ}" + exit 1 + fi +done + + +if [[ ! "${COMMANDS[*]}" =~ $1 ]]; then + usage +fi + + +function add_lang() { + mkdir -p "$LOCALE_DIR/$1/LC_MESSAGES" + cp -n "$LOCALE_DIR/voice.pot" "$LOCALE_DIR/$1/LC_MESSAGES/voice.po" +} + +function del_lang() { + # set -eu is present; so not dangerous + rm -rf "$LOCALE_DIR/$1" +} + +function comp_lang() { + msgfmt -o "$LOCALE_DIR/$1/LC_MESSAGES/voice.mo" "$LOCALE_DIR/$1/LC_MESSAGES/voice.po" +} + +function update_lang() { + xgettext -d voice -o "$LOCALE_DIR/voice.pot" "$VOICE_FILE" + msgmerge --update "$LOCALE_DIR/$1/LC_MESSAGES/voice.po" "$LOCALE_DIR/voice.pot" +} + +case "$1" in + add) + add_lang "$2" + ;; + delete) + del_lang "$2" + ;; + compile) + comp_lang "$2" + ;; + update) + update_lang "$2" + ;; +esac diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index e151e63..a47dc28 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -1,5 +1,7 @@ # main algorithm configuration main: + # currently implemented: en (default), de + lang: en # monitor interface to use iface: mon0 # command to run to bring the mon interface up in case it's not up already diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index 6f44622..de44012 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -8,7 +8,7 @@ import core import pwnagotchi from pwnagotchi.log import SessionParser -import pwnagotchi.voice as voice +from pwnagotchi.voice import Voice from pwnagotchi.agent import Agent from pwnagotchi.ui.display import Display @@ -74,7 +74,7 @@ if args.do_manual: auth.set_access_token(config['twitter']['access_token_key'], config['twitter']['access_token_secret']) api = tweepy.API(auth) - tweet = voice.on_log_tweet(log) + tweet = Voice(lang=config['main']['lang']).on_log_tweet(log) api.update_with_media(filename=picture, status=tweet) log.save_session_id() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..dcede010ed742768694a1053e34ad36b57502e97 GIT binary patch literal 3919 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 Og?2E|%(!=uy8i;U{VEs$ literal 0 HcmV?d00001 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po new file mode 100644 index 0000000..c85e254 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po @@ -0,0 +1,344 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-29 13:34+0200\n" +"PO-Revision-Date: 2019-09-29 14:00+0200\n" +"Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\n" +"Language-Team: DE <33197631+dadav@users.noreply.github.com>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:16 +msgid "ZzzzZZzzzzZzzz" +msgstr "" + +#: voice.py:21 +msgid "" +"Hi, I'm Pwnagotchi!\n" +"Starting ..." +msgstr "" +"Hi, ich bin\n" +"ein Pwnagotchi!\n" +"Starte ..." + +#: voice.py:22 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" +"Neuer Tag, neue Jagd,\n" +"neue Pwns!" + +#: voice.py:23 +msgid "Hack the Planet!" +msgstr "Hack den Planet!" + +#: voice.py:28 +msgid "AI ready." +msgstr "KI bereit." + +#: voice.py:29 +msgid "" +"The neural network\n" +"is ready." +msgstr "" +"Das neurale Netz\n" +"ist bereit." + +#: voice.py:39 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" +"Hey, Channel {channel} ist\n" +"frei! Dein AP wird\n" +"es dir danken." + +#: voice.py:44 +msgid "I'm bored ..." +msgstr "Mir ist langweilig..." + +#: voice.py:45 +msgid "Let's go for a walk!" +msgstr "Lass uns laufen gehen!" + +#: voice.py:49 +msgid "" +"This is the best\n" +"day of my life!" +msgstr "" +"Das ist der beste\n" +"Tag meines Lebens." + +#: voice.py:53 +msgid "Shitty day :/" +msgstr "Scheis Tag :/" + +#: voice.py:58 +msgid "I'm extremely bored ..." +msgstr "Mir ist sau langweilig..." + +#: voice.py:59 +msgid "I'm very sad ..." +msgstr "Ich bin sehr traurig..." + +#: voice.py:60 +msgid "I'm sad" +msgstr "Ich bin traurig" + +#: voice.py:66 +msgid "I'm living the life!" +msgstr "Ich lebe das Leben!" + +#: voice.py:67 +msgid "I pwn therefore I am." +msgstr "Ich pwne, also bin ich." + +#: voice.py:68 +msgid "So many networks!!!" +msgstr "So viele Netwerke!!!" + +#: voice.py:69 +msgid "" +"I'm having so much\n" +"fun!" +msgstr "" +"Ich habe sooo viel\n" +"Spaß!" + +#: voice.py:70 +msgid "" +"My crime is that of\n" +"curiosity ..." +msgstr "" +"Mein Verbrechen ist\n" +"das der Neugier ..." + +#: voice.py:75 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" +"Hallo {name},\n" +"Nett Dich\n" +"kennenzulernen." + +#: voice.py:76 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is nearby! {name}" +msgstr "" +"Gerät {name}\n" +"ist in der\n" +"nähe!!" + +#: voice.py:81 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" +"Uhm ...\n" +"tschüß\n" +"{name}" + +#: voice.py:82 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" +"{name}\n" +"ist weg ..." + +#: voice.py:87 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" +"Whoops ...\n" +"{name}\n" +"ist weg." + +#: voice.py:88 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" +"{name}\n" +"verpasst!" + +#: voice.py:89 +msgid "Missed!" +msgstr "Verpasst!" + +#: voice.py:94 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" +"Niemand will mit\n" +"mir spielen ..." + +#: voice.py:95 +msgid "I feel so alone ..." +msgstr "" +"Ich fühl mich\n" +"so alleine ..." + +#: voice.py:96 +msgid "Where's everybody?!" +msgstr "Wo sind denn alle?" + +#: voice.py:101 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Schlafe für {secs}s" + +#: voice.py:102 +msgid "Zzzzz" +msgstr "" + +#: voice.py:103 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Warte für {secs}s ..." + +#: voice.py:114 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Schaue mich um ({secs}s)" + +#: voice.py:121 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" +"Hey\n" +"{what}\n" +"lass uns Freunde sein!" + +#: voice.py:122 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" +"Verbinde mit\n" +"{what}" + +#: voice.py:123 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" + +#: voice.py:128 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "" +"Habe gerade entschieden,\n" +"dass {mac}\n" +"kein WiFi brauch!" + +#: voice.py:129 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" +"Deauthentifiziere\n" +"{mac}" + +#: voice.py:130 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" +"Kicke\n" +"{mac}!" + +#: voice.py:135 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" +"Cool, wir haben {num}\n" +"neue Handshake{plural}!" + +#: voice.py:139 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" +"Ops, da ist etwas\n" +"schief gelaufen ...\n" +"Starte neu ..." + +#: voice.py:143 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "{num} Stationen gekicked\n" + +#: voice.py:144 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "{num} Freunde gefunden\n" + +#: voice.py:145 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "{num} Handshakes aufgez.\n" + +#: voice.py:147 +msgid "Met 1 peer" +msgstr "1 Peer getroffen." + +#: voice.py:149 +#, python-brace-format +msgid "Met {num} peers" +msgstr "{num} Peers getroffen" + +#: voice.py:154 +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" +"Ich war {duration} am Pwnen und habe {deauthed} Clients gekickt! Außerdem habe ich " +"{associated} neue Freunde getroffen und {handshakes} Handshakes gefressen! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot new file mode 100644 index 0000000..671e44d --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot @@ -0,0 +1,288 @@ +# pwnigotchi voice data +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# FIRST AUTHOR <33197631+dadav@users.noreply.github.com>, 2019. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-29 13:42+0200\n" +"PO-Revision-Date: 2019-09-29 14:00+0200\n" +"Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\n" +"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" +"Language: english\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:16 +msgid "ZzzzZZzzzzZzzz" +msgstr "" + +#: voice.py:21 +msgid "" +"Hi, I'm Pwnagotchi!\n" +"Starting ..." +msgstr "" + +#: voice.py:22 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" + +#: voice.py:23 +msgid "Hack the Planet!" +msgstr "" + +#: voice.py:28 +msgid "AI ready." +msgstr "" + +#: voice.py:29 +msgid "" +"The neural network\n" +"is ready." +msgstr "" + +#: voice.py:39 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" + +#: voice.py:44 +msgid "I'm bored ..." +msgstr "" + +#: voice.py:45 +msgid "Let's go for a walk!" +msgstr "" + +#: voice.py:49 +msgid "" +"This is the best\n" +"day of my life!" +msgstr "" + +#: voice.py:53 +msgid "Shitty day :/" +msgstr "" + +#: voice.py:58 +msgid "I'm extremely bored ..." +msgstr "" + +#: voice.py:59 +msgid "I'm very sad ..." +msgstr "" + +#: voice.py:60 +msgid "I'm sad" +msgstr "" + +#: voice.py:66 +msgid "I'm living the life!" +msgstr "" + +#: voice.py:67 +msgid "I pwn therefore I am." +msgstr "" + +#: voice.py:68 +msgid "So many networks!!!" +msgstr "" + +#: voice.py:69 +msgid "" +"I'm having so much\n" +"fun!" +msgstr "" + +#: voice.py:70 +msgid "" +"My crime is that of\n" +"curiosity ..." +msgstr "" + +#: voice.py:75 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" + +#: voice.py:76 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is nearby! {name}" +msgstr "" + +#: voice.py:81 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" + +#: voice.py:82 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" + +#: voice.py:87 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" + +#: voice.py:88 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" + +#: voice.py:89 +msgid "Missed!" +msgstr "" + +#: voice.py:94 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" + +#: voice.py:95 +msgid "I feel so alone ..." +msgstr "" + +#: voice.py:96 +msgid "Where's everybody?!" +msgstr "" + +#: voice.py:101 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "" + +#: voice.py:102 +msgid "Zzzzz" +msgstr "" + +#: voice.py:103 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "" + +#: voice.py:114 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "" + +#: voice.py:121 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" + +#: voice.py:122 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" + +#: voice.py:123 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" + +#: voice.py:128 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "" + +#: voice.py:129 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" + +#: voice.py:130 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" + +#: voice.py:135 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" + +#: voice.py:139 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" + +#: voice.py:143 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "" + +#: voice.py:144 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "" + +#: voice.py:145 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "" + +#: voice.py:147 +msgid "Met 1 peer" +msgstr "" + +#: voice.py:149 +#, python-brace-format +msgid "Met {num} peers" +msgstr "" + +#: voice.py:154 +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index 1c49562..f6a6111 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -5,7 +5,7 @@ from PIL import Image, ImageDraw import core import pwnagotchi -from pwnagotchi import voice +from pwnagotchi.voice import Voice import pwnagotchi.ui.fonts as fonts import pwnagotchi.ui.faces as faces @@ -49,6 +49,7 @@ class View(object): self._config = config self._canvas = None self._lock = Lock() + self._voice = Voice(lang=config['main']['lang']) self._width, self._height, \ face_pos, name_pos, status_pos = setup_display_specifics(config) @@ -81,7 +82,7 @@ class View(object): 'name': Text(value='%s>' % 'pwnagotchi', position=name_pos, color=BLACK, font=fonts.Bold), # 'face2': Bitmap( '/root/pwnagotchi/data/images/face_happy.bmp', (0, 20)), - 'status': Text(value=voice.default(), position=status_pos, color=BLACK, font=fonts.Medium), + 'status': Text(value=self._voice.default(), position=status_pos, color=BLACK, font=fonts.Medium), 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=(0, self._height - int(self._height * .12) + 1), label_font=fonts.Bold, @@ -116,19 +117,19 @@ class View(object): self._state.set(key, value) def on_starting(self): - self.set('status', voice.on_starting()) + self.set('status', self._voice.on_starting()) self.set('face', faces.AWAKE) def on_ai_ready(self): self.set('mode', '') self.set('face', faces.HAPPY) - self.set('status', voice.on_ai_ready()) + self.set('status', self._voice.on_ai_ready()) self.update() def on_manual_mode(self, log): self.set('mode', 'MANU') self.set('face', faces.SAD if log.handshakes == 0 else faces.HAPPY) - self.set('status', voice.on_log(log)) + self.set('status', self._voice.on_log(log)) self.set('epoch', "%04d" % log.epochs) self.set('uptime', log.duration) self.set('channel', '-') @@ -152,7 +153,7 @@ class View(object): def on_normal(self): self.set('face', faces.AWAKE) - self.set('status', voice.on_normal()) + self.set('status', self._voice.on_normal()) self.update() def set_closest_peer(self, peer): @@ -180,17 +181,17 @@ class View(object): def on_new_peer(self, peer): self.set('face', faces.FRIEND) - self.set('status', voice.on_new_peer(peer)) + self.set('status', self._voice.on_new_peer(peer)) self.update() def on_lost_peer(self, peer): self.set('face', faces.LONELY) - self.set('status', voice.on_lost_peer(peer)) + self.set('status', self._voice.on_lost_peer(peer)) self.update() def on_free_channel(self, channel): self.set('face', faces.SMART) - self.set('status', voice.on_free_channel(channel)) + self.set('status', self._voice.on_free_channel(channel)) self.update() def wait(self, secs, sleeping=True): @@ -206,12 +207,12 @@ class View(object): if sleeping: if secs > 1: self.set('face', faces.SLEEP) - self.set('status', voice.on_napping(secs)) + self.set('status', self._voice.on_napping(secs)) else: self.set('face', faces.SLEEP2) - self.set('status', voice.on_awakening()) + self.set('status', self._voice.on_awakening()) else: - self.set('status', voice.on_waiting(secs)) + self.set('status', self._voice.on_waiting(secs)) if step % 2 == 0: self.set('face', faces.LOOK_R) else: @@ -224,57 +225,57 @@ class View(object): def on_bored(self): self.set('face', faces.BORED) - self.set('status', voice.on_bored()) + self.set('status', self._voice.on_bored()) self.update() def on_sad(self): self.set('face', faces.SAD) - self.set('status', voice.on_sad()) + self.set('status', self._voice.on_sad()) self.update() def on_motivated(self, reward): self.set('face', faces.MOTIVATED) - self.set('status', voice.on_motivated(reward)) + self.set('status', self._voice.on_motivated(reward)) self.update() def on_demotivated(self, reward): self.set('face', faces.DEMOTIVATED) - self.set('status', voice.on_demotivated(reward)) + self.set('status', self._voice.on_demotivated(reward)) self.update() def on_excited(self): self.set('face', faces.EXCITED) - self.set('status', voice.on_excited()) + self.set('status', self._voice.on_excited()) self.update() def on_assoc(self, ap): self.set('face', faces.INTENSE) - self.set('status', voice.on_assoc(ap)) + self.set('status', self._voice.on_assoc(ap)) self.update() def on_deauth(self, sta): self.set('face', faces.COOL) - self.set('status', voice.on_deauth(sta)) + self.set('status', self._voice.on_deauth(sta)) self.update() def on_miss(self, who): self.set('face', faces.SAD) - self.set('status', voice.on_miss(who)) + self.set('status', self._voice.on_miss(who)) self.update() def on_lonely(self): self.set('face', faces.LONELY) - self.set('status', voice.on_lonely()) + self.set('status', self._voice.on_lonely()) self.update() def on_handshakes(self, new_shakes): self.set('face', faces.HAPPY) - self.set('status', voice.on_handshakes(new_shakes)) + self.set('status', self._voice.on_handshakes(new_shakes)) self.update() def on_rebooting(self): self.set('face', faces.BROKEN) - self.set('status', voice.on_rebooting()) + self.set('status', self._voice.on_rebooting()) self.update() def update(self): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index 65b904f..3ff9e0e 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -1,147 +1,160 @@ import random +import gettext +import os -def default(): - return 'ZzzzZZzzzzZzzz' +class Voice: + def __init__(self, lang): + localedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'locale') + translation = gettext.translation( + 'voice', localedir, + languages=[lang], + fallback=True, + ) + translation.install() + self._ = translation.gettext + + def default(self): + return self._('ZzzzZZzzzzZzzz') -def on_starting(): - return random.choice([ \ - 'Hi, I\'m Pwnagotchi!\nStarting ...', - 'New day, new hunt,\nnew pwns!', - 'Hack the Planet!']) + def on_starting(self): + return random.choice([ \ + self._('Hi, I\'m Pwnagotchi!\nStarting ...'), + self._('New day, new hunt,\nnew pwns!'), + self._('Hack the Planet!')]) -def on_ai_ready(): - return random.choice([ - 'AI ready.', - 'The neural network\nis ready.']) + def on_ai_ready(self): + return random.choice([ + self._('AI ready.'), + self._('The neural network\nis ready.')]) -def on_normal(): - return random.choice([ \ - '', - '...']) + def on_normal(self): + return random.choice([ \ + '', + '...']) -def on_free_channel(channel): - return 'Hey, channel %d is\nfree! Your AP will\nsay thanks.' % channel + def on_free_channel(channel): + return self._('Hey, channel {channel} is\nfree! Your AP will\nsay thanks.').format(channel=channel) -def on_bored(): - return random.choice([ \ - 'I\'m bored ...', - 'Let\'s go for a walk!']) + def on_bored(): + return random.choice([ \ + self._('I\'m bored ...'), + self._('Let\'s go for a walk!')]) -def on_motivated(reward): - return 'This is the best\nday of my life!' + def on_motivated(self, reward): + return self._('This is the best\nday of my life!') -def on_demotivated(reward): - return 'Shitty day :/' + def on_demotivated(self, reward): + return self._('Shitty day :/') -def on_sad(): - return random.choice([ \ - 'I\'m extremely bored ...', - 'I\'m very sad ...', - 'I\'m sad', - '...']) + def on_sad(self): + return random.choice([ \ + self._('I\'m extremely bored ...'), + self._('I\'m very sad ...'), + self._('I\'m sad'), + '...']) -def on_excited(): - return random.choice([ \ - 'I\'m living the life!', - 'I pwn therefore I am.', - 'So many networks!!!', - 'I\'m having so much\nfun!', - 'My crime is that of\ncuriosity ...']) + def on_excited(self): + return random.choice([ \ + self._('I\'m living the life!'), + self._('I pwn therefore I am.'), + self._('So many networks!!!'), + self._('I\'m having so much\nfun!'), + self._('My crime is that of\ncuriosity ...')]) -def on_new_peer(peer): - return random.choice([ \ - 'Hello\n%s!\nNice to meet you.' % peer.name(), - 'Unit\n%s\nis nearby!' % peer.name()]) + def on_new_peer(self, peer): + return random.choice([ \ + self._('Hello\n{name}!\nNice to meet you. {name}').format(name=peer.name()), + self._('Unit\n{name}\nis nearby! {name}').format(name=peer.name())]) -def on_lost_peer(peer): - return random.choice([ \ - 'Uhm ...\ngoodbye\n%s' % peer.name(), - '%s\nis gone ...' % peer.name()]) + def on_lost_peer(self, peer): + return random.choice([ \ + self._('Uhm ...\ngoodbye\n{name}').format(name=peer.name()), + self._('{name}\nis gone ...').format(name=peer.name())]) -def on_miss(who): - return random.choice([ \ - 'Whoops ...\n%s\nis gone.' % who, - '%s\nmissed!' % who, - 'Missed!']) + def on_miss(self, who): + return random.choice([ \ + self._('Whoops ...\n{name}\nis gone.').format(name=who), + self._('{name}\nmissed!').format(name=who), + self._('Missed!')]) -def on_lonely(): - return random.choice([ \ - 'Nobody wants to\nplay with me ...', - 'I feel so alone ...', - 'Where\'s everybody?!']) + def on_lonely(self): + return random.choice([ \ + self._('Nobody wants to\nplay with me ...'), + self._('I feel so alone ...'), + self._('Where\'s everybody?!')]) -def on_napping(secs): - return random.choice([ \ - 'Napping for %ds ...' % secs, - 'Zzzzz', - 'ZzzZzzz (%ds)' % secs]) + def on_napping(self,secs): + return random.choice([ \ + self._('Napping for {secs}s ...').format(secs=secs), + self._('Zzzzz'), + self._('ZzzZzzz ({secs}s)').format(secs=secs)]) -def on_awakening(): - return random.choice(['...', '!']) + def on_awakening(self): + return random.choice(['...', '!']) -def on_waiting(secs): - return random.choice([ \ - 'Waiting for %ds ...' % secs, - '...', - 'Looking around (%ds)' % secs]) + def on_waiting(self,secs): + return random.choice([ \ + self._('Waiting for {secs}s ...').format(secs=secs), + '...', + self._('Looking around ({secs}s)').format(secs=secs)]) -def on_assoc(ap): - ssid, bssid = ap['hostname'], ap['mac'] - what = ssid if ssid != '' and ssid != '<hidden>' else bssid - return random.choice([ \ - 'Hey\n%s\nlet\'s be friends!' % what, - 'Associating to\n%s' % what, - 'Yo\n%s!' % what]) + def on_assoc(self,ap): + ssid, bssid = ap['hostname'], ap['mac'] + what = ssid if ssid != '' and ssid != '<hidden>' else bssid + return random.choice([ \ + self._('Hey\n{what}\nlet\'s be friends!').format(what=what), + self._('Associating to\n{what}').format(what=what), + self._('Yo\n{what}!').format(what=what)]) -def on_deauth(sta): - return random.choice([ \ - 'Just decided that\n%s\nneeds no WiFi!' % sta['mac'], - 'Deauthenticating\n%s' % sta['mac'], - 'Kickbanning\n%s!' % sta['mac']]) + def on_deauth(self,sta): + return random.choice([ \ + self._('Just decided that\n{mac}\nneeds no WiFi!').format(mac=sta['mac']), + self._('Deauthenticating\n{mac}').format(mac=sta['mac']), + self._('Kickbanning\n{mac}!').format(mac=sta['mac'])]) -def on_handshakes(new_shakes): - s = 's' if new_shakes > 1 else '' - return 'Cool, we got %d\nnew handshake%s!' % (new_shakes, s) + def on_handshakes(self,new_shakes): + s = 's' if new_shakes > 1 else '' + return self._('Cool, we got {num}\nnew handshake{plural}!').format(num=new_shakes, plural=s) -def on_rebooting(): - return "Ops, something\nwent wrong ...\nRebooting ..." + def on_rebooting(self): + return self._("Ops, something\nwent wrong ...\nRebooting ...") -def on_log(log): - status = 'Kicked %d stations\n' % log.deauthed - status += 'Made %d new friends\n' % log.associated - status += 'Got %d handshakes\n' % log.handshakes - if log.peers == 1: - status += 'Met 1 peer' - elif log.peers > 0: - status += 'Met %d peers' % log.peers - return status + def on_log(self,log): + status = self._('Kicked {num} stations\n').format(num=log.deauthed) + status += self._('Made {num} new friends\n').format(num=log.associated) + status += self._('Got {num} handshakes\n').format(num=log.handshakes) + if log.peers == 1: + status += self._('Met 1 peer') + elif log.peers > 0: + status += self._('Met {num} peers').format(num=log.peers) + return status -def on_log_tweet(log): - return 'I\'ve been pwning for %s and kicked %d clients! I\'ve also met %d new friends and ate %d handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet' % ( \ - log.duration_human, - log.deauthed, - log.associated, - log.handshakes) + def on_log_tweet(self,log): + return self._('I\'ve been pwning for {duration} and kicked {deauthed} clients! I\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format( + duration=log.duration_human, + deauthed=log.deauthed, + associated=log.associated, + handshakes=log.handshakes) From 8ba2ddcd88e6f2f6dfa5695db3f6feafbd4b0497 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sun, 29 Sep 2019 16:03:42 +0200 Subject: [PATCH 08/10] Update usage --- scripts/language.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/language.sh b/scripts/language.sh index 192f463..c56b784 100755 --- a/scripts/language.sh +++ b/scripts/language.sh @@ -15,10 +15,10 @@ cat <<EOF usage: $0 <command> [options] Commands: - add <language> # Adds a new language - delete <language> # Deletes a language - compile <language> # Compiles a language - update # Update + add <language> + delete <language> + compile <language> + update <language> EOF } From 927e764ff806e2a132e11b4c85a51636f38f7aea Mon Sep 17 00:00:00 2001 From: Cassiano Aquino <cassianoaquino@me.com> Date: Sun, 29 Sep 2019 18:00:31 +0100 Subject: [PATCH 09/10] if eth0 exists, enable dhcp on it. for pi3 users --- sdcard/rootfs/etc/network/interfaces | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdcard/rootfs/etc/network/interfaces b/sdcard/rootfs/etc/network/interfaces index 1d8ee6b..2c84f3c 100644 --- a/sdcard/rootfs/etc/network/interfaces +++ b/sdcard/rootfs/etc/network/interfaces @@ -5,6 +5,9 @@ iface lo inet loopback allow-hotplug wlan0 iface wlan0 inet static +allow-hotplug eth0 +iface eth0 inet dhcp + allow-hotplug usb0 iface usb0 inet static address 10.0.0.2 From e35a64734f146366a99b2bec4cc3999b321825bb Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sun, 29 Sep 2019 19:44:31 +0200 Subject: [PATCH 10/10] Add filesize check --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index f081681..97e9a6d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -54,7 +54,7 @@ class Stats(object): def load(self): with self._lock: - if os.path.exists(self.path): + if os.path.exists(self.path) and os.path.getsize(self.path) > 0: core.log("[ai] loading %s" % self.path) with open(self.path, 'rt') as fp: obj = json.load(fp)