""" Pydantic models for Battery Management Service """ from pydantic import BaseModel, Field from typing import List, Optional, Dict, Any, Literal from datetime import datetime from enum import Enum class BatteryState(str, Enum): IDLE = "idle" CHARGING = "charging" DISCHARGING = "discharging" MAINTENANCE = "maintenance" ERROR = "error" class BatteryType(str, Enum): LITHIUM_ION = "lithium_ion" LEAD_ACID = "lead_acid" NICKEL_METAL_HYDRIDE = "nickel_metal_hydride" FLOW_BATTERY = "flow_battery" class BatteryStatus(BaseModel): """Battery status model""" battery_id: str = Field(..., description="Unique battery identifier") name: str = Field(..., description="Human-readable battery name") type: BatteryType = Field(..., description="Battery technology type") state: BatteryState = Field(..., description="Current operational state") # Energy metrics capacity_kwh: float = Field(..., description="Total battery capacity in kWh") stored_energy_kwh: float = Field(..., description="Currently stored energy in kWh") state_of_charge: float = Field(..., description="State of charge (0-100%)") # Power metrics max_charge_power_kw: float = Field(..., description="Maximum charging power in kW") max_discharge_power_kw: float = Field(..., description="Maximum discharging power in kW") current_power_kw: float = Field(0, description="Current power flow in kW (positive = charging)") # Technical specifications efficiency: float = Field(0.95, description="Round-trip efficiency (0-1)") cycles_completed: int = Field(0, description="Number of charge/discharge cycles") max_cycles: int = Field(5000, description="Maximum rated cycles") # Health and maintenance health_percentage: float = Field(100, description="Battery health (0-100%)") temperature_celsius: Optional[float] = Field(None, description="Battery temperature") last_maintenance: Optional[datetime] = Field(None, description="Last maintenance date") next_maintenance: Optional[datetime] = Field(None, description="Next maintenance date") # Location and installation location: Optional[str] = Field(None, description="Physical location") building: Optional[str] = Field(None, description="Building identifier") room: Optional[str] = Field(None, description="Room identifier") # Operational data installed_date: Optional[datetime] = Field(None, description="Installation date") last_updated: datetime = Field(default_factory=datetime.utcnow, description="Last status update") class Config: json_encoders = { datetime: lambda v: v.isoformat() if v else None } class BatteryCommand(BaseModel): """Battery control command""" battery_id: str = Field(..., description="Target battery ID") command: Literal["charge", "discharge", "stop"] = Field(..., description="Command type") power_kw: Optional[float] = Field(None, description="Power level in kW") duration_minutes: Optional[int] = Field(None, description="Command duration in minutes") target_soc: Optional[float] = Field(None, description="Target state of charge (0-100%)") class ChargingRequest(BaseModel): """Battery charging/discharging request""" power_kw: float = Field(..., description="Power level in kW", gt=0) duration_minutes: Optional[int] = Field(None, description="Duration in minutes", gt=0) target_soc: Optional[float] = Field(None, description="Target SOC (0-100%)", ge=0, le=100) class BatteryResponse(BaseModel): """Battery operation response""" battery_id: str status: Dict[str, Any] message: Optional[str] = None class BatteryListResponse(BaseModel): """Response for battery list endpoint""" batteries: List[Dict[str, Any]] count: int total_capacity: float = Field(description="Total system capacity in kWh") total_stored_energy: float = Field(description="Total stored energy in kWh") class HistoricalDataRequest(BaseModel): """Request for historical battery data""" battery_id: str start_time: Optional[datetime] = None end_time: Optional[datetime] = None hours: int = Field(default=24, description="Hours of data to retrieve") class BatteryHistoricalData(BaseModel): """Historical battery data point""" timestamp: datetime state_of_charge: float power_kw: float temperature_celsius: Optional[float] = None efficiency: float class Config: json_encoders = { datetime: lambda v: v.isoformat() } class BatteryAnalytics(BaseModel): """Battery system analytics""" total_batteries: int active_batteries: int total_capacity_kwh: float total_stored_energy_kwh: float average_soc: float # Energy flows total_energy_charged_kwh: float total_energy_discharged_kwh: float net_energy_flow_kwh: float # Efficiency metrics round_trip_efficiency: float capacity_utilization: float # Health metrics average_health: float batteries_needing_maintenance: int class MaintenanceAlert(BaseModel): """Battery maintenance alert""" battery_id: str alert_type: Literal["scheduled", "health", "temperature", "cycles"] severity: Literal["info", "warning", "critical"] message: str recommended_action: str timestamp: datetime class Config: json_encoders = { datetime: lambda v: v.isoformat() } class HealthResponse(BaseModel): """Health check response""" service: str status: str timestamp: datetime version: str class Config: json_encoders = { datetime: lambda v: v.isoformat() }