Add jailbroken iPhone MCP screen app
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Minimal Hermes-compatible voice endpoint for iPhone integration testing."""
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import math
|
||||
import struct
|
||||
import wave
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
|
||||
|
||||
def response_wav() -> bytes:
|
||||
output = io.BytesIO()
|
||||
with wave.open(output, "wb") as wav:
|
||||
wav.setnchannels(1)
|
||||
wav.setsampwidth(2)
|
||||
wav.setframerate(16000)
|
||||
frames = bytearray()
|
||||
for index in range(int(16000 * 0.3)):
|
||||
sample = int(7000 * math.sin(2 * math.pi * 660 * index / 16000))
|
||||
frames.extend(struct.pack("<h", sample))
|
||||
wav.writeframes(frames)
|
||||
return output.getvalue()
|
||||
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
if self.path != "/api/esp32/voice":
|
||||
self.send_error(404)
|
||||
return
|
||||
length = int(self.headers.get("Content-Length", "0"))
|
||||
received = self.rfile.read(length)
|
||||
print(f"received {len(received)} bytes from {self.headers.get('X-Device-ID', 'unknown')}", flush=True)
|
||||
payload = response_wav()
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "audio/wav")
|
||||
self.send_header("Content-Length", str(len(payload)))
|
||||
self.send_header("X-Hermes-Transcript", "Mock voice request received")
|
||||
self.send_header("X-Hermes-Text-Response", "The iPhone Hermes integration is working")
|
||||
self.send_header("X-Hermes-Response-Id", "mock-response")
|
||||
self.send_header("X-Hermes-Conversation", "iphone-test")
|
||||
self.end_headers()
|
||||
self.wfile.write(payload)
|
||||
|
||||
def log_message(self, message, *args):
|
||||
print(message % args, flush=True)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--host", default="0.0.0.0")
|
||||
parser.add_argument("--port", type=int, default=8765)
|
||||
args = parser.parse_args()
|
||||
server = ThreadingHTTPServer((args.host, args.port), Handler)
|
||||
print(f"mock Hermes gateway listening on {args.host}:{args.port}", flush=True)
|
||||
server.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Stream a generated RGB565 color animation to iPhone MCP TCP port 8083."""
|
||||
|
||||
import argparse
|
||||
import socket
|
||||
import struct
|
||||
import time
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
|
||||
def rgb565be(image: Image.Image) -> bytes:
|
||||
image = image.convert("RGB")
|
||||
output = bytearray(image.width * image.height * 2)
|
||||
for index, (red, green, blue) in enumerate(image.getdata()):
|
||||
value = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3)
|
||||
output[index * 2] = value >> 8
|
||||
output[index * 2 + 1] = value & 0xFF
|
||||
return bytes(output)
|
||||
|
||||
|
||||
def send_frame(sock: socket.socket, image: Image.Image) -> None:
|
||||
payload = rgb565be(image)
|
||||
header = struct.pack(">4sBBHHIH", b"IMCR", 1, 1, image.width, image.height, len(payload), 0)
|
||||
sock.sendall(header + payload)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--ip", required=True, help="iPhone Wi-Fi IP")
|
||||
parser.add_argument("--port", type=int, default=8083)
|
||||
parser.add_argument("--width", type=int, default=400)
|
||||
parser.add_argument("--height", type=int, default=300)
|
||||
args = parser.parse_args()
|
||||
|
||||
with socket.create_connection((args.ip, args.port), timeout=8) as sock:
|
||||
frame = 0
|
||||
while True:
|
||||
hue = (frame * 4) % 256
|
||||
image = Image.new("RGB", (args.width, args.height), (12, 18, 35))
|
||||
draw = ImageDraw.Draw(image)
|
||||
for x in range(args.width):
|
||||
red = (x * 255 // max(1, args.width - 1) + hue) % 256
|
||||
blue = 255 - (x * 255 // max(1, args.width - 1))
|
||||
draw.line((x, 0, x, args.height - 1), fill=(red, 70, blue))
|
||||
draw.rounded_rectangle((20, 20, args.width - 20, args.height - 20), radius=22,
|
||||
outline=(255, 255, 255), width=4)
|
||||
draw.text((40, 45), "iPhone MCP RGB565", fill=(255, 255, 255))
|
||||
draw.text((40, 72), f"Frame {frame}", fill=(255, 240, 80))
|
||||
send_frame(sock, image)
|
||||
frame += 1
|
||||
time.sleep(1 / 20)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user