Live viewer now takes a screenshot once as second
This commit is contained in:
parent
f378f15c6c
commit
ebe6fab9c6
|
@ -12,3 +12,4 @@ logs.txt
|
||||||
rgb111-full.png
|
rgb111-full.png
|
||||||
state-new.json
|
state-new.json
|
||||||
settings.json
|
settings.json
|
||||||
|
screenshots/
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -59,6 +59,7 @@ class AsyncBotManager:
|
||||||
bits_on, bits_off, timestamp = data
|
bits_on, bits_off, timestamp = data
|
||||||
if timestamp < self._last_update:
|
if timestamp < self._last_update:
|
||||||
print("SKIPPING UPDATES: TOO OLD")
|
print("SKIPPING UPDATES: TOO OLD")
|
||||||
|
self._last_update: int = data["timestamp"]
|
||||||
for ndx in bits_on:
|
for ndx in bits_on:
|
||||||
y, x = divmod(ndx, 1000)
|
y, x = divmod(ndx, 1000)
|
||||||
self.canvas.putpixel((x, y), 255)
|
self.canvas.putpixel((x, y), 255)
|
||||||
|
@ -107,7 +108,7 @@ async def amain():
|
||||||
mgr.font = ImageFont.truetype(settings["font"], 8)
|
mgr.font = ImageFont.truetype(settings["font"], 8)
|
||||||
for elem in settings["elements"]:
|
for elem in settings["elements"]:
|
||||||
if elem["type"] == "text":
|
if elem["type"] == "text":
|
||||||
mgr.put_text(elem["text"], elem["x"], elem["y"])
|
mgr.put_text(elem["x"], elem["y"], elem["text"])
|
||||||
elif elem["type"] == "image":
|
elif elem["type"] == "image":
|
||||||
with Image.open(elem["path"]).convert("LA") as im:
|
with Image.open(elem["path"]).convert("LA") as im:
|
||||||
mgr.put_image(elem["x"], elem["y"], im)
|
mgr.put_image(elem["x"], elem["y"], im)
|
||||||
|
|
|
@ -4,10 +4,12 @@ from PIL import Image, ImageTk
|
||||||
from socketio import SimpleClient, exceptions
|
from socketio import SimpleClient, exceptions
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from requests import get
|
from requests import get
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
COLORS = [(0x33, 0x33, 0x66), (0x96, 0x96, 0xe0)]
|
COLORS = [(0x33, 0x33, 0x66), (0x96, 0x96, 0xe0)]
|
||||||
COLORS_UNPACKED = COLORS[0] + ((0, 0, 0) * 254) + COLORS[1]
|
COLORS_UNPACKED = COLORS[0] + ((0, 0, 0) * 254) + COLORS[1]
|
||||||
|
|
||||||
|
SCREENSHOTS_TMPL = "./screenshots/%Y%m%d_%H%M%S.png"
|
||||||
|
|
||||||
class App(tk.Tk):
|
class App(tk.Tk):
|
||||||
def __init__(self, url: str = "https://onemillioncheckboxes.com") -> None:
|
def __init__(self, url: str = "https://onemillioncheckboxes.com") -> None:
|
||||||
|
@ -22,6 +24,8 @@ class App(tk.Tk):
|
||||||
self._canvas.pack()
|
self._canvas.pack()
|
||||||
self.config(width=1000, height=1000, borderwidth=0, highlightthickness=0)
|
self.config(width=1000, height=1000, borderwidth=0, highlightthickness=0)
|
||||||
|
|
||||||
|
self._last_update = 0
|
||||||
|
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
self._image = Image.new("RGB", (1000, 1000), COLORS[0])
|
self._image = Image.new("RGB", (1000, 1000), COLORS[0])
|
||||||
|
@ -38,15 +42,25 @@ class App(tk.Tk):
|
||||||
x, y = event.x, event.y
|
x, y = event.x, event.y
|
||||||
self.sio.emit("toggle_bit", { "index": x + y * 1000 })
|
self.sio.emit("toggle_bit", { "index": x + y * 1000 })
|
||||||
|
|
||||||
|
def _save_image(self):
|
||||||
|
ts = datetime.fromtimestamp(self._last_update / 1000)
|
||||||
|
path = ts.strftime(SCREENSHOTS_TMPL)
|
||||||
|
print("SAVED", path)
|
||||||
|
self._image.save(path)
|
||||||
|
|
||||||
|
self.after(1000, self._save_image)
|
||||||
|
|
||||||
def _on_key_down(self, event: tk.Event):
|
def _on_key_down(self, event: tk.Event):
|
||||||
# <KeyPress event state=Control keysym=r keycode=27 char='\x12' x=538 y=556>
|
# <KeyPress event state=Control keysym=r keycode=27 char='\x12' x=538 y=556>
|
||||||
if event.keysym == "r":
|
if event.keysym == "r":
|
||||||
print("FULL REFRESH")
|
print("FULL REFRESH")
|
||||||
with get(f"{self.url}/api/initial-state") as req:
|
with get(f"{self.url}/api/initial-state") as req:
|
||||||
buffer = b64decode(req.json()["full_state"].encode() + b"=")
|
data = req.json()
|
||||||
|
buffer = b64decode(data["full_state"].encode() + b"=")
|
||||||
img = Image.frombytes("1", (1000, 1000), buffer).convert("P")
|
img = Image.frombytes("1", (1000, 1000), buffer).convert("P")
|
||||||
img.putpalette(COLORS_UNPACKED)
|
img.putpalette(COLORS_UNPACKED)
|
||||||
self._image.paste(img.convert("RGB"))
|
self._image.paste(img.convert("RGB"))
|
||||||
|
self._last_update = data["timestamp"]
|
||||||
print("FULL REFRESH DONE")
|
print("FULL REFRESH DONE")
|
||||||
|
|
||||||
def _reader(self):
|
def _reader(self):
|
||||||
|
@ -59,6 +73,10 @@ class App(tk.Tk):
|
||||||
|
|
||||||
if name == "batched_bit_toggles":
|
if name == "batched_bit_toggles":
|
||||||
bits_on, bits_off, timestamp = data
|
bits_on, bits_off, timestamp = data
|
||||||
|
if timestamp < self._last_update:
|
||||||
|
print("SKIP partial updates: too old")
|
||||||
|
continue
|
||||||
|
self._last_update = timestamp
|
||||||
for ndx in bits_on:
|
for ndx in bits_on:
|
||||||
y, x = divmod(ndx, 1000)
|
y, x = divmod(ndx, 1000)
|
||||||
self._image.putpixel((x, y), COLORS[1])
|
self._image.putpixel((x, y), COLORS[1])
|
||||||
|
@ -92,7 +110,9 @@ class App(tk.Tk):
|
||||||
self.sio.connect(f"{self.url}/socket.io")
|
self.sio.connect(f"{self.url}/socket.io")
|
||||||
|
|
||||||
with get(f"{self.url}/api/initial-state") as req:
|
with get(f"{self.url}/api/initial-state") as req:
|
||||||
buffer = b64decode(req.json()["full_state"].encode() + b"=")
|
data = req.json()
|
||||||
|
buffer = b64decode(data["full_state"].encode() + b"=")
|
||||||
|
self._last_update = data["timestamp"]
|
||||||
img = Image.frombytes("1", (1000, 1000), buffer).convert("P")
|
img = Image.frombytes("1", (1000, 1000), buffer).convert("P")
|
||||||
img.putpalette(COLORS_UNPACKED)
|
img.putpalette(COLORS_UNPACKED)
|
||||||
self._image.paste(img.convert("RGB"))
|
self._image.paste(img.convert("RGB"))
|
||||||
|
@ -104,6 +124,7 @@ class App(tk.Tk):
|
||||||
self._reader_thr.start()
|
self._reader_thr.start()
|
||||||
|
|
||||||
self.protocol("WM_DELETE_WINDOW", self._close)
|
self.protocol("WM_DELETE_WINDOW", self._close)
|
||||||
|
self.after(1000, self._save_image)
|
||||||
self.mainloop()
|
self.mainloop()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in New Issue