Project for those who are tired of the same old string faces. This mod allows you to use custom images as pwnagotchi Faces, with transparency feature (.png) and themed plugins.
Starting a collection of custom themes for pwnagotchi. Create your own and send me your pull request!
Name | Without Optional Plugins | With Optional Plugins | Description | Author | Avaliable To |
---|---|---|---|---|---|
A custom theme featuring Rebecca from Cyberpunk Edgerunners | Zerodya | waveshare_v3 | |||
A Fallout Vault Boy inpirated custom face | JD-2006 | 100x100 pixels for larger screens | |||
A 'Hackers' movie inspirated custom theme | cyberspacemanmike | waveshare_v3 | |||
A custom theme featuring Radical Edward from Cowboy Bebop | cyberspacemanmike | waveshare_v3 | |||
A custom theme featuring Holo (ホロ, Horo) from Spice and Wolf | SeverX | waveshare_v3 | |||
A custom theme featuring Hatsune Miku ♥ | SeverX | waveshare_v3 | |||
- | Follow the White Rabbit... | CodyTolene | waveshare_v3, waveshare144lcd | ||
An amazing art by PersephoneKarnstein, was the inspiration for this project, check this out! | PersephoneKarnstein | waveshare_v3 | |||
A custom theme featuring my favorite character | roodriiigooo | waveshare_v3 | |||
A custom theme featuring Fliper Zero's character. Enjoy this crossover! | roodriiigooo | waveshare_v3 | |||
- | Flowey is a fictional character and the main antagonist of Undertale, a role-playing video game created by Toby Fox | roodriiigooo | waveshare_v3 |
Warning From roodriiigooo: The content here is free for use, but it doesn't mean you can use it however you want. No author or contributor assumes responsibility for the misuse of this device, project, or any component herein. The project and modifications were developed solely for educational purposes. Any files, plugins or modifications of this project or original project found here should not be sold. In the case of use in open projects, videos or any form of dissemination, please remember to give credit to the repository ♥
Warning Certain content may be protected by copyright, use with caution.
Some notes...
This tutorial covers two projects, the
evilsocket
's one (original) andJayofelony
's fork..Don't limit yourself to just this article, You may need to adapt according to your specific scenario.
Important: The following steps were performed on a
Windows
computer usingPuTTY
as SSH client,FileZilla
as FTP client and the pwnagotchi with aWaveshare 2.13 V3 e-ink display
running on aRPI0W
.If you will use it in another fork or hardware, please be aware that you might need to adapt what is shown here
If the folder doesn't specify which screen it was tested on, assume the sprites are for the
waveshare_v3
and similar sizes
Anyone can contribute by making a pull request.
Don't limit yourself to just this article, feel free to create your own themes!
This tutorial requires a minimum level of knowledge.
# 1. Original Evilsocket's project
First and foremost, keep in mind that you must meet this requirements:
- A computer;
- The pwnagotchi must already be
v1.5.5
properly configured; - Perform a complete backup before making any modifications, including every file to be modified.
Note If pwnagotchi updates automatically, this mod must be applied again.
First, with the pwnagotchi connected to a computer in MANU
mode, establish an SSH connection.
Login as root:
pi@pwnagotchi:~ $ sudo su
root@pwnagotchi:/home/pi#
root@pwnagotchi:/home/pi# whoami
root
Navigate to root directory:
root@pwnagotchi:/home/pi# cd /
Let's create two folders, one for backing up the files and another one to receive the custom faces:
root@pwnagotchi:/# mkdir files-backup
root@pwnagotchi:/# mkdir custom-faces
Now let's navigate to the folder that contains the files we're going to modify:
root@pwnagotchi:/# cd /usr/local/lib/python3.7/dist-packages/pwnagotchi/ui
Stop the pwnagotchi service
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# systemctl stop pwnagotchi
Here are the following files:
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# ls
components.py faces.py hw __pycache__ view.py
display.py fonts.py __init__.py state.py web
Now run the following command to make a backup of the first file:
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# cp faces.py /files-backup/
Open the file using nano:
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# nano faces.py
Add these attributes to the code, resulting in the following:
...
UPLOAD1 = '(1__1)'
UPLOAD2 = '(0__1)'
PNG = False
POSITION_X = 0
POSITION_Y = 40
def load_from_config(config):
for face_name, face_value in config.items():
globals()[face_name.upper()] = face_value
...
CTRL + O to save, CTRL + X to close file.
Now let's move on to the next file. Backup first, then edit:
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# cp components.py /files-backup/
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# nano components.py
Locate this code snippet:
class Text(Widget):
def __init__(self, value="", position=(0, 0), font=None, color=0, wrap=False, max_length=0):
super().__init__(position, color)
self.value = value
self.font = font
self.wrap = wrap
self.max_length = max_length
self.wrapper = TextWrapper(width=self.max_length, replace_whitespace=False) if wrap else None
def draw(self, canvas, drawer):
if self.value is not None:
if self.wrap:
text = '\n'.join(self.wrapper.wrap(self.value))
else:
text = self.value
drawer.text(self.xy, text, font=self.font, fill=self.color)
Now replace with:
class Text(Widget):
def __init__(self, value="", position=(0, 0), font=None, color=0, wrap=False, max_length=0, png=False):
super().__init__(position, color)
self.value = value
self.font = font
self.wrap = wrap
self.max_length = max_length
self.wrapper = TextWrapper(width=self.max_length, replace_whitespace=False) if wrap else None
self.png = png
def draw(self, canvas, drawer):
if self.value is not None:
if not self.png:
if self.wrap:
text = '\n'.join(self.wrapper.wrap(self.value))
else:
text = self.value
drawer.text(self.xy, text, font=self.font, fill=self.color)
else:
self.image = Image.open(self.value)
self.image = self.image.convert('RGBA')
self.pixels = self.image.load()
for y in range(self.image.size[1]):
for x in range(self.image.size[0]):
if self.pixels[x,y][3] < 255: # check alpha
self.pixels[x,y] = (255, 255, 255, 255)
if self.color == 255:
self._image = ImageOps.colorize(self.image.convert('L'), black = "white", white = "black")
else:
self._image = self.image
self.image = self._image.convert('1')
canvas.paste(self.image, self.xy)
CTRL + O to save, CTRL + X to close file.
Now let's move on to the next file. Once again, backup first and then edit:
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# cp view.py /files-backup/
root@pwnagotchi:/usr/local/lib/python3.7/dist-packages/pwnagotchi/ui# nano view.py
Replace this one:
...
'face': Text(value=faces.SLEEP, position=self._layout['face'], color=BLACK, font=fonts.Huge),
...
With that:
...
'face': Text(value=faces.SLEEP, position=(config['ui']['faces']['position_x'], config['ui']['faces']['position_y']), color=BLACK, font=fonts.Huge, png=config['ui']['faces']['png']),
...
CTRL + O to save, CTRL + X to close file.
From this point on, the pwnagotchi is ready to display images instead of the default string.
From here, we will able configure the images for our custom Faces. So lets do that!
Prepare the files, there are a total of 25
. I use images of size 128x45
. To make it easier, name the files according to the facial expression or emotion:
Default .png file names:
LOOK_R, LOOK_L, LOOK_R_HAPPY, LOOK_L_HAPPY, SLEEP, SLEEP2, AWAKE, BORED, INTENSE, COOL, HAPPY, GRATEFUL, EXCITED, MOTIVATED, DEMOTIVATED, LONELY, SAD, ANGRY, FRIEND, BROKEN, DEBUG, UPLOAD, UPLOAD1, UPLOAD2, ICON, POSITION_X, POSITION_Y
Stop the pwnagotchi service, if its not:
root@pwnagotchi:/# systemctl stop pwnagotchi
Use FileZilla
or any other method you know to upload your images to the /custom-faces/
folder that was created earlier.
Note If you don't have it, use one of my theme packages from here
Open the pwnagotchi's configuration file:
root@pwnagotchi:/# nano /etc/pwnagotchi/config.toml
Locate this code snippet:
...
ui.faces.look_r = "( ⚆_⚆)"
ui.faces.look_l = "(☉_☉ )"
ui.faces.look_r_happy = "( ◕‿◕)"
ui.faces.look_l_happy = "(◕‿◕ )"
ui.faces.sleep = "(⇀‿‿↼)"
ui.faces.sleep2 = "(≖‿‿≖)"
ui.faces.awake = "(◕‿‿◕)"
ui.faces.bored = "(-__-)"
ui.faces.intense = "(°▃▃°)"
ui.faces.cool = "(⌐■_■)"
ui.faces.happy = "(•‿‿•)"
ui.faces.excited = "(ᵔ◡◡ᵔ)"
ui.faces.grateful = "(^‿‿^)"
ui.faces.motivated = "(☼‿‿☼)"
ui.faces.demotivated = "(≖__≖)"
ui.faces.smart = "(✜‿‿✜)"
ui.faces.lonely = "(ب__ب)"
ui.faces.sad = "(╥☁╥ )"
ui.faces.angry = "(-_-')"
ui.faces.friend = "(♥‿‿♥)"
ui.faces.broken = "(☓‿‿☓)"
ui.faces.debug = "(#__#)"
ui.faces.upload = "(1__0)"
ui.faces.upload1 = "(1__1)"
ui.faces.upload2 = "(0__1)"
...
This snippet will be responsible for enabling our customization. If it doesn't exist, you can add it.
Add the new entries pointing to the folder where the images were placed, set the position where the custom Face will be displayed and set the activation flag to True
.
...
ui.faces.look_r = "/custom-faces/LOOK_R.png"
ui.faces.look_l = "/custom-faces/LOOK_L.png"
ui.faces.look_r_happy = "/custom-faces/LOOK_R_HAPPY.png"
ui.faces.look_l_happy = "/custom-faces/LOOK_L_HAPPY.png"
ui.faces.sleep = "/custom-faces/SLEEP.png"
ui.faces.sleep2 = "/custom-faces/SLEEP2.png"
ui.faces.awake = "/custom-faces/AWAKE.png"
ui.faces.bored = "/custom-faces/BORED.png"
ui.faces.intense = "/custom-faces/INTENSE.png"
ui.faces.cool = "/custom-faces/COOL.png"
ui.faces.happy = "/custom-faces/HAPPY.png"
ui.faces.excited = "/custom-faces/EXCITED.png"
ui.faces.grateful = "/custom-faces/GRATEFUL.png"
ui.faces.motivated = "/custom-faces/MOTIVATED.png"
ui.faces.demotivated = "/custom-faces/DEMOTIVATED.png"
ui.faces.smart = "/custom-faces/SMART.png"
ui.faces.lonely = "/custom-faces/LONELY.png"
ui.faces.sad = "/custom-faces/SAD.png"
ui.faces.angry = "/custom-faces/ANGRY.png"
ui.faces.friend = "/custom-faces/FRIEND.png"
ui.faces.broken = "/custom-faces/BROKEN.png"
ui.faces.debug = "/custom-faces/DEBUG.png"
ui.faces.upload = "/custom-faces/UPLOAD.png"
ui.faces.upload1 = "/custom-faces/UPLOAD1.png"
ui.faces.upload2 = "/custom-faces/UPLOAD2.png"
ui.faces.png = true
ui.faces.position_x = 0
ui.faces.position_y = 34
...
Note 1: Check if your installed plugins modify the 'faces'. If there are any, replace them with the equivalent custom image address. If you don't do this, the pwnagotchi may crash. The code looks like this:
ui.set('face', "(◕‿‿◕)")
orview.set('face', "(◕‿‿◕)")
Note 2: I recommend that you always use the same path (
/custom-faces/
folder) for your customization. That way, it becomes easier as you only need to replace the files!
CTRL + O to save, CTRL + X to close file.
Restart your device
root@pwnagotchi:/# systemctl restart pwnagotchi
Enjoy!
# 2. Jayofelony's fork
Note: This fork already has the necessary modifications to display custom faces
First and foremost, keep in mind that you must meet this requirements:
- A computer;
- The pwnagotchi must already be on
latest
jayofelony's release;
First, with the pwnagotchi connected to a computer in MANU
mode, establish an SSH connection.
Login as root:
pi@pwnagotchi:~ $ sudo su
root@pwnagotchi:/home/pi#
root@pwnagotchi:/home/pi# whoami
root
Navigate to root directory:
root@pwnagotchi:/home/pi# cd /
Let's create custom-faces
folder to receive the custom faces:
root@pwnagotchi:/# mkdir custom-faces
Use FileZilla
or any other method you know to upload your images to the /custom-faces/
folder.
Note If you don't have it, use one of theme packages from here
Open the pwnagotchi's configuration file:
root@pwnagotchi:/# nano /etc/pwnagotchi/config.toml
Locate this code snippet:
...
ui.faces.look_r = "( ⚆_⚆)"
ui.faces.look_l = "(☉_☉ )"
ui.faces.look_r_happy = "( ◕‿◕)"
ui.faces.look_l_happy = "(◕‿◕ )"
ui.faces.sleep = "(⇀‿‿↼)"
ui.faces.sleep2 = "(≖‿‿≖)"
ui.faces.awake = "(◕‿‿◕)"
ui.faces.bored = "(-__-)"
ui.faces.intense = "(°▃▃°)"
ui.faces.cool = "(⌐■_■)"
ui.faces.happy = "(•‿‿•)"
ui.faces.excited = "(ᵔ◡◡ᵔ)"
ui.faces.grateful = "(^‿‿^)"
ui.faces.motivated = "(☼‿‿☼)"
ui.faces.demotivated = "(≖__≖)"
ui.faces.smart = "(✜‿‿✜)"
ui.faces.lonely = "(ب__ب)"
ui.faces.sad = "(╥☁╥ )"
ui.faces.angry = "(-_-')"
ui.faces.friend = "(♥‿‿♥)"
ui.faces.broken = "(☓‿‿☓)"
ui.faces.debug = "(#__#)"
ui.faces.upload = "(1__0)"
ui.faces.upload1 = "(1__1)"
ui.faces.upload2 = "(0__1)"
...
This snippet will be responsible for enabling our customization. If it doesn't exist, you can add it.
Add the new entries pointing to the folder where the images were placed, set the position where the custom Face will be displayed and set the activation flag to True
.
...
ui.faces.look_r = "/custom-faces/LOOK_R.png"
ui.faces.look_l = "/custom-faces/LOOK_L.png"
ui.faces.look_r_happy = "/custom-faces/LOOK_R_HAPPY.png"
ui.faces.look_l_happy = "/custom-faces/LOOK_L_HAPPY.png"
ui.faces.sleep = "/custom-faces/SLEEP.png"
ui.faces.sleep2 = "/custom-faces/SLEEP2.png"
ui.faces.awake = "/custom-faces/AWAKE.png"
ui.faces.bored = "/custom-faces/BORED.png"
ui.faces.intense = "/custom-faces/INTENSE.png"
ui.faces.cool = "/custom-faces/COOL.png"
ui.faces.happy = "/custom-faces/HAPPY.png"
ui.faces.excited = "/custom-faces/EXCITED.png"
ui.faces.grateful = "/custom-faces/GRATEFUL.png"
ui.faces.motivated = "/custom-faces/MOTIVATED.png"
ui.faces.demotivated = "/custom-faces/DEMOTIVATED.png"
ui.faces.smart = "/custom-faces/SMART.png"
ui.faces.lonely = "/custom-faces/LONELY.png"
ui.faces.sad = "/custom-faces/SAD.png"
ui.faces.angry = "/custom-faces/ANGRY.png"
ui.faces.friend = "/custom-faces/FRIEND.png"
ui.faces.broken = "/custom-faces/BROKEN.png"
ui.faces.debug = "/custom-faces/DEBUG.png"
ui.faces.upload = "/custom-faces/UPLOAD.png"
ui.faces.upload1 = "/custom-faces/UPLOAD1.png"
ui.faces.upload2 = "/custom-faces/UPLOAD2.png"
ui.faces.png = true
ui.faces.position_x = 0
ui.faces.position_y = 34
...
Note 1: Check if your installed plugins modify the 'faces'. If there are any, replace them with the equivalent custom image address. If you don't do this, the pwnagotchi may crash. The code looks like this:
ui.set('face', "(◕‿‿◕)")
orview.set('face', "(◕‿‿◕)")
Note 2: I recommend that you always use the same path (
/custom-faces/
folder) for your customization. That way, it becomes easier as you only need to replace the files!
CTRL + O to save, CTRL + X to close file.
Restart your device
root@pwnagotchi:/# systemctl restart pwnagotchi
Enjoy!
This is an entirely open project that accepts contributions via pull requests, your name will be placed as an author. If you have any questions, please open an issue.
- Create a fork of this repository
- Create your theme following the pattern of the ones already posted
- Commit your changes in English
- Include a brief summary of what was added
- Submit your pull request
- Update the docs for pwnagotchi
Evilsocket's v1.5.5
- Update the docs for pwnagotchi
Jayofelony
's fork - Buy new hardware
- Mod for new forks
- Check the log file, read and interpret:
root@pwnagotchi:/# tail -f /var/log/pwnagotchi.log
- The logs may not be enough, so use:
pi@pwnagotchi:~ $ sudo su
root@pwnagotchi:/home/pi# systemctl stop pwnagotchi
root@pwnagotchi:/home/pi# pwnagotchi
With this command you directly run the pwnagotchi services and this way you can see what happens at run time, showing errors what does not appear in the log
-
Restore the backup files that we placed in
/files-backup/
and try again -
If you don't have permission, try
chmod 777
-
Make sure that all entries related to the plugins are indeed in the
config.toml
file -
PM me here
Evilsocket - PersephoneKarnstein - V0r-T3x - @demetrius_official - CodyTolene - SeverX - cyberspacemanmike - JD-2006 - LuckyFish - Jayofelony - Zerodya - Owen