From 5485f83ca63089cf6e13085827ad01593c5c2a7e Mon Sep 17 00:00:00 2001 From: Fabiano F Oliveira Date: Tue, 26 Mar 2024 14:06:55 -0300 Subject: [PATCH 01/39] Update Portuguese (Brazil) Language --- pwnagotchi/locale/pt-br/LC_MESSAGES/voice.mo | Bin 5085 -> 5374 bytes pwnagotchi/locale/pt-br/LC_MESSAGES/voice.po | 518 +++++++++---------- 2 files changed, 259 insertions(+), 259 deletions(-) diff --git a/pwnagotchi/locale/pt-br/LC_MESSAGES/voice.mo b/pwnagotchi/locale/pt-br/LC_MESSAGES/voice.mo index 197597e2045a072ac2f5ffc639ba10084ded42ff..bba61b5ea1ce84e2202ee1293712a95cc2708242 100644 GIT binary patch delta 2567 zcmZ9MTWnNC7{{jq0$qAtNV92ozhZQrfCm!vkb?ciNq}=bZIiN&#z4 z1WAZ5=7dBaPzh0x1YY`JASPlq3Q@eg5fkcz!Ne#rCOl}o#sB~GY)~ip_BWR^^L^ic zzS*hOf45G2+c@*2KtH?j9k?9412zdUA(FGFH?)BrSl9zf@Hm(R&w-8LhaeC73akOY2N!~O zVkYJYF(2cVU>(>2VoCIZbUXlF1{K%>E=5+2@Go|u!%UuyCWNp+9`rJ}2s|0DUj*s! z6R;Yb0_o@nkdA%>Qy>@l-3pLObb=Bb0@L6axCVR|Y=VFBB|6OLHpq;B2f48p`blsd z$N+c8%z;ZVJ`B>)Ns#+4#Pc764D2R|qr`1+75FPS18kZnL<5)tCu-4YM`sq;1@hW^ z<8dE|YZ6a`%y3^k&cYzV6i%=nqs2xP`;)!@X1YW|}2HU_j&<(!DK9KtiNJmFOX7&cS47>>Pye~jr(Jhes z{sj4b0$EYn;{=h0hHitU@Le5+yLGH`OIeH6eJZCToI) z*bn&9twY~etgML!Es7nv}gKTu8%mj&V-v1rxNji>*3YJv1XMu%64Rr z?3Y`IRd!grwzBiu+fi_QOPOLO=UCzXc^l_inbddBu0=`#|~ zIc)5L6NT9wAV^1AI;cdO5|}F;w9~Taj5tz{8PBI<{036nzRnv3J*Yx=*i@IAh!!j@ z^JY}LzM)uFV0;G$MN6vWI-}b7kzh)WnmlryUdp;^)L|mic~qu-7e00TO>~x=o|^U= zor(yJJt7O`@bkLv8Hg%O*5~VUDyt3eDz9@UZ`|1vc(c&af~<%b_NrrLY0>38L$9D~ZM+9?AYQs1rH zs7PeVEl-XaE1YVS)jLN5<>skHSe;z8wEur^4Ng=^xjLtVOqfY7n8^YSdy>oVK9S*M QY1zL%i|!|qs8Yw`A0;)`zW@LL delta 2238 zcmYk6YiJZ#6vwYot5)-H6YDePZZ&E&#-wVisa6xS#XxVcF*_y$yE9>CcB_UZ zR9fhZwlI`F@j(Sqp`{3d#Y$`F1N>0@(n_hNv=oGj_EY;w>F>YUMGt%SH}}lF_uTWp zXZLQ~^`)b~r6#>+uwHxt-dOE_VwF-zb@m?FRVlLuAuZ#lr`l&g&_oCDWFz26R%(1j1e z5>%qspb~um)9^UdyvtC9{Q@og54OWOEM5jPu$lbE=Rp;{1y%7!PzyhU7G8n#;7zEF zr=Y9mwLl$UHRP4q0$bsBI1$EhCOio1;2V(JG9NpK8%xcXOM-!%$f) zSOnEneehAZ59-d|hjZa2C z8>5xLG*)*KSPiux3sKp;0(Ihdp%Nd5s_-I|q`yN|b_ePpvpKDrcNLV>eNYK^K=s5S zNJ>+JDs=Q69@GOzp_<}kWqcZ{g3qCP;(UddAU_oI9pu)`kC2uy-S~Q3u~qmQ{C-pC z_u!nfyl>^*XjvBhaXf}wTq?*^W!3cOq^fjcRV!sy<16vUaT(_*n~IRBN|_pPGtP~b zEzS2jTxvG!_pb)4nj~C~OOcJZ?p!7*C7(=<^#r~YSC8l#)SS9DUDYO>A4b_~_+E?a z_pV0ORq!`pI`FdTMb*?$vJJQ-e+2KsC3ow&JCk=#PDZ9bnfyBaljO}ArBrb6klm2k z*3OAnEX+@WI~iQ)GgoJ z??qa?`U2R|^FN)o~Q=Z!! z>w0pTEKq)afz>!i5e4$-@HTZq{>{uEG^guGgpC>g(9mPWgftJ2vYT z-B2~&TU{ii363p#S%))K*X<9TVnD6=@uKc~6NeISJktve3#R!XG2fVCmN!HJF7ki=grS1T7`$LZM?Z^#{UtkcDC>J})<(b_*86T13(DiJW z9d@HAaLm2X2z!(&;mBk{rlrj`3LXeO)EhfZ)?`g;P0Q}Q^#h7Pop!sMyo{85?380& z>nAU#o}c4-^i9t5-DqzV>^, YEAR. -# - -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-17 15:46+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Foxy \n" -"Language-Team: LANGUAGE \n" -"Language: Portuguese (Brazil)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "ZzzzZZzzzzZzzz" -msgstr "ZzzzZZzzzzZzzz" - -msgid "Hi, I'm Pwnagotchi! Starting ..." -msgstr "Olá, Eu sou Pwnagotchi! Iniciando ..." - -msgid "New day, new hunt, new pwns!" -msgstr "Um novo dia, Uma nova caça e novos pwns!" - -msgid "Hack the Planet!" -msgstr "Burle o Planeta!" - -msgid "AI ready." -msgstr "IA pronta." - -msgid "The neural network is ready." -msgstr "A rede neural está pronta." - -msgid "Generating keys, do not turn off ..." -msgstr "Criando chaves, não desligue o sistema ..." - -#, python-brace-format -msgid "Hey, channel {channel} is free! Your AP will say thanks." -msgstr "Ei, canal {channel} está livre! Seu AP vai agradecer." - -msgid "Reading last session logs ..." -msgstr "Lendo os logs da ultima sessão" - -#, python-brace-format -msgid "Read {lines_so_far} log lines so far ..." -msgstr "Leia {lines_so_far} linha de logs até agora ..." - -msgid "I'm bored ..." -msgstr "Eu estou entediado ..." - -msgid "Let's go for a walk!" -msgstr "Vamos ir numa caminhada!" - -msgid "This is the best day of my life!" -msgstr "Esse é o melhor dia da minha vida!" - -msgid "Shitty day :/" -msgstr "Dia ruim :/" - -msgid "I'm extremely bored ..." -msgstr "Eu estou extremamente entediado ..." - -msgid "I'm very sad ..." -msgstr "Eu estou muito triste ..." - -msgid "I'm sad" -msgstr "Eu estou triste" - -msgid "Leave me alone ..." -msgstr "Me deixe em paz ..." - -msgid "I'm mad at you!" -msgstr "Eu estou bravo com você!" - -msgid "I'm living the life!" -msgstr "Eu estou vivendo a vida!" - -msgid "I pwn therefore I am." -msgstr "Eu pwn então Eu sou." - -msgid "So many networks!!!" -msgstr "Tantas redes!!!" - -msgid "I'm having so much fun!" -msgstr "Eu estou tendo muita diversão" - -msgid "My crime is that of curiosity ..." -msgstr "Meu crime é de curiosidade ..." - -#, python-brace-format -msgid "Hello {name}! Nice to meet you." -msgstr "Olá {name}! É bom em conhecê-lo" - -#, python-brace-format -msgid "Yo {name}! Sup?" -msgstr "Ei {name}! Como vai?" - -#, python-brace-format -msgid "Hey {name} how are you doing?" -msgstr "Ei {name} como você está indo?" - -#, python-brace-format -msgid "Unit {name} is nearby!" -msgstr "" - -#, python-brace-format -msgid "Uhm ... goodbye {name}" -msgstr "" - -#, python-brace-format -msgid "{name} is gone ..." -msgstr "" - -#, python-brace-format -msgid "Whoops ... {name} is gone." -msgstr "" - -#, python-brace-format -msgid "{name} missed!" -msgstr "{name} errou!" - -msgid "Missed!" -msgstr "Errei!" - -msgid "Good friends are a blessing!" -msgstr "Bom amigos são uma bensão!" - -msgid "I love my friends!" -msgstr "Eu amo meus amigos!" - -msgid "Nobody wants to play with me ..." -msgstr "Ninguém quer brincar comigo ..." - -msgid "I feel so alone ..." -msgstr "Estou me sentindo sozinho" - -msgid "Where's everybody?!" -msgstr "Onde está todo mundo?!" - -#, python-brace-format -msgid "Napping for {secs}s ..." -msgstr "Tirando uma soneca por {secs}s ..." - -msgid "Zzzzz" -msgstr "Zzzzz" - -#, python-brace-format -msgid "ZzzZzzz ({secs}s)" -msgstr "ZzzZzzz ({secs}s)" - -msgid "Good night." -msgstr "Boa noite." - -msgid "Zzz" -msgstr "Zzz" - -#, python-brace-format -msgid "Waiting for {secs}s ..." -msgstr "Esperando por {secs}s ..." - -#, python-brace-format -msgid "Looking around ({secs}s)" -msgstr "Olhando por volta ({secs}s)" - -#, python-brace-format -msgid "Hey {what} let's be friends!" -msgstr "Ei {what} vamos ser amigos!" - -#, python-brace-format -msgid "Associating to {what}" -msgstr "Associando para {what}" - -#, python-brace-format -msgid "Yo {what}!" -msgstr "Ei {what}!" - -#, python-brace-format -msgid "Just decided that {mac} needs no WiFi!" -msgstr "Apenas decidindo que {mac} não precisa de WiFi!" - -#, python-brace-format -msgid "Deauthenticating {mac}" -msgstr "Desautenticando {mac}" - -#, python-brace-format -msgid "Kickbanning {mac}!" -msgstr "Banindo {mac}!" - -#, python-brace-format -msgid "Cool, we got {num} new handshake{plural}!" -msgstr "Legal, conseguimos {num} novos handshake{plural}!" - -#, python-brace-format -msgid "You have {count} new message{plural}!" -msgstr "Você tem {count} novas messagem{plural}!" - -msgid "Oops, something went wrong ... Rebooting ..." -msgstr "Oops, algo deu errado ... Reiniciando ..." - -#, python-brace-format -msgid "Uploading data to {to} ..." -msgstr "Enviando dados para {to} ..." - -#, python-brace-format -msgid "Downloading from {name} ..." -msgstr "Instalando para {name} ..." - -#, python-brace-format -msgid "Kicked {num} stations\n" -msgstr "Expulsei {num} estações\n" - -msgid "Made >999 new friends\n" -msgstr "Fiz >999 novos amigos\n" - -#, python-brace-format -msgid "Made {num} new friends\n" -msgstr "Fiz {num} novos amigos\n" - -#, python-brace-format -msgid "Got {num} handshakes\n" -msgstr "Peguei {num} handshakes\n" - -msgid "Met 1 peer" -msgstr "Encontrei 1 pessoa" - -#, python-brace-format -msgid "Met {num} peers" -msgstr "Encontrei {num} pessoas" - -#, 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 "" -"Estou navegando há {duration} e expulsei {deauthed} clientes! Também conheci " -"{associamos} novos amigos e comi {handshakes} handshakes! #pwnagotchi " -"#pwnlog #pwnlife #hacktheplanet #skynet" - -msgid "hours" -msgstr "horas" - -msgid "minutes" -msgstr "minutos" - -msgid "seconds" -msgstr "segundos" - -msgid "hour" -msgstr "hora" - -msgid "minute" -msgstr "minuto" - -msgid "second" +# pwnagotchi Brazilian Portuguese translation file. +# Copyright (C) 2024 +# This file is distributed under the same license as the pwnagotchi package. +# Fabiano F O , 2024. +# + +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-03-25 22:30+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Fabiano F O \n" +"Language-Team: LANGUAGE \n" +"Language: Brazilian Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "ZzzzZZzzzzZzzz" +msgstr "ZzzzZZzzzzZzzz" + +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Olá, sou Pwnagotchi! Iniciando ..." + +msgid "New day, new hunt, new pwns!" +msgstr "Novo dia, Nova caçada, Novos pwns!" + +msgid "Hack the Planet!" +msgstr "Hackeie o Planeta!" + +msgid "AI ready." +msgstr "IA pronta." + +msgid "The neural network is ready." +msgstr "A rede neural está pronta." + +msgid "Generating keys, do not turn off ..." +msgstr "Gerando chaves, não desligue ..." + +#, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Ei, o canal {channel} está livre! Seu AP vai agradecer." + +msgid "Reading last session logs ..." +msgstr "Lendo os logs da última sessão ..." + +#, python-brace-format +msgid "Read {lines_so_far} log lines so far ..." +msgstr "Li {lines_so_far} linhas de logs até agora ..." + +msgid "I'm bored ..." +msgstr "Estou entediado ..." + +msgid "Let's go for a walk!" +msgstr "Vamos dar um passeio!" + +msgid "This is the best day of my life!" +msgstr "Este é o melhor dia da minha vida!" + +msgid "Shitty day :/" +msgstr "Que dia ruim :/" + +msgid "I'm extremely bored ..." +msgstr "Estou extremamente entediado ..." + +msgid "I'm very sad ..." +msgstr "Estou muito triste ..." + +msgid "I'm sad" +msgstr "Estou triste" + +msgid "Leave me alone ..." +msgstr "Me deixe em paz ..." + +msgid "I'm mad at you!" +msgstr "Estou bravo com você!" + +msgid "I'm living the life!" +msgstr "Estou aproveitando a vida!" + +msgid "I pwn therefore I am." +msgstr "Eu pwn, logo existo." + +msgid "So many networks!!!" +msgstr "Uau! Quantas redes!!" + +msgid "I'm having so much fun!" +msgstr "Estou me divertindo muito!" + +msgid "My crime is that of curiosity ..." +msgstr "Meu crime é a curiosidade ..." + +#, python-brace-format +msgid "Hello {name}! Nice to meet you." +msgstr "Olá {name}! Prazer em conhecê-lo." + +#, python-brace-format +msgid "Yo {name}! Sup?" +msgstr "Ei {name}! Como vai?" + +#, python-brace-format +msgid "Hey {name} how are you doing?" +msgstr "Ei {name}, como você está?" + +#, python-brace-format +msgid "Unit {name} is nearby!" +msgstr "A unidade {name} está próxima!" + +#, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Hmm ... tchau {name}" + +#, python-brace-format +msgid "{name} is gone ..." +msgstr "{name} desapareceu ..." + +#, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Oops ... {name} desapareceu." + +#, python-brace-format +msgid "{name} missed!" +msgstr "Perdi {name}!" + +msgid "Missed!" +msgstr "Perdi!" + +msgid "Good friends are a blessing!" +msgstr "Bons amigos são uma bênção!" + +msgid "I love my friends!" +msgstr "Eu amo meus amigos!" + +msgid "Nobody wants to play with me ..." +msgstr "Ninguém quer brincar comigo ..." + +msgid "I feel so alone ..." +msgstr "Me sinto tão sozinho ..." + +msgid "Where's everybody?!" +msgstr "Onde está todo mundo?!" + +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Tirando uma soneca por {secs}s ..." + +msgid "Zzzzz" +msgstr "Zzzzz" + +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "ZzzZzzz ({secs}s)" + +msgid "Good night." +msgstr "Boa noite." + +msgid "Zzz" +msgstr "Zzz" + +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Aguardando {secs}s ..." + +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Olhando em volta ... ({secs}s)" + +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Ei {what}, vamos ser amigos!" + +#, python-brace-format +msgid "Associating to {what}" +msgstr "Associando a {what}" + +#, python-brace-format +msgid "Yo {what}!" +msgstr "Olá {what}!" + +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Acabei de decidir que {mac} não precisa de WiFi!" + +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Desautenticando {mac}" + +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Banindo {mac}!" + +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Legal, conseguimos {num} novo{plural} handshake{plural}!" + +#, python-brace-format +msgid "You have {count} new message{plural}!" +msgstr "Você tem {count} nova{plural} messagem{plural}!" + +msgid "Oops, something went wrong ... Rebooting ..." +msgstr "Oops, algo deu errado ... Reiniciando ..." + +#, python-brace-format +msgid "Uploading data to {to} ..." +msgstr "Enviando dados para {to} ..." + +#, python-brace-format +msgid "Downloading from {name} ..." +msgstr "Baixando de {name} ..." + +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Expulsei {num} estações\n" + +msgid "Made >999 new friends\n" +msgstr "Fiz >999 novos amigos\n" + +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Fiz {num} novos amigos\n" + +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Peguei {num} handshakes\n" + +msgid "Met 1 peer" +msgstr "Conheci 1 peer" + +#, python-brace-format +msgid "Met {num} peers" +msgstr "Conheci {num} peers" + +#, 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 "" +"Estou pwning há {duration} e expulsei {deauthed} clientes! Também conheci " +"{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "horas" + +msgid "minutes" +msgstr "minutos" + +msgid "seconds" +msgstr "segundos" + +msgid "hour" +msgstr "hora" + +msgid "minute" +msgstr "minuto" + +msgid "second" msgstr "segundo" \ No newline at end of file From 06a4491008b90eedf0f6fd991ceb2f8ceb7212c9 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 27 Mar 2024 07:17:35 +0100 Subject: [PATCH 02/39] Update 32bit to use latest pwngrid/bettercap Signed-off-by: jayofelony --- builder/raspberrypi32.yml | 43 +++++++++++++++++++++---------- pwnagotchi/ui/hw/waveshare3in7.py | 4 +-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index 17f45e8d..fc8ef338 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -374,21 +374,36 @@ when: golang.changed - name: download pwngrid - unarchive: - remote_src: yes - src: "{{ packages.opwngrid.url }}" - dest: /usr/local/bin/ - mode: 0755 + git: + repo: "{{ packages.pwngrid.source }}" + dest: /usr/local/src/pwngrid - - name: download and install bettercap - unarchive: - src: "{{ packages.bettercap.url }}" - dest: /usr/local/bin - remote_src: yes - exclude: - - README.md - - LICENSE.md - mode: 0755 + - name: install pwngrid + shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install" + args: + executable: /bin/bash + chdir: /usr/local/src/pwngrid + + - name: remove pwngrid folder + file: + state: absent + path: /usr/local/src/pwngrid + + - name: download bettercap + git: + repo: "{{ packages.bettercap.source }}" + dest: /usr/local/src/bettercap + + - name: install bettercap 2.32.4 + shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install" + args: + executable: /bin/bash + chdir: /usr/local/src/bettercap + + - name: remove bettercap folder + file: + state: absent + path: /usr/local/src/bettercap - name: clone bettercap caplets git: diff --git a/pwnagotchi/ui/hw/waveshare3in7.py b/pwnagotchi/ui/hw/waveshare3in7.py index 2b2cf155..f792845a 100644 --- a/pwnagotchi/ui/hw/waveshare3in7.py +++ b/pwnagotchi/ui/hw/waveshare3in7.py @@ -10,8 +10,8 @@ class Waveshare3in7(DisplayImpl): def layout(self): fonts.setup(10, 8, 10, 18, 25, 9) - self._layout['width'] = 280 - self._layout['height'] = 480 + self._layout['width'] = 480 + self._layout['height'] = 280 self._layout['face'] = (0, 43) self._layout['name'] = (0, 14) self._layout['channel'] = (0, 0) From 84d45a0d45c5b1f4da76d2aee7a0c6c373563058 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 27 Mar 2024 07:20:45 +0100 Subject: [PATCH 03/39] Version 2.9.0 Signed-off-by: jayofelony --- pwnagotchi/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py index bf560199..387cfacc 100644 --- a/pwnagotchi/_version.py +++ b/pwnagotchi/_version.py @@ -1 +1 @@ -__version__ = '2.8.9' +__version__ = '2.9.0' From 33ff5a0bf85ad277005ca6feaac7f16968ac5a31 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 27 Mar 2024 07:37:59 +0100 Subject: [PATCH 04/39] Fix ui.invert Signed-off-by: jayofelony --- pwnagotchi/ui/view.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index 3d822190..52b92f05 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -32,13 +32,10 @@ class View(object): logging.debug("INVERT BLACK/WHITES:" + str(config['ui']['invert'])) self.invert = 1 BLACK = 0x00 - WHITE - 0xFF + WHITE = 0xFF self._black = 0x00 self._white = 0xFF - - - # setup faces from the configuration in case the user customized them faces.load_from_config(config['ui']['faces']) From 3657859a73fa79dd292baf051294c054a616b589 Mon Sep 17 00:00:00 2001 From: alan67160 <20385640+alan67160@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:45:21 +0800 Subject: [PATCH 05/39] Update tw voice.po Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com> --- pwnagotchi/locale/tw/LC_MESSAGES/voice.po | 143 +++++++++++----------- 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/pwnagotchi/locale/tw/LC_MESSAGES/voice.po b/pwnagotchi/locale/tw/LC_MESSAGES/voice.po index 9a84594f..a45d4bff 100644 --- a/pwnagotchi/locale/tw/LC_MESSAGES/voice.po +++ b/pwnagotchi/locale/tw/LC_MESSAGES/voice.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-11-16 21:10+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2024-03-27 18:40+0800\n" +"Last-Translator: AlanLeung \n" "Language-Team: LANGUAGE \n" "Language: Twi\n" "MIME-Version: 1.0\n" @@ -18,218 +18,218 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" msgid "ZzzzZZzzzzZzzz" -msgstr "" +msgstr "ZzzzZZzzzzZzzz" msgid "Hi, I'm Pwnagotchi! Starting ..." -msgstr "" +msgstr "HI!我是Pwnagotchi!\n程式啟動..." msgid "New day, new hunt, new pwns!" -msgstr "" +msgstr "新的一天!\n新的狩獵!新的入侵!" msgid "Hack the Planet!" -msgstr "" +msgstr "我要駭入\n地球的所有人!" msgid "AI ready." -msgstr "" +msgstr "人工智慧已啟動。" msgid "The neural network is ready." -msgstr "" +msgstr "神經網路已啟動。" msgid "Generating keys, do not turn off ..." -msgstr "" +msgstr "產生金鑰中,\n請勿關閉..." #, python-brace-format msgid "Hey, channel {channel} is free! Your AP will say thanks." -msgstr "" +msgstr "嘿,{channel}很順暢!\n你的WIFI會感謝你的。" msgid "Reading last session logs ..." -msgstr "" +msgstr "正在閱讀最後的會話紀錄..." #, python-brace-format msgid "Read {lines_so_far} log lines so far ..." -msgstr "" +msgstr "目前已經閱讀了 {lines_so_far} 行的紀錄..." msgid "I'm bored ..." -msgstr "" +msgstr "我好無聊..." msgid "Let's go for a walk!" -msgstr "" +msgstr "我們! 散步! 散步散步散步散步" msgid "This is the best day of my life!" -msgstr "" +msgstr "這是我生命中最棒的一天!" msgid "Shitty day :/" -msgstr "" +msgstr "糟糕的一天 :/" msgid "I'm extremely bored ..." -msgstr "" +msgstr "我超無聊的...炒雞 炒雞的那種" msgid "I'm very sad ..." -msgstr "" +msgstr "我好難過..." msgid "I'm sad" -msgstr "" +msgstr "嗚嗚嗚...." msgid "Leave me alone ..." -msgstr "" +msgstr "尼奏凱啦臭臭" msgid "I'm mad at you!" -msgstr "" +msgstr "喔氣氣氣氣氣ˋ^ˊ" msgid "I'm living the life!" -msgstr "" +msgstr "真是充實的一生!" msgid "I pwn therefore I am." -msgstr "" +msgstr "我駭故我在." msgid "So many networks!!!" -msgstr "" +msgstr "好多網路啊!!!吃! 吃他! 吃光光!!!" msgid "I'm having so much fun!" -msgstr "" +msgstr "我玩的超級開心!" msgid "My crime is that of curiosity ..." -msgstr "" +msgstr "我的缺點就是\n太好奇了..." #, python-brace-format msgid "Hello {name}! Nice to meet you." -msgstr "" +msgstr "尼豪{name}!\n很高興認識你!!!!" #, python-brace-format msgid "Yo {name}! Sup?" -msgstr "" +msgstr "嗨 {name}! 你來攻打我的村莊?" #, python-brace-format msgid "Hey {name} how are you doing?" -msgstr "" +msgstr "嗨 {name} 你最近過得如何˙ˇ˙?" #, python-brace-format msgid "Unit {name} is nearby!" -msgstr "" +msgstr "{name}\n就在附近!" #, python-brace-format msgid "Uhm ... goodbye {name}" -msgstr "" +msgstr "哦嗚 ... \n拜拜{name}" #, python-brace-format msgid "{name} is gone ..." -msgstr "" +msgstr "{name}\n不見了 ..." #, python-brace-format msgid "Whoops ... {name} is gone." -msgstr "" +msgstr "哦歐...\n{name}\n不見了。" #, python-brace-format msgid "{name} missed!" -msgstr "" +msgstr "我剛剛錯過了{name}!" msgid "Missed!" -msgstr "" +msgstr "又錯過了!" msgid "Good friends are a blessing!" -msgstr "" +msgstr "有個好朋友\n真幸福!" msgid "I love my friends!" -msgstr "" +msgstr "我喜歡\n我的朋友!" msgid "Nobody wants to play with me ..." -msgstr "" +msgstr "沒人想跟我玩..." msgid "I feel so alone ..." -msgstr "" +msgstr "我覺得好孤單..." msgid "Where's everybody?!" -msgstr "" +msgstr "大家都去哪裡了?!" #, python-brace-format msgid "Napping for {secs}s ..." -msgstr "" +msgstr "我想瞇{secs}秒一下..." msgid "Zzzzz" -msgstr "" +msgstr "Zzzzz" #, python-brace-format msgid "ZzzZzzz ({secs}s)" -msgstr "" +msgstr "ZzzZzzz({secs}秒)" msgid "Good night." -msgstr "" +msgstr "晚安!" msgid "Zzz" -msgstr "" +msgstr "Zzz" #, python-brace-format msgid "Waiting for {secs}s ..." -msgstr "" +msgstr "等我{secs}秒..." #, python-brace-format msgid "Looking around ({secs}s)" -msgstr "" +msgstr "環顧四周({secs}秒)" #, python-brace-format msgid "Hey {what} let's be friends!" -msgstr "" +msgstr "嗨\n{what}\n讓我們來當朋友吧!" #, python-brace-format msgid "Associating to {what}" -msgstr "" +msgstr "正在連接\n{what}" #, python-brace-format msgid "Yo {what}!" -msgstr "" +msgstr "喲,\n{what}!" #, python-brace-format msgid "Just decided that {mac} needs no WiFi!" -msgstr "" +msgstr "我要讓\n{mac}\n斷線!\n他不需要上網!" #, python-brace-format msgid "Deauthenticating {mac}" -msgstr "" +msgstr "解除\n{mac}\n的授權中" #, python-brace-format msgid "Kickbanning {mac}!" -msgstr "" +msgstr "把\n{mac}\n踢出中!" #, python-brace-format msgid "Cool, we got {num} new handshake{plural}!" -msgstr "" +msgstr "酷耶,我們抓到{num}個\n新的握手包{plural}!" #, python-brace-format msgid "You have {count} new message{plural}!" -msgstr "" +msgstr "你有{count}個新訊息{plural}!" msgid "Oops, something went wrong ... Rebooting ..." -msgstr "" +msgstr "哦歐,有些地方出錯了...\n重新啟動中..." #, python-brace-format msgid "Uploading data to {to} ..." -msgstr "" +msgstr "正在上傳資料到 {to} ..." #, python-brace-format msgid "Downloading from {name} ..." -msgstr "" +msgstr "正在從 {name} 下載資料..." #, python-brace-format msgid "Kicked {num} stations\n" -msgstr "" +msgstr "踢了 {num} 個設備\n" msgid "Made >999 new friends\n" -msgstr "" +msgstr "交了 >999 個新朋友\n" #, python-brace-format msgid "Made {num} new friends\n" -msgstr "" +msgstr "交了 {num} 個新朋友\n" #, python-brace-format msgid "Got {num} handshakes\n" -msgstr "" +msgstr "捕獲了 {num} 個握手包\n" msgid "Met 1 peer" -msgstr "" +msgstr "遇到了 1 個同好" #, python-brace-format msgid "Met {num} peers" -msgstr "" +msgstr "遇到了 {num} 個同好" #, python-brace-format msgid "" @@ -237,21 +237,24 @@ msgid "" "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" +"我花了{duration}的時間\n駭入和踢了{deauthed}好多設備." +"我還交了好多{associated}新朋友,\n而且抓到了{handshakes}握手包!" +"#pwnagotchi#入侵日志 #駭客人生 #入侵整個星球 #天網 #我好棒˙ˇ˙" msgid "hours" -msgstr "" +msgstr "時" msgid "minutes" -msgstr "" +msgstr "分" msgid "seconds" -msgstr "" +msgstr "秒" msgid "hour" -msgstr "" +msgstr "時" msgid "minute" -msgstr "" +msgstr "分" msgid "second" -msgstr "" +msgstr "秒" From dc1b3c7635317288d52f2ca0979d4103b4c65643 Mon Sep 17 00:00:00 2001 From: alan67160 <20385640+alan67160@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:45:59 +0800 Subject: [PATCH 06/39] Delete tw voice.mo Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com> --- pwnagotchi/locale/tw/LC_MESSAGES/voice.mo | Bin 340 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pwnagotchi/locale/tw/LC_MESSAGES/voice.mo diff --git a/pwnagotchi/locale/tw/LC_MESSAGES/voice.mo b/pwnagotchi/locale/tw/LC_MESSAGES/voice.mo deleted file mode 100644 index 934069f1b0df4be8caaaca4f613372d0ed1298a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmYL@yH3O~5JeY3m68%sxS)espbKU}Yc}2`!cL+*R)WqXCKv@fa=bh~gx}*^a2j%@ zqbcT&=KLNW{LFmzJjb3B&%Wo(GbZ#L`Q??LW9L7aHE*(Z5I3-uc2GuRl#$f~*-*5l zc@d{ckjvg!2YhH%19!W2fYM+TWGUqGLyb2O2`4dnq$CHPLPXGgig|qclqNJ_VsKDe zp@&X5V=-D+jG=^ZiWZcUm@P>Z<+LbneO0$R(Ml+#c*ls5WK)eM3&xh6nj70r9gNCP z74VqT$^3GD5v+`MQu~kJy;pMb%boX~Q2H9xufh(}-Bjfo!l^f!y+{jG*QQar#VCAM HE|~oR;zL~S From e0a068e51d6c8c5bcf6ec5c8bfa6b6f7a217754e Mon Sep 17 00:00:00 2001 From: alan67160 <20385640+alan67160@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:46:42 +0800 Subject: [PATCH 07/39] Upload tw voice.mo Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com> --- pwnagotchi/locale/tw/LC_MESSAGES/voice.mo | Bin 0 -> 5482 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pwnagotchi/locale/tw/LC_MESSAGES/voice.mo diff --git a/pwnagotchi/locale/tw/LC_MESSAGES/voice.mo b/pwnagotchi/locale/tw/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..02c97b73ec3dee28759c22ed7f7aba5cc1636cf6 GIT binary patch literal 5482 zcmZXWd2Ae49mijxK$$>+w%iT8sS9a{*KrQ0;~uGVo7$5;9tRSgCBq^!3RI%k6#BCp}rgBU_1CAI0Zfc-U4Zzcfiks z4)|5@gMcgUW9%W+^T02FMIgG^E|B)E0Ovss{4V$~l%jRFf~3duK|K!AI!)l$z`me= z2BiId4JzQfAnoIUw9mgl6{JoY_XtRKCQzBq2g!affwazH@ZozH>jlYfvrvlUdK=sbz6*XGd;o(v zm>;klBz+8!_UQ!4Ekl%#dHfYe_PQhW@9WS6TT`Te&be(X>9 zBfI|{Bzr!DPU0Gn#%}@14+lUR9|ae|m%%mQk6|>5i%yWnp94w%>maTBcF_J0kn~j0 zNqRjB()i6FweJUMpO?T#z+ZrLelCEt&TWwNNQ3La|AM4vA&g0S3J^`K3tR`j0+PMo z0ckxisIP#qB=4j6`xdwfqV zURK)_yp!BepM4L7bRxY&D1|6HP)L4y$ZjeMM{^(q$tG*@PZCGvr5lo)cp=|X9N?JBr#Rrf;QHXb zAmCb%VvF(^J>Z6+7$hMkhET7j4USrz4!AQm%xgqL#R5K!0RI3#Yb+KeZi#4ijo6wSWR2a4% z_7`c0YvD$=&8#}eq^x`%F}Z<#>}0~=W_7hc z$TTCEsSE7LwS?druZjuF!h$N>Nu7pX6ScA0l7vgrSqj^wg=;zF;uSH?5Vp#8iC7Hk zNhwsmTMr9TH!g(DQ)aRN{i&>sQL|p|h<1pE4LAF}(lk6K>{S-85?SGB=~O-sV|PQu zcth~g$aM=tgi!elW-`G`DtNsfi*ZX!K`zaxwXmn2&r4Uuc}2aU!O-ETuJXOMmXOXM zOO^6!fi*3YYcbOh(lDhwW*!tgp2`VO%IoS4(l#NgO_-{bYjI4*%2lXF{As9(m+gdz zi&*Mo?NRL@`3c*^li?_@P8zD59n)nynK7nU3%@b0MYtx7=GQGPA_pH7i4?TU?gkO7 zgfK`l83Sg5H$)IKwr(1Y9C5^J^>8hOYl!#}6lvt)7~E}JDvW~ZT8spOe;TwPMg_)D z7%qhcR?%$18*-j+%*80y$;0k}W#xO!tnmqLcwQ7S0^RClgz!A8HibxGKTKLSkBG1y zfpG8?_NR!(#sZOOn0&v!Ls!|ekiH5oC*|Y-zlju*$HlUxstCn0p^?8xp{x(fWDM1q z9PUD3*K4s_m6e%hEv=>{%p??hticjttI=A`%C(5#PjA|^X}R)>-<&&}fl<&7lda=* zLL}s?KZ2?jE7vVcL{wIu;^Bl2kr1O&MYEcRlL_6lbUP)(Ww%yWx8yfp5WgMfk7$T@ znGTYM?Z3g!mdbXURc0gwb>KugU9c=_x*a9$DW0D*>u}sH6JCwd>h*9puTPkGMK|9g zs!Ve!`1c?|@rIag2lvP#6aAt;|^o5?Ogeyoh*U7CpknnD8$!CW|h{+ZYp zjZ5KckdvxX2u7J=*giw2%qf!|rW-;_RHan5uP&PvBbu$rjBA^ITHLScQg@1p!1q#t z{dBI8as-_)GVo@V?T?x;rQA2SM-9TOfW45*a(k0?n`K>QE)}my91jFzLl_}u`-dqG zgK0I(GWvl-hZqWehn58)RS(dg?4SV{7DZ;0e-?}DM$#4mEQXLVjYt5CeN;%PR?rj= zLb4)Z{#1nRP-!IeJVF&NEanv@Tc0i2xt%}1eb3&~=XNW5M4g$iL*-VD9tmwp)>xrR zvzRLt&xQ7ggF4L#Z9_gN=IaaBZwwV~2(5pduPZ9vSh%LJsIX8eLwtlP6PjVgG}}xR z^Aeo=GLb~+JgG&Xz%%hMzC#6d3G-i zc4yjdcum*y-HslosmJZ=bvkBc4se>f6}NvjJ$TqXao+9hc8<2?KI7ixXl7tck(o@P zA;&x1*Si+yrh_e<+vl>;yg1kG-RktNwY&WTbg0v(FQiY8WZHW&J+qjQuXwL@JKc9O zXNEKVoixB5?!?~C_<}p!?VRXV(!(RpTXX4&6Do5D2A!Es@K|5^*ww}PBiMv48yLSN zq{5(zH_@D#oOasA6=!%heX^BA>}4XT2f)*Rd=|_yVH|tKJMH;<4m+HF7(|UxZ8erU^9&iOsRM?y}lV2Zy!nb zUH9d8PEKO6vv=~BKJ~QWt4G|y3#x+6Alm-Y9i{GYt9y9Fd;Jx^iM+L|RK;@c*~=A6 zpCwgEPjx%DPWUdB)*@x+NviP$XL`)(p9xx>{$Y3eyn+=-d1*=*uA>Kbar@dx&fzH- z8ysIqA3pCjcV(Bm-saaa4^8QoQ<T?*(Ltu|aQY+G!amAcb2FFV2r)h~KgNdVu)$ErTd*I=VP_ z+K+!)ZrL4SDYVpO7lb?n*W&Fr-819PoijX-q?v&n^H7&(`}*FXz&tyG07To^#q{;7 zJkPhdJ9^3wpdeZiI>Bjj`){Og3?ejc_AkyI%OLJ1niuD~FcIz0dX{UW2=SO9} z{<)LjYpzg~JL4yu_A5@`gx5ZepY(Q9kILP?QFnSgOTV`KpQTUDX3kGKLqkr_RB*FM zPo7$h%tD6rZx^In)_#<8WKZrq=DIS??MNy#@BLdnbXJ{{N8t;WYhRib^f)IvGDj~X z3NT3qE!>{IHJ`b8&Y8V}_)?s)OXSV*b_@t2#cjQoKG*Jl2_Y*Y51B{y$s~q4JfH?C zE!}-Fee6xu&u_jbvCq|0a3I$4ZjAWhP1Bv;33vKrzRVp%$R=+8Td+LD^S4$q?Z>c; ze<0xxnvx!xaXOD7^QN!&X8NyqGfkxY$L=QH`J<%O8%>#`bj-53Sq?|Gac)yLvVwQ< zN^Vg4+DQ6ZA3A(>=!)V;HNwNYaoOqXdjD3l|8q{ZsvLiaBT1*N6FG5+AESRzU z^N?v8fN@Fn(<4sL0*B)saj Date: Fri, 29 Mar 2024 08:57:45 +0100 Subject: [PATCH 08/39] Fix Waveshare V2 Position The current location "178, 84" does not correctly display the temperature symbol (Cellsius, Kelvin, etc.). I fix the code whit the correct position. Signed-off-by: Andrea Draghetti --- pwnagotchi/plugins/default/memtemp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/plugins/default/memtemp.py b/pwnagotchi/plugins/default/memtemp.py index 6298eca9..985ead20 100644 --- a/pwnagotchi/plugins/default/memtemp.py +++ b/pwnagotchi/plugins/default/memtemp.py @@ -130,7 +130,7 @@ class MemTemp(plugins.Plugin): except Exception: # Set default position based on screen type if ui.is_waveshare_v2(): - h_pos = (178, 84) + h_pos = (175, 84) v_pos = (197, 74) elif ui.is_waveshare_v1(): h_pos = (170, 80) From f597bd6d29896e90f717686a1822348e4b0a7db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Allard?= Date: Fri, 29 Mar 2024 15:08:07 +0100 Subject: [PATCH 09/39] Fix range of lines about the displays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benoît Allard --- bin/pwnagotchi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pwnagotchi b/bin/pwnagotchi index 62e83264..e9e36254 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -237,7 +237,7 @@ def pwnagotchi_cli(): f.write("ui.display.enabled = true\n") pwn_display_type = input("What display do you use?\n\n" "Be sure to check for the correct display type @ \n" - "https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L431\n\n" + "https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L501\n\n" "Display type: ") if pwn_display_type != "": f.write(f"ui.display.type = \"{pwn_display_type}\"\n") From a8ba88c9cc39e9e6f4eef4b0ffe0ff19b651ff51 Mon Sep 17 00:00:00 2001 From: Morten Winther Olsson <18525061+olwimo@users.noreply.github.com> Date: Sat, 30 Mar 2024 08:04:55 +0100 Subject: [PATCH 10/39] Fix typo in ansible script Signed-off-by: Morten Winther Olsson <18525061+olwimo@users.noreply.github.com> --- builder/raspberrypi32.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index fc8ef338..16e18440 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -62,7 +62,7 @@ source: "https://github.com/jayofelony/bettercap.git" url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip" ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" - opwngrid: + pwngrid: source: "https://github.com/jayofelony/pwngrid.git" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" torch: @@ -574,4 +574,4 @@ handlers: - name: reload systemd services systemd: - daemon_reload: yes \ No newline at end of file + daemon_reload: yes From b03f6f747be03a1b66ea53b4e7aaa40cf401fb28 Mon Sep 17 00:00:00 2001 From: RasTacsko Date: Sun, 31 Mar 2024 23:55:15 +0200 Subject: [PATCH 11/39] Generic I2C Oled support , waveshare oled/lcd vertical layout work in progress for the triple screen project --- pwnagotchi/ui/display.py | 6 + pwnagotchi/ui/hw/__init__.py | 8 + pwnagotchi/ui/hw/i2coled.py | 58 +++ .../hw/libs/waveshare/oled/oledlcd/SSD1306.py | 294 ++++++++++++++ .../libs/waveshare/oled/oledlcd/ST7789vert.py | 360 ++++++++++++++++++ .../hw/libs/waveshare/oled/oledlcd/config.py | 37 ++ .../ui/hw/libs/waveshare/oled/oledlcd/epd.py | 23 ++ pwnagotchi/ui/hw/waveshareoledlcdvert.py | 59 +++ pwnagotchi/utils.py | 6 + 9 files changed, 851 insertions(+) create mode 100644 pwnagotchi/ui/hw/i2coled.py create mode 100644 pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py create mode 100644 pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py create mode 100644 pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py create mode 100644 pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/epd.py create mode 100644 pwnagotchi/ui/hw/waveshareoledlcdvert.py diff --git a/pwnagotchi/ui/display.py b/pwnagotchi/ui/display.py index 5e5645b0..28364f30 100644 --- a/pwnagotchi/ui/display.py +++ b/pwnagotchi/ui/display.py @@ -264,6 +264,12 @@ class Display(View): def is_waveshareoledlcd(self): return self._implementation.name == 'waveshareoledlcd' + + def is_waveshareoledlcdvert(self): + return self._implementation.name == 'waveshareoledlcdvert' + + def is_i2coled(self): + return self._implementation.name == 'i2coled' def is_waveshare35lcd(self): return self._implementation.name == 'waveshare35lcd' diff --git a/pwnagotchi/ui/hw/__init__.py b/pwnagotchi/ui/hw/__init__.py index 827c849c..f966af6e 100644 --- a/pwnagotchi/ui/hw/__init__.py +++ b/pwnagotchi/ui/hw/__init__.py @@ -104,6 +104,14 @@ def display_for(config): from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd return Waveshareoledlcd(config) + elif config['ui']['display']['type'] == 'waveshareoledlcdvert': + from pwnagotchi.ui.hw.waveshareoledlcdvert import Waveshareoledlcdvert + return Waveshareoledlcdvert(config) + + elif config['ui']['display']['type'] == 'i2coled': + from pwnagotchi.ui.hw.i2coled import I2COled + return I2COled(config) + elif config['ui']['display']['type'] == 'waveshare1in02': from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02 return Waveshare1in02(config) diff --git a/pwnagotchi/ui/hw/i2coled.py b/pwnagotchi/ui/hw/i2coled.py new file mode 100644 index 00000000..1392dc04 --- /dev/null +++ b/pwnagotchi/ui/hw/i2coled.py @@ -0,0 +1,58 @@ +# workinprogress based on the displayhatmini driver +# LCD support OK +# OLED support ongoing +# board GPIO: +# Key1: GPIO4 / pin7 +# Key2: GPIO17 / pin11 +# Key3: GPIO23 / pin16 +# Key4: GPIO24 / pin18 +# OLED SDA: GPIO2 / pin3 +# OLED SCL: GPIO3 / pin5 +# OLED info: +# driver: SSD1315 (I2C) +# resolution: 128x64 +# I2C address: 0x3C 0x3D +# HW datasheet: https://www.waveshare.com/wiki/OLED/LCD_HAT_(A) +import logging + +import pwnagotchi.ui.fonts as fonts +from pwnagotchi.ui.hw.base import DisplayImpl + +class I2COled(DisplayImpl): + def __init__(self, config): + super(I2COled, self).__init__(config, 'i2coled') + + def layout(self): + fonts.setup(8, 8, 8, 10, 10, 8) + self._layout['width'] = 128 + self._layout['height'] = 64 + self._layout['face'] = (0, 30) + self._layout['name'] = (0, 10) + self._layout['channel'] = (72, 10) + self._layout['aps'] = (0, 0) + self._layout['uptime'] = (87, 0) + self._layout['line1'] = [0, 9, 128, 9] + self._layout['line2'] = [0, 54, 128, 54] + self._layout['friend_face'] = (0, 41) + self._layout['friend_name'] = (40, 43) + self._layout['shakes'] = (0, 55) + self._layout['mode'] = (107, 10) + self._layout['status'] = { + 'pos': (37, 19), + 'font': fonts.status_font(fonts.Small), + 'max': 18 + } + return self._layout + + def initialize(self): + logging.info("initializing I2C Oled Display on address 0x3C") + from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.epd import EPD + self._display = EPD() + self._display.Init() + self._display.Clear() + + def render(self, canvas): + self._display.display(canvas) + + def clear(self): + self._display.clear() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py new file mode 100644 index 00000000..4ca97dad --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py @@ -0,0 +1,294 @@ +# Copyright (c) 2014 Adafruit Industries +# Author: Tony DiCola +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 FOR 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 __future__ import division +import logging +import time + +import RPi.GPIO as GPIO +import spidev +from smbus import SMBus +i2cbus = SMBus(1) + + +# Constants +SSD1306_I2C_ADDRESS = 0x3C # 011110+SA0+RW - 0x3C or 0x3D +SSD1306_SETCONTRAST = 0x81 +SSD1306_DISPLAYALLON_RESUME = 0xA4 +SSD1306_DISPLAYALLON = 0xA5 +SSD1306_NORMALDISPLAY = 0xA6 +SSD1306_INVERTDISPLAY = 0xA7 +SSD1306_DISPLAYOFF = 0xAE +SSD1306_DISPLAYON = 0xAF +SSD1306_SETDISPLAYOFFSET = 0xD3 +SSD1306_SETCOMPINS = 0xDA +SSD1306_SETVCOMDETECT = 0xDB +SSD1306_SETDISPLAYCLOCKDIV = 0xD5 +SSD1306_SETPRECHARGE = 0xD9 +SSD1306_SETMULTIPLEX = 0xA8 +SSD1306_SETLOWCOLUMN = 0x00 +SSD1306_SETHIGHCOLUMN = 0x10 +SSD1306_SETSTARTLINE = 0x40 +SSD1306_MEMORYMODE = 0x20 +SSD1306_COLUMNADDR = 0x21 +SSD1306_PAGEADDR = 0x22 +SSD1306_COMSCANINC = 0xC0 +SSD1306_COMSCANDEC = 0xC8 +SSD1306_SEGREMAP = 0xA0 +SSD1306_CHARGEPUMP = 0x8D +SSD1306_EXTERNALVCC = 0x1 +SSD1306_SWITCHCAPVCC = 0x2 + +# Scrolling constants +SSD1306_ACTIVATE_SCROLL = 0x2F +SSD1306_DEACTIVATE_SCROLL = 0x2E +SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 +SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 +SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 +SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 +SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A + + +class SSD1306Base(object): + """Base class for SSD1306-based OLED displays. Implementors should subclass + and provide an implementation for the _initialize function. + """ + + def __init__(self, width, height, address=SSD1306_I2C_ADDRESS, bus=None): + self._log = logging.getLogger('Adafruit_SSD1306.SSD1306Base') + # self._rst = None + self.cmd_mode = 0x00 + self.data_mode = 0x40 + self.bus = i2cbus + self.addr = address + self.width = width + self.height = height + self._pages = height//8 + self._buffer = [0]*(width*self._pages) + + def _initialize(self): + raise NotImplementedError + + def command(self, *cmd): + """Send command byte to display.""" + # I2C write. + assert(len(cmd) <= 31) + self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + + def data(self, data): + """Send byte of data to display.""" + # I2C write. + for i in range(0, len(data), 31): + self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + + def begin(self, vccstate=SSD1306_SWITCHCAPVCC): + """Initialize display.""" + # Save vcc state. + self._vccstate = vccstate + # Reset and initialize display. + self._initialize() + # Turn on the display. + self.command(SSD1306_DISPLAYON) + + def ShowImage(self): + """ + The image on the "canvas" is flushed through to the hardware display. + Takes the 1-bit image and dumps it to the SSD1306 OLED display. + """ + self.command(SSD1306_COLUMNADDR) + self.command(0) # Column start address. (0 = reset) + self.command(self.width-1) # Column end address. + self.command(SSD1306_PAGEADDR) + self.command(0) # Page start address. (0 = reset) + self.command(self._pages-1) # Page end address. + + for i in range(0, len(self._buffer), 16): + self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) + + def getbuffer(self, image): + """Set buffer to value of Python Imaging Library image. The image should + be in 1 bit mode and a size equal to the display size. + """ + if image.mode != '1': + raise ValueError('Image must be in mode 1.') + imwidth, imheight = image.size + if imwidth != self.width or imheight != self.height: + raise ValueError('Image must be same dimensions as display ({0}x{1}).' \ + .format(self.width, self.height)) + # Grab all the pixels from the image, faster than getpixel. + pix = image.load() + # Iterate through the memory pages + index = 0 + for page in range(self._pages): + # Iterate through all x axis columns. + for x in range(self.width): + # Set the bits for the column of pixels at the current position. + bits = 0 + # Don't use range here as it's a bit slow + for bit in [0, 1, 2, 3, 4, 5, 6, 7]: + bits = bits << 1 + bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 + # Update buffer byte and increment to next byte. + self._buffer[index] = bits + index += 1 + + def clear(self): + """Clear contents of image buffer.""" + self._buffer = [0]*(self.width*self._pages) + + def set_contrast(self, contrast): + """Sets the contrast of the display. Contrast should be a value between + 0 and 255.""" + if contrast < 0 or contrast > 255: + raise ValueError('Contrast must be a value from 0 to 255 (inclusive).') + self.command(SSD1306_SETCONTRAST) + self.command(contrast) + + def dim(self, dim): + """Adjusts contrast to dim the display if dim is True, otherwise sets the + contrast to normal brightness if dim is False. + """ + # Assume dim display. + contrast = 0 + # Adjust contrast based on VCC if not dimming. + if not dim: + if self._vccstate == SSD1306_EXTERNALVCC: + contrast = 0x9F + else: + contrast = 0xCF + self.set_contrast(contrast) + +class SSD1306_128_64(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_128_64, self).__init__(128, 64, address, bus) + + def _initialize(self): + # 128x64 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x80) # the suggested ratio 0x80 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x3F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x12) + self.command(SSD1306_SETCONTRAST) # 0x81 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x9F) + else: + self.command(0xCF) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 + +class SSD1306_128_32(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_128_64, self).__init__(128, 64, address, bus) + + def _initialize(self): + # 128x32 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x80) # the suggested ratio 0x80 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x1F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x02) + self.command(SSD1306_SETCONTRAST) # 0x81 + self.command(0x8F) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 + + +class SSD1306_96_16(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_96_16, self).__init__(96, 16, address, bus) + + def _initialize(self): + # 128x32 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x60) # the suggested ratio 0x60 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x0F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x02) + self.command(SSD1306_SETCONTRAST) # 0x81 + self.command(0x8F) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py new file mode 100644 index 00000000..f8894b98 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py @@ -0,0 +1,360 @@ +# Copyright (c) 2014 Adafruit Industries +# Author: Tony DiCola +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 FOR 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 numbers +import time +import numpy as np + +import spidev +import RPi.GPIO as GPIO + + +__version__ = '0.0.4' + +BG_SPI_CS_BACK = 0 +BG_SPI_CS_FRONT = 1 + +SPI_CLOCK_HZ = 16000000 + +ST7789_NOP = 0x00 +ST7789_SWRESET = 0x01 +ST7789_RDDID = 0x04 +ST7789_RDDST = 0x09 + +ST7789_SLPIN = 0x10 +ST7789_SLPOUT = 0x11 +ST7789_PTLON = 0x12 +ST7789_NORON = 0x13 + +ST7789_INVOFF = 0x20 +ST7789_INVON = 0x21 +ST7789_DISPOFF = 0x28 +ST7789_DISPON = 0x29 + +ST7789_CASET = 0x2A +ST7789_RASET = 0x2B +ST7789_RAMWR = 0x2C +ST7789_RAMRD = 0x2E + +ST7789_PTLAR = 0x30 +ST7789_MADCTL = 0x36 +ST7789_COLMOD = 0x3A + +ST7789_FRMCTR1 = 0xB1 +ST7789_FRMCTR2 = 0xB2 +ST7789_FRMCTR3 = 0xB3 +ST7789_INVCTR = 0xB4 +ST7789_DISSET5 = 0xB6 + +ST7789_GCTRL = 0xB7 +ST7789_GTADJ = 0xB8 +ST7789_VCOMS = 0xBB + +ST7789_LCMCTRL = 0xC0 +ST7789_IDSET = 0xC1 +ST7789_VDVVRHEN = 0xC2 +ST7789_VRHS = 0xC3 +ST7789_VDVS = 0xC4 +ST7789_VMCTR1 = 0xC5 +ST7789_FRCTRL2 = 0xC6 +ST7789_CABCCTRL = 0xC7 + +ST7789_RDID1 = 0xDA +ST7789_RDID2 = 0xDB +ST7789_RDID3 = 0xDC +ST7789_RDID4 = 0xDD + +ST7789_GMCTRP1 = 0xE0 +ST7789_GMCTRN1 = 0xE1 + +ST7789_PWCTR6 = 0xFC + + +class ST7789(object): + """Representation of an ST7789 TFT LCD.""" + + def __init__(self, port, cs, dc, backlight, rst=None, width=320, + height=240, rotation=270, invert=True, spi_speed_hz=60 * 1000 * 1000, + offset_left=0, + offset_top=0): + """Create an instance of the display using SPI communication. + + Must provide the GPIO pin number for the D/C pin and the SPI driver. + + Can optionally provide the GPIO pin number for the reset pin as the rst parameter. + + :param port: SPI port number + :param cs: SPI chip-select number (0 or 1 for BCM + :param backlight: Pin for controlling backlight + :param rst: Reset pin for ST7789 + :param width: Width of display connected to ST7789 + :param height: Height of display connected to ST7789 + :param rotation: Rotation of display connected to ST7789 + :param invert: Invert display + :param spi_speed_hz: SPI speed (in Hz) + + """ + if rotation not in [0, 90, 180, 270]: + raise ValueError("Invalid rotation {}".format(rotation)) + +# if width != height and rotation in [90, 270]: +# raise ValueError("Invalid rotation {} for {}x{} resolution".format(rotation, width, height)) + + GPIO.setwarnings(False) + GPIO.setmode(GPIO.BCM) + + self._spi = spidev.SpiDev(port, cs) + self._spi.mode = 0 + self._spi.lsbfirst = False + self._spi.max_speed_hz = spi_speed_hz + + self._dc = dc + self._rst = rst + self._width = width + self._height = height + self._rotation = rotation + self._invert = invert + + self._offset_left = offset_left + self._offset_top = offset_top + + # Set DC as output. + GPIO.setup(dc, GPIO.OUT) + + # Setup backlight as output (if provided). + self._backlight = backlight + if backlight is not None: + GPIO.setup(backlight, GPIO.OUT) + GPIO.output(backlight, GPIO.LOW) + time.sleep(0.1) + GPIO.output(backlight, GPIO.HIGH) + + # Setup reset as output (if provided). + if rst is not None: + GPIO.setup(self._rst, GPIO.OUT) + self.reset() + self._init() + + def send(self, data, is_data=True, chunk_size=4096): + """Write a byte or array of bytes to the display. Is_data parameter + controls if byte should be interpreted as display data (True) or command + data (False). Chunk_size is an optional size of bytes to write in a + single SPI transaction, with a default of 4096. + """ + # Set DC low for command, high for data. + GPIO.output(self._dc, is_data) + # Convert scalar argument to list so either can be passed as parameter. + if isinstance(data, numbers.Number): + data = [data & 0xFF] + # Write data a chunk at a time. + for start in range(0, len(data), chunk_size): + end = min(start + chunk_size, len(data)) + self._spi.xfer(data[start:end]) + + def set_backlight(self, value): + """Set the backlight on/off.""" + if self._backlight is not None: + GPIO.output(self._backlight, value) + + @property + def width(self): + return self._width if self._rotation == 0 or self._rotation == 180 else self._height + + @property + def height(self): + return self._height if self._rotation == 0 or self._rotation == 180 else self._width + + def command(self, data): + """Write a byte or array of bytes to the display as command data.""" + self.send(data, False) + + def data(self, data): + """Write a byte or array of bytes to the display as display data.""" + self.send(data, True) + + def reset(self): + """Reset the display, if reset pin is connected.""" + if self._rst is not None: + GPIO.output(self._rst, 1) + time.sleep(0.500) + GPIO.output(self._rst, 0) + time.sleep(0.500) + GPIO.output(self._rst, 1) + time.sleep(0.500) + + def _init(self): + # Initialize the display. + + self.command(ST7789_SWRESET) # Software reset + time.sleep(0.150) # delay 150 ms + + self.command(ST7789_MADCTL) + self.data(0x70) + + self.command(ST7789_FRMCTR2) # Frame rate ctrl - idle mode + self.data(0x0C) + self.data(0x0C) + self.data(0x00) + self.data(0x33) + self.data(0x33) + + self.command(ST7789_COLMOD) + self.data(0x05) + + self.command(ST7789_GCTRL) + self.data(0x14) + + self.command(ST7789_VCOMS) + self.data(0x37) + + self.command(ST7789_LCMCTRL) # Power control + self.data(0x2C) + + self.command(ST7789_VDVVRHEN) # Power control + self.data(0x01) + + self.command(ST7789_VRHS) # Power control + self.data(0x12) + + self.command(ST7789_VDVS) # Power control + self.data(0x20) + + self.command(0xD0) + self.data(0xA4) + self.data(0xA1) + + self.command(ST7789_FRCTRL2) + self.data(0x0F) + + self.command(ST7789_GMCTRP1) # Set Gamma + self.data(0xD0) + self.data(0x04) + self.data(0x0D) + self.data(0x11) + self.data(0x13) + self.data(0x2B) + self.data(0x3F) + self.data(0x54) + self.data(0x4C) + self.data(0x18) + self.data(0x0D) + self.data(0x0B) + self.data(0x1F) + self.data(0x23) + + self.command(ST7789_GMCTRN1) # Set Gamma + self.data(0xD0) + self.data(0x04) + self.data(0x0C) + self.data(0x11) + self.data(0x13) + self.data(0x2C) + self.data(0x3F) + self.data(0x44) + self.data(0x51) + self.data(0x2F) + self.data(0x1F) + self.data(0x1F) + self.data(0x20) + self.data(0x23) + + if self._invert: + self.command(ST7789_INVON) # Invert display + else: + self.command(ST7789_INVOFF) # Don't invert display + + self.command(ST7789_SLPOUT) + + self.command(ST7789_DISPON) # Display on + time.sleep(0.100) # 100 ms + + def begin(self): + """Set up the display + + Deprecated. Included in __init__. + + """ + pass + + def set_window(self, x0=0, y0=0, x1=None, y1=None): + """Set the pixel address window for proceeding drawing commands. x0 and + x1 should define the minimum and maximum x pixel bounds. y0 and y1 + should define the minimum and maximum y pixel bound. If no parameters + are specified the default will be to update the entire display from 0,0 + to width-1,height-1. + """ + if x1 is None: + x1 = self._width - 1 + + if y1 is None: + y1 = self._height - 1 + + y0 += self._offset_top + y1 += self._offset_top + + x0 += self._offset_left + x1 += self._offset_left + + self.command(ST7789_CASET) # Column addr set + self.data(x0 >> 8) + self.data(x0 & 0xFF) # XSTART + self.data(x1 >> 8) + self.data(x1 & 0xFF) # XEND + self.command(ST7789_RASET) # Row addr set + self.data(y0 >> 8) + self.data(y0 & 0xFF) # YSTART + self.data(y1 >> 8) + self.data(y1 & 0xFF) # YEND + self.command(ST7789_RAMWR) # write to RAM + + def display(self, image): + """Write the provided image to the hardware. + + :param image: Should be RGB format and the same dimensions as the display hardware. + + """ + # Set address bounds to entire display. + self.set_window() + + # Convert image to 16bit RGB565 format and + # flatten into bytes. + pixelbytes = self.image_to_data(image, self._rotation) + + # Write data to hardware. + for i in range(0, len(pixelbytes), 4096): + self.data(pixelbytes[i:i + 4096]) + + def image_to_data(self, image, rotation=0): + if not isinstance(image, np.ndarray): + image = np.array(image.convert('RGB')) + + # Rotate the image + pb = np.rot90(image, rotation // 90).astype('uint16') + + # Mask and shift the 888 RGB into 565 RGB + red = (pb[..., [0]] & 0xf8) << 8 + green = (pb[..., [1]] & 0xfc) << 3 + blue = (pb[..., [2]] & 0xf8) >> 3 + + # Stick 'em together + result = red | green | blue + + # Output the raw bytes + return result.byteswap().tobytes() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py new file mode 100644 index 00000000..a57a3515 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py @@ -0,0 +1,37 @@ +# /***************************************************************************** +# * | File : config.py +# * | Author : Waveshare team +# * | Function : Hardware underlying interface,for Jetson nano +# * | Info : +# *---------------- +# * | This version: V1.0 +# * | Date : 2019-06-06 +# * | Info : +# ******************************************************************************/ +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 time +from smbus import SMBus + +Device_SPI = 0 +Device_I2C = 1 +Device = Device_I2C +address = 0x3C +bus = SMBus(1) +### END OF FILE ### diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/epd.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/epd.py new file mode 100644 index 00000000..fed5a7f9 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/epd.py @@ -0,0 +1,23 @@ +from . import SSD1306 + +# Display resolution +EPD_WIDTH = 128 +EPD_HEIGHT = 64 + +disp = SSD1306.SSD1306_128_64(128, 64, address=0x3C) + +class EPD(object): + + def __init__(self): + self.width = EPD_WIDTH + self.height = EPD_HEIGHT + + def Init(self): + disp.begin() + + def Clear(self): + disp.clear() + + def display(self, image): + disp.getbuffer(image) + disp.ShowImage() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/waveshareoledlcdvert.py b/pwnagotchi/ui/hw/waveshareoledlcdvert.py new file mode 100644 index 00000000..ee817a26 --- /dev/null +++ b/pwnagotchi/ui/hw/waveshareoledlcdvert.py @@ -0,0 +1,59 @@ +# workinprogress based on the displayhatmini driver +# LCD support OK +# OLED support ongoing +# board GPIO: +# Key1: GPIO4 / pin7 +# Key2: GPIO17 / pin11 +# Key3: GPIO23 / pin16 +# Key4: GPIO24 / pin18 +# OLED SDA: GPIO2 / pin3 +# OLED SCL: GPIO3 / pin5 +# OLED info: +# driver: SSD1315 (I2C) +# resolution: 128x64 +# I2C address: 0x3C 0x3D +# HW datasheet: https://www.waveshare.com/wiki/OLED/LCD_HAT_(A) + +import logging + +import pwnagotchi.ui.fonts as fonts +from pwnagotchi.ui.hw.base import DisplayImpl + + +class Waveshareoledlcdvert(DisplayImpl): + def __init__(self, config): + super(Waveshareoledlcdvert, self).__init__(config, 'waveshareoledlcdvert') + + def layout(self): + fonts.setup(10, 9, 10, 35, 25, 9) + self._layout['width'] = 240 + self._layout['height'] = 320 + self._layout['face'] = (0, 40) + self._layout['name'] = (5, 20) + self._layout['channel'] = (0, 0) + self._layout['aps'] = (28, 0) + self._layout['uptime'] = (175, 0) + self._layout['line1'] = [0, 14, 240, 14] + self._layout['line2'] = [0, 108, 240, 108] + self._layout['friend_face'] = (0, 92) + self._layout['friend_name'] = (40, 94) + self._layout['shakes'] = (0, 109) + self._layout['mode'] = (215, 109) + self._layout['status'] = { + 'pos': (125, 20), + 'font': fonts.status_font(fonts.Medium), + 'max': 20 + } + + return self._layout + + def initialize(self): + logging.info("initializing Waveshare OLED/LCD hat vertical mode") + from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.ST7789vert import ST7789 + self._display = ST7789(0,0,22,18) + + def render(self, canvas): + self._display.display(canvas) + + def clear(self): + self._display.clear() \ No newline at end of file diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 547a1200..e17309b9 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -315,9 +315,15 @@ def load_config(args): elif config['ui']['display']['type'] in ('waveshareoledlcd'): config['ui']['display']['type'] = 'waveshareoledlcd' + elif config['ui']['display']['type'] in ('i2coled'): + config['ui']['display']['type'] = 'i2coled' + elif config['ui']['display']['type'] in ('waveshare35lcd'): config['ui']['display']['type'] = 'waveshare35lcd' + elif config['ui']['display']['type'] in ('waveshareoledlcdvert'): + config['ui']['display']['type'] = 'waveshareoledlcdvert' + # E-INK DISPLAYS ------------------------------------------------------------------------ # Adafruit From a71a90ba3db39364178c01f22a9fbdb093914b3d Mon Sep 17 00:00:00 2001 From: RasTacsko Date: Mon, 1 Apr 2024 01:37:47 +0200 Subject: [PATCH 12/39] Delete config.py --- .../hw/libs/waveshare/oled/oledlcd/config.py | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py deleted file mode 100644 index a57a3515..00000000 --- a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/config.py +++ /dev/null @@ -1,37 +0,0 @@ -# /***************************************************************************** -# * | File : config.py -# * | Author : Waveshare team -# * | Function : Hardware underlying interface,for Jetson nano -# * | Info : -# *---------------- -# * | This version: V1.0 -# * | Date : 2019-06-06 -# * | Info : -# ******************************************************************************/ -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation 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 -# furnished 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 time -from smbus import SMBus - -Device_SPI = 0 -Device_I2C = 1 -Device = Device_I2C -address = 0x3C -bus = SMBus(1) -### END OF FILE ### From 8f7741cd9e556275f9c1f6d3060d39e452f6afa7 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Mon, 1 Apr 2024 17:30:51 +0200 Subject: [PATCH 13/39] Remove unused imports Signed-off-by: jayofelony --- pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py b/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py index c165c74e..91e59855 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py +++ b/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py @@ -31,7 +31,6 @@ import os import logging import sys import time -import subprocess logger = logging.getLogger(__name__) @@ -113,6 +112,7 @@ class RaspberryPi: self.GPIO_RST_PIN.off() self.GPIO_DC_PIN.off() + self.GPIO_CS_PIN.off() self.GPIO_PWR_PIN.off() logger.debug("close 5V, Module enters 0 power consumption ...") From ab83de490533f7ad739bb0c305effa77ec55350b Mon Sep 17 00:00:00 2001 From: RasTacsko Date: Tue, 2 Apr 2024 17:46:11 +0200 Subject: [PATCH 14/39] separate I2C Oled display Separate files for ggeneric I2C Oled display with SSD1306 driver 128x64 resolution is tested, 128x32 and 96x16 resolutions is not tested yet --- pwnagotchi/ui/hw/i2coled.py | 26 +- pwnagotchi/ui/hw/libs/i2coled/SSD1306.py | 304 +++++++++++++++++++++++ pwnagotchi/ui/hw/libs/i2coled/epd.py | 27 ++ 3 files changed, 340 insertions(+), 17 deletions(-) create mode 100644 pwnagotchi/ui/hw/libs/i2coled/SSD1306.py create mode 100644 pwnagotchi/ui/hw/libs/i2coled/epd.py diff --git a/pwnagotchi/ui/hw/i2coled.py b/pwnagotchi/ui/hw/i2coled.py index 1392dc04..61a675dd 100644 --- a/pwnagotchi/ui/hw/i2coled.py +++ b/pwnagotchi/ui/hw/i2coled.py @@ -1,18 +1,9 @@ -# workinprogress based on the displayhatmini driver -# LCD support OK -# OLED support ongoing -# board GPIO: -# Key1: GPIO4 / pin7 -# Key2: GPIO17 / pin11 -# Key3: GPIO23 / pin16 -# Key4: GPIO24 / pin18 -# OLED SDA: GPIO2 / pin3 -# OLED SCL: GPIO3 / pin5 -# OLED info: -# driver: SSD1315 (I2C) -# resolution: 128x64 -# I2C address: 0x3C 0x3D -# HW datasheet: https://www.waveshare.com/wiki/OLED/LCD_HAT_(A) +# Created for the Pwnagotchi project by RasTacsko +# HW libraries are based on the adafruit python SSD1306 repo: +# https://github.com/adafruit/Adafruit_Python_SSD1306 +# SMBus parts coming from BLavery's lib_oled96 repo: +# https://github.com/BLavery/lib_oled96 + import logging import pwnagotchi.ui.fonts as fonts @@ -45,8 +36,9 @@ class I2COled(DisplayImpl): return self._layout def initialize(self): - logging.info("initializing I2C Oled Display on address 0x3C") - from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.epd import EPD + logging.info("initializing 128x64 I2C Oled Display on address 0x3C") + logging.info("To change resolution or address check pwnagotchi/ui/hw/libs/i2coled/epd.py") + from pwnagotchi.ui.hw.libs.i2coled.epd import EPD self._display = EPD() self._display.Init() self._display.Clear() diff --git a/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py new file mode 100644 index 00000000..e5c02ecd --- /dev/null +++ b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py @@ -0,0 +1,304 @@ +# Copyright (c) 2014 Adafruit Industries +# Author: Tony DiCola +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation 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 +# furnished 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 FOR 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. +# +# SMBus parts coming from BLavery's lib_oled96 repo: +# https://github.com/BLavery/lib_oled96 +# +# Modified for the Pwnagotchi project by RasTacsko +# Using SMBus, spidev RPi.GPIO for I2C communication instead of Adafruit libraries +# spidev maybe not necessary... needs some checking!!! +# ToDo: +# rotation support for vertical layouts +# checking luma oled library for support other chipsets/resolutions + +from __future__ import division +import logging +import time + +import RPi.GPIO as GPIO +# import spidev +from smbus import SMBus +i2cbus = SMBus(1) + + +# Constants +SSD1306_I2C_ADDRESS = 0x3C # 011110+SA0+RW - 0x3C or 0x3D +SSD1306_SETCONTRAST = 0x81 +SSD1306_DISPLAYALLON_RESUME = 0xA4 +SSD1306_DISPLAYALLON = 0xA5 +SSD1306_NORMALDISPLAY = 0xA6 +SSD1306_INVERTDISPLAY = 0xA7 +SSD1306_DISPLAYOFF = 0xAE +SSD1306_DISPLAYON = 0xAF +SSD1306_SETDISPLAYOFFSET = 0xD3 +SSD1306_SETCOMPINS = 0xDA +SSD1306_SETVCOMDETECT = 0xDB +SSD1306_SETDISPLAYCLOCKDIV = 0xD5 +SSD1306_SETPRECHARGE = 0xD9 +SSD1306_SETMULTIPLEX = 0xA8 +SSD1306_SETLOWCOLUMN = 0x00 +SSD1306_SETHIGHCOLUMN = 0x10 +SSD1306_SETSTARTLINE = 0x40 +SSD1306_MEMORYMODE = 0x20 +SSD1306_COLUMNADDR = 0x21 +SSD1306_PAGEADDR = 0x22 +SSD1306_COMSCANINC = 0xC0 +SSD1306_COMSCANDEC = 0xC8 +SSD1306_SEGREMAP = 0xA0 +SSD1306_CHARGEPUMP = 0x8D +SSD1306_EXTERNALVCC = 0x1 +SSD1306_SWITCHCAPVCC = 0x2 + +# Scrolling constants +SSD1306_ACTIVATE_SCROLL = 0x2F +SSD1306_DEACTIVATE_SCROLL = 0x2E +SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 +SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 +SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 +SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 +SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A + + +class SSD1306Base(object): + """Base class for SSD1306-based OLED displays. Implementors should subclass + and provide an implementation for the _initialize function. + """ + + def __init__(self, width, height, address=SSD1306_I2C_ADDRESS, bus=None): + self._log = logging.getLogger('Adafruit_SSD1306.SSD1306Base') + self.cmd_mode = 0x00 + self.data_mode = 0x40 + self.bus = i2cbus + self.addr = address + self.width = width + self.height = height + self._pages = height//8 + self._buffer = [0]*(width*self._pages) + + def _initialize(self): + raise NotImplementedError + + def command(self, *cmd): + """Send command byte to display.""" + # I2C write. + assert(len(cmd) <= 31) + self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + + def data(self, data): + """Send byte of data to display.""" + # I2C write. + for i in range(0, len(data), 31): + self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + + def begin(self, vccstate=SSD1306_SWITCHCAPVCC): + """Initialize display.""" + # Save vcc state. + self._vccstate = vccstate + # Reset and initialize display. + self._initialize() + # Turn on the display. + self.command(SSD1306_DISPLAYON) + + def ShowImage(self): + """ + The image on the "canvas" is flushed through to the hardware display. + Takes the 1-bit image and dumps it to the SSD1306 OLED display. + """ + self.command(SSD1306_COLUMNADDR) + self.command(0) # Column start address. (0 = reset) + self.command(self.width-1) # Column end address. + self.command(SSD1306_PAGEADDR) + self.command(0) # Page start address. (0 = reset) + self.command(self._pages-1) # Page end address. + + for i in range(0, len(self._buffer), 16): + self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) + + def getbuffer(self, image): + """Set buffer to value of Python Imaging Library image. The image should + be in 1 bit mode and a size equal to the display size. + """ + if image.mode != '1': + raise ValueError('Image must be in mode 1.') + imwidth, imheight = image.size + if imwidth != self.width or imheight != self.height: + raise ValueError('Image must be same dimensions as display ({0}x{1}).' \ + .format(self.width, self.height)) + # Grab all the pixels from the image, faster than getpixel. + pix = image.load() + # Iterate through the memory pages + index = 0 + for page in range(self._pages): + # Iterate through all x axis columns. + for x in range(self.width): + # Set the bits for the column of pixels at the current position. + bits = 0 + # Don't use range here as it's a bit slow + for bit in [0, 1, 2, 3, 4, 5, 6, 7]: + bits = bits << 1 + bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 + # Update buffer byte and increment to next byte. + self._buffer[index] = bits + index += 1 + + def clear(self): + """Clear contents of image buffer.""" + self._buffer = [0]*(self.width*self._pages) + + def set_contrast(self, contrast): + """Sets the contrast of the display. Contrast should be a value between + 0 and 255.""" + if contrast < 0 or contrast > 255: + raise ValueError('Contrast must be a value from 0 to 255 (inclusive).') + self.command(SSD1306_SETCONTRAST) + self.command(contrast) + + def dim(self, dim): + """Adjusts contrast to dim the display if dim is True, otherwise sets the + contrast to normal brightness if dim is False. + """ + # Assume dim display. + contrast = 0 + # Adjust contrast based on VCC if not dimming. + if not dim: + if self._vccstate == SSD1306_EXTERNALVCC: + contrast = 0x9F + else: + contrast = 0xCF + self.set_contrast(contrast) + +class SSD1306_128_64(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_128_64, self).__init__(128, 64, address, bus) + + def _initialize(self): + # 128x64 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x80) # the suggested ratio 0x80 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x3F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x12) + self.command(SSD1306_SETCONTRAST) # 0x81 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x9F) + else: + self.command(0xCF) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 + +class SSD1306_128_32(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_128_64, self).__init__(128, 64, address, bus) + + def _initialize(self): + # 128x32 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x80) # the suggested ratio 0x80 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x1F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x02) + self.command(SSD1306_SETCONTRAST) # 0x81 + self.command(0x8F) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 + + +class SSD1306_96_16(SSD1306Base): + def __init__(self, width, height, address=None, bus=None): + # Call base class constructor. + super(SSD1306_96_16, self).__init__(96, 16, address, bus) + + def _initialize(self): + # 128x32 pixel specific initialization. + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x60) # the suggested ratio 0x60 + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x0F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x02) + self.command(SSD1306_SETCONTRAST) # 0x81 + self.command(0x8F) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/i2coled/epd.py b/pwnagotchi/ui/hw/libs/i2coled/epd.py new file mode 100644 index 00000000..898aee36 --- /dev/null +++ b/pwnagotchi/ui/hw/libs/i2coled/epd.py @@ -0,0 +1,27 @@ +from . import SSD1306 + +# Display resolution, change if the screen resolution is changed! +EPD_WIDTH = 128 +EPD_HEIGHT = 64 + +# Available screen resolutions: +# disp = SSD1306.SSD1306_128_32(128, 32, address=0x3C) +# disp = SSD1306.SSD1306_96_16(96, 16, address=0x3C) +# If you change for different resolution, you have to modify the layout in pwnagotchi/ui/hw/i2coled.py +disp = SSD1306.SSD1306_128_64(128, 64, address=0x3C) + +class EPD(object): + + def __init__(self): + self.width = EPD_WIDTH + self.height = EPD_HEIGHT + + def Init(self): + disp.begin() + + def Clear(self): + disp.clear() + + def display(self, image): + disp.getbuffer(image) + disp.ShowImage() \ No newline at end of file From 47705ba1a2d76cb249596c3036bd008396688381 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 3 Apr 2024 09:39:10 +0200 Subject: [PATCH 15/39] Update config.txt at creation of image file, no more overwriting at auto-update. Signed-off-by: jayofelony --- builder/data/32bit/boot/config.txt | 67 -------------------- builder/data/64bit/boot/firmware/config.txt | 70 --------------------- builder/raspberrypi32.yml | 43 +++++++++++++ builder/raspberrypi64.yml | 28 +++++++++ 4 files changed, 71 insertions(+), 137 deletions(-) delete mode 100644 builder/data/32bit/boot/config.txt delete mode 100644 builder/data/64bit/boot/firmware/config.txt diff --git a/builder/data/32bit/boot/config.txt b/builder/data/32bit/boot/config.txt deleted file mode 100644 index 92a4d1a5..00000000 --- a/builder/data/32bit/boot/config.txt +++ /dev/null @@ -1,67 +0,0 @@ -# For more options and information see -# http://rptl.io/configtxt -# Some settings may impact device functionality. See link above for details - -# Uncomment some or all of these to enable the optional hardware interfaces -#dtparam=i2c_arm=on -#dtparam=i2s=on -#dtparam=spi=on - -# Enable audio (loads snd_bcm2835) -dtparam=audio=on - -# Additional overlays and parameters are documented -# /boot/overlays/README - -# Automatically load overlays for detected cameras -camera_auto_detect=1 - -# Automatically load overlays for detected DSI displays -display_auto_detect=1 - -# Automatically load initramfs files, if found -auto_initramfs=1 - -# Enable DRM VC4 V3D driver -dtoverlay=vc4-kms-v3d -max_framebuffers=2 - -# Don't have the firmware create an initial video= setting in cmdline.txt. -# Use the kernel's default instead. -disable_fw_kms_setup=1 - -# Run in 64-bit mode -arm_64bit=0 - -# Disable compensation for displays with overscan -disable_overscan=1 - -# Run as fast as firmware / board allows -arm_boost=1 - -[cm4] -# Enable host mode on the 2711 built-in XHCI USB controller. -# This line should be removed if the legacy DWC2 controller is required -# (e.g. for USB device mode) or if USB support is not required. -otg_mode=1 - -[all] -dtoverlay=dwc2 -dtparam=i2c1=on -dtparam=i2c_arm=on -dtparam=spi=on -gpu_mem=1 -dtoverlay=dwc2 -#dtoverlay=disable-wifi - -[pi0] -dtoverlay=spi1-3cs -#dtoverlay=disable-wifi - -[pi3] -dtoverlay=spi1-3cs -#dtoverlay=disable-wifi - -[pi4] -dtoverlay=spi1-3cs -#dtoverlay=disable-wifi diff --git a/builder/data/64bit/boot/firmware/config.txt b/builder/data/64bit/boot/firmware/config.txt deleted file mode 100644 index 948e70ec..00000000 --- a/builder/data/64bit/boot/firmware/config.txt +++ /dev/null @@ -1,70 +0,0 @@ -# For more options and information see -# http://rptl.io/configtxt -# Some settings may impact device functionality. See link above for details - -# Uncomment some or all of these to enable the optional hardware interfaces -#dtparam=i2c_arm=on -#dtparam=i2s=on -#dtparam=spi=on - -# Enable audio (loads snd_bcm2835) -dtparam=audio=on - -# Additional overlays and parameters are documented -# /boot/firmware/overlays/README - -# Automatically load overlays for detected cameras -camera_auto_detect=1 - -# Automatically load overlays for detected DSI displays -display_auto_detect=1 - -# Automatically load initramfs files, if found -auto_initramfs=1 - -# Enable DRM VC4 V3D driver -dtoverlay=vc4-kms-v3d -max_framebuffers=2 - -# Don't have the firmware create an initial video= setting in cmdline.txt. -# Use the kernel's default instead. -disable_fw_kms_setup=1 - -# Run in 64-bit mode -arm_64bit=1 - -# Disable compensation for displays with overscan -disable_overscan=1 - -# Run as fast as firmware / board allows -arm_boost=1 - -[cm4] -# Enable host mode on the 2711 built-in XHCI USB controller. -# This line should be removed if the legacy DWC2 controller is required -# (e.g. for USB device mode) or if USB support is not required. -otg_mode=1 - -[all] -dtparam=i2c1=on -dtparam=i2c_arm=on -dtparam=spi=on -gpu_mem=1 -dtoverlay=dwc2 -#dtoverlay=disable-wifi - -[pi0] -dtoverlay=spi0-0cs -#dtoverlay=disable-wifi - -[pi3] -dtoverlay=spi0-0cs -#dtoverlay=disable-wifi - -[pi4] -dtoverlay=spi0-0cs -#dtoverlay=disable-wifi - -[pi5] -dtoverlay=spi0-0cs -#dtoverlay=disable-wifi diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index 16e18440..bf6a03b7 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -123,6 +123,7 @@ - libc-ares-dev - libc6-dev - libcpuinfo-dev + - libcurl4-openssl-dev - libdbus-1-dev - libdbus-glib-1-dev - libeigen3-dev @@ -206,6 +207,30 @@ state: present when: hostname.changed + - name: setup /boot/config.txt + blockinfile: + path: /boot/config.txt + insertafter: EOF + block: | + dtparam=i2c1=on + dtparam=i2c_arm=on + dtparam=spi=on + gpu_mem=1 + dtoverlay=dwc2 + #dtoverlay=disable-wifi + + [pi0] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + + [pi3] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + + [pi4] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + - name: Create custom plugin directory file: path: '{{ pwnagotchi.custom_plugin_dir }}' @@ -264,6 +289,24 @@ dest: /usr/local/lib/libpcap.so.0.8 state: link + # install latest hcxtools + + - name: clone hcxtools + git: + repo: https://github.com/ZerBea/hcxtools.git + dest: /usr/local/src/hcxtools + + - name: install hcxtools + shell: "make && make install" + args: + executable: /bin/bash + chdir: /usr/local/src/hcxtools + + - name: remove hcxtools directory + file: + state: absent + path: /usr/local/src/hcxtools + ############################################################### # Install nexmon to fix wireless scanning (takes 2.5G of space) ############################################################### diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 479f11ca..11f1a027 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -211,6 +211,34 @@ regexp: '(.*)$' line: '\1 modules-load=dwc2,g_ether' + - name: setup /boot/firmware/config.txt + blockinfile: + path: /boot/firmware/config.txt + insertafter: EOF + block: | + dtparam=i2c1=on + dtparam=i2c_arm=on + dtparam=spi=on + gpu_mem=1 + dtoverlay=dwc2 + #dtoverlay=disable-wifi + + [pi0] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + + [pi3] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + + [pi4] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + + [pi5] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi + - name: change hostname lineinfile: dest: /etc/hostname From 415e5cd551d71782b6b7d8b2474facf786e423a1 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 3 Apr 2024 09:39:38 +0200 Subject: [PATCH 16/39] Small changes Signed-off-by: jayofelony --- pwnagotchi/plugins/default/gpio_buttons.py | 7 ++++--- pwnagotchi/plugins/default/grid.py | 2 +- pwnagotchi/plugins/default/switcher.py | 5 ++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pwnagotchi/plugins/default/gpio_buttons.py b/pwnagotchi/plugins/default/gpio_buttons.py index 50338aa2..2a5cfe2b 100644 --- a/pwnagotchi/plugins/default/gpio_buttons.py +++ b/pwnagotchi/plugins/default/gpio_buttons.py @@ -14,8 +14,9 @@ class GPIOButtons(plugins.Plugin): self.running = False self.ports = {} self.commands = None + self.options = dict() - def runCommand(self, channel): + def runcommand(self, channel): command = self.ports[channel] logging.info(f"Button Pressed! Running command: {command}") process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None, @@ -35,8 +36,8 @@ class GPIOButtons(plugins.Plugin): gpio = int(gpio) self.ports[gpio] = command GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP) - GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runCommand, bouncetime=600) - #set pimoroni display hat mini LED off/dim + GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runcommand, bouncetime=600) + # set pimoroni display hat mini LED off/dim GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py index a2a35357..9c24ed53 100644 --- a/pwnagotchi/plugins/default/grid.py +++ b/pwnagotchi/plugins/default/grid.py @@ -89,7 +89,7 @@ class Grid(plugins.Plugin): logging.debug("checking pcap's") config = agent.config() - pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap")) + pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap")) num_networks = len(pcap_files) reported = self.report.data_field_or('reported', default=[]) num_reported = len(reported) diff --git a/pwnagotchi/plugins/default/switcher.py b/pwnagotchi/plugins/default/switcher.py index 21335ac3..4d63f41e 100644 --- a/pwnagotchi/plugins/default/switcher.py +++ b/pwnagotchi/plugins/default/switcher.py @@ -18,12 +18,14 @@ def systemd_dropin(name, content): systemctl("daemon-reload") + def systemctl(command, unit=None): if unit: os.system("/bin/systemctl %s %s" % (command, unit)) else: os.system("/bin/systemctl %s" % command) + def run_task(name, options): task_service_name = "switcher-%s-task.service" % name # save all the commands to a shell script @@ -57,7 +59,7 @@ def run_task(name, options): """ % (name, task_service_name, name)) if 'reboot' in options and options['reboot']: - # create a indication file! + # create an indication file! # if this file is set, we want the switcher-tasks to run open('/root/.switcher', 'a').close() @@ -98,6 +100,7 @@ def run_task(name, options): systemctl("daemon-reload") systemctl("start", task_service_name) + class Switcher(plugins.Plugin): __author__ = '33197631+dadav@users.noreply.github.com' __version__ = '0.0.1' From 8991dd681135ada5d39a20be11e7e2c135de58c7 Mon Sep 17 00:00:00 2001 From: Rai <58925163+rai68@users.noreply.github.com> Date: Thu, 4 Apr 2024 03:04:31 +1000 Subject: [PATCH 17/39] Update components.py this allows plugins / ui elements of bitmap to be inverted for plugins etc Signed-off-by: Rai <58925163+rai68@users.noreply.github.com> --- pwnagotchi/ui/components.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pwnagotchi/ui/components.py b/pwnagotchi/ui/components.py index b6d4db49..763f510b 100644 --- a/pwnagotchi/ui/components.py +++ b/pwnagotchi/ui/components.py @@ -10,13 +10,17 @@ class Widget(object): def draw(self, canvas, drawer): raise Exception("not implemented") - +# canvas.paste: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.paste +# takes mask variable, to identify color system. (not used for pwnagotchi yet) +# Pwn should use "1" since its mainly black or white displays. class Bitmap(Widget): def __init__(self, path, xy, color=0): super().__init__(xy, color) self.image = Image.open(path) def draw(self, canvas, drawer): + if self.color = 0xFF: + self.image = ImageOps.invert(self.image) canvas.paste(self.image, self.xy) From ac2973889daaa2d8c62ef3f19c27a2c849b6b8a4 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Wed, 3 Apr 2024 21:14:22 +0200 Subject: [PATCH 18/39] Update FUNDING.yml --- .github/FUNDING.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 3be73f82..f8690609 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,3 @@ # These are supported funding model platforms -github: jayofelony -custom: https://tikkie.me/pay/dubcto94hnskg539kar0 \ No newline at end of file +github: jayofelony \ No newline at end of file From 8fd0e358a90f07b7ddd84c6ba21164f2248c36c4 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Mon, 15 Apr 2024 15:23:34 +0200 Subject: [PATCH 19/39] Small changes Signed-off-by: jayofelony --- builder/data/32bit/usr/bin/pwnlib | 1 + builder/data/64bit/usr/bin/pwnlib | 1 + 2 files changed, 2 insertions(+) diff --git a/builder/data/32bit/usr/bin/pwnlib b/builder/data/32bit/usr/bin/pwnlib index 45b875c6..c995a67e 100755 --- a/builder/data/32bit/usr/bin/pwnlib +++ b/builder/data/32bit/usr/bin/pwnlib @@ -32,6 +32,7 @@ start_monitor_interface() { ifconfig wlan0 down ifconfig wlan0mon up iw dev wlan0mon set power_save off + iw dev wlan0 del } # stops mon0 diff --git a/builder/data/64bit/usr/bin/pwnlib b/builder/data/64bit/usr/bin/pwnlib index 6cc93f24..fee25488 100755 --- a/builder/data/64bit/usr/bin/pwnlib +++ b/builder/data/64bit/usr/bin/pwnlib @@ -26,6 +26,7 @@ start_monitor_interface() { ifconfig wlan0 down ifconfig wlan0mon up iw dev wlan0mon set power_save off + iw dev wlan0 del } # stops mon0 From 1064936503dd9436c2325cf5baa3073704edd7be Mon Sep 17 00:00:00 2001 From: jayofelony Date: Mon, 15 Apr 2024 15:23:47 +0200 Subject: [PATCH 20/39] Small changes Signed-off-by: jayofelony --- pwnagotchi/ui/hw/displayhatmini.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pwnagotchi/ui/hw/displayhatmini.py b/pwnagotchi/ui/hw/displayhatmini.py index b5a8db80..afc590db 100644 --- a/pwnagotchi/ui/hw/displayhatmini.py +++ b/pwnagotchi/ui/hw/displayhatmini.py @@ -34,10 +34,10 @@ class DisplayHatMini(DisplayImpl): def initialize(self): logging.info("initializing Display Hat Mini") from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789 - self._display = ST7789(0, 1, 9, 13) + self._display = ST7789(0, 1, 9, 13, width=self._layout['width'], height=self._layout['height'], rotation=0) def render(self, canvas): self._display.display(canvas) def clear(self): - self._display.clear() + pass From fef442edbb61e4e4182d64b30cf3c2b1bab6370b Mon Sep 17 00:00:00 2001 From: RasTacsko Date: Thu, 18 Apr 2024 17:39:53 +0200 Subject: [PATCH 21/39] I2C oled driver mods by NurseJackass I2C oled config can be added in the config.toml Default is 128x64 display on i2c address 0x3C ui.display.type = "i2coled" ui.display.i2c_addr = 0x3C ui.display.width = 128 ui.display.height = 64 --- pwnagotchi/ui/hw/i2coled.py | 27 +++++++++++++++---- pwnagotchi/ui/hw/libs/i2coled/SSD1306.py | 26 +++++++++++------- pwnagotchi/ui/hw/libs/i2coled/epd.py | 23 ++++++++++------ .../hw/libs/waveshare/oled/oledlcd/SSD1306.py | 6 ++--- .../libs/waveshare/oled/oledlcd/ST7789vert.py | 8 ------ 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/pwnagotchi/ui/hw/i2coled.py b/pwnagotchi/ui/hw/i2coled.py index 61a675dd..1c55035e 100644 --- a/pwnagotchi/ui/hw/i2coled.py +++ b/pwnagotchi/ui/hw/i2coled.py @@ -3,20 +3,33 @@ # https://github.com/adafruit/Adafruit_Python_SSD1306 # SMBus parts coming from BLavery's lib_oled96 repo: # https://github.com/BLavery/lib_oled96 +# I2C address, width and height import from config.toml made by NurseJackass import logging import pwnagotchi.ui.fonts as fonts from pwnagotchi.ui.hw.base import DisplayImpl +# +# Default is 128x64 display on i2c address 0x3C +# +# Configure i2c address and dimensions in config.toml: +# +# ui.display.type = "i2coled" +# ui.display.i2c_addr = 0x3C +# ui.display.width = 128 +# ui.display.height = 64 +# + class I2COled(DisplayImpl): def __init__(self, config): + self._config = config['ui']['display'] super(I2COled, self).__init__(config, 'i2coled') def layout(self): fonts.setup(8, 8, 8, 10, 10, 8) - self._layout['width'] = 128 - self._layout['height'] = 64 + self._layout['width'] = self._config['width'] if 'width' in self._config else 128 + self._layout['height'] = self._config['height'] if 'height' in self._config else 64 self._layout['face'] = (0, 30) self._layout['name'] = (0, 10) self._layout['channel'] = (72, 10) @@ -36,10 +49,14 @@ class I2COled(DisplayImpl): return self._layout def initialize(self): - logging.info("initializing 128x64 I2C Oled Display on address 0x3C") - logging.info("To change resolution or address check pwnagotchi/ui/hw/libs/i2coled/epd.py") + i2caddr = self._config['i2c_addr'] if 'i2c_addr' in self._config else 0x3C + width = self._config['width'] if 'width' in self._config else 128 + height = self._config['height'] if 'height' in self._config else 64 + + logging.info("initializing %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr)) + from pwnagotchi.ui.hw.libs.i2coled.epd import EPD - self._display = EPD() + self._display = EPD(address=i2caddr, width=width, height=height) self._display.Init() self._display.Clear() diff --git a/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py index e5c02ecd..815f53cf 100644 --- a/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py +++ b/pwnagotchi/ui/hw/libs/i2coled/SSD1306.py @@ -100,13 +100,19 @@ class SSD1306Base(object): """Send command byte to display.""" # I2C write. assert(len(cmd) <= 31) - self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + try: + self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd)) + except Exception as e: + logging.exception(e) def data(self, data): """Send byte of data to display.""" # I2C write. - for i in range(0, len(data), 31): - self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + try: + for i in range(0, len(data), 31): + self.bus.write_i2c_block_data(self.addr, self.data_mode, list(data[i:i+31])) + except Exception as e: + logging.exception(e) def begin(self, vccstate=SSD1306_SWITCHCAPVCC): """Initialize display.""" @@ -116,7 +122,7 @@ class SSD1306Base(object): self._initialize() # Turn on the display. self.command(SSD1306_DISPLAYON) - + def ShowImage(self): """ The image on the "canvas" is flushed through to the hardware display. @@ -128,10 +134,12 @@ class SSD1306Base(object): self.command(SSD1306_PAGEADDR) self.command(0) # Page start address. (0 = reset) self.command(self._pages-1) # Page end address. - - for i in range(0, len(self._buffer), 16): - self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) - + try: + for i in range(0, len(self._buffer), 16): + self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) + except Exception as e: + logging.exception(e) + def getbuffer(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. @@ -229,7 +237,7 @@ class SSD1306_128_64(SSD1306Base): class SSD1306_128_32(SSD1306Base): def __init__(self, width, height, address=None, bus=None): # Call base class constructor. - super(SSD1306_128_64, self).__init__(128, 64, address, bus) + super(SSD1306_128_32, self).__init__(128, 32, address, bus) def _initialize(self): # 128x32 pixel specific initialization. diff --git a/pwnagotchi/ui/hw/libs/i2coled/epd.py b/pwnagotchi/ui/hw/libs/i2coled/epd.py index 898aee36..c35ee8c9 100644 --- a/pwnagotchi/ui/hw/libs/i2coled/epd.py +++ b/pwnagotchi/ui/hw/libs/i2coled/epd.py @@ -8,20 +8,27 @@ EPD_HEIGHT = 64 # disp = SSD1306.SSD1306_128_32(128, 32, address=0x3C) # disp = SSD1306.SSD1306_96_16(96, 16, address=0x3C) # If you change for different resolution, you have to modify the layout in pwnagotchi/ui/hw/i2coled.py -disp = SSD1306.SSD1306_128_64(128, 64, address=0x3C) class EPD(object): - def __init__(self): - self.width = EPD_WIDTH - self.height = EPD_HEIGHT + def __init__(self, address=0x3D, width=EPD_WIDTH, height=EPD_HEIGHT): + self.width = width + self.height = height + + # choose subclass based on dimensions + if height == 32: + self.disp = SSD1306.SSD1306_128_32(width, height, address) + elif height == 16: + self.disp = SSD1306.SSD1306_96_16(width, height, address) + else: + self.disp = SSD1306.SSD1306_128_64(width, height, address) def Init(self): - disp.begin() + self.disp.begin() def Clear(self): - disp.clear() + self.disp.clear() def display(self, image): - disp.getbuffer(image) - disp.ShowImage() \ No newline at end of file + self.disp.getbuffer(image) + self.disp.ShowImage() \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py index 4ca97dad..c529c48f 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/SSD1306.py @@ -106,7 +106,7 @@ class SSD1306Base(object): self._initialize() # Turn on the display. self.command(SSD1306_DISPLAYON) - + def ShowImage(self): """ The image on the "canvas" is flushed through to the hardware display. @@ -118,10 +118,10 @@ class SSD1306Base(object): self.command(SSD1306_PAGEADDR) self.command(0) # Page start address. (0 = reset) self.command(self._pages-1) # Page end address. - + for i in range(0, len(self._buffer), 16): self.bus.write_i2c_block_data(self.addr, self.data_mode, self._buffer[i:i+16]) - + def getbuffer(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. diff --git a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py index f8894b98..b0f0763d 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py +++ b/pwnagotchi/ui/hw/libs/waveshare/oled/oledlcd/ST7789vert.py @@ -95,11 +95,8 @@ class ST7789(object): offset_left=0, offset_top=0): """Create an instance of the display using SPI communication. - Must provide the GPIO pin number for the D/C pin and the SPI driver. - Can optionally provide the GPIO pin number for the reset pin as the rst parameter. - :param port: SPI port number :param cs: SPI chip-select number (0 or 1 for BCM :param backlight: Pin for controlling backlight @@ -109,7 +106,6 @@ class ST7789(object): :param rotation: Rotation of display connected to ST7789 :param invert: Invert display :param spi_speed_hz: SPI speed (in Hz) - """ if rotation not in [0, 90, 180, 270]: raise ValueError("Invalid rotation {}".format(rotation)) @@ -287,9 +283,7 @@ class ST7789(object): def begin(self): """Set up the display - Deprecated. Included in __init__. - """ pass @@ -326,9 +320,7 @@ class ST7789(object): def display(self, image): """Write the provided image to the hardware. - :param image: Should be RGB format and the same dimensions as the display hardware. - """ # Set address bounds to entire display. self.set_window() From b3e81a95c8320a662026f5ba9ae17e6b011d9737 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Thu, 25 Apr 2024 20:06:54 +0200 Subject: [PATCH 22/39] Update raspberrypi32.yml Signed-off-by: Jayofelony --- builder/raspberrypi32.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index bf6a03b7..fc3f3e64 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -152,6 +152,7 @@ - libsleef-dev - libsqlite3-dev - libssl-dev + - libssl-ocaml-dev - libswscale5 - libtiff5 - libtool From 4e07fbf1aa721818fe704a7a6e21311e0e719763 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Thu, 25 Apr 2024 20:30:45 +0200 Subject: [PATCH 23/39] Update raspberrypi32.yml Signed-off-by: Jayofelony --- builder/raspberrypi32.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index fc3f3e64..cfdc1a3a 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -292,21 +292,21 @@ # install latest hcxtools - - name: clone hcxtools - git: - repo: https://github.com/ZerBea/hcxtools.git - dest: /usr/local/src/hcxtools + #- name: clone hcxtools + # git: + # repo: https://github.com/ZerBea/hcxtools.git + # dest: /usr/local/src/hcxtools - - name: install hcxtools - shell: "make && make install" - args: - executable: /bin/bash - chdir: /usr/local/src/hcxtools + #- name: install hcxtools + # shell: "make && make install" + # args: + # executable: /bin/bash + # chdir: /usr/local/src/hcxtools - - name: remove hcxtools directory - file: - state: absent - path: /usr/local/src/hcxtools + #- name: remove hcxtools directory + # file: + # state: absent + # path: /usr/local/src/hcxtools ############################################################### # Install nexmon to fix wireless scanning (takes 2.5G of space) From 518e8c219c7d41772b108730cc3252c1df381734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Kolesz=C3=A1r?= Date: Fri, 26 Apr 2024 01:34:26 +0200 Subject: [PATCH 24/39] Fix incorrect use of assignment operator (=) instead of comparison operator (==) in draw method of ui/components.py --- pwnagotchi/ui/components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/ui/components.py b/pwnagotchi/ui/components.py index 763f510b..8537cddf 100644 --- a/pwnagotchi/ui/components.py +++ b/pwnagotchi/ui/components.py @@ -19,7 +19,7 @@ class Bitmap(Widget): self.image = Image.open(path) def draw(self, canvas, drawer): - if self.color = 0xFF: + if self.color == 0xFF: self.image = ImageOps.invert(self.image) canvas.paste(self.image, self.xy) From b38274e652ff323f45d743f083472779edab8f92 Mon Sep 17 00:00:00 2001 From: Regan Kouchoo Date: Fri, 26 Apr 2024 13:21:55 +1000 Subject: [PATCH 25/39] Fix 3.7 orientation --- pwnagotchi/ui/hw/waveshare3in7.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pwnagotchi/ui/hw/waveshare3in7.py b/pwnagotchi/ui/hw/waveshare3in7.py index f792845a..2b2cf155 100644 --- a/pwnagotchi/ui/hw/waveshare3in7.py +++ b/pwnagotchi/ui/hw/waveshare3in7.py @@ -10,8 +10,8 @@ class Waveshare3in7(DisplayImpl): def layout(self): fonts.setup(10, 8, 10, 18, 25, 9) - self._layout['width'] = 480 - self._layout['height'] = 280 + self._layout['width'] = 280 + self._layout['height'] = 480 self._layout['face'] = (0, 43) self._layout['name'] = (0, 14) self._layout['channel'] = (0, 0) From 357ffc67e5d1e4f0101f340c48ae65816c6f90b2 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Fri, 26 Apr 2024 09:19:13 +0200 Subject: [PATCH 26/39] Update _version.py Signed-off-by: Jayofelony --- pwnagotchi/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py index 387cfacc..b03f5b5d 100644 --- a/pwnagotchi/_version.py +++ b/pwnagotchi/_version.py @@ -1 +1 @@ -__version__ = '2.9.0' +__version__ = '2.9.1' From e2fa3ca138004b46a7e594a4593bab926862cce3 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Fri, 26 Apr 2024 17:02:33 +0200 Subject: [PATCH 27/39] Update pwnlib --- builder/data/32bit/usr/bin/pwnlib | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/data/32bit/usr/bin/pwnlib b/builder/data/32bit/usr/bin/pwnlib index c995a67e..45b875c6 100755 --- a/builder/data/32bit/usr/bin/pwnlib +++ b/builder/data/32bit/usr/bin/pwnlib @@ -32,7 +32,6 @@ start_monitor_interface() { ifconfig wlan0 down ifconfig wlan0mon up iw dev wlan0mon set power_save off - iw dev wlan0 del } # stops mon0 From 6603e01005b6c3d0bf6bcd7592341e0a93dfa930 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Fri, 26 Apr 2024 17:02:51 +0200 Subject: [PATCH 28/39] Update pwnlib --- builder/data/64bit/usr/bin/pwnlib | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/data/64bit/usr/bin/pwnlib b/builder/data/64bit/usr/bin/pwnlib index fee25488..6cc93f24 100755 --- a/builder/data/64bit/usr/bin/pwnlib +++ b/builder/data/64bit/usr/bin/pwnlib @@ -26,7 +26,6 @@ start_monitor_interface() { ifconfig wlan0 down ifconfig wlan0mon up iw dev wlan0mon set power_save off - iw dev wlan0 del } # stops mon0 From de07226be198062ed0241ceeb56fa581eff5fca4 Mon Sep 17 00:00:00 2001 From: Jayofelony Date: Fri, 26 Apr 2024 17:03:16 +0200 Subject: [PATCH 29/39] Update _version.py --- pwnagotchi/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py index b03f5b5d..c2d9c8e1 100644 --- a/pwnagotchi/_version.py +++ b/pwnagotchi/_version.py @@ -1 +1 @@ -__version__ = '2.9.1' +__version__ = '2.9.1.2' From 9941f093e9572671fb92c5894e27b76b63b63bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Henriques?= Date: Fri, 26 Apr 2024 16:07:00 +0100 Subject: [PATCH 30/39] Fix issue with FilledRect when using ui.invert=true --- pwnagotchi/ui/view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index 52b92f05..8d31ffeb 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -109,7 +109,7 @@ class View(object): self._state.has_element(key) def add_element(self, key, elem): - if self.invert is 1 and elem.color: + if self.invert is 1 and hasattr(elem, 'color'): if elem.color == 0xff: elem.color = 0x00 elif elem.color == 0x00: From 5b5718c186708ebbdcbc4c427b68bdd941a4daa7 Mon Sep 17 00:00:00 2001 From: Dragan Miljkovic Date: Wed, 1 May 2024 22:22:01 +0200 Subject: [PATCH 31/39] added serbian language --- pwnagotchi/locale/rs/LC_MESSAGES/voice.mo | Bin 0 -> 5308 bytes pwnagotchi/locale/rs/LC_MESSAGES/voice.po | 260 ++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 pwnagotchi/locale/rs/LC_MESSAGES/voice.mo create mode 100644 pwnagotchi/locale/rs/LC_MESSAGES/voice.po diff --git a/pwnagotchi/locale/rs/LC_MESSAGES/voice.mo b/pwnagotchi/locale/rs/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..1b5a68bf6e6602d0d304148d1a4128129c0ba6aa GIT binary patch literal 5308 zcmbW4OKc=Z8OJLm5O5$s0tt^iYO+9Hwv$al*mWMe&f2@{#P(Widso>5p=P=~Q#0LN zLqEnD8z&$EE1~3o&76d@rbkbn~iqJZoJQUpkF3>=6+9CC;hiPwqWSKZ_BMt~44 z*ZjJxtE;~HzJGmH{=;=wT~b^pDK}9T-=UO&U$}}Nx!$GJd%zX&!|)n-Cv3nQ;1lrU zun9i_pMlcPOYj=_3Y70&g&%-_gtx-C;LY&*tE={h;Srvfp@tXX_3%6JI`~s4{rnof z5B>?>2;ZuC&AXNQ5YLC;`{5DDD|H&mxGV4{(7;c@o0ydJdjiTl&ehKelzzSlKLRh+ z@4pXaygfJpe-CAxzd#x1@2~;orL?;ZiXUd6hUeiVd>Y;XzYS&nzk)KKH=xY-pHRNL z7UyYrHx&C8YqsFWc;13C&Lt?{eXp+nITX8IgLI|dfS-hagIB_v->cLIVFO+Z?}zV% zk3k9f>H2vI5+bzl=!^~AB8tE*}LF5D7yL*l>T3Y;-?=& zneXr5N8z8L*d?Nn@ot3j{==_C}r z%t8%63&oCSYrasw{}JR<^&2Smyk5V56G}f5{D@t*LizqKD0-QLn66GkT&^xa(Tl6! zdnmfe>-wjm=;j$Hy7@}Y=OKUU5X^QCO1Z8wdyhuxzU80H6 zb+o<_e>0t+2hqIvS7LWBPuCP( zh_+=N$R&AXKHOD5_k+7B57l)NhvO7dU${gskJR^Sc0p&>M8jz{o9DjeOySbDF1+5} z?3iLlo$x-M)SFhfeWAD0GTG6o-P9eEMtR5d>~=pcGZXJL)SNYC(XnaaT2&|8iD~Vq zIlr04-bB*vM&=VbF^S#L)6>)Hlud0`HSXDAKB*(GQ^qOEEY*HvqiW=R#Fx%8qBfb; zMmJ-d=XBUmr{rbo+MR;l_AT7EE}u}RO{=G|ORvNxwM9dnwsFk#f)x$D>{?c)n^;@u zp)aR-KOEWE@ta{p>M@N0k5zAjYjkXj+jHHtBjcp&;iPUcdTL|6UEl0zm(#@BhJMnQ znVwzIn=X!ZZid)p(q7J(Zc;DYp6Hd$)Zpk=$2Ih7VX_bm@zjFeu=JUGZDOC=;Ftv+ z`+?QTaBRSW?r)|t+stlwT(zK0!pHR7#4)m4c!j-HHi!kvDJ(pPN_=B0k%u)~Kb8$Z%g4^kNFDx5ts+8Ece&4l#P|*>E5G zc132R4|UK8bL$6%=tFsLh*H$!WnSpWwp@g9M2hi6(F|-+V(RsIchWV~6IkCQbI8q&JiKl8N21o!eHvli#V9 zOl0+=M~@yoIQfaHdb~Dkr%;c}4(q!5AeUv+@9)R0GNh`<{gFZMAsv)yQQhI^yrGtT(?>(5Ll9+k;aQ$s(UIAUp3nF` z%RTo*wIjW65^lYjd2V^F&)TN<`{F-Kg3{ZuOKtvC?w{H)*$&cgBSmUNtki^FrJ?i| z8zPrWj_|3p%){H&jw_fHM(de-)GCrP=@9daO`rAhMx&wD(06JjpN*=;FLi!g>u?|3 zB!U)c&=Kxp{Z(sXy^{pv+vKF?5HW@nqt;U=nKL9kK2NR5n!|=#?~k%#WC{~9ZsDu6 zc;2`$chN*0`!Ip?vaU%vR#uoe_*g@o?|57p#vPB*MqbnE$#IrjE&Ip9bI4o`ZcCO2 zV%%;av7%Z`2@W&u0~!6o)|R61w{<{-@_0dh!V76YvksXp{NyTeX<67Bxk55NjcVlT zawEgE>Z+ucCdJ;^J=4 z4_xcMqsQBcaq)D^C*u#W+Gb5>(ut*orTOt(4o}}Zal)qsil15=_OY=b9pA$eap^;{ zdt|vS9$8;IIdx>*PE6gf+0=a6@*?pWeWdA%3E94Lyn>Ra)e5`8R@t=)(kK6pcJL=k zHgK1iMC1_mZ*1<2v!frF|Fn0nWVYOrPc>ez!?eF|yS*0~suy?5-RDuHEPs|q^;~vY z=+bh|H#3Qw>k^H)>vUeSdy|QC_AWA=>6K*C-HU8eGE8OQeiFwt*}!{rSMA8@o#;!0ii{T8cDHuCPs=$`3$ojcjSsjIf{j_Hz3`KDP$7UztOl#RSQ zse2|R5sbHSM!;&;ok<&dZQ#4ImG55U_`tNR-ZGtmiCMYRwT+XyYly?;yZQyw_q)%# zRKgSzVQzOX(uNKSA3Mw}`6TXI_7{17j!ND#njKrn2K=~@4K+kNGQF6WJ}-RNG4DCg z=F8`mQ>2siy_ZeCUlY~uwJ(|cz`oB||KHBP-VYiRBYYI2Z|6lQqwQZpUD$#7?*{-z$K{oxIRm5| zizn0>?gmbFLEM?RtPDXuZMq1s)C8hPyNLW$Y$FCQQ{#I+_6M@>YGHe|2djg?+gviC z4zxJ9-p5{}iFmd;8JOy!YAI&}%tjSHF&M+?ZwZ-i#X+*N#4;1f>WUFtuzXH(59{{e z!2pZ!R!TyUJJxx9*H1U8;BX)+Ct2*hY-4FD+H>tp){0J2{zC|omGePr_g>`mAkvqF z!7sK1mvKVClUWfKKqX|cvA{L|{-8htlK(DP87B0<`y7o~g>pP#%3%N-Nd@NyM4Q;e+Ata{v%=8?=OgV9Yhc3WuUOc4@(g2|j5dO=Csqoc#_bI9ZJ zc$^~3k#+NdGLWD1@o@orI~b6aJtHT8 l|Mi%Vn?g}sbvmeijmmA0bMA;v)jQ3;aUm9UWq&Nqe*qNAg+TxS literal 0 HcmV?d00001 diff --git a/pwnagotchi/locale/rs/LC_MESSAGES/voice.po b/pwnagotchi/locale/rs/LC_MESSAGES/voice.po new file mode 100644 index 00000000..9622a6e1 --- /dev/null +++ b/pwnagotchi/locale/rs/LC_MESSAGES/voice.po @@ -0,0 +1,260 @@ +# 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 , 2024. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Srpski prevod v1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-02-16 15:26-0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: RS \n" +"Language: Serbian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "ZzzzZZzzzzZzzz" +msgstr "ZzzzZZzzzzZzzz" + +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Zdravo, ja sam Pwnagotchi! Započinjem ..." + +msgid "New day, new hunt, new pwns!" +msgstr "Novi dan, novi lov, novi pnwovi!" + +msgid "Hack the Planet!" +msgstr "Hakuj Planetu!" + +msgid "AI ready." +msgstr "AI spreman." + +msgid "The neural network is ready." +msgstr "Neuronska mreža je spremna." + +msgid "Generating keys, do not turn off ..." +msgstr "Generišem ključeve, ne isključuj me..." + +#, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Hej, kanal {channel} je slobodan! Tvoj AP će ti se zahvaliti." + +msgid "Reading last session logs ..." +msgstr "Čitanje logova poslednje sesije ..." + +#, python-brace-format +msgid "Read {lines_so_far} log lines so far ..." +msgstr "Pročitao {lines_so_far} log linija do sada ..." + +msgid "I'm bored ..." +msgstr "Dosadno mi je ..." + +msgid "Let's go for a walk!" +msgstr "Hajmo u šetnju!" + +msgid "This is the best day of my life!" +msgstr "Ovo je najbolji dan mog života!" + +msgid "Shitty day :/" +msgstr "Sranje dan :/" + +msgid "I'm extremely bored ..." +msgstr "Užasno mi je dosadno ..." + +msgid "I'm very sad ..." +msgstr "Jako sam tužan ..." + +msgid "I'm sad" +msgstr "Tužan sam" + +msgid "Leave me alone ..." +msgstr "Ostavi me na miru ..." + +msgid "I'm mad at you!" +msgstr "Ljut sam na tebe!" + +msgid "I'm living the life!" +msgstr "Živim ga!" + +msgid "I pwn therefore I am." +msgstr "Ja pwnujem dakle postojim." + +msgid "So many networks!!!" +msgstr "Tako mnogo mreža!!!" + +msgid "I'm having so much fun!" +msgstr "Previše se zabavljam!" + +msgid "My crime is that of curiosity ..." +msgstr "Moj zločin je radoznalost ..." + +#, python-brace-format +msgid "Hello {name}! Nice to meet you." +msgstr "Zdravo {name}! Drago mi je da te upoznam." + +#, python-brace-format +msgid "Yo {name}! Sup?" +msgstr "Ej {name}! Šta ima?" + +#, python-brace-format +msgid "Hey {name} how are you doing?" +msgstr "Hej {name} kako si?" + +#, python-brace-format +msgid "Unit {name} is nearby!" +msgstr "Jedinica {name} je blizu!" + +#, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Umm ... doviđenja {name}" + +#, python-brace-format +msgid "{name} is gone ..." +msgstr "{name} je nestao ..." + +#, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Ups ... {name} je nestao." + +#, python-brace-format +msgid "{name} missed!" +msgstr "{name} promašen!" + +msgid "Missed!" +msgstr "Promašen!" + +msgid "Good friends are a blessing!" +msgstr "Dobri prijatelji su blagoslov!" + +msgid "I love my friends!" +msgstr "Volim svoje prijatelje!" + +msgid "Nobody wants to play with me ..." +msgstr "Niko ne želi da se igra sa mnom ..." + +msgid "I feel so alone ..." +msgstr "Osećam se toliko usamljeno ..." + +msgid "Where's everybody?!" +msgstr "Gde su svi?!" + +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Dremam {secs}s ..." + +msgid "Zzzzz" +msgstr "Zzzzz" + +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "ZzzZzzz ({secs}s)" + +msgid "Good night." +msgstr "Laku noć." + +msgid "Zzz" +msgstr "Zzz" + +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Čekam {secs}s ..." + +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Gledam unaokolo ({secs}s)" + +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Hej {what} hajde da budemo prijatelji!" + +#, python-brace-format +msgid "Associating to {what}" +msgstr "Povezujem se sa {what}" + +#, python-brace-format +msgid "Yo {what}!" +msgstr "Ej {what}!" + +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Upravo sam odlučio da {mac} ne zahteva WiFi!" + +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Deauthenticating {mac}" + +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Kickbanning {mac}!" + +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Kul, imamo {num} novih handshakeova" + +#, python-brace-format +msgid "You have {count} new message{plural}!" +msgstr "Imas {count} novih poruka" + +msgid "Oops, something went wrong ... Rebooting ..." +msgstr "Ups, nešto je poslo po zlu ... Restartujem ..." + +#, python-brace-format +msgid "Uploading data to {to} ..." +msgstr "Otpremam podatke na {to} ..." + +#, python-brace-format +msgid "Downloading from {name} ..." +msgstr "Preuzimam od {name} ..." + +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Kickovano {num} stanica\n" + +msgid "Made >999 new friends\n" +msgstr "Stekao sam >999 novih prijatelja\n" + +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Stekao sam {num} novih prijatelja\n" + +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Imam {num} handshakeova\n" + +msgid "Met 1 peer" +msgstr "Sreo 1 peera" + +#, python-brace-format +msgid "Met {num} peers" +msgstr "Sreo {num} peerova" + +#, 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 "" +"Pwnujem već {duration} i kickovao sam {deauthed} klijenata! Takođe sam sreo " +"{associated} novih prijatelja i pojeo {handshakes} handshakeova! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "sati" + +msgid "minutes" +msgstr "minuta" + +msgid "seconds" +msgstr "sekundi" + +msgid "hour" +msgstr "sat" + +msgid "minute" +msgstr "minut" + +msgid "second" +msgstr "sekunda" From 8e99ae419dacf3850d706129d112fb533408c4dd Mon Sep 17 00:00:00 2001 From: jayofelony Date: Sun, 2 Jun 2024 12:47:51 +0200 Subject: [PATCH 32/39] Version 2.9.2 Signed-off-by: jayofelony --- .idea/deployment.xml | 19 +- Makefile | 17 +- builder/combined.json.pkr.hcl | 26 +- .../etc/NetworkManager/NetworkManager.conf | 5 + builder/data/32bit/etc/dhcpcd.conf | 62 --- .../32bit/etc/network/interfaces.d/eth0-cfg | 2 + .../32bit/etc/network/interfaces.d/lo-cfg | 2 + .../32bit/etc/network/interfaces.d/usb0-cfg | 8 + .../32bit/etc/network/interfaces.d/wlan0-cfg | 2 + builder/extras/nexmon.yml | 40 -- builder/raspberrypi32.json.pkr.hcl | 24 +- builder/raspberrypi32.yml | 478 ++++++++---------- builder/raspberrypi64.json.pkr.hcl | 8 +- builder/raspberrypi64.yml | 126 ++--- pwnagotchi/_version.py | 2 +- pyproject.toml | 6 +- requirements.txt | 4 +- 17 files changed, 324 insertions(+), 507 deletions(-) create mode 100644 builder/data/32bit/etc/NetworkManager/NetworkManager.conf delete mode 100644 builder/data/32bit/etc/dhcpcd.conf create mode 100644 builder/data/32bit/etc/network/interfaces.d/eth0-cfg create mode 100644 builder/data/32bit/etc/network/interfaces.d/lo-cfg create mode 100644 builder/data/32bit/etc/network/interfaces.d/usb0-cfg create mode 100644 builder/data/32bit/etc/network/interfaces.d/wlan0-cfg delete mode 100644 builder/extras/nexmon.yml diff --git a/.idea/deployment.xml b/.idea/deployment.xml index 7d23be04..3a8e62ab 100644 --- a/.idea/deployment.xml +++ b/.idea/deployment.xml @@ -1,23 +1,6 @@ - + \ No newline at end of file diff --git a/Makefile b/Makefile index e2786abf..14a71834 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PACKER_VERSION := 1.10.1 +PACKER_VERSION := 1.11.0 PWN_HOSTNAME := pwnagotchi PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py) @@ -26,7 +26,7 @@ UNSHARE := $(UNSHARE) --uts endif # sudo apt-get install qemu-user-static qemu-utils -all: clean packer image +all: packer image update_langs: @for lang in pwnagotchi/locale/*/; do\ @@ -40,22 +40,23 @@ compile_langs: ./scripts/language.sh compile $$(basename $$lang); \ done -packer: clean +packer: curl https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip -o /tmp/packer.zip - unzip /tmp/packer.zip -d /tmp + unzip -o /tmp/packer.zip -d /tmp sudo mv /tmp/packer /usr/bin/packer -image: clean packer +image: packer export LC_ALL=en_GB.UTF-8 cd builder && sudo /usr/bin/packer init combined.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" combined.json.pkr.hcl -bullseye: clean packer +32bit: packer export LC_ALL=en_GB.UTF-8 - cd builder && sudo /usr/bin/packer init raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi32.json.pkr.hcl + cd builder && sudo /usr/bin/packer init raspberrypi32.json.pkr.hcl && QEMU_CPU=arm1176 sudo -E $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi32.json.pkr.hcl -bookworm: clean packer +64bit: packer export LC_ALL=en_GB.UTF-8 cd builder && sudo /usr/bin/packer init raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi64.json.pkr.hcl clean: - rm -rf /tmp/packer* + - rm -rf /tmp/LICENSE.txt diff --git a/builder/combined.json.pkr.hcl b/builder/combined.json.pkr.hcl index 4186deeb..e4f0877f 100644 --- a/builder/combined.json.pkr.hcl +++ b/builder/combined.json.pkr.hcl @@ -25,7 +25,7 @@ source "arm" "rpi64-pwnagotchi" { file_checksum_type = "sha256" file_target_extension = "xz" file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] - image_path = "../pwnagotchi-64bit.img" + image_path = "../../../pwnagotchi-64bit.img" qemu_binary_source_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P" qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P" image_build_method = "resize" @@ -50,12 +50,12 @@ source "arm" "rpi64-pwnagotchi" { } source "arm" "rpi32-pwnagotchi" { - file_checksum_url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2024-03-12/2024-03-12-raspios-bullseye-armhf-lite.img.xz.sha256" - file_urls = ["https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2024-03-12/2024-03-12-raspios-bullseye-armhf-lite.img.xz"] + file_checksum_url = "https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf-lite.img.xz.sha256" + file_urls = ["https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf-lite.img.xz"] file_checksum_type = "sha256" file_target_extension = "xz" file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] - image_path = "../pwnagotchi-32bit.img" + image_path = "../../../pwnagotchi-32bit.img" qemu_binary_source_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" image_build_method = "resize" @@ -67,7 +67,7 @@ source "arm" "rpi32-pwnagotchi" { start_sector = "8192" filesystem = "fat" size = "256M" - mountpoint = "/boot" + mountpoint = "/boot/firmware" } image_partitions { name = "root" @@ -101,6 +101,13 @@ build { provisioner "shell" { inline = ["chmod +x /usr/bin/*"] } + provisioner "shell" { + inline = ["mkdir -p /usr/local/src/pwnagotchi"] + } + provisioner "file" { + destination = "/usr/local/src/pwnagotchi/" + source = "../" + } provisioner "file" { destination = "/etc/systemd/system/" @@ -142,10 +149,16 @@ build { "data/32bit/usr/bin/pwnlib", ] } + provisioner "shell" { + inline = ["mkdir -p /usr/local/src/pwnagotchi"] + } + provisioner "file" { + destination = "/usr/local/src/pwnagotchi/" + source = "../" + } provisioner "shell" { inline = ["chmod +x /usr/bin/*"] } - provisioner "file" { destination = "/etc/systemd/system/" sources = [ @@ -167,7 +180,6 @@ build { provisioner "ansible-local" { command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] - playbook_dir = "extras/" playbook_file = "raspberrypi32.yml" } } \ No newline at end of file diff --git a/builder/data/32bit/etc/NetworkManager/NetworkManager.conf b/builder/data/32bit/etc/NetworkManager/NetworkManager.conf new file mode 100644 index 00000000..3d2022a5 --- /dev/null +++ b/builder/data/32bit/etc/NetworkManager/NetworkManager.conf @@ -0,0 +1,5 @@ +[main] +plugins=keyfile,ifupdown + +[ifupdown] +managed=true diff --git a/builder/data/32bit/etc/dhcpcd.conf b/builder/data/32bit/etc/dhcpcd.conf deleted file mode 100644 index 90444ad0..00000000 --- a/builder/data/32bit/etc/dhcpcd.conf +++ /dev/null @@ -1,62 +0,0 @@ -# A sample configuration for dhcpcd. -# See dhcpcd.conf(5) for details. - -# Allow users of this group to interact with dhcpcd via the control socket. -#controlgroup wheel - -# Inform the DHCP server of our hostname for DDNS. -hostname - -# Use the hardware address of the interface for the Client ID. -clientid -# or -# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. -# Some non-RFC compliant DHCP servers do not reply with this set. -# In this case, comment out duid and enable clientid above. -#duid - -# Persist interface configuration when dhcpcd exits. -persistent - -# Rapid commit support. -# Safe to enable by default because it requires the equivalent option set -# on the server to actually work. -option rapid_commit - -# A list of options to request from the DHCP server. -option domain_name_servers, domain_name, domain_search, host_name -option classless_static_routes -# Respect the network MTU. This is applied to DHCP routes. -option interface_mtu - -# Most distributions have NTP support. -#option ntp_servers - -# A ServerID is required by RFC2131. -require dhcp_server_identifier - -# Generate SLAAC address using the Hardware Address of the interface -#slaac hwaddr -# OR generate Stable Private IPv6 Addresses based from the DUID -slaac private - -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# !! DO NOT EDIT THESE LINES BELOW PLEASE !! -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -# static IP configuration: -denyinterfaces wlan0 - -interface eth0 -static domain_name_servers=8.8.8.8 1.1.1.1 -metric 201 - -interface usb0 -static ip_address=10.0.0.2/24 -static routers=10.0.0.1 -static domain_name_servers=10.0.0.1 8.8.8.8 1.1.1.1 -metric 202 - -interface bnep0 -static domain_name_servers=8.8.8.8 1.1.1.1 -metric 203 \ No newline at end of file diff --git a/builder/data/32bit/etc/network/interfaces.d/eth0-cfg b/builder/data/32bit/etc/network/interfaces.d/eth0-cfg new file mode 100644 index 00000000..2166051a --- /dev/null +++ b/builder/data/32bit/etc/network/interfaces.d/eth0-cfg @@ -0,0 +1,2 @@ +allow-hotplug eth0 +iface eth0 inet dhcp \ No newline at end of file diff --git a/builder/data/32bit/etc/network/interfaces.d/lo-cfg b/builder/data/32bit/etc/network/interfaces.d/lo-cfg new file mode 100644 index 00000000..18ff4764 --- /dev/null +++ b/builder/data/32bit/etc/network/interfaces.d/lo-cfg @@ -0,0 +1,2 @@ +auto lo +iface lo inet loopback \ No newline at end of file diff --git a/builder/data/32bit/etc/network/interfaces.d/usb0-cfg b/builder/data/32bit/etc/network/interfaces.d/usb0-cfg new file mode 100644 index 00000000..3521780a --- /dev/null +++ b/builder/data/32bit/etc/network/interfaces.d/usb0-cfg @@ -0,0 +1,8 @@ +allow-hotplug usb0 +iface usb0 inet static + address 10.0.0.2 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + gateway 10.0.0.1 + metric 101 diff --git a/builder/data/32bit/etc/network/interfaces.d/wlan0-cfg b/builder/data/32bit/etc/network/interfaces.d/wlan0-cfg new file mode 100644 index 00000000..f5425694 --- /dev/null +++ b/builder/data/32bit/etc/network/interfaces.d/wlan0-cfg @@ -0,0 +1,2 @@ +allow-hotplug wlan0 +iface wlan0 inet static \ No newline at end of file diff --git a/builder/extras/nexmon.yml b/builder/extras/nexmon.yml deleted file mode 100644 index 6cdaafac..00000000 --- a/builder/extras/nexmon.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Install nexmon to fix wireless scanning (takes 2.5G of space) -- name: clone nexmon repository - git: - repo: https://github.com/DrSchottky/nexmon.git - dest: /usr/local/src/nexmon - -- name: make firmware - shell: "source ./setup_env.sh && make" - args: - executable: /bin/bash - chdir: /usr/local/src/nexmon/ - -- name: "make firmware patch ({{ item.name }})" - shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/{{ item.patch }}/nexmon/ && make" - args: - executable: /bin/bash - chdir: /usr/local/src/nexmon/ - environment: - QEMU_UNAME: "{{ item.kernel }}" - ARCHFLAGS: "{{ item.arch_flags }}" - -- name: "install new firmware ({{ item.name }})" - copy: - src: "/usr/local/src/nexmon/patches/{{ item.patch }}/nexmon/{{ item.firmware }}" - dest: "/usr/lib/firmware/brcm/{{ item.firmware }}" - follow: true - environment: - QEMU_UNAME: "{{ item.kernel }}" - ARCHFLAGS: "{{ item.arch_flags }}" - -- name: backup original driver - command: "mv /usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" - -- name: copy modified driver - copy: - src: "/usr/local/src/nexmon/patches/driver/brcmfmac_6.1.y-nexmon/brcmfmac.ko" - dest: "/usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko" - -- name : load brcmfmac drivers - command: "/sbin/depmod -a {{ item.kernel }}" diff --git a/builder/raspberrypi32.json.pkr.hcl b/builder/raspberrypi32.json.pkr.hcl index 0b7398bd..4880d521 100644 --- a/builder/raspberrypi32.json.pkr.hcl +++ b/builder/raspberrypi32.json.pkr.hcl @@ -1,8 +1,8 @@ packer { required_plugins { arm = { - version = "1.0.0" - source = "github.com/cdecoux/builder-arm" + version = ">=1.0.0" + source = "github.com/michalfita/cross" } ansible = { source = "github.com/hashicorp/ansible" @@ -20,12 +20,12 @@ variable "pwn_version" { } source "arm" "rpi32-pwnagotchi" { - file_checksum_url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2024-03-12/2024-03-12-raspios-bullseye-armhf-lite.img.xz.sha256" - file_urls = ["https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2024-03-12/2024-03-12-raspios-bullseye-armhf-lite.img.xz"] + file_checksum_url = "https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf-lite.img.xz.sha256" + file_urls = ["https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf-lite.img.xz"] file_checksum_type = "sha256" file_target_extension = "xz" file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] - image_path = "../../pwnagotchi-32bit.img" + image_path = "../../../pwnagotchi-32bit.img" qemu_binary_source_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" image_build_method = "resize" @@ -37,7 +37,7 @@ source "arm" "rpi32-pwnagotchi" { start_sector = "8192" filesystem = "fat" size = "256M" - mountpoint = "/boot" + mountpoint = "/boot/firmware" } image_partitions { name = "root" @@ -51,6 +51,9 @@ source "arm" "rpi32-pwnagotchi" { build { name = "Raspberry Pi 32 Pwnagotchi" sources = ["source.arm.rpi32-pwnagotchi"] + provisioner "shell" { + inline = ["uname -m"] + } provisioner "file" { destination = "/usr/bin/" sources = [ @@ -66,7 +69,13 @@ build { provisioner "shell" { inline = ["chmod +x /usr/bin/*"] } - + provisioner "shell" { + inline = ["mkdir -p /usr/local/src/pwnagotchi"] + } + provisioner "file" { + destination = "/usr/local/src/pwnagotchi/" + source = "../" + } provisioner "file" { destination = "/etc/systemd/system/" sources = [ @@ -88,7 +97,6 @@ build { provisioner "ansible-local" { command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] - playbook_dir = "extras/" playbook_file = "raspberrypi32.yml" } } \ No newline at end of file diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index cfdc1a3a..d4b1aaac 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -4,46 +4,15 @@ gather_facts: true become: true vars: - boards: - - { - kernel: "6.1.21+", - name: "PiZeroW", - firmware: "brcmfmac43430-sdio.bin", - patch: "bcm43430a1/7_45_41_46", - cpu: arm1176, - arch_flags: "-arch armv6l" - } - - { - kernel: "6.1.21-v7+", - name: "PiZero2W", - firmware: "brcmfmac43436-sdio.bin", - patch: "bcm43436b0/9_88_4_65", - cpu: any, #cortex-a53 - arch_flags: "-arch armv7l" - } - - { - kernel: "6.1.21-v7l+", - name: "Pi4b_32", - firmware: "brcmfmac43455-sdio.bin", - patch: "bcm43455c0/7_45_206", - cpu: any, #cortex-a72 - arch_flags: "-arch armv7l" - } kernel: - min: "6.1" - full: "6.1.21+" - full_2w: "6.1.21-v7+" - full_4b: "6.1.21-v7l+" - arch: "v6l" + min: "6.6" + full: "6.6.31+rpt-rpi-v6" pwnagotchi: hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" - version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}" - custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins" + version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}" services: enable: - bettercap.service - - bluetooth.service - - dphys-swapfile.service - fstrim.timer - pwnagotchi.service - pwngrid-peer.service @@ -52,25 +21,23 @@ - apt-daily-upgrade.timer - apt-daily.service - apt-daily.timer + - bluetooth.service - ifup@wlan0.service - - triggerhappy.service - - wpa_supplicant.service packages: caplets: source: "https://github.com/jayofelony/caplets.git" bettercap: source: "https://github.com/jayofelony/bettercap.git" - url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip" ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" pwngrid: source: "https://github.com/jayofelony/pwngrid.git" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" torch: - wheel: "torch-2.1.0a0+gitunknown-cp39-cp39-linux_armv6l.whl" - url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/v1.0.0/torch-2.1.0a0+gitunknown-cp39-cp39-linux_armv6l.whl" + wheel: "torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6ll.whl" + url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6l.whl" torchvision: - wheel: "torchvision-0.16.0a0-cp39-cp39-linux_armv6l.whl" - url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/v1.0.0/torchvision-0.16.0a0-cp39-cp39-linux_armv6l.whl" + wheel: "torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6ll.whl" + url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6l.whl" apt: downgrade: - libpcap-dev_1.9.1-4_armhf.deb @@ -85,111 +52,142 @@ - firmware-realtek - libpcap-dev - libpcap0.8 - - libpcap0.8-dev - libpcap0.8-dbg + - libpcap0.8-dev remove: - avahi-daemon - nfs-common - triggerhappy - wpasupplicant install: + - aircrack-ng - autoconf - - bc - bison - bluez - bluez-tools - build-essential - curl - - dkms - dphys-swapfile - - espeak-ng - - evtest - fbi + - firmware-atheros + - firmware-brcm80211 + - firmware-libertas + - firmware-misc-nonfree + - firmware-realtek - flex - - fonts-dejavu - - fonts-dejavu-core - - fonts-dejavu-extra - - fonts-freefont-ttf - g++ - gawk - gcc-arm-none-eabi - git - libatlas-base-dev - - libavcodec58 - - libavformat58 - - libblas-dev - - libbluetooth-dev - - libbz2-dev - - libc-ares-dev - libc6-dev - - libcpuinfo-dev - - libcurl4-openssl-dev + - libcurl-ocaml-dev - libdbus-1-dev - libdbus-glib-1-dev - - libeigen3-dev - - libelf-dev - - libffi-dev - libfl-dev - - libfuse-dev - - libgdbm-dev - - libgl1-mesa-glx - libgmp3-dev - - libgstreamer1.0-0 - - libhdf5-dev - - liblapack-dev - - libncursesw5-dev - libnetfilter-queue-dev - - libopenblas-dev - libopenjp2-7 - - libopenmpi-dev - - libopenmpi3 - libpcap-dev - - libprotobuf-dev - libraspberrypi-bin - libraspberrypi-dev - libraspberrypi-doc - libraspberrypi0 - - libsleef-dev - - libsqlite3-dev - libssl-dev - libssl-ocaml-dev - - libswscale5 - - libtiff5 - libtool - - libts-bin - libusb-1.0-0-dev - - lsof - make - ntp - - python3-dbus - - python3-flask - - python3-flask-cors - - python3-flaskext.wtf - - python3-pil + - pkg-config + - python3-dev - python3-pip - - python3-protobuf - - python3-smbus + - python3-setuptools - qpdf - raspberrypi-kernel-headers - rsync - - screen - tcpdump - texinfo - - time - - tk-dev - unzip - - vim - wget - wl - xxd - zlib1g-dev - + environment: + ARCHFLAGS: "-arch armv6l" + tasks: + # First we install packages + - name: install packages + apt: + name: "{{ packages.apt.install }}" + state: latest + update_cache: yes + install_recommends: no + + - name: update pip3, setuptools, wheel + shell: "python3 -m pip install --upgrade pip setuptools wheel --break-system-packages" + args: + executable: /bin/bash + chdir: /usr/local/src + + - name: install 32bit torch + shell: "python3 -m pip install {{ packages.torch.url }} {{ packages.torchvision.url }} --break-system-packages" + args: + executable: /bin/bash + environment: + QEMU_UNAME: "{{ kernel.full }}" + ARCHFLAGS: "-arch armv6l" + + # Now we set up /boot/firmware - name: Create pi user copy: - dest: /boot/userconf + dest: /boot/firmware/userconf content: | - pi:$6$3jNr0GA9KIyt4hmM$efeVIopdMQ8DGgEPCWWlbx3mJJNAYci1lEXGdlky0xPyjqwKNbwTL5SrCcpb4144C4IvzWjn7Iv.QjqmU7iyT/ + pi:$5$733Efsksay$SEFUKemv8FaNAu6X4GUfxdSzSDh6PbpOcdtNe5b7Nt0 + + - name: enable ssh on boot + file: + path: /boot/firmware/ssh + state: touch + + - name: remove current rc.local + file: + path: /etc/rc.local + state: absent + + - name: change root partition + replace: + dest: /boot/firmware/cmdline.txt + backup: no + regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+" + replace: "root=/dev/mmcblk0p2" + + - name: configure /boot/firmware/cmdline.txt + lineinfile: + path: /boot/firmware/cmdline.txt + backrefs: True + state: present + backup: no + regexp: '(.*)$' + line: '\1 modules-load=dwc2,g_ether' + + - name: setup /boot/firmware/config.txt + blockinfile: + path: /boot/firmware/config.txt + insertafter: EOF + block: | + dtparam=i2c1=on + dtparam=i2c_arm=on + dtparam=spi=on + gpu_mem=1 + dtoverlay=dwc2 + #dtoverlay=disable-wifi + enable_uart=1 + + [pi0] + dtoverlay=spi0-0cs + #dtoverlay=disable-wifi - name: change hostname lineinfile: @@ -208,55 +206,14 @@ state: present when: hostname.changed - - name: setup /boot/config.txt - blockinfile: - path: /boot/config.txt - insertafter: EOF - block: | - dtparam=i2c1=on - dtparam=i2c_arm=on - dtparam=spi=on - gpu_mem=1 - dtoverlay=dwc2 - #dtoverlay=disable-wifi - - [pi0] - dtoverlay=spi0-0cs - #dtoverlay=disable-wifi - - [pi3] - dtoverlay=spi0-0cs - #dtoverlay=disable-wifi - - [pi4] - dtoverlay=spi0-0cs - #dtoverlay=disable-wifi - - - name: Create custom plugin directory - file: - path: '{{ pwnagotchi.custom_plugin_dir }}' - state: directory - - - name: remove current rc.local - file: - path: /etc/rc.local - state: absent - - - name: update apt package cache - apt: - update_cache: yes - - - name: install packages - apt: - name: "{{ packages.apt.install }}" + # Now we disable sap and a2dp, we don't use them on rpi + - name: disable sap plugin for bluetooth.service + lineinfile: + dest: /lib/systemd/system/bluetooth.service + regexp: '^ExecStart=/usr/libexec/bluetooth/bluetoothd$' + line: 'ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap,a2dp' state: present - - name: update pip3, setuptools, wheel - shell: "python3 -m pip install --upgrade pip setuptools wheel" - args: - executable: /bin/bash - chdir: /usr/local/src - ########################################### # # libpcap v1.9 - build from source @@ -291,34 +248,60 @@ state: link # install latest hcxtools + - name: clone hcxtools + git: + repo: https://github.com/ZerBea/hcxtools.git + dest: /usr/local/src/hcxtools - #- name: clone hcxtools - # git: - # repo: https://github.com/ZerBea/hcxtools.git - # dest: /usr/local/src/hcxtools + - name: install hcxtools + shell: "make && make install" + args: + executable: /bin/bash + chdir: /usr/local/src/hcxtools - #- name: install hcxtools - # shell: "make && make install" - # args: - # executable: /bin/bash - # chdir: /usr/local/src/hcxtools + - name: remove hcxtools directory + file: + state: absent + path: /usr/local/src/hcxtools - #- name: remove hcxtools directory - # file: - # state: absent - # path: /usr/local/src/hcxtools + # Installing nexmon + - name: clone nexmon repository + git: + repo: https://github.com/DrSchottky/nexmon.git + dest: /usr/local/src/nexmon - ############################################################### - # Install nexmon to fix wireless scanning (takes 2.5G of space) - ############################################################### + - name: make firmware + shell: "source ./setup_env.sh && make" + args: + executable: /bin/bash + chdir: /usr/local/src/nexmon/ + environment: + QEMU_UNAME: "{{ kernel.full }}" + ARCHFLAGS: "-arch armv6l" - # Install nexmon for all boards - - name: build and install nexmon as needed - include_tasks: nexmon.yml - loop: "{{ boards }}" + - name: make firmware patch (bcm43430a1) + shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/ && make" + args: + executable: /bin/bash + chdir: /usr/local/src/nexmon/ + environment: + QEMU_UNAME: "{{ kernel.full }}" + ARCHFLAGS: "-arch armv6l" + + - name: install new firmware (bcm43430a1) + copy: + src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin + dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin + follow: true + + - name: copy modified driver + copy: + src: "/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko" + dest: "/usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko" + environment: + QEMU_UNAME: "{{ kernel.full }}" + ARCHFLAGS: "-arch armv6l" - # some pizero2w have the pizeroW wifi chip - # could this be a link instead of a copy? and force, only if not a link? - name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2 copy: src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin @@ -333,9 +316,19 @@ loop: - /usr/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43430b0-sdio.raspberrypi,model-zero-2-w.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob - /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.clm_blob + - /usr/lib/firmware/brcm/brcmfmac43430b0-sdio.raspberrypi,model-zero-2-w.clm_blob + - /usr/lib/firmware/brcm/brcmfmac43436-sdio.clm_blob + - /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob + - /usr/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob + + - name: backup original driver + command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" + + - name: load brcmfmac drivers + command: "/sbin/depmod {{ kernel.full }}" + environment: + QEMU_UNAME: "{{ kernel.full }}" # To shrink the final image, remove the nexmon directory (takes 2.5G of space) post build and installation - name: Delete nexmon content & directory @@ -343,58 +336,36 @@ state: absent path: /usr/local/src/nexmon/ - - name: clone pwnagotchi repository - git: - repo: https://github.com/jayofelony/pwnagotchi.git - dest: /usr/local/src/pwnagotchi - register: pwnagotchigit + - name: Create custom config directory + file: + path: /etc/pwnagotchi/conf.d/ + state: directory + + #- name: clone pwnagotchi repository + # git: + # repo: https://github.com/jayofelony/pwnagotchi.git + # dest: /usr/local/src/pwnagotchi - # is this even necessary? Can't we just link from /home/pi/pwnagotchi to /usr/local/{bin,lib,etc} - # then just git update in the home dir and encourage hacking? - # make owned by pi.pi, and custom plugins. - name: build pwnagotchi wheel - command: "python3 setup.py sdist bdist_wheel" + command: "pip3 install . --no-cache-dir --break-system-packages" args: chdir: /usr/local/src/pwnagotchi - when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version) - - - name: download torch whl - get_url: - url: "{{ packages.torch.url }}" - dest: /usr/local/src/ - - - name: download torchvision whl - get_url: - url: "{{ packages.torchvision.url }}" - dest: /usr/local/src/ - - - name: install 32-bit pwnagotchi wheel and dependencies with 32-bit torch wheels - pip: - name: - - "{{ lookup('fileglob', '/usr/local/src/pwnagotchi/dist/pwnagotchi*.whl') }}" - - "{{ packages.torch.url }}" - - "{{ packages.torchvision.url }}" - extra_args: "--no-cache-dir" - environment: - QEMU_CPU: arm1176 - QEMU_UNAME: "{{ kernel.full }}" - when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version) - name: create /usr/local/share/pwnagotchi/ folder file: path: /usr/local/share/pwnagotchi/ state: directory + - name: Create custom plugin directory + file: + path: /usr/local/share/pwnagotchi/custom-plugins/ + state: directory + - name: remove pwnagotchi folder file: state: absent path: /usr/local/src/pwnagotchi - - name: remove torch whl - file: - state: absent - path: "{{ lookup('fileglob', '/usr/local/src/torch*.whl') }}" - ########################################## # # pwngrid, bettercap @@ -403,14 +374,14 @@ - name: Install go-1.21 unarchive: - src: https://go.dev/dl/go1.21.6.linux-armv6l.tar.gz + src: https://go.dev/dl/go1.22.3.linux-armv6l.tar.gz dest: /usr/local remote_src: yes register: golang - name: Update .bashrc for go-1.21 blockinfile: - dest: /home/pi/.bashrc + dest: /etc/profile state: present block: | export GOPATH=$HOME/go @@ -449,6 +420,16 @@ state: absent path: /usr/local/src/bettercap + #- name: download and install bettercap + # unarchive: + # src: "{{ packages.bettercap.url }}" + # dest: /usr/local/bin + # remote_src: yes + # exclude: + # - README.md + # - LICENSE.md + # mode: 0755 + - name: clone bettercap caplets git: repo: "{{ packages.caplets.source }}" @@ -481,11 +462,6 @@ path: /etc/pwnagotchi state: directory - - name: create log folder - file: - path: /home/pi/logs - state: directory - - name: check if user configuration exists stat: path: /etc/pwnagotchi/config.toml @@ -501,32 +477,16 @@ # ui.display.type = "waveshare_4" when: not user_config.stat.exists + - name: Delete motd + file: + state: absent + path: /etc/motd + - name: Delete motd 10-uname file: state: absent path: /etc/update-motd.d/10-uname - - name: enable ssh on boot - file: - path: /boot/ssh - state: touch - - - name: change root partition - replace: - dest: /boot/cmdline.txt - backup: no - regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+" - replace: "root=/dev/mmcblk0p2" - - - name: configure /boot/cmdline.txt - lineinfile: - path: /boot/cmdline.txt - backrefs: True - state: present - backup: no - regexp: '(.*)$' - line: '\1 modules-load=dwc2,g_ether' - - name: add firmware packages to hold dpkg_selections: name: "{{ item }}" @@ -546,16 +506,7 @@ enabled: true state: stopped with_items: "{{ services.enable }}" - - #- name: remove golang build libraries - # file: - # state: absent - # path: /root/go - - #- name: remove golang - # file: - # state: absent - # path: /usr/local/go + register: enabled - name: make /root readable, becauase that's where all the files are file: @@ -569,53 +520,58 @@ group: pi recurse: true - - name: remove unnecessary apt packages - apt: - name: "{{ packages.apt.remove }}" - state: absent - purge: yes - - - name: remove dependencies that are no longer required - apt: - autoremove: yes - - - name: clean apt cache - apt: - autoclean: true - - - name: remove golang build libraries - file: - state: absent - path: /root/go - - name: remove pre-collected packages zip file: path: /root/go_pkgs.tgz state: absent - - name: remove golang + - name: remove /root/go folder + file: + state: absent + path: /root/go + + - name: remove /usr/local/go folder file: state: absent path: /usr/local/go - - name: remove /root/.cache (pip cache) + - name: remove pip cache file: state: absent - path: /root/.cache + path: /root/.cache/pip - name: remove ssh keys file: state: absent path: "{{ item }}" with_fileglob: - - "/etc/ssh/ssh_host*_key*" + - "/etc/ssh/ssh_host*_key*" - name: regenerate ssh keys shell: "dpkg-reconfigure openssh-server" args: executable: /bin/bash + # Now we remove packages + - name: remove unnecessary apt packages + apt: + name: "{{ packages.apt.remove }}" + state: absent + purge: yes + register: removed + + - name: remove dependencies that are no longer required + apt: + autoremove: yes + when: removed.changed + + - name: clean apt cache + apt: + autoclean: true + when: removed.changed + handlers: - name: reload systemd services systemd: daemon_reload: yes + when: enabled.changed \ No newline at end of file diff --git a/builder/raspberrypi64.json.pkr.hcl b/builder/raspberrypi64.json.pkr.hcl index 5d0ff792..3d7c2e04 100644 --- a/builder/raspberrypi64.json.pkr.hcl +++ b/builder/raspberrypi64.json.pkr.hcl @@ -73,7 +73,13 @@ build { provisioner "shell" { inline = ["chmod +x /usr/bin/*"] } - + provisioner "shell" { + inline = ["mkdir -p /usr/local/src/pwnagotchi"] + } + provisioner "file" { + destination = "/usr/local/src/pwnagotchi/" + source = "../" + } provisioner "file" { destination = "/etc/systemd/system/" sources = [ diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 11f1a027..2b7fb36a 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -6,8 +6,8 @@ vars: kernel: min: "6.6" - full: "6.6.20+rpt-rpi-v8" - full_pi5: "6.6.20+rpt-rpi-2712" + full: "6.6.31+rpt-rpi-v8" + full_pi5: "6.6.31+rpt-rpi-2712" pwnagotchi: hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}" @@ -53,21 +53,17 @@ remove: - avahi-daemon - dhpys-swapfile - - libcurl-ocaml-dev - - libssl-ocaml-dev - nfs-common - triggerhappy - wpasupplicant install: - aircrack-ng - autoconf - - bc - bison - bluez - bluez-tools - build-essential - curl - - dkms - dphys-swapfile - fbi - firmware-atheros @@ -76,86 +72,38 @@ - firmware-misc-nonfree - firmware-realtek - flex - - fonts-dejavu - - fonts-dejavu-core - - fonts-dejavu-extra - - fonts-freefont-ttf - g++ - gawk - gcc-arm-none-eabi - git - - hcxtools - - libatlas-base-dev - - libavcodec59 - - libavformat59 - - libblas-dev - - libbluetooth-dev - - libbz2-dev - - libc-ares-dev - libc6-dev - - libcap-dev - libcurl-ocaml-dev - libdbus-1-dev - libdbus-glib-1-dev - - libeigen3-dev - - libelf-dev - - libffi-dev - libfl-dev - - libfuse-dev - - libgdbm-dev - - libgl1-mesa-glx - libgmp3-dev - - libgstreamer1.0-0 - - libhdf5-dev - - liblapack-dev - - libncursesw5-dev - libnetfilter-queue-dev - - libopenblas-dev - - libopenjp2-7 - - libopenmpi-dev - - libopenmpi3 - libpcap-dev - libraspberrypi-bin - libraspberrypi-dev - libraspberrypi-doc - libraspberrypi0 - - libsqlite3-dev - libssl-dev - libssl-ocaml-dev - - libswscale5 - - libtiff6 - libtool - libusb-1.0-0-dev - - lsof - make - ntp - - python3-dbus - - python3-flask - - python3-flask-cors - - python3-flaskext.wtf - - python3-gast - - python3-pil + - pkg-config + - python3-dev - python3-pip - - python3-pycryptodome - - python3-requests - - python3-scapy - python3-setuptools - - python3-smbus - - python3-smbus2 - - python3-spidev - - python3-tweepy - - python3-werkzeug - - python3-yaml - qpdf - raspberrypi-kernel-headers - rsync - - screen - tcpdump - texinfo - - time - - tk-dev - unzip - - vim - wget - wl - xxd @@ -168,9 +116,9 @@ - name: install packages apt: name: "{{ packages.apt.install }}" - state: present + state: latest update_cache: yes - install_recommends: false + install_recommends: no - name: update pip3, setuptools, wheel shell: "python3 -m pip install --upgrade pip setuptools wheel --break-system-packages" @@ -178,12 +126,22 @@ executable: /bin/bash chdir: /usr/local/src + - name: build pwnagotchi wheel + command: "pip3 install . --no-cache-dir --break-system-packages" + args: + chdir: /usr/local/src/pwnagotchi + + - name: remove pwnagotchi folder + file: + state: absent + path: /usr/local/src/pwnagotchi + # Now we set up /boot/firmware - name: Create pi user copy: dest: /boot/firmware/userconf content: | - pi:$6$3jNr0GA9KIyt4hmM$efeVIopdMQ8DGgEPCWWlbx3mJJNAYci1lEXGdlky0xPyjqwKNbwTL5SrCcpb4144C4IvzWjn7Iv.QjqmU7iyT/ + pi:$5$733Efsksay$SEFUKemv8FaNAu6X4GUfxdSzSDh6PbpOcdtNe5b7Nt0 - name: enable ssh on boot file: @@ -222,6 +180,7 @@ gpu_mem=1 dtoverlay=dwc2 #dtoverlay=disable-wifi + enable_uart=1 [pi0] dtoverlay=spi0-0cs @@ -298,7 +257,6 @@ state: link # install latest hcxtools - - name: clone hcxtools git: repo: https://github.com/ZerBea/hcxtools.git @@ -315,13 +273,13 @@ state: absent path: /usr/local/src/hcxtools + # Installing nexmon - name: clone nexmon repository git: repo: https://github.com/DrSchottky/nexmon.git dest: /usr/local/src/nexmon # FIRST WE BUILD DRIVER FOR RPi5 - - name: make firmware, RPi5 shell: "source ./setup_env.sh && make" args: @@ -348,11 +306,6 @@ QEMU_UNAME: "{{ kernel.full_pi5 }}" ARCHFLAGS: "-arch aarch64" - - name: Delete the modified driver, RPi5 - file: - state: absent - path: '/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko' - - name: backup original driver, RPi5 command: "mv /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" @@ -367,7 +320,6 @@ path: /usr/local/src/nexmon/ # NOW WE BUILD DRIVERS FOR RPi4, RPizero2w and RPi3 - - name: clone nexmon repository git: repo: https://github.com/DrSchottky/nexmon.git @@ -398,7 +350,6 @@ follow: true # NOW WE BUILD DRIVERS FOR RPiZero2W, RPi 3 - - name: make firmware patch (bcm43436b0) shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/ && make" args: @@ -423,6 +374,12 @@ QEMU_UNAME: "{{ kernel.full }}" ARCHFLAGS: "-arch aarch64" + - name: install new firmware (bcm43430a1) + copy: + src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin + dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin + follow: true + - name: copy modified driver, RPi4 copy: src: "/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko" @@ -431,12 +388,6 @@ QEMU_UNAME: "{{ kernel.full }}" ARCHFLAGS: "-arch aarch64" - - name: install new firmware (bcm43430a1) - copy: - src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin - dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin - follow: true - - name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2 copy: src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin @@ -471,39 +422,24 @@ state: absent path: /usr/local/src/nexmon/ - - name: Create custom plugin directory - file: - path: /usr/local/share/pwnagotchi/custom-plugins/ - state: directory - - name: Create custom config directory file: path: /etc/pwnagotchi/conf.d/ state: directory - - name: clone pwnagotchi repository - git: - repo: https://github.com/jayofelony/pwnagotchi.git - dest: /usr/local/src/pwnagotchi - - - name: build pwnagotchi wheel - command: "pip3 install . --no-cache-dir --break-system-packages" - args: - chdir: /usr/local/src/pwnagotchi - - - name: remove pwnagotchi folder - file: - state: absent - path: /usr/local/src/pwnagotchi - - name: create /usr/local/share/pwnagotchi/ folder file: path: /usr/local/share/pwnagotchi/ state: directory + - name: Create custom plugin directory + file: + path: /usr/local/share/pwnagotchi/custom-plugins/ + state: directory + - name: Install go-1.21 unarchive: - src: https://go.dev/dl/go1.21.5.linux-arm64.tar.gz + src: https://go.dev/dl/go1.22.3.linux-arm64.tar.gz dest: /usr/local remote_src: yes register: golang diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py index c2d9c8e1..c0d35b3f 100644 --- a/pwnagotchi/_version.py +++ b/pwnagotchi/_version.py @@ -1 +1 @@ -__version__ = '2.9.1.2' +__version__ = '2.9.2' diff --git a/pyproject.toml b/pyproject.toml index 834dcb47..be0a33da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] dependencies = [ "Pillow", "PyYAML", - "RPi.GPIO", + "rpi.lgpio", "dbus-python", "file-read-backwards", "flask", @@ -29,8 +29,8 @@ dependencies = [ "spidev", "stable_baselines3", "toml", - "torch", - "torchvision", + "torch; platform_machine=='aarch64'", + "torchvision; platform_machine=='aarch64'", "tweepy", "websockets", ] diff --git a/requirements.txt b/requirements.txt index ab51bdcb..e7714400 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,9 +18,7 @@ dbus-python toml python-dateutil websockets -torch -torchvision stable_baselines3 -RPi.GPIO +rpi-lgpio rpi_hardware_pwm pydrive2 \ No newline at end of file From ed62ac0b84de25b2d0bad9981ffb5cc9114120a3 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Mon, 3 Jun 2024 20:06:32 +0200 Subject: [PATCH 33/39] Version 2.9.2 Signed-off-by: jayofelony --- builder/raspberrypi32.yml | 9 ++++++--- builder/raspberrypi64.json.pkr.hcl | 4 ++-- builder/raspberrypi64.yml | 2 +- pwnagotchi/plugins/default/fix_services.py | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index d4b1aaac..dbc47968 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -33,10 +33,10 @@ source: "https://github.com/jayofelony/pwngrid.git" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" torch: - wheel: "torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6ll.whl" + wheel: "torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6l.whl" url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6l.whl" torchvision: - wheel: "torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6ll.whl" + wheel: "torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6l.whl" url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6l.whl" apt: downgrade: @@ -55,7 +55,6 @@ - libpcap0.8-dbg - libpcap0.8-dev remove: - - avahi-daemon - nfs-common - triggerhappy - wpasupplicant @@ -81,18 +80,21 @@ - git - libatlas-base-dev - libc6-dev + - libcpuinfo-dev - libcurl-ocaml-dev - libdbus-1-dev - libdbus-glib-1-dev - libfl-dev - libgmp3-dev - libnetfilter-queue-dev + - libopenblas-dev # https://stackoverflow.com/questions/14570011/explain-why-numpy-should-not-be-imported-from-source-directory - libopenjp2-7 - libpcap-dev - libraspberrypi-bin - libraspberrypi-dev - libraspberrypi-doc - libraspberrypi0 + - libsleef-dev - libssl-dev - libssl-ocaml-dev - libtool @@ -102,6 +104,7 @@ - pkg-config - python3-dev - python3-pip + - python3-protobuf - python3-setuptools - qpdf - raspberrypi-kernel-headers diff --git a/builder/raspberrypi64.json.pkr.hcl b/builder/raspberrypi64.json.pkr.hcl index 3d7c2e04..1e22695d 100644 --- a/builder/raspberrypi64.json.pkr.hcl +++ b/builder/raspberrypi64.json.pkr.hcl @@ -1,8 +1,8 @@ packer { required_plugins { arm = { - version = "1.0.0" - source = "github.com/cdecoux/builder-arm" + version = ">=1.0.0" + source = "github.com/michalfita/cross" } ansible = { source = "github.com/hashicorp/ansible" diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 2b7fb36a..75d50b21 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -51,7 +51,6 @@ - libpcap0.8-dbg - libpcap0.8-dev remove: - - avahi-daemon - dhpys-swapfile - nfs-common - triggerhappy @@ -407,6 +406,7 @@ - /usr/lib/firmware/brcm/brcmfmac43436-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob - /usr/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob + - /usr/lib/firmware/brcm/BCM43430A1.raspberrypi,model-zero-2-w.hcd - name: backup original driver command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" diff --git a/pwnagotchi/plugins/default/fix_services.py b/pwnagotchi/plugins/default/fix_services.py index 16c9b77c..6f23df26 100644 --- a/pwnagotchi/plugins/default/fix_services.py +++ b/pwnagotchi/plugins/default/fix_services.py @@ -106,7 +106,7 @@ class FixServices(plugins.Plugin): other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10'], stdout=subprocess.PIPE).stdout))[-10:]) other_other_last_lines = ''.join( - list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/var/log/pwnagotchi.log'], + list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/etc/pwnagotchi/log/pwnagotchi.log'], stdout=subprocess.PIPE).stdout))[-10:]) # don't check if we ran a reset recently logging.debug("[Fix_Services]**** epoch") From 20bae7adaa67b20dd9fb2b9d1c5826a724de0ca4 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Mon, 3 Jun 2024 21:49:57 +0200 Subject: [PATCH 34/39] Version 2.9.2 Signed-off-by: jayofelony --- builder/raspberrypi32.yml | 5 ----- pwnagotchi/plugins/default/grid.py | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index dbc47968..9f743d79 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -319,11 +319,6 @@ loop: - /usr/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43430b0-sdio.raspberrypi,model-zero-2-w.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43436-sdio.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob - - /usr/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob - name: backup original driver command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py index 9c24ed53..55f90b21 100644 --- a/pwnagotchi/plugins/default/grid.py +++ b/pwnagotchi/plugins/default/grid.py @@ -47,7 +47,7 @@ class Grid(plugins.Plugin): __version__ = '1.0.1' __license__ = 'GPL3' __description__ = 'This plugin signals the unit cryptographic identity and list of pwned networks and list of pwned ' \ - 'networks to api.pwnagotchi.ai ' + 'networks to opwngrid.xyz ' def __init__(self): self.options = dict() From cbc601e38bc332bce0ff371b5246ed5787308f24 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 5 Jun 2024 10:50:15 +0200 Subject: [PATCH 35/39] Updated displays Signed-off-by: jayofelony --- .../ui/hw/libs/waveshare/epaper/epdconfig.py | 52 +++++- .../waveshare/epaper/v2in7_v2/epd2in7_V2.py | 4 +- .../waveshare/epaper/v4in2b_v2/epd4in2b_V2.py | 171 ++++++++++++++---- 3 files changed, 179 insertions(+), 48 deletions(-) diff --git a/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py b/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py index 91e59855..75e1d1a0 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py +++ b/pwnagotchi/ui/hw/libs/waveshare/epaper/epdconfig.py @@ -31,6 +31,9 @@ import os import logging import sys import time +import subprocess + +from ctypes import * logger = logging.getLogger(__name__) @@ -42,6 +45,8 @@ class RaspberryPi: CS_PIN = 8 BUSY_PIN = 24 PWR_PIN = 18 + MOSI_PIN = 10 + SCLK_PIN = 11 def __init__(self): import spidev @@ -97,13 +102,45 @@ class RaspberryPi: def spi_writebyte2(self, data): self.SPI.writebytes2(data) - def module_init(self): + def DEV_SPI_write(self, data): + self.DEV_SPI.DEV_SPI_SendData(data) + + def DEV_SPI_nwrite(self, data): + self.DEV_SPI.DEV_SPI_SendnData(data) + + def DEV_SPI_read(self): + return self.DEV_SPI.DEV_SPI_ReadData() + + def module_init(self, cleanup=False): self.GPIO_PWR_PIN.on() - # SPI device, bus = 0, device = 0 - self.SPI.open(0, 0) - self.SPI.max_speed_hz = 4000000 - self.SPI.mode = 0b00 + if cleanup: + find_dirs = [ + os.path.dirname(os.path.realpath(__file__)), + '/usr/local/lib', + '/usr/lib', + ] + self.DEV_SPI = None + for find_dir in find_dirs: + val = int(os.popen('getconf LONG_BIT').read()) + logging.debug("System is %d bit" % val) + if val == 64: + so_filename = os.path.join(find_dir, 'DEV_Config_64.so') + else: + so_filename = os.path.join(find_dir, 'DEV_Config_32.so') + if os.path.exists(so_filename): + self.DEV_SPI = CDLL(so_filename) + break + if self.DEV_SPI is None: + RuntimeError('Cannot find DEV_Config.so') + + self.DEV_SPI.DEV_Module_Init() + + else: + # SPI device, bus = 0, device = 0 + self.SPI.open(0, 0) + self.SPI.max_speed_hz = 4000000 + self.SPI.mode = 0b00 return 0 def module_exit(self, cleanup=False): @@ -112,7 +149,6 @@ class RaspberryPi: self.GPIO_RST_PIN.off() self.GPIO_DC_PIN.off() - self.GPIO_CS_PIN.off() self.GPIO_PWR_PIN.off() logger.debug("close 5V, Module enters 0 power consumption ...") @@ -127,6 +163,4 @@ class RaspberryPi: implementation = RaspberryPi() for func in [x for x in dir(implementation) if not x.startswith('_')]: - setattr(sys.modules[__name__], func, getattr(implementation, func)) - -### END OF FILE ### \ No newline at end of file + setattr(sys.modules[__name__], func, getattr(implementation, func)) \ No newline at end of file diff --git a/pwnagotchi/ui/hw/libs/waveshare/epaper/v2in7_v2/epd2in7_V2.py b/pwnagotchi/ui/hw/libs/waveshare/epaper/v2in7_v2/epd2in7_V2.py index c12e2650..951d4d0b 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/epaper/v2in7_v2/epd2in7_V2.py +++ b/pwnagotchi/ui/hw/libs/waveshare/epaper/v2in7_v2/epd2in7_V2.py @@ -446,7 +446,7 @@ class EPD: def display_4Gray(self, image): self.send_command(0x24) - for i in range(0, 48000): # 5808*4 46464 + for i in range(0, 5808): # 5808*4 46464 temp3 = 0 for j in range(0, 2): temp1 = image[i * 2 + j] @@ -478,7 +478,7 @@ class EPD: self.send_data(temp3) self.send_command(0x26) - for i in range(0, 48000): # 5808*4 46464 + for i in range(0, 5808): # 5808*4 46464 temp3 = 0 for j in range(0, 2): temp1 = image[i * 2 + j] diff --git a/pwnagotchi/ui/hw/libs/waveshare/epaper/v4in2b_v2/epd4in2b_V2.py b/pwnagotchi/ui/hw/libs/waveshare/epaper/v4in2b_v2/epd4in2b_V2.py index 7843f829..a3745135 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/epaper/v4in2b_v2/epd4in2b_V2.py +++ b/pwnagotchi/ui/hw/libs/waveshare/epaper/v4in2b_v2/epd4in2b_V2.py @@ -28,7 +28,7 @@ # import logging -from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig +from .. import epdconfig # Display resolution EPD_WIDTH = 400 @@ -45,6 +45,10 @@ class EPD: self.cs_pin = epdconfig.CS_PIN self.width = EPD_WIDTH self.height = EPD_HEIGHT + self.flag = 0 + + if (epdconfig.module_init(cleanup=True) != 0): + return -1 # Hardware reset def reset(self): @@ -58,13 +62,13 @@ class EPD: def send_command(self, command): epdconfig.digital_write(self.dc_pin, 0) epdconfig.digital_write(self.cs_pin, 0) - epdconfig.spi_writebyte([command]) + epdconfig.DEV_SPI_write(command) epdconfig.digital_write(self.cs_pin, 1) def send_data(self, data): epdconfig.digital_write(self.dc_pin, 1) epdconfig.digital_write(self.cs_pin, 0) - epdconfig.spi_writebyte([data]) + epdconfig.DEV_SPI_write(data) epdconfig.digital_write(self.cs_pin, 1) # send a lot of data @@ -76,23 +80,77 @@ class EPD: def ReadBusy(self): logger.debug("e-Paper busy") - self.send_command(0x71) - while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy - self.send_command(0x71) - epdconfig.delay_ms(20) + if (self.flag == 1): + while (epdconfig.digital_read(self.busy_pin) == 1): + epdconfig.delay_ms(100) + + else: + while (epdconfig.digital_read(self.busy_pin) == 0): + epdconfig.delay_ms(100) logger.debug("e-Paper busy release") + def TurnOnDisplay(self): + if (self.flag == 1): + self.send_command(0x22) + self.send_data(0xF7) + self.send_command(0x20) + self.ReadBusy() + + else: + self.send_command(0x12) + epdconfig.delay_ms(100) + self.ReadBusy() + def init(self): - if (epdconfig.module_init() != 0): - return -1 - + i = 0x00 self.reset() + self.send_command(0x2F) + epdconfig.delay_ms(100) + epdconfig.digital_write(self.dc_pin, 1) + epdconfig.digital_write(self.cs_pin, 0) + i = epdconfig.DEV_SPI_read() + epdconfig.digital_write(self.cs_pin, 1) + # print(i) - self.send_command(0x04); - self.ReadBusy(); + if (i == 0x01): + self.flag = 1 + self.ReadBusy() + self.send_command(0x12) + self.ReadBusy() - self.send_command(0x00); - self.send_data(0x0f); + self.send_command(0x3C) + self.send_data(0x05) + + self.send_command(0x18) + self.send_data(0x80) + + self.send_command(0x11) + self.send_data(0x03) + + self.send_command(0x44) + self.send_data(0x00) + self.send_data(self.width // 8 - 1) + + self.send_command(0x45) + self.send_data(0x00) + self.send_data(0x00) + self.send_data((self.height - 1) % 256) + self.send_data((self.height - 1) // 256) + + self.send_command(0x4E) + self.send_data(0x00) + self.send_command(0x4F) + self.send_data(0x00) + self.send_data(0x00) + self.ReadBusy() + + else: + self.flag = 0 + self.send_command(0x04) # POWER_ON + self.ReadBusy() + + self.send_command(0x00) # panel setting + self.send_data(0x0f) return 0 @@ -121,40 +179,79 @@ class EPD: return buf def display(self, imageblack, imagered): - self.send_command(0x10) - self.send_data2(imageblack) + high = self.height + if (self.width % 8 == 0): + wide = self.width // 8 + else: + wide = self.width // 8 + 1 - self.send_command(0x13) - self.send_data2(imagered) + if (self.flag == 1): + self.send_command(0x24) + for j in range(0, high): + for i in range(0, wide): + self.send_data(imageblack[i + j * wide]) - self.send_command(0x12) - epdconfig.delay_ms(20) - self.ReadBusy() + self.send_command(0x26) + for j in range(0, high): + for i in range(0, wide): + self.send_data(~imagered[i + j * wide]) + + else: + self.send_command(0x10) + for j in range(0, high): + for i in range(0, wide): + self.send_data(imageblack[i + j * wide]) + + self.send_command(0x13) + for j in range(0, high): + for i in range(0, wide): + self.send_data(imagered[i + j * wide]) + + self.TurnOnDisplay() def Clear(self): - if self.width % 8 == 0: - linewidth = int(self.width / 8) + high = self.height + if (self.width % 8 == 0): + wide = self.width // 8 else: - linewidth = int(self.width / 8) + 1 + wide = self.width // 8 + 1 - self.send_command(0x10) - self.send_data2([0xff] * int(self.height * linewidth)) + if (self.flag == 1): + self.send_command(0x24) + for j in range(0, high): + for i in range(0, wide): + self.send_data(0xff) - self.send_command(0x13) - self.send_data2([0xff] * int(self.height * linewidth)) + self.send_command(0x26) + for j in range(0, high): + for i in range(0, wide): + self.send_data(0x00) - self.send_command(0x12) - epdconfig.delay_ms(20) - self.ReadBusy() + else: + self.send_command(0x10) + for j in range(0, high): + for i in range(0, wide): + self.send_data(0xff) + + self.send_command(0x13) + for j in range(0, high): + for i in range(0, wide): + self.send_data(0xff) + + self.TurnOnDisplay() def sleep(self): - self.send_command(0X50) - self.send_data(0xf7) # border floating + if (self.flag == 1): + self.send_command(0X10) + self.send_data(0x03) - self.send_command(0X02) # power off - self.ReadBusy() # waiting for the electronic paper IC to release the idle signal - self.send_command(0X07) # deep sleep - self.send_data(0xA5) + else: + self.send_command(0X50) + self.send_data(0xf7) + self.send_command(0X02) + self.ReadBusy() + self.send_command(0X07) + self.send_data(0xA5) epdconfig.delay_ms(2000) epdconfig.module_exit() From 4e1f08f6a86141ef7ed952f6109d1d183bb99c81 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Wed, 5 Jun 2024 10:55:21 +0200 Subject: [PATCH 36/39] Updated partnership with PiSugar team. Signed-off-by: jayofelony --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ceaa1a67..0d30e4b8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ This is the main source for all forks: [GH Sponsor](https://github.com/sponsors/jayofelony) +**Proudly partnering with [PiSugar](https://www.pisugar.com)!!** + --- [Pwnagotchi](https://pwnagotchi.ai/) is an [A2C](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752)-based "AI" leveraging [bettercap](https://www.bettercap.org/) that learns from its surrounding Wi-Fi environment to maximize the crackable WPA key material it captures (either passively, or by performing authentication and association attacks). This material is collected as PCAP files containing any form of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/), From 1614d1f94d630e86e91089e12e0b5fa5bade11e3 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Thu, 6 Jun 2024 13:41:19 +0200 Subject: [PATCH 37/39] Updated fix_services.py Updated pwnagotchi Signed-off-by: jayofelony --- bin/pwnagotchi | 2 +- pwnagotchi/plugins/default/fix_services.py | 29 +--------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/bin/pwnagotchi b/bin/pwnagotchi index e9e36254..dc6015ad 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -60,7 +60,7 @@ def pwnagotchi_cli(): channels = agent.get_access_points_by_channel() # for each channel for ch, aps in channels: - time.sleep(0.2) + time.sleep(0.5) agent.set_channel(ch) if not agent.is_stale() and agent.any_activity(): diff --git a/pwnagotchi/plugins/default/fix_services.py b/pwnagotchi/plugins/default/fix_services.py index 6f23df26..ea69ad80 100644 --- a/pwnagotchi/plugins/default/fix_services.py +++ b/pwnagotchi/plugins/default/fix_services.py @@ -29,7 +29,6 @@ class FixServices(plugins.Plugin): def __init__(self): self.options = dict() - self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed') self.pattern2 = re.compile(r'wifi error while hopping to channel') self.pattern3 = re.compile(r'Firmware has halted or crashed') self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon') @@ -55,20 +54,6 @@ class FixServices(plugins.Plugin): if ",UP," in str(cmd_output): logging.debug("wlan0mon is up.") - if len(self.pattern.findall(last_lines)) >= 3: - if hasattr(agent, 'view'): - display = agent.view() - display.set('status', 'Blind-Bug detected. Restarting.') - display.update(force=True) - logging.debug('[Fix_Services] Blind-Bug detected. Restarting.') - try: - self._tryTurningItOffAndOnAgain(agent) - except Exception as err: - logging.warning("[Fix_Services turnOffAndOn] %s" % repr(err)) - - else: - logging.debug("[Fix_Services] Logs look good!") - except Exception as err: logging.error("[Fix_Services ip link show wlan0mon]: %s" % repr(err)) try: @@ -116,20 +101,8 @@ class FixServices(plugins.Plugin): logging.debug("[Fix_Services]**** checking") - # Look for pattern 1 - if len(self.pattern.findall(last_lines)) >= 3: - logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) - if hasattr(agent, 'view'): - display.set('status', 'Blind-Bug detected. Restarting.') - display.update(force=True) - logging.debug('[Fix_Services] Blind-Bug detected. Restarting.') - try: - self._tryTurningItOffAndOnAgain(agent) - except Exception as err: - logging.warning("[Fix_Services] TTOAOA: %s" % repr(err)) - # Look for pattern 2 - elif len(self.pattern2.findall(other_last_lines)) >= 5: + if len(self.pattern2.findall(other_last_lines)) >= 5: logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) if hasattr(agent, 'view'): display.set('status', 'Wifi channel stuck. Restarting recon.') From 318e3480ceb37ed5a2048f38d554cecafc30a163 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Thu, 6 Jun 2024 13:43:59 +0200 Subject: [PATCH 38/39] Remove clear on exit, invokes an extra restart at boot Signed-off-by: jayofelony --- builder/data/64bit/etc/systemd/system/pwnagotchi.service | 1 - pwnagotchi/defaults.toml | 2 -- 2 files changed, 3 deletions(-) diff --git a/builder/data/64bit/etc/systemd/system/pwnagotchi.service b/builder/data/64bit/etc/systemd/system/pwnagotchi.service index 2810e3f5..daa53acc 100644 --- a/builder/data/64bit/etc/systemd/system/pwnagotchi.service +++ b/builder/data/64bit/etc/systemd/system/pwnagotchi.service @@ -8,7 +8,6 @@ After=pwngrid-peer.service Type=simple WorkingDirectory=~ ExecStart=/usr/bin/pwnagotchi-launcher -ExecStopPost=/usr/bin/bash -c "if egrep -qi 'personality.clear_on_exit[ =]*true' /etc/pwnagotchi/config.toml ; then /usr/local/bin/pwnagotchi --clear; fi" Restart=always RestartSec=30 TasksMax=infinity diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml index 3a773bb2..b5d6f3a8 100644 --- a/pwnagotchi/defaults.toml +++ b/pwnagotchi/defaults.toml @@ -150,8 +150,6 @@ personality.bond_encounters_factor = 20000 personality.throttle_a = 0.4 personality.throttle_d = 0.9 -personality.clear_on_exit = true # clear display when shutting down cleanly - ui.invert = false # false = black background, true = white background ui.fps = 0.0 From 3f40c0b7b32fadcab245989dd419d2e6b5180a51 Mon Sep 17 00:00:00 2001 From: jayofelony Date: Thu, 6 Jun 2024 14:36:33 +0200 Subject: [PATCH 39/39] Switch to bettercap lite Signed-off-by: jayofelony --- builder/raspberrypi32.yml | 30 ++++-------------------------- builder/raspberrypi64.yml | 20 ++++---------------- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/builder/raspberrypi32.yml b/builder/raspberrypi32.yml index 9f743d79..c5efdeda 100644 --- a/builder/raspberrypi32.yml +++ b/builder/raspberrypi32.yml @@ -26,9 +26,10 @@ packages: caplets: source: "https://github.com/jayofelony/caplets.git" + branch: "lite" # or master bettercap: source: "https://github.com/jayofelony/bettercap.git" - ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" + branch: "lite" # or master pwngrid: source: "https://github.com/jayofelony/pwngrid.git" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" @@ -405,6 +406,7 @@ - name: download bettercap git: repo: "{{ packages.bettercap.source }}" + version: "{{ packages.bettercap.branch }} " dest: /usr/local/src/bettercap - name: install bettercap 2.32.4 @@ -418,19 +420,10 @@ state: absent path: /usr/local/src/bettercap - #- name: download and install bettercap - # unarchive: - # src: "{{ packages.bettercap.url }}" - # dest: /usr/local/bin - # remote_src: yes - # exclude: - # - README.md - # - LICENSE.md - # mode: 0755 - - name: clone bettercap caplets git: repo: "{{ packages.caplets.source }}" + version: "{{ packages.caplets.branch }}" dest: /tmp/caplets register: capletsgit @@ -440,21 +433,6 @@ target: install when: capletsgit.changed - - name: download and install bettercap ui - unarchive: - src: "{{ packages.bettercap.ui }}" - dest: /usr/local/share/bettercap/ - remote_src: yes - mode: 0755 - - # to always have the bettercap webui available (because why not?) - - name: copy pwnagotchi-manual over pwnagotchi-auto caplet - ansible.builtin.copy: - src: /usr/local/share/bettercap/caplets/pwnagotchi-manual.cap - dest: /usr/local/share/bettercap/caplets/pwnagotchi-auto.cap - force: true - ignore_errors: true - - name: create /etc/pwnagotchi folder file: path: /etc/pwnagotchi diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 75d50b21..e5609b52 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -27,10 +27,11 @@ packages: caplets: source: "https://github.com/jayofelony/caplets.git" + branch: "lite" # or master bettercap: source: "https://github.com/jayofelony/bettercap.git" url: "https://github.com/jayofelony/bettercap/releases/download/2.32.4/bettercap-2.32.4.zip" - ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" + branch: "lite" # or master pwngrid: source: "https://github.com/jayofelony/pwngrid.git" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.5/pwngrid-1.10.5-aarch64.zip" @@ -472,6 +473,7 @@ - name: download bettercap git: repo: "{{ packages.bettercap.source }}" + version: "{{ packages.bettercap.branch }}" dest: /usr/local/src/bettercap - name: install bettercap 2.32.4 @@ -498,6 +500,7 @@ - name: clone bettercap caplets git: repo: "{{ packages.caplets.source }}" + version: "{{ packages.caplets.branch }}" dest: /tmp/caplets register: capletsgit @@ -507,21 +510,6 @@ target: install when: capletsgit.changed - - name: download and install bettercap ui - unarchive: - src: "{{ packages.bettercap.ui }}" - dest: /usr/local/share/bettercap/ - remote_src: yes - mode: 0755 - - # to always have the bettercap webui available (because why not?) - - name: copy pwnagotchi-manual over pwnagotchi-auto caplet - ansible.builtin.copy: - src: /usr/local/share/bettercap/caplets/pwnagotchi-manual.cap - dest: /usr/local/share/bettercap/caplets/pwnagotchi-auto.cap - force: true - ignore_errors: true - - name: create /etc/pwnagotchi folder file: path: /etc/pwnagotchi