config.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. """Configuration loader for SpoolBuddy daemon.
  2. All configuration is via environment variables. The systemd service file
  3. or a shell wrapper sets these before launching the daemon.
  4. Required:
  5. SPOOLBUDDY_BACKEND_URL — Bambuddy server URL (e.g. http://192.168.1.100:5000)
  6. SPOOLBUDDY_API_KEY — API key created in Bambuddy Settings → API Keys
  7. Optional:
  8. SPOOLBUDDY_DEVICE_ID — Unique device identifier (default: derived from MAC)
  9. SPOOLBUDDY_HOSTNAME — Display name (default: system hostname)
  10. """
  11. import os
  12. import socket
  13. from dataclasses import dataclass
  14. from pathlib import Path
  15. @dataclass
  16. class Config:
  17. backend_url: str = ""
  18. api_key: str = ""
  19. device_id: str = ""
  20. hostname: str = ""
  21. nfc_poll_interval: float = 0.3
  22. scale_read_interval: float = 0.1
  23. scale_report_interval: float = 1.0
  24. heartbeat_interval: float = 10.0
  25. stability_threshold: float = 2.0
  26. stability_window: float = 1.0
  27. tare_offset: int = 0
  28. calibration_factor: float = 1.0
  29. @classmethod
  30. def load(cls) -> "Config":
  31. cfg = cls()
  32. cfg.backend_url = os.environ.get("SPOOLBUDDY_BACKEND_URL", "")
  33. cfg.api_key = os.environ.get("SPOOLBUDDY_API_KEY", "")
  34. cfg.device_id = os.environ.get("SPOOLBUDDY_DEVICE_ID", "")
  35. cfg.hostname = os.environ.get("SPOOLBUDDY_HOSTNAME", "")
  36. if not cfg.backend_url:
  37. raise RuntimeError("SPOOLBUDDY_BACKEND_URL is required (e.g. http://192.168.1.100:5000)")
  38. if not cfg.api_key:
  39. raise RuntimeError("SPOOLBUDDY_API_KEY is required (create one in Bambuddy Settings → API Keys)")
  40. # Default device_id from MAC address
  41. if not cfg.device_id:
  42. cfg.device_id = _get_mac_id()
  43. # Default hostname from system
  44. if not cfg.hostname:
  45. cfg.hostname = socket.gethostname()
  46. return cfg
  47. def _get_mac_id() -> str:
  48. """Generate a device ID from the primary network interface MAC address."""
  49. try:
  50. for iface in Path("/sys/class/net").iterdir():
  51. if iface.name == "lo":
  52. continue
  53. addr_file = iface / "address"
  54. if addr_file.exists():
  55. mac = addr_file.read_text().strip().replace(":", "")
  56. if mac and mac != "000000000000":
  57. return f"sb-{mac}"
  58. except Exception:
  59. pass
  60. import uuid
  61. return f"sb-{uuid.uuid4().hex[:12]}"