From ca916b4722a7faffeb6ebda84d7903500dc52760 Mon Sep 17 00:00:00 2001 From: Periklis Fregkos <leajian13@gmail.com> Date: Mon, 30 Sep 2019 05:03:33 +0300 Subject: [PATCH 1/2] Added Greek support There are some issues with plural words though. --- .../pwnagotchi/locale/gr/LC_MESSAGES/voice.mo | Bin 0 -> 4750 bytes .../pwnagotchi/locale/gr/LC_MESSAGES/voice.po | 341 ++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..434c3b8426a1ea2236573ce376eefaf58166c189 GIT binary patch literal 4750 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 XKe;+P`WC<1I&!w?GHtZvlEVKF>Fjqx literal 0 HcmV?d00001 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po new file mode 100644 index 0000000..2d21d99 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po @@ -0,0 +1,341 @@ +# 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: greek\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 "" +"Γεία, είμαι το Pwnagotchi!\n" +"Εκκινούμαι ..." + +#: voice.py:22 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" +"Νέα μέρα, νέο κυνήγι,\n" +"νέα pwns!" + +#: voice.py:23 +msgid "Hack the Planet!" +msgstr "Hackαρε τον Πλανήτη!" + +#: voice.py:28 +msgid "AI ready." +msgstr "ΤΝ έτοιμη." + +#: voice.py:29 +msgid "" +"The neural network\n" +"is ready." +msgstr "" +"Το νευρωνικό δίκτυο\n" +"είναι έτοιμο." + +#: voice.py:39 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" +"Ε, το κανάλι {channel} είναι\n" +"ελεύθερο! Το AP σου θα\n" +"είναι ευγνώμων." + +#: 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 "" +"Είναι η καλύτερη\n" +"μέρα της ζωής μου!" + +#: 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 "Pwnάρω άρα υπάρχω." + +#: 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 "" +"Το μόνο μου έγκλημα\n" +"είναι η περιέργεια ..." + +#: voice.py:75 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" +"Γειά σου\n" +"{name}!\n" +"Χάρηκα για τη γνωριμία. {name}" + +#: voice.py:76 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is nearby! {name}" +msgstr "" +"Η μονάδα\n" +"{name}\n" +"είναι κοντά! {name}" + +#: voice.py:81 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" +"Εμμ ...\n" +"αντίο\n" +"{name}" + +#: voice.py:82 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" +"{name}\n" +"έφυγε ..." + +#: voice.py:87 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" +"Ουπς ...\n" +"{name}\n" +"έφυγε." + +#: voice.py:88 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" +"{name}\n" +"χάθηκε!" + +#: voice.py:89 +msgid "Missed!" +msgstr "Χάθηκε!" + +#: voice.py:94 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" +"Κανείς δε θέλει να\n" +"παίξει μαζί μου ..." + +#: 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 "Κοιμάμαι για {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 "Περιμένω για {secs}s ..." + +#: voice.py:114 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Ψάχνω τριγύρω ({secs}s)" + +#: voice.py:121 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" +"Εε\n" +"{what}\n" +"ας γίνουμε φίλοι!" + +#: voice.py:122 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" +"Συσχετίζομαι με το\n" +"{what}" + +#: voice.py:123 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" +"Που'σε ρε τρελέ'\n" +"{what}!" + +#: voice.py:128 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "" +"Μόλις αποφάσισα ότι η\n" +"{mac}\n" +"δε χρείαζεται WiFi!" + +#: voice.py:129 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" +"Αποπιστοποίηση της\n" +"{mac}" + +#: voice.py:130 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" +"Κλωτσομπούνι στη\n" +"{mac}!" + +#: voice.py:135 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" +"Τέλεια δικέ μου, πήραμε {num}\n" +"νέες handshake{plural}!" + +#: voice.py:139 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" +"Ουπς, κάτι\n" +"πήγε λάθος ...\n" +"Επανεκκινούμαι ..." + +#: voice.py:143 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Έριξα {num} σταθμούς\n" + +#: voice.py:144 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Έκανα {num} νέους φίλους\n" + +#: voice.py:145 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Πήρα {num} χειραψίες\n" + +#: voice.py:147 +msgid "Met 1 peer" +msgstr "Γνώρισα 1 συνάδελφο" + +#: voice.py:149 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Γνώρισα {num} συναδέλφους" + +#: 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 "" +"Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα " +"{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" From b25092c97b2c1453d9defba3f3d5ffeef70d450f Mon Sep 17 00:00:00 2001 From: James Hooker <g0blin@hackthebox.eu> Date: Mon, 30 Sep 2019 11:20:35 +0100 Subject: [PATCH 2/2] Include PaPiRus drivers in project --- .../scripts/pwnagotchi/ui/display.py | 6 +- .../scripts/pwnagotchi/ui/papirus/__init__.py | 0 .../scripts/pwnagotchi/ui/papirus/epd.py | 213 ++++++++++++++++++ .../scripts/pwnagotchi/ui/papirus/lm75b.py | 46 ++++ .../root/pwnagotchi/scripts/requirements.txt | 1 + 5 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 4f9bb4a..c530caa 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -123,11 +123,11 @@ class Display(View): self._display = InkyPHAT(self._display_color) self._display.set_border(InkyPHAT.BLACK) self._render_cb = self._inky_render - + elif self._is_papirus(): - from papirus import Papirus + from pwnagotchi.ui.papirus.epd import EPD os.environ['EPD_SIZE'] = '2.0' - self._display = Papirus() + self._display = EPD() self._display.clear() self._render_cb = self._papirus_render diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py new file mode 100644 index 0000000..923993b --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py @@ -0,0 +1,213 @@ +#qCopyright 2013-2015 Pervasive Displays, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language +# governing permissions and limitations under the License. + + +from PIL import Image +from PIL import ImageOps +from pwnagotchi.ui.papirus.lm75b import LM75B +import re +import os +import sys + +if sys.version_info < (3,): + def b(x): + return x +else: + def b(x): + return x.encode('ISO-8859-1') + +class EPDError(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +class EPD(object): + + """EPD E-Ink interface + +to use: + from EPD import EPD + + epd = EPD([path='/path/to/epd'], [auto=boolean], [rotation = 0|90|180|270]) + + image = Image.new('1', epd.size, 0) + # draw on image + epd.clear() # clear the panel + epd.display(image) # tranfer image data + epd.update() # refresh the panel image - not needed if auto=true +""" + + + PANEL_RE = re.compile('^([A-Za-z]+)\s+(\d+\.\d+)\s+(\d+)x(\d+)\s+COG\s+(\d+)\s+FILM\s+(\d+)\s*$', flags=0) + + def __init__(self, *args, **kwargs): + self._epd_path = '/dev/epd' + self._width = 200 + self._height = 96 + self._panel = 'EPD 2.0' + self._cog = 0 + self._film = 0 + self._auto = False + self._lm75b = LM75B() + self._rotation = 0 + self._uselm75b = True + + if len(args) > 0: + self._epd_path = args[0] + elif 'epd' in kwargs: + self._epd_path = kwargs['epd'] + + if ('auto' in kwargs) and kwargs['auto']: + self._auto = True + if ('rotation' in kwargs): + rot = kwargs['rotation'] + if rot in (0, 90, 180, 270): + self._rotation = rot + else: + raise EPDError('rotation can only be 0, 90, 180 or 270') + + with open(os.path.join(self._epd_path, 'version')) as f: + self._version = f.readline().rstrip('\n') + + with open(os.path.join(self._epd_path, 'panel')) as f: + line = f.readline().rstrip('\n') + m = self.PANEL_RE.match(line) + if m is None: + raise EPDError('invalid panel string') + self._panel = m.group(1) + ' ' + m.group(2) + self._width = int(m.group(3)) + self._height = int(m.group(4)) + self._cog = int(m.group(5)) + self._film = int(m.group(6)) + + if self._width < 1 or self._height < 1: + raise EPDError('invalid panel geometry') + if self._rotation in (90, 270): + self._width, self._height = self._height, self._width + + @property + def size(self): + return (self._width, self._height) + + @property + def width(self): + return self._width + + @property + def height(self): + return self._height + + @property + def panel(self): + return self._panel + + @property + def version(self): + return self._version + + @property + def cog(self): + return self._cog + + @property + def film(self): + return self._film + + @property + def auto(self): + return self._auto + + @auto.setter + def auto(self, flag): + if flag: + self._auto = True + else: + self._auto = False + + @property + def rotation(self): + return self._rotation + + @rotation.setter + def rotation(self, rot): + if rot not in (0, 90, 180, 270): + raise EPDError('rotation can only be 0, 90, 180 or 270') + if abs(self._rotation - rot) == 90 or abs(self._rotation - rot) == 270: + self._width, self._height = self._height, self._width + self._rotation = rot + + @property + def use_lm75b(self): + return self._uselm75b + + @use_lm75b.setter + def use_lm75b(self, flag): + if flag: + self._uselm75b = True + else: + self._uselm75b = False + + def error_status(self): + with open(os.path.join(self._epd_path, 'error'), 'r') as f: + return(f.readline().rstrip('\n')) + + def rotation_angle(self, rotation): + angles = { 90 : Image.ROTATE_90, 180 : Image.ROTATE_180, 270 : Image.ROTATE_270 } + return angles[rotation] + + def display(self, image): + + # attempt grayscale conversion, and then to single bit + # better to do this before calling this if the image is to + # be dispayed several times + if image.mode != "1": + image = ImageOps.grayscale(image).convert("1", dither=Image.FLOYDSTEINBERG) + + if image.mode != "1": + raise EPDError('only single bit images are supported') + + if image.size != self.size: + raise EPDError('image size mismatch') + + if self._rotation != 0: + image = image.transpose(self.rotation_angle(self._rotation)) + + with open(os.path.join(self._epd_path, 'LE', 'display_inverse'), 'r+b') as f: + f.write(image.tobytes()) + + if self.auto: + self.update() + + + def update(self): + self._command('U') + + def partial_update(self): + self._command('P') + + def fast_update(self): + self._command('F') + + def clear(self): + self._command('C') + + def _command(self, c): + if self._uselm75b: + with open(os.path.join(self._epd_path, 'temperature'), 'wb') as f: + f.write(b(repr(self._lm75b.getTempC()))) + with open(os.path.join(self._epd_path, 'command'), 'wb') as f: + f.write(b(c)) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py new file mode 100644 index 0000000..f3087f2 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py @@ -0,0 +1,46 @@ +# Minimal support for LM75b temperature sensor on the Papirus HAT / Papirus Zero +# This module allows you to read the temperature. +# The OS-output (Over-temperature Shutdown) connected to GPIO xx (pin 11) is not supported +# by this module +# + +from __future__ import (print_function, division) + +import smbus + +LM75B_ADDRESS = 0x48 + +LM75B_TEMP_REGISTER = 0 +LM75B_CONF_REGISTER = 1 +LM75B_THYST_REGISTER = 2 +LM75B_TOS_REGISTER = 3 + +LM75B_CONF_NORMAL = 0 + +class LM75B(object): + def __init__(self, address=LM75B_ADDRESS, busnum=1): + self._address = address + self._bus = smbus.SMBus(busnum) + self._bus.write_byte_data(self._address, LM75B_CONF_REGISTER, LM75B_CONF_NORMAL) + + def getTempCFloat(self): + """Return temperature in degrees Celsius as float""" + raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = ((raw << 8) & 0xFF00) + (raw >> 8) + return (raw / 32.0) / 8.0 + + def getTempFFloat(self): + """Return temperature in degrees Fahrenheit as float""" + return (self.getTempCFloat() * (9.0 / 5.0)) + 32.0 + + def getTempC(self): + """Return temperature in degrees Celsius as integer, so it can be + used to write to /dev/epd/temperature""" + raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = ((raw << 8) & 0xFF00) + (raw >> 8) + return (raw + 128) // 256 # round to nearest integer + +if __name__ == "__main__": + sens = LM75B() + print(sens.getTempC(), sens.getTempFFloat()) + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt index 9b0d40d..0a82ef7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt +++ b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt @@ -9,3 +9,4 @@ tweepy file_read_backwards numpy inky +smbus