Compare commits

...

90 Commits

Author SHA1 Message Date
357ffc67e5 Update _version.py
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-26 09:19:13 +02:00
ea8fb5e533 Merge pull request #139 from RKouchoo/master
Fix 3.7 orientation
2024-04-26 06:37:39 +02:00
31afd6d0ba Merge pull request #138 from kszabi1/fix-ui-components-draw
Fix [#137 issue]: Incorrect use of assignment operator (=) instead of comparison operator (==) in draw method
2024-04-26 06:37:28 +02:00
b38274e652 Fix 3.7 orientation 2024-04-26 13:21:55 +10:00
518e8c219c Fix incorrect use of assignment operator (=) instead of comparison operator (==) in draw method of ui/components.py 2024-04-26 01:34:26 +02:00
4e07fbf1aa Update raspberrypi32.yml
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-25 20:30:45 +02:00
b3e81a95c8 Update raspberrypi32.yml
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-25 20:06:54 +02:00
050966215b Merge pull request #132
I2C oled support for SSD1306 chipsed oled screens
2024-04-22 08:41:34 +02:00
fef442edbb 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
2024-04-18 17:39:53 +02:00
1064936503 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-15 15:23:47 +02:00
a762a7f763 Merge remote-tracking branch 'origin/master' 2024-04-15 15:23:41 +02:00
8fd0e358a9 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-15 15:23:34 +02:00
9a941c1d46 Merge branch 'jayofelony:master' into master 2024-04-04 15:46:29 +02:00
ead5a3baac Merge pull request #121 from rai68/patch-2
Update components.py
2024-04-03 21:58:17 +02:00
ac2973889d Update FUNDING.yml 2024-04-03 21:14:22 +02:00
Rai
8991dd6811 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>
2024-04-04 03:04:31 +10:00
415e5cd551 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-03 09:39:38 +02:00
47705ba1a2 Update config.txt at creation of image file, no more overwriting at auto-update.
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-03 09:39:10 +02:00
7c7bbc770b Merge branch 'jayofelony:master' into master 2024-04-02 17:54:00 +02:00
ab83de4905 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
2024-04-02 17:46:11 +02:00
8f7741cd9e Remove unused imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-01 17:30:51 +02:00
835886e6f6 Merge pull request #114
Update Traditional Chinese (TW) Language
2024-04-01 17:29:58 +02:00
6b2039a8e6 Merge pull request #116
Fix Waveshare V2 Position
2024-04-01 17:29:28 +02:00
d53d0c7841 Merge pull request #117
Fix range of lines about the displays
2024-04-01 17:29:10 +02:00
6c40998b51 Merge pull request #118
Fix typo in ansible script
2024-04-01 17:28:18 +02:00
a71a90ba3d Delete config.py 2024-04-01 01:37:47 +02:00
b03f6f747b Generic I2C Oled support , waveshare oled/lcd vertical layout
work in progress for the triple screen project
2024-03-31 23:55:15 +02:00
a8ba88c9cc Fix typo in ansible script
Signed-off-by: Morten Winther Olsson <18525061+olwimo@users.noreply.github.com>
2024-03-30 08:04:55 +01:00
f597bd6d29 Fix range of lines about the displays
Signed-off-by: Benoît Allard <benoit.allard@gmx.de>
2024-03-29 15:08:07 +01:00
a3f103ac06 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 <drego85@draghetti.it>
2024-03-29 08:57:45 +01:00
e0a068e51d Upload tw voice.mo
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:46:42 +08:00
dc1b3c7635 Delete tw voice.mo
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:45:59 +08:00
3657859a73 Update tw voice.po
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:45:21 +08:00
33ff5a0bf8 Fix ui.invert
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:37:59 +01:00
666f65c640 Merge pull request #110
Update Portuguese (Brazil) Language
2024-03-27 07:36:24 +01:00
84d45a0d45 Version 2.9.0
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:20:45 +01:00
06a4491008 Update 32bit to use latest pwngrid/bettercap
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:17:35 +01:00
5485f83ca6 Update Portuguese (Brazil) Language 2024-03-26 14:06:55 -03:00
ab541458fa add extra check for fix_services
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 12:15:00 +01:00
ac345c2ee7 make_latest: true
generate_release_notes: true

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 07:58:06 +01:00
468cfd9f4f prerelease: false
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 07:55:06 +01:00
d6bc5c0e66 Reboot after auto-update
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 00:07:15 +01:00
4905eb6b26 Optimize display imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 00:05:50 +01:00
697a7778b1 Fix fix_services.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 23:29:10 +01:00
9287283ee7 Added 11 waveshare lcd displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 22:53:07 +01:00
8013109ef7 Refactoring displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 22:52:42 +01:00
f140fe1a2d Update setup.py to look for empty apt_packages.txt
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 11:58:46 +01:00
8fe503c67d No new apt-packages needed
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 08:11:39 +01:00
d81013412e Update several displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 15:18:58 +01:00
3c701822bd Update donation method
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:58:26 +01:00
2f5ddb492a Small typo's
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:58:07 +01:00
9e3324221d Fix adafruit 2.13inch display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:40 +01:00
b069b82984 Version 2.8.9
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:20 +01:00
cb7d965271 Update MOTD
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:08 +01:00
7abf9ff8da Update faces.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:49:46 +01:00
18fb956251 Update setup.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:46:32 +01:00
afb1d11cd8 Added Adafruit 2in13_V3 display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:24:52 +01:00
627be80e6c add system wide aliases, if you were to use custom users
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:49 +01:00
c4c4d6c417 in case you use an unsupported display it will default to dummy display, displaying nothing
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:27 +01:00
8dcae13ce9 add commented dtoverlay=disable-wifi
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:00 +01:00
1352e99774 Fix wrong imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 18:34:49 +01:00
2182d7c29d Update Frysian Language
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:56:47 +01:00
703c05a93b Full SSID again
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:06:04 +01:00
697cc5d88b Add DummyDisplay
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:56 +01:00
4b04f9b7a5 Install OS packages from auto-update
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:22 +01:00
c7b94a0707 Version 2.8.8 starts here
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:01 +01:00
5116bac2a7 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:32:04 +01:00
51625e61f9 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:25:36 +01:00
bf9a0a96c1 Update raspberrypi64.yml 2024-03-20 21:17:20 +01:00
bd03f07aa8 Update raspberrypi32.yml 2024-03-20 21:16:50 +01:00
3f13df8f20 Merge pull request #104
Update defaults.toml
2024-03-20 07:20:19 +01:00
ce0275f2ae Update defaults.toml
Removed main.filter since it's no longer referenced in agent.py as of this commit 1a55afd74a (diff-0548f0a21e1984ecf3c32d6cd9c17e6a62f4f139c001360935890f649b745cc7)

Signed-off-by: seelenamt <dandrewe@gmail.com>
2024-03-19 10:51:59 -05:00
b971f18f75 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:54 +01:00
ea9d11d018 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:00 +01:00
8a572f1b70 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:16:14 +01:00
0c4f2a5093 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 09:25:17 +01:00
7edd752664 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 07:56:06 +01:00
cc550aa236 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 15:05:00 +01:00
ff033d41d3 Revert "fallback to older 32bit image"
This reverts commit b33af167d4.
2024-03-18 14:56:59 +01:00
6d0a0d8d5f fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 13:04:19 +01:00
b33af167d4 fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 12:03:20 +01:00
9053762e71 2.8.7.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:59:32 +01:00
26fef7dd99 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	builder/data/64bit/raspberrypi64.yml
2024-03-18 11:58:33 +01:00
5dd17291f7 Fix a lot of stuff
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:58:22 +01:00
bac79f3465 Update _version.py 2024-03-17 21:17:08 +01:00
bb8dfe0244 Update raspberrypi64.yml 2024-03-17 21:16:25 +01:00
1b16975031 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:24:57 +01:00
dd2b559ebc Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:22:35 +01:00
93ba2a7f79 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:20:02 +01:00
dd18072002 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:18:31 +01:00
307 changed files with 5504 additions and 3219 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,3 +1,3 @@
# These are supported funding model platforms # These are supported funding model platforms
github: jayofelony github: jayofelony

View File

@ -20,21 +20,6 @@ jobs:
VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py) VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py)
echo "VERSION=$VERSION" >> $GITHUB_ENV echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Get latest tag
uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
- name: Set LAST_VERSION as an environment variable
run: echo "LAST_VERSION=${{ steps.get-latest-tag.outputs.tag }}" >> $GITHUB_ENV
- name: Generate release notes
id: generate_release_notes
run: |
COMMITS=$(git log --merges --pretty=format:"* %s" $LAST_VERSION--$VERSION | sed 's/$/\\n/g')
CONTRIBUTORS=$(git shortlog -sn $LAST_VERSION--$VERSION | awk '{print "* @" $2}' | sed 's/$/\\n/g')
RELEASE_BODY="**Full Changelog**: https://github.com/jayofelony/pwnagotchi/compare/$LAST_VERSION...$VERSION"
echo "RELEASE_BODY=$RELEASE_BODY" >> $GITHUB_ENV
- name: Install qemu dependencies - name: Install qemu dependencies
run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y
@ -61,12 +46,13 @@ jobs:
run: mv "pwnagotchi-64bit.img.xz" "pwnagotchi-$VERSION-64bit.img.xz" run: mv "pwnagotchi-64bit.img.xz" "pwnagotchi-$VERSION-64bit.img.xz"
- name: Release - name: Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v2
with: with:
prerelease: true prerelease: false
make_latest: true
tag_name: v${{ env.VERSION }} tag_name: v${{ env.VERSION }}
name: Pwnagotchi v${{ env.VERSION }} name: Pwnagotchi v${{ env.VERSION }}
files: | files: |
pwnagotchi-${{ env.VERSION }}-32bit.img.xz pwnagotchi-${{ env.VERSION }}-32bit.img.xz
pwnagotchi-${{ env.VERSION }}-64bit.img.xz pwnagotchi-${{ env.VERSION }}-64bit.img.xz
body: ${{ env.RELEASE_BODY }} generate_release_notes: true

View File

@ -51,13 +51,11 @@ image: clean packer
bullseye: clean packer bullseye: clean packer
export LC_ALL=en_GB.UTF-8 export LC_ALL=en_GB.UTF-8
cd builder && sudo /usr/bin/packer init data/32bit/raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/32bit/raspberrypi32.json.pkr.hcl 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
sudo pishrink -vaZ pwnagotchi-32bit.img
bookworm: clean packer bookworm: clean packer
export LC_ALL=en_GB.UTF-8 export LC_ALL=en_GB.UTF-8
cd builder && sudo /usr/bin/packer init data/64bit/raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/64bit/raspberrypi64.json.pkr.hcl 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
sudo pishrink -vaZ pwnagotchi-64bit.img
clean: clean:
- rm -rf /tmp/packer* - rm -rf /tmp/packer*

View File

@ -237,7 +237,7 @@ def pwnagotchi_cli():
f.write("ui.display.enabled = true\n") f.write("ui.display.enabled = true\n")
pwn_display_type = input("What display do you use?\n\n" pwn_display_type = input("What display do you use?\n\n"
"Be sure to check for the correct display type @ \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: ") "Display type: ")
if pwn_display_type != "": if pwn_display_type != "":
f.write(f"ui.display.type = \"{pwn_display_type}\"\n") f.write(f"ui.display.type = \"{pwn_display_type}\"\n")
@ -264,8 +264,7 @@ def pwnagotchi_cli():
sys.exit(0) sys.exit(0)
if args.donate: if args.donate:
print("Donations can made @ \n " print("Donations can be made @ \n "
"https://www.patreon.com/pwnagotchi_torch \n "
"https://github.com/sponsors/jayofelony \n\n" "https://github.com/sponsors/jayofelony \n\n"
"But only if you really want to!") "But only if you really want to!")
sys.exit(0) sys.exit(0)
@ -278,8 +277,7 @@ def pwnagotchi_cli():
local = version_to_tuple(pwnagotchi.__version__) local = version_to_tuple(pwnagotchi.__version__)
remote = version_to_tuple(latest_ver) remote = version_to_tuple(latest_ver)
if remote > local: if remote > local:
user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] " user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] " % (pwnagotchi.__version__, latest_ver))
% (pwnagotchi.__version__, latest_ver))
# input validation # input validation
if user_input.lower() in ('y', 'yes'): if user_input.lower() in ('y', 'yes'):
if os.path.exists('/root/.auto-update'): if os.path.exists('/root/.auto-update'):
@ -334,5 +332,6 @@ def pwnagotchi_cli():
else: else:
do_auto_mode(agent) do_auto_mode(agent)
if __name__ == '__main__': if __name__ == '__main__':
pwnagotchi_cli() pwnagotchi_cli()

View File

@ -123,7 +123,7 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" 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\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml" playbook_file = "raspberrypi64.yml"
} }
} }
@ -167,7 +167,7 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" 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\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/" playbook_dir = "extras/"
playbook_file = "data/32bit/raspberrypi32.yml" playbook_file = "raspberrypi32.yml"
} }
} }

View File

@ -0,0 +1,6 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
i2c-dev

View File

@ -0,0 +1,40 @@
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "$(id -u)" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'

View File

@ -20,6 +20,7 @@ echo " I'm managed by systemd. Here are some basic commands."
echo echo
echo " If you want to know what I'm doing, you can check my logs with the command" echo " If you want to know what I'm doing, you can check my logs with the command"
echo " - pwnlog" echo " - pwnlog"
echo " - sudo pwnagotchi --wizard, to help set up a config.toml"
echo " - sudo pwnagotchi --version, to check the current version" echo " - sudo pwnagotchi --version, to check the current version"
echo " - sudo pwnagotchi --donate, to see how you can donate to this project" echo " - sudo pwnagotchi --donate, to see how you can donate to this project"
echo " - sudo pwnagotchi --check-update, to see if there is a new version available" echo " - sudo pwnagotchi --check-update, to see if there is a new version available"
@ -30,4 +31,4 @@ echo
echo " You can restart me using" echo " You can restart me using"
echo " pwnkill" echo " pwnkill"
echo echo
echo " You learn more about me at https://pwnagotchi.ai/" echo " You can learn more about me at https://pwnagotchi.org/"

View File

@ -32,6 +32,7 @@ start_monitor_interface() {
ifconfig wlan0 down ifconfig wlan0 down
ifconfig wlan0mon up ifconfig wlan0mon up
iw dev wlan0mon set power_save off iw dev wlan0mon set power_save off
iw dev wlan0 del
} }
# stops mon0 # stops mon0

View File

@ -0,0 +1,6 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
i2c-dev

View File

@ -0,0 +1,40 @@
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "$(id -u)" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'

View File

@ -2,7 +2,7 @@
_hostname=$(hostname) _hostname=$(hostname)
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py) _version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py)
echo echo
echo "(☉_☉ ) $_hostname" echo "(◕‿‿◕) $_hostname"
echo echo
echo " Hi! I'm a pwnagotchi $_version, please take good care of me!" echo " Hi! I'm a pwnagotchi $_version, please take good care of me!"
echo " Here are some basic things you need to know to raise me properly!" echo " Here are some basic things you need to know to raise me properly!"

View File

@ -1,18 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# well ... it blinks the led
blink_led() {
# shellcheck disable=SC2034
for i in $(seq 1 "$1"); do
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
echo 1 >/sys/class/leds/led0/brightness
sleep 0.3
done
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
}
# reload mod # reload mod
reload_brcm() { reload_brcm() {
if ! modprobe -r brcmfmac; then if ! modprobe -r brcmfmac; then
@ -39,6 +26,7 @@ start_monitor_interface() {
ifconfig wlan0 down ifconfig wlan0 down
ifconfig wlan0mon up ifconfig wlan0mon up
iw dev wlan0mon set power_save off iw dev wlan0mon set power_save off
iw dev wlan0 del
} }
# stops mon0 # stops mon0

View File

@ -88,7 +88,7 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" 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\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/" playbook_dir = "extras/"
playbook_file = "data/32bit/raspberrypi32.yml" playbook_file = "raspberrypi32.yml"
} }
} }

View File

@ -39,26 +39,6 @@
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins" custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
system:
boot_options:
- "#### pwnagotchi additions"
- "# this pwnagotchi image is 32-bit only no v8+ headers to build nexmon for 64 bit"
- "arm_64bit=0"
- "# dwc2 for RNDIS. comment out, and remove dwc2 and g_ether from cmdline.txt for X306 usb battery hat"
- "dtoverlay=dwc2"
- "dtoverlay=spi0-0cs"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
- "#### audio out on pins 18 and 19"
- "#dtoverlay=audremap,pins_18_19"
- "#### touchscreen on waveshare touch e-paper"
- "#dtoverlay=goodix,interrupt=27,reset=22"
- "#### for PWM backlighting on pimoroni displayhatmini"
- "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4"
modules:
- "i2c-dev"
services: services:
enable: enable:
- bettercap.service - bettercap.service
@ -82,7 +62,7 @@
source: "https://github.com/jayofelony/bettercap.git" source: "https://github.com/jayofelony/bettercap.git"
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip" 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" ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip"
opwngrid: pwngrid:
source: "https://github.com/jayofelony/pwngrid.git" source: "https://github.com/jayofelony/pwngrid.git"
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip"
torch: torch:
@ -117,6 +97,7 @@
- bc - bc
- bison - bison
- bluez - bluez
- bluez-tools
- build-essential - build-essential
- curl - curl
- dkms - dkms
@ -142,6 +123,7 @@
- libc-ares-dev - libc-ares-dev
- libc6-dev - libc6-dev
- libcpuinfo-dev - libcpuinfo-dev
- libcurl4-openssl-dev
- libdbus-1-dev - libdbus-1-dev
- libdbus-glib-1-dev - libdbus-glib-1-dev
- libeigen3-dev - libeigen3-dev
@ -170,6 +152,7 @@
- libsleef-dev - libsleef-dev
- libsqlite3-dev - libsqlite3-dev
- libssl-dev - libssl-dev
- libssl-ocaml-dev
- libswscale5 - libswscale5
- libtiff5 - libtiff5
- libtool - libtool
@ -178,6 +161,7 @@
- lsof - lsof
- make - make
- ntp - ntp
- python3-dbus
- python3-flask - python3-flask
- python3-flask-cors - python3-flask-cors
- python3-flaskext.wtf - python3-flaskext.wtf
@ -224,6 +208,30 @@
state: present state: present
when: hostname.changed 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 - name: Create custom plugin directory
file: file:
path: '{{ pwnagotchi.custom_plugin_dir }}' path: '{{ pwnagotchi.custom_plugin_dir }}'
@ -282,6 +290,24 @@
dest: /usr/local/lib/libpcap.so.0.8 dest: /usr/local/lib/libpcap.so.0.8
state: link 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) # Install nexmon to fix wireless scanning (takes 2.5G of space)
############################################################### ###############################################################
@ -389,29 +415,39 @@
block: | block: |
export GOPATH=$HOME/go export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed when: golang.changed
- name: download pwngrid - name: download pwngrid
unarchive: git:
remote_src: yes repo: "{{ packages.pwngrid.source }}"
src: "{{ packages.opwngrid.url }}" dest: /usr/local/src/pwngrid
dest: /usr/local/bin/
mode: 0755
- name: download and install bettercap - name: install pwngrid
unarchive: shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
src: "{{ packages.bettercap.url }}" args:
dest: /usr/local/bin executable: /bin/bash
remote_src: yes chdir: /usr/local/src/pwngrid
exclude:
- README.md - name: remove pwngrid folder
- LICENSE.md file:
mode: 0755 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 - name: clone bettercap caplets
git: git:
@ -475,20 +511,6 @@
path: /boot/ssh path: /boot/ssh
state: touch state: touch
- name: adjust /boot/config.txt
lineinfile:
dest: /boot/config.txt
insertafter: EOF
line: '{{ item }}'
with_items: "{{system.boot_options}}"
- name: adjust /etc/modules
lineinfile:
dest: /etc/modules
insertafter: EOF
line: '{{ item }}'
with_items: "{{system.modules}}"
- name: change root partition - name: change root partition
replace: replace:
dest: /boot/cmdline.txt dest: /boot/cmdline.txt
@ -596,4 +618,4 @@
handlers: handlers:
- name: reload systemd services - name: reload systemd services
systemd: systemd:
daemon_reload: yes daemon_reload: yes

View File

@ -95,6 +95,6 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" 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\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml" playbook_file = "raspberrypi64.yml"
} }
} }

View File

@ -11,23 +11,6 @@
pwnagotchi: pwnagotchi:
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
system:
boot_options:
- "dtoverlay=dwc2"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
- "[pi0]"
- "dtoverlay=spi0-0cs"
- "[pi3]"
- "dtoverlay=spi0-0cs"
- "[pi4]"
- "dtoverlay=spi0-0cs"
- "[pi5]"
- "dtoverlay=spi0-0cs"
modules:
- "i2c-dev"
services: services:
enable: enable:
- bettercap.service - bettercap.service
@ -81,6 +64,7 @@
- bc - bc
- bison - bison
- bluez - bluez
- bluez-tools
- build-essential - build-essential
- curl - curl
- dkms - dkms
@ -211,25 +195,6 @@
path: /etc/rc.local path: /etc/rc.local
state: absent state: absent
- name: adjust /boot/config.txt
blockinfile:
dest: /boot/config.txt
insertafter: EOF
block: |
dtoverlay=dwc2
dtparam=i2c1=on
dtparam=i2c_arm=on"
dtparam=spi=on
gpu_mem=16
[pi0]
dtoverlay=spi0-0cs
[pi3]
dtoverlay=spi0-0cs
[pi4]
dtoverlay=spi0-0cs
[pi5]
dtoverlay=spi0-0cs
- name: change root partition - name: change root partition
replace: replace:
dest: /boot/firmware/cmdline.txt dest: /boot/firmware/cmdline.txt
@ -246,6 +211,34 @@
regexp: '(.*)$' regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether' 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 - name: change hostname
lineinfile: lineinfile:
dest: /etc/hostname dest: /etc/hostname
@ -517,16 +510,11 @@
- name: Update .bashrc for go-1.21 - name: Update .bashrc for go-1.21
blockinfile: blockinfile:
dest: /home/pi/.bashrc dest: /etc/profile
state: present state: present
block: | block: |
export GOPATH=$HOME/go export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed when: golang.changed
- name: download pwngrid - name: download pwngrid

View File

@ -1 +1 @@
__version__ = '2.8.7' __version__ = '2.9.1'

View File

@ -254,7 +254,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
txt = '%d (%d)' % (len(self._handshakes), tot) txt = '%d (%d)' % (len(self._handshakes), tot)
if self._last_pwnd is not None: if self._last_pwnd is not None:
txt += ' [%s]' % self._last_pwnd[:11] # So it doesn't overlap with fix_brcmfmac_plugin txt += ' [%s]' % self._last_pwnd
self._view.set('shakes', txt) self._view.set('shakes', txt)

View File

@ -100,7 +100,6 @@ class Client(object):
await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time)
continue continue
except OSError: except OSError:
sleep_time = min_sleep + max_sleep * random.random()
logging.warning('connection to the bettercap endpoint failed...') logging.warning('connection to the bettercap endpoint failed...')
pwnagotchi.restart("AUTO") pwnagotchi.restart("AUTO")

View File

@ -112,8 +112,6 @@ main.mon_stop_cmd = "/usr/bin/monstop"
main.mon_max_blind_epochs = 50 main.mon_max_blind_epochs = 50
main.no_restart = false main.no_restart = false
main.filter = ""
main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log" main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log"
main.log.rotation.enabled = true main.log.rotation.enabled = true
main.log.rotation.size = "10M" main.log.rotation.size = "10M"

View File

@ -248,7 +248,7 @@ msgid "minutes"
msgstr "minuten" msgstr "minuten"
msgid "seconds" msgid "seconds"
msgstr "seconds" msgstr "sekondes"
msgid "hour" msgid "hour"
msgstr "oere" msgstr "oere"

View File

@ -1,260 +1,260 @@
# SOME DESCRIPTIVE TITLE. # pwnagotchi Brazilian Portuguese translation file.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2024
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the pwnagotchi package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Fabiano F O <fabfernandes@hotmail.com>, 2024.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-17 15:46+0100\n" "POT-Creation-Date: 2024-03-25 22:30+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Foxy <EMAIL@ADDRESS>\n" "Last-Translator: Fabiano F O <fabfernandes@hotmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: Portuguese (Brazil)\n" "Language: Brazilian Portuguese\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz" msgid "ZzzzZZzzzzZzzz"
msgstr "ZzzzZZzzzzZzzz" msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "Olá, Eu sou Pwnagotchi! Iniciando ..." msgstr "Olá, sou Pwnagotchi! Iniciando ..."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "Um novo dia, Uma nova caça e novos pwns!" msgstr "Novo dia, Nova caçada, Novos pwns!"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "Burle o Planeta!" msgstr "Hackeie o Planeta!"
msgid "AI ready." msgid "AI ready."
msgstr "IA pronta." msgstr "IA pronta."
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "A rede neural está pronta." msgstr "A rede neural está pronta."
msgid "Generating keys, do not turn off ..." msgid "Generating keys, do not turn off ..."
msgstr "Criando chaves, não desligue o sistema ..." msgstr "Gerando chaves, não desligue ..."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "Ei, canal {channel} está livre! Seu AP vai agradecer." msgstr "Ei, o canal {channel} está livre! Seu AP vai agradecer."
msgid "Reading last session logs ..." msgid "Reading last session logs ..."
msgstr "Lendo os logs da ultima sessão" msgstr "Lendo os logs da última sessão ..."
#, python-brace-format #, python-brace-format
msgid "Read {lines_so_far} log lines so far ..." msgid "Read {lines_so_far} log lines so far ..."
msgstr "Leia {lines_so_far} linha de logs até agora ..." msgstr "Li {lines_so_far} linhas de logs até agora ..."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "Eu estou entediado ..." msgstr "Estou entediado ..."
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "Vamos ir numa caminhada!" msgstr "Vamos dar um passeio!"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "Esse é o melhor dia da minha vida!" msgstr "Este é o melhor dia da minha vida!"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "Dia ruim :/" msgstr "Que dia ruim :/"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "Eu estou extremamente entediado ..." msgstr "Estou extremamente entediado ..."
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "Eu estou muito triste ..." msgstr "Estou muito triste ..."
msgid "I'm sad" msgid "I'm sad"
msgstr "Eu estou triste" msgstr "Estou triste"
msgid "Leave me alone ..." msgid "Leave me alone ..."
msgstr "Me deixe em paz ..." msgstr "Me deixe em paz ..."
msgid "I'm mad at you!" msgid "I'm mad at you!"
msgstr "Eu estou bravo com você!" msgstr "Estou bravo com você!"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "Eu estou vivendo a vida!" msgstr "Estou aproveitando a vida!"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "Eu pwn então Eu sou." msgstr "Eu pwn, logo existo."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "Tantas redes!!!" msgstr "Uau! Quantas redes!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "Eu estou tendo muita diversão" msgstr "Estou me divertindo muito!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "Meu crime é de curiosidade ..." msgstr "Meu crime é a curiosidade ..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you." msgid "Hello {name}! Nice to meet you."
msgstr "Olá {name}! É bom em conhecê-lo" msgstr "Olá {name}! Prazer em conhecê-lo."
#, python-brace-format #, python-brace-format
msgid "Yo {name}! Sup?" msgid "Yo {name}! Sup?"
msgstr "Ei {name}! Como vai?" msgstr "Ei {name}! Como vai?"
#, python-brace-format #, python-brace-format
msgid "Hey {name} how are you doing?" msgid "Hey {name} how are you doing?"
msgstr "Ei {name} como você está indo?" msgstr "Ei {name}, como você está?"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby!" msgid "Unit {name} is nearby!"
msgstr "" msgstr "A unidade {name} está próxima!"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "" msgstr "Hmm ... tchau {name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "" msgstr "{name} desapareceu ..."
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "" msgstr "Oops ... {name} desapareceu."
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "{name} errou!" msgstr "Perdi {name}!"
msgid "Missed!" msgid "Missed!"
msgstr "Errei!" msgstr "Perdi!"
msgid "Good friends are a blessing!" msgid "Good friends are a blessing!"
msgstr "Bom amigos são uma bensão!" msgstr "Bons amigos são uma bênção!"
msgid "I love my friends!" msgid "I love my friends!"
msgstr "Eu amo meus amigos!" msgstr "Eu amo meus amigos!"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "Ninguém quer brincar comigo ..." msgstr "Ninguém quer brincar comigo ..."
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "Estou me sentindo sozinho" msgstr "Me sinto tão sozinho ..."
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "Onde está todo mundo?!" msgstr "Onde está todo mundo?!"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "Tirando uma soneca por {secs}s ..." msgstr "Tirando uma soneca por {secs}s ..."
msgid "Zzzzz" msgid "Zzzzz"
msgstr "Zzzzz" msgstr "Zzzzz"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "ZzzZzzz ({secs}s)" msgstr "ZzzZzzz ({secs}s)"
msgid "Good night." msgid "Good night."
msgstr "Boa noite." msgstr "Boa noite."
msgid "Zzz" msgid "Zzz"
msgstr "Zzz" msgstr "Zzz"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "Esperando por {secs}s ..." msgstr "Aguardando {secs}s ..."
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "Olhando por volta ({secs}s)" msgstr "Olhando em volta ... ({secs}s)"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "Ei {what} vamos ser amigos!" msgstr "Ei {what}, vamos ser amigos!"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "Associando para {what}" msgstr "Associando a {what}"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "Ei {what}!" msgstr "Olá {what}!"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "Apenas decidindo que {mac} não precisa de WiFi!" msgstr "Acabei de decidir que {mac} não precisa de WiFi!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "Desautenticando {mac}" msgstr "Desautenticando {mac}"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "Banindo {mac}!" msgstr "Banindo {mac}!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "Legal, conseguimos {num} novos handshake{plural}!" msgstr "Legal, conseguimos {num} novo{plural} handshake{plural}!"
#, python-brace-format #, python-brace-format
msgid "You have {count} new message{plural}!" msgid "You have {count} new message{plural}!"
msgstr "Você tem {count} novas messagem{plural}!" msgstr "Você tem {count} nova{plural} messagem{plural}!"
msgid "Oops, something went wrong ... Rebooting ..." msgid "Oops, something went wrong ... Rebooting ..."
msgstr "Oops, algo deu errado ... Reiniciando ..." msgstr "Oops, algo deu errado ... Reiniciando ..."
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "Enviando dados para {to} ..." msgstr "Enviando dados para {to} ..."
#, python-brace-format #, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "Instalando para {name} ..." msgstr "Baixando de {name} ..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "Expulsei {num} estações\n" msgstr "Expulsei {num} estações\n"
msgid "Made >999 new friends\n" msgid "Made >999 new friends\n"
msgstr "Fiz >999 novos amigos\n" msgstr "Fiz >999 novos amigos\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "Fiz {num} novos amigos\n" msgstr "Fiz {num} novos amigos\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "Peguei {num} handshakes\n" msgstr "Peguei {num} handshakes\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "Encontrei 1 pessoa" msgstr "Conheci 1 peer"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "Encontrei {num} pessoas" msgstr "Conheci {num} peers"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " "I've been pwning for {duration} and kicked {deauthed} clients! I've also met "
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"Estou navegando há {duration} e expulsei {deauthed} clientes! Também conheci " "Estou pwning há {duration} e expulsei {deauthed} clientes! Também conheci "
"{associamos} novos amigos e comi {handshakes} handshakes! #pwnagotchi " "{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgid "hours" msgid "hours"
msgstr "horas" msgstr "horas"
msgid "minutes" msgid "minutes"
msgstr "minutos" msgstr "minutos"
msgid "seconds" msgid "seconds"
msgstr "segundos" msgstr "segundos"
msgid "hour" msgid "hour"
msgstr "hora" msgstr "hora"
msgid "minute" msgid "minute"
msgstr "minuto" msgstr "minuto"
msgid "second" msgid "second"
msgstr "segundo" msgstr "segundo"

View File

@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-16 21:10+0100\n" "POT-Creation-Date: 2023-11-16 21:10+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2024-03-27 18:40+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: AlanLeung <admin@mcnot.pro>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: Twi\n" "Language: Twi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -18,218 +18,218 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz" msgid "ZzzzZZzzzzZzzz"
msgstr "" msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "" msgstr "HI!我是Pwnagotchi!\n程式啟動..."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "" msgstr "新的一天!\n新的狩獵!新的入侵!"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "" msgstr "我要駭入\n地球的所有人!"
msgid "AI ready." msgid "AI ready."
msgstr "" msgstr "人工智慧已啟動。"
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "" msgstr "神經網路已啟動。"
msgid "Generating keys, do not turn off ..." msgid "Generating keys, do not turn off ..."
msgstr "" msgstr "產生金鑰中,\n請勿關閉..."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "" msgstr "嘿,{channel}很順暢!\n你的WIFI會感謝你的。"
msgid "Reading last session logs ..." msgid "Reading last session logs ..."
msgstr "" msgstr "正在閱讀最後的會話紀錄..."
#, python-brace-format #, python-brace-format
msgid "Read {lines_so_far} log lines so far ..." msgid "Read {lines_so_far} log lines so far ..."
msgstr "" msgstr "目前已經閱讀了 {lines_so_far} 行的紀錄..."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "" msgstr "我好無聊..."
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "" msgstr "我們! 散步! 散步散步散步散步"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "" msgstr "這是我生命中最棒的一天!"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "" msgstr "糟糕的一天 :/"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "" msgstr "我超無聊的...炒雞 炒雞的那種"
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "" msgstr "我好難過..."
msgid "I'm sad" msgid "I'm sad"
msgstr "" msgstr "嗚嗚嗚...."
msgid "Leave me alone ..." msgid "Leave me alone ..."
msgstr "" msgstr "尼奏凱啦臭臭"
msgid "I'm mad at you!" msgid "I'm mad at you!"
msgstr "" msgstr "喔氣氣氣氣氣ˋ^ˊ"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "" msgstr "真是充實的一生!"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "" msgstr "我駭故我在."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "" msgstr "好多網路啊!!!吃! 吃他! 吃光光!!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "" msgstr "我玩的超級開心!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "" msgstr "我的缺點就是\n太好奇了..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you." msgid "Hello {name}! Nice to meet you."
msgstr "" msgstr "尼豪{name}!\n很高興認識你!!!!"
#, python-brace-format #, python-brace-format
msgid "Yo {name}! Sup?" msgid "Yo {name}! Sup?"
msgstr "" msgstr "嗨 {name}! 你來攻打我的村莊?"
#, python-brace-format #, python-brace-format
msgid "Hey {name} how are you doing?" msgid "Hey {name} how are you doing?"
msgstr "" msgstr "嗨 {name} 你最近過得如何˙ˇ˙?"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby!" msgid "Unit {name} is nearby!"
msgstr "" msgstr "{name}\n就在附近!"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "" msgstr "哦嗚 ... \n拜拜{name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "" msgstr "{name}\n不見了 ..."
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "" msgstr "哦歐...\n{name}\n不見了。"
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "" msgstr "我剛剛錯過了{name}!"
msgid "Missed!" msgid "Missed!"
msgstr "" msgstr "又錯過了!"
msgid "Good friends are a blessing!" msgid "Good friends are a blessing!"
msgstr "" msgstr "有個好朋友\n真幸福!"
msgid "I love my friends!" msgid "I love my friends!"
msgstr "" msgstr "我喜歡\n我的朋友!"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "" msgstr "沒人想跟我玩..."
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "" msgstr "我覺得好孤單..."
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "" msgstr "大家都去哪裡了?!"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "" msgstr "我想瞇{secs}秒一下..."
msgid "Zzzzz" msgid "Zzzzz"
msgstr "" msgstr "Zzzzz"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "" msgstr "ZzzZzzz({secs}秒)"
msgid "Good night." msgid "Good night."
msgstr "" msgstr "晚安!"
msgid "Zzz" msgid "Zzz"
msgstr "" msgstr "Zzz"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "" msgstr "等我{secs}秒..."
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "" msgstr "環顧四周({secs}秒)"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "" msgstr "嗨\n{what}\n讓我們來當朋友吧!"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "" msgstr "正在連接\n{what}"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "" msgstr "喲,\n{what}!"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "" msgstr "我要讓\n{mac}\n斷線!\n他不需要上網!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "" msgstr "解除\n{mac}\n的授權中"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "" msgstr "把\n{mac}\n踢出中!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "" msgstr "酷耶,我們抓到{num}個\n新的握手包{plural}!"
#, python-brace-format #, python-brace-format
msgid "You have {count} new message{plural}!" msgid "You have {count} new message{plural}!"
msgstr "" msgstr "你有{count}個新訊息{plural}!"
msgid "Oops, something went wrong ... Rebooting ..." msgid "Oops, something went wrong ... Rebooting ..."
msgstr "" msgstr "哦歐,有些地方出錯了...\n重新啟動中..."
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "" msgstr "正在上傳資料到 {to} ..."
#, python-brace-format #, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "" msgstr "正在從 {name} 下載資料..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "" msgstr "踢了 {num} 個設備\n"
msgid "Made >999 new friends\n" msgid "Made >999 new friends\n"
msgstr "" msgstr "交了 >999 個新朋友\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "" msgstr "交了 {num} 個新朋友\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "" msgstr "捕獲了 {num} 個握手包\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "" msgstr "遇到了 個同好"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "" msgstr "遇到了 {num} 個同好"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
@ -237,21 +237,24 @@ msgid ""
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"我花了{duration}的時間\n駭入和踢了{deauthed}好多設備."
"我還交了好多{associated}新朋友,\n而且抓到了{handshakes}握手包!"
"#pwnagotchi#入侵日志 #駭客人生 #入侵整個星球 #天網 #我好棒˙ˇ˙"
msgid "hours" msgid "hours"
msgstr "" msgstr ""
msgid "minutes" msgid "minutes"
msgstr "" msgstr ""
msgid "seconds" msgid "seconds"
msgstr "" msgstr ""
msgid "hour" msgid "hour"
msgstr "" msgstr ""
msgid "minute" msgid "minute"
msgstr "" msgstr ""
msgid "second" msgid "second"
msgstr "" msgstr ""

View File

@ -230,7 +230,7 @@ class AutoUpdate(plugins.Plugin):
if num_installed > 0: if num_installed > 0:
display.update(force=True, new_data={'status': 'Rebooting ...'}) display.update(force=True, new_data={'status': 'Rebooting ...'})
time.sleep(3) time.sleep(3)
os.system("service pwnagotchi restart") pwnagotchi.reboot()
except Exception as e: except Exception as e:
logging.error("[update] %s" % e) logging.error("[update] %s" % e)

View File

@ -4,6 +4,7 @@ import subprocess
import time import time
import random import random
from io import TextIOWrapper from io import TextIOWrapper
import os
import pwnagotchi import pwnagotchi
from pwnagotchi import plugins from pwnagotchi import plugins
@ -32,6 +33,9 @@ class FixServices(plugins.Plugin):
self.pattern2 = re.compile(r'wifi error while hopping to channel') self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed') self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon') self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern5 = re.compile(r'fatal error: concurrent map iteration and map write')
self.pattern6 = re.compile(r'panic: runtime error')
self.pattern7 = re.compile(r'ieee80211 phy0: _brcmf_set_multicast_list: Setting allmulti failed, -110')
self.isReloadingMon = False self.isReloadingMon = False
self.connection = None self.connection = None
self.LASTTRY = 0 self.LASTTRY = 0
@ -108,7 +112,7 @@ class FixServices(plugins.Plugin):
logging.debug("[Fix_Services]**** epoch") logging.debug("[Fix_Services]**** epoch")
if time.time() - self.LASTTRY > 180: if time.time() - self.LASTTRY > 180:
# get last 10 lines # get last 10 lines
display = None display = agent.view()
logging.debug("[Fix_Services]**** checking") logging.debug("[Fix_Services]**** checking")
@ -116,7 +120,6 @@ class FixServices(plugins.Plugin):
if len(self.pattern.findall(last_lines)) >= 3: if len(self.pattern.findall(last_lines)) >= 3:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.') display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True) display.update(force=True)
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.') logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
@ -129,7 +132,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern2.findall(other_last_lines)) >= 5: elif len(self.pattern2.findall(other_last_lines)) >= 5:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Wifi channel stuck. Restarting recon.') display.set('status', 'Wifi channel stuck. Restarting recon.')
display.update(force=True) display.update(force=True)
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.') logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.')
@ -153,7 +155,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern3.findall(other_last_lines)) >= 1: elif len(self.pattern3.findall(other_last_lines)) >= 1:
logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.") logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.') display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.')
display.update(force=True) display.update(force=True)
try: try:
@ -167,7 +168,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern4.findall(other_other_last_lines)) >= 3: elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
logging.debug("[Fix_Services] wlan0 is down!") logging.debug("[Fix_Services] wlan0 is down!")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting wlan0 now!') display.set('status', 'Restarting wlan0 now!')
display.update(force=True) display.update(force=True)
try: try:
@ -177,6 +177,41 @@ class FixServices(plugins.Plugin):
except Exception as err: except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err)) logging.error("[Fix_Services monstart]: %s" % repr(err))
# Look for pattern 5
elif len(self.pattern5.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 6
elif len(self.pattern6.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 7
elif len(self.pattern7.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Monitor mode failed!")
try:
result = agent.run("wifi.recon off; wifi.recon on")
if result["success"]:
logging.debug("[Fix_Services] wifi.recon flip: success!")
if display:
display.update(force=True, new_data={"status": "Wifi recon flipped!",
"face": faces.COOL})
else:
print("Wifi recon flipped\nthat was easy!")
else:
logging.warning("[Fix_Services] wifi.recon flip: FAILED: %s" % repr(result))
except Exception as err:
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
else: else:
print("logs look good") print("logs look good")

View File

@ -14,8 +14,9 @@ class GPIOButtons(plugins.Plugin):
self.running = False self.running = False
self.ports = {} self.ports = {}
self.commands = None self.commands = None
self.options = dict()
def runCommand(self, channel): def runcommand(self, channel):
command = self.ports[channel] command = self.ports[channel]
logging.info(f"Button Pressed! Running command: {command}") logging.info(f"Button Pressed! Running command: {command}")
process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None, 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) gpio = int(gpio)
self.ports[gpio] = command self.ports[gpio] = command
GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP) GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP)
GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runCommand, bouncetime=600) GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runcommand, bouncetime=600)
#set pimoroni display hat mini LED off/dim # set pimoroni display hat mini LED off/dim
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(22, 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) GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

View File

@ -89,7 +89,7 @@ class Grid(plugins.Plugin):
logging.debug("checking pcap's") logging.debug("checking pcap's")
config = agent.config() 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) num_networks = len(pcap_files)
reported = self.report.data_field_or('reported', default=[]) reported = self.report.data_field_or('reported', default=[])
num_reported = len(reported) num_reported = len(reported)

View File

@ -253,7 +253,6 @@ class Logtail(plugins.Plugin):
""" """
logging.info("Logtail plugin loaded.") logging.info("Logtail plugin loaded.")
def on_webhook(self, path, request): def on_webhook(self, path, request):
if not self.ready: if not self.ready:
return "Plugin not ready" return "Plugin not ready"

View File

@ -130,7 +130,7 @@ class MemTemp(plugins.Plugin):
except Exception: except Exception:
# Set default position based on screen type # Set default position based on screen type
if ui.is_waveshare_v2(): if ui.is_waveshare_v2():
h_pos = (178, 84) h_pos = (175, 84)
v_pos = (197, 74) v_pos = (197, 74)
elif ui.is_waveshare_v1(): elif ui.is_waveshare_v1():
h_pos = (170, 80) h_pos = (170, 80)

View File

@ -18,12 +18,14 @@ def systemd_dropin(name, content):
systemctl("daemon-reload") systemctl("daemon-reload")
def systemctl(command, unit=None): def systemctl(command, unit=None):
if unit: if unit:
os.system("/bin/systemctl %s %s" % (command, unit)) os.system("/bin/systemctl %s %s" % (command, unit))
else: else:
os.system("/bin/systemctl %s" % command) os.system("/bin/systemctl %s" % command)
def run_task(name, options): def run_task(name, options):
task_service_name = "switcher-%s-task.service" % name task_service_name = "switcher-%s-task.service" % name
# save all the commands to a shell script # save all the commands to a shell script
@ -57,7 +59,7 @@ def run_task(name, options):
""" % (name, task_service_name, name)) """ % (name, task_service_name, name))
if 'reboot' in options and options['reboot']: 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 # if this file is set, we want the switcher-tasks to run
open('/root/.switcher', 'a').close() open('/root/.switcher', 'a').close()
@ -98,6 +100,7 @@ def run_task(name, options):
systemctl("daemon-reload") systemctl("daemon-reload")
systemctl("start", task_service_name) systemctl("start", task_service_name)
class Switcher(plugins.Plugin): class Switcher(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com' __author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '0.0.1' __version__ = '0.0.1'

View File

@ -10,13 +10,17 @@ class Widget(object):
def draw(self, canvas, drawer): def draw(self, canvas, drawer):
raise Exception("not implemented") 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): class Bitmap(Widget):
def __init__(self, path, xy, color=0): def __init__(self, path, xy, color=0):
super().__init__(xy, color) super().__init__(xy, color)
self.image = Image.open(path) self.image = Image.open(path)
def draw(self, canvas, drawer): def draw(self, canvas, drawer):
if self.color == 0xFF:
self.image = ImageOps.invert(self.image)
canvas.paste(self.image, self.xy) canvas.paste(self.image, self.xy)

View File

@ -28,6 +28,39 @@ class Display(View):
def is_lcdhat(self): def is_lcdhat(self):
return self._implementation.name == 'lcdhat' return self._implementation.name == 'lcdhat'
def is_wavesharelcd0in96(self):
return self._implementation.name == 'wavesharelcd0in96'
def is_wavesharelcd1in3(self):
return self._implementation.name == 'wavesharelcd1in3'
def is_wavesharelcd1in8(self):
return self._implementation.name == 'wavesharelcd1in8'
def is_wavesharelcd1in9(self):
return self._implementation.name == 'wavesharelcd1in9'
def is_wavesharelcd1in14(self):
return self._implementation.name == 'wavesharelcd1in14'
def is_wavesharelcd1in28(self):
return self._implementation.name == 'wavesharelcd1in28'
def is_wavesharelcd1in47(self):
return self._implementation.name == 'wavesharelcd1in47'
def is_wavesharelcd1in54(self):
return self._implementation.name == 'wavesharelcd1in54'
def is_wavesharelcd1in69(self):
return self._implementation.name == 'wavesharelcd1in69'
def is_wavesharelcd2in0(self):
return self._implementation.name == 'wavesharelcd2in0'
def is_wavesharelcd2in4(self):
return self._implementation.name == 'wavesharelcd2in4'
def is_waveshare144lcd(self): def is_waveshare144lcd(self):
return self._implementation.name == 'waveshare144lcd' return self._implementation.name == 'waveshare144lcd'
@ -202,6 +235,9 @@ class Display(View):
def is_inky(self): def is_inky(self):
return self._implementation.name == 'inky' return self._implementation.name == 'inky'
def is_dummy_display(self):
return self._implementation.name == 'dummydisplay'
def is_papirus(self): def is_papirus(self):
return self._implementation.name == 'papirus' return self._implementation.name == 'papirus'
@ -228,10 +264,19 @@ class Display(View):
def is_waveshareoledlcd(self): def is_waveshareoledlcd(self):
return self._implementation.name == 'waveshareoledlcd' 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): def is_waveshare35lcd(self):
return self._implementation.name == 'waveshare35lcd' return self._implementation.name == 'waveshare35lcd'
def is_adfruit213v3(self):
return self._implementation.name == 'adafruit2in13_v3'
def is_waveshare_any(self): def is_waveshare_any(self):
return self.is_waveshare_v1() or self.is_waveshare_v2() return self.is_waveshare_v1() or self.is_waveshare_v2()

View File

@ -27,6 +27,7 @@ PNG = False
POSITION_X = 0 POSITION_X = 0
POSITION_Y = 40 POSITION_Y = 40
def load_from_config(config): def load_from_config(config):
for face_name, face_value in config.items(): for face_name, face_value in config.items():
globals()[face_name.upper()] = face_value globals()[face_name.upper()] = face_value

View File

@ -1,283 +1,341 @@
from pwnagotchi.ui.hw.inky import Inky
from pwnagotchi.ui.hw.papirus import Papirus
from pwnagotchi.ui.hw.oledhat import OledHat
from pwnagotchi.ui.hw.lcdhat import LcdHat
from pwnagotchi.ui.hw.dfrobot import DFRobotV1
from pwnagotchi.ui.hw.dfrobot_v2 import DFRobotV2
from pwnagotchi.ui.hw.waveshare2in13 import WaveshareV1
from pwnagotchi.ui.hw.waveshare2in13_V2 import WaveshareV2
from pwnagotchi.ui.hw.waveshare2in13_V3 import WaveshareV3
from pwnagotchi.ui.hw.waveshare2in13_V4 import WaveshareV4
from pwnagotchi.ui.hw.waveshare2in7 import Waveshare27inch
from pwnagotchi.ui.hw.waveshare2in7_V2 import Waveshare27inchV2
from pwnagotchi.ui.hw.waveshare2in9 import Waveshare29inch
from pwnagotchi.ui.hw.waveshare2in9_V2 import Waveshare29inchV2
from pwnagotchi.ui.hw.waveshare1in44lcd import Waveshare144lcd
from pwnagotchi.ui.hw.waveshare1in54b import Waveshare154inchb
from pwnagotchi.ui.hw.waveshare2in13bc import Waveshare213bc
from pwnagotchi.ui.hw.waveshare2in13d import Waveshare213d
from pwnagotchi.ui.hw.waveshare2in13g import Waveshare2in13g
from pwnagotchi.ui.hw.waveshare2in13b_V4 import Waveshare213bV4
from pwnagotchi.ui.hw.waveshare3in5lcd import Waveshare35lcd
from pwnagotchi.ui.hw.spotpear24in import Spotpear24inch
from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
from pwnagotchi.ui.hw.pitft import Pitft
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
from pwnagotchi.ui.hw.waveshare1in54_V2 import Waveshare154V2
from pwnagotchi.ui.hw.waveshare1in54b_V2 import Waveshare154bV2
from pwnagotchi.ui.hw.waveshare1in54c import Waveshare1in54c
from pwnagotchi.ui.hw.waveshare1in64g import Waveshare1in64g
from pwnagotchi.ui.hw.waveshare2in7b import Waveshare27b
from pwnagotchi.ui.hw.waveshare2in7b_V2 import Waveshare27bV2
from pwnagotchi.ui.hw.waveshare2in9b_V3 import Waveshare29bV3
from pwnagotchi.ui.hw.waveshare2in9b_V4 import Waveshare29bV4
from pwnagotchi.ui.hw.waveshare2in9bc import Waveshare2in9bc
from pwnagotchi.ui.hw.waveshare2in9d import Waveshare2in9d
from pwnagotchi.ui.hw.waveshare2in13b_V3 import Waveshare2in13bV3
from pwnagotchi.ui.hw.waveshare2in36g import Waveshare2in36g
from pwnagotchi.ui.hw.waveshare2in66 import Waveshare2in66
from pwnagotchi.ui.hw.waveshare2in66b import Waveshare2in66b
from pwnagotchi.ui.hw.waveshare2in66g import Waveshare2in66g
from pwnagotchi.ui.hw.waveshare3in0g import Waveshare3in0g
from pwnagotchi.ui.hw.waveshare3in7 import Waveshare3in7
from pwnagotchi.ui.hw.waveshare3in52 import Waveshare3in52
from pwnagotchi.ui.hw.waveshare4in01f import Waveshare4in01f
from pwnagotchi.ui.hw.waveshare4in2 import Waveshare4in2
from pwnagotchi.ui.hw.waveshare4in2_V2 import Waveshare4in2V2
from pwnagotchi.ui.hw.waveshare4in2b_V2 import Waveshare4in2bV2
from pwnagotchi.ui.hw.waveshare4in2bc import Waveshare4in2bc
from pwnagotchi.ui.hw.waveshare4in26 import Waveshare4in26
from pwnagotchi.ui.hw.waveshare4in37g import Waveshare4in37g
from pwnagotchi.ui.hw.waveshare5in65f import Waveshare5in65f
from pwnagotchi.ui.hw.waveshare5in79 import Waveshare5in79
from pwnagotchi.ui.hw.waveshare5in79b import Waveshare5in79b
from pwnagotchi.ui.hw.waveshare5in83 import Waveshare5in83
from pwnagotchi.ui.hw.waveshare5in83_V2 import Waveshare5in83V2
from pwnagotchi.ui.hw.waveshare5in83b_V2 import Waveshare5in83bV2
from pwnagotchi.ui.hw.waveshare5in83bc import Waveshare5in83bc
from pwnagotchi.ui.hw.waveshare7in3f import Waveshare7in3f
from pwnagotchi.ui.hw.waveshare7in3g import Waveshare7in3g
from pwnagotchi.ui.hw.waveshare7in5 import Waveshare7in5
from pwnagotchi.ui.hw.waveshare7in5_HD import Waveshare7in5HD
from pwnagotchi.ui.hw.waveshare7in5_V2 import Waveshare7in5V2
from pwnagotchi.ui.hw.waveshare7in5b_HD import Waveshare7in5bHD
from pwnagotchi.ui.hw.waveshare7in5b_V2 import Waveshare7in5bV2
from pwnagotchi.ui.hw.waveshare7in5bc import Waveshare7in5bc
from pwnagotchi.ui.hw.waveshare13in3k import Waveshare13in3k
def display_for(config): def display_for(config):
# config has been normalized already in utils.load_config # config has been normalized already in utils.load_config
if config['ui']['display']['type'] == 'inky': if config['ui']['display']['type'] == 'inky':
from pwnagotchi.ui.hw.inky import Inky
return Inky(config) return Inky(config)
elif config['ui']['display']['type'] == 'wavesharelcd0in96':
from pwnagotchi.ui.hw.wavesharelcd0in96 import Wavesharelcd0in96
return Wavesharelcd0in96(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in3':
from pwnagotchi.ui.hw.wavesharelcd1in3 import Wavesharelcd1in3
return Wavesharelcd1in3(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in8':
from pwnagotchi.ui.hw.wavesharelcd1in8 import Wavesharelcd1in8
return Wavesharelcd1in8(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in9':
from pwnagotchi.ui.hw.wavesharelcd1in9 import Wavesharelcd1in9
return Wavesharelcd1in9(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in14':
from pwnagotchi.ui.hw.wavesharelcd1in14 import Wavesharelcd1in14
return Wavesharelcd1in14(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in28':
from pwnagotchi.ui.hw.wavesharelcd1in28 import Wavesharelcd1in28
return Wavesharelcd1in28(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in47':
from pwnagotchi.ui.hw.wavesharelcd1in47 import Wavesharelcd1in47
return Wavesharelcd1in47(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in54':
from pwnagotchi.ui.hw.wavesharelcd1in54 import Wavesharelcd1in54
return Wavesharelcd1in54(config)
elif config['ui']['display']['type'] == 'wavesharelcd1in69':
from pwnagotchi.ui.hw.wavesharelcd1in69 import Wavesharelcd1in69
return Wavesharelcd1in69(config)
elif config['ui']['display']['type'] == 'wavesharelcd2in0':
from pwnagotchi.ui.hw.wavesharelcd2in0 import Wavesharelcd2in0
return Wavesharelcd2in0(config)
elif config['ui']['display']['type'] == 'wavesharelcd2in4':
from pwnagotchi.ui.hw.wavesharelcd2in4 import Wavesharelcd2in4
return Wavesharelcd2in4(config)
elif config['ui']['display']['type'] == 'dummydisplay':
from pwnagotchi.ui.hw.dummydisplay import DummyDisplay
return DummyDisplay(config)
elif config['ui']['display']['type'] == 'papirus': elif config['ui']['display']['type'] == 'papirus':
from pwnagotchi.ui.hw.papirus import Papirus
return Papirus(config) return Papirus(config)
elif config['ui']['display']['type'] == 'oledhat': elif config['ui']['display']['type'] == 'oledhat':
from pwnagotchi.ui.hw.oledhat import OledHat
return OledHat(config) return OledHat(config)
elif config['ui']['display']['type'] == 'lcdhat': elif config['ui']['display']['type'] == 'lcdhat':
from pwnagotchi.ui.hw.lcdhat import LcdHat
return LcdHat(config) return LcdHat(config)
elif config['ui']['display']['type'] == 'dfrobot_1': elif config['ui']['display']['type'] == 'dfrobot_1':
from pwnagotchi.ui.hw.dfrobot import DFRobotV1
return DFRobotV1(config) return DFRobotV1(config)
elif config['ui']['display']['type'] == 'dfrobot_2': elif config['ui']['display']['type'] == 'dfrobot_2':
from pwnagotchi.ui.hw.dfrobot_v2 import DFRobotV2
return DFRobotV2(config) return DFRobotV2(config)
elif config['ui']['display']['type'] == 'waveshare144lcd': elif config['ui']['display']['type'] == 'waveshare144lcd':
from pwnagotchi.ui.hw.waveshare1in44lcd import Waveshare144lcd
return Waveshare144lcd(config) return Waveshare144lcd(config)
elif config['ui']['display']['type'] == 'waveshare35lcd': elif config['ui']['display']['type'] == 'waveshare35lcd':
from pwnagotchi.ui.hw.waveshare3in5lcd import Waveshare35lcd
return Waveshare35lcd(config) return Waveshare35lcd(config)
elif config['ui']['display']['type'] == 'spotpear24inch': elif config['ui']['display']['type'] == 'spotpear24inch':
from pwnagotchi.ui.hw.spotpear24in import Spotpear24inch
return Spotpear24inch(config) return Spotpear24inch(config)
elif config['ui']['display']['type'] == 'displayhatmini': elif config['ui']['display']['type'] == 'displayhatmini':
from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
return DisplayHatMini(config) return DisplayHatMini(config)
elif config['ui']['display']['type'] == 'pirateaudio': elif config['ui']['display']['type'] == 'pirateaudio':
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
return PirateAudio(config) return PirateAudio(config)
elif config['ui']['display']['type'] == 'pitft': elif config['ui']['display']['type'] == 'pitft':
from pwnagotchi.ui.hw.pitft import Pitft
return Pitft(config) return Pitft(config)
elif config['ui']['display']['type'] == 'tftbonnet': elif config['ui']['display']['type'] == 'tftbonnet':
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
return TftBonnet(config) return TftBonnet(config)
elif config['ui']['display']['type'] == 'waveshareoledlcd': elif config['ui']['display']['type'] == 'waveshareoledlcd':
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
return Waveshareoledlcd(config) 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': elif config['ui']['display']['type'] == 'waveshare1in02':
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
return Waveshare1in02(config) return Waveshare1in02(config)
elif config['ui']['display']['type'] == 'waveshare1in54': elif config['ui']['display']['type'] == 'waveshare1in54':
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
return Waveshare154(config) return Waveshare154(config)
elif config['ui']['display']['type'] == 'waveshare1in54_v2': elif config['ui']['display']['type'] == 'waveshare1in54_v2':
from pwnagotchi.ui.hw.waveshare1in54_V2 import Waveshare154V2
return Waveshare154V2(config) return Waveshare154V2(config)
elif config['ui']['display']['type'] == 'waveshare1in54b': elif config['ui']['display']['type'] == 'waveshare1in54b':
from pwnagotchi.ui.hw.waveshare1in54b import Waveshare154inchb
return Waveshare154inchb(config) return Waveshare154inchb(config)
elif config['ui']['display']['type'] == 'waveshare1in54b_v2': elif config['ui']['display']['type'] == 'waveshare1in54b_v2':
from pwnagotchi.ui.hw.waveshare1in54b_V2 import Waveshare154bV2
return Waveshare154bV2(config) return Waveshare154bV2(config)
elif config['ui']['display']['type'] == 'waveshare1in54c': elif config['ui']['display']['type'] == 'waveshare1in54c':
from pwnagotchi.ui.hw.waveshare1in54c import Waveshare1in54c
return Waveshare1in54c(config) return Waveshare1in54c(config)
elif config['ui']['display']['type'] == 'waveshare1in64g': elif config['ui']['display']['type'] == 'waveshare1in64g':
from pwnagotchi.ui.hw.waveshare1in64g import Waveshare1in64g
return Waveshare1in64g(config) return Waveshare1in64g(config)
elif config['ui']['display']['type'] == 'waveshare2in7': elif config['ui']['display']['type'] == 'waveshare2in7':
from pwnagotchi.ui.hw.waveshare2in7 import Waveshare27inch
return Waveshare27inch(config) return Waveshare27inch(config)
elif config['ui']['display']['type'] == 'waveshare2in7_v2': elif config['ui']['display']['type'] == 'waveshare2in7_v2':
from pwnagotchi.ui.hw.waveshare2in7_V2 import Waveshare27inchV2
return Waveshare27inchV2(config) return Waveshare27inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in7b': elif config['ui']['display']['type'] == 'waveshare2in7b':
from pwnagotchi.ui.hw.waveshare2in7b import Waveshare27b
return Waveshare27b(config) return Waveshare27b(config)
elif config['ui']['display']['type'] == 'waveshare2in7b_v2': elif config['ui']['display']['type'] == 'waveshare2in7b_v2':
from pwnagotchi.ui.hw.waveshare2in7b_V2 import Waveshare27bV2
return Waveshare27bV2(config) return Waveshare27bV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9': elif config['ui']['display']['type'] == 'waveshare2in9':
from pwnagotchi.ui.hw.waveshare2in9 import Waveshare29inch
return Waveshare29inch(config) return Waveshare29inch(config)
elif config['ui']['display']['type'] == 'waveshare2in9bc': elif config['ui']['display']['type'] == 'waveshare2in9bc':
from pwnagotchi.ui.hw.waveshare2in9bc import Waveshare2in9bc
return Waveshare2in9bc(config) return Waveshare2in9bc(config)
elif config['ui']['display']['type'] == 'waveshare2in9d': elif config['ui']['display']['type'] == 'waveshare2in9d':
from pwnagotchi.ui.hw.waveshare2in9d import Waveshare2in9d
return Waveshare2in9d(config) return Waveshare2in9d(config)
elif config['ui']['display']['type'] == 'waveshare2in9_v2': elif config['ui']['display']['type'] == 'waveshare2in9_v2':
from pwnagotchi.ui.hw.waveshare2in9_V2 import Waveshare29inchV2
return Waveshare29inchV2(config) return Waveshare29inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9b_v3': elif config['ui']['display']['type'] == 'waveshare2in9b_v3':
from pwnagotchi.ui.hw.waveshare2in9b_V3 import Waveshare29bV3
return Waveshare29bV3(config) return Waveshare29bV3(config)
elif config['ui']['display']['type'] == 'waveshare2in9b_v4': elif config['ui']['display']['type'] == 'waveshare2in9b_v4':
from pwnagotchi.ui.hw.waveshare2in9b_V4 import Waveshare29bV4
return Waveshare29bV4(config) return Waveshare29bV4(config)
elif config['ui']['display']['type'] == 'waveshare_1': elif config['ui']['display']['type'] == 'waveshare_1':
from pwnagotchi.ui.hw.waveshare2in13 import WaveshareV1
return WaveshareV1(config) return WaveshareV1(config)
elif config['ui']['display']['type'] == 'waveshare_2': elif config['ui']['display']['type'] == 'waveshare_2':
from pwnagotchi.ui.hw.waveshare2in13_V2 import WaveshareV2
return WaveshareV2(config) return WaveshareV2(config)
elif config['ui']['display']['type'] == 'waveshare_3': elif config['ui']['display']['type'] == 'waveshare_3':
from pwnagotchi.ui.hw.waveshare2in13_V3 import WaveshareV3
return WaveshareV3(config) return WaveshareV3(config)
elif config['ui']['display']['type'] == 'waveshare_4': elif config['ui']['display']['type'] == 'waveshare_4':
from pwnagotchi.ui.hw.waveshare2in13_V4 import WaveshareV4
return WaveshareV4(config) return WaveshareV4(config)
elif config['ui']['display']['type'] == 'adafruit2in13_v3':
from pwnagotchi.ui.hw.adafruit2in13 import Adafruit2in13V3
return Adafruit2in13V3(config)
elif config['ui']['display']['type'] == 'waveshare2in13bc': elif config['ui']['display']['type'] == 'waveshare2in13bc':
from pwnagotchi.ui.hw.waveshare2in13bc import Waveshare213bc
return Waveshare213bc(config) return Waveshare213bc(config)
elif config['ui']['display']['type'] == 'waveshare2in13d': elif config['ui']['display']['type'] == 'waveshare2in13d':
from pwnagotchi.ui.hw.waveshare2in13d import Waveshare213d
return Waveshare213d(config) return Waveshare213d(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v3': elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
from pwnagotchi.ui.hw.waveshare2in13b_V3 import Waveshare2in13bV3
return Waveshare2in13bV3(config) return Waveshare2in13bV3(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v4': elif config['ui']['display']['type'] == 'waveshare2in13b_v4':
from pwnagotchi.ui.hw.waveshare2in13b_V4 import Waveshare213bV4
return Waveshare213bV4(config) return Waveshare213bV4(config)
elif config['ui']['display']['type'] == 'waveshare2in13g': elif config['ui']['display']['type'] == 'waveshare2in13g':
from pwnagotchi.ui.hw.waveshare2in13g import Waveshare2in13g
return Waveshare2in13g(config) return Waveshare2in13g(config)
elif config['ui']['display']['type'] == 'waveshare2in36g': elif config['ui']['display']['type'] == 'waveshare2in36g':
from pwnagotchi.ui.hw.waveshare2in36g import Waveshare2in36g
return Waveshare2in36g(config) return Waveshare2in36g(config)
elif config['ui']['display']['type'] == 'waveshare2in66': elif config['ui']['display']['type'] == 'waveshare2in66':
from pwnagotchi.ui.hw.waveshare2in66 import Waveshare2in66
return Waveshare2in66(config) return Waveshare2in66(config)
elif config['ui']['display']['type'] == 'waveshare2in66b': elif config['ui']['display']['type'] == 'waveshare2in66b':
from pwnagotchi.ui.hw.waveshare2in66b import Waveshare2in66b
return Waveshare2in66b(config) return Waveshare2in66b(config)
elif config['ui']['display']['type'] == 'waveshare2in66g': elif config['ui']['display']['type'] == 'waveshare2in66g':
from pwnagotchi.ui.hw.waveshare2in66g import Waveshare2in66g
return Waveshare2in66g(config) return Waveshare2in66g(config)
elif config['ui']['display']['type'] == 'waveshare3in0g': elif config['ui']['display']['type'] == 'waveshare3in0g':
from pwnagotchi.ui.hw.waveshare3in0g import Waveshare3in0g
return Waveshare3in0g(config) return Waveshare3in0g(config)
elif config['ui']['display']['type'] == 'waveshare3in7': elif config['ui']['display']['type'] == 'waveshare3in7':
from pwnagotchi.ui.hw.waveshare3in7 import Waveshare3in7
return Waveshare3in7(config) return Waveshare3in7(config)
elif config['ui']['display']['type'] == 'waveshare3in52': elif config['ui']['display']['type'] == 'waveshare3in52':
from pwnagotchi.ui.hw.waveshare3in52 import Waveshare3in52
return Waveshare3in52(config) return Waveshare3in52(config)
elif config['ui']['display']['type'] == 'waveshare4in01f': elif config['ui']['display']['type'] == 'waveshare4in01f':
from pwnagotchi.ui.hw.waveshare4in01f import Waveshare4in01f
return Waveshare4in01f(config) return Waveshare4in01f(config)
elif config['ui']['display']['type'] == 'waveshare4in2': elif config['ui']['display']['type'] == 'waveshare4in2':
from pwnagotchi.ui.hw.waveshare4in2 import Waveshare4in2
return Waveshare4in2(config) return Waveshare4in2(config)
elif config['ui']['display']['type'] == 'waveshare4in2_v2': elif config['ui']['display']['type'] == 'waveshare4in2_v2':
from pwnagotchi.ui.hw.waveshare4in2_V2 import Waveshare4in2V2
return Waveshare4in2V2(config) return Waveshare4in2V2(config)
elif config['ui']['display']['type'] == 'waveshare4in2b_v2': elif config['ui']['display']['type'] == 'waveshare4in2b_v2':
from pwnagotchi.ui.hw.waveshare4in2b_V2 import Waveshare4in2bV2
return Waveshare4in2bV2(config) return Waveshare4in2bV2(config)
elif config['ui']['display']['type'] == 'waveshare4in2bc': elif config['ui']['display']['type'] == 'waveshare4in2bc':
from pwnagotchi.ui.hw.waveshare4in2bc import Waveshare4in2bc
return Waveshare4in2bc(config) return Waveshare4in2bc(config)
elif config['ui']['display']['type'] == 'waveshare4in26': elif config['ui']['display']['type'] == 'waveshare4in26':
from pwnagotchi.ui.hw.waveshare4in26 import Waveshare4in26
return Waveshare4in26(config) return Waveshare4in26(config)
elif config['ui']['display']['type'] == 'waveshare4in37g': elif config['ui']['display']['type'] == 'waveshare4in37g':
from pwnagotchi.ui.hw.waveshare4in37g import Waveshare4in37g
return Waveshare4in37g(config) return Waveshare4in37g(config)
elif config['ui']['display']['type'] == 'waveshare5in65f': elif config['ui']['display']['type'] == 'waveshare5in65f':
from pwnagotchi.ui.hw.waveshare5in65f import Waveshare5in65f
return Waveshare5in65f(config) return Waveshare5in65f(config)
elif config['ui']['display']['type'] == 'waveshare5in79': elif config['ui']['display']['type'] == 'waveshare5in79':
from pwnagotchi.ui.hw.waveshare5in79 import Waveshare5in79
return Waveshare5in79(config) return Waveshare5in79(config)
elif config['ui']['display']['type'] == 'waveshare5in79b': elif config['ui']['display']['type'] == 'waveshare5in79b':
from pwnagotchi.ui.hw.waveshare5in79b import Waveshare5in79b
return Waveshare5in79b(config) return Waveshare5in79b(config)
elif config['ui']['display']['type'] == 'waveshare5in83': elif config['ui']['display']['type'] == 'waveshare5in83':
from pwnagotchi.ui.hw.waveshare5in83 import Waveshare5in83
return Waveshare5in83(config) return Waveshare5in83(config)
elif config['ui']['display']['type'] == 'waveshare5in83_v2': elif config['ui']['display']['type'] == 'waveshare5in83_v2':
from pwnagotchi.ui.hw.waveshare5in83_V2 import Waveshare5in83V2
return Waveshare5in83V2(config) return Waveshare5in83V2(config)
elif config['ui']['display']['type'] == 'waveshare5in83b_v2': elif config['ui']['display']['type'] == 'waveshare5in83b_v2':
from pwnagotchi.ui.hw.waveshare5in83b_V2 import Waveshare5in83bV2
return Waveshare5in83bV2(config) return Waveshare5in83bV2(config)
elif config['ui']['display']['type'] == 'waveshare5in83bc': elif config['ui']['display']['type'] == 'waveshare5in83bc':
from pwnagotchi.ui.hw.waveshare5in83bc import Waveshare5in83bc
return Waveshare5in83bc(config) return Waveshare5in83bc(config)
elif config['ui']['display']['type'] == 'waveshare7in3f': elif config['ui']['display']['type'] == 'waveshare7in3f':
from pwnagotchi.ui.hw.waveshare7in3f import Waveshare7in3f
return Waveshare7in3f(config) return Waveshare7in3f(config)
elif config['ui']['display']['type'] == 'waveshare7in3g': elif config['ui']['display']['type'] == 'waveshare7in3g':
from pwnagotchi.ui.hw.waveshare7in3g import Waveshare7in3g
return Waveshare7in3g(config) return Waveshare7in3g(config)
elif config['ui']['display']['type'] == 'waveshare7in5': elif config['ui']['display']['type'] == 'waveshare7in5':
from pwnagotchi.ui.hw.waveshare7in5 import Waveshare7in5
return Waveshare7in5(config) return Waveshare7in5(config)
elif config['ui']['display']['type'] == 'waveshare7in5_HD': elif config['ui']['display']['type'] == 'waveshare7in5_HD':
from pwnagotchi.ui.hw.waveshare7in5_HD import Waveshare7in5HD
return Waveshare7in5HD(config) return Waveshare7in5HD(config)
elif config['ui']['display']['type'] == 'waveshare7in5_v2': elif config['ui']['display']['type'] == 'waveshare7in5_v2':
from pwnagotchi.ui.hw.waveshare7in5_V2 import Waveshare7in5V2
return Waveshare7in5V2(config) return Waveshare7in5V2(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_HD': elif config['ui']['display']['type'] == 'waveshare7in5b_HD':
from pwnagotchi.ui.hw.waveshare7in5b_HD import Waveshare7in5bHD
return Waveshare7in5bHD(config) return Waveshare7in5bHD(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_v2': elif config['ui']['display']['type'] == 'waveshare7in5b_v2':
from pwnagotchi.ui.hw.waveshare7in5b_V2 import Waveshare7in5bV2
return Waveshare7in5bV2(config) return Waveshare7in5bV2(config)
elif config['ui']['display']['type'] == 'waveshare7in5bc': elif config['ui']['display']['type'] == 'waveshare7in5bc':
from pwnagotchi.ui.hw.waveshare7in5bc import Waveshare7in5bc
return Waveshare7in5bc(config) return Waveshare7in5bc(config)
elif config['ui']['display']['type'] == 'waveshare13in3k': elif config['ui']['display']['type'] == 'waveshare13in3k':
from pwnagotchi.ui.hw.waveshare13in3k import Waveshare13in3k
return Waveshare13in3k(config) return Waveshare13in3k(config)

View File

@ -0,0 +1,45 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class Adafruit2in13V3(DisplayImpl):
def __init__(self, config):
super(Adafruit2in13V3, self).__init__(config, 'adafruit2in13_v3')
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250
self._layout['height'] = 122
self._layout['face'] = (0, 40)
self._layout['name'] = (5, 20)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (28, 0)
self._layout['uptime'] = (185, 0)
self._layout['line1'] = [0, 14, 250, 14]
self._layout['line2'] = [0, 108, 250, 108]
self._layout['friend_face'] = (0, 92)
self._layout['friend_name'] = (40, 94)
self._layout['shakes'] = (0, 109)
self._layout['mode'] = (225, 109)
self._layout['status'] = {
'pos': (125, 20),
'font': fonts.status_font(fonts.Medium),
'max': 20
}
return self._layout
def initialize(self):
logging.info("initializing adafruit 2in13 V3 display")
from pwnagotchi.ui.hw.libs.adafruit.v2in13_v3.epd2in13_v3 import EPD
self._display = EPD()
self._display.init()
self._display.Clear(0xFF)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.displayPartial(buf)
def clear(self):
self._display.Clear(0xFF)

View File

@ -34,10 +34,10 @@ class DisplayHatMini(DisplayImpl):
def initialize(self): def initialize(self):
logging.info("initializing Display Hat Mini") logging.info("initializing Display Hat Mini")
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789 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): def render(self, canvas):
self._display.display(canvas) self._display.display(canvas)
def clear(self): def clear(self):
self._display.clear() pass

View File

@ -0,0 +1,43 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DummyDisplay(DisplayImpl):
def __init__(self, config):
super(DummyDisplay, self).__init__(config, 'DummyDisplay')
def layout(self):
width = 480 if 'width' not in self.config else self.config['width']
height = 720 if 'height' not in self.config else self.config['height']
fonts.setup(int(height/30), int(height/40), int(height/30), int(height/6), int(height/30), int(height/35))
self._layout['width'] = width
self._layout['height'] = height
self._layout['face'] = (0, int(width/12))
self._layout['name'] = (5, int(width/25))
self._layout['channel'] = (0, 0)
self._layout['aps'] = (int(width/8), 0)
self._layout['uptime'] = (width-int(width/12), 0)
self._layout['line1'] = [0, int(height/32), width, int(height/32)]
self._layout['line2'] = [0, height-int(height/25)-1, width, height-int(height/25)-1]
self._layout['friend_face'] = (0, int(height/10))
self._layout['friend_name'] = (int(width/12), int(height/10))
self._layout['shakes'] = (0, height-int(height/25))
self._layout['mode'] = (width-int(width/8), height - int (height/25))
lw, lh = fonts.Small.getsize("W")
self._layout['status'] = {
'pos': (int(width/48), int(height/3)),
'font': fonts.status_font(fonts.Small),
'max': int(width / lw)
}
return self._layout
def initialize(self):
return
def render(self, canvas):
return
def clear(self):
return

View File

@ -0,0 +1,67 @@
# 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
# 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'] = 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)
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):
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(address=i2caddr, width=width, height=height)
self._display.Init()
self._display.Clear()
def render(self, canvas):
self._display.display(canvas)
def clear(self):
self._display.clear()

View File

@ -33,7 +33,7 @@ class LcdHat(DisplayImpl):
def initialize(self): def initialize(self):
logging.info("initializing lcdhat display") logging.info("initializing lcdhat display")
from pwnagotchi.ui.hw.libs.waveshare.lcdhat.epd import EPD from pwnagotchi.ui.hw.libs.waveshare.lcd.lcdhat.epd import EPD
self._display = EPD() self._display = EPD()
self._display.init() self._display.init()
self._display.clear() self._display.clear()

View File

@ -0,0 +1,132 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.2
# * | Date : 2022-10-29
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import os
import logging
import sys
import time
import subprocess
logger = logging.getLogger(__name__)
class RaspberryPi:
# Pin definition
RST_PIN = 27
DC_PIN = 22
CS_PIN = 8
BUSY_PIN = 17
PWR_PIN = 18
def __init__(self):
import spidev
import gpiozero
self.SPI = spidev.SpiDev()
self.GPIO_RST_PIN = gpiozero.LED(self.RST_PIN)
self.GPIO_DC_PIN = gpiozero.LED(self.DC_PIN)
self.GPIO_CS_PIN = gpiozero.LED(self.CS_PIN)
self.GPIO_PWR_PIN = gpiozero.LED(self.PWR_PIN)
self.GPIO_BUSY_PIN = gpiozero.Button(self.BUSY_PIN, pull_up=False)
def digital_write(self, pin, value):
if pin == self.RST_PIN:
if value:
self.GPIO_RST_PIN.on()
else:
self.GPIO_RST_PIN.off()
elif pin == self.DC_PIN:
if value:
self.GPIO_DC_PIN.on()
else:
self.GPIO_DC_PIN.off()
elif pin == self.CS_PIN:
if value:
self.GPIO_CS_PIN.on()
else:
self.GPIO_CS_PIN.off()
elif pin == self.PWR_PIN:
if value:
self.GPIO_PWR_PIN.on()
else:
self.GPIO_PWR_PIN.off()
def digital_read(self, pin):
if pin == self.BUSY_PIN:
return self.GPIO_BUSY_PIN.value
elif pin == self.RST_PIN:
return self.RST_PIN.value
elif pin == self.DC_PIN:
return self.DC_PIN.value
elif pin == self.CS_PIN:
return self.CS_PIN.value
elif pin == self.PWR_PIN:
return self.PWR_PIN.value
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def spi_writebyte2(self, data):
self.SPI.writebytes2(data)
def module_init(self):
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
return 0
def module_exit(self, cleanup=False):
logger.debug("spi end")
self.SPI.close()
self.GPIO_RST_PIN.off()
self.GPIO_DC_PIN.off()
self.GPIO_PWR_PIN.off()
logger.debug("close 5V, Module enters 0 power consumption ...")
if cleanup:
self.GPIO_RST_PIN.close()
self.GPIO_DC_PIN.close()
self.GPIO_CS_PIN.close()
self.GPIO_PWR_PIN.close()
self.GPIO_BUSY_PIN.close()
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 ###

View File

@ -93,6 +93,7 @@ ILI9341_GMCTRN1 = 0xE1
ILI9341_PWCTR6 = 0xFC ILI9341_PWCTR6 = 0xFC
class ILI9341(object): class ILI9341(object):
"""Representation of an ILI9341 TFT LCD.""" """Representation of an ILI9341 TFT LCD."""
@ -349,7 +350,6 @@ class ILI9341(object):
# Rotate the image # Rotate the image
pb = np.rot90(image, rotation // 90).astype('uint16') pb = np.rot90(image, rotation // 90).astype('uint16')
# Mask and shift the 888 RGB into 565 RGB # Mask and shift the 888 RGB into 565 RGB
red = (pb[..., [0]] & 0xf8) << 8 red = (pb[..., [0]] & 0xf8) << 8
green = (pb[..., [1]] & 0xfc) << 3 green = (pb[..., [1]] & 0xfc) << 3

View File

@ -1,144 +1,164 @@
FBIOGET_VSCREENINFO=0x4600 FBIOGET_VSCREENINFO = 0x4600
FBIOPUT_VSCREENINFO=0x4601 FBIOPUT_VSCREENINFO = 0x4601
FBIOGET_FSCREENINFO=0x4602 FBIOGET_FSCREENINFO = 0x4602
FBIOGETCMAP=0x4604 FBIOGETCMAP = 0x4604
FBIOPUTCMAP=0x4605 FBIOPUTCMAP = 0x4605
FBIOPAN_DISPLAY=0x4606 FBIOPAN_DISPLAY = 0x4606
FBIOGET_CON2FBMAP=0x460F FBIOGET_CON2FBMAP = 0x460F
FBIOPUT_CON2FBMAP=0x4610 FBIOPUT_CON2FBMAP = 0x4610
FBIOBLANK=0x4611 FBIOBLANK = 0x4611
FBIO_ALLOC=0x4613 FBIO_ALLOC = 0x4613
FBIO_FREE=0x4614 FBIO_FREE = 0x4614
FBIOGET_GLYPH=0x4615 FBIOGET_GLYPH = 0x4615
FBIOGET_HWCINFO=0x4616 FBIOGET_HWCINFO = 0x4616
FBIOPUT_MODEINFO=0x4617 FBIOPUT_MODEINFO = 0x4617
FBIOGET_DISPINFO=0x4618 FBIOGET_DISPINFO = 0x4618
from mmap import mmap from mmap import mmap
from fcntl import ioctl from fcntl import ioctl
import struct import struct
mm = None mm = None
bpp, w, h = 0, 0, 0 # framebuffer bpp and size bpp, w, h = 0, 0, 0 # framebuffer bpp and size
bytepp = 0 bytepp = 0
vx, vy, vw, vh = 0, 0, 0, 0 #virtual window offset and size vx, vy, vw, vh = 0, 0, 0, 0 # virtual window offset and size
vi, fi = None, None vi, fi = None, None
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a _fb_cmap = 'IIPPPP' # start, len, r, g, b, a
RGB = False RGB = False
_verbose = False _verbose = False
msize_kb = 0 msize_kb = 0
def report_fb(i=0, layer=0): def report_fb(i=0, layer=0):
with open('/dev/fb'+str(i), 'r+b')as f: with open('/dev/fb' + str(i), 'r+b') as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160)) vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I'*40, vi)) vi = list(struct.unpack('I' * 40, vi))
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH' ffm = 'c' * 16 + 'L' + 'I' * 4 + 'H' * 3 + 'ILIIHHH'
fic = struct.calcsize(ffm) fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic))) fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
def ready_fb(_bpp=None, i=0, layer=0, _win=None): def ready_fb(_bpp=None, i=0, layer=0, _win=None):
global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp
if mm and bpp == _bpp: return mm, w, h, bpp if mm and bpp == _bpp:
with open('/dev/fb'+str(i), 'r+b')as f: return mm, w, h, bpp
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160)) with open('/dev/fb' + str(i), 'r+b') as f:
vi = list(struct.unpack('I'*40, vi)) vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
bpp = vi[6] vi = list(struct.unpack('I' * 40, vi))
bytepp = bpp//8
if _bpp:
vi[6] = _bpp # 24 bit = BGR 888 mode
try:
vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I'*40, *vi)) # fb_var_screeninfo
vi = struct.unpack('I'*40,vi)
bpp = vi[6] bpp = vi[6]
bytepp = bpp//8 bytepp = bpp // 8
except: if _bpp:
pass vi[6] = _bpp # 24 bit = BGR 888 mode
try:
if vi[8] == 0 : RGB = True vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I' * 40, *vi)) # fb_var_screeninfo
vi = struct.unpack('I' * 40, vi)
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH' bpp = vi[6]
fic = struct.calcsize(ffm) bytepp = bpp // 8
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic))) except:
msize = fi[17] # = w*h*bpp//8 pass
ll, start = fi[-7:-5]
w, h = ll//bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.
if _win and len(_win)==4: # virtual window settings
vx, vy, vw, vh = _win
if vw == 'w': vw = w
if vh == 'h': vh = h
vx, vy, vw, vh = map(int, (vx, vy, vw, vh))
if vx>=w: vx = 0
if vy>=h: vy = 0
if vx>w: vw = w - vx
else: vw -= vx
if vy>h: vh = h - vy
else: vh -= vy
else:
vx, vy, vw, vh = 0,0,w,h
msize_kb = vw*vh*bytepp//1024 # more accurate FB memory size in kb
mm = mmap(f.fileno(), msize, offset=start) if vi[8] == 0:
return mm, w, h, bpp#ll//(bpp//8), h RGB = True
ffm = 'c' * 16 + 'L' + 'I' * 4 + 'H' * 3 + 'ILIIHHH'
fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
msize = fi[17] # = w*h*bpp//8
ll, start = fi[-7:-5]
w, h = ll // bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.
if _win and len(_win) == 4: # virtual window settings
vx, vy, vw, vh = _win
if vw == 'w':
vw = w
if vh == 'h':
vh = h
vx, vy, vw, vh = map(int, (vx, vy, vw, vh))
if vx >= w:
vx = 0
if vy >= h:
vy = 0
if vx > w:
vw = w - vx
else:
vw -= vx
if vy > h:
vh = h - vy
else:
vh -= vy
else:
vx, vy, vw, vh = 0, 0, w, h
msize_kb = vw * vh * bytepp // 1024 # more accurate FB memory size in kb
mm = mmap(f.fileno(), msize, offset=start)
return mm, w, h, bpp # ll//(bpp//8), h
def fill_scr(r, g, b):
if bpp == 32:
seed = struct.pack('BBBB', b, g, r, 255)
elif bpp == 24:
seed = struct.pack('BBB', b, g, r)
elif bpp == 16:
seed = struct.pack('H', r >> 3 << 11 | g >> 2 << 5 | b >> 3)
mm.seek(0)
show_img(seed * vw * vh)
def fill_scr(r,g,b):
if bpp == 32:
seed = struct.pack('BBBB', b, g, r, 255)
elif bpp == 24:
seed = struct.pack('BBB', b, g, r)
elif bpp == 16:
seed = struct.pack('H', r>>3<<11 | g>>2<<5 | b>>3)
mm.seek(0)
show_img(seed * vw * vh)
def black_scr(): def black_scr():
fill_scr(0,0,0) fill_scr(0, 0, 0)
def white_scr(): def white_scr():
fill_scr(255,255,255) fill_scr(255, 255, 255)
def mmseekto(x, y):
mm.seek((x + y * w) * bytepp)
def mmseekto(x,y):
mm.seek((x + y*w) * bytepp)
def dot(x, y, r, g, b): def dot(x, y, r, g, b):
mmseekto(x,y) mmseekto(x, y)
mm.write(struct.pack('BBB',*((r,g,b) if RGB else (b,g,r)))) mm.write(struct.pack('BBB', *((r, g, b) if RGB else (b, g, r))))
def get_pixel(x, y):
mmseekto(x, y)
return mm.read(bytepp)
def get_pixel(x,y):
mmseekto(x,y)
return mm.read(bytepp)
def _888_to_565(bt): def _888_to_565(bt):
b = b'' b = b''
for i in range(0, len(bt),3): for i in range(0, len(bt), 3):
b += int.to_bytes(bt[i]>>3<<11|bt[i+1]>>2<<5|bt[i+2]>>3, 2, 'little') b += int.to_bytes(bt[i] >> 3 << 11 | bt[i + 1] >> 2 << 5 | bt[i + 2] >> 3, 2, 'little')
return b return b
def numpy_888_565(bt): def numpy_888_565(bt):
import numpy as np import numpy as np
arr = np.fromstring(bt, dtype=np.uint32) arr = np.fromstring(bt, dtype=np.uint32)
return (((0xF80000 & arr)>>8)|((0xFC00 & arr)>>5)|((0xF8 & arr)>>3)).astype(np.uint16).tostring() return (((0xF80000 & arr) >> 8) | ((0xFC00 & arr) >> 5) | ((0xF8 & arr) >> 3)).astype(np.uint16).tostring()
def show_img(img): def show_img(img):
if not type(img) is bytes: if not type(img) is bytes:
if not RGB: if not RGB:
if bpp == 24: # for RPI if bpp == 24: # for RPI
img = img.tobytes('raw', 'BGR') img = img.tobytes('raw', 'BGR')
else: else:
img = img.convert('RGBA').tobytes('raw', 'BGRA') img = img.convert('RGBA').tobytes('raw', 'BGRA')
if bpp == 16: if bpp == 16:
img = numpy_888_565(img) img = numpy_888_565(img)
else: else:
if bpp == 24: if bpp == 24:
img = img.tobytes() img = img.tobytes()
else: else:
img = img.convert('RGBA').tobytes() img = img.convert('RGBA').tobytes()
if bpp == 16: if bpp == 16:
img = numpy_888_565(img) img = numpy_888_565(img)
from io import BytesIO from io import BytesIO
b = BytesIO(img) b = BytesIO(img)
s = vw*bytepp s = vw * bytepp
for y in range(vh): # virtual window drawing for y in range(vh): # virtual window drawing
mmseekto(vx,vy+y) mmseekto(vx, vy + y)
mm.write(b.read(s)) mm.write(b.read(s))

View File

@ -0,0 +1,312 @@
# 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)
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.
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."""
# 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.
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.
"""
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_32, self).__init__(128, 32, 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

View File

@ -0,0 +1,34 @@
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
class EPD(object):
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):
self.disp.begin()
def Clear(self):
self.disp.clear()
def display(self, image):
self.disp.getbuffer(image)
self.disp.ShowImage()

View File

@ -90,8 +90,8 @@ ST7789_PWCTR6 = 0xFC
class ST7789(object): class ST7789(object):
"""Representation of an ST7789 TFT LCD.""" """Representation of an ST7789 TFT LCD."""
def __init__(self, port, cs, dc, backlight, rst=None, width=320, def __init__(self, port, cs, dc, backlight=None, rst=None, width=240,
height=240, rotation=0, invert=True, spi_speed_hz=60 * 1000 * 1000, height=240, rotation=90, invert=True, spi_speed_hz=4000000,
offset_left=0, offset_left=0,
offset_top=0): offset_top=0):
"""Create an instance of the display using SPI communication. """Create an instance of the display using SPI communication.

View File

@ -31,7 +31,6 @@ import os
import logging import logging
import sys import sys
import time import time
import subprocess
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -113,6 +112,7 @@ class RaspberryPi:
self.GPIO_RST_PIN.off() self.GPIO_RST_PIN.off()
self.GPIO_DC_PIN.off() self.GPIO_DC_PIN.off()
self.GPIO_CS_PIN.off()
self.GPIO_PWR_PIN.off() self.GPIO_PWR_PIN.off()
logger.debug("close 5V, Module enters 0 power consumption ...") logger.debug("close 5V, Module enters 0 power consumption ...")

View File

@ -29,7 +29,7 @@
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 960 EPD_WIDTH = 960

View File

@ -29,7 +29,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 80 EPD_WIDTH = 80

View File

@ -80,7 +80,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 200 EPD_WIDTH = 200

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 200 EPD_WIDTH = 200

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 200 EPD_WIDTH = 200

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 200 EPD_WIDTH = 200

View File

@ -27,7 +27,7 @@
# THE SOFTWARE. # THE SOFTWARE.
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 152 EPD_WIDTH = 152

View File

@ -29,11 +29,9 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import PIL
from PIL import Image from PIL import Image
import io
# Display resolution # Display resolution
EPD_WIDTH = 168 EPD_WIDTH = 168

View File

@ -29,7 +29,7 @@
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -27,7 +27,7 @@
# THE SOFTWARE. # THE SOFTWARE.
# #
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
# import numpy as np # import numpy as np

View File

@ -40,9 +40,8 @@
import logging import logging
from . import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
from PIL import Image from PIL import Image
import RPi.GPIO as GPIO
# Display resolution # Display resolution
EPD_WIDTH = 104 EPD_WIDTH = 104

View File

@ -29,7 +29,7 @@
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -4,8 +4,8 @@
# * | Function : Electronic paper driver # * | Function : Electronic paper driver
# * | Info : # * | Info :
# *---------------- # *----------------
# * | This version: V1.1 # * | This version: V1.2
# * | Date : 2021-10-30 # * | Date : 2022-08-9
# # | Info : python demo # # | Info : python demo
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
@ -29,15 +29,15 @@
import logging import logging
from . import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import numpy as np
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122
EPD_HEIGHT = 250 EPD_HEIGHT = 250
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class EPD: class EPD:
def __init__(self): def __init__(self):
self.reset_pin = epdconfig.RST_PIN self.reset_pin = epdconfig.RST_PIN
@ -46,68 +46,70 @@ class EPD:
self.cs_pin = epdconfig.CS_PIN self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH self.width = EPD_WIDTH
self.height = EPD_HEIGHT self.height = EPD_HEIGHT
lut_partial_update= [ lut_partial_update = [
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x14,0x0,0x0,0x0,0x0,0x0,0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
0x22,0x17,0x41,0x00,0x32,0x36, 0x22, 0x17, 0x41, 0x00, 0x32, 0x36,
] ]
lut_full_update = [ lut_full_update = [
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xF,0x0,0x0,0x0,0x0,0x0,0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xF,0x0,0x0,0xF,0x0,0x0,0x2, 0xF, 0x0, 0x0, 0xF, 0x0, 0x0, 0x2,
0xF,0x0,0x0,0x0,0x0,0x0,0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
0x22,0x17,0x41,0x0,0x32,0x36, 0x22, 0x17, 0x41, 0x0, 0x32, 0x36,
] ]
''' '''
function :Hardware reset function :Hardware reset
parameter: parameter:
''' '''
def reset(self): def reset(self):
epdconfig.digital_write(self.reset_pin, 1) epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20) epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0) epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2) epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1) epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20) epdconfig.delay_ms(20)
''' '''
function :send command function :send command
parameter: parameter:
command : Command register command : Command register
''' '''
def send_command(self, command): def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0) epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0) epdconfig.digital_write(self.cs_pin, 0)
@ -119,71 +121,84 @@ class EPD:
parameter: parameter:
data : Write data data : Write data
''' '''
def send_data(self, data): def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1) epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0) epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data]) epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1) epdconfig.digital_write(self.cs_pin, 1)
# send a lot of data
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte2(data)
epdconfig.digital_write(self.cs_pin, 1)
''' '''
function :Wait until the busy_pin goes LOW function :Wait until the busy_pin goes LOW
parameter: parameter:
''' '''
def ReadBusy(self): def ReadBusy(self):
logger.debug("e-Paper busy") logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy while (epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10) epdconfig.delay_ms(10)
logger.debug("e-Paper busy release") logger.debug("e-Paper busy release")
''' '''
function : Turn On Display function : Turn On Display
parameter: parameter:
''' '''
def TurnOnDisplay(self): def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control self.send_command(0x22) # Display Update Control
self.send_data(0xC7) self.send_data(0xC7)
self.send_command(0x20) # Activate Display Update Sequence self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy() self.ReadBusy()
''' '''
function : Turn On Display Part function : Turn On Display Part
parameter: parameter:
''' '''
def TurnOnDisplayPart(self): def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control self.send_command(0x22) # Display Update Control
self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy() self.ReadBusy()
''' '''
function : Set lut function : Set lut
parameter: parameter:
lut : lut data lut : lut data
''' '''
def Lut(self, lut): def Lut(self, lut):
self.send_command(0x32) self.send_command(0x32)
for i in range(0, 153): for i in range(0, 153):
self.send_data(lut[i]) self.send_data(lut[i])
self.ReadBusy() self.ReadBusy()
''' '''
function : Send lut data and configuration function : Send lut data and configuration
parameter: parameter:
lut : lut data lut : lut data
''' '''
def SetLut(self, lut): def SetLut(self, lut):
self.Lut(lut) self.Lut(lut)
self.send_command(0x3f) self.send_command(0x3f)
self.send_data(lut[153]) self.send_data(lut[153])
self.send_command(0x03) # gate voltage self.send_command(0x03) # gate voltage
self.send_data(lut[154]) self.send_data(lut[154])
self.send_command(0x04) # source voltage self.send_command(0x04) # source voltage
self.send_data(lut[155]) # VSH self.send_data(lut[155]) # VSH
self.send_data(lut[156]) # VSH2 self.send_data(lut[156]) # VSH2
self.send_data(lut[157]) # VSL self.send_data(lut[157]) # VSL
self.send_command(0x2c) # VCOM self.send_command(0x2c) # VCOM
self.send_data(lut[158]) self.send_data(lut[158])
''' '''
function : Setting the display window function : Setting the display window
parameter: parameter:
@ -192,13 +207,14 @@ class EPD:
xend : End position of X-axis xend : End position of X-axis
yend : End position of Y-axis yend : End position of Y-axis
''' '''
def SetWindow(self, x_start, y_start, x_end, y_end): def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored # x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF) self.send_data((x_start >> 3) & 0xFF)
self.send_data((x_end>>3) & 0xFF) self.send_data((x_end >> 3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF) self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF) self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF) self.send_data(y_end & 0xFF)
@ -210,52 +226,54 @@ class EPD:
x : X-axis starting position x : X-axis starting position
y : Y-axis starting position y : Y-axis starting position
''' '''
def SetCursor(self, x, y): def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored # x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF) self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF) self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF) self.send_data((y >> 8) & 0xFF)
''' '''
function : Initialize the e-Paper register function : Initialize the e-Paper register
parameter: parameter:
''' '''
def init(self): def init(self):
if (epdconfig.module_init() != 0): if (epdconfig.module_init() != 0):
return -1 return -1
# EPD hardware init start # EPD hardware init start
self.reset() self.reset()
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x01) #Driver output control self.ReadBusy()
self.send_command(0x12) # SWRESET
self.ReadBusy()
self.send_command(0x01) # Driver output control
self.send_data(0xf9) self.send_data(0xf9)
self.send_data(0x00) self.send_data(0x00)
self.send_data(0x00) self.send_data(0x00)
self.send_command(0x11) #data entry mode self.send_command(0x11) # data entry mode
self.send_data(0x03) self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1) self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0) self.SetCursor(0, 0)
self.send_command(0x3c) self.send_command(0x3c)
self.send_data(0x05) self.send_data(0x05)
self.send_command(0x21) # Display update control self.send_command(0x21) # Display update control
self.send_data(0x00) self.send_data(0x00)
self.send_data(0x80) self.send_data(0x80)
self.send_command(0x18) self.send_command(0x18)
self.send_data(0x80) self.send_data(0x80)
self.ReadBusy() self.ReadBusy()
self.SetLut(self.lut_full_update) self.SetLut(self.lut_full_update)
return 0 return 0
@ -264,54 +282,52 @@ class EPD:
parameter: parameter:
image : Image data image : Image data
''' '''
def getbuffer(self, image): def getbuffer(self, image):
img = image img = image
imwidth, imheight = img.size imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height): if (imwidth == self.width and imheight == self.height):
img = img.convert('1') img = img.convert('1')
elif(imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated # image has correct dimensions, but needs to be rotated
img = img.rotate(90, expand=True).convert('1') img = img.rotate(90, expand=True).convert('1')
else: else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height)) logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer # return a blank buffer
return [0x00] * (int(self.width/8) * self.height) return [0x00] * (int(self.width / 8) * self.height)
buf = bytearray(img.tobytes('raw')) buf = bytearray(img.tobytes('raw'))
return buf return buf
''' '''
function : Sends the image buffer in RAM to e-Paper and displays function : Sends the image buffer in RAM to e-Paper and displays
parameter: parameter:
image : Image data image : Image data
''' '''
def display(self, image): def display(self, image):
if self.width%8 == 0: if self.width % 8 == 0:
linewidth = int(self.width/8) linewidth = int(self.width / 8)
else: else:
linewidth = int(self.width/8) + 1 linewidth = int(self.width / 8) + 1
self.send_command(0x24) self.send_command(0x24)
for j in range(0, self.height): for j in range(0, self.height):
for i in range(0, linewidth): for i in range(0, linewidth):
self.send_data(image[i + j * linewidth]) self.send_data(image[i + j * linewidth])
self.TurnOnDisplay() self.TurnOnDisplay()
''' '''
function : Sends the image buffer in RAM to e-Paper and partial refresh function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter: parameter:
image : Image data image : Image data
''' '''
def displayPartial(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0) epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1) epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1) epdconfig.digital_write(self.reset_pin, 1)
self.SetLut(self.lut_partial_update) self.SetLut(self.lut_partial_update)
self.send_command(0x37) self.send_command(0x37)
self.send_data(0x00) self.send_data(0x00)
@ -322,24 +338,25 @@ class EPD:
self.send_data(0x40) self.send_data(0x40)
self.send_data(0x00) self.send_data(0x00)
self.send_data(0x00) self.send_data(0x00)
self.send_data(0x00) self.send_data(0x00)
self.send_data(0x00) self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom self.send_command(0x3C) # BorderWavefrom
self.send_data(0x80) self.send_data(0x80)
self.send_command(0x22) self.send_command(0x22)
self.send_data(0xC0) self.send_data(0xC0)
self.send_command(0x20) self.send_command(0x20)
self.ReadBusy() self.ReadBusy()
self.SetWindow(0, 0, self.width - 1, self.height - 1) self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0) self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM self.send_command(0x24) # WRITE_RAM
for j in range(0, self.height): # for j in range(0, self.height):
for i in range(0, linewidth): # for i in range(0, linewidth):
self.send_data(image[i + j * linewidth]) # self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplayPart() self.TurnOnDisplayPart()
''' '''
@ -347,51 +364,41 @@ class EPD:
parameter: parameter:
image : Image data image : Image data
''' '''
def displayPartBaseImage(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
def displayPartBaseImage(self, image):
self.send_command(0x24) self.send_command(0x24)
for j in range(0, self.height): self.send_data2(image)
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_command(0x26) self.send_command(0x26)
for j in range(0, self.height): self.send_data2(image)
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay() self.TurnOnDisplay()
''' '''
function : Clear screen function : Clear screen
parameter: parameter:
''' '''
def Clear(self, color):
if self.width%8 == 0: def Clear(self, color=0xFF):
linewidth = int(self.width/8) if self.width % 8 == 0:
linewidth = int(self.width / 8)
else: else:
linewidth = int(self.width/8) + 1 linewidth = int(self.width / 8) + 1
# logger.debug(linewidth) # logger.debug(linewidth)
self.send_command(0x24) self.send_command(0x24)
for j in range(0, self.height): self.send_data2([color] * int(self.height * linewidth))
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay() self.TurnOnDisplay()
''' '''
function : Enter sleep mode function : Enter sleep mode
parameter: parameter:
''' '''
def sleep(self): def sleep(self):
self.send_command(0x10) #enter deep sleep self.send_command(0x10) # enter deep sleep
self.send_data(0x01) self.send_data(0x01)
epdconfig.delay_ms(2000) epdconfig.delay_ms(2000)
epdconfig.module_exit() epdconfig.module_exit()
### END OF FILE ### ### END OF FILE ###

View File

@ -29,7 +29,7 @@
import logging import logging
from . import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 104 EPD_WIDTH = 104

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -28,7 +28,7 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
from PIL import Image from PIL import Image
# Display resolution # Display resolution

View File

@ -29,9 +29,8 @@
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
from PIL import Image from PIL import Image
import RPi.GPIO as GPIO
# Display resolution # Display resolution
EPD_WIDTH = 104 EPD_WIDTH = 104

View File

@ -29,11 +29,9 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import PIL
from PIL import Image from PIL import Image
import io
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -29,11 +29,9 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import PIL
from PIL import Image from PIL import Image
import io
# Display resolution # Display resolution
EPD_WIDTH = 122 EPD_WIDTH = 122

View File

@ -29,11 +29,9 @@
# #
import logging import logging
from .. import epdconfig from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
import PIL
from PIL import Image from PIL import Image
import io
# Display resolution # Display resolution
EPD_WIDTH = 168 EPD_WIDTH = 168

Some files were not shown because too many files have changed in this diff Show More