#!/usr/bin/env python3 """ HomeAI Reminder Daemon — checks ~/homeai-data/reminders.json every 60s and fires TTS via POST http://localhost:8081/api/tts when reminders are due. """ import json import os import time import urllib.request from datetime import datetime REMINDERS_FILE = os.path.expanduser("~/homeai-data/reminders.json") TTS_URL = "http://localhost:8081/api/tts" CHECK_INTERVAL = 60 # seconds def load_reminders(): try: with open(REMINDERS_FILE) as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError): return {"reminders": []} def save_reminders(data): with open(REMINDERS_FILE, "w") as f: json.dump(data, f, indent=2) def fire_tts(message): """Speak reminder via the OpenClaw bridge TTS endpoint.""" try: payload = json.dumps({"text": f"Reminder: {message}"}).encode() req = urllib.request.Request( TTS_URL, data=payload, headers={"Content-Type": "application/json"}, method="POST" ) urllib.request.urlopen(req, timeout=30) print(f"[{datetime.now().isoformat()}] TTS fired: {message}") return True except Exception as e: print(f"[{datetime.now().isoformat()}] TTS error: {e}") return False def check_reminders(): data = load_reminders() now = datetime.now() changed = False for r in data.get("reminders", []): if r.get("fired"): continue try: due = datetime.fromisoformat(r["due_at"]) except (KeyError, ValueError): continue if now >= due: print(f"[{now.isoformat()}] Reminder due: {r.get('message', '?')}") fire_tts(r["message"]) r["fired"] = True changed = True if changed: # Clean up fired reminders older than 24h cutoff = (now.timestamp() - 86400) * 1000 data["reminders"] = [ r for r in data["reminders"] if not r.get("fired") or int(r.get("id", "0")) > cutoff ] save_reminders(data) def main(): print(f"[{datetime.now().isoformat()}] Reminder daemon started (check every {CHECK_INTERVAL}s)") while True: try: check_reminders() except Exception as e: print(f"[{datetime.now().isoformat()}] Error: {e}") time.sleep(CHECK_INTERVAL) if __name__ == "__main__": main()