Merge branch 'master' into log-changes

Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
This commit is contained in:
Rai
2024-08-07 00:58:01 +10:00
committed by GitHub
5 changed files with 140 additions and 26 deletions

33
pwnagotchi/ui/colors.py Normal file
View File

@ -0,0 +1,33 @@
LOOK_R = '( ⚆_⚆)'
LOOK_L = '(☉_☉ )'
LOOK_R_HAPPY = '( ◕‿◕)'
LOOK_L_HAPPY = '(◕‿◕ )'
SLEEP = '(⇀‿‿↼)'
SLEEP2 = '(≖‿‿≖)'
AWAKE = '(◕‿‿◕)'
BORED = '(-__-)'
INTENSE = '(°▃▃°)'
COOL = '(⌐■_■)'
HAPPY = '(•‿‿•)'
GRATEFUL = '(^‿‿^)'
EXCITED = '(ᵔ◡◡ᵔ)'
MOTIVATED = '(☼‿‿☼)'
DEMOTIVATED = '(≖__≖)'
SMART = '(✜‿‿✜)'
LONELY = '(ب__ب)'
SAD = '(╥☁╥ )'
ANGRY = "(-_-')"
FRIEND = '(♥‿‿♥)'
BROKEN = '(☓‿‿☓)'
DEBUG = '(#__#)'
UPLOAD = '(1__0)'
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

View File

@ -7,6 +7,7 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class DisplayHatMini(DisplayImpl): class DisplayHatMini(DisplayImpl):
def __init__(self, config): def __init__(self, config):
super(DisplayHatMini, self).__init__(config, 'displayhatmini') super(DisplayHatMini, self).__init__(config, 'displayhatmini')
self.mode = "RGB" # its actually BGR;16 5,6,5 bit, but display lib converts it
def layout(self): def layout(self):
fonts.setup(12, 10, 12, 70, 25, 9) fonts.setup(12, 10, 12, 70, 25, 9)

View File

@ -7,7 +7,8 @@ from pwnagotchi.ui.hw.base import DisplayImpl
class Wavesharelcd1in8(DisplayImpl): class Wavesharelcd1in8(DisplayImpl):
def __init__(self, config): def __init__(self, config):
super(Wavesharelcd1in8, self).__init__(config, 'wavesharelcd1in8') super(Wavesharelcd1in8, self).__init__(config, 'wavesharelcd1in8')
self.mode = "RGB"
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9) fonts.setup(10, 8, 10, 18, 25, 9)
self._layout['width'] = 160 self._layout['width'] = 160

View File

@ -3,7 +3,7 @@ from threading import Lock
class State(object): class State(object):
def __init__(self, state={}): def __init__(self, state={}):
self._state = state self._state = state # all ui elements
self._lock = Lock() self._lock = Lock()
self._listeners = {} self._listeners = {}
self._changes = {} self._changes = {}

View File

@ -5,6 +5,7 @@ import time
from threading import Lock from threading import Lock
from PIL import ImageDraw from PIL import ImageDraw
from PIL import ImageColor as colors
import pwnagotchi import pwnagotchi
import pwnagotchi.plugins as plugins import pwnagotchi.plugins as plugins
@ -12,29 +13,106 @@ import pwnagotchi.ui.faces as faces
import pwnagotchi.ui.fonts as fonts import pwnagotchi.ui.fonts as fonts
import pwnagotchi.ui.web as web import pwnagotchi.ui.web as web
import pwnagotchi.utils as utils import pwnagotchi.utils as utils
from pwnagotchi.ui.components import * from pwnagotchi.ui.components import *
from pwnagotchi.ui.state import State from pwnagotchi.ui.state import State
from pwnagotchi.voice import Voice from pwnagotchi.voice import Voice
WHITE = 0x00 WHITE = 0x00 # white is actually black on jays image
BLACK = 0xFF BLACK = 0xFF # black is actually white on jays image
BACKGROUND_1 = 0
FOREGROUND_1 = 1
BACKGROUND_L = 0
FOREGROUND_L = 255
BACKGROUND_BGR_16 = (0,0,0)
FOREGROUND_BGR_16 = (31,63,31)
BACKGROUND_RGB = (0,0,0)
FOREGROUND_RGB = (255,255,255)
ROOT = None ROOT = None
#1 (1-bit pixels, black and white, stored with one pixel per byte)
#L (8-bit pixels, grayscale)
#P (8-bit pixels, mapped to any other mode using a color palette)
#BGR;16 (5,6,5 bits, for 65k color)
#RGB (3x8-bit pixels, true color)
#RGBA (4x8-bit pixels, true color with transparency mask)
#CMYK (4x8-bit pixels, color separation)
#YCbCr (3x8-bit pixels, color video format)
#self.FOREGROUND is the main color
#self.BACKGROUNDGROUND is the 2ndary color, used for background
class View(object): class View(object):
def __init__(self, config, impl, state=None): def __init__(self, config, impl, state=None):
global ROOT, BLACK, WHITE global ROOT, BLACK, WHITE
#values/code for display color mode
self.mode = '1' # 1 = (1-bit pixels, black and white, stored with one pixel per byte)
if hasattr(impl, 'mode'):
self.mode = impl.mode
match self.mode:
case '1':
self.BACKGROUND = BACKGROUND_1
self.FOREGROUND = FOREGROUND_1
# do stuff is color mode is 1 when View object is created.
case 'L':
self.BACKGROUND = BACKGROUND_L # black 0 to 255
self.FOREGROUND = FOREGROUND_L
# do stuff is color mode is L when View object is created.
case 'P':
pass
# do stuff is color mode is P when View object is created.
case 'BGR;16':
self.BACKGROUND = BACKGROUND_BGR_16 #black tuple
self.FOREGROUND = FOREGROUND_BGR_16 #white tuple
case 'RGB':
self.BACKGROUND = BACKGROUND_RGB #black tuple
self.FOREGROUND = FOREGROUND_RGB #white tuple
# do stuff is color mode is RGB when View object is created.
case 'RGBA':
# do stuff is color mode is RGBA when View object is created.
pass
case 'CMYK':
# do stuff is color mode is CMYK when View object is created.
pass
case 'YCbCr':
# do stuff is color mode is YCbCr when View object is created.
pass
case _:
# do stuff when color mode doesnt exist for display
self.BACKGROUND = BACKGROUND_1
self.FOREGROUND = FOREGROUND_1
self.invert = 0 self.invert = 0
self._black = 0xFF if 'invert' in config['ui'] and config['ui']['invert'] == True:
self._white = 0x00 logging.debug("INVERT:" + str(config['ui']['invert']))
if 'invert' in config['ui'] and config['ui']['invert']:
logging.debug("INVERT BLACK/WHITES:" + str(config['ui']['invert']))
self.invert = 1 self.invert = 1
BLACK = 0x00 tmp = self.FOREGROUND
WHITE = 0xFF self.FOREGROUND = self.FOREGROUND
self._black = 0x00 self.FOREGROUND = tmp
self._white = 0xFF
# setup faces from the configuration in case the user customized them # setup faces from the configuration in case the user customized them
faces.load_from_config(config['ui']['faces']) faces.load_from_config(config['ui']['faces'])
@ -51,40 +129,40 @@ class View(object):
self._width = self._layout['width'] self._width = self._layout['width']
self._height = self._layout['height'] self._height = self._layout['height']
self._state = State(state={ self._state = State(state={
'channel': LabeledValue(color=BLACK, label='CH', value='00', position=self._layout['channel'], 'channel': LabeledValue(color=self.FOREGROUND, label='CH', value='00', position=self._layout['channel'],
label_font=fonts.Bold, label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
'aps': LabeledValue(color=BLACK, label='APS', value='0 (00)', position=self._layout['aps'], 'aps': LabeledValue(color=self.FOREGROUND, label='APS', value='0 (00)', position=self._layout['aps'],
label_font=fonts.Bold, label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=self._layout['uptime'], 'uptime': LabeledValue(color=self.FOREGROUND, label='UP', value='00:00:00', position=self._layout['uptime'],
label_font=fonts.Bold, label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
'line1': Line(self._layout['line1'], color=BLACK), 'line1': Line(self._layout['line1'], color=self.FOREGROUND),
'line2': Line(self._layout['line2'], color=BLACK), 'line2': Line(self._layout['line2'], color=self.FOREGROUND),
'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']), 'face': Text(value=faces.SLEEP, position=(config['ui']['faces']['position_x'], config['ui']['faces']['position_y']), color=self.FOREGROUND, font=fonts.Huge, png=config['ui']['faces']['png']),
# 'friend_face': Text(value=None, position=self._layout['friend_face'], font=fonts.Bold, color=BLACK), # 'friend_face': Text(value=None, position=self._layout['friend_face'], font=fonts.Bold, color=self.FOREGROUND),
'friend_name': Text(value=None, position=self._layout['friend_face'], font=fonts.BoldSmall, color=BLACK), 'friend_name': Text(value=None, position=self._layout['friend_face'], font=fonts.BoldSmall, color=self.FOREGROUND),
'name': Text(value='%s>' % 'pwnagotchi', position=self._layout['name'], color=BLACK, font=fonts.Bold), 'name': Text(value='%s>' % 'pwnagotchi', position=self._layout['name'], color=self.FOREGROUND, font=fonts.Bold),
'status': Text(value=self._voice.default(), 'status': Text(value=self._voice.default(),
position=self._layout['status']['pos'], position=self._layout['status']['pos'],
color=BLACK, color=self.FOREGROUND,
font=self._layout['status']['font'], font=self._layout['status']['font'],
wrap=True, wrap=True,
# the current maximum number of characters per line, assuming each character is 6 pixels wide # the current maximum number of characters per line, assuming each character is 6 pixels wide
max_length=self._layout['status']['max']), max_length=self._layout['status']['max']),
'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=self.FOREGROUND,
position=self._layout['shakes'], label_font=fonts.Bold, position=self._layout['shakes'], label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
'mode': Text(value='AUTO', position=self._layout['mode'], 'mode': Text(value='AUTO', position=self._layout['mode'],
font=fonts.Bold, color=BLACK), font=fonts.Bold, color=self.FOREGROUND),
}) })
if state: if state:
@ -387,12 +465,13 @@ class View(object):
state = self._state state = self._state
changes = state.changes(ignore=self._ignore_changes) changes = state.changes(ignore=self._ignore_changes)
if force or len(changes): if force or len(changes):
self._canvas = Image.new('1', (self._width, self._height), self._white) self._canvas = Image.new(self.mode, (self._width, self._height), self.BACKGROUND)
drawer = ImageDraw.Draw(self._canvas) drawer = ImageDraw.Draw(self._canvas, self.mode)
plugins.on('ui_update', self) plugins.on('ui_update', self)
for key, lv in state.items(): for key, lv in state.items():
#lv is a ui element
lv.draw(self._canvas, drawer) lv.draw(self._canvas, drawer)
web.update_frame(self._canvas) web.update_frame(self._canvas)