Merge pull request #15 from caquino/caquino/SD-IO

Support for InkyPHAT displays from pimoroni using the inky library
This commit is contained in:
evilsocket 2019-09-28 19:17:43 +02:00 committed by GitHub
commit af6dc69248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 32 deletions

View File

@ -90,6 +90,10 @@ ui:
# ePaper display can update every 3 secs anyway # ePaper display can update every 3 secs anyway
fps: 0.3 fps: 0.3
display: display:
# Possible options inkyphat/waveshare
type: 'inkyphat'
# Possible options red/yellow/black (black used for monocromatic displays)
display_color: 'red'
enabled: true enabled: true
rotation: 180 rotation: 180
video: video:

View File

@ -62,7 +62,7 @@ if args.do_manual:
core.log("detected a new session and internet connectivity!") core.log("detected a new session and internet connectivity!")
picture = '/tmp/pwnagotchi.png' picture = '/dev/shm/pwnagotchi.png'
display.update() display.update()
display.image().save(picture, 'png') display.image().save(picture, 'png')

View File

@ -77,6 +77,8 @@ class Display(View):
self._video_enabled = config['ui']['display']['video']['enabled'] self._video_enabled = config['ui']['display']['video']['enabled']
self._video_port = config['ui']['display']['video']['port'] self._video_port = config['ui']['display']['video']['port']
self._video_address = config['ui']['display']['video']['address'] self._video_address = config['ui']['display']['video']['address']
self._display_type = config['ui']['display']['type']
self._display_color = config['ui']['display']['display_color']
self._display = None self._display = None
self._httpd = None self._httpd = None
self.canvas = None self.canvas = None
@ -99,12 +101,18 @@ class Display(View):
core.log("could not get ip of usb0, video server not starting") core.log("could not get ip of usb0, video server not starting")
def _init_display(self): def _init_display(self):
if self._display_type == 'inkyphat':
from inky import InkyPHAT
self._display = InkyPHAT(self._display_color)
self._display.set_border(InkyPHAT.BLACK)
else:
from pwnagotchi.ui.waveshare import EPD from pwnagotchi.ui.waveshare import EPD
# core.log("display module started") # core.log("display module started")
self._display = EPD() self._display = EPD()
self._display.init(self._display.FULL_UPDATE) self._display.init(self._display.FULL_UPDATE)
self._display.Clear(WHITE) self._display.Clear(WHITE)
self._display.init(self._display.PART_UPDATE) self._display.init(self._display.PART_UPDATE)
self.on_render(self._on_view_rendered) self.on_render(self._on_view_rendered)
def image(self): def image(self):
@ -119,5 +127,34 @@ class Display(View):
if self._enabled: if self._enabled:
self.canvas = img if self._rotation == 0 else img.rotate(self._rotation) self.canvas = img if self._rotation == 0 else img.rotate(self._rotation)
if self._display_type == 'inkyphat':
if self._display_color != 'mono':
display_colors = 3
else:
display_colors = 2
imgbuf = self.canvas.convert('RGB').convert('P', palette=1, colors=display_colors)
if self._display_color == 'red':
imgbuf.putpalette([
255, 255, 255, # index 0 is white
0, 0, 0, # index 1 is black
255, 0, 0 # index 2 is red
])
elif self._display_color == 'yellow':
imgbuf.putpalette([
255, 255, 255, # index 0 is white
0, 0, 0, # index 1 is black
255, 255, 0 #index 2 is yellow
])
else:
imgbuf.putpalette([
255, 255, 255, # index 0 is white
0, 0, 0 # index 1 is black
])
self._display.set_image(imgbuf)
self._display.show()
else:
buf = self._display.getbuffer(self.canvas) buf = self._display.getbuffer(self.canvas)
self._display.displayPartial(buf) self._display.displayPartial(buf)

View File

@ -3,6 +3,6 @@ from PIL import ImageFont
PATH = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono' PATH = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono'
Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, 10) Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, 10)
BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, 9) BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, 8)
Medium = ImageFont.truetype("%s.ttf" % PATH, 10) Medium = ImageFont.truetype("%s.ttf" % PATH, 10)
Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, 35) Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, 25)

View File

@ -14,9 +14,6 @@ from pwnagotchi.ui.state import State
WHITE = 0xff WHITE = 0xff
BLACK = 0x00 BLACK = 0x00
WIDTH = 122
HEIGHT = 250
class View(object): class View(object):
def __init__(self, config, state={}): def __init__(self, config, state={}):
@ -24,6 +21,14 @@ class View(object):
self._config = config self._config = config
self._canvas = None self._canvas = None
self._lock = Lock() self._lock = Lock()
if config['ui']['display']['type'] == 'inkyphat':
self._width = 212
self._height = 104
else:
self._width = 250
self.heigth = 122
self._state = State(state={ self._state = State(state={
'channel': LabeledValue(color=BLACK, label='CH', value='00', position=(0, 0), label_font=fonts.Bold, 'channel': LabeledValue(color=BLACK, label='CH', value='00', position=(0, 0), label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
@ -31,27 +36,27 @@ class View(object):
text_font=fonts.Medium), text_font=fonts.Medium),
#'epoch': LabeledValue(color=BLACK, label='E', value='0000', position=(145, 0), label_font=fonts.Bold, #'epoch': LabeledValue(color=BLACK, label='E', value='0000', position=(145, 0), label_font=fonts.Bold,
# text_font=fonts.Medium), # text_font=fonts.Medium),
'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=(185, 0), label_font=fonts.Bold, 'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=(self._width - 65, 0), label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
# 'square': Rect([1, 11, 124, 111]), # 'square': Rect([1, 11, 124, 111]),
'line1': Line([0, 13, 250, 13], color=BLACK), 'line1': Line([0, int(self._height * .12), self._width, int(self._height * .12)], color=BLACK),
'line2': Line([0, 109, 250, 109], color=BLACK), 'line2': Line([0, self._height - int(self._height * .12), self._width, self._height - int(self._height * .12)], color=BLACK),
# 'histogram': Histogram([4, 94], color = BLACK), # 'histogram': Histogram([4, 94], color = BLACK),
'face': Text(value=faces.SLEEP, position=(0, 40), color=BLACK, font=fonts.Huge), 'face': Text(value=faces.SLEEP, position=(0, int(self._height / 4)), color=BLACK, font=fonts.Huge),
'friend_face': Text(value=None, position=(0, 90), font=fonts.Bold, color=BLACK), 'friend_face': Text(value=None, position=(0, 90), font=fonts.Bold, color=BLACK),
'friend_name': Text(value=None, position=(40, 93), font=fonts.BoldSmall, color=BLACK), 'friend_name': Text(value=None, position=(40, 93), font=fonts.BoldSmall, color=BLACK),
'name': Text(value='%s>' % 'pwnagotchi', position=(125, 20), color=BLACK, font=fonts.Bold), 'name': Text(value='%s>' % 'pwnagotchi', position=(int(self._width / 2) - 15, int(self._height * .15)), color=BLACK, font=fonts.Bold),
# 'face2': Bitmap( '/root/pwnagotchi/data/images/face_happy.bmp', (0, 20)), # 'face2': Bitmap( '/root/pwnagotchi/data/images/face_happy.bmp', (0, 20)),
'status': Text(value=voice.default(), position=(125, 35), color=BLACK, font=fonts.Medium), 'status': Text(value=voice.default(), position=(int(self._width /2) - 15, int(self._height * .30)), color=BLACK, font=fonts.Medium),
'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=(0, 110), label_font=fonts.Bold, 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=(0, self._height - int(self._height * .12) + 1), label_font=fonts.Bold,
text_font=fonts.Medium), text_font=fonts.Medium),
'mode': Text(value='AUTO', position=(225, 110), font=fonts.Bold, color=BLACK), 'mode': Text(value='AUTO', position=(self._width - 25, self._height - int(self._height * .12) + 1), font=fonts.Bold, color=BLACK),
}) })
for key, value in state.items(): for key, value in state.items():
@ -293,7 +298,7 @@ class View(object):
1 0.000 0.000 0.000 0.000 ImageMode.py:20(ModeDescriptor) 1 0.000 0.000 0.000 0.000 ImageMode.py:20(ModeDescriptor)
""" """
with self._lock: with self._lock:
self._canvas = Image.new('1', (HEIGHT, WIDTH), WHITE) self._canvas = Image.new('1', (self._width, self._height), WHITE)
drawer = ImageDraw.Draw(self._canvas) drawer = ImageDraw.Draw(self._canvas)
for key, lv in self._state.items(): for key, lv in self._state.items():

View File

@ -8,3 +8,4 @@ tensorflow
tweepy tweepy
file_read_backwards file_read_backwards
numpy numpy
inky