# Integrationen **Revision:** r1 **Source:** CLAUDE.md, trixy_core/network/, trixy_core/plugins/ **Last updated:** 2026-01-31 12:35 --- ## Trixy-Protokoll ### Nachrichtenstruktur ``` ┌─────────┬──────────┬───────────┬───────────┬──────────┬───────────────┬─────────────┬──────────┐ │ Magic │ Version │ Timestamp │ Flags │ Checksum │ ClassNameLen │ ClassName │ Data │ │ 4 bytes │ 2 bytes │ 8 bytes │ 4 bytes │ 16 bytes│ 2 bytes │ variable │ variable │ └─────────┴──────────┴───────────┴───────────┴──────────┴───────────────┴─────────────┴──────────┘ ``` | Feld | Beschreibung | |------|--------------| | Magic | `TRXI` (4 bytes) | | Version | Major.Minor (je 1 byte) | | Timestamp | Unix-Zeit in ms (8 bytes) | | Flags | ProtocolFlags (32-bit) | | Checksum | MD5 der Daten (16 bytes) | | ClassNameLen | Länge des Klassennamens | | ClassName | Name der Nachrichtenklasse | | Data | Serialisierte Daten | ### ProtocolFlags | Flag | Bit | Beschreibung | |------|-----|--------------| | COMPRESSED | 0 | Daten komprimiert (zlib) | | ENCRYPTED | 1 | AES-256-GCM verschlüsselt | | JSON | 2 | JSON-Format | | ACK_REQUIRED | 3 | Bestätigung erforderlich | | BASE64 | 4 | Base64-kodiert | | MULTIPART | 5 | Teil einer Mehrteiligen Nachricht | | DICT | 6 | Dictionary-Daten | | SILENT | 7 | Kein Logging | | PICKLE | 8 | Pickle-serialisiert | | RESPONSE | 9 | Ist Antwort | | ERROR | 10 | Enthält Fehlerdaten | | BINARY | 11 | Rohe Binärdaten | ### Hard-coded Befehle Für Effizienz werden diese Befehle direkt gesendet (8 bytes): | Befehl | Bytes | Verwendung | |--------|-------|------------| | TRXINOOP | `54 52 58 49 4E 4F 4F 50` | Keine Operation | | TRXIPING | `54 52 58 49 50 49 4E 47` | Ping-Anfrage | | TRXIPONG | `54 52 58 49 50 4F 4E 47` | Ping-Antwort | | TRXIPRNT | `54 52 58 49 50 52 4E 54` | Debug-Ausgabe | | TRXYHELO | `54 52 58 59 48 45 4C 4F` | Handshake | ## Verschlüsselung ### AES-256-GCM ```python class TrixyEncryption: NONCE_SIZE = 12 KEY_SIZE = 32 # 256 bit def encrypt(plaintext: bytes, associated_data: bytes | None) -> bytes # Gibt zurück: Nonce (12 bytes) + Ciphertext + Tag (16 bytes) def decrypt(ciphertext: bytes, associated_data: bytes | None) -> bytes def save_key(path: Path) -> None @classmethod def load_key(path: Path) -> TrixyEncryption @classmethod def load_or_create(path: Path) -> TrixyEncryption ``` ## Plugin-System ### Plugin-Verzeichnisstruktur ``` plugins/ └── mein_plugin/ ├── main.py # Plugin-Klasse └── config.json # Plugin-Konfiguration ``` ### Plugin-Entwicklung ```python from trixy_core.plugins import TrixyPlugin class MeinPlugin(TrixyPlugin): NAME = "MeinPlugin" VERSION = "1.0.0" DESCRIPTION = "Beschreibung" AUTHOR = "Autor" async def on_load(self): # Wird beim Laden aufgerufen pass async def on_unload(self): # Wird beim Entladen aufgerufen pass @TrixyEvent(["wakeword_received"]) def on_wakeword(self, event_name, event_data): # Event-Handler pass ``` ### Plugin-Konfiguration (config.json) ```json { "enabled": true, "setting1": "value1", "nested": { "key": "value" } } ``` ### PluginManager API ```python manager = PluginManager(application, directory="plugins") await manager.load_all() # Alle Plugins laden await manager.load("plugin_name") # Einzelnes Plugin await manager.unload("PluginName") # Plugin entladen await manager.reload("plugin_name") # Neu laden await manager.enable("PluginName") # Aktivieren await manager.disable("PluginName") # Deaktivieren plugin = manager.get("PluginName") plugins = manager.get_all() enabled = manager.get_enabled() failed = manager.get_failed() # dict[name, error] ``` ## Audio-Streaming | Stream | Port | Format | Sample Rate | Channels | |--------|------|--------|-------------|----------| | Audio Input | 2102 | 16-bit PCM | 16 kHz | 1 (mono) | | Audio Output | 2103 | 16-bit PCM | 16 kHz | 1 (mono) | | Music | 2104 | 16-bit PCM | 48 kHz | 2 (stereo) | --- **See also:** [architecture.md](architecture.md), [workflows.md](workflows.md)