Compare commits

..

79 Commits

Author SHA1 Message Date
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
307 changed files with 5505 additions and 3222 deletions

2
.github/FUNDING.yml vendored
View File

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

View File

@ -20,23 +20,6 @@ jobs:
VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py)
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Get latest tag
uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
with:
token: ${{ secrets.GITHUB_TOKEN }}
- 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
run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y
@ -65,10 +48,11 @@ jobs:
- name: Release
uses: softprops/action-gh-release@v2
with:
prerelease: true
prerelease: false
make_latest: true
tag_name: v${{ env.VERSION }}
name: Pwnagotchi v${{ env.VERSION }}
files: |
pwnagotchi-${{ env.VERSION }}-32bit.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
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
sudo pishrink -vaZ pwnagotchi-32bit.img
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
bookworm: clean packer
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
sudo pishrink -vaZ pwnagotchi-64bit.img
cd builder && sudo /usr/bin/packer init raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi64.json.pkr.hcl
clean:
- rm -rf /tmp/packer*

View File

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

View File

@ -123,7 +123,7 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml"
playbook_file = "raspberrypi64.yml"
}
}
@ -167,7 +167,7 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/"
playbook_file = "data/32bit/raspberrypi32.yml"
playbook_dir = "extras/"
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 " If you want to know what I'm doing, you can check my logs with the command"
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 --donate, to see how you can donate to this project"
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 " pwnkill"
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 wlan0mon up
iw dev wlan0mon set power_save off
iw dev wlan0 del
}
# 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)
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py)
echo
echo "(☉_☉ ) $_hostname"
echo "(◕‿‿◕) $_hostname"
echo
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!"

View File

@ -1,18 +1,5 @@
#!/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_brcm() {
if ! modprobe -r brcmfmac; then
@ -39,6 +26,7 @@ start_monitor_interface() {
ifconfig wlan0 down
ifconfig wlan0mon up
iw dev wlan0mon set power_save off
iw dev wlan0 del
}
# stops mon0

View File

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

View File

@ -39,26 +39,6 @@
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
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:
enable:
- bettercap.service
@ -82,7 +62,7 @@
source: "https://github.com/jayofelony/bettercap.git"
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip"
ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip"
opwngrid:
pwngrid:
source: "https://github.com/jayofelony/pwngrid.git"
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip"
torch:
@ -117,6 +97,7 @@
- bc
- bison
- bluez
- bluez-tools
- build-essential
- curl
- dkms
@ -142,6 +123,7 @@
- libc-ares-dev
- libc6-dev
- libcpuinfo-dev
- libcurl4-openssl-dev
- libdbus-1-dev
- libdbus-glib-1-dev
- libeigen3-dev
@ -170,6 +152,7 @@
- libsleef-dev
- libsqlite3-dev
- libssl-dev
- libssl-ocaml-dev
- libswscale5
- libtiff5
- libtool
@ -178,6 +161,7 @@
- lsof
- make
- ntp
- python3-dbus
- python3-flask
- python3-flask-cors
- python3-flaskext.wtf
@ -224,6 +208,30 @@
state: present
when: hostname.changed
- name: setup /boot/config.txt
blockinfile:
path: /boot/config.txt
insertafter: EOF
block: |
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
[pi0]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi3]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi4]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
- name: Create custom plugin directory
file:
path: '{{ pwnagotchi.custom_plugin_dir }}'
@ -282,6 +290,24 @@
dest: /usr/local/lib/libpcap.so.0.8
state: link
# install latest hcxtools
#- name: clone hcxtools
# git:
# repo: https://github.com/ZerBea/hcxtools.git
# dest: /usr/local/src/hcxtools
#- name: install hcxtools
# shell: "make && make install"
# args:
# executable: /bin/bash
# chdir: /usr/local/src/hcxtools
#- name: remove hcxtools directory
# file:
# state: absent
# path: /usr/local/src/hcxtools
###############################################################
# Install nexmon to fix wireless scanning (takes 2.5G of space)
###############################################################
@ -389,29 +415,39 @@
block: |
export GOPATH=$HOME/go
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
- name: download pwngrid
unarchive:
remote_src: yes
src: "{{ packages.opwngrid.url }}"
dest: /usr/local/bin/
mode: 0755
git:
repo: "{{ packages.pwngrid.source }}"
dest: /usr/local/src/pwngrid
- name: download and install bettercap
unarchive:
src: "{{ packages.bettercap.url }}"
dest: /usr/local/bin
remote_src: yes
exclude:
- README.md
- LICENSE.md
mode: 0755
- name: install pwngrid
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
args:
executable: /bin/bash
chdir: /usr/local/src/pwngrid
- name: remove pwngrid folder
file:
state: absent
path: /usr/local/src/pwngrid
- name: download bettercap
git:
repo: "{{ packages.bettercap.source }}"
dest: /usr/local/src/bettercap
- name: install bettercap 2.32.4
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
args:
executable: /bin/bash
chdir: /usr/local/src/bettercap
- name: remove bettercap folder
file:
state: absent
path: /usr/local/src/bettercap
- name: clone bettercap caplets
git:
@ -475,20 +511,6 @@
path: /boot/ssh
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
replace:
dest: /boot/cmdline.txt
@ -596,4 +618,4 @@
handlers:
- name: reload systemd services
systemd:
daemon_reload: yes
daemon_reload: yes

View File

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

View File

@ -11,23 +11,6 @@
pwnagotchi:
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | 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:
enable:
- bettercap.service
@ -81,6 +64,7 @@
- bc
- bison
- bluez
- bluez-tools
- build-essential
- curl
- dkms
@ -211,25 +195,6 @@
path: /etc/rc.local
state: absent
- name: adjust /boot/firmware/config.txt
blockinfile:
dest: /boot/firmware/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
replace:
dest: /boot/firmware/cmdline.txt
@ -246,6 +211,34 @@
regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether'
- name: setup /boot/firmware/config.txt
blockinfile:
path: /boot/firmware/config.txt
insertafter: EOF
block: |
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
[pi0]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi3]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi4]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi5]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
- name: change hostname
lineinfile:
dest: /etc/hostname
@ -517,16 +510,11 @@
- name: Update .bashrc for go-1.21
blockinfile:
dest: /home/pi/.bashrc
dest: /etc/profile
state: present
block: |
export GOPATH=$HOME/go
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
- name: download pwngrid

View File

@ -1 +1 @@
__version__ = '2.8.7.1'
__version__ = '2.9.0'

View File

@ -254,7 +254,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
txt = '%d (%d)' % (len(self._handshakes), tot)
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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,6 +4,7 @@ import subprocess
import time
import random
from io import TextIOWrapper
import os
import pwnagotchi
from pwnagotchi import plugins
@ -32,6 +33,9 @@ class FixServices(plugins.Plugin):
self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
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.connection = None
self.LASTTRY = 0
@ -108,7 +112,7 @@ class FixServices(plugins.Plugin):
logging.debug("[Fix_Services]**** epoch")
if time.time() - self.LASTTRY > 180:
# get last 10 lines
display = None
display = agent.view()
logging.debug("[Fix_Services]**** checking")
@ -116,7 +120,6 @@ class FixServices(plugins.Plugin):
if len(self.pattern.findall(last_lines)) >= 3:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
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:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Wifi channel stuck. Restarting recon.')
display.update(force=True)
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:
logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.')
display.update(force=True)
try:
@ -167,7 +168,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
logging.debug("[Fix_Services] wlan0 is down!")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting wlan0 now!')
display.update(force=True)
try:
@ -177,6 +177,41 @@ class FixServices(plugins.Plugin):
except Exception as 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:
print("logs look good")

View File

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

View File

@ -89,7 +89,7 @@ class Grid(plugins.Plugin):
logging.debug("checking pcap's")
config = agent.config()
pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap"))
pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap"))
num_networks = len(pcap_files)
reported = self.report.data_field_or('reported', default=[])
num_reported = len(reported)

View File

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

View File

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

View File

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

View File

@ -10,13 +10,17 @@ class Widget(object):
def draw(self, canvas, drawer):
raise Exception("not implemented")
# canvas.paste: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.paste
# takes mask variable, to identify color system. (not used for pwnagotchi yet)
# Pwn should use "1" since its mainly black or white displays.
class Bitmap(Widget):
def __init__(self, path, xy, color=0):
super().__init__(xy, color)
self.image = Image.open(path)
def draw(self, canvas, drawer):
if self.color = 0xFF:
self.image = ImageOps.invert(self.image)
canvas.paste(self.image, self.xy)

View File

@ -28,6 +28,39 @@ class Display(View):
def is_lcdhat(self):
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):
return self._implementation.name == 'waveshare144lcd'
@ -202,6 +235,9 @@ class Display(View):
def is_inky(self):
return self._implementation.name == 'inky'
def is_dummy_display(self):
return self._implementation.name == 'dummydisplay'
def is_papirus(self):
return self._implementation.name == 'papirus'
@ -228,10 +264,19 @@ class Display(View):
def is_waveshareoledlcd(self):
return self._implementation.name == 'waveshareoledlcd'
def is_waveshareoledlcdvert(self):
return self._implementation.name == 'waveshareoledlcdvert'
def is_i2coled(self):
return self._implementation.name == 'i2coled'
def is_waveshare35lcd(self):
return self._implementation.name == 'waveshare35lcd'
def is_adfruit213v3(self):
return self._implementation.name == 'adafruit2in13_v3'
def is_waveshare_any(self):
return self.is_waveshare_v1() or self.is_waveshare_v2()

View File

@ -27,6 +27,7 @@ PNG = False
POSITION_X = 0
POSITION_Y = 40
def load_from_config(config):
for face_name, face_value in config.items():
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):
# config has been normalized already in utils.load_config
if config['ui']['display']['type'] == 'inky':
from pwnagotchi.ui.hw.inky import Inky
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':
from pwnagotchi.ui.hw.papirus import Papirus
return Papirus(config)
elif config['ui']['display']['type'] == 'oledhat':
from pwnagotchi.ui.hw.oledhat import OledHat
return OledHat(config)
elif config['ui']['display']['type'] == 'lcdhat':
from pwnagotchi.ui.hw.lcdhat import LcdHat
return LcdHat(config)
elif config['ui']['display']['type'] == 'dfrobot_1':
from pwnagotchi.ui.hw.dfrobot import DFRobotV1
return DFRobotV1(config)
elif config['ui']['display']['type'] == 'dfrobot_2':
from pwnagotchi.ui.hw.dfrobot_v2 import DFRobotV2
return DFRobotV2(config)
elif config['ui']['display']['type'] == 'waveshare144lcd':
from pwnagotchi.ui.hw.waveshare1in44lcd import Waveshare144lcd
return Waveshare144lcd(config)
elif config['ui']['display']['type'] == 'waveshare35lcd':
from pwnagotchi.ui.hw.waveshare3in5lcd import Waveshare35lcd
return Waveshare35lcd(config)
elif config['ui']['display']['type'] == 'spotpear24inch':
from pwnagotchi.ui.hw.spotpear24in import Spotpear24inch
return Spotpear24inch(config)
elif config['ui']['display']['type'] == 'displayhatmini':
from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
return DisplayHatMini(config)
elif config['ui']['display']['type'] == 'pirateaudio':
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
return PirateAudio(config)
elif config['ui']['display']['type'] == 'pitft':
from pwnagotchi.ui.hw.pitft import Pitft
return Pitft(config)
elif config['ui']['display']['type'] == 'tftbonnet':
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
return TftBonnet(config)
elif config['ui']['display']['type'] == 'waveshareoledlcd':
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
return Waveshareoledlcd(config)
elif config['ui']['display']['type'] == 'waveshareoledlcdvert':
from pwnagotchi.ui.hw.waveshareoledlcdvert import Waveshareoledlcdvert
return Waveshareoledlcdvert(config)
elif config['ui']['display']['type'] == 'i2coled':
from pwnagotchi.ui.hw.i2coled import I2COled
return I2COled(config)
elif config['ui']['display']['type'] == 'waveshare1in02':
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
return Waveshare1in02(config)
elif config['ui']['display']['type'] == 'waveshare1in54':
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
return Waveshare154(config)
elif config['ui']['display']['type'] == 'waveshare1in54_v2':
from pwnagotchi.ui.hw.waveshare1in54_V2 import Waveshare154V2
return Waveshare154V2(config)
elif config['ui']['display']['type'] == 'waveshare1in54b':
from pwnagotchi.ui.hw.waveshare1in54b import Waveshare154inchb
return Waveshare154inchb(config)
elif config['ui']['display']['type'] == 'waveshare1in54b_v2':
from pwnagotchi.ui.hw.waveshare1in54b_V2 import Waveshare154bV2
return Waveshare154bV2(config)
elif config['ui']['display']['type'] == 'waveshare1in54c':
from pwnagotchi.ui.hw.waveshare1in54c import Waveshare1in54c
return Waveshare1in54c(config)
elif config['ui']['display']['type'] == 'waveshare1in64g':
from pwnagotchi.ui.hw.waveshare1in64g import Waveshare1in64g
return Waveshare1in64g(config)
elif config['ui']['display']['type'] == 'waveshare2in7':
from pwnagotchi.ui.hw.waveshare2in7 import Waveshare27inch
return Waveshare27inch(config)
elif config['ui']['display']['type'] == 'waveshare2in7_v2':
from pwnagotchi.ui.hw.waveshare2in7_V2 import Waveshare27inchV2
return Waveshare27inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in7b':
from pwnagotchi.ui.hw.waveshare2in7b import Waveshare27b
return Waveshare27b(config)
elif config['ui']['display']['type'] == 'waveshare2in7b_v2':
from pwnagotchi.ui.hw.waveshare2in7b_V2 import Waveshare27bV2
return Waveshare27bV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9':
from pwnagotchi.ui.hw.waveshare2in9 import Waveshare29inch
return Waveshare29inch(config)
elif config['ui']['display']['type'] == 'waveshare2in9bc':
from pwnagotchi.ui.hw.waveshare2in9bc import Waveshare2in9bc
return Waveshare2in9bc(config)
elif config['ui']['display']['type'] == 'waveshare2in9d':
from pwnagotchi.ui.hw.waveshare2in9d import Waveshare2in9d
return Waveshare2in9d(config)
elif config['ui']['display']['type'] == 'waveshare2in9_v2':
from pwnagotchi.ui.hw.waveshare2in9_V2 import Waveshare29inchV2
return Waveshare29inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9b_v3':
from pwnagotchi.ui.hw.waveshare2in9b_V3 import Waveshare29bV3
return Waveshare29bV3(config)
elif config['ui']['display']['type'] == 'waveshare2in9b_v4':
from pwnagotchi.ui.hw.waveshare2in9b_V4 import Waveshare29bV4
return Waveshare29bV4(config)
elif config['ui']['display']['type'] == 'waveshare_1':
from pwnagotchi.ui.hw.waveshare2in13 import WaveshareV1
return WaveshareV1(config)
elif config['ui']['display']['type'] == 'waveshare_2':
from pwnagotchi.ui.hw.waveshare2in13_V2 import WaveshareV2
return WaveshareV2(config)
elif config['ui']['display']['type'] == 'waveshare_3':
from pwnagotchi.ui.hw.waveshare2in13_V3 import WaveshareV3
return WaveshareV3(config)
elif config['ui']['display']['type'] == 'waveshare_4':
from pwnagotchi.ui.hw.waveshare2in13_V4 import WaveshareV4
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':
from pwnagotchi.ui.hw.waveshare2in13bc import Waveshare213bc
return Waveshare213bc(config)
elif config['ui']['display']['type'] == 'waveshare2in13d':
from pwnagotchi.ui.hw.waveshare2in13d import Waveshare213d
return Waveshare213d(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
from pwnagotchi.ui.hw.waveshare2in13b_V3 import Waveshare2in13bV3
return Waveshare2in13bV3(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v4':
from pwnagotchi.ui.hw.waveshare2in13b_V4 import Waveshare213bV4
return Waveshare213bV4(config)
elif config['ui']['display']['type'] == 'waveshare2in13g':
from pwnagotchi.ui.hw.waveshare2in13g import Waveshare2in13g
return Waveshare2in13g(config)
elif config['ui']['display']['type'] == 'waveshare2in36g':
from pwnagotchi.ui.hw.waveshare2in36g import Waveshare2in36g
return Waveshare2in36g(config)
elif config['ui']['display']['type'] == 'waveshare2in66':
from pwnagotchi.ui.hw.waveshare2in66 import Waveshare2in66
return Waveshare2in66(config)
elif config['ui']['display']['type'] == 'waveshare2in66b':
from pwnagotchi.ui.hw.waveshare2in66b import Waveshare2in66b
return Waveshare2in66b(config)
elif config['ui']['display']['type'] == 'waveshare2in66g':
from pwnagotchi.ui.hw.waveshare2in66g import Waveshare2in66g
return Waveshare2in66g(config)
elif config['ui']['display']['type'] == 'waveshare3in0g':
from pwnagotchi.ui.hw.waveshare3in0g import Waveshare3in0g
return Waveshare3in0g(config)
elif config['ui']['display']['type'] == 'waveshare3in7':
from pwnagotchi.ui.hw.waveshare3in7 import Waveshare3in7
return Waveshare3in7(config)
elif config['ui']['display']['type'] == 'waveshare3in52':
from pwnagotchi.ui.hw.waveshare3in52 import Waveshare3in52
return Waveshare3in52(config)
elif config['ui']['display']['type'] == 'waveshare4in01f':
from pwnagotchi.ui.hw.waveshare4in01f import Waveshare4in01f
return Waveshare4in01f(config)
elif config['ui']['display']['type'] == 'waveshare4in2':
from pwnagotchi.ui.hw.waveshare4in2 import Waveshare4in2
return Waveshare4in2(config)
elif config['ui']['display']['type'] == 'waveshare4in2_v2':
from pwnagotchi.ui.hw.waveshare4in2_V2 import Waveshare4in2V2
return Waveshare4in2V2(config)
elif config['ui']['display']['type'] == 'waveshare4in2b_v2':
from pwnagotchi.ui.hw.waveshare4in2b_V2 import Waveshare4in2bV2
return Waveshare4in2bV2(config)
elif config['ui']['display']['type'] == 'waveshare4in2bc':
from pwnagotchi.ui.hw.waveshare4in2bc import Waveshare4in2bc
return Waveshare4in2bc(config)
elif config['ui']['display']['type'] == 'waveshare4in26':
from pwnagotchi.ui.hw.waveshare4in26 import Waveshare4in26
return Waveshare4in26(config)
elif config['ui']['display']['type'] == 'waveshare4in37g':
from pwnagotchi.ui.hw.waveshare4in37g import Waveshare4in37g
return Waveshare4in37g(config)
elif config['ui']['display']['type'] == 'waveshare5in65f':
from pwnagotchi.ui.hw.waveshare5in65f import Waveshare5in65f
return Waveshare5in65f(config)
elif config['ui']['display']['type'] == 'waveshare5in79':
from pwnagotchi.ui.hw.waveshare5in79 import Waveshare5in79
return Waveshare5in79(config)
elif config['ui']['display']['type'] == 'waveshare5in79b':
from pwnagotchi.ui.hw.waveshare5in79b import Waveshare5in79b
return Waveshare5in79b(config)
elif config['ui']['display']['type'] == 'waveshare5in83':
from pwnagotchi.ui.hw.waveshare5in83 import Waveshare5in83
return Waveshare5in83(config)
elif config['ui']['display']['type'] == 'waveshare5in83_v2':
from pwnagotchi.ui.hw.waveshare5in83_V2 import Waveshare5in83V2
return Waveshare5in83V2(config)
elif config['ui']['display']['type'] == 'waveshare5in83b_v2':
from pwnagotchi.ui.hw.waveshare5in83b_V2 import Waveshare5in83bV2
return Waveshare5in83bV2(config)
elif config['ui']['display']['type'] == 'waveshare5in83bc':
from pwnagotchi.ui.hw.waveshare5in83bc import Waveshare5in83bc
return Waveshare5in83bc(config)
elif config['ui']['display']['type'] == 'waveshare7in3f':
from pwnagotchi.ui.hw.waveshare7in3f import Waveshare7in3f
return Waveshare7in3f(config)
elif config['ui']['display']['type'] == 'waveshare7in3g':
from pwnagotchi.ui.hw.waveshare7in3g import Waveshare7in3g
return Waveshare7in3g(config)
elif config['ui']['display']['type'] == 'waveshare7in5':
from pwnagotchi.ui.hw.waveshare7in5 import Waveshare7in5
return Waveshare7in5(config)
elif config['ui']['display']['type'] == 'waveshare7in5_HD':
from pwnagotchi.ui.hw.waveshare7in5_HD import Waveshare7in5HD
return Waveshare7in5HD(config)
elif config['ui']['display']['type'] == 'waveshare7in5_v2':
from pwnagotchi.ui.hw.waveshare7in5_V2 import Waveshare7in5V2
return Waveshare7in5V2(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_HD':
from pwnagotchi.ui.hw.waveshare7in5b_HD import Waveshare7in5bHD
return Waveshare7in5bHD(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_v2':
from pwnagotchi.ui.hw.waveshare7in5b_V2 import Waveshare7in5bV2
return Waveshare7in5bV2(config)
elif config['ui']['display']['type'] == 'waveshare7in5bc':
from pwnagotchi.ui.hw.waveshare7in5bc import Waveshare7in5bc
return Waveshare7in5bc(config)
elif config['ui']['display']['type'] == 'waveshare13in3k':
from pwnagotchi.ui.hw.waveshare13in3k import Waveshare13in3k
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):
logging.info("initializing Display Hat Mini")
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789
self._display = ST7789(0,1,9,13)
self._display = ST7789(0, 1, 9, 13, width=self._layout['width'], height=self._layout['height'], rotation=0)
def render(self, canvas):
self._display.display(canvas)
def clear(self):
self._display.clear()
pass

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

View File

@ -1,144 +1,164 @@
FBIOGET_VSCREENINFO=0x4600
FBIOPUT_VSCREENINFO=0x4601
FBIOGET_FSCREENINFO=0x4602
FBIOGETCMAP=0x4604
FBIOPUTCMAP=0x4605
FBIOPAN_DISPLAY=0x4606
FBIOGET_VSCREENINFO = 0x4600
FBIOPUT_VSCREENINFO = 0x4601
FBIOGET_FSCREENINFO = 0x4602
FBIOGETCMAP = 0x4604
FBIOPUTCMAP = 0x4605
FBIOPAN_DISPLAY = 0x4606
FBIOGET_CON2FBMAP=0x460F
FBIOPUT_CON2FBMAP=0x4610
FBIOBLANK=0x4611
FBIO_ALLOC=0x4613
FBIO_FREE=0x4614
FBIOGET_GLYPH=0x4615
FBIOGET_HWCINFO=0x4616
FBIOPUT_MODEINFO=0x4617
FBIOGET_DISPINFO=0x4618
FBIOGET_CON2FBMAP = 0x460F
FBIOPUT_CON2FBMAP = 0x4610
FBIOBLANK = 0x4611
FBIO_ALLOC = 0x4613
FBIO_FREE = 0x4614
FBIOGET_GLYPH = 0x4615
FBIOGET_HWCINFO = 0x4616
FBIOPUT_MODEINFO = 0x4617
FBIOGET_DISPINFO = 0x4618
from mmap import mmap
from fcntl import ioctl
import struct
mm = None
bpp, w, h = 0, 0, 0 # framebuffer bpp and size
bpp, w, h = 0, 0, 0 # framebuffer bpp and size
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
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a
RGB = False
_verbose = False
msize_kb = 0
def report_fb(i=0, layer=0):
with open('/dev/fb'+str(i), 'r+b')as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I'*40, vi))
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'
fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
with open('/dev/fb' + str(i), 'r+b') as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I' * 40, vi))
ffm = 'c' * 16 + 'L' + 'I' * 4 + 'H' * 3 + 'ILIIHHH'
fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
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
if mm and bpp == _bpp: return mm, w, h, bpp
with open('/dev/fb'+str(i), 'r+b')as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I'*40, vi))
bpp = vi[6]
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)
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
with open('/dev/fb' + str(i), 'r+b') as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I' * 40, vi))
bpp = vi[6]
bytepp = bpp//8
except:
pass
if vi[8] == 0 : 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
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]
bytepp = bpp // 8
except:
pass
mm = mmap(f.fileno(), msize, offset=start)
return mm, w, h, bpp#ll//(bpp//8), h
if vi[8] == 0:
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():
fill_scr(0,0,0)
fill_scr(0, 0, 0)
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):
mmseekto(x,y)
mm.write(struct.pack('BBB',*((r,g,b) if RGB else (b,g,r))))
mmseekto(x, y)
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):
b = b''
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')
return b
b = b''
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')
return b
def numpy_888_565(bt):
import numpy as np
arr = np.fromstring(bt, dtype=np.uint32)
return (((0xF80000 & arr)>>8)|((0xFC00 & arr)>>5)|((0xF8 & arr)>>3)).astype(np.uint16).tostring()
import numpy as np
arr = np.fromstring(bt, dtype=np.uint32)
return (((0xF80000 & arr) >> 8) | ((0xFC00 & arr) >> 5) | ((0xF8 & arr) >> 3)).astype(np.uint16).tostring()
def show_img(img):
if not type(img) is bytes:
if not RGB:
if bpp == 24: # for RPI
img = img.tobytes('raw', 'BGR')
else:
img = img.convert('RGBA').tobytes('raw', 'BGRA')
if bpp == 16:
img = numpy_888_565(img)
else:
if bpp == 24:
img = img.tobytes()
else:
img = img.convert('RGBA').tobytes()
if bpp == 16:
img = numpy_888_565(img)
from io import BytesIO
b = BytesIO(img)
s = vw*bytepp
for y in range(vh): # virtual window drawing
mmseekto(vx,vy+y)
mm.write(b.read(s))
if not type(img) is bytes:
if not RGB:
if bpp == 24: # for RPI
img = img.tobytes('raw', 'BGR')
else:
img = img.convert('RGBA').tobytes('raw', 'BGRA')
if bpp == 16:
img = numpy_888_565(img)
else:
if bpp == 24:
img = img.tobytes()
else:
img = img.convert('RGBA').tobytes()
if bpp == 16:
img = numpy_888_565(img)
from io import BytesIO
b = BytesIO(img)
s = vw * bytepp
for y in range(vh): # virtual window drawing
mmseekto(vx, vy + y)
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):
"""Representation of an ST7789 TFT LCD."""
def __init__(self, port, cs, dc, backlight, rst=None, width=320,
height=240, rotation=0, invert=True, spi_speed_hz=60 * 1000 * 1000,
def __init__(self, port, cs, dc, backlight=None, rst=None, width=240,
height=240, rotation=90, invert=True, spi_speed_hz=4000000,
offset_left=0,
offset_top=0):
"""Create an instance of the display using SPI communication.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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