odoo_mqtt/iot_bridge/config/schema.py

112 lines
5.1 KiB
Python

"""Configuration schema for IoT Bridge using Pydantic."""
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class MQTTConfig(BaseModel):
"""MQTT Broker configuration."""
broker: str = Field(default="localhost", description="MQTT broker hostname")
port: int = Field(default=1883, ge=1, le=65535, description="MQTT broker port")
username: str | None = Field(default=None, description="MQTT username (optional)")
password: str | None = Field(default=None, description="MQTT password (optional)")
client_id: str = Field(default="iot_bridge", description="MQTT client ID")
keepalive: int = Field(default=60, ge=1, description="MQTT keepalive interval (s)")
use_tls: bool = Field(default=False, description="Use TLS/SSL for MQTT connection")
class OdooConfig(BaseModel):
"""Odoo connection configuration."""
base_url: str | None = Field(default=None, description="Odoo base URL")
database: str | None = Field(default=None, description="Odoo database name")
username: str | None = Field(default=None, description="Odoo username")
api_key: str | None = Field(default=None, description="Odoo API key")
use_mock: bool = Field(default=True, description="Use mock Odoo client for testing")
mock_failure_rate: float = Field(
default=0.0, ge=0.0, le=1.0, description="Mock failure rate for testing (0.0-1.0)"
)
class LoggingConfig(BaseModel):
"""Logging configuration."""
level: str = Field(default="INFO", description="Log level")
format: str = Field(default="json", description="Log format (json or console)")
log_file: str | None = Field(default=None, description="Log file path (optional)")
class EventQueueConfig(BaseModel):
"""Event queue retry configuration."""
max_retries: int = Field(default=3, ge=0, description="Maximum retry attempts")
initial_retry_delay_s: float = Field(default=2.0, gt=0, description="Initial retry delay (s)")
max_retry_delay_s: float = Field(default=60.0, gt=0, description="Maximum retry delay (s)")
retry_backoff_factor: float = Field(
default=2.0, gt=1.0, description="Exponential backoff factor"
)
class DeviceStatusConfig(BaseModel):
"""Configuration for device online/offline status monitoring."""
enabled: bool = Field(default=True, description="Enable device status monitoring")
timeout_s: int = Field(default=30, ge=1, description="Device offline timeout (s)")
check_interval_s: int = Field(default=5, ge=1, description="Status check interval (s)")
persistence_path: str = Field(
default="/data/device_status.json", description="Path to persist device status"
)
class SessionConfig(BaseModel):
"""Session detection configuration for a device."""
strategy: str = Field(default="power_threshold", description="Session detection strategy")
standby_threshold_w: float = Field(gt=0, description="Power threshold for session start (W)")
working_threshold_w: float = Field(gt=0, description="Power threshold for working state (W)")
start_debounce_s: float = Field(gt=0, description="Debounce time for session start (s)")
stop_debounce_s: float = Field(gt=0, description="Debounce time for session stop (s)")
message_timeout_s: float = Field(gt=0, description="Max time without messages (s)")
heartbeat_interval_s: float = Field(gt=0, description="Interval for heartbeat events (s)")
class DeviceConfig(BaseModel):
"""Configuration for a single IoT device."""
device_id: str = Field(min_length=1, description="Unique device identifier")
mqtt_topic: str = Field(min_length=1, description="MQTT topic to subscribe to")
parser_type: str = Field(default="shelly_pm", description="Parser type")
machine_name: str = Field(min_length=1, description="Human-readable machine name")
session_config: SessionConfig
class BridgeConfig(BaseModel):
"""Complete bridge configuration."""
mqtt: MQTTConfig
odoo: OdooConfig
logging: LoggingConfig
event_queue: EventQueueConfig
device_status: DeviceStatusConfig
devices: list[DeviceConfig]
class EnvOverrideSettings(BaseSettings):
"""Environment variable overrides for selected configuration values."""
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
mqtt_broker: str | None = Field(default=None, alias="MQTT_BROKER")
mqtt_port: int | None = Field(default=None, alias="MQTT_PORT")
mqtt_username: str | None = Field(default=None, alias="MQTT_USERNAME")
mqtt_password: str | None = Field(default=None, alias="MQTT_PASSWORD")
mqtt_client_id: str | None = Field(default=None, alias="MQTT_CLIENT_ID")
mqtt_keepalive: int | None = Field(default=None, alias="MQTT_KEEPALIVE")
mqtt_use_tls: bool | None = Field(default=None, alias="MQTT_USE_TLS")
odoo_base_url: str | None = Field(default=None, alias="ODOO_BASE_URL")
odoo_database: str | None = Field(default=None, alias="ODOO_DATABASE")
odoo_username: str | None = Field(default=None, alias="ODOO_USERNAME")
odoo_api_key: str | None = Field(default=None, alias="ODOO_API_KEY")