Initial commit: Javis project
This commit is contained in:
commit
435c645f36
164 files changed
+35279
No files matched your search
@@ -0,0 +1,90 @@
|
||||
"""Slave-local configuration: master address, credentials, audio devices.
|
||||
|
||||
Persisted to ``%LOCALAPPDATA%/JavisSlave/slave_config.json`` (or
|
||||
``~/.javis-slave/slave_config.json`` on non-Windows). Set
|
||||
``JAVIS_SLAVE_CONFIG_DIR`` to override (useful for systemd services).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def config_dir() -> Path:
|
||||
override = os.environ.get("JAVIS_SLAVE_CONFIG_DIR")
|
||||
if override:
|
||||
return Path(override).expanduser()
|
||||
base = os.environ.get("LOCALAPPDATA")
|
||||
if base:
|
||||
return Path(base) / "JavisSlave"
|
||||
return Path.home() / ".javis-slave"
|
||||
|
||||
|
||||
def config_path() -> Path:
|
||||
return config_dir() / "slave_config.json"
|
||||
|
||||
|
||||
@dataclass
|
||||
class WakeWordSettings:
|
||||
"""Wake-word block received from the master."""
|
||||
model: str = "hey_jarvis"
|
||||
threshold: float = 0.5
|
||||
vad_threshold: float = 0.5
|
||||
silence_ms: int = 800
|
||||
|
||||
|
||||
@dataclass
|
||||
class SlaveConfig:
|
||||
device_id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
||||
device_name: str = ""
|
||||
master_host: str = ""
|
||||
master_port: int = 8765
|
||||
api_key: str = ""
|
||||
room: Optional[str] = None # cached; refreshed from master
|
||||
input_device: Optional[int] = None
|
||||
output_device: Optional[int] = None
|
||||
input_gain: float = 1.0
|
||||
sample_rate: int = 16000
|
||||
wake_word: WakeWordSettings = field(default_factory=WakeWordSettings)
|
||||
# Local MCP control server bind (review A-6: was hardcoded to 127.0.0.1,
|
||||
# unreachable by remote controllers). 0.0.0.0 lets other devices reach it.
|
||||
api_host: str = "0.0.0.0"
|
||||
api_port: int = 8766
|
||||
|
||||
@property
|
||||
def paired(self) -> bool:
|
||||
return bool(self.master_host and self.api_key)
|
||||
|
||||
@property
|
||||
def base_url(self) -> str:
|
||||
return f"http://{self.master_host}:{self.master_port}"
|
||||
|
||||
|
||||
def load_config() -> SlaveConfig:
|
||||
path = config_path()
|
||||
cfg = SlaveConfig()
|
||||
if path.exists():
|
||||
try:
|
||||
raw = json.loads(path.read_text(encoding="utf-8"))
|
||||
ww_raw = raw.pop("wake_word", {}) or {}
|
||||
for key, val in raw.items():
|
||||
if hasattr(cfg, key) and key != "wake_word":
|
||||
setattr(cfg, key, val)
|
||||
for key, val in ww_raw.items():
|
||||
if hasattr(cfg.wake_word, key):
|
||||
setattr(cfg.wake_word, key, val)
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
return cfg
|
||||
|
||||
|
||||
def save_config(cfg: SlaveConfig) -> None:
|
||||
path = config_path()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = path.with_suffix(".tmp")
|
||||
tmp.write_text(json.dumps(asdict(cfg), indent=2), encoding="utf-8")
|
||||
tmp.replace(path)
|
||||
Reference in new issue
Block a user