61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
#!/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()
|