annotate web_to_mqtt.py @ 4:e273cc60b389

draft of web-to-lcd and simulator
author drewp@bigasterisk.com
date Tue, 05 Mar 2024 18:12:15 -0800
parents
children d97a5930db7e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
1 import asyncio
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
2 import base64
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
3 import io
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
4 import subprocess
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
5 import tempfile
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
6
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
7 import aiomqtt
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
8 from PIL import Image, ImageChops
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
9
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
10
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
11 class WebRenderer:
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
12 def __init__(self):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
13 self.chrome_proc = subprocess.Popen(["google-chrome"])
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
14 print("Chrome subprocess started.")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
15
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
16 def capture_screenshot(self, url, output_path):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
17 out = tempfile.NamedTemporaryFile(suffix=".png")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
18 screenshot_command = [
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
19 "google-chrome",
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
20 "--headless",
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
21 f"--screenshot={out.name}",
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
22 url,
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
23 ]
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
24 subprocess.run(screenshot_command)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
25 return Image.open(out.name)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
26
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
27
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
28
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
29 async def render_webpage_to_png():
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
30 # Code to render the webpage to a PNG
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
31 # Replace this with your actual code to render the webpage to a PNG
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
32 # For example, you can use libraries like Selenium or requests-html to render the webpage and capture a screenshot
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
33 pass
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
34
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
35
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
36 async def check_for_changes(renderer, last_image):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
37
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
38 renderer.capture_screenshot("https://en.wikipedia.org", "/tmp/output.png")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
39
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
40 current_image = await render_webpage_to_png()
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
41 if last_image is not None:
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
42 diff_image = ImageChops.difference(last_image, current_image)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
43 # Iterate over 64x64 pixel squares and check for changes
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
44 for y in range(0, diff_image.height, 64):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
45 for x in range(0, diff_image.width, 64):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
46 box = (x, y, x + 64, y + 64)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
47 region = diff_image.crop(box)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
48 if (region.getbbox()
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
49 ): # Check if region is not empty (i.e., contains changes)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
50 # Send changed square as MQTT message
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
51 queue these
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
52 await send_mqtt_message(region)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
53 return current_image
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
54
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
55
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
56 async def send_mqtt_message(region):
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
57 # Convert changed region to base64 encoded string
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
58 buffer = io.BytesIO()
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
59 region.save(buffer, format="PNG")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
60 base64_image = base64.b64encode(buffer.getvalue()).decode("utf-8")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
61 mqtt_client = aiomqtt.Client("mqtt_client")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
62 await mqtt_client.connect("mqtt://broker.example.com")
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
63 await mqtt_client.publish("changed_squares", base64_image, qos=1)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
64 await mqtt_client.disconnect()
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
65
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
66
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
67 async def main():
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
68 # also listen for dirty msgs from the web page; see ts
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
69 renderer = WebRenderer()
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
70 async with aiomqtt.Client("mqtt_client") as client:
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
71 last_image = None
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
72 while True:
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
73 last_image = await check_for_changes(renderer,last_image)
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
74 await asyncio.sleep(2) # Adjust the interval as needed
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
75
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
76
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
77 if __name__ == "__main__":
e273cc60b389 draft of web-to-lcd and simulator
drewp@bigasterisk.com
parents:
diff changeset
78 asyncio.run(main())