mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2025-07-01 18:37:27 -04:00
Compare commits
90 Commits
Author | SHA1 | Date | |
---|---|---|---|
357ffc67e5 | |||
ea8fb5e533 | |||
31afd6d0ba | |||
b38274e652 | |||
518e8c219c | |||
4e07fbf1aa | |||
b3e81a95c8 | |||
050966215b | |||
fef442edbb | |||
1064936503 | |||
a762a7f763 | |||
8fd0e358a9 | |||
9a941c1d46 | |||
ead5a3baac | |||
ac2973889d | |||
8991dd6811 | |||
415e5cd551 | |||
47705ba1a2 | |||
7c7bbc770b | |||
ab83de4905 | |||
8f7741cd9e | |||
835886e6f6 | |||
6b2039a8e6 | |||
d53d0c7841 | |||
6c40998b51 | |||
a71a90ba3d | |||
b03f6f747b | |||
a8ba88c9cc | |||
f597bd6d29 | |||
a3f103ac06 | |||
e0a068e51d | |||
dc1b3c7635 | |||
3657859a73 | |||
33ff5a0bf8 | |||
666f65c640 | |||
84d45a0d45 | |||
06a4491008 | |||
5485f83ca6 | |||
ab541458fa | |||
ac345c2ee7 | |||
468cfd9f4f | |||
d6bc5c0e66 | |||
4905eb6b26 | |||
697a7778b1 | |||
9287283ee7 | |||
8013109ef7 | |||
f140fe1a2d | |||
8fe503c67d | |||
d81013412e | |||
3c701822bd | |||
2f5ddb492a | |||
9e3324221d | |||
b069b82984 | |||
cb7d965271 | |||
7abf9ff8da | |||
18fb956251 | |||
afb1d11cd8 | |||
627be80e6c | |||
c4c4d6c417 | |||
8dcae13ce9 | |||
1352e99774 | |||
2182d7c29d | |||
703c05a93b | |||
697cc5d88b | |||
4b04f9b7a5 | |||
c7b94a0707 | |||
5116bac2a7 | |||
51625e61f9 | |||
bf9a0a96c1 | |||
bd03f07aa8 | |||
3f13df8f20 | |||
ce0275f2ae | |||
b971f18f75 | |||
ea9d11d018 | |||
8a572f1b70 | |||
0c4f2a5093 | |||
7edd752664 | |||
cc550aa236 | |||
ff033d41d3 | |||
6d0a0d8d5f | |||
b33af167d4 | |||
9053762e71 | |||
26fef7dd99 | |||
5dd17291f7 | |||
bac79f3465 | |||
bb8dfe0244 | |||
1b16975031 | |||
dd2b559ebc | |||
93ba2a7f79 | |||
dd18072002 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,3 +1,3 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: jayofelony
|
github: jayofelony
|
22
.github/workflows/publish.yml
vendored
22
.github/workflows/publish.yml
vendored
@ -20,21 +20,6 @@ jobs:
|
|||||||
VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py)
|
VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py)
|
||||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Get latest tag
|
|
||||||
uses: actions-ecosystem/action-get-latest-tag@v1
|
|
||||||
id: get-latest-tag
|
|
||||||
|
|
||||||
- name: Set LAST_VERSION as an environment variable
|
|
||||||
run: echo "LAST_VERSION=${{ steps.get-latest-tag.outputs.tag }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Generate release notes
|
|
||||||
id: generate_release_notes
|
|
||||||
run: |
|
|
||||||
COMMITS=$(git log --merges --pretty=format:"* %s" $LAST_VERSION--$VERSION | sed 's/$/\\n/g')
|
|
||||||
CONTRIBUTORS=$(git shortlog -sn $LAST_VERSION--$VERSION | awk '{print "* @" $2}' | sed 's/$/\\n/g')
|
|
||||||
RELEASE_BODY="**Full Changelog**: https://github.com/jayofelony/pwnagotchi/compare/$LAST_VERSION...$VERSION"
|
|
||||||
echo "RELEASE_BODY=$RELEASE_BODY" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Install qemu dependencies
|
- name: Install qemu dependencies
|
||||||
run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y
|
run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y
|
||||||
|
|
||||||
@ -61,12 +46,13 @@ jobs:
|
|||||||
run: mv "pwnagotchi-64bit.img.xz" "pwnagotchi-$VERSION-64bit.img.xz"
|
run: mv "pwnagotchi-64bit.img.xz" "pwnagotchi-$VERSION-64bit.img.xz"
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
prerelease: true
|
prerelease: false
|
||||||
|
make_latest: true
|
||||||
tag_name: v${{ env.VERSION }}
|
tag_name: v${{ env.VERSION }}
|
||||||
name: Pwnagotchi v${{ env.VERSION }}
|
name: Pwnagotchi v${{ env.VERSION }}
|
||||||
files: |
|
files: |
|
||||||
pwnagotchi-${{ env.VERSION }}-32bit.img.xz
|
pwnagotchi-${{ env.VERSION }}-32bit.img.xz
|
||||||
pwnagotchi-${{ env.VERSION }}-64bit.img.xz
|
pwnagotchi-${{ env.VERSION }}-64bit.img.xz
|
||||||
body: ${{ env.RELEASE_BODY }}
|
generate_release_notes: true
|
6
Makefile
6
Makefile
@ -51,13 +51,11 @@ image: clean packer
|
|||||||
|
|
||||||
bullseye: clean packer
|
bullseye: clean packer
|
||||||
export LC_ALL=en_GB.UTF-8
|
export LC_ALL=en_GB.UTF-8
|
||||||
cd builder && sudo /usr/bin/packer init data/32bit/raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/32bit/raspberrypi32.json.pkr.hcl
|
cd builder && sudo /usr/bin/packer init raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi32.json.pkr.hcl
|
||||||
sudo pishrink -vaZ pwnagotchi-32bit.img
|
|
||||||
|
|
||||||
bookworm: clean packer
|
bookworm: clean packer
|
||||||
export LC_ALL=en_GB.UTF-8
|
export LC_ALL=en_GB.UTF-8
|
||||||
cd builder && sudo /usr/bin/packer init data/64bit/raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/64bit/raspberrypi64.json.pkr.hcl
|
cd builder && sudo /usr/bin/packer init raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi64.json.pkr.hcl
|
||||||
sudo pishrink -vaZ pwnagotchi-64bit.img
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
- rm -rf /tmp/packer*
|
- rm -rf /tmp/packer*
|
||||||
|
@ -237,7 +237,7 @@ def pwnagotchi_cli():
|
|||||||
f.write("ui.display.enabled = true\n")
|
f.write("ui.display.enabled = true\n")
|
||||||
pwn_display_type = input("What display do you use?\n\n"
|
pwn_display_type = input("What display do you use?\n\n"
|
||||||
"Be sure to check for the correct display type @ \n"
|
"Be sure to check for the correct display type @ \n"
|
||||||
"https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L431\n\n"
|
"https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L501\n\n"
|
||||||
"Display type: ")
|
"Display type: ")
|
||||||
if pwn_display_type != "":
|
if pwn_display_type != "":
|
||||||
f.write(f"ui.display.type = \"{pwn_display_type}\"\n")
|
f.write(f"ui.display.type = \"{pwn_display_type}\"\n")
|
||||||
@ -264,8 +264,7 @@ def pwnagotchi_cli():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if args.donate:
|
if args.donate:
|
||||||
print("Donations can made @ \n "
|
print("Donations can be made @ \n "
|
||||||
"https://www.patreon.com/pwnagotchi_torch \n "
|
|
||||||
"https://github.com/sponsors/jayofelony \n\n"
|
"https://github.com/sponsors/jayofelony \n\n"
|
||||||
"But only if you really want to!")
|
"But only if you really want to!")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@ -278,8 +277,7 @@ def pwnagotchi_cli():
|
|||||||
local = version_to_tuple(pwnagotchi.__version__)
|
local = version_to_tuple(pwnagotchi.__version__)
|
||||||
remote = version_to_tuple(latest_ver)
|
remote = version_to_tuple(latest_ver)
|
||||||
if remote > local:
|
if remote > local:
|
||||||
user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] "
|
user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] " % (pwnagotchi.__version__, latest_ver))
|
||||||
% (pwnagotchi.__version__, latest_ver))
|
|
||||||
# input validation
|
# input validation
|
||||||
if user_input.lower() in ('y', 'yes'):
|
if user_input.lower() in ('y', 'yes'):
|
||||||
if os.path.exists('/root/.auto-update'):
|
if os.path.exists('/root/.auto-update'):
|
||||||
@ -334,5 +332,6 @@ def pwnagotchi_cli():
|
|||||||
else:
|
else:
|
||||||
do_auto_mode(agent)
|
do_auto_mode(agent)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pwnagotchi_cli()
|
pwnagotchi_cli()
|
||||||
|
@ -123,7 +123,7 @@ build {
|
|||||||
provisioner "ansible-local" {
|
provisioner "ansible-local" {
|
||||||
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
||||||
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
||||||
playbook_file = "data/64bit/raspberrypi64.yml"
|
playbook_file = "raspberrypi64.yml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ build {
|
|||||||
provisioner "ansible-local" {
|
provisioner "ansible-local" {
|
||||||
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
||||||
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
||||||
playbook_dir = "data/32bit/extras/"
|
playbook_dir = "extras/"
|
||||||
playbook_file = "data/32bit/raspberrypi32.yml"
|
playbook_file = "raspberrypi32.yml"
|
||||||
}
|
}
|
||||||
}
|
}
|
6
builder/data/32bit/etc/modules-load.d/modules.conf
Normal file
6
builder/data/32bit/etc/modules-load.d/modules.conf
Normal 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
|
40
builder/data/32bit/etc/profile
Normal file
40
builder/data/32bit/etc/profile
Normal 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'
|
||||||
|
|
@ -20,6 +20,7 @@ echo " I'm managed by systemd. Here are some basic commands."
|
|||||||
echo
|
echo
|
||||||
echo " If you want to know what I'm doing, you can check my logs with the command"
|
echo " If you want to know what I'm doing, you can check my logs with the command"
|
||||||
echo " - pwnlog"
|
echo " - pwnlog"
|
||||||
|
echo " - sudo pwnagotchi --wizard, to help set up a config.toml"
|
||||||
echo " - sudo pwnagotchi --version, to check the current version"
|
echo " - sudo pwnagotchi --version, to check the current version"
|
||||||
echo " - sudo pwnagotchi --donate, to see how you can donate to this project"
|
echo " - sudo pwnagotchi --donate, to see how you can donate to this project"
|
||||||
echo " - sudo pwnagotchi --check-update, to see if there is a new version available"
|
echo " - sudo pwnagotchi --check-update, to see if there is a new version available"
|
||||||
@ -30,4 +31,4 @@ echo
|
|||||||
echo " You can restart me using"
|
echo " You can restart me using"
|
||||||
echo " pwnkill"
|
echo " pwnkill"
|
||||||
echo
|
echo
|
||||||
echo " You learn more about me at https://pwnagotchi.ai/"
|
echo " You can learn more about me at https://pwnagotchi.org/"
|
@ -32,6 +32,7 @@ start_monitor_interface() {
|
|||||||
ifconfig wlan0 down
|
ifconfig wlan0 down
|
||||||
ifconfig wlan0mon up
|
ifconfig wlan0mon up
|
||||||
iw dev wlan0mon set power_save off
|
iw dev wlan0mon set power_save off
|
||||||
|
iw dev wlan0 del
|
||||||
}
|
}
|
||||||
|
|
||||||
# stops mon0
|
# stops mon0
|
||||||
|
6
builder/data/64bit/etc/modules-load.d/modules.conf
Normal file
6
builder/data/64bit/etc/modules-load.d/modules.conf
Normal 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
|
40
builder/data/64bit/etc/profile
Normal file
40
builder/data/64bit/etc/profile
Normal 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'
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
_hostname=$(hostname)
|
_hostname=$(hostname)
|
||||||
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py)
|
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py)
|
||||||
echo
|
echo
|
||||||
echo "(☉_☉ ) $_hostname"
|
echo "(◕‿‿◕) $_hostname"
|
||||||
echo
|
echo
|
||||||
echo " Hi! I'm a pwnagotchi $_version, please take good care of me!"
|
echo " Hi! I'm a pwnagotchi $_version, please take good care of me!"
|
||||||
echo " Here are some basic things you need to know to raise me properly!"
|
echo " Here are some basic things you need to know to raise me properly!"
|
||||||
|
@ -1,18 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# well ... it blinks the led
|
|
||||||
blink_led() {
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
for i in $(seq 1 "$1"); do
|
|
||||||
echo 0 >/sys/class/leds/led0/brightness
|
|
||||||
sleep 0.3
|
|
||||||
echo 1 >/sys/class/leds/led0/brightness
|
|
||||||
sleep 0.3
|
|
||||||
done
|
|
||||||
echo 0 >/sys/class/leds/led0/brightness
|
|
||||||
sleep 0.3
|
|
||||||
}
|
|
||||||
|
|
||||||
# reload mod
|
# reload mod
|
||||||
reload_brcm() {
|
reload_brcm() {
|
||||||
if ! modprobe -r brcmfmac; then
|
if ! modprobe -r brcmfmac; then
|
||||||
@ -39,6 +26,7 @@ start_monitor_interface() {
|
|||||||
ifconfig wlan0 down
|
ifconfig wlan0 down
|
||||||
ifconfig wlan0mon up
|
ifconfig wlan0mon up
|
||||||
iw dev wlan0mon set power_save off
|
iw dev wlan0mon set power_save off
|
||||||
|
iw dev wlan0 del
|
||||||
}
|
}
|
||||||
|
|
||||||
# stops mon0
|
# stops mon0
|
||||||
|
@ -88,7 +88,7 @@ build {
|
|||||||
provisioner "ansible-local" {
|
provisioner "ansible-local" {
|
||||||
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
||||||
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
||||||
playbook_dir = "data/32bit/extras/"
|
playbook_dir = "extras/"
|
||||||
playbook_file = "data/32bit/raspberrypi32.yml"
|
playbook_file = "raspberrypi32.yml"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,26 +39,6 @@
|
|||||||
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
|
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
|
||||||
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
|
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
|
||||||
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
|
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
|
||||||
system:
|
|
||||||
boot_options:
|
|
||||||
- "#### pwnagotchi additions"
|
|
||||||
- "# this pwnagotchi image is 32-bit only no v8+ headers to build nexmon for 64 bit"
|
|
||||||
- "arm_64bit=0"
|
|
||||||
- "# dwc2 for RNDIS. comment out, and remove dwc2 and g_ether from cmdline.txt for X306 usb battery hat"
|
|
||||||
- "dtoverlay=dwc2"
|
|
||||||
- "dtoverlay=spi0-0cs"
|
|
||||||
- "dtparam=i2c1=on"
|
|
||||||
- "dtparam=i2c_arm=on"
|
|
||||||
- "dtparam=spi=on"
|
|
||||||
- "gpu_mem=16"
|
|
||||||
- "#### audio out on pins 18 and 19"
|
|
||||||
- "#dtoverlay=audremap,pins_18_19"
|
|
||||||
- "#### touchscreen on waveshare touch e-paper"
|
|
||||||
- "#dtoverlay=goodix,interrupt=27,reset=22"
|
|
||||||
- "#### for PWM backlighting on pimoroni displayhatmini"
|
|
||||||
- "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4"
|
|
||||||
modules:
|
|
||||||
- "i2c-dev"
|
|
||||||
services:
|
services:
|
||||||
enable:
|
enable:
|
||||||
- bettercap.service
|
- bettercap.service
|
||||||
@ -82,7 +62,7 @@
|
|||||||
source: "https://github.com/jayofelony/bettercap.git"
|
source: "https://github.com/jayofelony/bettercap.git"
|
||||||
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip"
|
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip"
|
||||||
ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip"
|
ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip"
|
||||||
opwngrid:
|
pwngrid:
|
||||||
source: "https://github.com/jayofelony/pwngrid.git"
|
source: "https://github.com/jayofelony/pwngrid.git"
|
||||||
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip"
|
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip"
|
||||||
torch:
|
torch:
|
||||||
@ -117,6 +97,7 @@
|
|||||||
- bc
|
- bc
|
||||||
- bison
|
- bison
|
||||||
- bluez
|
- bluez
|
||||||
|
- bluez-tools
|
||||||
- build-essential
|
- build-essential
|
||||||
- curl
|
- curl
|
||||||
- dkms
|
- dkms
|
||||||
@ -142,6 +123,7 @@
|
|||||||
- libc-ares-dev
|
- libc-ares-dev
|
||||||
- libc6-dev
|
- libc6-dev
|
||||||
- libcpuinfo-dev
|
- libcpuinfo-dev
|
||||||
|
- libcurl4-openssl-dev
|
||||||
- libdbus-1-dev
|
- libdbus-1-dev
|
||||||
- libdbus-glib-1-dev
|
- libdbus-glib-1-dev
|
||||||
- libeigen3-dev
|
- libeigen3-dev
|
||||||
@ -170,6 +152,7 @@
|
|||||||
- libsleef-dev
|
- libsleef-dev
|
||||||
- libsqlite3-dev
|
- libsqlite3-dev
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
|
- libssl-ocaml-dev
|
||||||
- libswscale5
|
- libswscale5
|
||||||
- libtiff5
|
- libtiff5
|
||||||
- libtool
|
- libtool
|
||||||
@ -178,6 +161,7 @@
|
|||||||
- lsof
|
- lsof
|
||||||
- make
|
- make
|
||||||
- ntp
|
- ntp
|
||||||
|
- python3-dbus
|
||||||
- python3-flask
|
- python3-flask
|
||||||
- python3-flask-cors
|
- python3-flask-cors
|
||||||
- python3-flaskext.wtf
|
- python3-flaskext.wtf
|
||||||
@ -224,6 +208,30 @@
|
|||||||
state: present
|
state: present
|
||||||
when: hostname.changed
|
when: hostname.changed
|
||||||
|
|
||||||
|
- name: setup /boot/config.txt
|
||||||
|
blockinfile:
|
||||||
|
path: /boot/config.txt
|
||||||
|
insertafter: EOF
|
||||||
|
block: |
|
||||||
|
dtparam=i2c1=on
|
||||||
|
dtparam=i2c_arm=on
|
||||||
|
dtparam=spi=on
|
||||||
|
gpu_mem=1
|
||||||
|
dtoverlay=dwc2
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi0]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi3]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi4]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
- name: Create custom plugin directory
|
- name: Create custom plugin directory
|
||||||
file:
|
file:
|
||||||
path: '{{ pwnagotchi.custom_plugin_dir }}'
|
path: '{{ pwnagotchi.custom_plugin_dir }}'
|
||||||
@ -282,6 +290,24 @@
|
|||||||
dest: /usr/local/lib/libpcap.so.0.8
|
dest: /usr/local/lib/libpcap.so.0.8
|
||||||
state: link
|
state: link
|
||||||
|
|
||||||
|
# install latest hcxtools
|
||||||
|
|
||||||
|
#- name: clone hcxtools
|
||||||
|
# git:
|
||||||
|
# repo: https://github.com/ZerBea/hcxtools.git
|
||||||
|
# dest: /usr/local/src/hcxtools
|
||||||
|
|
||||||
|
#- name: install hcxtools
|
||||||
|
# shell: "make && make install"
|
||||||
|
# args:
|
||||||
|
# executable: /bin/bash
|
||||||
|
# chdir: /usr/local/src/hcxtools
|
||||||
|
|
||||||
|
#- name: remove hcxtools directory
|
||||||
|
# file:
|
||||||
|
# state: absent
|
||||||
|
# path: /usr/local/src/hcxtools
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
# Install nexmon to fix wireless scanning (takes 2.5G of space)
|
# Install nexmon to fix wireless scanning (takes 2.5G of space)
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -389,29 +415,39 @@
|
|||||||
block: |
|
block: |
|
||||||
export GOPATH=$HOME/go
|
export GOPATH=$HOME/go
|
||||||
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
|
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
|
||||||
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
|
|
||||||
alias config='sudo nano /etc/pwnagotchi/config.toml'
|
|
||||||
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
|
|
||||||
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
|
|
||||||
alias pwnkill='sudo killall -USR1 pwnagotchi'
|
|
||||||
when: golang.changed
|
when: golang.changed
|
||||||
|
|
||||||
- name: download pwngrid
|
- name: download pwngrid
|
||||||
unarchive:
|
git:
|
||||||
remote_src: yes
|
repo: "{{ packages.pwngrid.source }}"
|
||||||
src: "{{ packages.opwngrid.url }}"
|
dest: /usr/local/src/pwngrid
|
||||||
dest: /usr/local/bin/
|
|
||||||
mode: 0755
|
|
||||||
|
|
||||||
- name: download and install bettercap
|
- name: install pwngrid
|
||||||
unarchive:
|
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
|
||||||
src: "{{ packages.bettercap.url }}"
|
args:
|
||||||
dest: /usr/local/bin
|
executable: /bin/bash
|
||||||
remote_src: yes
|
chdir: /usr/local/src/pwngrid
|
||||||
exclude:
|
|
||||||
- README.md
|
- name: remove pwngrid folder
|
||||||
- LICENSE.md
|
file:
|
||||||
mode: 0755
|
state: absent
|
||||||
|
path: /usr/local/src/pwngrid
|
||||||
|
|
||||||
|
- name: download bettercap
|
||||||
|
git:
|
||||||
|
repo: "{{ packages.bettercap.source }}"
|
||||||
|
dest: /usr/local/src/bettercap
|
||||||
|
|
||||||
|
- name: install bettercap 2.32.4
|
||||||
|
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
chdir: /usr/local/src/bettercap
|
||||||
|
|
||||||
|
- name: remove bettercap folder
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: /usr/local/src/bettercap
|
||||||
|
|
||||||
- name: clone bettercap caplets
|
- name: clone bettercap caplets
|
||||||
git:
|
git:
|
||||||
@ -475,20 +511,6 @@
|
|||||||
path: /boot/ssh
|
path: /boot/ssh
|
||||||
state: touch
|
state: touch
|
||||||
|
|
||||||
- name: adjust /boot/config.txt
|
|
||||||
lineinfile:
|
|
||||||
dest: /boot/config.txt
|
|
||||||
insertafter: EOF
|
|
||||||
line: '{{ item }}'
|
|
||||||
with_items: "{{system.boot_options}}"
|
|
||||||
|
|
||||||
- name: adjust /etc/modules
|
|
||||||
lineinfile:
|
|
||||||
dest: /etc/modules
|
|
||||||
insertafter: EOF
|
|
||||||
line: '{{ item }}'
|
|
||||||
with_items: "{{system.modules}}"
|
|
||||||
|
|
||||||
- name: change root partition
|
- name: change root partition
|
||||||
replace:
|
replace:
|
||||||
dest: /boot/cmdline.txt
|
dest: /boot/cmdline.txt
|
||||||
@ -596,4 +618,4 @@
|
|||||||
handlers:
|
handlers:
|
||||||
- name: reload systemd services
|
- name: reload systemd services
|
||||||
systemd:
|
systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: yes
|
@ -95,6 +95,6 @@ build {
|
|||||||
provisioner "ansible-local" {
|
provisioner "ansible-local" {
|
||||||
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
||||||
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
|
||||||
playbook_file = "data/64bit/raspberrypi64.yml"
|
playbook_file = "raspberrypi64.yml"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,23 +11,6 @@
|
|||||||
pwnagotchi:
|
pwnagotchi:
|
||||||
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
|
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
|
||||||
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
|
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
|
||||||
system:
|
|
||||||
boot_options:
|
|
||||||
- "dtoverlay=dwc2"
|
|
||||||
- "dtparam=i2c1=on"
|
|
||||||
- "dtparam=i2c_arm=on"
|
|
||||||
- "dtparam=spi=on"
|
|
||||||
- "gpu_mem=16"
|
|
||||||
- "[pi0]"
|
|
||||||
- "dtoverlay=spi0-0cs"
|
|
||||||
- "[pi3]"
|
|
||||||
- "dtoverlay=spi0-0cs"
|
|
||||||
- "[pi4]"
|
|
||||||
- "dtoverlay=spi0-0cs"
|
|
||||||
- "[pi5]"
|
|
||||||
- "dtoverlay=spi0-0cs"
|
|
||||||
modules:
|
|
||||||
- "i2c-dev"
|
|
||||||
services:
|
services:
|
||||||
enable:
|
enable:
|
||||||
- bettercap.service
|
- bettercap.service
|
||||||
@ -81,6 +64,7 @@
|
|||||||
- bc
|
- bc
|
||||||
- bison
|
- bison
|
||||||
- bluez
|
- bluez
|
||||||
|
- bluez-tools
|
||||||
- build-essential
|
- build-essential
|
||||||
- curl
|
- curl
|
||||||
- dkms
|
- dkms
|
||||||
@ -211,25 +195,6 @@
|
|||||||
path: /etc/rc.local
|
path: /etc/rc.local
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
- name: adjust /boot/config.txt
|
|
||||||
blockinfile:
|
|
||||||
dest: /boot/config.txt
|
|
||||||
insertafter: EOF
|
|
||||||
block: |
|
|
||||||
dtoverlay=dwc2
|
|
||||||
dtparam=i2c1=on
|
|
||||||
dtparam=i2c_arm=on"
|
|
||||||
dtparam=spi=on
|
|
||||||
gpu_mem=16
|
|
||||||
[pi0]
|
|
||||||
dtoverlay=spi0-0cs
|
|
||||||
[pi3]
|
|
||||||
dtoverlay=spi0-0cs
|
|
||||||
[pi4]
|
|
||||||
dtoverlay=spi0-0cs
|
|
||||||
[pi5]
|
|
||||||
dtoverlay=spi0-0cs
|
|
||||||
|
|
||||||
- name: change root partition
|
- name: change root partition
|
||||||
replace:
|
replace:
|
||||||
dest: /boot/firmware/cmdline.txt
|
dest: /boot/firmware/cmdline.txt
|
||||||
@ -246,6 +211,34 @@
|
|||||||
regexp: '(.*)$'
|
regexp: '(.*)$'
|
||||||
line: '\1 modules-load=dwc2,g_ether'
|
line: '\1 modules-load=dwc2,g_ether'
|
||||||
|
|
||||||
|
- name: setup /boot/firmware/config.txt
|
||||||
|
blockinfile:
|
||||||
|
path: /boot/firmware/config.txt
|
||||||
|
insertafter: EOF
|
||||||
|
block: |
|
||||||
|
dtparam=i2c1=on
|
||||||
|
dtparam=i2c_arm=on
|
||||||
|
dtparam=spi=on
|
||||||
|
gpu_mem=1
|
||||||
|
dtoverlay=dwc2
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi0]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi3]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi4]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
|
[pi5]
|
||||||
|
dtoverlay=spi0-0cs
|
||||||
|
#dtoverlay=disable-wifi
|
||||||
|
|
||||||
- name: change hostname
|
- name: change hostname
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: /etc/hostname
|
dest: /etc/hostname
|
||||||
@ -517,16 +510,11 @@
|
|||||||
|
|
||||||
- name: Update .bashrc for go-1.21
|
- name: Update .bashrc for go-1.21
|
||||||
blockinfile:
|
blockinfile:
|
||||||
dest: /home/pi/.bashrc
|
dest: /etc/profile
|
||||||
state: present
|
state: present
|
||||||
block: |
|
block: |
|
||||||
export GOPATH=$HOME/go
|
export GOPATH=$HOME/go
|
||||||
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
|
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
|
||||||
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
|
|
||||||
alias config='sudo nano /etc/pwnagotchi/config.toml'
|
|
||||||
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
|
|
||||||
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
|
|
||||||
alias pwnkill='sudo killall -USR1 pwnagotchi'
|
|
||||||
when: golang.changed
|
when: golang.changed
|
||||||
|
|
||||||
- name: download pwngrid
|
- name: download pwngrid
|
@ -1 +1 @@
|
|||||||
__version__ = '2.8.7'
|
__version__ = '2.9.1'
|
||||||
|
@ -254,7 +254,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
|
|||||||
txt = '%d (%d)' % (len(self._handshakes), tot)
|
txt = '%d (%d)' % (len(self._handshakes), tot)
|
||||||
|
|
||||||
if self._last_pwnd is not None:
|
if self._last_pwnd is not None:
|
||||||
txt += ' [%s]' % self._last_pwnd[:11] # So it doesn't overlap with fix_brcmfmac_plugin
|
txt += ' [%s]' % self._last_pwnd
|
||||||
|
|
||||||
self._view.set('shakes', txt)
|
self._view.set('shakes', txt)
|
||||||
|
|
||||||
|
@ -100,7 +100,6 @@ class Client(object):
|
|||||||
await asyncio.sleep(sleep_time)
|
await asyncio.sleep(sleep_time)
|
||||||
continue
|
continue
|
||||||
except OSError:
|
except OSError:
|
||||||
sleep_time = min_sleep + max_sleep * random.random()
|
|
||||||
logging.warning('connection to the bettercap endpoint failed...')
|
logging.warning('connection to the bettercap endpoint failed...')
|
||||||
pwnagotchi.restart("AUTO")
|
pwnagotchi.restart("AUTO")
|
||||||
|
|
||||||
|
@ -112,8 +112,6 @@ main.mon_stop_cmd = "/usr/bin/monstop"
|
|||||||
main.mon_max_blind_epochs = 50
|
main.mon_max_blind_epochs = 50
|
||||||
main.no_restart = false
|
main.no_restart = false
|
||||||
|
|
||||||
main.filter = ""
|
|
||||||
|
|
||||||
main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log"
|
main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log"
|
||||||
main.log.rotation.enabled = true
|
main.log.rotation.enabled = true
|
||||||
main.log.rotation.size = "10M"
|
main.log.rotation.size = "10M"
|
||||||
|
Binary file not shown.
@ -248,7 +248,7 @@ msgid "minutes"
|
|||||||
msgstr "minuten"
|
msgstr "minuten"
|
||||||
|
|
||||||
msgid "seconds"
|
msgid "seconds"
|
||||||
msgstr "seconds"
|
msgstr "sekondes"
|
||||||
|
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr "oere"
|
msgstr "oere"
|
||||||
|
Binary file not shown.
@ -1,260 +1,260 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# pwnagotchi Brazilian Portuguese translation file.
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) 2024
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the pwnagotchi package.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# Fabiano F O <fabfernandes@hotmail.com>, 2024.
|
||||||
#
|
#
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-11-17 15:46+0100\n"
|
"POT-Creation-Date: 2024-03-25 22:30+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: Foxy <EMAIL@ADDRESS>\n"
|
"Last-Translator: Fabiano F O <fabfernandes@hotmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: Portuguese (Brazil)\n"
|
"Language: Brazilian Portuguese\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "ZzzzZZzzzzZzzz"
|
msgid "ZzzzZZzzzzZzzz"
|
||||||
msgstr "ZzzzZZzzzzZzzz"
|
msgstr "ZzzzZZzzzzZzzz"
|
||||||
|
|
||||||
msgid "Hi, I'm Pwnagotchi! Starting ..."
|
msgid "Hi, I'm Pwnagotchi! Starting ..."
|
||||||
msgstr "Olá, Eu sou Pwnagotchi! Iniciando ..."
|
msgstr "Olá, sou Pwnagotchi! Iniciando ..."
|
||||||
|
|
||||||
msgid "New day, new hunt, new pwns!"
|
msgid "New day, new hunt, new pwns!"
|
||||||
msgstr "Um novo dia, Uma nova caça e novos pwns!"
|
msgstr "Novo dia, Nova caçada, Novos pwns!"
|
||||||
|
|
||||||
msgid "Hack the Planet!"
|
msgid "Hack the Planet!"
|
||||||
msgstr "Burle o Planeta!"
|
msgstr "Hackeie o Planeta!"
|
||||||
|
|
||||||
msgid "AI ready."
|
msgid "AI ready."
|
||||||
msgstr "IA pronta."
|
msgstr "IA pronta."
|
||||||
|
|
||||||
msgid "The neural network is ready."
|
msgid "The neural network is ready."
|
||||||
msgstr "A rede neural está pronta."
|
msgstr "A rede neural está pronta."
|
||||||
|
|
||||||
msgid "Generating keys, do not turn off ..."
|
msgid "Generating keys, do not turn off ..."
|
||||||
msgstr "Criando chaves, não desligue o sistema ..."
|
msgstr "Gerando chaves, não desligue ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey, channel {channel} is free! Your AP will say thanks."
|
msgid "Hey, channel {channel} is free! Your AP will say thanks."
|
||||||
msgstr "Ei, canal {channel} está livre! Seu AP vai agradecer."
|
msgstr "Ei, o canal {channel} está livre! Seu AP vai agradecer."
|
||||||
|
|
||||||
msgid "Reading last session logs ..."
|
msgid "Reading last session logs ..."
|
||||||
msgstr "Lendo os logs da ultima sessão"
|
msgstr "Lendo os logs da última sessão ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Read {lines_so_far} log lines so far ..."
|
msgid "Read {lines_so_far} log lines so far ..."
|
||||||
msgstr "Leia {lines_so_far} linha de logs até agora ..."
|
msgstr "Li {lines_so_far} linhas de logs até agora ..."
|
||||||
|
|
||||||
msgid "I'm bored ..."
|
msgid "I'm bored ..."
|
||||||
msgstr "Eu estou entediado ..."
|
msgstr "Estou entediado ..."
|
||||||
|
|
||||||
msgid "Let's go for a walk!"
|
msgid "Let's go for a walk!"
|
||||||
msgstr "Vamos ir numa caminhada!"
|
msgstr "Vamos dar um passeio!"
|
||||||
|
|
||||||
msgid "This is the best day of my life!"
|
msgid "This is the best day of my life!"
|
||||||
msgstr "Esse é o melhor dia da minha vida!"
|
msgstr "Este é o melhor dia da minha vida!"
|
||||||
|
|
||||||
msgid "Shitty day :/"
|
msgid "Shitty day :/"
|
||||||
msgstr "Dia ruim :/"
|
msgstr "Que dia ruim :/"
|
||||||
|
|
||||||
msgid "I'm extremely bored ..."
|
msgid "I'm extremely bored ..."
|
||||||
msgstr "Eu estou extremamente entediado ..."
|
msgstr "Estou extremamente entediado ..."
|
||||||
|
|
||||||
msgid "I'm very sad ..."
|
msgid "I'm very sad ..."
|
||||||
msgstr "Eu estou muito triste ..."
|
msgstr "Estou muito triste ..."
|
||||||
|
|
||||||
msgid "I'm sad"
|
msgid "I'm sad"
|
||||||
msgstr "Eu estou triste"
|
msgstr "Estou triste"
|
||||||
|
|
||||||
msgid "Leave me alone ..."
|
msgid "Leave me alone ..."
|
||||||
msgstr "Me deixe em paz ..."
|
msgstr "Me deixe em paz ..."
|
||||||
|
|
||||||
msgid "I'm mad at you!"
|
msgid "I'm mad at you!"
|
||||||
msgstr "Eu estou bravo com você!"
|
msgstr "Estou bravo com você!"
|
||||||
|
|
||||||
msgid "I'm living the life!"
|
msgid "I'm living the life!"
|
||||||
msgstr "Eu estou vivendo a vida!"
|
msgstr "Estou aproveitando a vida!"
|
||||||
|
|
||||||
msgid "I pwn therefore I am."
|
msgid "I pwn therefore I am."
|
||||||
msgstr "Eu pwn então Eu sou."
|
msgstr "Eu pwn, logo existo."
|
||||||
|
|
||||||
msgid "So many networks!!!"
|
msgid "So many networks!!!"
|
||||||
msgstr "Tantas redes!!!"
|
msgstr "Uau! Quantas redes!!"
|
||||||
|
|
||||||
msgid "I'm having so much fun!"
|
msgid "I'm having so much fun!"
|
||||||
msgstr "Eu estou tendo muita diversão"
|
msgstr "Estou me divertindo muito!"
|
||||||
|
|
||||||
msgid "My crime is that of curiosity ..."
|
msgid "My crime is that of curiosity ..."
|
||||||
msgstr "Meu crime é de curiosidade ..."
|
msgstr "Meu crime é a curiosidade ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hello {name}! Nice to meet you."
|
msgid "Hello {name}! Nice to meet you."
|
||||||
msgstr "Olá {name}! É bom em conhecê-lo"
|
msgstr "Olá {name}! Prazer em conhecê-lo."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Yo {name}! Sup?"
|
msgid "Yo {name}! Sup?"
|
||||||
msgstr "Ei {name}! Como vai?"
|
msgstr "Ei {name}! Como vai?"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey {name} how are you doing?"
|
msgid "Hey {name} how are you doing?"
|
||||||
msgstr "Ei {name} como você está indo?"
|
msgstr "Ei {name}, como você está?"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Unit {name} is nearby!"
|
msgid "Unit {name} is nearby!"
|
||||||
msgstr ""
|
msgstr "A unidade {name} está próxima!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Uhm ... goodbye {name}"
|
msgid "Uhm ... goodbye {name}"
|
||||||
msgstr ""
|
msgstr "Hmm ... tchau {name}"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} is gone ..."
|
msgid "{name} is gone ..."
|
||||||
msgstr ""
|
msgstr "{name} desapareceu ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Whoops ... {name} is gone."
|
msgid "Whoops ... {name} is gone."
|
||||||
msgstr ""
|
msgstr "Oops ... {name} desapareceu."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} missed!"
|
msgid "{name} missed!"
|
||||||
msgstr "{name} errou!"
|
msgstr "Perdi {name}!"
|
||||||
|
|
||||||
msgid "Missed!"
|
msgid "Missed!"
|
||||||
msgstr "Errei!"
|
msgstr "Perdi!"
|
||||||
|
|
||||||
msgid "Good friends are a blessing!"
|
msgid "Good friends are a blessing!"
|
||||||
msgstr "Bom amigos são uma bensão!"
|
msgstr "Bons amigos são uma bênção!"
|
||||||
|
|
||||||
msgid "I love my friends!"
|
msgid "I love my friends!"
|
||||||
msgstr "Eu amo meus amigos!"
|
msgstr "Eu amo meus amigos!"
|
||||||
|
|
||||||
msgid "Nobody wants to play with me ..."
|
msgid "Nobody wants to play with me ..."
|
||||||
msgstr "Ninguém quer brincar comigo ..."
|
msgstr "Ninguém quer brincar comigo ..."
|
||||||
|
|
||||||
msgid "I feel so alone ..."
|
msgid "I feel so alone ..."
|
||||||
msgstr "Estou me sentindo sozinho"
|
msgstr "Me sinto tão sozinho ..."
|
||||||
|
|
||||||
msgid "Where's everybody?!"
|
msgid "Where's everybody?!"
|
||||||
msgstr "Onde está todo mundo?!"
|
msgstr "Onde está todo mundo?!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Napping for {secs}s ..."
|
msgid "Napping for {secs}s ..."
|
||||||
msgstr "Tirando uma soneca por {secs}s ..."
|
msgstr "Tirando uma soneca por {secs}s ..."
|
||||||
|
|
||||||
msgid "Zzzzz"
|
msgid "Zzzzz"
|
||||||
msgstr "Zzzzz"
|
msgstr "Zzzzz"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "ZzzZzzz ({secs}s)"
|
msgid "ZzzZzzz ({secs}s)"
|
||||||
msgstr "ZzzZzzz ({secs}s)"
|
msgstr "ZzzZzzz ({secs}s)"
|
||||||
|
|
||||||
msgid "Good night."
|
msgid "Good night."
|
||||||
msgstr "Boa noite."
|
msgstr "Boa noite."
|
||||||
|
|
||||||
msgid "Zzz"
|
msgid "Zzz"
|
||||||
msgstr "Zzz"
|
msgstr "Zzz"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Waiting for {secs}s ..."
|
msgid "Waiting for {secs}s ..."
|
||||||
msgstr "Esperando por {secs}s ..."
|
msgstr "Aguardando {secs}s ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Looking around ({secs}s)"
|
msgid "Looking around ({secs}s)"
|
||||||
msgstr "Olhando por volta ({secs}s)"
|
msgstr "Olhando em volta ... ({secs}s)"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey {what} let's be friends!"
|
msgid "Hey {what} let's be friends!"
|
||||||
msgstr "Ei {what} vamos ser amigos!"
|
msgstr "Ei {what}, vamos ser amigos!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Associating to {what}"
|
msgid "Associating to {what}"
|
||||||
msgstr "Associando para {what}"
|
msgstr "Associando a {what}"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Yo {what}!"
|
msgid "Yo {what}!"
|
||||||
msgstr "Ei {what}!"
|
msgstr "Olá {what}!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Just decided that {mac} needs no WiFi!"
|
msgid "Just decided that {mac} needs no WiFi!"
|
||||||
msgstr "Apenas decidindo que {mac} não precisa de WiFi!"
|
msgstr "Acabei de decidir que {mac} não precisa de WiFi!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Deauthenticating {mac}"
|
msgid "Deauthenticating {mac}"
|
||||||
msgstr "Desautenticando {mac}"
|
msgstr "Desautenticando {mac}"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Kickbanning {mac}!"
|
msgid "Kickbanning {mac}!"
|
||||||
msgstr "Banindo {mac}!"
|
msgstr "Banindo {mac}!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Cool, we got {num} new handshake{plural}!"
|
msgid "Cool, we got {num} new handshake{plural}!"
|
||||||
msgstr "Legal, conseguimos {num} novos handshake{plural}!"
|
msgstr "Legal, conseguimos {num} novo{plural} handshake{plural}!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "You have {count} new message{plural}!"
|
msgid "You have {count} new message{plural}!"
|
||||||
msgstr "Você tem {count} novas messagem{plural}!"
|
msgstr "Você tem {count} nova{plural} messagem{plural}!"
|
||||||
|
|
||||||
msgid "Oops, something went wrong ... Rebooting ..."
|
msgid "Oops, something went wrong ... Rebooting ..."
|
||||||
msgstr "Oops, algo deu errado ... Reiniciando ..."
|
msgstr "Oops, algo deu errado ... Reiniciando ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Uploading data to {to} ..."
|
msgid "Uploading data to {to} ..."
|
||||||
msgstr "Enviando dados para {to} ..."
|
msgstr "Enviando dados para {to} ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Downloading from {name} ..."
|
msgid "Downloading from {name} ..."
|
||||||
msgstr "Instalando para {name} ..."
|
msgstr "Baixando de {name} ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Kicked {num} stations\n"
|
msgid "Kicked {num} stations\n"
|
||||||
msgstr "Expulsei {num} estações\n"
|
msgstr "Expulsei {num} estações\n"
|
||||||
|
|
||||||
msgid "Made >999 new friends\n"
|
msgid "Made >999 new friends\n"
|
||||||
msgstr "Fiz >999 novos amigos\n"
|
msgstr "Fiz >999 novos amigos\n"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Made {num} new friends\n"
|
msgid "Made {num} new friends\n"
|
||||||
msgstr "Fiz {num} novos amigos\n"
|
msgstr "Fiz {num} novos amigos\n"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Got {num} handshakes\n"
|
msgid "Got {num} handshakes\n"
|
||||||
msgstr "Peguei {num} handshakes\n"
|
msgstr "Peguei {num} handshakes\n"
|
||||||
|
|
||||||
msgid "Met 1 peer"
|
msgid "Met 1 peer"
|
||||||
msgstr "Encontrei 1 pessoa"
|
msgstr "Conheci 1 peer"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Met {num} peers"
|
msgid "Met {num} peers"
|
||||||
msgstr "Encontrei {num} pessoas"
|
msgstr "Conheci {num} peers"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"I've been pwning for {duration} and kicked {deauthed} clients! I've also met "
|
"I've been pwning for {duration} and kicked {deauthed} clients! I've also met "
|
||||||
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
|
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
|
||||||
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Estou navegando há {duration} e expulsei {deauthed} clientes! Também conheci "
|
"Estou pwning há {duration} e expulsei {deauthed} clientes! Também conheci "
|
||||||
"{associamos} novos amigos e comi {handshakes} handshakes! #pwnagotchi "
|
"{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchi "
|
||||||
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
||||||
|
|
||||||
msgid "hours"
|
msgid "hours"
|
||||||
msgstr "horas"
|
msgstr "horas"
|
||||||
|
|
||||||
msgid "minutes"
|
msgid "minutes"
|
||||||
msgstr "minutos"
|
msgstr "minutos"
|
||||||
|
|
||||||
msgid "seconds"
|
msgid "seconds"
|
||||||
msgstr "segundos"
|
msgstr "segundos"
|
||||||
|
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr "hora"
|
msgstr "hora"
|
||||||
|
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgstr "minuto"
|
msgstr "minuto"
|
||||||
|
|
||||||
msgid "second"
|
msgid "second"
|
||||||
msgstr "segundo"
|
msgstr "segundo"
|
Binary file not shown.
@ -9,8 +9,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-11-16 21:10+0100\n"
|
"POT-Creation-Date: 2023-11-16 21:10+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2024-03-27 18:40+0800\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: AlanLeung <admin@mcnot.pro>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: Twi\n"
|
"Language: Twi\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -18,218 +18,218 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "ZzzzZZzzzzZzzz"
|
msgid "ZzzzZZzzzzZzzz"
|
||||||
msgstr ""
|
msgstr "ZzzzZZzzzzZzzz"
|
||||||
|
|
||||||
msgid "Hi, I'm Pwnagotchi! Starting ..."
|
msgid "Hi, I'm Pwnagotchi! Starting ..."
|
||||||
msgstr ""
|
msgstr "HI!我是Pwnagotchi!\n程式啟動..."
|
||||||
|
|
||||||
msgid "New day, new hunt, new pwns!"
|
msgid "New day, new hunt, new pwns!"
|
||||||
msgstr ""
|
msgstr "新的一天!\n新的狩獵!新的入侵!"
|
||||||
|
|
||||||
msgid "Hack the Planet!"
|
msgid "Hack the Planet!"
|
||||||
msgstr ""
|
msgstr "我要駭入\n地球的所有人!"
|
||||||
|
|
||||||
msgid "AI ready."
|
msgid "AI ready."
|
||||||
msgstr ""
|
msgstr "人工智慧已啟動。"
|
||||||
|
|
||||||
msgid "The neural network is ready."
|
msgid "The neural network is ready."
|
||||||
msgstr ""
|
msgstr "神經網路已啟動。"
|
||||||
|
|
||||||
msgid "Generating keys, do not turn off ..."
|
msgid "Generating keys, do not turn off ..."
|
||||||
msgstr ""
|
msgstr "產生金鑰中,\n請勿關閉..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey, channel {channel} is free! Your AP will say thanks."
|
msgid "Hey, channel {channel} is free! Your AP will say thanks."
|
||||||
msgstr ""
|
msgstr "嘿,{channel}很順暢!\n你的WIFI會感謝你的。"
|
||||||
|
|
||||||
msgid "Reading last session logs ..."
|
msgid "Reading last session logs ..."
|
||||||
msgstr ""
|
msgstr "正在閱讀最後的會話紀錄..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Read {lines_so_far} log lines so far ..."
|
msgid "Read {lines_so_far} log lines so far ..."
|
||||||
msgstr ""
|
msgstr "目前已經閱讀了 {lines_so_far} 行的紀錄..."
|
||||||
|
|
||||||
msgid "I'm bored ..."
|
msgid "I'm bored ..."
|
||||||
msgstr ""
|
msgstr "我好無聊..."
|
||||||
|
|
||||||
msgid "Let's go for a walk!"
|
msgid "Let's go for a walk!"
|
||||||
msgstr ""
|
msgstr "我們! 散步! 散步散步散步散步"
|
||||||
|
|
||||||
msgid "This is the best day of my life!"
|
msgid "This is the best day of my life!"
|
||||||
msgstr ""
|
msgstr "這是我生命中最棒的一天!"
|
||||||
|
|
||||||
msgid "Shitty day :/"
|
msgid "Shitty day :/"
|
||||||
msgstr ""
|
msgstr "糟糕的一天 :/"
|
||||||
|
|
||||||
msgid "I'm extremely bored ..."
|
msgid "I'm extremely bored ..."
|
||||||
msgstr ""
|
msgstr "我超無聊的...炒雞 炒雞的那種"
|
||||||
|
|
||||||
msgid "I'm very sad ..."
|
msgid "I'm very sad ..."
|
||||||
msgstr ""
|
msgstr "我好難過..."
|
||||||
|
|
||||||
msgid "I'm sad"
|
msgid "I'm sad"
|
||||||
msgstr ""
|
msgstr "嗚嗚嗚...."
|
||||||
|
|
||||||
msgid "Leave me alone ..."
|
msgid "Leave me alone ..."
|
||||||
msgstr ""
|
msgstr "尼奏凱啦臭臭"
|
||||||
|
|
||||||
msgid "I'm mad at you!"
|
msgid "I'm mad at you!"
|
||||||
msgstr ""
|
msgstr "喔氣氣氣氣氣ˋ^ˊ"
|
||||||
|
|
||||||
msgid "I'm living the life!"
|
msgid "I'm living the life!"
|
||||||
msgstr ""
|
msgstr "真是充實的一生!"
|
||||||
|
|
||||||
msgid "I pwn therefore I am."
|
msgid "I pwn therefore I am."
|
||||||
msgstr ""
|
msgstr "我駭故我在."
|
||||||
|
|
||||||
msgid "So many networks!!!"
|
msgid "So many networks!!!"
|
||||||
msgstr ""
|
msgstr "好多網路啊!!!吃! 吃他! 吃光光!!!"
|
||||||
|
|
||||||
msgid "I'm having so much fun!"
|
msgid "I'm having so much fun!"
|
||||||
msgstr ""
|
msgstr "我玩的超級開心!"
|
||||||
|
|
||||||
msgid "My crime is that of curiosity ..."
|
msgid "My crime is that of curiosity ..."
|
||||||
msgstr ""
|
msgstr "我的缺點就是\n太好奇了..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hello {name}! Nice to meet you."
|
msgid "Hello {name}! Nice to meet you."
|
||||||
msgstr ""
|
msgstr "尼豪{name}!\n很高興認識你!!!!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Yo {name}! Sup?"
|
msgid "Yo {name}! Sup?"
|
||||||
msgstr ""
|
msgstr "嗨 {name}! 你來攻打我的村莊?"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey {name} how are you doing?"
|
msgid "Hey {name} how are you doing?"
|
||||||
msgstr ""
|
msgstr "嗨 {name} 你最近過得如何˙ˇ˙?"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Unit {name} is nearby!"
|
msgid "Unit {name} is nearby!"
|
||||||
msgstr ""
|
msgstr "{name}\n就在附近!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Uhm ... goodbye {name}"
|
msgid "Uhm ... goodbye {name}"
|
||||||
msgstr ""
|
msgstr "哦嗚 ... \n拜拜{name}"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} is gone ..."
|
msgid "{name} is gone ..."
|
||||||
msgstr ""
|
msgstr "{name}\n不見了 ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Whoops ... {name} is gone."
|
msgid "Whoops ... {name} is gone."
|
||||||
msgstr ""
|
msgstr "哦歐...\n{name}\n不見了。"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{name} missed!"
|
msgid "{name} missed!"
|
||||||
msgstr ""
|
msgstr "我剛剛錯過了{name}!"
|
||||||
|
|
||||||
msgid "Missed!"
|
msgid "Missed!"
|
||||||
msgstr ""
|
msgstr "又錯過了!"
|
||||||
|
|
||||||
msgid "Good friends are a blessing!"
|
msgid "Good friends are a blessing!"
|
||||||
msgstr ""
|
msgstr "有個好朋友\n真幸福!"
|
||||||
|
|
||||||
msgid "I love my friends!"
|
msgid "I love my friends!"
|
||||||
msgstr ""
|
msgstr "我喜歡\n我的朋友!"
|
||||||
|
|
||||||
msgid "Nobody wants to play with me ..."
|
msgid "Nobody wants to play with me ..."
|
||||||
msgstr ""
|
msgstr "沒人想跟我玩..."
|
||||||
|
|
||||||
msgid "I feel so alone ..."
|
msgid "I feel so alone ..."
|
||||||
msgstr ""
|
msgstr "我覺得好孤單..."
|
||||||
|
|
||||||
msgid "Where's everybody?!"
|
msgid "Where's everybody?!"
|
||||||
msgstr ""
|
msgstr "大家都去哪裡了?!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Napping for {secs}s ..."
|
msgid "Napping for {secs}s ..."
|
||||||
msgstr ""
|
msgstr "我想瞇{secs}秒一下..."
|
||||||
|
|
||||||
msgid "Zzzzz"
|
msgid "Zzzzz"
|
||||||
msgstr ""
|
msgstr "Zzzzz"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "ZzzZzzz ({secs}s)"
|
msgid "ZzzZzzz ({secs}s)"
|
||||||
msgstr ""
|
msgstr "ZzzZzzz({secs}秒)"
|
||||||
|
|
||||||
msgid "Good night."
|
msgid "Good night."
|
||||||
msgstr ""
|
msgstr "晚安!"
|
||||||
|
|
||||||
msgid "Zzz"
|
msgid "Zzz"
|
||||||
msgstr ""
|
msgstr "Zzz"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Waiting for {secs}s ..."
|
msgid "Waiting for {secs}s ..."
|
||||||
msgstr ""
|
msgstr "等我{secs}秒..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Looking around ({secs}s)"
|
msgid "Looking around ({secs}s)"
|
||||||
msgstr ""
|
msgstr "環顧四周({secs}秒)"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Hey {what} let's be friends!"
|
msgid "Hey {what} let's be friends!"
|
||||||
msgstr ""
|
msgstr "嗨\n{what}\n讓我們來當朋友吧!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Associating to {what}"
|
msgid "Associating to {what}"
|
||||||
msgstr ""
|
msgstr "正在連接\n{what}"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Yo {what}!"
|
msgid "Yo {what}!"
|
||||||
msgstr ""
|
msgstr "喲,\n{what}!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Just decided that {mac} needs no WiFi!"
|
msgid "Just decided that {mac} needs no WiFi!"
|
||||||
msgstr ""
|
msgstr "我要讓\n{mac}\n斷線!\n他不需要上網!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Deauthenticating {mac}"
|
msgid "Deauthenticating {mac}"
|
||||||
msgstr ""
|
msgstr "解除\n{mac}\n的授權中"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Kickbanning {mac}!"
|
msgid "Kickbanning {mac}!"
|
||||||
msgstr ""
|
msgstr "把\n{mac}\n踢出中!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Cool, we got {num} new handshake{plural}!"
|
msgid "Cool, we got {num} new handshake{plural}!"
|
||||||
msgstr ""
|
msgstr "酷耶,我們抓到{num}個\n新的握手包{plural}!"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "You have {count} new message{plural}!"
|
msgid "You have {count} new message{plural}!"
|
||||||
msgstr ""
|
msgstr "你有{count}個新訊息{plural}!"
|
||||||
|
|
||||||
msgid "Oops, something went wrong ... Rebooting ..."
|
msgid "Oops, something went wrong ... Rebooting ..."
|
||||||
msgstr ""
|
msgstr "哦歐,有些地方出錯了...\n重新啟動中..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Uploading data to {to} ..."
|
msgid "Uploading data to {to} ..."
|
||||||
msgstr ""
|
msgstr "正在上傳資料到 {to} ..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Downloading from {name} ..."
|
msgid "Downloading from {name} ..."
|
||||||
msgstr ""
|
msgstr "正在從 {name} 下載資料..."
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Kicked {num} stations\n"
|
msgid "Kicked {num} stations\n"
|
||||||
msgstr ""
|
msgstr "踢了 {num} 個設備\n"
|
||||||
|
|
||||||
msgid "Made >999 new friends\n"
|
msgid "Made >999 new friends\n"
|
||||||
msgstr ""
|
msgstr "交了 >999 個新朋友\n"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Made {num} new friends\n"
|
msgid "Made {num} new friends\n"
|
||||||
msgstr ""
|
msgstr "交了 {num} 個新朋友\n"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Got {num} handshakes\n"
|
msgid "Got {num} handshakes\n"
|
||||||
msgstr ""
|
msgstr "捕獲了 {num} 個握手包\n"
|
||||||
|
|
||||||
msgid "Met 1 peer"
|
msgid "Met 1 peer"
|
||||||
msgstr ""
|
msgstr "遇到了 1 個同好"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Met {num} peers"
|
msgid "Met {num} peers"
|
||||||
msgstr ""
|
msgstr "遇到了 {num} 個同好"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -237,21 +237,24 @@ msgid ""
|
|||||||
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
|
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
|
||||||
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
"#pwnlog #pwnlife #hacktheplanet #skynet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"我花了{duration}的時間\n駭入和踢了{deauthed}好多設備."
|
||||||
|
"我還交了好多{associated}新朋友,\n而且抓到了{handshakes}握手包!"
|
||||||
|
"#pwnagotchi#入侵日志 #駭客人生 #入侵整個星球 #天網 #我好棒˙ˇ˙"
|
||||||
|
|
||||||
msgid "hours"
|
msgid "hours"
|
||||||
msgstr ""
|
msgstr "時"
|
||||||
|
|
||||||
msgid "minutes"
|
msgid "minutes"
|
||||||
msgstr ""
|
msgstr "分"
|
||||||
|
|
||||||
msgid "seconds"
|
msgid "seconds"
|
||||||
msgstr ""
|
msgstr "秒"
|
||||||
|
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr ""
|
msgstr "時"
|
||||||
|
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgstr ""
|
msgstr "分"
|
||||||
|
|
||||||
msgid "second"
|
msgid "second"
|
||||||
msgstr ""
|
msgstr "秒"
|
||||||
|
@ -230,7 +230,7 @@ class AutoUpdate(plugins.Plugin):
|
|||||||
if num_installed > 0:
|
if num_installed > 0:
|
||||||
display.update(force=True, new_data={'status': 'Rebooting ...'})
|
display.update(force=True, new_data={'status': 'Rebooting ...'})
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
os.system("service pwnagotchi restart")
|
pwnagotchi.reboot()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("[update] %s" % e)
|
logging.error("[update] %s" % e)
|
||||||
|
@ -4,6 +4,7 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
|
import os
|
||||||
|
|
||||||
import pwnagotchi
|
import pwnagotchi
|
||||||
from pwnagotchi import plugins
|
from pwnagotchi import plugins
|
||||||
@ -32,6 +33,9 @@ class FixServices(plugins.Plugin):
|
|||||||
self.pattern2 = re.compile(r'wifi error while hopping to channel')
|
self.pattern2 = re.compile(r'wifi error while hopping to channel')
|
||||||
self.pattern3 = re.compile(r'Firmware has halted or crashed')
|
self.pattern3 = re.compile(r'Firmware has halted or crashed')
|
||||||
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
|
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
|
||||||
|
self.pattern5 = re.compile(r'fatal error: concurrent map iteration and map write')
|
||||||
|
self.pattern6 = re.compile(r'panic: runtime error')
|
||||||
|
self.pattern7 = re.compile(r'ieee80211 phy0: _brcmf_set_multicast_list: Setting allmulti failed, -110')
|
||||||
self.isReloadingMon = False
|
self.isReloadingMon = False
|
||||||
self.connection = None
|
self.connection = None
|
||||||
self.LASTTRY = 0
|
self.LASTTRY = 0
|
||||||
@ -108,7 +112,7 @@ class FixServices(plugins.Plugin):
|
|||||||
logging.debug("[Fix_Services]**** epoch")
|
logging.debug("[Fix_Services]**** epoch")
|
||||||
if time.time() - self.LASTTRY > 180:
|
if time.time() - self.LASTTRY > 180:
|
||||||
# get last 10 lines
|
# get last 10 lines
|
||||||
display = None
|
display = agent.view()
|
||||||
|
|
||||||
logging.debug("[Fix_Services]**** checking")
|
logging.debug("[Fix_Services]**** checking")
|
||||||
|
|
||||||
@ -116,7 +120,6 @@ class FixServices(plugins.Plugin):
|
|||||||
if len(self.pattern.findall(last_lines)) >= 3:
|
if len(self.pattern.findall(last_lines)) >= 3:
|
||||||
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
||||||
if hasattr(agent, 'view'):
|
if hasattr(agent, 'view'):
|
||||||
display = agent.view()
|
|
||||||
display.set('status', 'Blind-Bug detected. Restarting.')
|
display.set('status', 'Blind-Bug detected. Restarting.')
|
||||||
display.update(force=True)
|
display.update(force=True)
|
||||||
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
|
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
|
||||||
@ -129,7 +132,6 @@ class FixServices(plugins.Plugin):
|
|||||||
elif len(self.pattern2.findall(other_last_lines)) >= 5:
|
elif len(self.pattern2.findall(other_last_lines)) >= 5:
|
||||||
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
||||||
if hasattr(agent, 'view'):
|
if hasattr(agent, 'view'):
|
||||||
display = agent.view()
|
|
||||||
display.set('status', 'Wifi channel stuck. Restarting recon.')
|
display.set('status', 'Wifi channel stuck. Restarting recon.')
|
||||||
display.update(force=True)
|
display.update(force=True)
|
||||||
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.')
|
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.')
|
||||||
@ -153,7 +155,6 @@ class FixServices(plugins.Plugin):
|
|||||||
elif len(self.pattern3.findall(other_last_lines)) >= 1:
|
elif len(self.pattern3.findall(other_last_lines)) >= 1:
|
||||||
logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
|
logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
|
||||||
if hasattr(agent, 'view'):
|
if hasattr(agent, 'view'):
|
||||||
display = agent.view()
|
|
||||||
display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.')
|
display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.')
|
||||||
display.update(force=True)
|
display.update(force=True)
|
||||||
try:
|
try:
|
||||||
@ -167,7 +168,6 @@ class FixServices(plugins.Plugin):
|
|||||||
elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
|
elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
|
||||||
logging.debug("[Fix_Services] wlan0 is down!")
|
logging.debug("[Fix_Services] wlan0 is down!")
|
||||||
if hasattr(agent, 'view'):
|
if hasattr(agent, 'view'):
|
||||||
display = agent.view()
|
|
||||||
display.set('status', 'Restarting wlan0 now!')
|
display.set('status', 'Restarting wlan0 now!')
|
||||||
display.update(force=True)
|
display.update(force=True)
|
||||||
try:
|
try:
|
||||||
@ -177,6 +177,41 @@ class FixServices(plugins.Plugin):
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
logging.error("[Fix_Services monstart]: %s" % repr(err))
|
logging.error("[Fix_Services monstart]: %s" % repr(err))
|
||||||
|
|
||||||
|
# Look for pattern 5
|
||||||
|
elif len(self.pattern5.findall(other_other_last_lines)) >= 1:
|
||||||
|
logging.debug("[Fix_Services] Bettercap has crashed!")
|
||||||
|
if hasattr(agent, 'view'):
|
||||||
|
display.set('status', 'Restarting pwnagotchi!')
|
||||||
|
display.update(force=True)
|
||||||
|
os.system("systemctl restart bettercap")
|
||||||
|
pwnagotchi.restart("AUTO")
|
||||||
|
|
||||||
|
# Look for pattern 6
|
||||||
|
elif len(self.pattern6.findall(other_other_last_lines)) >= 1:
|
||||||
|
logging.debug("[Fix_Services] Bettercap has crashed!")
|
||||||
|
if hasattr(agent, 'view'):
|
||||||
|
display.set('status', 'Restarting pwnagotchi!')
|
||||||
|
display.update(force=True)
|
||||||
|
os.system("systemctl restart bettercap")
|
||||||
|
pwnagotchi.restart("AUTO")
|
||||||
|
|
||||||
|
# Look for pattern 7
|
||||||
|
elif len(self.pattern7.findall(other_other_last_lines)) >= 1:
|
||||||
|
logging.debug("[Fix_Services] Monitor mode failed!")
|
||||||
|
try:
|
||||||
|
result = agent.run("wifi.recon off; wifi.recon on")
|
||||||
|
if result["success"]:
|
||||||
|
logging.debug("[Fix_Services] wifi.recon flip: success!")
|
||||||
|
if display:
|
||||||
|
display.update(force=True, new_data={"status": "Wifi recon flipped!",
|
||||||
|
"face": faces.COOL})
|
||||||
|
else:
|
||||||
|
print("Wifi recon flipped\nthat was easy!")
|
||||||
|
else:
|
||||||
|
logging.warning("[Fix_Services] wifi.recon flip: FAILED: %s" % repr(result))
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
|
||||||
else:
|
else:
|
||||||
print("logs look good")
|
print("logs look good")
|
||||||
|
|
||||||
|
@ -14,8 +14,9 @@ class GPIOButtons(plugins.Plugin):
|
|||||||
self.running = False
|
self.running = False
|
||||||
self.ports = {}
|
self.ports = {}
|
||||||
self.commands = None
|
self.commands = None
|
||||||
|
self.options = dict()
|
||||||
|
|
||||||
def runCommand(self, channel):
|
def runcommand(self, channel):
|
||||||
command = self.ports[channel]
|
command = self.ports[channel]
|
||||||
logging.info(f"Button Pressed! Running command: {command}")
|
logging.info(f"Button Pressed! Running command: {command}")
|
||||||
process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None,
|
process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None,
|
||||||
@ -35,8 +36,8 @@ class GPIOButtons(plugins.Plugin):
|
|||||||
gpio = int(gpio)
|
gpio = int(gpio)
|
||||||
self.ports[gpio] = command
|
self.ports[gpio] = command
|
||||||
GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP)
|
GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP)
|
||||||
GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runCommand, bouncetime=600)
|
GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runcommand, bouncetime=600)
|
||||||
#set pimoroni display hat mini LED off/dim
|
# set pimoroni display hat mini LED off/dim
|
||||||
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||||
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||||
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||||
|
@ -89,7 +89,7 @@ class Grid(plugins.Plugin):
|
|||||||
logging.debug("checking pcap's")
|
logging.debug("checking pcap's")
|
||||||
config = agent.config()
|
config = agent.config()
|
||||||
|
|
||||||
pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap"))
|
pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap"))
|
||||||
num_networks = len(pcap_files)
|
num_networks = len(pcap_files)
|
||||||
reported = self.report.data_field_or('reported', default=[])
|
reported = self.report.data_field_or('reported', default=[])
|
||||||
num_reported = len(reported)
|
num_reported = len(reported)
|
||||||
|
@ -253,7 +253,6 @@ class Logtail(plugins.Plugin):
|
|||||||
"""
|
"""
|
||||||
logging.info("Logtail plugin loaded.")
|
logging.info("Logtail plugin loaded.")
|
||||||
|
|
||||||
|
|
||||||
def on_webhook(self, path, request):
|
def on_webhook(self, path, request):
|
||||||
if not self.ready:
|
if not self.ready:
|
||||||
return "Plugin not ready"
|
return "Plugin not ready"
|
||||||
|
@ -130,7 +130,7 @@ class MemTemp(plugins.Plugin):
|
|||||||
except Exception:
|
except Exception:
|
||||||
# Set default position based on screen type
|
# Set default position based on screen type
|
||||||
if ui.is_waveshare_v2():
|
if ui.is_waveshare_v2():
|
||||||
h_pos = (178, 84)
|
h_pos = (175, 84)
|
||||||
v_pos = (197, 74)
|
v_pos = (197, 74)
|
||||||
elif ui.is_waveshare_v1():
|
elif ui.is_waveshare_v1():
|
||||||
h_pos = (170, 80)
|
h_pos = (170, 80)
|
||||||
|
@ -18,12 +18,14 @@ def systemd_dropin(name, content):
|
|||||||
|
|
||||||
systemctl("daemon-reload")
|
systemctl("daemon-reload")
|
||||||
|
|
||||||
|
|
||||||
def systemctl(command, unit=None):
|
def systemctl(command, unit=None):
|
||||||
if unit:
|
if unit:
|
||||||
os.system("/bin/systemctl %s %s" % (command, unit))
|
os.system("/bin/systemctl %s %s" % (command, unit))
|
||||||
else:
|
else:
|
||||||
os.system("/bin/systemctl %s" % command)
|
os.system("/bin/systemctl %s" % command)
|
||||||
|
|
||||||
|
|
||||||
def run_task(name, options):
|
def run_task(name, options):
|
||||||
task_service_name = "switcher-%s-task.service" % name
|
task_service_name = "switcher-%s-task.service" % name
|
||||||
# save all the commands to a shell script
|
# save all the commands to a shell script
|
||||||
@ -57,7 +59,7 @@ def run_task(name, options):
|
|||||||
""" % (name, task_service_name, name))
|
""" % (name, task_service_name, name))
|
||||||
|
|
||||||
if 'reboot' in options and options['reboot']:
|
if 'reboot' in options and options['reboot']:
|
||||||
# create a indication file!
|
# create an indication file!
|
||||||
# if this file is set, we want the switcher-tasks to run
|
# if this file is set, we want the switcher-tasks to run
|
||||||
open('/root/.switcher', 'a').close()
|
open('/root/.switcher', 'a').close()
|
||||||
|
|
||||||
@ -98,6 +100,7 @@ def run_task(name, options):
|
|||||||
systemctl("daemon-reload")
|
systemctl("daemon-reload")
|
||||||
systemctl("start", task_service_name)
|
systemctl("start", task_service_name)
|
||||||
|
|
||||||
|
|
||||||
class Switcher(plugins.Plugin):
|
class Switcher(plugins.Plugin):
|
||||||
__author__ = '33197631+dadav@users.noreply.github.com'
|
__author__ = '33197631+dadav@users.noreply.github.com'
|
||||||
__version__ = '0.0.1'
|
__version__ = '0.0.1'
|
||||||
|
@ -10,13 +10,17 @@ class Widget(object):
|
|||||||
def draw(self, canvas, drawer):
|
def draw(self, canvas, drawer):
|
||||||
raise Exception("not implemented")
|
raise Exception("not implemented")
|
||||||
|
|
||||||
|
# canvas.paste: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.paste
|
||||||
|
# takes mask variable, to identify color system. (not used for pwnagotchi yet)
|
||||||
|
# Pwn should use "1" since its mainly black or white displays.
|
||||||
class Bitmap(Widget):
|
class Bitmap(Widget):
|
||||||
def __init__(self, path, xy, color=0):
|
def __init__(self, path, xy, color=0):
|
||||||
super().__init__(xy, color)
|
super().__init__(xy, color)
|
||||||
self.image = Image.open(path)
|
self.image = Image.open(path)
|
||||||
|
|
||||||
def draw(self, canvas, drawer):
|
def draw(self, canvas, drawer):
|
||||||
|
if self.color == 0xFF:
|
||||||
|
self.image = ImageOps.invert(self.image)
|
||||||
canvas.paste(self.image, self.xy)
|
canvas.paste(self.image, self.xy)
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,39 @@ class Display(View):
|
|||||||
def is_lcdhat(self):
|
def is_lcdhat(self):
|
||||||
return self._implementation.name == 'lcdhat'
|
return self._implementation.name == 'lcdhat'
|
||||||
|
|
||||||
|
def is_wavesharelcd0in96(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd0in96'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in3(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in3'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in8(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in8'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in9(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in9'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in14(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in14'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in28(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in28'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in47(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in47'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in54(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in54'
|
||||||
|
|
||||||
|
def is_wavesharelcd1in69(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd1in69'
|
||||||
|
|
||||||
|
def is_wavesharelcd2in0(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd2in0'
|
||||||
|
|
||||||
|
def is_wavesharelcd2in4(self):
|
||||||
|
return self._implementation.name == 'wavesharelcd2in4'
|
||||||
|
|
||||||
def is_waveshare144lcd(self):
|
def is_waveshare144lcd(self):
|
||||||
return self._implementation.name == 'waveshare144lcd'
|
return self._implementation.name == 'waveshare144lcd'
|
||||||
|
|
||||||
@ -202,6 +235,9 @@ class Display(View):
|
|||||||
def is_inky(self):
|
def is_inky(self):
|
||||||
return self._implementation.name == 'inky'
|
return self._implementation.name == 'inky'
|
||||||
|
|
||||||
|
def is_dummy_display(self):
|
||||||
|
return self._implementation.name == 'dummydisplay'
|
||||||
|
|
||||||
def is_papirus(self):
|
def is_papirus(self):
|
||||||
return self._implementation.name == 'papirus'
|
return self._implementation.name == 'papirus'
|
||||||
|
|
||||||
@ -228,10 +264,19 @@ class Display(View):
|
|||||||
|
|
||||||
def is_waveshareoledlcd(self):
|
def is_waveshareoledlcd(self):
|
||||||
return self._implementation.name == 'waveshareoledlcd'
|
return self._implementation.name == 'waveshareoledlcd'
|
||||||
|
|
||||||
|
def is_waveshareoledlcdvert(self):
|
||||||
|
return self._implementation.name == 'waveshareoledlcdvert'
|
||||||
|
|
||||||
|
def is_i2coled(self):
|
||||||
|
return self._implementation.name == 'i2coled'
|
||||||
|
|
||||||
def is_waveshare35lcd(self):
|
def is_waveshare35lcd(self):
|
||||||
return self._implementation.name == 'waveshare35lcd'
|
return self._implementation.name == 'waveshare35lcd'
|
||||||
|
|
||||||
|
def is_adfruit213v3(self):
|
||||||
|
return self._implementation.name == 'adafruit2in13_v3'
|
||||||
|
|
||||||
def is_waveshare_any(self):
|
def is_waveshare_any(self):
|
||||||
return self.is_waveshare_v1() or self.is_waveshare_v2()
|
return self.is_waveshare_v1() or self.is_waveshare_v2()
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ PNG = False
|
|||||||
POSITION_X = 0
|
POSITION_X = 0
|
||||||
POSITION_Y = 40
|
POSITION_Y = 40
|
||||||
|
|
||||||
|
|
||||||
def load_from_config(config):
|
def load_from_config(config):
|
||||||
for face_name, face_value in config.items():
|
for face_name, face_value in config.items():
|
||||||
globals()[face_name.upper()] = face_value
|
globals()[face_name.upper()] = face_value
|
||||||
|
@ -1,283 +1,341 @@
|
|||||||
from pwnagotchi.ui.hw.inky import Inky
|
|
||||||
from pwnagotchi.ui.hw.papirus import Papirus
|
|
||||||
from pwnagotchi.ui.hw.oledhat import OledHat
|
|
||||||
from pwnagotchi.ui.hw.lcdhat import LcdHat
|
|
||||||
from pwnagotchi.ui.hw.dfrobot import DFRobotV1
|
|
||||||
from pwnagotchi.ui.hw.dfrobot_v2 import DFRobotV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13 import WaveshareV1
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13_V2 import WaveshareV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13_V3 import WaveshareV3
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13_V4 import WaveshareV4
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in7 import Waveshare27inch
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in7_V2 import Waveshare27inchV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9 import Waveshare29inch
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9_V2 import Waveshare29inchV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in44lcd import Waveshare144lcd
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in54b import Waveshare154inchb
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13bc import Waveshare213bc
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13d import Waveshare213d
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13g import Waveshare2in13g
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13b_V4 import Waveshare213bV4
|
|
||||||
from pwnagotchi.ui.hw.waveshare3in5lcd import Waveshare35lcd
|
|
||||||
from pwnagotchi.ui.hw.spotpear24in import Spotpear24inch
|
|
||||||
from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
|
|
||||||
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
|
|
||||||
from pwnagotchi.ui.hw.pitft import Pitft
|
|
||||||
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
|
|
||||||
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in54_V2 import Waveshare154V2
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in54b_V2 import Waveshare154bV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in54c import Waveshare1in54c
|
|
||||||
from pwnagotchi.ui.hw.waveshare1in64g import Waveshare1in64g
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in7b import Waveshare27b
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in7b_V2 import Waveshare27bV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9b_V3 import Waveshare29bV3
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9b_V4 import Waveshare29bV4
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9bc import Waveshare2in9bc
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in9d import Waveshare2in9d
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in13b_V3 import Waveshare2in13bV3
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in36g import Waveshare2in36g
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in66 import Waveshare2in66
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in66b import Waveshare2in66b
|
|
||||||
from pwnagotchi.ui.hw.waveshare2in66g import Waveshare2in66g
|
|
||||||
from pwnagotchi.ui.hw.waveshare3in0g import Waveshare3in0g
|
|
||||||
from pwnagotchi.ui.hw.waveshare3in7 import Waveshare3in7
|
|
||||||
from pwnagotchi.ui.hw.waveshare3in52 import Waveshare3in52
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in01f import Waveshare4in01f
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in2 import Waveshare4in2
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in2_V2 import Waveshare4in2V2
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in2b_V2 import Waveshare4in2bV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in2bc import Waveshare4in2bc
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in26 import Waveshare4in26
|
|
||||||
from pwnagotchi.ui.hw.waveshare4in37g import Waveshare4in37g
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in65f import Waveshare5in65f
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in79 import Waveshare5in79
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in79b import Waveshare5in79b
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in83 import Waveshare5in83
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in83_V2 import Waveshare5in83V2
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in83b_V2 import Waveshare5in83bV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare5in83bc import Waveshare5in83bc
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in3f import Waveshare7in3f
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in3g import Waveshare7in3g
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5 import Waveshare7in5
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5_HD import Waveshare7in5HD
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5_V2 import Waveshare7in5V2
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5b_HD import Waveshare7in5bHD
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5b_V2 import Waveshare7in5bV2
|
|
||||||
from pwnagotchi.ui.hw.waveshare7in5bc import Waveshare7in5bc
|
|
||||||
from pwnagotchi.ui.hw.waveshare13in3k import Waveshare13in3k
|
|
||||||
|
|
||||||
|
|
||||||
def display_for(config):
|
def display_for(config):
|
||||||
# config has been normalized already in utils.load_config
|
# config has been normalized already in utils.load_config
|
||||||
if config['ui']['display']['type'] == 'inky':
|
if config['ui']['display']['type'] == 'inky':
|
||||||
|
from pwnagotchi.ui.hw.inky import Inky
|
||||||
return Inky(config)
|
return Inky(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd0in96':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd0in96 import Wavesharelcd0in96
|
||||||
|
return Wavesharelcd0in96(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in3':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in3 import Wavesharelcd1in3
|
||||||
|
return Wavesharelcd1in3(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in8':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in8 import Wavesharelcd1in8
|
||||||
|
return Wavesharelcd1in8(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in9':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in9 import Wavesharelcd1in9
|
||||||
|
return Wavesharelcd1in9(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in14':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in14 import Wavesharelcd1in14
|
||||||
|
return Wavesharelcd1in14(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in28':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in28 import Wavesharelcd1in28
|
||||||
|
return Wavesharelcd1in28(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in47':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in47 import Wavesharelcd1in47
|
||||||
|
return Wavesharelcd1in47(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in54':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in54 import Wavesharelcd1in54
|
||||||
|
return Wavesharelcd1in54(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd1in69':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd1in69 import Wavesharelcd1in69
|
||||||
|
return Wavesharelcd1in69(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd2in0':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd2in0 import Wavesharelcd2in0
|
||||||
|
return Wavesharelcd2in0(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'wavesharelcd2in4':
|
||||||
|
from pwnagotchi.ui.hw.wavesharelcd2in4 import Wavesharelcd2in4
|
||||||
|
return Wavesharelcd2in4(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'dummydisplay':
|
||||||
|
from pwnagotchi.ui.hw.dummydisplay import DummyDisplay
|
||||||
|
return DummyDisplay(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'papirus':
|
elif config['ui']['display']['type'] == 'papirus':
|
||||||
|
from pwnagotchi.ui.hw.papirus import Papirus
|
||||||
return Papirus(config)
|
return Papirus(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'oledhat':
|
elif config['ui']['display']['type'] == 'oledhat':
|
||||||
|
from pwnagotchi.ui.hw.oledhat import OledHat
|
||||||
return OledHat(config)
|
return OledHat(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'lcdhat':
|
elif config['ui']['display']['type'] == 'lcdhat':
|
||||||
|
from pwnagotchi.ui.hw.lcdhat import LcdHat
|
||||||
return LcdHat(config)
|
return LcdHat(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'dfrobot_1':
|
elif config['ui']['display']['type'] == 'dfrobot_1':
|
||||||
|
from pwnagotchi.ui.hw.dfrobot import DFRobotV1
|
||||||
return DFRobotV1(config)
|
return DFRobotV1(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'dfrobot_2':
|
elif config['ui']['display']['type'] == 'dfrobot_2':
|
||||||
|
from pwnagotchi.ui.hw.dfrobot_v2 import DFRobotV2
|
||||||
return DFRobotV2(config)
|
return DFRobotV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare144lcd':
|
elif config['ui']['display']['type'] == 'waveshare144lcd':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in44lcd import Waveshare144lcd
|
||||||
return Waveshare144lcd(config)
|
return Waveshare144lcd(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare35lcd':
|
elif config['ui']['display']['type'] == 'waveshare35lcd':
|
||||||
|
from pwnagotchi.ui.hw.waveshare3in5lcd import Waveshare35lcd
|
||||||
return Waveshare35lcd(config)
|
return Waveshare35lcd(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'spotpear24inch':
|
elif config['ui']['display']['type'] == 'spotpear24inch':
|
||||||
|
from pwnagotchi.ui.hw.spotpear24in import Spotpear24inch
|
||||||
return Spotpear24inch(config)
|
return Spotpear24inch(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'displayhatmini':
|
elif config['ui']['display']['type'] == 'displayhatmini':
|
||||||
|
from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
|
||||||
return DisplayHatMini(config)
|
return DisplayHatMini(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'pirateaudio':
|
elif config['ui']['display']['type'] == 'pirateaudio':
|
||||||
|
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
|
||||||
return PirateAudio(config)
|
return PirateAudio(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'pitft':
|
elif config['ui']['display']['type'] == 'pitft':
|
||||||
|
from pwnagotchi.ui.hw.pitft import Pitft
|
||||||
return Pitft(config)
|
return Pitft(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'tftbonnet':
|
elif config['ui']['display']['type'] == 'tftbonnet':
|
||||||
|
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
|
||||||
return TftBonnet(config)
|
return TftBonnet(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshareoledlcd':
|
elif config['ui']['display']['type'] == 'waveshareoledlcd':
|
||||||
|
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
|
||||||
return Waveshareoledlcd(config)
|
return Waveshareoledlcd(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'waveshareoledlcdvert':
|
||||||
|
from pwnagotchi.ui.hw.waveshareoledlcdvert import Waveshareoledlcdvert
|
||||||
|
return Waveshareoledlcdvert(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'i2coled':
|
||||||
|
from pwnagotchi.ui.hw.i2coled import I2COled
|
||||||
|
return I2COled(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in02':
|
elif config['ui']['display']['type'] == 'waveshare1in02':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
|
||||||
return Waveshare1in02(config)
|
return Waveshare1in02(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in54':
|
elif config['ui']['display']['type'] == 'waveshare1in54':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
|
||||||
return Waveshare154(config)
|
return Waveshare154(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in54_v2':
|
elif config['ui']['display']['type'] == 'waveshare1in54_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in54_V2 import Waveshare154V2
|
||||||
return Waveshare154V2(config)
|
return Waveshare154V2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in54b':
|
elif config['ui']['display']['type'] == 'waveshare1in54b':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in54b import Waveshare154inchb
|
||||||
return Waveshare154inchb(config)
|
return Waveshare154inchb(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in54b_v2':
|
elif config['ui']['display']['type'] == 'waveshare1in54b_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in54b_V2 import Waveshare154bV2
|
||||||
return Waveshare154bV2(config)
|
return Waveshare154bV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in54c':
|
elif config['ui']['display']['type'] == 'waveshare1in54c':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in54c import Waveshare1in54c
|
||||||
return Waveshare1in54c(config)
|
return Waveshare1in54c(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare1in64g':
|
elif config['ui']['display']['type'] == 'waveshare1in64g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare1in64g import Waveshare1in64g
|
||||||
return Waveshare1in64g(config)
|
return Waveshare1in64g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in7':
|
elif config['ui']['display']['type'] == 'waveshare2in7':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in7 import Waveshare27inch
|
||||||
return Waveshare27inch(config)
|
return Waveshare27inch(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in7_v2':
|
elif config['ui']['display']['type'] == 'waveshare2in7_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in7_V2 import Waveshare27inchV2
|
||||||
return Waveshare27inchV2(config)
|
return Waveshare27inchV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in7b':
|
elif config['ui']['display']['type'] == 'waveshare2in7b':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in7b import Waveshare27b
|
||||||
return Waveshare27b(config)
|
return Waveshare27b(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in7b_v2':
|
elif config['ui']['display']['type'] == 'waveshare2in7b_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in7b_V2 import Waveshare27bV2
|
||||||
return Waveshare27bV2(config)
|
return Waveshare27bV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9':
|
elif config['ui']['display']['type'] == 'waveshare2in9':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9 import Waveshare29inch
|
||||||
return Waveshare29inch(config)
|
return Waveshare29inch(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9bc':
|
elif config['ui']['display']['type'] == 'waveshare2in9bc':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9bc import Waveshare2in9bc
|
||||||
return Waveshare2in9bc(config)
|
return Waveshare2in9bc(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9d':
|
elif config['ui']['display']['type'] == 'waveshare2in9d':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9d import Waveshare2in9d
|
||||||
return Waveshare2in9d(config)
|
return Waveshare2in9d(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9_v2':
|
elif config['ui']['display']['type'] == 'waveshare2in9_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9_V2 import Waveshare29inchV2
|
||||||
return Waveshare29inchV2(config)
|
return Waveshare29inchV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9b_v3':
|
elif config['ui']['display']['type'] == 'waveshare2in9b_v3':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9b_V3 import Waveshare29bV3
|
||||||
return Waveshare29bV3(config)
|
return Waveshare29bV3(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in9b_v4':
|
elif config['ui']['display']['type'] == 'waveshare2in9b_v4':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in9b_V4 import Waveshare29bV4
|
||||||
return Waveshare29bV4(config)
|
return Waveshare29bV4(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare_1':
|
elif config['ui']['display']['type'] == 'waveshare_1':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13 import WaveshareV1
|
||||||
return WaveshareV1(config)
|
return WaveshareV1(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare_2':
|
elif config['ui']['display']['type'] == 'waveshare_2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13_V2 import WaveshareV2
|
||||||
return WaveshareV2(config)
|
return WaveshareV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare_3':
|
elif config['ui']['display']['type'] == 'waveshare_3':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13_V3 import WaveshareV3
|
||||||
return WaveshareV3(config)
|
return WaveshareV3(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare_4':
|
elif config['ui']['display']['type'] == 'waveshare_4':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13_V4 import WaveshareV4
|
||||||
return WaveshareV4(config)
|
return WaveshareV4(config)
|
||||||
|
|
||||||
|
elif config['ui']['display']['type'] == 'adafruit2in13_v3':
|
||||||
|
from pwnagotchi.ui.hw.adafruit2in13 import Adafruit2in13V3
|
||||||
|
return Adafruit2in13V3(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in13bc':
|
elif config['ui']['display']['type'] == 'waveshare2in13bc':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13bc import Waveshare213bc
|
||||||
return Waveshare213bc(config)
|
return Waveshare213bc(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in13d':
|
elif config['ui']['display']['type'] == 'waveshare2in13d':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13d import Waveshare213d
|
||||||
return Waveshare213d(config)
|
return Waveshare213d(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
|
elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13b_V3 import Waveshare2in13bV3
|
||||||
return Waveshare2in13bV3(config)
|
return Waveshare2in13bV3(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in13b_v4':
|
elif config['ui']['display']['type'] == 'waveshare2in13b_v4':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13b_V4 import Waveshare213bV4
|
||||||
return Waveshare213bV4(config)
|
return Waveshare213bV4(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in13g':
|
elif config['ui']['display']['type'] == 'waveshare2in13g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in13g import Waveshare2in13g
|
||||||
return Waveshare2in13g(config)
|
return Waveshare2in13g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in36g':
|
elif config['ui']['display']['type'] == 'waveshare2in36g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in36g import Waveshare2in36g
|
||||||
return Waveshare2in36g(config)
|
return Waveshare2in36g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in66':
|
elif config['ui']['display']['type'] == 'waveshare2in66':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in66 import Waveshare2in66
|
||||||
return Waveshare2in66(config)
|
return Waveshare2in66(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in66b':
|
elif config['ui']['display']['type'] == 'waveshare2in66b':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in66b import Waveshare2in66b
|
||||||
return Waveshare2in66b(config)
|
return Waveshare2in66b(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare2in66g':
|
elif config['ui']['display']['type'] == 'waveshare2in66g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare2in66g import Waveshare2in66g
|
||||||
return Waveshare2in66g(config)
|
return Waveshare2in66g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare3in0g':
|
elif config['ui']['display']['type'] == 'waveshare3in0g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare3in0g import Waveshare3in0g
|
||||||
return Waveshare3in0g(config)
|
return Waveshare3in0g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare3in7':
|
elif config['ui']['display']['type'] == 'waveshare3in7':
|
||||||
|
from pwnagotchi.ui.hw.waveshare3in7 import Waveshare3in7
|
||||||
return Waveshare3in7(config)
|
return Waveshare3in7(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare3in52':
|
elif config['ui']['display']['type'] == 'waveshare3in52':
|
||||||
|
from pwnagotchi.ui.hw.waveshare3in52 import Waveshare3in52
|
||||||
return Waveshare3in52(config)
|
return Waveshare3in52(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in01f':
|
elif config['ui']['display']['type'] == 'waveshare4in01f':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in01f import Waveshare4in01f
|
||||||
return Waveshare4in01f(config)
|
return Waveshare4in01f(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in2':
|
elif config['ui']['display']['type'] == 'waveshare4in2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in2 import Waveshare4in2
|
||||||
return Waveshare4in2(config)
|
return Waveshare4in2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in2_v2':
|
elif config['ui']['display']['type'] == 'waveshare4in2_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in2_V2 import Waveshare4in2V2
|
||||||
return Waveshare4in2V2(config)
|
return Waveshare4in2V2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in2b_v2':
|
elif config['ui']['display']['type'] == 'waveshare4in2b_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in2b_V2 import Waveshare4in2bV2
|
||||||
return Waveshare4in2bV2(config)
|
return Waveshare4in2bV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in2bc':
|
elif config['ui']['display']['type'] == 'waveshare4in2bc':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in2bc import Waveshare4in2bc
|
||||||
return Waveshare4in2bc(config)
|
return Waveshare4in2bc(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in26':
|
elif config['ui']['display']['type'] == 'waveshare4in26':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in26 import Waveshare4in26
|
||||||
return Waveshare4in26(config)
|
return Waveshare4in26(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare4in37g':
|
elif config['ui']['display']['type'] == 'waveshare4in37g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare4in37g import Waveshare4in37g
|
||||||
return Waveshare4in37g(config)
|
return Waveshare4in37g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in65f':
|
elif config['ui']['display']['type'] == 'waveshare5in65f':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in65f import Waveshare5in65f
|
||||||
return Waveshare5in65f(config)
|
return Waveshare5in65f(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in79':
|
elif config['ui']['display']['type'] == 'waveshare5in79':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in79 import Waveshare5in79
|
||||||
return Waveshare5in79(config)
|
return Waveshare5in79(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in79b':
|
elif config['ui']['display']['type'] == 'waveshare5in79b':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in79b import Waveshare5in79b
|
||||||
return Waveshare5in79b(config)
|
return Waveshare5in79b(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in83':
|
elif config['ui']['display']['type'] == 'waveshare5in83':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in83 import Waveshare5in83
|
||||||
return Waveshare5in83(config)
|
return Waveshare5in83(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in83_v2':
|
elif config['ui']['display']['type'] == 'waveshare5in83_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in83_V2 import Waveshare5in83V2
|
||||||
return Waveshare5in83V2(config)
|
return Waveshare5in83V2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in83b_v2':
|
elif config['ui']['display']['type'] == 'waveshare5in83b_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in83b_V2 import Waveshare5in83bV2
|
||||||
return Waveshare5in83bV2(config)
|
return Waveshare5in83bV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare5in83bc':
|
elif config['ui']['display']['type'] == 'waveshare5in83bc':
|
||||||
|
from pwnagotchi.ui.hw.waveshare5in83bc import Waveshare5in83bc
|
||||||
return Waveshare5in83bc(config)
|
return Waveshare5in83bc(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in3f':
|
elif config['ui']['display']['type'] == 'waveshare7in3f':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in3f import Waveshare7in3f
|
||||||
return Waveshare7in3f(config)
|
return Waveshare7in3f(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in3g':
|
elif config['ui']['display']['type'] == 'waveshare7in3g':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in3g import Waveshare7in3g
|
||||||
return Waveshare7in3g(config)
|
return Waveshare7in3g(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5':
|
elif config['ui']['display']['type'] == 'waveshare7in5':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5 import Waveshare7in5
|
||||||
return Waveshare7in5(config)
|
return Waveshare7in5(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5_HD':
|
elif config['ui']['display']['type'] == 'waveshare7in5_HD':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5_HD import Waveshare7in5HD
|
||||||
return Waveshare7in5HD(config)
|
return Waveshare7in5HD(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5_v2':
|
elif config['ui']['display']['type'] == 'waveshare7in5_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5_V2 import Waveshare7in5V2
|
||||||
return Waveshare7in5V2(config)
|
return Waveshare7in5V2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5b_HD':
|
elif config['ui']['display']['type'] == 'waveshare7in5b_HD':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5b_HD import Waveshare7in5bHD
|
||||||
return Waveshare7in5bHD(config)
|
return Waveshare7in5bHD(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5b_v2':
|
elif config['ui']['display']['type'] == 'waveshare7in5b_v2':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5b_V2 import Waveshare7in5bV2
|
||||||
return Waveshare7in5bV2(config)
|
return Waveshare7in5bV2(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare7in5bc':
|
elif config['ui']['display']['type'] == 'waveshare7in5bc':
|
||||||
|
from pwnagotchi.ui.hw.waveshare7in5bc import Waveshare7in5bc
|
||||||
return Waveshare7in5bc(config)
|
return Waveshare7in5bc(config)
|
||||||
|
|
||||||
elif config['ui']['display']['type'] == 'waveshare13in3k':
|
elif config['ui']['display']['type'] == 'waveshare13in3k':
|
||||||
|
from pwnagotchi.ui.hw.waveshare13in3k import Waveshare13in3k
|
||||||
return Waveshare13in3k(config)
|
return Waveshare13in3k(config)
|
||||||
|
45
pwnagotchi/ui/hw/adafruit2in13.py
Normal file
45
pwnagotchi/ui/hw/adafruit2in13.py
Normal 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)
|
@ -34,10 +34,10 @@ class DisplayHatMini(DisplayImpl):
|
|||||||
def initialize(self):
|
def initialize(self):
|
||||||
logging.info("initializing Display Hat Mini")
|
logging.info("initializing Display Hat Mini")
|
||||||
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789
|
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789
|
||||||
self._display = ST7789(0,1,9,13)
|
self._display = ST7789(0, 1, 9, 13, width=self._layout['width'], height=self._layout['height'], rotation=0)
|
||||||
|
|
||||||
def render(self, canvas):
|
def render(self, canvas):
|
||||||
self._display.display(canvas)
|
self._display.display(canvas)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self._display.clear()
|
pass
|
||||||
|
43
pwnagotchi/ui/hw/dummydisplay.py
Normal file
43
pwnagotchi/ui/hw/dummydisplay.py
Normal 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
|
67
pwnagotchi/ui/hw/i2coled.py
Normal file
67
pwnagotchi/ui/hw/i2coled.py
Normal 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()
|
@ -33,7 +33,7 @@ class LcdHat(DisplayImpl):
|
|||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
logging.info("initializing lcdhat display")
|
logging.info("initializing lcdhat display")
|
||||||
from pwnagotchi.ui.hw.libs.waveshare.lcdhat.epd import EPD
|
from pwnagotchi.ui.hw.libs.waveshare.lcd.lcdhat.epd import EPD
|
||||||
self._display = EPD()
|
self._display = EPD()
|
||||||
self._display.init()
|
self._display.init()
|
||||||
self._display.clear()
|
self._display.clear()
|
||||||
|
132
pwnagotchi/ui/hw/libs/adafruit/epdconfig.py
Normal file
132
pwnagotchi/ui/hw/libs/adafruit/epdconfig.py
Normal 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 ###
|
@ -93,6 +93,7 @@ ILI9341_GMCTRN1 = 0xE1
|
|||||||
|
|
||||||
ILI9341_PWCTR6 = 0xFC
|
ILI9341_PWCTR6 = 0xFC
|
||||||
|
|
||||||
|
|
||||||
class ILI9341(object):
|
class ILI9341(object):
|
||||||
"""Representation of an ILI9341 TFT LCD."""
|
"""Representation of an ILI9341 TFT LCD."""
|
||||||
|
|
||||||
@ -349,7 +350,6 @@ class ILI9341(object):
|
|||||||
# Rotate the image
|
# Rotate the image
|
||||||
pb = np.rot90(image, rotation // 90).astype('uint16')
|
pb = np.rot90(image, rotation // 90).astype('uint16')
|
||||||
|
|
||||||
|
|
||||||
# Mask and shift the 888 RGB into 565 RGB
|
# Mask and shift the 888 RGB into 565 RGB
|
||||||
red = (pb[..., [0]] & 0xf8) << 8
|
red = (pb[..., [0]] & 0xf8) << 8
|
||||||
green = (pb[..., [1]] & 0xfc) << 3
|
green = (pb[..., [1]] & 0xfc) << 3
|
||||||
|
@ -1,144 +1,164 @@
|
|||||||
FBIOGET_VSCREENINFO=0x4600
|
FBIOGET_VSCREENINFO = 0x4600
|
||||||
FBIOPUT_VSCREENINFO=0x4601
|
FBIOPUT_VSCREENINFO = 0x4601
|
||||||
FBIOGET_FSCREENINFO=0x4602
|
FBIOGET_FSCREENINFO = 0x4602
|
||||||
FBIOGETCMAP=0x4604
|
FBIOGETCMAP = 0x4604
|
||||||
FBIOPUTCMAP=0x4605
|
FBIOPUTCMAP = 0x4605
|
||||||
FBIOPAN_DISPLAY=0x4606
|
FBIOPAN_DISPLAY = 0x4606
|
||||||
|
|
||||||
FBIOGET_CON2FBMAP=0x460F
|
FBIOGET_CON2FBMAP = 0x460F
|
||||||
FBIOPUT_CON2FBMAP=0x4610
|
FBIOPUT_CON2FBMAP = 0x4610
|
||||||
FBIOBLANK=0x4611
|
FBIOBLANK = 0x4611
|
||||||
FBIO_ALLOC=0x4613
|
FBIO_ALLOC = 0x4613
|
||||||
FBIO_FREE=0x4614
|
FBIO_FREE = 0x4614
|
||||||
FBIOGET_GLYPH=0x4615
|
FBIOGET_GLYPH = 0x4615
|
||||||
FBIOGET_HWCINFO=0x4616
|
FBIOGET_HWCINFO = 0x4616
|
||||||
FBIOPUT_MODEINFO=0x4617
|
FBIOPUT_MODEINFO = 0x4617
|
||||||
FBIOGET_DISPINFO=0x4618
|
FBIOGET_DISPINFO = 0x4618
|
||||||
|
|
||||||
from mmap import mmap
|
from mmap import mmap
|
||||||
from fcntl import ioctl
|
from fcntl import ioctl
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
mm = None
|
mm = None
|
||||||
bpp, w, h = 0, 0, 0 # framebuffer bpp and size
|
bpp, w, h = 0, 0, 0 # framebuffer bpp and size
|
||||||
bytepp = 0
|
bytepp = 0
|
||||||
vx, vy, vw, vh = 0, 0, 0, 0 #virtual window offset and size
|
vx, vy, vw, vh = 0, 0, 0, 0 # virtual window offset and size
|
||||||
vi, fi = None, None
|
vi, fi = None, None
|
||||||
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a
|
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a
|
||||||
RGB = False
|
RGB = False
|
||||||
_verbose = False
|
_verbose = False
|
||||||
msize_kb = 0
|
msize_kb = 0
|
||||||
|
|
||||||
|
|
||||||
def report_fb(i=0, layer=0):
|
def report_fb(i=0, layer=0):
|
||||||
with open('/dev/fb'+str(i), 'r+b')as f:
|
with open('/dev/fb' + str(i), 'r+b') as f:
|
||||||
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
|
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
|
||||||
vi = list(struct.unpack('I'*40, vi))
|
vi = list(struct.unpack('I' * 40, vi))
|
||||||
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'
|
ffm = 'c' * 16 + 'L' + 'I' * 4 + 'H' * 3 + 'ILIIHHH'
|
||||||
fic = struct.calcsize(ffm)
|
fic = struct.calcsize(ffm)
|
||||||
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
|
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
|
||||||
|
|
||||||
|
|
||||||
def ready_fb(_bpp=None, i=0, layer=0, _win=None):
|
def ready_fb(_bpp=None, i=0, layer=0, _win=None):
|
||||||
global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp
|
global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp
|
||||||
if mm and bpp == _bpp: return mm, w, h, bpp
|
if mm and bpp == _bpp:
|
||||||
with open('/dev/fb'+str(i), 'r+b')as f:
|
return mm, w, h, bpp
|
||||||
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
|
with open('/dev/fb' + str(i), 'r+b') as f:
|
||||||
vi = list(struct.unpack('I'*40, vi))
|
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
|
||||||
bpp = vi[6]
|
vi = list(struct.unpack('I' * 40, vi))
|
||||||
bytepp = bpp//8
|
|
||||||
if _bpp:
|
|
||||||
vi[6] = _bpp # 24 bit = BGR 888 mode
|
|
||||||
try:
|
|
||||||
vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I'*40, *vi)) # fb_var_screeninfo
|
|
||||||
vi = struct.unpack('I'*40,vi)
|
|
||||||
bpp = vi[6]
|
bpp = vi[6]
|
||||||
bytepp = bpp//8
|
bytepp = bpp // 8
|
||||||
except:
|
if _bpp:
|
||||||
pass
|
vi[6] = _bpp # 24 bit = BGR 888 mode
|
||||||
|
try:
|
||||||
if vi[8] == 0 : RGB = True
|
vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I' * 40, *vi)) # fb_var_screeninfo
|
||||||
|
vi = struct.unpack('I' * 40, vi)
|
||||||
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'
|
bpp = vi[6]
|
||||||
fic = struct.calcsize(ffm)
|
bytepp = bpp // 8
|
||||||
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
|
except:
|
||||||
msize = fi[17] # = w*h*bpp//8
|
pass
|
||||||
ll, start = fi[-7:-5]
|
|
||||||
w, h = ll//bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.
|
|
||||||
if _win and len(_win)==4: # virtual window settings
|
|
||||||
vx, vy, vw, vh = _win
|
|
||||||
if vw == 'w': vw = w
|
|
||||||
if vh == 'h': vh = h
|
|
||||||
vx, vy, vw, vh = map(int, (vx, vy, vw, vh))
|
|
||||||
if vx>=w: vx = 0
|
|
||||||
if vy>=h: vy = 0
|
|
||||||
if vx>w: vw = w - vx
|
|
||||||
else: vw -= vx
|
|
||||||
if vy>h: vh = h - vy
|
|
||||||
else: vh -= vy
|
|
||||||
else:
|
|
||||||
vx, vy, vw, vh = 0,0,w,h
|
|
||||||
msize_kb = vw*vh*bytepp//1024 # more accurate FB memory size in kb
|
|
||||||
|
|
||||||
mm = mmap(f.fileno(), msize, offset=start)
|
if vi[8] == 0:
|
||||||
return mm, w, h, bpp#ll//(bpp//8), h
|
RGB = True
|
||||||
|
|
||||||
|
ffm = 'c' * 16 + 'L' + 'I' * 4 + 'H' * 3 + 'ILIIHHH'
|
||||||
|
fic = struct.calcsize(ffm)
|
||||||
|
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
|
||||||
|
msize = fi[17] # = w*h*bpp//8
|
||||||
|
ll, start = fi[-7:-5]
|
||||||
|
w, h = ll // bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.
|
||||||
|
if _win and len(_win) == 4: # virtual window settings
|
||||||
|
vx, vy, vw, vh = _win
|
||||||
|
if vw == 'w':
|
||||||
|
vw = w
|
||||||
|
if vh == 'h':
|
||||||
|
vh = h
|
||||||
|
vx, vy, vw, vh = map(int, (vx, vy, vw, vh))
|
||||||
|
if vx >= w:
|
||||||
|
vx = 0
|
||||||
|
if vy >= h:
|
||||||
|
vy = 0
|
||||||
|
if vx > w:
|
||||||
|
vw = w - vx
|
||||||
|
else:
|
||||||
|
vw -= vx
|
||||||
|
if vy > h:
|
||||||
|
vh = h - vy
|
||||||
|
else:
|
||||||
|
vh -= vy
|
||||||
|
else:
|
||||||
|
vx, vy, vw, vh = 0, 0, w, h
|
||||||
|
msize_kb = vw * vh * bytepp // 1024 # more accurate FB memory size in kb
|
||||||
|
|
||||||
|
mm = mmap(f.fileno(), msize, offset=start)
|
||||||
|
return mm, w, h, bpp # ll//(bpp//8), h
|
||||||
|
|
||||||
|
|
||||||
|
def fill_scr(r, g, b):
|
||||||
|
if bpp == 32:
|
||||||
|
seed = struct.pack('BBBB', b, g, r, 255)
|
||||||
|
elif bpp == 24:
|
||||||
|
seed = struct.pack('BBB', b, g, r)
|
||||||
|
elif bpp == 16:
|
||||||
|
seed = struct.pack('H', r >> 3 << 11 | g >> 2 << 5 | b >> 3)
|
||||||
|
mm.seek(0)
|
||||||
|
show_img(seed * vw * vh)
|
||||||
|
|
||||||
def fill_scr(r,g,b):
|
|
||||||
if bpp == 32:
|
|
||||||
seed = struct.pack('BBBB', b, g, r, 255)
|
|
||||||
elif bpp == 24:
|
|
||||||
seed = struct.pack('BBB', b, g, r)
|
|
||||||
elif bpp == 16:
|
|
||||||
seed = struct.pack('H', r>>3<<11 | g>>2<<5 | b>>3)
|
|
||||||
mm.seek(0)
|
|
||||||
show_img(seed * vw * vh)
|
|
||||||
|
|
||||||
def black_scr():
|
def black_scr():
|
||||||
fill_scr(0,0,0)
|
fill_scr(0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def white_scr():
|
def white_scr():
|
||||||
fill_scr(255,255,255)
|
fill_scr(255, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
|
def mmseekto(x, y):
|
||||||
|
mm.seek((x + y * w) * bytepp)
|
||||||
|
|
||||||
def mmseekto(x,y):
|
|
||||||
mm.seek((x + y*w) * bytepp)
|
|
||||||
|
|
||||||
def dot(x, y, r, g, b):
|
def dot(x, y, r, g, b):
|
||||||
mmseekto(x,y)
|
mmseekto(x, y)
|
||||||
mm.write(struct.pack('BBB',*((r,g,b) if RGB else (b,g,r))))
|
mm.write(struct.pack('BBB', *((r, g, b) if RGB else (b, g, r))))
|
||||||
|
|
||||||
|
|
||||||
|
def get_pixel(x, y):
|
||||||
|
mmseekto(x, y)
|
||||||
|
return mm.read(bytepp)
|
||||||
|
|
||||||
def get_pixel(x,y):
|
|
||||||
mmseekto(x,y)
|
|
||||||
return mm.read(bytepp)
|
|
||||||
|
|
||||||
def _888_to_565(bt):
|
def _888_to_565(bt):
|
||||||
b = b''
|
b = b''
|
||||||
for i in range(0, len(bt),3):
|
for i in range(0, len(bt), 3):
|
||||||
b += int.to_bytes(bt[i]>>3<<11|bt[i+1]>>2<<5|bt[i+2]>>3, 2, 'little')
|
b += int.to_bytes(bt[i] >> 3 << 11 | bt[i + 1] >> 2 << 5 | bt[i + 2] >> 3, 2, 'little')
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
|
||||||
def numpy_888_565(bt):
|
def numpy_888_565(bt):
|
||||||
import numpy as np
|
import numpy as np
|
||||||
arr = np.fromstring(bt, dtype=np.uint32)
|
arr = np.fromstring(bt, dtype=np.uint32)
|
||||||
return (((0xF80000 & arr)>>8)|((0xFC00 & arr)>>5)|((0xF8 & arr)>>3)).astype(np.uint16).tostring()
|
return (((0xF80000 & arr) >> 8) | ((0xFC00 & arr) >> 5) | ((0xF8 & arr) >> 3)).astype(np.uint16).tostring()
|
||||||
|
|
||||||
|
|
||||||
def show_img(img):
|
def show_img(img):
|
||||||
if not type(img) is bytes:
|
if not type(img) is bytes:
|
||||||
if not RGB:
|
if not RGB:
|
||||||
if bpp == 24: # for RPI
|
if bpp == 24: # for RPI
|
||||||
img = img.tobytes('raw', 'BGR')
|
img = img.tobytes('raw', 'BGR')
|
||||||
else:
|
else:
|
||||||
img = img.convert('RGBA').tobytes('raw', 'BGRA')
|
img = img.convert('RGBA').tobytes('raw', 'BGRA')
|
||||||
if bpp == 16:
|
if bpp == 16:
|
||||||
img = numpy_888_565(img)
|
img = numpy_888_565(img)
|
||||||
else:
|
else:
|
||||||
if bpp == 24:
|
if bpp == 24:
|
||||||
img = img.tobytes()
|
img = img.tobytes()
|
||||||
else:
|
else:
|
||||||
img = img.convert('RGBA').tobytes()
|
img = img.convert('RGBA').tobytes()
|
||||||
if bpp == 16:
|
if bpp == 16:
|
||||||
img = numpy_888_565(img)
|
img = numpy_888_565(img)
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
b = BytesIO(img)
|
b = BytesIO(img)
|
||||||
s = vw*bytepp
|
s = vw * bytepp
|
||||||
for y in range(vh): # virtual window drawing
|
for y in range(vh): # virtual window drawing
|
||||||
mmseekto(vx,vy+y)
|
mmseekto(vx, vy + y)
|
||||||
mm.write(b.read(s))
|
mm.write(b.read(s))
|
||||||
|
|
||||||
|
312
pwnagotchi/ui/hw/libs/i2coled/SSD1306.py
Normal file
312
pwnagotchi/ui/hw/libs/i2coled/SSD1306.py
Normal 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
|
34
pwnagotchi/ui/hw/libs/i2coled/epd.py
Normal file
34
pwnagotchi/ui/hw/libs/i2coled/epd.py
Normal 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()
|
@ -90,8 +90,8 @@ ST7789_PWCTR6 = 0xFC
|
|||||||
class ST7789(object):
|
class ST7789(object):
|
||||||
"""Representation of an ST7789 TFT LCD."""
|
"""Representation of an ST7789 TFT LCD."""
|
||||||
|
|
||||||
def __init__(self, port, cs, dc, backlight, rst=None, width=320,
|
def __init__(self, port, cs, dc, backlight=None, rst=None, width=240,
|
||||||
height=240, rotation=0, invert=True, spi_speed_hz=60 * 1000 * 1000,
|
height=240, rotation=90, invert=True, spi_speed_hz=4000000,
|
||||||
offset_left=0,
|
offset_left=0,
|
||||||
offset_top=0):
|
offset_top=0):
|
||||||
"""Create an instance of the display using SPI communication.
|
"""Create an instance of the display using SPI communication.
|
||||||
|
0
pwnagotchi/ui/hw/libs/waveshare/epaper/__init__.py
Normal file
0
pwnagotchi/ui/hw/libs/waveshare/epaper/__init__.py
Normal file
@ -31,7 +31,6 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import subprocess
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -113,6 +112,7 @@ class RaspberryPi:
|
|||||||
|
|
||||||
self.GPIO_RST_PIN.off()
|
self.GPIO_RST_PIN.off()
|
||||||
self.GPIO_DC_PIN.off()
|
self.GPIO_DC_PIN.off()
|
||||||
|
self.GPIO_CS_PIN.off()
|
||||||
self.GPIO_PWR_PIN.off()
|
self.GPIO_PWR_PIN.off()
|
||||||
logger.debug("close 5V, Module enters 0 power consumption ...")
|
logger.debug("close 5V, Module enters 0 power consumption ...")
|
||||||
|
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 960
|
EPD_WIDTH = 960
|
@ -29,7 +29,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 80
|
EPD_WIDTH = 80
|
@ -80,7 +80,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 200
|
EPD_WIDTH = 200
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 200
|
EPD_WIDTH = 200
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 200
|
EPD_WIDTH = 200
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 200
|
EPD_WIDTH = 200
|
@ -27,7 +27,7 @@
|
|||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
#
|
#
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 152
|
EPD_WIDTH = 152
|
@ -29,11 +29,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
import PIL
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 168
|
EPD_WIDTH = 168
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -27,7 +27,7 @@
|
|||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
# import numpy as np
|
# import numpy as np
|
||||||
|
|
@ -40,9 +40,8 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from . import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 104
|
EPD_WIDTH = 104
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -4,8 +4,8 @@
|
|||||||
# * | Function : Electronic paper driver
|
# * | Function : Electronic paper driver
|
||||||
# * | Info :
|
# * | Info :
|
||||||
# *----------------
|
# *----------------
|
||||||
# * | This version: V1.1
|
# * | This version: V1.2
|
||||||
# * | Date : 2021-10-30
|
# * | Date : 2022-08-9
|
||||||
# # | Info : python demo
|
# # | Info : python demo
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -29,15 +29,15 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from . import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
||||||
EPD_HEIGHT = 250
|
EPD_HEIGHT = 250
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EPD:
|
class EPD:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.reset_pin = epdconfig.RST_PIN
|
self.reset_pin = epdconfig.RST_PIN
|
||||||
@ -46,68 +46,70 @@ class EPD:
|
|||||||
self.cs_pin = epdconfig.CS_PIN
|
self.cs_pin = epdconfig.CS_PIN
|
||||||
self.width = EPD_WIDTH
|
self.width = EPD_WIDTH
|
||||||
self.height = EPD_HEIGHT
|
self.height = EPD_HEIGHT
|
||||||
|
|
||||||
lut_partial_update= [
|
lut_partial_update = [
|
||||||
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x14,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
|
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
|
||||||
0x22,0x17,0x41,0x00,0x32,0x36,
|
0x22, 0x17, 0x41, 0x00, 0x32, 0x36,
|
||||||
]
|
]
|
||||||
|
|
||||||
lut_full_update = [
|
lut_full_update = [
|
||||||
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
|
0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0xF,0x0,0x0,0xF,0x0,0x0,0x2,
|
0xF, 0x0, 0x0, 0xF, 0x0, 0x0, 0x2,
|
||||||
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
|
0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
|
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
|
||||||
0x22,0x17,0x41,0x0,0x32,0x36,
|
0x22, 0x17, 0x41, 0x0, 0x32, 0x36,
|
||||||
]
|
]
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function :Hardware reset
|
function :Hardware reset
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
epdconfig.digital_write(self.reset_pin, 1)
|
epdconfig.digital_write(self.reset_pin, 1)
|
||||||
epdconfig.delay_ms(20)
|
epdconfig.delay_ms(20)
|
||||||
epdconfig.digital_write(self.reset_pin, 0)
|
epdconfig.digital_write(self.reset_pin, 0)
|
||||||
epdconfig.delay_ms(2)
|
epdconfig.delay_ms(2)
|
||||||
epdconfig.digital_write(self.reset_pin, 1)
|
epdconfig.digital_write(self.reset_pin, 1)
|
||||||
epdconfig.delay_ms(20)
|
epdconfig.delay_ms(20)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function :send command
|
function :send command
|
||||||
parameter:
|
parameter:
|
||||||
command : Command register
|
command : Command register
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def send_command(self, command):
|
def send_command(self, command):
|
||||||
epdconfig.digital_write(self.dc_pin, 0)
|
epdconfig.digital_write(self.dc_pin, 0)
|
||||||
epdconfig.digital_write(self.cs_pin, 0)
|
epdconfig.digital_write(self.cs_pin, 0)
|
||||||
@ -119,71 +121,84 @@ class EPD:
|
|||||||
parameter:
|
parameter:
|
||||||
data : Write data
|
data : Write data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def send_data(self, data):
|
def send_data(self, data):
|
||||||
epdconfig.digital_write(self.dc_pin, 1)
|
epdconfig.digital_write(self.dc_pin, 1)
|
||||||
epdconfig.digital_write(self.cs_pin, 0)
|
epdconfig.digital_write(self.cs_pin, 0)
|
||||||
epdconfig.spi_writebyte([data])
|
epdconfig.spi_writebyte([data])
|
||||||
epdconfig.digital_write(self.cs_pin, 1)
|
epdconfig.digital_write(self.cs_pin, 1)
|
||||||
|
|
||||||
|
# send a lot of data
|
||||||
|
def send_data2(self, data):
|
||||||
|
epdconfig.digital_write(self.dc_pin, 1)
|
||||||
|
epdconfig.digital_write(self.cs_pin, 0)
|
||||||
|
epdconfig.spi_writebyte2(data)
|
||||||
|
epdconfig.digital_write(self.cs_pin, 1)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function :Wait until the busy_pin goes LOW
|
function :Wait until the busy_pin goes LOW
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def ReadBusy(self):
|
def ReadBusy(self):
|
||||||
logger.debug("e-Paper busy")
|
logger.debug("e-Paper busy")
|
||||||
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
|
while (epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
|
||||||
epdconfig.delay_ms(10)
|
epdconfig.delay_ms(10)
|
||||||
logger.debug("e-Paper busy release")
|
logger.debug("e-Paper busy release")
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Turn On Display
|
function : Turn On Display
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def TurnOnDisplay(self):
|
def TurnOnDisplay(self):
|
||||||
self.send_command(0x22) # Display Update Control
|
self.send_command(0x22) # Display Update Control
|
||||||
self.send_data(0xC7)
|
self.send_data(0xC7)
|
||||||
self.send_command(0x20) # Activate Display Update Sequence
|
self.send_command(0x20) # Activate Display Update Sequence
|
||||||
self.ReadBusy()
|
self.ReadBusy()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Turn On Display Part
|
function : Turn On Display Part
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def TurnOnDisplayPart(self):
|
def TurnOnDisplayPart(self):
|
||||||
self.send_command(0x22) # Display Update Control
|
self.send_command(0x22) # Display Update Control
|
||||||
self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf
|
self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf
|
||||||
self.send_command(0x20) # Activate Display Update Sequence
|
self.send_command(0x20) # Activate Display Update Sequence
|
||||||
self.ReadBusy()
|
self.ReadBusy()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Set lut
|
function : Set lut
|
||||||
parameter:
|
parameter:
|
||||||
lut : lut data
|
lut : lut data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def Lut(self, lut):
|
def Lut(self, lut):
|
||||||
self.send_command(0x32)
|
self.send_command(0x32)
|
||||||
for i in range(0, 153):
|
for i in range(0, 153):
|
||||||
self.send_data(lut[i])
|
self.send_data(lut[i])
|
||||||
self.ReadBusy()
|
self.ReadBusy()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Send lut data and configuration
|
function : Send lut data and configuration
|
||||||
parameter:
|
parameter:
|
||||||
lut : lut data
|
lut : lut data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def SetLut(self, lut):
|
def SetLut(self, lut):
|
||||||
self.Lut(lut)
|
self.Lut(lut)
|
||||||
self.send_command(0x3f)
|
self.send_command(0x3f)
|
||||||
self.send_data(lut[153])
|
self.send_data(lut[153])
|
||||||
self.send_command(0x03) # gate voltage
|
self.send_command(0x03) # gate voltage
|
||||||
self.send_data(lut[154])
|
self.send_data(lut[154])
|
||||||
self.send_command(0x04) # source voltage
|
self.send_command(0x04) # source voltage
|
||||||
self.send_data(lut[155]) # VSH
|
self.send_data(lut[155]) # VSH
|
||||||
self.send_data(lut[156]) # VSH2
|
self.send_data(lut[156]) # VSH2
|
||||||
self.send_data(lut[157]) # VSL
|
self.send_data(lut[157]) # VSL
|
||||||
self.send_command(0x2c) # VCOM
|
self.send_command(0x2c) # VCOM
|
||||||
self.send_data(lut[158])
|
self.send_data(lut[158])
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Setting the display window
|
function : Setting the display window
|
||||||
parameter:
|
parameter:
|
||||||
@ -192,13 +207,14 @@ class EPD:
|
|||||||
xend : End position of X-axis
|
xend : End position of X-axis
|
||||||
yend : End position of Y-axis
|
yend : End position of Y-axis
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def SetWindow(self, x_start, y_start, x_end, y_end):
|
def SetWindow(self, x_start, y_start, x_end, y_end):
|
||||||
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
|
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
|
||||||
# x point must be the multiple of 8 or the last 3 bits will be ignored
|
# x point must be the multiple of 8 or the last 3 bits will be ignored
|
||||||
self.send_data((x_start>>3) & 0xFF)
|
self.send_data((x_start >> 3) & 0xFF)
|
||||||
self.send_data((x_end>>3) & 0xFF)
|
self.send_data((x_end >> 3) & 0xFF)
|
||||||
|
|
||||||
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
|
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
|
||||||
self.send_data(y_start & 0xFF)
|
self.send_data(y_start & 0xFF)
|
||||||
self.send_data((y_start >> 8) & 0xFF)
|
self.send_data((y_start >> 8) & 0xFF)
|
||||||
self.send_data(y_end & 0xFF)
|
self.send_data(y_end & 0xFF)
|
||||||
@ -210,52 +226,54 @@ class EPD:
|
|||||||
x : X-axis starting position
|
x : X-axis starting position
|
||||||
y : Y-axis starting position
|
y : Y-axis starting position
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def SetCursor(self, x, y):
|
def SetCursor(self, x, y):
|
||||||
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
|
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
|
||||||
# x point must be the multiple of 8 or the last 3 bits will be ignored
|
# x point must be the multiple of 8 or the last 3 bits will be ignored
|
||||||
self.send_data(x & 0xFF)
|
self.send_data(x & 0xFF)
|
||||||
|
|
||||||
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
|
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
|
||||||
self.send_data(y & 0xFF)
|
self.send_data(y & 0xFF)
|
||||||
self.send_data((y >> 8) & 0xFF)
|
self.send_data((y >> 8) & 0xFF)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Initialize the e-Paper register
|
function : Initialize the e-Paper register
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
if (epdconfig.module_init() != 0):
|
if (epdconfig.module_init() != 0):
|
||||||
return -1
|
return -1
|
||||||
# EPD hardware init start
|
# EPD hardware init start
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
self.ReadBusy()
|
|
||||||
self.send_command(0x12) #SWRESET
|
|
||||||
self.ReadBusy()
|
|
||||||
|
|
||||||
self.send_command(0x01) #Driver output control
|
self.ReadBusy()
|
||||||
|
self.send_command(0x12) # SWRESET
|
||||||
|
self.ReadBusy()
|
||||||
|
|
||||||
|
self.send_command(0x01) # Driver output control
|
||||||
self.send_data(0xf9)
|
self.send_data(0xf9)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
|
|
||||||
self.send_command(0x11) #data entry mode
|
self.send_command(0x11) # data entry mode
|
||||||
self.send_data(0x03)
|
self.send_data(0x03)
|
||||||
|
|
||||||
self.SetWindow(0, 0, self.width-1, self.height-1)
|
self.SetWindow(0, 0, self.width - 1, self.height - 1)
|
||||||
self.SetCursor(0, 0)
|
self.SetCursor(0, 0)
|
||||||
|
|
||||||
self.send_command(0x3c)
|
self.send_command(0x3c)
|
||||||
self.send_data(0x05)
|
self.send_data(0x05)
|
||||||
|
|
||||||
self.send_command(0x21) # Display update control
|
self.send_command(0x21) # Display update control
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
self.send_data(0x80)
|
self.send_data(0x80)
|
||||||
|
|
||||||
self.send_command(0x18)
|
self.send_command(0x18)
|
||||||
self.send_data(0x80)
|
self.send_data(0x80)
|
||||||
|
|
||||||
self.ReadBusy()
|
self.ReadBusy()
|
||||||
|
|
||||||
self.SetLut(self.lut_full_update)
|
self.SetLut(self.lut_full_update)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -264,54 +282,52 @@ class EPD:
|
|||||||
parameter:
|
parameter:
|
||||||
image : Image data
|
image : Image data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def getbuffer(self, image):
|
def getbuffer(self, image):
|
||||||
img = image
|
img = image
|
||||||
imwidth, imheight = img.size
|
imwidth, imheight = img.size
|
||||||
if(imwidth == self.width and imheight == self.height):
|
if (imwidth == self.width and imheight == self.height):
|
||||||
img = img.convert('1')
|
img = img.convert('1')
|
||||||
elif(imwidth == self.height and imheight == self.width):
|
elif (imwidth == self.height and imheight == self.width):
|
||||||
# image has correct dimensions, but needs to be rotated
|
# image has correct dimensions, but needs to be rotated
|
||||||
img = img.rotate(90, expand=True).convert('1')
|
img = img.rotate(90, expand=True).convert('1')
|
||||||
else:
|
else:
|
||||||
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
|
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
|
||||||
# return a blank buffer
|
# return a blank buffer
|
||||||
return [0x00] * (int(self.width/8) * self.height)
|
return [0x00] * (int(self.width / 8) * self.height)
|
||||||
|
|
||||||
buf = bytearray(img.tobytes('raw'))
|
buf = bytearray(img.tobytes('raw'))
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Sends the image buffer in RAM to e-Paper and displays
|
function : Sends the image buffer in RAM to e-Paper and displays
|
||||||
parameter:
|
parameter:
|
||||||
image : Image data
|
image : Image data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def display(self, image):
|
def display(self, image):
|
||||||
if self.width%8 == 0:
|
if self.width % 8 == 0:
|
||||||
linewidth = int(self.width/8)
|
linewidth = int(self.width / 8)
|
||||||
else:
|
else:
|
||||||
linewidth = int(self.width/8) + 1
|
linewidth = int(self.width / 8) + 1
|
||||||
|
|
||||||
self.send_command(0x24)
|
self.send_command(0x24)
|
||||||
for j in range(0, self.height):
|
for j in range(0, self.height):
|
||||||
for i in range(0, linewidth):
|
for i in range(0, linewidth):
|
||||||
self.send_data(image[i + j * linewidth])
|
self.send_data(image[i + j * linewidth])
|
||||||
self.TurnOnDisplay()
|
self.TurnOnDisplay()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Sends the image buffer in RAM to e-Paper and partial refresh
|
function : Sends the image buffer in RAM to e-Paper and partial refresh
|
||||||
parameter:
|
parameter:
|
||||||
image : Image data
|
image : Image data
|
||||||
'''
|
'''
|
||||||
def displayPartial(self, image):
|
|
||||||
if self.width%8 == 0:
|
|
||||||
linewidth = int(self.width/8)
|
|
||||||
else:
|
|
||||||
linewidth = int(self.width/8) + 1
|
|
||||||
|
|
||||||
|
def displayPartial(self, image):
|
||||||
epdconfig.digital_write(self.reset_pin, 0)
|
epdconfig.digital_write(self.reset_pin, 0)
|
||||||
epdconfig.delay_ms(1)
|
epdconfig.delay_ms(1)
|
||||||
epdconfig.digital_write(self.reset_pin, 1)
|
epdconfig.digital_write(self.reset_pin, 1)
|
||||||
|
|
||||||
self.SetLut(self.lut_partial_update)
|
self.SetLut(self.lut_partial_update)
|
||||||
self.send_command(0x37)
|
self.send_command(0x37)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
@ -322,24 +338,25 @@ class EPD:
|
|||||||
self.send_data(0x40)
|
self.send_data(0x40)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
self.send_data(0x00)
|
self.send_data(0x00)
|
||||||
|
|
||||||
self.send_command(0x3C) #BorderWavefrom
|
self.send_command(0x3C) # BorderWavefrom
|
||||||
self.send_data(0x80)
|
self.send_data(0x80)
|
||||||
|
|
||||||
self.send_command(0x22)
|
self.send_command(0x22)
|
||||||
self.send_data(0xC0)
|
self.send_data(0xC0)
|
||||||
self.send_command(0x20)
|
self.send_command(0x20)
|
||||||
self.ReadBusy()
|
self.ReadBusy()
|
||||||
|
|
||||||
self.SetWindow(0, 0, self.width - 1, self.height - 1)
|
self.SetWindow(0, 0, self.width - 1, self.height - 1)
|
||||||
self.SetCursor(0, 0)
|
self.SetCursor(0, 0)
|
||||||
|
|
||||||
self.send_command(0x24) # WRITE_RAM
|
self.send_command(0x24) # WRITE_RAM
|
||||||
for j in range(0, self.height):
|
# for j in range(0, self.height):
|
||||||
for i in range(0, linewidth):
|
# for i in range(0, linewidth):
|
||||||
self.send_data(image[i + j * linewidth])
|
# self.send_data(image[i + j * linewidth])
|
||||||
|
self.send_data2(image)
|
||||||
self.TurnOnDisplayPart()
|
self.TurnOnDisplayPart()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -347,51 +364,41 @@ class EPD:
|
|||||||
parameter:
|
parameter:
|
||||||
image : Image data
|
image : Image data
|
||||||
'''
|
'''
|
||||||
def displayPartBaseImage(self, image):
|
|
||||||
if self.width%8 == 0:
|
|
||||||
linewidth = int(self.width/8)
|
|
||||||
else:
|
|
||||||
linewidth = int(self.width/8) + 1
|
|
||||||
|
|
||||||
|
def displayPartBaseImage(self, image):
|
||||||
self.send_command(0x24)
|
self.send_command(0x24)
|
||||||
for j in range(0, self.height):
|
self.send_data2(image)
|
||||||
for i in range(0, linewidth):
|
|
||||||
self.send_data(image[i + j * linewidth])
|
|
||||||
|
|
||||||
self.send_command(0x26)
|
self.send_command(0x26)
|
||||||
for j in range(0, self.height):
|
self.send_data2(image)
|
||||||
for i in range(0, linewidth):
|
|
||||||
self.send_data(image[i + j * linewidth])
|
|
||||||
self.TurnOnDisplay()
|
self.TurnOnDisplay()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Clear screen
|
function : Clear screen
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
def Clear(self, color):
|
|
||||||
if self.width%8 == 0:
|
def Clear(self, color=0xFF):
|
||||||
linewidth = int(self.width/8)
|
if self.width % 8 == 0:
|
||||||
|
linewidth = int(self.width / 8)
|
||||||
else:
|
else:
|
||||||
linewidth = int(self.width/8) + 1
|
linewidth = int(self.width / 8) + 1
|
||||||
# logger.debug(linewidth)
|
# logger.debug(linewidth)
|
||||||
|
|
||||||
self.send_command(0x24)
|
self.send_command(0x24)
|
||||||
for j in range(0, self.height):
|
self.send_data2([color] * int(self.height * linewidth))
|
||||||
for i in range(0, linewidth):
|
|
||||||
self.send_data(color)
|
|
||||||
|
|
||||||
self.TurnOnDisplay()
|
self.TurnOnDisplay()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
function : Enter sleep mode
|
function : Enter sleep mode
|
||||||
parameter:
|
parameter:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def sleep(self):
|
def sleep(self):
|
||||||
self.send_command(0x10) #enter deep sleep
|
self.send_command(0x10) # enter deep sleep
|
||||||
self.send_data(0x01)
|
self.send_data(0x01)
|
||||||
|
|
||||||
epdconfig.delay_ms(2000)
|
epdconfig.delay_ms(2000)
|
||||||
epdconfig.module_exit()
|
epdconfig.module_exit()
|
||||||
|
|
||||||
### END OF FILE ###
|
### END OF FILE ###
|
||||||
|
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from . import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 104
|
EPD_WIDTH = 104
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -28,7 +28,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
@ -29,9 +29,8 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 104
|
EPD_WIDTH = 104
|
@ -29,11 +29,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
import PIL
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -29,11 +29,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
import PIL
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 122
|
@ -29,11 +29,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .. import epdconfig
|
from pwnagotchi.ui.hw.libs.waveshare.epaper import epdconfig
|
||||||
|
|
||||||
import PIL
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 168
|
EPD_WIDTH = 168
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user