From 8a3eacb5d240a402f5d8fe86536e279e201e45e5 Mon Sep 17 00:00:00 2001 From: Rai <58925163+rai68@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:05:24 +1000 Subject: [PATCH 1/6] Update LCD_2inch4.py Signed-off-by: Rai <58925163+rai68@users.noreply.github.com> --- pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py b/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py index dc1da5ec..ff19d242 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py +++ b/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py @@ -4,8 +4,8 @@ import numbers class LCD_2inch4(lcdconfig.RaspberryPi): - width = 240 - height = 320 + self.width = 240 + self.height = 320 def command(self, cmd): self.digital_write(self.DC_PIN, False) From 8a242a707b75c64cf33ebb90abde09c237d60d15 Mon Sep 17 00:00:00 2001 From: Rai <58925163+rai68@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:06:05 +1000 Subject: [PATCH 2/6] Update LCD_2inch4.py Signed-off-by: Rai <58925163+rai68@users.noreply.github.com> --- pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py b/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py index ff19d242..dc1da5ec 100644 --- a/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py +++ b/pwnagotchi/ui/hw/libs/waveshare/lcd/lcdhat2in4/LCD_2inch4.py @@ -4,8 +4,8 @@ import numbers class LCD_2inch4(lcdconfig.RaspberryPi): - self.width = 240 - self.height = 320 + width = 240 + height = 320 def command(self, cmd): self.digital_write(self.DC_PIN, False) From 8eccd71c6bce315739a82387918fd59ecd265c05 Mon Sep 17 00:00:00 2001 From: XxKingsxX-Pinu <58925163+rai68@users.noreply.github.com> Date: Thu, 13 Jun 2024 02:55:05 +1000 Subject: [PATCH 3/6] changes to ui --- pwnagotchi/ui/colors.py | 33 ++++++++ pwnagotchi/ui/hw/wavesharelcd1in8.py | 3 +- pwnagotchi/ui/state.py | 2 +- pwnagotchi/ui/view.py | 115 ++++++++++++++++++++++----- 4 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 pwnagotchi/ui/colors.py diff --git a/pwnagotchi/ui/colors.py b/pwnagotchi/ui/colors.py new file mode 100644 index 00000000..a81966c5 --- /dev/null +++ b/pwnagotchi/ui/colors.py @@ -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 diff --git a/pwnagotchi/ui/hw/wavesharelcd1in8.py b/pwnagotchi/ui/hw/wavesharelcd1in8.py index 9006d145..59eefad0 100644 --- a/pwnagotchi/ui/hw/wavesharelcd1in8.py +++ b/pwnagotchi/ui/hw/wavesharelcd1in8.py @@ -7,7 +7,8 @@ from pwnagotchi.ui.hw.base import DisplayImpl class Wavesharelcd1in8(DisplayImpl): def __init__(self, config): super(Wavesharelcd1in8, self).__init__(config, 'wavesharelcd1in8') - + self.mode = "RGB" + def layout(self): fonts.setup(10, 8, 10, 18, 25, 9) self._layout['width'] = 160 diff --git a/pwnagotchi/ui/state.py b/pwnagotchi/ui/state.py index b416b4a2..3c1a543c 100644 --- a/pwnagotchi/ui/state.py +++ b/pwnagotchi/ui/state.py @@ -3,7 +3,7 @@ from threading import Lock class State(object): def __init__(self, state={}): - self._state = state + self._state = state # all ui elements self._lock = Lock() self._listeners = {} self._changes = {} diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index 8d31ffeb..cdab577f 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -5,6 +5,7 @@ import time from threading import Lock from PIL import ImageDraw +from PIL import ImageColor as colors import pwnagotchi import pwnagotchi.plugins as plugins @@ -12,29 +13,98 @@ import pwnagotchi.ui.faces as faces import pwnagotchi.ui.fonts as fonts import pwnagotchi.ui.web as web import pwnagotchi.utils as utils + from pwnagotchi.ui.components import * from pwnagotchi.ui.state import State from pwnagotchi.voice import Voice -WHITE = 0x00 -BLACK = 0xFF +WHITE = 0x00 # white is actually black on jays image +BLACK = 0xFF # black is actually white on jays image + +BACKGROUND_1 = 0 +FOREGROUND_1 = 1 + +BACKGROUND_L = 0 +FOREGROUND_L = 255 + +BACKGROUND_RGB = (0,0,0) +FOREGROUND_RGB = (255,255,255) + 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) + +#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.FOREGROUND is the 2ndary color, used for background + + + class View(object): def __init__(self, config, impl, state=None): 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 '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._black = 0xFF - self._white = 0x00 + if 'invert' in config['ui'] and config['ui']['invert'] == True: logging.debug("INVERT BLACK/WHITES:" + str(config['ui']['invert'])) self.invert = 1 - BLACK = 0x00 - WHITE = 0xFF - self._black = 0x00 - self._white = 0xFF + tmp = self.FOREGROUND + self.FOREGROUND = self.FOREGROUND + self.FOREGROUND = tmp # setup faces from the configuration in case the user customized them faces.load_from_config(config['ui']['faces']) @@ -51,40 +121,40 @@ class View(object): self._width = self._layout['width'] self._height = self._layout['height'] 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, 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, 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, text_font=fonts.Medium), - 'line1': Line(self._layout['line1'], color=BLACK), - 'line2': Line(self._layout['line2'], color=BLACK), + 'line1': Line(self._layout['line1'], color=self.FOREGROUND), + '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_name': Text(value=None, position=self._layout['friend_face'], font=fonts.BoldSmall, 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=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(), position=self._layout['status']['pos'], - color=BLACK, + color=self.FOREGROUND, font=self._layout['status']['font'], wrap=True, # the current maximum number of characters per line, assuming each character is 6 pixels wide 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, text_font=fonts.Medium), 'mode': Text(value='AUTO', position=self._layout['mode'], - font=fonts.Bold, color=BLACK), + font=fonts.Bold, color=self.FOREGROUND), }) if state: @@ -387,8 +457,9 @@ class View(object): state = self._state changes = state.changes(ignore=self._ignore_changes) if force or len(changes): - self._canvas = Image.new('1', (self._width, self._height), self._white) - drawer = ImageDraw.Draw(self._canvas) + logging.info(self.mode) + self._canvas = Image.new(self.mode, (self._width, self._height), self.BACKGROUND) + drawer = ImageDraw.Draw(self._canvas, self.mode) plugins.on('ui_update', self) From 689d39c450e1bf26dad267fae3474370c62ecf32 Mon Sep 17 00:00:00 2001 From: XxKingsxX-Pinu <58925163+rai68@users.noreply.github.com> Date: Thu, 13 Jun 2024 03:37:51 +1000 Subject: [PATCH 4/6] more changes --- pwnagotchi/ui/hw/displayhatmini.py | 1 + pwnagotchi/ui/view.py | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pwnagotchi/ui/hw/displayhatmini.py b/pwnagotchi/ui/hw/displayhatmini.py index afc590db..81b5d72e 100644 --- a/pwnagotchi/ui/hw/displayhatmini.py +++ b/pwnagotchi/ui/hw/displayhatmini.py @@ -7,6 +7,7 @@ from pwnagotchi.ui.hw.base import DisplayImpl class DisplayHatMini(DisplayImpl): def __init__(self, config): 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): fonts.setup(12, 10, 12, 70, 25, 9) diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index cdab577f..808feda5 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -27,9 +27,16 @@ 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) +BACKGROUND_RGB_24 = (0,0,0) +FOREGROUND_RGB_24 = (255,255,255) + ROOT = None @@ -41,6 +48,8 @@ ROOT = None #P (8-bit pixels, mapped to any other mode using a color palette) + +#BGR;16 (5,6,5 ) #RGB (3x8-bit pixels, true color) #RGBA (4x8-bit pixels, true color with transparency mask) @@ -50,7 +59,7 @@ ROOT = None #YCbCr (3x8-bit pixels, color video format) #self.FOREGROUND is the main color -#self.FOREGROUND is the 2ndary color, used for background +#self.BACKGROUNDGROUND is the 2ndary color, used for background @@ -78,6 +87,9 @@ class View(object): 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 @@ -135,7 +147,7 @@ class View(object): 'line1': Line(self._layout['line1'], color=self.FOREGROUND), '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=self.FOREGROUND, 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=(255,0,255), font=fonts.Huge, png=config['ui']['faces']['png']), # '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=self.FOREGROUND), From 7d8b66e1cb866901e2fe42f98949b38377a3bf9d Mon Sep 17 00:00:00 2001 From: XxKingsxX-Pinu <58925163+rai68@users.noreply.github.com> Date: Thu, 13 Jun 2024 04:18:57 +1000 Subject: [PATCH 5/6] Update displayhatmini.py --- pwnagotchi/ui/hw/displayhatmini.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/ui/hw/displayhatmini.py b/pwnagotchi/ui/hw/displayhatmini.py index 81b5d72e..d404f962 100644 --- a/pwnagotchi/ui/hw/displayhatmini.py +++ b/pwnagotchi/ui/hw/displayhatmini.py @@ -7,7 +7,7 @@ from pwnagotchi.ui.hw.base import DisplayImpl class DisplayHatMini(DisplayImpl): def __init__(self, config): super(DisplayHatMini, self).__init__(config, 'displayhatmini') - self.mode = "RGB" # its actually BGR;16 5,6,5 bit, but display lib converts it + self.mode = "RGB" # its actually BGR;16 5,6,5 bit, but display lib converts it def layout(self): fonts.setup(12, 10, 12, 70, 25, 9) From b7eb86d55cb37332e81fc62611e0de039afe44a0 Mon Sep 17 00:00:00 2001 From: XxKingsxX-Pinu <58925163+rai68@users.noreply.github.com> Date: Thu, 13 Jun 2024 05:45:42 +1000 Subject: [PATCH 6/6] Update view.py --- pwnagotchi/ui/view.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index 808feda5..0d73257f 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -27,15 +27,12 @@ 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) -BACKGROUND_RGB_24 = (0,0,0) -FOREGROUND_RGB_24 = (255,255,255) ROOT = None @@ -48,8 +45,8 @@ ROOT = None #P (8-bit pixels, mapped to any other mode using a color palette) +#BGR;16 (5,6,5 bits, for 65k color) -#BGR;16 (5,6,5 ) #RGB (3x8-bit pixels, true color) #RGBA (4x8-bit pixels, true color with transparency mask) @@ -147,7 +144,7 @@ class View(object): 'line1': Line(self._layout['line1'], color=self.FOREGROUND), '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=(255,0,255), 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=self.FOREGROUND), 'friend_name': Text(value=None, position=self._layout['friend_face'], font=fonts.BoldSmall, color=self.FOREGROUND), @@ -469,13 +466,13 @@ class View(object): state = self._state changes = state.changes(ignore=self._ignore_changes) if force or len(changes): - logging.info(self.mode) self._canvas = Image.new(self.mode, (self._width, self._height), self.BACKGROUND) drawer = ImageDraw.Draw(self._canvas, self.mode) plugins.on('ui_update', self) for key, lv in state.items(): + #lv is a ui element lv.draw(self._canvas, drawer) web.update_frame(self._canvas)