# Architecture ## Module Structure ``` lego-dimensions-reader/ ├── lego_dimensions_reader.py # Core portal communication ├── moonlight_integration.py # Video player integration ├── character_database.json # Character/vehicle ID mappings ├── requirements.txt # Python dependencies └── .claude-context/ # Session history ``` ## Core Classes ### `LegoDimensionsReader` Event-driven portal interface with callbacks: - `on_tag_insert(TagInfo)` — fired when disc placed - `on_tag_remove(TagInfo)` — fired when disc removed - `on_connect()` / `on_disconnect()` — portal connection state - `on_error(Exception)` — error handling ### `TagInfo` (dataclass) - `uid: bytes` — 7-byte NFC tag UID - `pad: Pad` — CENTER, LEFT, or RIGHT - `event: TagEvent` — INSERTED or REMOVED - `character_id: Optional[int]` — decrypted ID (if available) - `character_name: Optional[str]` — looked up from database ## USB Protocol **Endpoints:** - OUT: 0x01 — commands to portal - IN: 0x81 — events from portal (32-byte interrupt packets) **Command structure:** ``` [0x55, length, cmd_type, cmd_id, ...payload, checksum, ...padding] ``` **Tag event packet (0x56):** ``` [0x56, ??, pad_num, ??, ??, action, uid[0:7], ...] ``` ## Platform Support | Platform | Backend | Driver Setup | |----------|---------|--------------| | Linux | libusb (native) | udev rules for non-root access | | Windows | libusb-win32 via WinUSB | Zadig to replace HID driver | | macOS | libusb (homebrew) | Should work, untested | ## Dependencies - `pyusb` — USB device communication - `libusb` (on Windows) — provides backend DLL --- *Last updated: 2026-09-23*