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