2019-09-30 11:21:15 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import argparse
|
|
|
|
import yaml
|
2019-10-01 18:56:27 +02:00
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
sys.path.insert(0,
|
|
|
|
os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
2019-10-06 08:55:51 +02:00
|
|
|
'../'))
|
2019-09-30 11:21:15 +02:00
|
|
|
|
2019-10-06 19:59:03 +02:00
|
|
|
import pwnagotchi.ui.faces as faces
|
2019-10-27 15:43:42 +00:00
|
|
|
from pwnagotchi.ui.display import Display
|
2019-10-06 00:14:09 +02:00
|
|
|
from PIL import Image
|
2019-10-01 18:56:27 +02:00
|
|
|
|
2019-10-06 00:27:21 +02:00
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
class CustomDisplay(Display):
|
|
|
|
|
2019-10-06 00:14:09 +02:00
|
|
|
def __init__(self, config, state):
|
|
|
|
self.last_image = None
|
|
|
|
super(CustomDisplay, self).__init__(config, state)
|
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
def _http_serve(self):
|
2019-10-06 00:14:09 +02:00
|
|
|
# do nothing
|
|
|
|
pass
|
2019-09-30 11:21:15 +02:00
|
|
|
|
|
|
|
def _on_view_rendered(self, img):
|
2019-10-06 00:14:09 +02:00
|
|
|
self.last_image = img
|
2019-09-30 11:21:15 +02:00
|
|
|
|
2019-10-06 00:14:09 +02:00
|
|
|
def get_image(self):
|
|
|
|
"""
|
|
|
|
Return the saved image
|
|
|
|
"""
|
|
|
|
return self.last_image
|
2019-09-30 11:21:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
class DummyPeer:
|
2019-10-06 19:59:03 +02:00
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.rssi = -50
|
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
@staticmethod
|
|
|
|
def name():
|
|
|
|
return "beta"
|
|
|
|
|
2019-10-06 19:59:03 +02:00
|
|
|
@staticmethod
|
|
|
|
def pwnd_run():
|
|
|
|
return 50
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def pwnd_total():
|
|
|
|
return 100
|
|
|
|
|
2019-10-27 15:43:42 +00:00
|
|
|
@staticmethod
|
|
|
|
def first_encounter():
|
|
|
|
return 1
|
|
|
|
|
2019-10-06 19:59:03 +02:00
|
|
|
@staticmethod
|
|
|
|
def face():
|
|
|
|
return faces.FRIEND
|
|
|
|
|
2019-10-06 00:27:21 +02:00
|
|
|
|
2019-10-06 00:14:09 +02:00
|
|
|
def append_images(images, horizontal=True, xmargin=0, ymargin=0):
|
|
|
|
w, h = zip(*(i.size for i in images))
|
|
|
|
|
|
|
|
if horizontal:
|
|
|
|
t_w = sum(w)
|
|
|
|
t_h = max(h)
|
|
|
|
else:
|
|
|
|
t_w = max(w)
|
|
|
|
t_h = sum(h)
|
|
|
|
|
|
|
|
result = Image.new('RGB', (t_w, t_h))
|
|
|
|
|
|
|
|
x_offset = 0
|
|
|
|
y_offset = 0
|
|
|
|
|
|
|
|
for im in images:
|
2019-10-06 00:27:21 +02:00
|
|
|
result.paste(im, (x_offset, y_offset))
|
|
|
|
if horizontal:
|
|
|
|
x_offset += im.size[0] + xmargin
|
|
|
|
else:
|
|
|
|
y_offset += im.size[1] + ymargin
|
2019-10-06 00:14:09 +02:00
|
|
|
|
|
|
|
return result
|
2019-09-30 11:21:15 +02:00
|
|
|
|
2019-10-06 00:27:21 +02:00
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(description="This program emulates\
|
|
|
|
the pwnagotchi display")
|
2019-10-30 01:05:58 +00:00
|
|
|
parser.add_argument('--displays', help="Which displays to use.", nargs="+", default=["waveshare_2"])
|
2019-09-30 11:21:15 +02:00
|
|
|
parser.add_argument('--lang', help="Language to use",
|
|
|
|
default="en")
|
2019-10-06 00:14:09 +02:00
|
|
|
parser.add_argument('--output', help="Path to output image (PNG)", default="preview.png")
|
2019-10-06 19:59:03 +02:00
|
|
|
parser.add_argument('--show-peer', dest="showpeer", help="This options will show a dummy peer", action="store_true")
|
|
|
|
parser.add_argument('--xmargin', help="Add X-Margin", type=int, default=5)
|
|
|
|
parser.add_argument('--ymargin', help="Add Y-Margin", type=int, default=5)
|
2019-09-30 11:21:15 +02:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2019-10-06 00:14:09 +02:00
|
|
|
config_template = '''
|
2019-09-30 11:21:15 +02:00
|
|
|
main:
|
|
|
|
lang: {lang}
|
|
|
|
ui:
|
|
|
|
fps: 0.3
|
|
|
|
display:
|
|
|
|
enabled: false
|
|
|
|
rotation: 180
|
|
|
|
color: black
|
|
|
|
refresh: 30
|
|
|
|
type: {display}
|
|
|
|
video:
|
|
|
|
enabled: true
|
2019-10-01 18:56:27 +02:00
|
|
|
address: "0.0.0.0"
|
2019-10-06 00:14:09 +02:00
|
|
|
port: 8080
|
2019-10-27 15:43:42 +00:00
|
|
|
|
|
|
|
faces:
|
|
|
|
look_r: '( ⚆_⚆)'
|
|
|
|
look_l: '(☉_☉ )'
|
|
|
|
look_r_happy: '( ◕‿◕)'
|
|
|
|
look_l_happy: '(◕‿◕ )'
|
|
|
|
sleep: '(⇀‿‿↼)'
|
|
|
|
sleep2: '(≖‿‿≖)'
|
|
|
|
awake: '(◕‿‿◕)'
|
|
|
|
bored: '(-__-)'
|
|
|
|
intense: '(°▃▃°)'
|
|
|
|
cool: '(⌐■_■)'
|
|
|
|
happy: '(•‿‿•)'
|
|
|
|
excited: '(ᵔ◡◡ᵔ)'
|
|
|
|
grateful: '(^‿‿^)'
|
|
|
|
motivated: '(☼‿‿☼)'
|
|
|
|
demotivated: '(≖__≖)'
|
|
|
|
smart: '(✜‿‿✜)'
|
|
|
|
lonely: '(ب__ب)'
|
|
|
|
sad: '(╥☁╥ )'
|
|
|
|
friend: '(♥‿‿♥)'
|
|
|
|
broken: '(☓‿‿☓)'
|
|
|
|
debug: '(#__#)'
|
2019-10-06 00:14:09 +02:00
|
|
|
'''
|
|
|
|
|
|
|
|
list_of_displays = list()
|
|
|
|
for display_type in args.displays:
|
|
|
|
config = yaml.safe_load(config_template.format(display=display_type,
|
2019-10-06 00:27:21 +02:00
|
|
|
lang=args.lang))
|
2019-10-06 00:14:09 +02:00
|
|
|
display = CustomDisplay(config=config, state={'name': f"{display_type}>"})
|
|
|
|
list_of_displays.append(display)
|
|
|
|
|
|
|
|
columns = list()
|
|
|
|
|
|
|
|
for display in list_of_displays:
|
|
|
|
emotions = list()
|
2019-10-06 19:59:03 +02:00
|
|
|
if args.showpeer:
|
2019-10-07 18:42:57 +02:00
|
|
|
display.set_closest_peer(DummyPeer(), 10)
|
2019-10-06 00:14:09 +02:00
|
|
|
display.on_starting()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_ai_ready()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_normal()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_new_peer(DummyPeer())
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_lost_peer(DummyPeer())
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_free_channel('6')
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.wait(2)
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_bored()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_sad()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_motivated(1)
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_demotivated(-1)
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_excited()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'})
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_miss('test')
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_lonely()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_handshakes(1)
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
display.on_rebooting()
|
|
|
|
display.update()
|
|
|
|
emotions.append(display.get_image())
|
|
|
|
|
|
|
|
# append them all together (vertical)
|
|
|
|
columns.append(append_images(emotions, horizontal=False, xmargin=args.xmargin, ymargin=args.ymargin))
|
|
|
|
|
|
|
|
# append columns side by side
|
|
|
|
final_image = append_images(columns, horizontal=True, xmargin=args.xmargin, ymargin=args.ymargin)
|
|
|
|
final_image.save(args.output, 'PNG')
|
2019-09-30 11:21:15 +02:00
|
|
|
|
2019-10-06 00:27:21 +02:00
|
|
|
|
2019-09-30 11:21:15 +02:00
|
|
|
if __name__ == '__main__':
|
|
|
|
SystemExit(main())
|