Merge branch 'jayofelony:noai' into noai

This commit is contained in:
V0rT3x
2024-12-01 20:17:14 -05:00
committed by GitHub
56 changed files with 705 additions and 1288 deletions

View File

@ -1,12 +1,12 @@
# board GPIO:
# Key1:
# Key2:
# Key3:
# Key4:
#
# Key1: GPIO 16
# Key2: GPIO 20
# Key3: GPIO 21
# Key4: GPIO 26
# IR: GPIO 23
# Touch chipset:
# HW info: https://argon40.com/products/pod-display-2-8inch
# HW datasheet:
# HW MANUAL: https://cdn.shopify.com/s/files/1/0556/1660/2177/files/ARGON_POD_MANUAL.pdf?v=1668390711%0A
import logging
@ -44,6 +44,9 @@ class ArgonPod(DisplayImpl):
def initialize(self):
logging.info("Initializing Argon Pod display")
logging.info("Available pins for GPIO Buttons: 16, 20, 21, 26")
logging.info("IR available on GPIO 23")
logging.info("Backlight pin available on GPIO 18")
from pwnagotchi.ui.hw.libs.argon.argonpod.ILI9341 import ILI9341
self._display = ILI9341(0, 0, 22, 18)

View File

@ -1,9 +1,7 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DisplayHatMini(DisplayImpl):
def __init__(self, config):
super(DisplayHatMini, self).__init__(config, 'displayhatmini')
@ -29,11 +27,14 @@ class DisplayHatMini(DisplayImpl):
'font': fonts.status_font(fonts.Medium),
'max': 20
}
return self._layout
def initialize(self):
logging.info("initializing Display Hat Mini")
logging.info("Initializing Display Hat Mini")
logging.info("Available pins for GPIO Buttons A/B/X/Y: 5, 6, 16, 24")
logging.info("Available pins for RGB Led: 17, 27, 22")
logging.info("Backlight pin available on GPIO 13")
logging.info("I2C bus available on stemma QT and Breakout Garden headers")
from pwnagotchi.ui.hw.libs.pimoroni.displayhatmini.ST7789 import ST7789
self._display = ST7789(0,1,9,13)

View File

@ -8,7 +8,7 @@
# ui.display.blcolor = "olive"
#
# Contrast should be between 30-50, default is 40
# Backlight are predefined in the epd.py
# Backlight are predefined in the lcd.py
# Available backlight colors:
# white, grey, maroon, red, purple, fuchsia, green,
# lime, olive, yellow, navy, blue, teal, aqua
@ -48,10 +48,16 @@ class GfxHat(DisplayImpl):
def initialize(self):
contrast = self._config['contrast'] if 'contrast' in self._config else 40
blcolor = self._config['blcolor'] if 'blcolor' in self._config else 'OLIVE'
logging.info("initializing Pimoroni GfxHat")
logging.info("initializing Pimoroni GfxHat - Contrast: %d Backlight color: %s" % (contrast, blcolor))
from pwnagotchi.ui.hw.libs.pimoroni.gfxhat.epd import EPD
self._display = EPD(contrast=contrast)
logging.info("Initializing Pimoroni GfxHat - Contrast: %d Backlight color: %s" % (contrast, blcolor))
logging.info("Available config options: ui.display.contrast and ui.display.color")
logging.info("Contrast should be between 30-50, default is 40")
logging.info("Backlight are predefined in the lcd.py")
logging.info("Available backlight colors:")
logging.info("white, grey, maroon, red, purple, fuchsia, green,")
logging.info("lime, olive, yellow, navy, blue, teal, aqua")
logging.info("Touch control work in progress (6 touch buttons with short and long press and LED feedback)")
from pwnagotchi.ui.hw.libs.pimoroni.gfxhat.lcd import LCD
self._display = LCD(contrast=contrast)
self._display.Init(color_name=blcolor)
self._display.Clear()

View File

@ -52,11 +52,11 @@ class I2COled(DisplayImpl):
i2caddr = self._config['i2c_addr'] if 'i2c_addr' in self._config else 0x3C
width = self._config['width'] if 'width' in self._config else 128
height = self._config['height'] if 'height' in self._config else 64
logging.info("Initializing SSD1306 based %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr))
logging.info("Available config options: ui.display.width, ui.display.height and ui.display.i2caddr")
logging.info("initializing %dx%d I2C Oled Display on address 0x%X" % (width, height, i2caddr))
from pwnagotchi.ui.hw.libs.i2coled.epd import EPD
self._display = EPD(address=i2caddr, width=width, height=height)
from pwnagotchi.ui.hw.libs.i2coled.oled import OLED
self._display = OLED(address=i2caddr, width=width, height=height)
self._display.Init()
self._display.Clear()

View File

@ -9,7 +9,7 @@ EPD_HEIGHT = 64
# disp = SSD1306.SSD1306_96_16(96, 16, address=0x3C)
# If you change for different resolution, you have to modify the layout in pwnagotchi/ui/hw/i2coled.py
class EPD(object):
class OLED(object):
def __init__(self, address=0x3C, width=EPD_WIDTH, height=EPD_HEIGHT):
self.width = width

View File

@ -9,7 +9,7 @@ LED_MAP = [2, 1, 0, 5, 4, 3]
def setup():
"""Set up the backlight on GFX HAT."""
global _sn3218
import sn3218 as _sn3218
from . import sn3218 as _sn3218
_sn3218.enable()
_sn3218.enable_leds(0b111111111111111111)

View File

@ -1,55 +0,0 @@
from . import st7567
from . import backlight
CONTRAST = 40
# Define RGB colors
WHITE = (255, 255, 255)
GREY = (255, 255, 255)
MAROON = (128, 0, 0)
RED = (255, 0, 0)
PURPLE = (128, 0, 128)
FUCHSIA = (255, 0, 255)
GREEN = (0, 128, 0)
LIME = (0, 255, 0)
OLIVE = (128, 128, 0)
YELLOW = (255, 255, 0)
NAVY = (0, 0, 128)
BLUE = (0, 0, 255)
TEAL = (0, 128, 128)
AQUA = (0, 255, 255)
# Map color names to RGB values
color_map = {
'WHITE': WHITE,
'GREY' : GREY,
'MAROON': MAROON,
'RED': RED,
'PURPLE': PURPLE,
'FUCHSIA': FUCHSIA,
'GREEN' : GREEN,
'LIME' : LIME,
'OLIVE' : OLIVE,
'YELLOW' : YELLOW,
'NAVY' : NAVY,
'BLUE' : BLUE,
'TEAL' : TEAL,
'AQUA' : AQUA
}
class EPD(object):
def __init__(self, contrast=CONTRAST, blcolor=('OLIVE')):
self.disp = st7567.ST7567()
self.disp.contrast(contrast)
def Init(self, color_name):
self.disp.setup()
blcolor = color_map.get(color_name.upper(), OLIVE) # Default to olive if color not found
backlight.set_all(*blcolor)
backlight.show()
def Clear(self):
self.disp.clear()
def Display(self, image):
self.disp.show(image)

View File

@ -1,57 +1,55 @@
"""Library for the GFX HAT ST7567 SPI LCD."""
from .st7567 import ST7567
from . import st7567
from . import backlight
CONTRAST = 40
st7567 = ST7567()
# Define RGB colors
WHITE = (255, 255, 255)
GREY = (255, 255, 255)
MAROON = (128, 0, 0)
RED = (255, 0, 0)
PURPLE = (128, 0, 128)
FUCHSIA = (255, 0, 255)
GREEN = (0, 128, 0)
LIME = (0, 255, 0)
OLIVE = (128, 128, 0)
YELLOW = (255, 255, 0)
NAVY = (0, 0, 128)
BLUE = (0, 0, 255)
TEAL = (0, 128, 128)
AQUA = (0, 255, 255)
dimensions = st7567.dimensions
# Map color names to RGB values
color_map = {
'WHITE': WHITE,
'GREY' : GREY,
'MAROON': MAROON,
'RED': RED,
'PURPLE': PURPLE,
'FUCHSIA': FUCHSIA,
'GREEN' : GREEN,
'LIME' : LIME,
'OLIVE' : OLIVE,
'YELLOW' : YELLOW,
'NAVY' : NAVY,
'BLUE' : BLUE,
'TEAL' : TEAL,
'AQUA' : AQUA
}
class LCD(object):
def clear():
"""Clear GFX HAT's display buffer."""
st7567.clear()
def __init__(self, contrast=CONTRAST, blcolor=('OLIVE')):
self.disp = st7567.ST7567()
self.disp.contrast(contrast)
def Init(self, color_name):
self.disp.setup()
blcolor = color_map.get(color_name.upper(), OLIVE) # Default to olive if color not found
backlight.set_all(*blcolor)
backlight.show()
def set_pixel(x, y, value):
"""Set a single pixel in GTX HAT's display buffer.
def Clear(self):
self.disp.clear()
:param x: X position (from 0 to 127)
:param y: Y position (from 0 to 63)
:param value: pixel state 1 = On, 0 = Off
"""
st7567.set_pixel(x, y, value)
def show():
"""Update GFX HAT with the current buffer contents."""
st7567.show()
def contrast(value):
"""Change GFX HAT LCD contrast."""
st7567.contrast(value)
def rotation(r=0):
"""Set the display rotation.
:param r: Specify the rotation in degrees: 0, or 180
"""
if r == 0:
st7567.rotated = False
elif r == 180:
st7567.rotated = True
else:
raise ValueError('Rotation must be 0 or 180 degrees')
def get_rotation():
"""Get the display rotation value.
Returns an integer, either 0, or 180
"""
return 180 if st7567.rotated else 0
def Display(self, image):
self.disp.show(image)

View File

@ -0,0 +1,214 @@
import sys
import warnings
__version__ = '1.2.7'
I2C_ADDRESS = 0x54
CMD_ENABLE_OUTPUT = 0x00
CMD_SET_PWM_VALUES = 0x01
CMD_ENABLE_LEDS = 0x13
CMD_UPDATE = 0x16
CMD_RESET = 0x17
if sys.version_info < (3, ):
SMBUS = "python-smbus"
else:
SMBUS = "python3-smbus"
# Helper function to avoid exception chaining output in python3.
# use exec to shield newer syntax from older python
if sys.version_info < (3, 3):
def _raise_from_none(exc):
raise exc
else:
exec("def _raise_from_none(exc): raise exc from None")
try:
from smbus import SMBus
except ImportError:
err_string = "This library requires {smbus}\nInstall with: sudo apt install {smbus}".format(smbus=SMBUS)
import_error = ImportError(err_string)
_raise_from_none(import_error)
def i2c_bus_id():
"""
Returns the i2c bus ID.
"""
with open('/proc/cpuinfo') as cpuinfo:
revision = [l[12:-1] for l in cpuinfo if l[:8] == "Revision"][0]
# https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
return 1 if int(revision, 16) >= 4 else 0
def enable():
"""
Enables output.
"""
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_OUTPUT, [0x01])
def disable():
"""
Disables output.
"""
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_OUTPUT, [0x00])
def reset():
"""
Resets all internal registers.
"""
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_RESET, [0xFF])
def enable_leds(enable_mask):
"""
Enables or disables each LED channel. The first 18 bit values are
used to determine the state of each channel (1=on, 0=off) if fewer
than 18 bits are provided the remaining channels are turned off.
Args:
enable_mask (int): up to 18 bits of data
Raises:
TypeError: if enable_mask is not an integer.
"""
if not isinstance(enable_mask, int):
raise TypeError("enable_mask must be an integer")
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_ENABLE_LEDS,
[enable_mask & 0x3F, (enable_mask >> 6) & 0x3F, (enable_mask >> 12) & 0X3F])
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF])
def channel_gamma(channel, gamma_table):
"""
Overrides the gamma table for a single channel.
Args:
channel (int): channel number
gamma_table (list): list of 256 gamma correction values
Raises:
TypeError: if channel is not an integer.
ValueError: if channel is not in the range 0..17.
TypeError: if gamma_table is not a list.
"""
global channel_gamma_table
if not isinstance(channel, int):
raise TypeError("channel must be an integer")
if channel not in range(18):
raise ValueError("channel be an integer in the range 0..17")
if not isinstance(gamma_table, list) or len(gamma_table) != 256:
raise TypeError("gamma_table must be a list of 256 integers")
channel_gamma_table[channel] = gamma_table
def output(values):
"""
Outputs a new set of values to the driver.
Args:
values (list): channel number
Raises:
TypeError: if values is not a list of 18 integers.
"""
if not isinstance(values, list) or len(values) != 18:
raise TypeError("values must be a list of 18 integers")
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_SET_PWM_VALUES, [channel_gamma_table[i][values[i]] for i in range(18)])
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF])
def output_raw(values):
"""
Outputs a new set of values to the driver.
Similar to output(), but does not use channel_gamma_table.
Args:
values (list): channel number
Raises:
TypeError: if values is not a list of 18 integers.
"""
# SMBus.write_i2c_block_data does the type check, so we don't have to
if len(values) != 18:
raise TypeError("values must be a list of 18 integers")
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_SET_PWM_VALUES, values)
i2c.write_i2c_block_data(I2C_ADDRESS, CMD_UPDATE, [0xFF])
try:
i2c = SMBus(i2c_bus_id())
except IOError as e:
warntxt="""
###### ###### ###### ###### ###### ###### ###### ######
i2c initialization failed - is i2c enabled on this system?
See https://github.com/pimoroni/sn3218/wiki/missing-i2c
###### ###### ###### ###### ###### ###### ###### ######
"""
warnings.warn(warntxt)
raise(e)
# generate a good default gamma table
default_gamma_table = [int(pow(255, float(i - 1) / 255)) for i in range(256)]
channel_gamma_table = [default_gamma_table] * 18
enable_leds(0b111111111111111111)
def test_cycles():
print("sn3218 test cycles")
import time
import math
# enable output
enable()
enable_leds(0b111111111111111111)
print(">> test enable mask (on/off)")
enable_mask = 0b000000000000000000
output([0x10] * 18)
for i in range(10):
enable_mask = ~enable_mask
enable_leds(enable_mask)
time.sleep(0.15)
print(">> test enable mask (odd/even)")
enable_mask = 0b101010101010101010
output([0x10] * 18)
for i in range(10):
enable_mask = ~enable_mask
enable_leds(enable_mask)
time.sleep(0.15)
print(">> test enable mask (rotate)")
enable_mask = 0b100000100000100000
output([0x10] * 18)
for i in range(10):
enable_mask = ((enable_mask & 0x01) << 18) | enable_mask >> 1
enable_leds(enable_mask)
time.sleep(0.15)
print(">> test gamma gradient")
enable_mask = 0b111111111111111111
enable_leds(enable_mask)
for i in range(256):
output([((j * (256//18)) + (i * (256//18))) % 256 for j in range(18)])
time.sleep(0.01)
print(">> test gamma fade")
enable_mask = 0b111111111111111111
enable_leds(enable_mask)
for i in range(512):
output([int((math.sin(float(i)/64.0) + 1.0) * 128.0)]*18)
time.sleep(0.01)
# turn everything off and disable output
output([0 for i in range(18)])
disable()
if __name__ == "__main__":
test_cycles()

View File

@ -1,6 +1,6 @@
# board GPIO:
# A: GPIO22
# B: GPIO23
# A: GPIO23
# B: GPIO24
#
# HW datasheet: https://learn.adafruit.com/adafruit-1-3-color-tft-bonnet-for-raspberry-pi/overview
@ -38,7 +38,10 @@ class MiniPitft(DisplayImpl):
return self._layout
def initialize(self):
logging.info("initializing Adafruit Mini Pi Tft 240x240")
logging.info("Initializing Adafruit Mini Pi Tft 240x240")
logging.info("Available pins for GPIO Buttons: 23, 24")
logging.info("Backlight pin available on GPIO 22")
logging.info("I2C bus available on stemma QT header")
from pwnagotchi.ui.hw.libs.adafruit.minipitft.ST7789 import ST7789
self._display = ST7789(0,0,25,22)

View File

@ -1,6 +1,6 @@
# board GPIO:
# A: GPIO22
# B: GPIO23
# A: GPIO23
# B: GPIO24
#
# HW datasheet: https://learn.adafruit.com/adafruit-1-3-color-tft-bonnet-for-raspberry-pi/overview
@ -39,6 +39,9 @@ class MiniPitft2(DisplayImpl):
def initialize(self):
logging.info("initializing Adafruit Mini Pi Tft 135x240")
logging.info("Available pins for GPIO Buttons: 23, 24")
logging.info("Backlight pin available on GPIO 22")
logging.info("I2C bus available on stemma QT header")
from pwnagotchi.ui.hw.libs.adafruit.minipitft2.ST7789 import ST7789
self._display = ST7789(0,0,25,22)

View File

@ -45,6 +45,10 @@ class PirateAudio(DisplayImpl):
def initialize(self):
logging.info("Initializing PirateAudio - display only")
logging.info("Available pins for GPIO Buttons A/B/X/Y: 5, 6, 16, 20 or 24")
logging.info("refer to the pimoroni site or pinout.xyz")
logging.info("Backlight pin available on GPIO 13")
logging.info("I2S for the DAC available on pins: 18, 19 and 21")
from pwnagotchi.ui.hw.libs.pimoroni.pirateaudio.ST7789 import ST7789
self._display = ST7789(0,1,9,13)

View File

@ -50,6 +50,9 @@ class Pitft(DisplayImpl):
def initialize(self):
logging.info("Initializing adafruit pitft 320x240 screen")
logging.info("Available pins for GPIO Buttons on the 3,2inch: 17, 22, 23, 27")
logging.info("Available pins for GPIO Buttons on the 2,8inch: 26, 13, 12, 6, 5")
logging.info("Backlight pin available on GPIO 18")
from pwnagotchi.ui.hw.libs.adafruit.pitft.ILI9341 import ILI9341
self._display = ILI9341(0, 0, 25, 18)

View File

@ -44,6 +44,9 @@ class TftBonnet(DisplayImpl):
def initialize(self):
logging.info("initializing Adafruit Tft Bonnet")
logging.info("Available pins for GPIO Buttons Up/Down/Left/Right/Center/A/B: 17, 22, 27, 23, 4, 5, 6")
logging.info("Backlight pin available on GPIO 26")
logging.info("I2C bus available on stemma QT header")
from pwnagotchi.ui.hw.libs.adafruit.tftbonnet.ST7789 import ST7789
self._display = ST7789(0,0,25,26)

View File

@ -49,6 +49,7 @@ class Waveshareoledlcd(DisplayImpl):
def initialize(self):
logging.info("initializing Waveshare OLED/LCD hat")
logging.info("Available pins for GPIO Buttons K1/K2/K3/K4: 4, 17, 23, 24")
from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.ST7789 import ST7789
self._display = ST7789(0,0,22,18)

View File

@ -49,6 +49,7 @@ class Waveshareoledlcdvert(DisplayImpl):
def initialize(self):
logging.info("initializing Waveshare OLED/LCD hat vertical mode")
logging.info("Available pins for GPIO Buttons K1/K2/K3/K4: 4, 17, 23, 24")
from pwnagotchi.ui.hw.libs.waveshare.oled.oledlcd.ST7789vert import ST7789
self._display = ST7789(0,0,22,18)

View File

@ -1,4 +1,4 @@
#import _thread
# import _thread
import threading
import logging
import random
@ -6,7 +6,6 @@ import time
from threading import Lock
from PIL import ImageDraw
from PIL import ImageColor as colors
import pwnagotchi
import pwnagotchi.plugins as plugins
@ -19,105 +18,28 @@ from pwnagotchi.ui.components import *
from pwnagotchi.ui.state import State
from pwnagotchi.voice import Voice
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_BGR_16 = (0,0,0)
FOREGROUND_BGR_16 = (31,63,31)
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)
#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
WHITE = 0x00 # white is actually black on jays image
BLACK = 0xFF # black is actually white on jays image
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 '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._black = 0xFF
self._white = 0x00
if 'invert' in config['ui'] and config['ui']['invert'] == True:
logging.debug("INVERT:" + str(config['ui']['invert']))
logging.debug("INVERT BLACK/WHITES:" + str(config['ui']['invert']))
self.invert = 1
tmp = self.FOREGROUND
self.FOREGROUND = self.FOREGROUND
self.FOREGROUND = tmp
BLACK = 0x00
WHITE = 0xFF
self._black = 0x00
self._white = 0xFF
# setup faces from the configuration in case the user customized them
faces.load_from_config(config['ui']['faces'])
self._agent = None
self._render_cbs = []
self._config = config
@ -130,40 +52,42 @@ class View(object):
self._width = self._layout['width']
self._height = self._layout['height']
self._state = State(state={
'channel': LabeledValue(color=self.FOREGROUND, label='CH', value='00', position=self._layout['channel'],
'channel': LabeledValue(color=BLACK, label='CH', value='00', position=self._layout['channel'],
label_font=fonts.Bold,
text_font=fonts.Medium),
'aps': LabeledValue(color=self.FOREGROUND, label='APS', value='0 (00)', position=self._layout['aps'],
'aps': LabeledValue(color=BLACK, label='APS', value='0 (00)', position=self._layout['aps'],
label_font=fonts.Bold,
text_font=fonts.Medium),
'uptime': LabeledValue(color=self.FOREGROUND, label='UP', value='00:00:00', position=self._layout['uptime'],
'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=self._layout['uptime'],
label_font=fonts.Bold,
text_font=fonts.Medium),
'line1': Line(self._layout['line1'], color=self.FOREGROUND),
'line2': Line(self._layout['line2'], color=self.FOREGROUND),
'line1': Line(self._layout['line1'], color=BLACK),
'line2': Line(self._layout['line2'], color=BLACK),
'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=BLACK, 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),
# '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),
'name': Text(value='%s>' % 'pwnagotchi', position=self._layout['name'], color=self.FOREGROUND, font=fonts.Bold),
'name': Text(value='%s>' % 'pwnagotchi', position=self._layout['name'], color=BLACK, font=fonts.Bold),
'status': Text(value=self._voice.default(),
position=self._layout['status']['pos'],
color=self.FOREGROUND,
color=BLACK,
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=self.FOREGROUND,
'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK,
position=self._layout['shakes'], label_font=fonts.Bold,
text_font=fonts.Medium),
'mode': Text(value='AUTO', position=self._layout['mode'],
font=fonts.Bold, color=self.FOREGROUND),
font=fonts.Bold, color=BLACK),
})
if state:
@ -173,8 +97,8 @@ class View(object):
plugins.on('ui_setup', self)
if config['ui']['fps'] > 0.0:
threading.Thread(target=self._refresh_handler, args=(), name="UI Handler", daemon = True).start()
threading.Thread(target=self._refresh_handler, args=(), name="UI Handler", daemon=True).start()
self._ignore_changes = ()
else:
logging.warning("ui.fps is 0, the display will only update for major changes")
@ -189,7 +113,7 @@ class View(object):
self._state.has_element(key)
def add_element(self, key, elem):
if self.invert is 1 and hasattr(elem, 'color'):
if self.invert is 1 and elem.color:
if elem.color == 0xff:
elem.color = 0x00
elif elem.color == 0x00:
@ -250,7 +174,8 @@ class View(object):
self.set('uptime', last_session.duration)
self.set('channel', '-')
self.set('aps', "%d" % last_session.associated)
self.set('shakes', '%d (%s)' % (last_session.handshakes, utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
self.set('shakes', '%d (%s)' % (
last_session.handshakes, utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
self.set_closest_peer(last_session.last_peer, last_session.peers)
self.update()
@ -340,7 +265,7 @@ class View(object):
def wait(self, secs, sleeping=True):
was_normal = self.is_normal()
part = secs/10.0
part = secs / 10.0
for step in range(0, 10):
# if we weren't in a normal state before going
@ -468,13 +393,13 @@ class View(object):
state = self._state
changes = state.changes(ignore=self._ignore_changes)
if force or len(changes):
self._canvas = Image.new(self.mode, (self._width, self._height), self.BACKGROUND)
drawer = ImageDraw.Draw(self._canvas, self.mode)
self._canvas = Image.new('1', (self._width, self._height), self._white)
drawer = ImageDraw.Draw(self._canvas)
plugins.on('ui_update', self)
for key, lv in state.items():
#lv is a ui element
# lv is a ui element
lv.draw(self._canvas, drawer)
web.update_frame(self._canvas)