diff --git a/pwnagotchi/defaults.yml b/pwnagotchi/defaults.yml index 0aed0f7f..d2e9d271 100644 --- a/pwnagotchi/defaults.yml +++ b/pwnagotchi/defaults.yml @@ -58,6 +58,7 @@ main: wpa-sec: enabled: false api_key: ~ + api_url: "https://wpa-sec.stanev.org" wigle: enabled: false api_key: ~ @@ -194,7 +195,7 @@ ui: display: enabled: true rotation: 180 - # Possible options inkyphat/inky, papirus/papi, waveshare_1/ws_1 or waveshare_2/ws_2, oledhat + # Possible options inkyphat/inky, papirus/papi, waveshare_1/ws_1 or waveshare_2/ws_2, oledhat, waveshare27inch type: 'waveshare_2' # Possible options red/yellow/black (black used for monocromatic displays) color: 'black' diff --git a/pwnagotchi/locale/pl/LC_MESSAGES/voice.mo b/pwnagotchi/locale/pl/LC_MESSAGES/voice.mo index 303c60b3..f762e958 100644 Binary files a/pwnagotchi/locale/pl/LC_MESSAGES/voice.mo and b/pwnagotchi/locale/pl/LC_MESSAGES/voice.mo differ diff --git a/pwnagotchi/locale/pl/LC_MESSAGES/voice.po b/pwnagotchi/locale/pl/LC_MESSAGES/voice.po index d616bc3b..70fd08aa 100644 --- a/pwnagotchi/locale/pl/LC_MESSAGES/voice.po +++ b/pwnagotchi/locale/pl/LC_MESSAGES/voice.po @@ -1,24 +1,23 @@ # Polish voice data for pwnagotchi. # Copyright (C) 2019 -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR szymex73 , 2019. +# This file is distributed under the same license as the pwnagotchi package. +# szymex73 , 2019. # -#, fuzzy msgid "" msgstr "" -"Project-Id-Version: 0.0.1\n" +"Project-Id-Version: 0.0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-09 17:42+0200\n" -"PO-Revision-Date: 2019-10-09 17:42+0200\n" -"Last-Translator: szymex73 \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2019-10-21 08:39+0200\n" +"PO-Revision-Date: 2019-10-21 10:55+0200\n" +"Last-Translator: gkrs <457603+gkrs@users.noreply.github.com>\n" +"Language-Team: PL <457603+gkrs@users.noreply.github.com>\n" "Language: polish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "ZzzzZZzzzzZzzz" -msgstr "ZzzzZZzzzzZzzz" +msgstr "" msgid "Hi, I'm Pwnagotchi! Starting ..." msgstr "Hej, jestem Pwnagotchi! Uruchamianie ..." @@ -35,9 +34,12 @@ msgstr "SI gotowa." msgid "The neural network is ready." msgstr "Sieć neuronowa jest gotowa." +msgid "Generating keys, do not turn off ..." +msgstr "Generuję klucze, nie wyłączaj ..." + #, python-brace-format msgid "Hey, channel {channel} is free! Your AP will say thanks." -msgstr "Hej, kanał {channel} jest wolny! Twój AP mi podziękuje." +msgstr "Hej, kanał {channel} jest wolny! Twój AP będzie Ci wdzięczny." msgid "I'm bored ..." msgstr "Nudzi mi się ..." @@ -46,10 +48,10 @@ msgid "Let's go for a walk!" msgstr "Chodźmy na spacer!" msgid "This is the best day of my life!" -msgstr "To jest najlepszy dzień w moim życiu!" +msgstr "To najlepszy dzień mojego życia!" msgid "Shitty day :/" -msgstr "Ten dzień jest do dupy :/" +msgstr "Gówniany dzień :/" msgid "I'm extremely bored ..." msgstr "Straaaasznie się nudzę ..." @@ -64,7 +66,7 @@ msgid "I'm living the life!" msgstr "Cieszę się życiem!" msgid "I pwn therefore I am." -msgstr "Pwnuje więc jestem." +msgstr "Pwnuję więc jestem." msgid "So many networks!!!" msgstr "Jak dużo sieci!!!" @@ -76,12 +78,12 @@ msgid "My crime is that of curiosity ..." msgstr "Moją zbrodnią jest ciekawość ..." #, python-brace-format -msgid "Hello {name}! Nice to meet you. {name}" -msgstr "Cześć {name}! Miło cię poznać. {name}" +msgid "Hello {name}! Nice to meet you." +msgstr "Cześć {name}! Miło Cię poznać." #, python-brace-format -msgid "Unit {name} is nearby! {name}" -msgstr "Jednostka {name} jest niedaleko! {name}" +msgid "Unit {name} is nearby!" +msgstr "Urządzenie {name} jest w pobliżu!" #, python-brace-format msgid "Uhm ... goodbye {name}" @@ -97,16 +99,16 @@ msgstr "Ups ... {name} zniknął." #, python-brace-format msgid "{name} missed!" -msgstr "{name} przeoczył!" +msgstr "{name} pudło!" msgid "Missed!" -msgstr "Spóźniony!" +msgstr "Pudło!" msgid "Nobody wants to play with me ..." -msgstr "Nikt się nie chce ze mną bawić ..." +msgstr "Nikt nie chce się ze mną bawić ..." msgid "I feel so alone ..." -msgstr "Czuję się tak samotnie ..." +msgstr "Czuję się taki samotny ..." msgid "Where's everybody?!" msgstr "Gdzie są wszyscy?!" @@ -116,17 +118,17 @@ msgid "Napping for {secs}s ..." msgstr "Zdrzemnę się przez {secs}s ..." msgid "Zzzzz" -msgstr "Zzzzz" +msgstr "" #, python-brace-format msgid "ZzzZzzz ({secs}s)" -msgstr "ZzzZzzz ({secs}s)" +msgstr "" msgid "Good night." msgstr "Dobranoc." msgid "Zzz" -msgstr "Zzz" +msgstr "" #, python-brace-format msgid "Waiting for {secs}s ..." @@ -138,15 +140,15 @@ msgstr "Rozglądam się ({secs}s)" #, python-brace-format msgid "Hey {what} let's be friends!" -msgstr "Hej {what}, zostańmy przyjaciółmi!" +msgstr "Hej {what} zostańmy przyjaciółmi!" #, python-brace-format msgid "Associating to {what}" -msgstr "Łączenie się z {what}" +msgstr "Dołączam do {what}" #, python-brace-format msgid "Yo {what}!" -msgstr "Ej {what}!" +msgstr "Siema {what}!" #, python-brace-format msgid "Just decided that {mac} needs no WiFi!" @@ -158,33 +160,33 @@ msgstr "Rozłączam {mac}" #, python-brace-format msgid "Kickbanning {mac}!" -msgstr "Banowanie {mac}!" +msgstr "Banuję {mac}!" #, python-brace-format msgid "Cool, we got {num} new handshake{plural}!" -msgstr "Super, zdobylismy {num} handshake{plural}!" +msgstr "Super, zdobyliśmy {num} nowych handshake'ów!" msgid "Ops, something went wrong ... Rebooting ..." -msgstr "Ups, coś się stało ... Restartuję ..." +msgstr "Ups, coś poszło nie tak ... Restaruję ..." #, python-brace-format msgid "Kicked {num} stations\n" -msgstr "Wyrzucono {num} stacji\n" +msgstr "Wyrzuciłem {num} stacji\n" #, python-brace-format msgid "Made {num} new friends\n" -msgstr "Zdobyto {num} przyjaciół\n" +msgstr "Zdobyłem {num} nowych przyjaciół\n" #, python-brace-format msgid "Got {num} handshakes\n" -msgstr "Zdobyto {num} handshakow\n" +msgstr "Zdobyłem {num} handshake'ów\n" msgid "Met 1 peer" -msgstr "Spotkano 1 kolegę" +msgstr "Spotkałem 1 kolegę" #, python-brace-format msgid "Met {num} peers" -msgstr "Spotkano {num} kolegów" +msgstr "Spotkałem {num} kolegów" #, python-brace-format msgid "" @@ -192,8 +194,8 @@ msgid "" "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" -"Pwnowalem przez {duration} i wyrzuciłem {deauthed} klientów! Spotkałem także " -"{associated} nowych przyjaciół i zjadłem {handshakes} handshaków! #pwnagotchi " +"Pwnowałem {duration} i wyrzuciłem {deauthed} klientów! Spotkałem także " +"{associated} nowych przyjaciół i zjadłem {handshakes} handshake'ow! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgid "hours" diff --git a/pwnagotchi/locale/voice.pot b/pwnagotchi/locale/voice.pot index cf023626..10de71fe 100644 --- a/pwnagotchi/locale/voice.pot +++ b/pwnagotchi/locale/voice.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-09 17:42+0200\n" +"POT-Creation-Date: 2019-10-21 10:49+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -35,6 +35,9 @@ msgstr "" msgid "The neural network is ready." msgstr "" +msgid "Generating keys, do not turn off ..." +msgstr "" + #, python-brace-format msgid "Hey, channel {channel} is free! Your AP will say thanks." msgstr "" @@ -76,11 +79,11 @@ msgid "My crime is that of curiosity ..." msgstr "" #, python-brace-format -msgid "Hello {name}! Nice to meet you. {name}" +msgid "Hello {name}! Nice to meet you." msgstr "" #, python-brace-format -msgid "Unit {name} is nearby! {name}" +msgid "Unit {name} is nearby!" msgstr "" #, python-brace-format diff --git a/pwnagotchi/plugins/default/example.py b/pwnagotchi/plugins/default/example.py index 3f3e570c..72087cfb 100644 --- a/pwnagotchi/plugins/default/example.py +++ b/pwnagotchi/plugins/default/example.py @@ -14,6 +14,18 @@ import pwnagotchi.ui.fonts as fonts # Will be set with the options in config.yml config['main']['plugins'][__name__] OPTIONS = dict() +# called when :/plugins/ is opened +def on_webhook(response, path): + res = "Hook triggered" + response.send_response(200) + response.send_header('Content-type', 'text/html') + response.end_headers() + + try: + response.wfile.write(bytes(res, "utf-8")) + except Exception as ex: + logging.error(ex) + # called when the plugin is loaded def on_loaded(): logging.warning("WARNING: plugin %s should be disabled!" % __name__) diff --git a/pwnagotchi/plugins/default/wpa-sec.py b/pwnagotchi/plugins/default/wpa-sec.py index efa3faaf..6bf99940 100644 --- a/pwnagotchi/plugins/default/wpa-sec.py +++ b/pwnagotchi/plugins/default/wpa-sec.py @@ -25,19 +25,23 @@ def on_loaded(): logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org") return + if 'api_url' not in OPTIONS or ('api_url' in OPTIONS and OPTIONS['api_url'] is None): + logging.error("WPA_SEC: API-URL isn't set. Can't upload, no endpoint configured.") + return + READY = True def _upload_to_wpasec(path, timeout=30): """ - Uploads the file to wpa-sec.stanev.org + Uploads the file to https://wpa-sec.stanev.org, or another endpoint. """ with open(path, 'rb') as file_to_upload: cookie = {'key': OPTIONS['api_key']} payload = {'file': file_to_upload} try: - result = requests.post('https://wpa-sec.stanev.org', + result = requests.post(OPTIONS['api_url'], cookies=cookie, files=payload, timeout=timeout) diff --git a/pwnagotchi/ui/display.py b/pwnagotchi/ui/display.py index eac519f2..c4fd4952 100644 --- a/pwnagotchi/ui/display.py +++ b/pwnagotchi/ui/display.py @@ -29,6 +29,9 @@ class Display(View): def is_waveshare_v2(self): return self._implementation.name == 'waveshare_2' + def is_waveshare27inch(self): + return self._implementation.name == 'waveshare27inch' + def is_oledhat(self): return self._implementation.name == 'oledhat' diff --git a/pwnagotchi/ui/hw/__init__.py b/pwnagotchi/ui/hw/__init__.py index ee00a73e..1e0bf31a 100644 --- a/pwnagotchi/ui/hw/__init__.py +++ b/pwnagotchi/ui/hw/__init__.py @@ -4,6 +4,7 @@ from pwnagotchi.ui.hw.oledhat import OledHat from pwnagotchi.ui.hw.lcdhat import LcdHat from pwnagotchi.ui.hw.waveshare1 import WaveshareV1 from pwnagotchi.ui.hw.waveshare2 import WaveshareV2 +from pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch def display_for(config): @@ -26,3 +27,6 @@ def display_for(config): elif config['ui']['display']['type'] == 'waveshare_2': return WaveshareV2(config) + + elif config['ui']['display']['type'] == 'waveshare27inch': + return Waveshare27inch(config) \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/v27inch/__init__.py b/pwnagotchi/ui/hw/libs/waveshare/v27inch/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pwnagotchi/ui/hw/libs/waveshare/v27inch/epd2in7.py b/pwnagotchi/ui/hw/libs/waveshare/v27inch/epd2in7.py new file mode 100644 index 00000000..01e84736 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/v27inch/epd2in7.py @@ -0,0 +1,300 @@ +# /***************************************************************************** +# * | File : EPD_1in54.py +# * | Author : Waveshare team +# * | Function : Electronic paper driver +# * | Info : +# *---------------- +# * | This version: V3.0 +# * | Date : 2018-11-06 +# * | Info : python2 demo +# * 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 +# * 2.Change: +# display_frame -> TurnOnDisplay +# set_memory_area -> SetWindow +# set_memory_pointer -> SetCursor +# get_frame_buffer -> getbuffer +# set_frame_memory -> display +# * 3.How to use +# epd = epd2in7.EPD() +# epd.init(epd.lut_full_update) +# image = Image.new('1', (epd1in54.EPD_WIDTH, epd1in54.EPD_HEIGHT), 255) +# ... +# drawing ...... +# ... +# epd.display(getbuffer(image)) +# ******************************************************************************/ +# 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 + +# Display resolution +EPD_WIDTH = 176 +EPD_HEIGHT = 264 + +# EPD2IN7 commands +PANEL_SETTING = 0x00 +POWER_SETTING = 0x01 +POWER_OFF = 0x02 +POWER_OFF_SEQUENCE_SETTING = 0x03 +POWER_ON = 0x04 +POWER_ON_MEASURE = 0x05 +BOOSTER_SOFT_START = 0x06 +DEEP_SLEEP = 0x07 +DATA_START_TRANSMISSION_1 = 0x10 +DATA_STOP = 0x11 +DISPLAY_REFRESH = 0x12 +DATA_START_TRANSMISSION_2 = 0x13 +PARTIAL_DATA_START_TRANSMISSION_1 = 0x14 +PARTIAL_DATA_START_TRANSMISSION_2 = 0x15 +PARTIAL_DISPLAY_REFRESH = 0x16 +LUT_FOR_VCOM = 0x20 +LUT_WHITE_TO_WHITE = 0x21 +LUT_BLACK_TO_WHITE = 0x22 +LUT_WHITE_TO_BLACK = 0x23 +LUT_BLACK_TO_BLACK = 0x24 +PLL_CONTROL = 0x30 +TEMPERATURE_SENSOR_COMMAND = 0x40 +TEMPERATURE_SENSOR_CALIBRATION = 0x41 +TEMPERATURE_SENSOR_WRITE = 0x42 +TEMPERATURE_SENSOR_READ = 0x43 +VCOM_AND_DATA_INTERVAL_SETTING = 0x50 +LOW_POWER_DETECTION = 0x51 +TCON_SETTING = 0x60 +TCON_RESOLUTION = 0x61 +SOURCE_AND_GATE_START_SETTING = 0x62 +GET_STATUS = 0x71 +AUTO_MEASURE_VCOM = 0x80 +VCOM_VALUE = 0x81 +VCM_DC_SETTING_REGISTER = 0x82 +PROGRAM_MODE = 0xA0 +ACTIVE_PROGRAM = 0xA1 +READ_OTP_DATA = 0xA2 + +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_vcom_dc = [ + 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x60, 0x28, 0x28, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x12, 0x12, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + lut_ww = [ + 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, + 0x40, 0x14, 0x00, 0x00, 0x00, 0x01, + 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + lut_bw = [ + 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, + 0x40, 0x14, 0x00, 0x00, 0x00, 0x01, + 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + lut_bb = [ + 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, + 0x80, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + lut_wb = [ + 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, + 0x80, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 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): + while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy + self.send_command(0x71) + epdconfig.delay_ms(100) + + def set_lut(self): + self.send_command(LUT_FOR_VCOM) # vcom + for count in range(0, 44): + self.send_data(self.lut_vcom_dc[count]) + self.send_command(LUT_WHITE_TO_WHITE) # ww -- + for count in range(0, 42): + self.send_data(self.lut_ww[count]) + self.send_command(LUT_BLACK_TO_WHITE) # bw r + for count in range(0, 42): + self.send_data(self.lut_bw[count]) + self.send_command(LUT_WHITE_TO_BLACK) # wb w + for count in range(0, 42): + self.send_data(self.lut_bb[count]) + self.send_command(LUT_BLACK_TO_BLACK) # bb b + for count in range(0, 42): + self.send_data(self.lut_wb[count]) + + def init(self): + if (epdconfig.module_init() != 0): + return -1 + # EPD hardware init start + self.reset() + self.send_command(POWER_SETTING) + self.send_data(0x03) # VDS_EN, VDG_EN + self.send_data(0x00) # VCOM_HV, VGHL_LV[1], VGHL_LV[0] + self.send_data(0x2b) # VDH + self.send_data(0x2b) # VDL + self.send_data(0x09) # VDHR + self.send_command(BOOSTER_SOFT_START) + self.send_data(0x07) + self.send_data(0x07) + self.send_data(0x17) + # Power optimization + self.send_command(0xF8) + self.send_data(0x60) + self.send_data(0xA5) + # Power optimization + self.send_command(0xF8) + self.send_data(0x89) + self.send_data(0xA5) + # Power optimization + self.send_command(0xF8) + self.send_data(0x90) + self.send_data(0x00) + # Power optimization + self.send_command(0xF8) + self.send_data(0x93) + self.send_data(0x2A) + # Power optimization + self.send_command(0xF8) + self.send_data(0xA0) + self.send_data(0xA5) + # Power optimization + self.send_command(0xF8) + self.send_data(0xA1) + self.send_data(0x00) + # Power optimization + self.send_command(0xF8) + self.send_data(0x73) + self.send_data(0x41) + self.send_command(PARTIAL_DISPLAY_REFRESH) + self.send_data(0x00) + self.send_command(POWER_ON) + self.wait_until_idle() + + self.send_command(PANEL_SETTING) + self.send_data(0xAF) # KW-BF KWR-AF BWROTP 0f + self.send_command(PLL_CONTROL) + self.send_data(0x3A) # 3A 100HZ 29 150Hz 39 200HZ 31 171HZ + self.send_command(VCM_DC_SETTING_REGISTER) + self.send_data(0x12) + self.set_lut() + # EPD hardware init end + return 0 + + def getbuffer(self, image): + # print "bufsiz = ",(self.width/8) * self.height + buf = [0xFF] * ((self.width//8) * self.height) + image_monocolor = image.convert('1') + imwidth, imheight = image_monocolor.size + pixels = image_monocolor.load() + # print "imwidth = %d, imheight = %d",imwidth,imheight + if(imwidth == self.width and imheight == self.height): + print("Vertical") + for y in range(imheight): + for x in range(imwidth): + # Set the bits for the column of pixels at the current position. + if pixels[x, y] == 0: + buf[(x + y * self.width) // 8] &= ~(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: + buf[(newx + newy*self.width) // 8] &= ~(0x80 >> (y % 8)) + return buf + + def display(self, image): + self.send_command(DATA_START_TRANSMISSION_1) + for i in range(0, self.width * self.height // 8): + self.send_data(0xFF) + self.send_command(DATA_START_TRANSMISSION_2) + for i in range(0, self.width * self.height // 8): + self.send_data(image[i]) + self.send_command(DISPLAY_REFRESH) + self.wait_until_idle() + + def Clear(self, color): + self.send_command(DATA_START_TRANSMISSION_1) + for i in range(0, self.width * self.height // 8): + self.send_data(0xFF) + self.send_command(DATA_START_TRANSMISSION_2) + for i in range(0, self.width * self.height // 8): + self.send_data(0xFF) + self.send_command(DISPLAY_REFRESH) + self.wait_until_idle() + + def sleep(self): + self.send_command(0X50) + self.send_data(0xf7) + self.send_command(0X02) + self.send_command(0X07) + self.send_data(0xA5) +### END OF FILE ### + diff --git a/pwnagotchi/ui/hw/libs/waveshare/v27inch/epdconfig.py b/pwnagotchi/ui/hw/libs/waveshare/v27inch/epdconfig.py new file mode 100644 index 00000000..78ff6479 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/v27inch/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 ### diff --git a/pwnagotchi/ui/hw/waveshare27inch.py b/pwnagotchi/ui/hw/waveshare27inch.py new file mode 100644 index 00000000..9dff62d1 --- /dev/null +++ b/pwnagotchi/ui/hw/waveshare27inch.py @@ -0,0 +1,46 @@ +import logging + +import pwnagotchi.ui.fonts as fonts +from pwnagotchi.ui.hw.base import DisplayImpl + + +class Waveshare27inch(DisplayImpl): + def __init__(self, config): + super(Waveshare27inch, self).__init__(config, 'waveshare_2_7inch') + self._display = None + + def layout(self): + fonts.setup(10, 9, 10, 35) + self._layout['width'] = 264 + self._layout['height'] = 176 + self._layout['face'] = (0, 54) + self._layout['name'] = (5, 34) + 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': (139, 34), + 'font': fonts.Medium, + 'max': 20 + } + return self._layout + + def initialize(self): + logging.info("initializing waveshare v1 2.7 inch display") + from pwnagotchi.ui.hw.libs.waveshare.v27inch.epd2in7 import EPD + self._display = EPD() + self._display.init() + self._display.Clear(0xFF) + + def render(self, canvas): + buf = self._display.getbuffer(canvas) + self._display.display(buf) + + def clear(self): + self._display.Clear(0xff) diff --git a/pwnagotchi/ui/web.py b/pwnagotchi/ui/web.py index c6b3ac64..021c37a9 100644 --- a/pwnagotchi/ui/web.py +++ b/pwnagotchi/ui/web.py @@ -1,3 +1,4 @@ +import re import _thread from http.server import BaseHTTPRequestHandler, HTTPServer from threading import Lock @@ -5,6 +6,7 @@ import shutil import logging import pwnagotchi +from pwnagotchi import plugins frame_path = '/root/pwnagotchi.png' frame_format = 'PNG' @@ -159,6 +161,13 @@ class Handler(BaseHTTPRequestHandler): elif self.path.startswith('/ui'): self._image() + elif self.path.startswith('/plugins'): + plugin_from_path = re.match(r'\/plugins\/([^\/]+)(\/.*)?', self.path) + if plugin_from_path: + plugin_name = plugin_from_path.groups()[0] + right_path = plugin_from_path.groups()[1] if len(plugin_from_path.groups()) == 2 else None + if plugin_name in plugins.loaded and hasattr(plugins.loaded[plugin_name], 'on_webhook'): + plugins.loaded[plugin_name].on_webhook(self, right_path) else: self.send_response(404) diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 46f1103b..ab7acfd3 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -82,6 +82,9 @@ def load_config(args): elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2'): config['ui']['display']['type'] = 'waveshare_2' + elif config['ui']['display']['type'] in ('ws_27inch', 'ws27inch', 'waveshare_27inch', 'waveshare27inch'): + config['ui']['display']['type'] = 'waveshare27inch' + else: print("unsupported display type %s" % config['ui']['display']['type']) exit(1)