from __future__ import annotations from typing import Any, Dict, List from app.adapters.device_client import CDeviceClient, MockDeviceClient from app.cache.memory_store import memory_store from app.core.config import settings from app.core.security import hash_password from app.repositories.alarm_repo import AlarmRepository from app.repositories.json_config_repo import JsonConfigRepository from app.schemas.platform import ( AiAlarmSettingIn, ChannelConfigIn, DeviceConfigIn, DeviceStatus, LineAlarmSettingIn, RealtimeData, SwitchControlIn, SystemConfigIn, ) from app.ws.manager import ws_manager class PlatformService: def __init__(self) -> None: self.config_repo = JsonConfigRepository() self.alarm_repo = AlarmRepository() self.device_client = MockDeviceClient() if settings.use_mock_device else CDeviceClient() def get_realtime_data(self) -> RealtimeData: cached = memory_store.get_realtime() if cached is not None: return cached realtime = self.device_client.read_realtime_data() memory_store.set_realtime(realtime) return realtime def get_device_status(self) -> DeviceStatus: cached = memory_store.get_status() if cached is not None: return cached status = self.device_client.read_device_status() memory_store.set_status(status) return status def save_device_config(self, payload: DeviceConfigIn) -> Dict[str, Any]: data = payload.model_dump() data["password"] = hash_password(payload.password) path = self.config_repo.write_device_config(data) device_result = self.device_client.send_device_config(payload) return {"save_path": f"/config/{path.name}", **device_result} def save_channel_config(self, payload: ChannelConfigIn) -> Dict[str, Any]: path = self.config_repo.write_channel_config(payload.model_dump()) device_result = self.device_client.send_channel_config(payload) return {"save_path": f"/config/{path.name}", **device_result} def save_line_alarm_setting(self, payload: LineAlarmSettingIn) -> Dict[str, Any]: current = self.config_repo.read_json("setting.json") if not isinstance(current, dict): current = {} current["line_alarm_setting"] = payload.model_dump() path = self.config_repo.write_setting_config(current) device_result = self.device_client.send_line_alarm_setting(payload) return {"save_path": f"/config/{path.name}", **device_result} def save_ai_alarm_setting(self, payload: List[AiAlarmSettingIn]) -> Dict[str, Any]: current = self.config_repo.read_json("setting.json") if not isinstance(current, dict): current = {} current["ai_alarm_setting"] = [item.model_dump() for item in payload] path = self.config_repo.write_setting_config(current) device_result = self.device_client.send_ai_alarm_setting(current["ai_alarm_setting"]) return {"save_path": f"/config/{path.name}", **device_result} def save_system_config(self, payload: SystemConfigIn) -> Dict[str, Any]: current = self.config_repo.read_json("setting.json") if not isinstance(current, dict): current = {} current["system_config"] = payload.model_dump() self.config_repo.write_setting_config(current) return self.device_client.send_system_config(payload) def list_alarms(self, page: int, size: int) -> List[Dict[str, Any]]: return self.alarm_repo.list_alarms(page=page, size=size) def switch_control(self, payload: SwitchControlIn) -> Dict[str, Any]: return self.device_client.send_switch_control(payload) async def poll_device_once(self) -> None: realtime = self.device_client.read_realtime_data() status = self.device_client.read_device_status() alarms = self.device_client.read_alarm_events() memory_store.set_realtime(realtime) memory_store.set_status(status) await ws_manager.broadcast("real-time", {"type": "real_time", "data": realtime.model_dump()}) for alarm in alarms: alarm.id = self.alarm_repo.save_alarm(alarm) memory_store.push_alarm(alarm) await ws_manager.broadcast("alarm", alarm.model_dump(mode="json")) platform_service = PlatformService()