Compare commits

..

30 Commits

Author SHA1 Message Date
cca3e77d50 Version 2.7.6 2024-01-22 14:25:16 +01:00
4fe603bf5e Small edit to net-pos.py 2024-01-22 12:35:21 +01:00
9a9ee70a78 Fixed wigle plugin 2024-01-22 12:06:20 +01:00
7fc8838f76 2.7.5 2024-01-21 11:43:58 +01:00
94b2ff7047 2.7.5 2024-01-21 11:40:27 +01:00
8edb0fdaa4 2.7.5 2024-01-21 11:33:22 +01:00
b557768159 Fix gdrivesync.py 2024-01-21 11:32:39 +01:00
5a6967eb4d Fix gdrivesync.py 2024-01-21 11:14:17 +01:00
c0c35231cf Fix gdrivesync.py 2024-01-21 11:13:51 +01:00
88362b3354 Version 2.7.4 2024-01-21 00:00:45 +01:00
e50cf04967 Moved self._display = None to base.py for easier debugging display files.
Fixed waveshare2in13g.py
2024-01-20 23:54:32 +01:00
85a64a3914 Merge pull request #23 from Opalinus/master
Repair broken Waveshare213g #22
2024-01-20 23:27:02 +01:00
63d0c20a3e Repair broken Waveshare213g 2024-01-20 20:16:01 +01:00
044639a6d4 Fix 2.7V2 display 2024-01-20 10:23:50 +01:00
7fc2c6b25f Update README.md 2024-01-19 12:25:08 +01:00
c5d5d9bb14 Changed Makefile 2024-01-19 09:04:08 +01:00
129ae92447 Version 2.7.3 2024-01-19 08:51:56 +01:00
2560692ee2 Fixed a mistake on display loading 2024-01-19 08:50:16 +01:00
1424e0d510 Added display waveshare2in66b 2024-01-19 08:43:00 +01:00
2c9eaa436a Added display waveshare2in13g 2024-01-19 08:34:41 +01:00
0c5c6058a5 Added display waveshare2in13g 2024-01-19 07:28:31 +01:00
a3fb39d78c Update README.md 2024-01-18 23:36:25 +01:00
bac62bc4aa Fix for pwnlib 2024-01-17 23:17:48 +01:00
f7a5f2a554 Update build 2024-01-17 21:55:27 +01:00
6921fd14a3 Update Makefile 2024-01-17 20:46:03 +01:00
0dbd611ed5 zramswap 2024-01-17 20:42:28 +01:00
18b9093f70 Version 2.7.2 2024-01-17 20:11:38 +01:00
26913016b9 Changed from dphys-swapfile to zram-tools
Fix on auto-update.py
2024-01-17 19:55:07 +01:00
0786b6757e Changed from dphys-swapfile to zram-tools
Fix on auto-update.py
2024-01-17 19:53:36 +01:00
0f4eda8039 Changed from ext4 to f2fs
Changed from dphys-swapfile to zram-tools
Fix on auto-update.py
2024-01-17 19:51:38 +01:00
94 changed files with 707 additions and 585 deletions

3
.idea/misc.xml generated
View File

@ -4,4 +4,7 @@
<option name="sdkName" value="Python 3.11 (pwnagotchi)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pwnagotchi-torch-bookworm)" project-jdk-type="Python SDK" />
<component name="PythonCompatibilityInspectionAdvertiser">
<option name="version" value="3" />
</component>
</project>

View File

@ -11,7 +11,7 @@ Select Credentials from the left menu, click Create Credentials, sel
Now, the product name and consent screen need to be set -> click Configure consent screen and follow the instructions. Once finished:
Select Application type to be Desktop application.
Select Application type to be Web application.
Enter an appropriate name.
@ -19,7 +19,7 @@ Input http://localhost/ for Authorized redirect URIs.
Select the correct oauth scope:
- drive
- drive.file
- drive.install
Click Create.

View File

@ -7,7 +7,7 @@ It seems the Pi 5 is unable to run in monitor mode, will keep you updated on thi
If you are using an older 32-bit version Raspberry Pi, ZeroWH, use this [fork](https://github.com/jayofelony/pwnagotchi-torch/releases/tag/v2.6.4) and make sure you download the `armhf` version.
---
Download latest image file [here](https://github.com/jayofelony/pwnagotchi-bookworm/releases/tag/v2.6.7), and let it auto-update from here on out.
Download latest image file [here](https://github.com/jayofelony/pwnagotchi-bookworm/releases/tag/v2.7.3), and let it auto-update from here on out.
**Use RPi imager to flash, please don't flash a new user as this will mess with logs created.**

View File

@ -157,7 +157,7 @@ def pwnagotchi_cli():
sys.exit(0)
if args.donate:
print("Donations can made @ https://www.patreon.com/pwnagotchi_torch \n\nBut only if you really want to!")
print("Donations can made @ https://github.com/sponsors/jayofelony \n\nBut only if you really want to!")
sys.exit(0)
if args.check_update:

View File

@ -0,0 +1,15 @@
# Specifies amount of zram devices to create.
# By default, zramswap-start will use all available cores.
#CORES=1
# Specifies the amount of RAM that should be used for zram
# based on a percentage the total amount of available memory
PERCENTAGE=60
# Specifies a static amount of RAM that should be used for
# the ZRAM devices, this is in MiB
#ALLOCATION=256
# Specifies the priority for the swap devices, see swapon(2)
# for more details.
#PRIORITY=100

View File

@ -1,26 +0,0 @@
# /etc/dphys-swapfile - user settings for dphys-swapfile package
# author Neil Franklin, last modification 2010.05.05
# copyright ETH Zuerich Physics Departement
# use under either modified/non-advertising BSD or GPL license
# this file is sourced with . so full normal sh syntax applies
# the default settings are added as commented out CONF_*=* lines
# where we want the swapfile to be, this is the default
#CONF_SWAPFILE=/var/swap
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
CONF_SWAPSIZE=2048
# set size to computed value, this times RAM size, dynamically adapts,
# guarantees that there is enough swap without wasting disk space on excess
#CONF_SWAPFACTOR=2
# restrict size (computed and absolute!) to maximally this limit
# can be set to empty for no limit, but beware of filled partitions!
# this is/was a (outdated?) 32bit kernel limit (in MBytes), do not overrun it
# but is also sensible on 64bit to prevent filling /var or even / partition
#CONF_MAXSWAP=2048

View File

@ -39,8 +39,10 @@ reload_brcm() {
start_monitor_interface() {
rfkill unblock all
ifconfig wlan0 up
sleep 3
iw dev wlan0 set power_save off
iw phy "$(iw phy | head -1 | cut -d" " -f2)" interface add wlan0mon type monitor
sleep 2
rfkill unblock all
ifconfig wlan0 down
ifconfig wlan0mon up
@ -54,7 +56,7 @@ stop_monitor_interface() {
ifconfig wlan0 up
}
# returns 0 if the specificed network interface is up
# returns 0 if the specified network interface is up
is_interface_up() {
if grep -qi 'up' /sys/class/net/"$1"/operstate; then
return 0

View File

@ -23,21 +23,17 @@
services:
enable:
- bettercap.service
- dphys-swapfile.service
- fstrim.timer
- pwnagotchi.service
- pwngrid-peer.service
- zramswap.service
disable:
- apt-daily-upgrade.service
- apt-daily-upgrade.timer
- apt-daily.service
- apt-daily.timer
- avahi-daemon.service
- avahi-daemon.socket
- bluetooth.service
- ifup@wlan0.service
- triggerhappy.service
- wpa_supplicant.service
packages:
caplets:
source: "https://github.com/jayofelony/caplets.git"
@ -61,6 +57,7 @@
- libpcap0.8-dbg
remove:
- avahi-daemon
- dhpys-swapfile
- nfs-common
- triggerhappy
- wpasupplicant
@ -73,7 +70,6 @@
- build-essential
- curl
- dkms
- dphys-swapfile
- fbi
- flex
- fonts-dejavu
@ -161,17 +157,62 @@
- wl
- xxd
- zlib1g-dev
- zram-tools
environment:
ARCHFLAGS: "-arch aarch64"
QEMU_UNAME: "{{ kernel.full }}"
tasks:
# First we install and remove unnecessary packages
- name: install packages
apt:
name: "{{ packages.apt.install }}"
state: present
update_cache: yes
install_recommends: false
- name: remove unnecessary apt packages
apt:
name: "{{ packages.apt.remove }}"
state: absent
purge: yes
register: removed
# Now we set up /boot/firmware
- name: Create pi user
copy:
dest: /boot/firmware/userconf
content: |
pi:$6$3jNr0GA9KIyt4hmM$efeVIopdMQ8DGgEPCWWlbx3mJJNAYci1lEXGdlky0xPyjqwKNbwTL5SrCcpb4144C4IvzWjn7Iv.QjqmU7iyT/
- name: enable ssh on boot
file:
path: /boot/firmware/ssh
state: touch
- name: adjust /boot/firmware/config.txt
lineinfile:
dest: /boot/firmware/config.txt
insertafter: EOF
line: '{{ item }}'
with_items: "{{ system.boot_options }}"
- name: change root partition
replace:
dest: /boot/firmware/cmdline.txt
backup: no
regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+"
replace: "root=/dev/mmcblk0p2"
- name: configure /boot/firmware/cmdline.txt
lineinfile:
path: /boot/firmware/cmdline.txt
backrefs: True
state: present
backup: no
regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether'
- name: change hostname
lineinfile:
dest: /etc/hostname
@ -189,6 +230,7 @@
state: present
when: hostname.changed
# Now we disable sap and a2dp, we don't use them on rpi
- name: disable sap plugin for bluetooth.service
lineinfile:
dest: /lib/systemd/system/bluetooth.service
@ -196,19 +238,6 @@
line: 'ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap,a2dp'
state: present
- name: configure dphys-swapfile
lineinfile:
path: /etc/dphys-swapfile
regexp: "^CONF_SWAPSIZE=.*$"
line: "CONF_SWAPSIZE=2048"
- name: install packages
apt:
name: "{{ packages.apt.install }}"
state: present
update_cache: yes
install_recommends: false
###########################################
#
# libpcap v1.9 - build from source
@ -477,41 +506,6 @@
state: absent
path: /etc/update-motd.d/10-uname
- name: enable ssh on boot
file:
path: /boot/firmware/ssh
state: touch
- name: adjust /boot/config.txt
lineinfile:
dest: /boot/firmware/config.txt
insertafter: EOF
line: '{{ item }}'
with_items: "{{ system.boot_options }}"
- name: adjust /etc/modules
lineinfile:
dest: /etc/modules
insertafter: EOF
line: '{{ item }}'
with_items: "{{ system.modules }}"
- name: change root partition
replace:
dest: /boot/firmware/cmdline.txt
backup: no
regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+"
replace: "root=/dev/mmcblk0p2"
- name: configure /boot/cmdline.txt
lineinfile:
path: /boot/cmdline.txt
backrefs: True
state: present
backup: no
regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether'
- name: Add pwnlog alias
lineinfile:
dest: /home/pi/.bashrc
@ -563,13 +557,6 @@
group: pi
recurse: true
- name: remove unnecessary apt packages
apt:
name: "{{ packages.apt.remove }}"
state: absent
purge: yes
register: removed
- name: clean apt cache
apt:
autoclean: true

View File

@ -1 +1 @@
__version__ = '2.7.1'
__version__ = '2.7.6'

View File

@ -59,7 +59,8 @@ def load(config, agent, epoch, from_disk=True):
return a2c
except Exception as e:
logging.exception("[AI] error while starting AI (%s)", e)
logging.info("[AI] Error while starting AI")
logging.debug("[AI] error while starting AI (%s)", e)
logging.info("[AI] Deleting brain and restarting.")
os.system("rm /root/brain.nn && service pwnagotchi restart")

View File

@ -212,7 +212,7 @@ class AutoUpdate(plugins.Plugin):
if install(display, update):
num_installed += 1
else:
prev_status = '%d new update%c available!' % (num_updates, 's' if num_updates > 1 else '')
prev_status = '%d new update%s available!' % (num_updates, 's' if num_updates > 1 else '')
logging.info("[update] done")

View File

@ -21,9 +21,6 @@ class FixServices(plugins.Plugin):
__help__ = """
Reload brcmfmac module when blindbug is detected, instead of rebooting. Adapted from WATCHDOG.
"""
__dependencies__ = {
'pip': ['scapy']
}
__defaults__ = {
'enabled': True,
}
@ -46,8 +43,7 @@ class FixServices(plugins.Plugin):
logging.info("[Fix_Services] plugin loaded.")
def on_ready(self, agent):
last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10', '-k'],
stdout=subprocess.PIPE).stdout))[-10:])
last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10)
try:
cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True)
logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
@ -99,14 +95,23 @@ class FixServices(plugins.Plugin):
logging.error("[Fix_Services]SYSLOG wifi.recon flip fail: %s" % err)
self._tryTurningItOffAndOnAgain(agent)
def get_last_lines(self, command, args, n):
try:
process = subprocess.Popen([command] + args, stdout=subprocess.PIPE)
output = TextIOWrapper(process.stdout)
lines = output.readlines()
last_n_lines = ''.join(lines[-n:])
return last_n_lines
except Exception as e:
print(f"Error occurred: {e}")
return None
def on_epoch(self, agent, epoch, epoch_data):
last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10', '-k'],
stdout=subprocess.PIPE).stdout))[-10:])
other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10'],
stdout=subprocess.PIPE).stdout))[-10:])
other_other_last_lines = ''.join(
list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/home/pi/logs/pwnagotchi.log'],
stdout=subprocess.PIPE).stdout))[-10:])
last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10)
other_last_lines = self.get_last_lines('journalctl', ['-n10'], 10)
other_other_last_lines = self.get_last_lines('tail', ['-n10', '/home/pi/logs/pwnagotchi.log'], 10)
# don't check if we ran a reset recently
logging.debug("[Fix_Services]**** epoch")
if time.time() - self.LASTTRY > 180:

View File

@ -14,19 +14,15 @@ import zipfile
class GdriveSync(plugins.Plugin):
__author__ = '@jayofelony'
__version__ = '1.0'
__version__ = '1.2'
__license__ = 'GPL3'
__description__ = 'A plugin to backup various pwnagotchi files and folders to Google Drive. Once every hour from loading plugin.'
__dependencies__ = {
'pip': ['pydrive2']
}
def __init__(self):
self.options = dict()
self.lock = Lock()
self.internet = False
self.ready = False
self.drive = None
self.status = StatusFile('/root/.gdrive-backup')
self.backup = True
self.backupfiles = [
@ -38,12 +34,11 @@ class GdriveSync(plugins.Plugin):
'/etc/pwnagotchi'
]
def on_loaded(self, agent):
def on_loaded(self):
"""
Called when the plugin is loaded
"""
# client_secrets.json needs to be not empty
display = agent.view()
if os.stat("/root/client_secrets.json").st_size == 0:
logging.error("[gDriveSync] /root/client_secrets.json is empty. Please RTFM!")
return
@ -78,25 +73,24 @@ class GdriveSync(plugins.Plugin):
# logging.warning(f"[gDriveSync] No files found in the folder with ID {root_file_list} and {pwnagotchi_file_list}")
if self.options['backupfiles'] is not None:
self.backupfiles = self.backupfiles + self.options['backupfiles']
self.backup_files(self.backupfiles, '/backup')
self.backup_files(self.backupfiles, '/home/pi/backup')
# Create a zip archive of the /backup folder
zip_file_path = os.path.join('/home/pi', 'backup.zip')
with zipfile.ZipFile(zip_file_path, 'w') as zip_ref:
for root, dirs, files in os.walk('/backup'):
for root, dirs, files in os.walk('/home/pi/backup'):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, '/backup')
arcname = os.path.relpath(file_path, '/home/pi/backup')
zip_ref.write(file_path, arcname=arcname)
# Upload the zip archive to Google Drive
self.upload_to_gdrive(zip_file_path, self.get_folder_id_by_name(self.drive, self.options['backup_folder']))
display.on_uploading("Google Drive")
self.backup = True
self.status.update()
# Specify the local backup path
local_backup_path = '/'
local_backup_path = '/home/pi/'
# Download the zip archive from Google Drive
zip_file_id = self.get_latest_backup_file_id(self.options['backup_folder'])
@ -104,7 +98,6 @@ class GdriveSync(plugins.Plugin):
zip_file = self.drive.CreateFile({'id': zip_file_id})
zip_file.GetContentFile(os.path.join(local_backup_path, 'backup.zip'))
display.on_downloading("Google Drive")
logging.info("[gDriveSync] Downloaded backup.zip from Google Drive")
# Extract the zip archive to the root directory
@ -112,9 +105,12 @@ class GdriveSync(plugins.Plugin):
zip_ref.extractall('/')
self.status.update()
os.remove("/backup")
# Reboot so we can start opwngrid with the backup id
pwnagotchi.reboot()
shutil.rmtree("/home/pi/backup")
os.remove("/home/pi/backup.zip")
self.ready = True
logging.info("[gdrivesync] loaded")
# Restart so we can start opwngrid with the backup id
pwnagotchi.restart("AUTO")
# all set, gdriveSync is ready to run
self.ready = True
@ -186,15 +182,15 @@ class GdriveSync(plugins.Plugin):
logging.info("[gdrivesync] new handshake captured, backing up to gdrive")
if self.options['backupfiles'] is not None:
self.backupfiles = self.backupfiles + self.options['backupfiles']
self.backup_files(self.backupfiles, '/backup')
self.backup_files(self.backupfiles, '/home/pi/backup')
# Create a zip archive of the /backup folder
zip_file_path = os.path.join('/home/pi', 'backup.zip')
with zipfile.ZipFile(zip_file_path, 'w') as zip_ref:
for root, dirs, files in os.walk('/backup'):
for root, dirs, files in os.walk('/home/pi/backup'):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, '/backup')
arcname = os.path.relpath(file_path, '/home/pi/backup')
zip_ref.write(file_path, arcname=arcname)
# Upload the zip archive to Google Drive
@ -203,7 +199,7 @@ class GdriveSync(plugins.Plugin):
# Cleanup the local zip file
os.remove(zip_file_path)
os.remove("/backup")
shutil.rmtree("/home/pi/backup")
self.status.update()
display = agent.view()
display.update(force=True, new_data={'Backing up to gdrive ...'})

View File

@ -24,6 +24,7 @@ class NetPos(plugins.Plugin):
self.skip = list()
self.ready = False
self.lock = threading.Lock()
self.options = dict()
def on_loaded(self):
if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):
@ -116,6 +117,7 @@ class NetPos(plugins.Plugin):
except OSError as os_e:
logging.error("NET-POS: %s", os_e)
def _get_netpos(self, agent):
aps = agent.get_access_points()
netpos = dict()

View File

@ -1,14 +1,20 @@
# Based on UPS Lite v1.1 from https://github.com/xenDE
# Made specifically to address the problems caused by the hardware changes in 1.3. Oh yeah I also removed the auto-shutdown feature because it's kind of broken.
#
# functions for get UPS status - needs enable "i2c" in raspi-config
# To setup, see page six of this manual to see how to enable i2c:
# https://github.com/linshuqin329/UPS-Lite/blob/master/UPS-Lite_V1.3_CW2015/Instructions%20for%20UPS-Lite%20V1.3.pdf
#
# https://github.com/linshuqin329/UPS-Lite
# Follow page seven, install the dependencies (python-smbus) and copy this script over for later use:
# https://github.com/linshuqin329/UPS-Lite/blob/master/UPS-Lite_V1.3_CW2015/UPS_Lite_V1.3_CW2015.py
#
# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4
# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310
# https://www.aliexpress.com/item/32888533624.html
# Now, install this plugin by copying this to the 'available-plugins' folder in your pwnagotchi, install and enable the plugin with the commands:
# sudo pwnagotchi plugins install upslite_plugin_1_3
# sudo pwnagotchi plugins enable upslite_plugin_1_3
#
# To display external power supply status you need to bridge the necessary pins on the UPS-Lite board. See instructions in the UPS-Lite repo.
# Now restart raspberry pi. Once back up ensure upslite_plugin_1_3 plugin is turned on in the WebUI. If there is still '0%' on your battery meter
# run the script we saved earlier and ensure that the pwnagotchi is plugged in both at the battery and the raspberry pi. The script should start trying to
# read the battery, and should be successful once there's a USB cable running power to the battery supply.
import logging
import struct
@ -20,6 +26,11 @@ import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
CW2015_ADDRESS = 0X62
CW2015_REG_VCELL = 0X02
CW2015_REG_SOC = 0X04
CW2015_REG_MODE = 0X0A
# TODO: add enable switch in config.yml an cleanup all to the best place
class UPS:
@ -31,8 +42,7 @@ class UPS:
def voltage(self):
try:
address = 0x36
read = self._bus.read_word_data(address, 2)
read = self._bus.read_word_data(CW2015_ADDRESS, CW2015_REG_VCELL)
swapped = struct.unpack("<H", struct.pack(">H", read))[0]
return swapped * 1.25 / 1000 / 16
except:
@ -41,7 +51,7 @@ class UPS:
def capacity(self):
try:
address = 0x36
read = self._bus.read_word_data(address, 4)
read = self._bus.read_word_data(CW2015_ADDRESS, CW2015_REG_SOC)
swapped = struct.unpack("<H", struct.pack(">H", read))[0]
return swapped / 256
except:
@ -57,10 +67,10 @@ class UPS:
class UPSLite(plugins.Plugin):
__author__ = 'evilsocket@gmail.com'
__version__ = '1.0.0'
__author__ = 'marbasec'
__version__ = '1.3.0'
__license__ = 'GPL3'
__description__ = 'A plugin that will add a voltage indicator for the UPS Lite v1.1'
__description__ = 'A plugin that will add a voltage indicator for the UPS Lite v1.3'
def __init__(self):
self.ups = None
@ -69,7 +79,7 @@ class UPSLite(plugins.Plugin):
self.ups = UPS()
def on_ui_setup(self, ui):
ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 + 15, 0),
ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%', position=(ui.width() / 2 + 15, 0),
label_font=fonts.Bold, text_font=fonts.Medium))
def on_unload(self, ui):
@ -80,7 +90,3 @@ class UPSLite(plugins.Plugin):
capacity = self.ups.capacity()
charging = self.ups.charging()
ui.set('ups', "%2i%s" % (capacity, charging))
if capacity <= self.options['shutdown']:
logging.info('[ups_lite] Empty battery (<= %s%%): shuting down' % self.options['shutdown'])
ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'})
pwnagotchi.shutdown()

View File

@ -3,6 +3,7 @@ import logging
import json
import csv
import requests
import pwnagotchi
from io import StringIO
from datetime import datetime
@ -24,7 +25,11 @@ def _extract_gps_data(path):
with open(path, 'r') as json_file:
tempJson = json.load(json_file)
d = datetime.utcfromtimestamp(int(tempJson["ts"]))
return {"Latitude": tempJson["location"]["lat"], "Longitude": tempJson["location"]["lng"], "Altitude": 10, "Updated": d.strftime('%Y-%m-%dT%H:%M:%S.%f')}
return {"Latitude": tempJson["location"]["lat"],
"Longitude": tempJson["location"]["lng"],
"Altitude": 10,
"Accuracy": tempJson["accuracy"],
"Updated": d.strftime('%Y-%m-%dT%H:%M:%S.%f')}
else:
with open(path, 'r') as json_file:
return json.load(json_file)
@ -38,7 +43,7 @@ def _format_auth(data):
out = ""
for auth in data:
out = f"{out}[{auth}]"
return out
return [f"{auth}" for auth in data]
def _transform_wigle_entry(gps_data, pcap_data, plugin_version):
@ -47,10 +52,10 @@ def _transform_wigle_entry(gps_data, pcap_data, plugin_version):
"""
dummy = StringIO()
# write kismet header
dummy.write(
"WigleWifi-1.4,appRelease={},model=pwnagotchi,release={},device=pwnagotchi,display=kismet,board=kismet,brand=pwnagotchi\n".format(plugin_version, __pwnagotchi_version__))
dummy.write(
"MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type")
dummy.write(f"WigleWifi-1.4,appRelease={plugin_version},model=pwnagotchi,release={__pwnagotchi_version__},"
f"device={pwnagotchi.name()},display=kismet,board=RaspberryPi,brand=pwnagotchi\n")
dummy.write("MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,"
"CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n")
writer = csv.writer(dummy, delimiter=",", quoting=csv.QUOTE_NONE, escapechar="\\")
writer.writerow([
@ -64,7 +69,7 @@ def _transform_wigle_entry(gps_data, pcap_data, plugin_version):
gps_data['Latitude'],
gps_data['Longitude'],
gps_data['Altitude'],
0, # accuracy?
gps_data['Accuracy'],
'WIFI'])
return dummy.getvalue()
@ -84,7 +89,7 @@ def _send_to_wigle(lines, api_key, donate=True, timeout=30):
headers = {'Authorization': f"Basic {api_key}",
'Accept': 'application/json'}
data = {'donate': 'on' if donate else 'false'}
payload = {'file': dummy, 'type': 'text/csv'}
payload = {'file': (pwnagotchi.name()+".csv", dummy), 'type': 'multipart/form-data'}
try:
res = requests.post('https://api.wigle.net/api/v2/file/upload',
data=data,
@ -99,8 +104,8 @@ def _send_to_wigle(lines, api_key, donate=True, timeout=30):
class Wigle(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '2.0.0'
__author__ = 'Dadav and fixed by Jayofelony'
__version__ = '3.0.0'
__license__ = 'GPL3'
__description__ = 'This plugin automatically uploads collected wifis to wigle.net'
@ -109,6 +114,7 @@ class Wigle(plugins.Plugin):
self.report = StatusFile('/root/.wigle_uploads', data_format='json')
self.skip = list()
self.lock = Lock()
self.options = dict()
def on_loaded(self):
if 'api_key' not in self.options or ('api_key' in self.options and self.options['api_key'] is None):

View File

@ -103,8 +103,8 @@ class Display(View):
def is_waveshare2in13d(self):
return self._implementation.name == 'waveshare2in13d'
def is_waveshare2in23g(self):
return self._implementation.name == 'waveshare2in23g'
def is_waveshare2in13g(self):
return self._implementation.name == 'waveshare2in13g'
def is_waveshare2in36g(self):
return self._implementation.name == 'waveshare2in36g'
@ -112,6 +112,9 @@ class Display(View):
def is_waveshare2in66(self):
return self._implementation.name == 'waveshare2in66'
def is_waveshare2in66b(self):
return self._implementation.name == 'waveshare2in66b'
def is_waveshare2in66g(self):
return self._implementation.name == 'waveshare2in66g'

View File

@ -16,6 +16,7 @@ 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
@ -33,9 +34,10 @@ 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.waveshare2in23g import Waveshare2in23g
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
@ -82,6 +84,21 @@ def display_for(config):
elif config['ui']['display']['type'] == 'dfrobot_2':
return DFRobotV2(config)
elif config['ui']['display']['type'] == 'waveshare144lcd':
return Waveshare144lcd(config)
elif config['ui']['display']['type'] == 'waveshare35lcd':
return Waveshare35lcd(config)
elif config['ui']['display']['type'] == 'spotpear24inch':
return Spotpear24inch(config)
elif config['ui']['display']['type'] == 'displayhatmini':
return DisplayHatMini(config)
elif config['ui']['display']['type'] == 'waveshare1in02':
return Waveshare1in02(config)
elif config['ui']['display']['type'] == 'waveshare1in54':
return Waveshare154(config)
@ -94,12 +111,36 @@ def display_for(config):
elif config['ui']['display']['type'] == 'waveshare1in54b_v2':
return Waveshare154bV2(config)
elif config['ui']['display']['type'] == 'waveshare1in54c':
return Waveshare1in54c(config)
elif config['ui']['display']['type'] == 'waveshare1in64g':
return Waveshare1in64g(config)
elif config['ui']['display']['type'] == 'waveshare2in7':
return Waveshare27inch(config)
elif config['ui']['display']['type'] == 'waveshare2in7_v2':
return Waveshare27inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in7b':
return Waveshare27b(config)
elif config['ui']['display']['type'] == 'waveshare2in7b_v2':
return Waveshare27bV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9':
return Waveshare29inch(config)
elif config['ui']['display']['type'] == 'waveshare2in9bc':
return Waveshare2in9bc(config)
elif config['ui']['display']['type'] == 'waveshare2in9d':
return Waveshare2in9d(config)
elif config['ui']['display']['type'] == 'waveshare2in9_v2':
return Waveshare29inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9b_v3':
return Waveshare29bV3(config)
@ -118,137 +159,101 @@ def display_for(config):
elif config['ui']['display']['type'] == 'waveshare_4':
return WaveshareV4(config)
elif config['ui']['display']['type'] == 'waveshare2in7':
return Waveshare27inch(config)
elif config['ui']['display']['type'] == 'waveshare2in7_v2':
return Waveshare27inchV2(config)
elif config['ui']['display']['type'] == 'waveshare2in9':
return Waveshare29inch(config)
elif config['ui']['display']['type'] == 'waveshare2in9_v2':
return Waveshare29inchV2(config)
elif config['ui']['display']['type'] == 'waveshare144lcd':
return Waveshare144lcd(config)
elif config['ui']['display']['type'] == 'waveshare1in54b':
return Waveshare154inchb(config)
elif config['ui']['display']['type'] == 'waveshare2in13bc':
return Waveshare213bc(config)
elif config['ui']['display']['type'] == 'waveshare2in13d':
return Waveshare213d(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
return Waveshare2in13bV3(config)
elif config['ui']['display']['type'] == 'waveshare2in13b_v4':
return Waveshare213bV4(config)
elif config['ui']['display']['type'] == 'waveshare35lcd':
return Waveshare35lcd(config)
elif config['ui']['display']['type'] == 'spotpear24inch':
return Spotpear24inch(config)
elif config['ui']['display']['type'] == 'displayhatmini':
return DisplayHatMini(config)
elif config['ui']['display']['type'] == 'waveshare1in54c':
return Waveshare1in54c
elif config['ui']['display']['type'] == 'waveshare1in64g':
return Waveshare1in64g
elif config['ui']['display']['type'] == 'waveshare1in02':
return Waveshare1in02
elif config['ui']['display']['type'] == 'waveshare2in9bc':
return Waveshare2in9bc
elif config['ui']['display']['type'] == 'waveshare2in9d':
return Waveshare2in9d
elif config['ui']['display']['type'] == 'waveshare2in13b_v3':
return Waveshare2in13bV3
elif config['ui']['display']['type'] == 'waveshare2in23g':
return Waveshare2in23g
elif config['ui']['display']['type'] == 'waveshare2in13g':
return Waveshare2in13g(config)
elif config['ui']['display']['type'] == 'waveshare2in36g':
return Waveshare2in36g
return Waveshare2in36g(config)
elif config['ui']['display']['type'] == 'waveshare2in66':
return Waveshare2in66
return Waveshare2in66(config)
elif config['ui']['display']['type'] == 'waveshare2in66b':
return Waveshare2in66b(config)
elif config['ui']['display']['type'] == 'waveshare2in66g':
return Waveshare2in66g(config)
elif config['ui']['display']['type'] == 'waveshare3in0g':
return Waveshare3in0g
return Waveshare3in0g(config)
elif config['ui']['display']['type'] == 'waveshare3in7':
return Waveshare3in7
return Waveshare3in7(config)
elif config['ui']['display']['type'] == 'waveshare3in52':
return Waveshare3in52
return Waveshare3in52(config)
elif config['ui']['display']['type'] == 'waveshare4in01f':
return Waveshare4in01f
return Waveshare4in01f(config)
elif config['ui']['display']['type'] == 'waveshare4in2':
return Waveshare4in2
return Waveshare4in2(config)
elif config['ui']['display']['type'] == 'waveshare4in2_v2':
return Waveshare4in2V2
return Waveshare4in2V2(config)
elif config['ui']['display']['type'] == 'waveshare4in2b_v2':
return Waveshare4in2bV2
return Waveshare4in2bV2(config)
elif config['ui']['display']['type'] == 'waveshare4in2bc':
return Waveshare4in2bc
return Waveshare4in2bc(config)
elif config['ui']['display']['type'] == 'waveshare4in26':
return Waveshare4in26
return Waveshare4in26(config)
elif config['ui']['display']['type'] == 'waveshare4in37g':
return Waveshare4in37g
return Waveshare4in37g(config)
elif config['ui']['display']['type'] == 'waveshare5in65f':
return Waveshare5in65f
return Waveshare5in65f(config)
elif config['ui']['display']['type'] == 'waveshare5in83':
return Waveshare5in83
return Waveshare5in83(config)
elif config['ui']['display']['type'] == 'waveshare5in83_v2':
return Waveshare5in83V2
return Waveshare5in83V2(config)
elif config['ui']['display']['type'] == 'waveshare5in83b_v2':
return Waveshare5in83bV2
return Waveshare5in83bV2(config)
elif config['ui']['display']['type'] == 'waveshare5in83bc':
return Waveshare5in83bc
return Waveshare5in83bc(config)
elif config['ui']['display']['type'] == 'waveshare7in3f':
return Waveshare7in3f
return Waveshare7in3f(config)
elif config['ui']['display']['type'] == 'waveshare7in3g':
return Waveshare7in3g
return Waveshare7in3g(config)
elif config['ui']['display']['type'] == 'waveshare7in5':
return Waveshare7in5
return Waveshare7in5(config)
elif config['ui']['display']['type'] == 'waveshare7in5_HD':
return Waveshare7in5HD
return Waveshare7in5HD(config)
elif config['ui']['display']['type'] == 'waveshare7in5_v2':
return Waveshare7in5V2
return Waveshare7in5V2(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_HD':
return Waveshare7in5bHD
return Waveshare7in5bHD(config)
elif config['ui']['display']['type'] == 'waveshare7in5b_v2':
return Waveshare7in5bV2
return Waveshare7in5bV2(config)
elif config['ui']['display']['type'] == 'waveshare7in5bc':
return Waveshare7in5bc
return Waveshare7in5bc(config)
elif config['ui']['display']['type'] == 'waveshare13in3k':
return Waveshare13in3k
return Waveshare13in3k(config)

View File

@ -3,6 +3,7 @@ import pwnagotchi.ui.fonts as fonts
class DisplayImpl(object):
def __init__(self, config, name):
self._display = None
if fonts.Medium is None:
fonts.init(config)
self.name = name

View File

@ -3,41 +3,41 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobotV1(DisplayImpl):
def __init__(self, config):
super(DFRobotV1, self).__init__(config, 'dfrobot_1')
self._display = None
def __init__(self, config):
super(DFRobotV1, self).__init__(config, 'dfrobot_1')
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 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 dfrobot1 display")
from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot
self._display = DFRobot()
def initialize(self):
logging.info("initializing dfrobot1 display")
from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear(0xFF)
def clear(self):
self._display.Clear(0xFF)

View File

@ -3,41 +3,41 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobotV1(DisplayImpl):
def __init__(self, config):
super(DFRobotV1, self).__init__(config, 'dfrobot_1')
self._display = None
def __init__(self, config):
super(DFRobotV1, self).__init__(config, 'dfrobot_1')
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 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 dfrobot1 display")
from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot
self._display = DFRobot()
def initialize(self):
logging.info("initializing dfrobot1 display")
from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear(0xFF)
def clear(self):
self._display.Clear(0xFF)

View File

@ -3,41 +3,41 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobotV2(DisplayImpl):
def __init__(self, config):
super(DFRobotV2, self).__init__(config, 'dfrobot_2')
self._display = None
def __init__(self, config):
super(DFRobotV2, self).__init__(config, 'dfrobot_2')
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 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 dfrobot2 display")
from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot
self._display = DFRobot()
def initialize(self):
logging.info("initializing dfrobot2 display")
from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear(0xFF)
def clear(self):
self._display.Clear(0xFF)

View File

@ -3,41 +3,41 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobotV2(DisplayImpl):
def __init__(self, config):
super(DFRobotV2, self).__init__(config, 'dfrobot_2')
self._display = None
def __init__(self, config):
super(DFRobotV2, self).__init__(config, 'dfrobot_2')
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 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 dfrobot2 display")
from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot
self._display = DFRobot()
def initialize(self):
logging.info("initializing dfrobot2 display")
from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear(0xFF)
def clear(self):
self._display.Clear(0xFF)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class DisplayHatMini(DisplayImpl):
def __init__(self, config):
super(DisplayHatMini, self).__init__(config, 'displayhatmini')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Inky(DisplayImpl):
def __init__(self, config):
super(Inky, self).__init__(config, 'inky')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 28, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class LcdHat(DisplayImpl):
def __init__(self, config):
super(LcdHat, self).__init__(config, 'lcdhat')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -91,9 +91,9 @@ class EPD:
def SetWindow(self):
self.send_command(0x61) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(self.Source_BITS / 256)
self.send_data(int(self.Source_BITS / 256))
self.send_data(self.Source_BITS % 256)
self.send_data(self.Gate_BITS / 256)
self.send_data(int(self.Gate_BITS / 256))
self.send_data(self.Gate_BITS % 256)
def TurnOnDisplay(self):
@ -166,20 +166,21 @@ class EPD:
def getbuffer(self, image):
# Create a pallette with the 4 colors supported by the panel
global image_temp
pal_image = Image.new("P", (1, 1))
pal_image.putpalette((0, 0, 0, 255, 255, 255, 255, 255, 0, 255, 0, 0) + (0, 0, 0) * 252)
# Check if we need to rotate the image
imwidth, imheight = image.size
if (imwidth == self.width and imheight == self.height):
if imwidth == self.width and imheight == self.height:
image_temp = image
elif (imwidth == self.height and imheight == self.width):
elif imwidth == self.height and imheight == self.width:
image_temp = image.rotate(90, expand=True)
else:
logger.warning(
"Invalid image dimensions: %d x %d, expected %d x %d" % (imwidth, imheight, self.width, self.height))
# Convert the soruce image to the 4 colors, dithering if needed
# Convert the source image to the 4 colors, dithering if needed
image_4color = image_temp.convert("RGB").quantize(palette=pal_image)
buf_4color = bytearray(image_4color.tobytes('raw'))

View File

@ -0,0 +1,189 @@
# *****************************************************************************
# * | File : epd2in66b.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.1
# * | Date : 2022-08-9
# # | Info : python demo
# -----------------------------------------------------------------------------
# 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 logging
from .. import epdconfig
# Display resolution
EPD_WIDTH = 152
EPD_HEIGHT = 296
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
# Hardware reset
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(5)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.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)
def ReadBusy(self):
logger.debug("e-Paper busy")
while (epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(20)
logger.debug("e-Paper busy release")
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x12)
epdconfig.delay_ms(30)
self.ReadBusy()
self.send_command(0x11) # setting gaet number
self.send_data(0x03)
self.setWindows(0, 0, self.width - 1, self.height - 1)
self.send_command(0x21)
self.send_data(0x00)
self.send_data(0x80)
self.setCursor(0, 0)
self.ReadBusy()
return 0
def setWindows(self, Xstart, Ystart, Xend, Yend):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
self.send_data((Xstart >> 3) & 0x1F)
self.send_data((Xend >> 3) & 0x1F)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(Ystart & 0xFF)
self.send_data((Ystart >> 8) & 0x01)
self.send_data(Yend & 0xFF)
self.send_data((Yend >> 8) & 0x01)
def setCursor(self, Xstart, Ystart):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
self.send_data(Xstart & 0x1F)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(Ystart & 0xFF)
self.send_data((Ystart >> 8) & 0x01)
def turnon_display(self):
self.send_command(0x20)
self.ReadBusy()
def getbuffer(self, image):
# logger.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logger.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if (imwidth == self.width and imheight == self.height):
logger.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif (imwidth == self.height and imheight == self.width):
logger.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, Blackimage, Redimage):
if (Blackimage == None or Redimage == None):
return
Redimage_1 = [0x00] * len(Redimage)
for i in range(len(Redimage)):
Redimage_1[i] = ~Redimage[i]
self.send_command(0x24)
self.send_data2(Blackimage)
self.send_command(0x26)
self.send_data2(Redimage_1)
self.turnon_display()
def Clear(self):
if self.width % 8 == 0:
linewidth = int(self.width / 8)
else:
linewidth = int(self.width / 8) + 1
self.send_command(0x24)
self.send_data2([0xff] * int(self.height * linewidth))
self.send_command(0x26)
self.send_data2([0x00] * int(self.height * linewidth))
self.turnon_display()
def sleep(self):
self.send_command(0X10) # DEEP_SLEEP_MODE
self.send_data(0x01)
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -100,7 +100,7 @@ class EPD:
def ReadBusy(self):
logger.debug("e-Paper busy")
while (epdconfig.digital_read(self.busy_pin) == 1): # 1: idle, 0: busy
while epdconfig.digital_read(self.busy_pin) == 1: # 1: idle, 0: busy
epdconfig.delay_ms(20)
logger.debug("e-Paper busy release")
@ -134,7 +134,7 @@ class EPD:
self.send_data(self.LUT_DATA_4Gray[i])
def init(self):
if (epdconfig.module_init() != 0):
if epdconfig.module_init() != 0:
return -1
# EPD hardware init start
@ -159,7 +159,7 @@ class EPD:
return 0
def init_Fast(self):
if (epdconfig.module_init() != 0):
if epdconfig.module_init() != 0:
return -1
# EPD hardware init start
@ -204,12 +204,12 @@ class EPD:
return 0
def Init_4Gray(self):
if (epdconfig.module_init() != 0):
if epdconfig.module_init() != 0:
return -1
self.reset()
self.send_command(0x12) # soft reset
self.ReadBusy();
self.ReadBusy()
self.send_command(0x74) # set analog block control
self.send_data(0x54)
@ -268,14 +268,14 @@ class EPD:
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logger.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if (imwidth == self.width and imheight == self.height):
if imwidth == self.width and imheight == self.height:
logger.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif (imwidth == self.height and imheight == self.width):
elif imwidth == self.height and imheight == self.width:
logger.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
@ -293,40 +293,40 @@ class EPD:
pixels = image_monocolor.load()
i = 0
# logger.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if (imwidth == self.width and imheight == self.height):
if imwidth == self.width and imheight == self.height:
logger.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if (pixels[x, y] == 0xC0):
if pixels[x, y] == 0xC0:
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
elif pixels[x, y] == 0x80:
pixels[x, y] = 0x40
i = i + 1
if (i % 4 == 0):
if i % 4 == 0:
buf[int((x + (y * self.width)) / 4)] = (
(pixels[x - 3, y] & 0xc0) | (pixels[x - 2, y] & 0xc0) >> 2 | (
pixels[x - 1, y] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
elif (imwidth == self.height and imheight == self.width):
elif imwidth == self.height and imheight == self.width:
logger.debug("Horizontal")
for x in range(imwidth):
for y in range(imheight):
newx = y
newy = self.height - x - 1
if (pixels[x, y] == 0xC0):
if pixels[x, y] == 0xC0:
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
elif pixels[x, y] == 0x80:
pixels[x, y] = 0x40
i = i + 1
if (i % 4 == 0):
if i % 4 == 0:
buf[int((newx + (newy * self.width)) / 4)] = (
(pixels[x, y - 3] & 0xc0) | (pixels[x, y - 2] & 0xc0) >> 2 | (
pixels[x, y - 1] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
return buf
def Clear(self):
if (self.width % 8 == 0):
if self.width % 8 == 0:
Width = self.width // 8
else:
Width = self.width // 8 + 1
@ -338,7 +338,7 @@ class EPD:
self.TurnOnDisplay()
def display(self, image):
if (self.width % 8 == 0):
if self.width % 8 == 0:
Width = self.width // 8
else:
Width = self.width // 8 + 1
@ -350,7 +350,7 @@ class EPD:
self.TurnOnDisplay()
def display_Fast(self, image):
if (self.width % 8 == 0):
if self.width % 8 == 0:
Width = self.width // 8
else:
Width = self.width // 8 + 1
@ -362,7 +362,7 @@ class EPD:
self.TurnOnDisplay_Fast()
def display_Base(self, image):
if (self.width % 8 == 0):
if self.width % 8 == 0:
Width = self.width // 8
else:
Width = self.width // 8 + 1
@ -379,7 +379,7 @@ class EPD:
self.TurnOnDisplay()
def display_Base_color(self, color):
if (self.width % 8 == 0):
if self.width % 8 == 0:
Width = self.width // 8
else:
Width = self.width // 8 + 1
@ -396,8 +396,7 @@ class EPD:
# self.TurnOnDisplay()
def display_Partial(self, Image, Xstart, Ystart, Xend, Yend):
if ((Xstart % 8 + Xend % 8 == 8 & Xstart % 8 > Xend % 8) | Xstart % 8 + Xend % 8 == 0 | (
Xend - Xstart) % 8 == 0):
if (Xstart % 8 + Xend % 8 == 8 & Xstart % 8 > Xend % 8) | Xstart % 8 + Xend % 8 == 0 | (Xend - Xstart) % 8 == 0:
Xstart = Xstart // 8
Xend = Xend // 8
else:
@ -440,23 +439,23 @@ class EPD:
self.send_command(0x24) # Write Black and White image to RAM
for j in range(Height):
for i in range(Width):
if ((j > Ystart - 1) & (j < (Yend + 1)) & (i > Xstart - 1) & (i < (Xend + 1))):
if (j > Ystart - 1) & (j < (Yend + 1)) & (i > Xstart - 1) & (i < (Xend + 1)):
self.send_data(Image[i + j * Width])
self.TurnOnDisplay_Partial()
def display_4Gray(self, image):
self.send_command(0x24)
for i in range(0, 48000): # 5808*4 46464
for i in range(0, 5808): # 5808*4 46464
temp3 = 0
for j in range(0, 2):
temp1 = image[i * 2 + j]
for k in range(0, 2):
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
if temp2 == 0xC0:
temp3 |= 0x00
elif (temp2 == 0x00):
elif temp2 == 0x00:
temp3 |= 0x01
elif (temp2 == 0x80):
elif temp2 == 0x80:
temp3 |= 0x01
else: # 0x40
temp3 |= 0x00
@ -464,31 +463,31 @@ class EPD:
temp1 <<= 2
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
if temp2 == 0xC0:
temp3 |= 0x00
elif (temp2 == 0x00):
elif temp2 == 0x00:
temp3 |= 0x01
elif (temp2 == 0x80):
elif temp2 == 0x80:
temp3 |= 0x01
else: # 0x40
temp3 |= 0x00
if (j != 1 or k != 1):
if j != 1 or k != 1:
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
self.send_command(0x26)
for i in range(0, 48000): # 5808*4 46464
for i in range(0, 5808): # 5808*4 46464
temp3 = 0
for j in range(0, 2):
temp1 = image[i * 2 + j]
for k in range(0, 2):
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
if temp2 == 0xC0:
temp3 |= 0x00
elif (temp2 == 0x00):
elif temp2 == 0x00:
temp3 |= 0x01
elif (temp2 == 0x80):
elif temp2 == 0x80:
temp3 |= 0x00
else: # 0x40
temp3 |= 0x01
@ -496,15 +495,15 @@ class EPD:
temp1 <<= 2
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
if temp2 == 0xC0:
temp3 |= 0x00
elif (temp2 == 0x00):
elif temp2 == 0x00:
temp3 |= 0x01
elif (temp2 == 0x80):
elif temp2 == 0x80:
temp3 |= 0x00
else: # 0x40
temp3 |= 0x01
if (j != 1 or k != 1):
if j != 1 or k != 1:
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
@ -517,4 +516,3 @@ class EPD:
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class OledHat(DisplayImpl):
def __init__(self, config):
super(OledHat, self).__init__(config, 'oledhat')
self._display = None
def layout(self):
fonts.setup(8, 8, 8, 10, 10, 8)

View File

@ -8,7 +8,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Papirus(DisplayImpl):
def __init__(self, config):
super(Papirus, self).__init__(config, 'papirus')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 23, 25, 9)

View File

@ -3,12 +3,12 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
import os,time
import time
class Spotpear24inch(DisplayImpl):
def __init__(self, config):
super(Spotpear24inch, self).__init__(config, 'spotpear24inch')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -3,12 +3,12 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
import os,time
import time
class Spotpear24inch(DisplayImpl):
def __init__(self, config):
super(Spotpear24inch, self).__init__(config, 'spotpear24inch')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare13in3k(DisplayImpl):
def __init__(self, config):
super(Waveshare13in3k, self).__init__(config, 'waveshare13in3k')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare144lcd(DisplayImpl):
def __init__(self, config):
super(Waveshare144lcd, self).__init__(config, 'waveshare144lcd')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)
@ -42,5 +41,4 @@ class Waveshare144lcd(DisplayImpl):
self._display.display(canvas)
def clear(self):
pass
#self._display.clear()
self._display.clear()

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare1in02(DisplayImpl):
def __init__(self, config):
super(Waveshare1in02, self).__init__(config, 'waveshare1in02')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare144lcd(DisplayImpl):
def __init__(self, config):
super(Waveshare144lcd, self).__init__(config, 'waveshare144lcd')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare154(DisplayImpl):
def __init__(self, config):
super(Waveshare154, self).__init__(config, 'waveshare1in54')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare154V2(DisplayImpl):
def __init__(self, config):
super(Waveshare154V2, self).__init__(config, 'waveshare1in54_v2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare154inchb(DisplayImpl):
def __init__(self, config):
super(Waveshare154inchb, self).__init__(config, 'waveshare1in54b')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare154bV2(DisplayImpl):
def __init__(self, config):
super(Waveshare154bV2, self).__init__(config, 'waveshare1in54b_v2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare1in54c(DisplayImpl):
def __init__(self, config):
super(Waveshare1in54c, self).__init__(config, 'waveshare1in54c')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare1in64g(DisplayImpl):
def __init__(self, config):
super(Waveshare1in64g, self).__init__(config, 'waveshare1in64g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class WaveshareV1(DisplayImpl):
def __init__(self, config):
super(WaveshareV1, self).__init__(config, 'waveshare_1')
self._display = None
def layout(self):
if self.config['color'] == 'black':

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class WaveshareV2(DisplayImpl):
def __init__(self, config):
super(WaveshareV2, self).__init__(config, 'waveshare_2')
self._display = None
def layout(self):
if self.config['color'] == 'black':

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class WaveshareV3(DisplayImpl):
def __init__(self, config):
super(WaveshareV3, self).__init__(config, 'waveshare_3')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class WaveshareV4(DisplayImpl):
def __init__(self, config):
super(WaveshareV4, self).__init__(config, 'waveshare_4')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -8,7 +8,6 @@ from PIL import Image
class Waveshare2in13bV3(DisplayImpl):
def __init__(self, config):
super(Waveshare2in13bV3, self).__init__(config, 'waveshare2in13b_v3')
self._display = None
def layout(self):
if self.config['color'] == 'black':

View File

@ -8,7 +8,6 @@ from PIL import Image
class Waveshare213bV4(DisplayImpl):
def __init__(self, config):
super(Waveshare213bV4, self).__init__(config, 'waveshare213inb_v4')
self._display = None
def layout(self):
if self.config['color'] == 'black':

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare213bc(DisplayImpl):
def __init__(self, config):
super(Waveshare213bc, self).__init__(config, 'waveshare2in13bc')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 25, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare213d(DisplayImpl):
def __init__(self, config):
super(Waveshare213d, self).__init__(config, 'waveshare2in13d')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 25, 25, 9)

View File

@ -0,0 +1,45 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in13g(DisplayImpl):
def __init__(self, config):
super(Waveshare2in13g, self).__init__(config, 'waveshare2in13g')
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 waveshare v2in13g display")
from pwnagotchi.ui.hw.libs.waveshare.v2in13g.epd2in13g import EPD
self._display = EPD()
self._display.init()
self._display.Clear()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear()

View File

@ -1,46 +0,0 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in23g(DisplayImpl):
def __init__(self, config):
super(Waveshare2in23g, self).__init__(config, 'waveshare2in23g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 25, 25, 9)
self._layout['width'] = 122
self._layout['height'] = 250
self._layout['face'] = (0, 26)
self._layout['name'] = (5, 15)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (28, 0)
self._layout['uptime'] = (147, 0)
self._layout['line1'] = [0, 12, 122, 12]
self._layout['line2'] = [0, 92, 122, 92]
self._layout['friend_face'] = (0, 76)
self._layout['friend_name'] = (40, 78)
self._layout['shakes'] = (0, 93)
self._layout['mode'] = (187, 93)
self._layout['status'] = {
'pos': (91, 15),
'font': fonts.status_font(fonts.Medium),
'max': 20
}
return self._layout
def initialize(self):
logging.info("initializing waveshare 2.23g inch display")
from pwnagotchi.ui.hw.libs.waveshare.v2in23g.epd2in13g import EPD
self._display = EPD()
self._display.init()
self._display.Clear()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear()

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in36g(DisplayImpl):
def __init__(self, config):
super(Waveshare2in36g, self).__init__(config, 'waveshare2in36g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in66(DisplayImpl):
def __init__(self, config):
super(Waveshare2in66, self).__init__(config, 'waveshare2in66')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -0,0 +1,45 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in66b(DisplayImpl):
def __init__(self, config):
super(Waveshare2in66b, self).__init__(config, 'waveshare2in66b')
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)
self._layout['width'] = 152
self._layout['height'] = 296
self._layout['face'] = (0, 43)
self._layout['name'] = (0, 14)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (0, 71)
self._layout['uptime'] = (0, 25)
self._layout['line1'] = [0, 12, 152, 12]
self._layout['line2'] = [0, 116, 152, 116]
self._layout['friend_face'] = (12, 88)
self._layout['friend_name'] = (1, 103)
self._layout['shakes'] = (26, 117)
self._layout['mode'] = (0, 117)
self._layout['status'] = {
'pos': (65, 26),
'font': fonts.status_font(fonts.Small),
'max': 12
}
return self._layout
def initialize(self):
logging.info("initializing waveshare 2.66b inch lcd display")
from pwnagotchi.ui.hw.libs.waveshare.v2in66b.epd2in66b import EPD
self._display = EPD()
self._display.init()
self._display.Clear()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self):
self._display.Clear()

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in66g(DisplayImpl):
def __init__(self, config):
super(Waveshare2in66g, self).__init__(config, 'waveshare2in66g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare27inch(DisplayImpl):
def __init__(self, config):
super(Waveshare27inch, self).__init__(config, 'waveshare2in7')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare27inchV2(DisplayImpl):
def __init__(self, config):
super(Waveshare27inchV2, self).__init__(config, 'waveshare2in7_v2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)
@ -42,7 +41,7 @@ class Waveshare27inchV2(DisplayImpl):
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display_Partial(buf,0,0,176,264)
self._display.display_Partial(buf, 0, 0, 176, 264)
def clear(self):
# This line also removes the 0xFF

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare27b(DisplayImpl):
def __init__(self, config):
super(Waveshare27b, self).__init__(config, 'waveshare2in7b')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare27bV2(DisplayImpl):
def __init__(self, config):
super(Waveshare27bV2, self).__init__(config, 'waveshare2in7b_v2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare29inch(DisplayImpl):
def __init__(self, config):
super(Waveshare29inch, self).__init__(config, 'waveshare2in9')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare29inchV2(DisplayImpl):
def __init__(self, config):
super(Waveshare29inchV2, self).__init__(config, 'waveshare2in9_v2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare29bV3(DisplayImpl):
def __init__(self, config):
super(Waveshare29bV3, self).__init__(config, 'waveshare2in9b_v3')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare29bV4(DisplayImpl):
def __init__(self, config):
super(Waveshare29bV4, self).__init__(config, 'waveshare2in9b_v4')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in9bc(DisplayImpl):
def __init__(self, config):
super(Waveshare2in9bc, self).__init__(config, 'waveshare2in9bc')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare2in9d(DisplayImpl):
def __init__(self, config):
super(Waveshare2in9d, self).__init__(config, 'waveshare2in9d')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -9,7 +9,6 @@ import os, time
class Waveshare35lcd(DisplayImpl):
def __init__(self, config):
super(Waveshare35lcd, self).__init__(config, 'waveshare35lcd')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare3in0g(DisplayImpl):
def __init__(self, config):
super(Waveshare3in0g, self).__init__(config, 'waveshare3in0g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare3in52(DisplayImpl):
def __init__(self, config):
super(Waveshare3in52, self).__init__(config, 'waveshare3in52')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -9,7 +9,6 @@ import os, time
class Waveshare35lcd(DisplayImpl):
def __init__(self, config):
super(Waveshare35lcd, self).__init__(config, 'waveshare35lcd')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare3in7(DisplayImpl):
def __init__(self, config):
super(Waveshare3in7, self).__init__(config, 'waveshare3in7')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)
@ -39,7 +38,7 @@ class Waveshare3in7(DisplayImpl):
self._display.Clear(0)
def render(self, canvas):
self._display.display(canvas)
self._display.display_4Gray(canvas)
def clear(self):
self._display.Clear(0)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in01f(DisplayImpl):
def __init__(self, config):
super(Waveshare4in01f, self).__init__(config, 'waveshare4in01f')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in2(DisplayImpl):
def __init__(self, config):
super(Waveshare4in2, self).__init__(config, 'waveshare4in2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in26(DisplayImpl):
def __init__(self, config):
super(Waveshare4in26, self).__init__(config, 'waveshare4in26')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in2V2(DisplayImpl):
def __init__(self, config):
super(Waveshare4in2V2, self).__init__(config, 'waveshare4in2_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in2bV2(DisplayImpl):
def __init__(self, config):
super(Waveshare4in2bV2, self).__init__(config, 'waveshare4in2b_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in2bc(DisplayImpl):
def __init__(self, config):
super(Waveshare4in2bc, self).__init__(config, 'waveshare4in2bc')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare4in37g(DisplayImpl):
def __init__(self, config):
super(Waveshare4in37g, self).__init__(config, 'waveshare4in37g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare5in65f(DisplayImpl):
def __init__(self, config):
super(Waveshare5in65f, self).__init__(config, 'waveshare5in65f')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare5in83(DisplayImpl):
def __init__(self, config):
super(Waveshare5in83, self).__init__(config, 'waveshare5in83')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare5in83V2(DisplayImpl):
def __init__(self, config):
super(Waveshare5in83V2, self).__init__(config, 'waveshare5in83_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare5in83bV2(DisplayImpl):
def __init__(self, config):
super(Waveshare5in83bV2, self).__init__(config, 'waveshare5in83b_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare5in83bc(DisplayImpl):
def __init__(self, config):
super(Waveshare5in83bc, self).__init__(config, 'waveshare5in83bc')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in3f(DisplayImpl):
def __init__(self, config):
super(Waveshare7in3f, self).__init__(config, 'waveshare7in3f')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in3g(DisplayImpl):
def __init__(self, config):
super(Waveshare7in3g, self).__init__(config, 'waveshare7in3g')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5, self).__init__(config, 'waveshare7in5')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5HD(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5HD, self).__init__(config, 'waveshare7in5_HD')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5V2(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5V2, self).__init__(config, 'waveshare7in5_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5bHD(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5bHD, self).__init__(config, 'waveshare7in5b_HD')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5bV2(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5bV2, self).__init__(config, 'waveshare7in5b_v2')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -7,7 +7,6 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Waveshare7in5bc(DisplayImpl):
def __init__(self, config):
super(Waveshare7in5bc, self).__init__(config, 'waveshare7in5bc')
self._display = None
def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9)

View File

@ -306,6 +306,9 @@ def load_config(args):
elif config['ui']['display']['type'] in ('ws_213d', 'ws213d', 'waveshare2in13d', 'waveshare_213d', 'waveshare213d'):
config['ui']['display']['type'] = 'waveshare2in13d'
elif config['ui']['display']['type'] in ('ws_213g', 'waveshare2in13g', 'waveshare213g', 'ws213g', 'waveshare_213g'):
config['ui']['display']['type'] = 'waveshare2in13g'
elif config['ui']['display']['type'] in ('ws_213bc', 'ws213bc', 'waveshare2in13bc', 'waveshare_213bc', 'waveshare213bc'):
config['ui']['display']['type'] = 'waveshare2in13bc'
@ -339,15 +342,18 @@ def load_config(args):
elif config['ui']['display']['type'] in 'waveshare2in13b_v3':
config['ui']['display']['type'] = 'waveshare2in13b_v3'
elif config['ui']['display']['type'] in 'waveshare2in23g':
config['ui']['display']['type'] = 'waveshare2in23g'
elif config['ui']['display']['type'] in 'waveshare2in36g':
config['ui']['display']['type'] = 'waveshare2in36g'
elif config['ui']['display']['type'] in 'waveshare2in66':
config['ui']['display']['type'] = 'waveshare2in66'
elif config['ui']['display']['type'] in 'waveshare2in66b':
config['ui']['display']['type'] = 'waveshare2in66b'
elif config['ui']['display']['type'] in 'waveshare2in66g':
config['ui']['display']['type'] = 'waveshare2in66g'
elif config['ui']['display']['type'] in 'waveshare3in0g':
config['ui']['display']['type'] = 'waveshare3in0g'

View File

@ -1,60 +0,0 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "pwnagotchi"
dynamic = ["version"]
dependencies = [
"Pillow",
"PyYAML",
"RPi.GPIO",
"file-read-backwards",
"flask",
"flask-cors",
"flask-wtf",
"gast",
"gym",
"inky",
"pycryptodome",
"pydrive2",
"python-dateutil",
"requests",
"rpi_hardware_pwm",
"scapy",
"shimmy",
"smbus2",
"spidev",
"stable_baselines3",
"toml",
"torch",
"torchvision",
"tweepy",
"websockets"
]
requires-python = ">=3.9"
authors = [
{name = "Evilsocket", email = "evilsocket@gmail.com"},
{name = "Jayofelony", email = "oudshoorn.jeroen@gmail.com"}
]
maintainers = [
{name = "Jayofelony", email = "oudshoorn.jeroen@gmail.com"}
]
description = "(⌐■_■) - Deep Reinforcement Learning instrumenting bettercap for WiFI pwning."
readme = "README.md"
license = {file = "LICENSE.md"}
classifiers = [
'Programming Language :: Python :: 3',
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Environment :: Console',
]
[project.urls]
Homepage = "https://pwnagotchi.ai/"
Documentation = "https://pwnagotchi.ai/"
Repository = "https://github.com/jayofelony/pwnagotchi-bookworm"
"Bug Tracker" = "https://github.com/jayofelony/pwnagotchi-bookworm/issues"
[project.scripts]
pwnagotchi_cli = "bin.pwnagotchi:pwnagotchi_cli"