add systemd services and handlers pipeline

This commit is contained in:
2026-01-30 12:20:34 +03:00
parent 056c12580d
commit dc7fd19022
22 changed files with 2875 additions and 3 deletions

View File

@@ -44,6 +44,44 @@ class PollingConfig:
slow_pids: List[int] = field(default_factory=lambda: [0x05, 0x2F, 0x5C])
@dataclass
class StorageConfig:
"""SQLite storage configuration."""
enabled: bool = True
db_path: Optional[str] = None # None = default location
wal_mode: bool = True
retention_days: int = 30
batch_size: int = 50
flush_interval: float = 1.0
@dataclass
class PostgreSQLConfig:
"""PostgreSQL sync configuration."""
enabled: bool = False
host: str = "localhost"
port: int = 5432
database: str = "carpibord"
user: str = "carpibord"
password: str = ""
sync_interval: float = 30.0
batch_size: int = 500
max_retries: int = 3
retry_delay: float = 5.0
@dataclass
class FlipperConfig:
"""Flipper Zero configuration."""
enabled: bool = False
port: str = "/dev/serial0"
baudrate: int = 115200
show_ups: bool = True
@dataclass
class Config:
"""Main configuration container."""
@@ -52,6 +90,9 @@ class Config:
obd2: OBD2Config = field(default_factory=OBD2Config)
scan: ScanConfig = field(default_factory=ScanConfig)
polling: PollingConfig = field(default_factory=PollingConfig)
storage: StorageConfig = field(default_factory=StorageConfig)
postgresql: PostgreSQLConfig = field(default_factory=PostgreSQLConfig)
flipper: FlipperConfig = field(default_factory=FlipperConfig)
@classmethod
def load(cls, config_path: Optional[str] = None) -> "Config":
@@ -120,8 +161,52 @@ class Config:
self._parse_hex(p) for p in poll_data["slow_pids"]
]
if "storage" in data:
storage_data = data["storage"]
self.storage.enabled = storage_data.get("enabled", self.storage.enabled)
self.storage.db_path = storage_data.get("db_path", self.storage.db_path)
self.storage.wal_mode = storage_data.get("wal_mode", self.storage.wal_mode)
self.storage.retention_days = storage_data.get(
"retention_days", self.storage.retention_days
)
self.storage.batch_size = storage_data.get(
"batch_size", self.storage.batch_size
)
self.storage.flush_interval = storage_data.get(
"flush_interval", self.storage.flush_interval
)
if "postgresql" in data:
pg_data = data["postgresql"]
self.postgresql.enabled = pg_data.get("enabled", self.postgresql.enabled)
self.postgresql.host = pg_data.get("host", self.postgresql.host)
self.postgresql.port = pg_data.get("port", self.postgresql.port)
self.postgresql.database = pg_data.get("database", self.postgresql.database)
self.postgresql.user = pg_data.get("user", self.postgresql.user)
self.postgresql.password = pg_data.get("password", self.postgresql.password)
self.postgresql.sync_interval = pg_data.get(
"sync_interval", self.postgresql.sync_interval
)
self.postgresql.batch_size = pg_data.get(
"batch_size", self.postgresql.batch_size
)
self.postgresql.max_retries = pg_data.get(
"max_retries", self.postgresql.max_retries
)
self.postgresql.retry_delay = pg_data.get(
"retry_delay", self.postgresql.retry_delay
)
if "flipper" in data:
flipper_data = data["flipper"]
self.flipper.enabled = flipper_data.get("enabled", self.flipper.enabled)
self.flipper.port = flipper_data.get("port", self.flipper.port)
self.flipper.baudrate = flipper_data.get("baudrate", self.flipper.baudrate)
self.flipper.show_ups = flipper_data.get("show_ups", self.flipper.show_ups)
def _load_from_env(self) -> None:
"""Load configuration from environment variables."""
# CAN config
if "OBD2_CAN_INTERFACE" in os.environ:
self.can.interface = os.environ["OBD2_CAN_INTERFACE"]
if "OBD2_CAN_BITRATE" in os.environ:
@@ -131,6 +216,32 @@ class Config:
if "OBD2_TIMEOUT" in os.environ:
self.obd2.timeout = float(os.environ["OBD2_TIMEOUT"])
# Storage config
if "OBD2_STORAGE_ENABLED" in os.environ:
self.storage.enabled = os.environ["OBD2_STORAGE_ENABLED"].lower() == "true"
if "OBD2_STORAGE_PATH" in os.environ:
self.storage.db_path = os.environ["OBD2_STORAGE_PATH"]
# PostgreSQL config
if "OBD2_PG_ENABLED" in os.environ:
self.postgresql.enabled = os.environ["OBD2_PG_ENABLED"].lower() == "true"
if "OBD2_PG_HOST" in os.environ:
self.postgresql.host = os.environ["OBD2_PG_HOST"]
if "OBD2_PG_PORT" in os.environ:
self.postgresql.port = int(os.environ["OBD2_PG_PORT"])
if "OBD2_PG_DATABASE" in os.environ:
self.postgresql.database = os.environ["OBD2_PG_DATABASE"]
if "OBD2_PG_USER" in os.environ:
self.postgresql.user = os.environ["OBD2_PG_USER"]
if "OBD2_PG_PASSWORD" in os.environ:
self.postgresql.password = os.environ["OBD2_PG_PASSWORD"]
# Flipper config
if "OBD2_FLIPPER_ENABLED" in os.environ:
self.flipper.enabled = os.environ["OBD2_FLIPPER_ENABLED"].lower() == "true"
if "OBD2_FLIPPER_PORT" in os.environ:
self.flipper.port = os.environ["OBD2_FLIPPER_PORT"]
@staticmethod
def _parse_hex(value) -> int:
"""Parse hex string or int to int."""