# services/production/app/schemas/equipment.py """ Equipment schemas for Production Service """ from pydantic import BaseModel, Field, ConfigDict from typing import Optional, List from datetime import datetime from uuid import UUID from app.models.production import EquipmentType, EquipmentStatus, IoTProtocol, IoTConnectionStatus class IoTConnectionConfig(BaseModel): """Schema for IoT connection configuration""" protocol: str = Field(..., description="IoT protocol (rest_api, opc_ua, mqtt, modbus, custom)") endpoint: str = Field(..., description="Connection endpoint (URL or IP address)") port: Optional[int] = Field(None, description="Connection port") username: Optional[str] = Field(None, description="Username for authentication") password: Optional[str] = Field(None, description="Password for authentication") api_key: Optional[str] = Field(None, description="API key for authentication") token: Optional[str] = Field(None, description="Authentication token") additional_config: Optional[dict] = Field(None, description="Additional protocol-specific configuration") model_config = ConfigDict( json_schema_extra={ "example": { "protocol": "rest_api", "endpoint": "https://connectedcooking.com/api/v1", "port": 443, "api_key": "your-api-key-here", "additional_config": {"poll_interval": 30} } } ) class EquipmentCreate(BaseModel): """Schema for creating new equipment""" name: str = Field(..., min_length=1, max_length=255, description="Equipment name") type: EquipmentType = Field(..., description="Equipment type") model: Optional[str] = Field(None, max_length=100, description="Equipment model") serial_number: Optional[str] = Field(None, max_length=100, description="Serial number") location: Optional[str] = Field(None, max_length=255, description="Physical location") manufacturer: Optional[str] = Field(None, max_length=100, description="Manufacturer") firmware_version: Optional[str] = Field(None, max_length=50, description="Firmware version") status: EquipmentStatus = Field(default=EquipmentStatus.OPERATIONAL, description="Equipment status") # Installation and maintenance install_date: Optional[datetime] = Field(None, description="Installation date") last_maintenance_date: Optional[datetime] = Field(None, description="Last maintenance date") next_maintenance_date: Optional[datetime] = Field(None, description="Next scheduled maintenance date") maintenance_interval_days: Optional[int] = Field(None, ge=1, description="Maintenance interval in days") # Performance metrics efficiency_percentage: Optional[float] = Field(None, ge=0, le=100, description="Current efficiency percentage") uptime_percentage: Optional[float] = Field(None, ge=0, le=100, description="Overall uptime percentage") energy_usage_kwh: Optional[float] = Field(None, ge=0, description="Current energy usage in kWh") # Specifications power_kw: Optional[float] = Field(None, ge=0, description="Power consumption in kilowatts") capacity: Optional[float] = Field(None, ge=0, description="Equipment capacity") weight_kg: Optional[float] = Field(None, ge=0, description="Weight in kilograms") # Temperature monitoring current_temperature: Optional[float] = Field(None, description="Current temperature") target_temperature: Optional[float] = Field(None, description="Target temperature") # IoT Connectivity iot_enabled: bool = Field(default=False, description="Enable IoT connectivity") iot_protocol: Optional[str] = Field(None, description="IoT protocol") iot_endpoint: Optional[str] = Field(None, description="IoT endpoint URL or IP") iot_port: Optional[int] = Field(None, description="IoT connection port") iot_config: Optional[dict] = Field(None, description="IoT configuration") # Real-time monitoring supports_realtime: bool = Field(default=False, description="Supports real-time monitoring") poll_interval_seconds: Optional[int] = Field(None, ge=1, description="Polling interval in seconds") # Sensor capabilities temperature_zones: Optional[int] = Field(None, ge=1, description="Number of temperature zones") supports_humidity: bool = Field(default=False, description="Supports humidity monitoring") supports_energy_monitoring: bool = Field(default=False, description="Supports energy monitoring") supports_remote_control: bool = Field(default=False, description="Supports remote control") # Notes notes: Optional[str] = Field(None, description="Additional notes") # Support contact information support_contact: Optional[dict] = Field( None, description="Support contact information for equipment maintenance", json_schema_extra={ "example": { "email": "support@ovenfactory.com", "phone": "+1-800-555-1234", "company": "OvenTech Support", "contract_number": "SUP-2023-001", "response_time_sla": 24 } } ) model_config = ConfigDict( json_schema_extra={ "example": { "name": "Horno Principal #1", "type": "oven", "model": "Miwe Condo CO 4.1212", "serial_number": "MCO-2021-001", "location": "Área de Horneado - Zona A", "status": "operational", "install_date": "2021-03-15T00:00:00Z", "maintenance_interval_days": 90, "efficiency_percentage": 92.0, "uptime_percentage": 98.5, "power_kw": 45.0, "capacity": 24.0 } } ) class EquipmentUpdate(BaseModel): """Schema for updating equipment""" name: Optional[str] = Field(None, min_length=1, max_length=255) type: Optional[EquipmentType] = None model: Optional[str] = Field(None, max_length=100) serial_number: Optional[str] = Field(None, max_length=100) location: Optional[str] = Field(None, max_length=255) manufacturer: Optional[str] = Field(None, max_length=100) firmware_version: Optional[str] = Field(None, max_length=50) status: Optional[EquipmentStatus] = None # Installation and maintenance install_date: Optional[datetime] = None last_maintenance_date: Optional[datetime] = None next_maintenance_date: Optional[datetime] = None maintenance_interval_days: Optional[int] = Field(None, ge=1) # Performance metrics efficiency_percentage: Optional[float] = Field(None, ge=0, le=100) uptime_percentage: Optional[float] = Field(None, ge=0, le=100) energy_usage_kwh: Optional[float] = Field(None, ge=0) # Specifications power_kw: Optional[float] = Field(None, ge=0) capacity: Optional[float] = Field(None, ge=0) weight_kg: Optional[float] = Field(None, ge=0) # Temperature monitoring current_temperature: Optional[float] = None target_temperature: Optional[float] = None # IoT Connectivity iot_enabled: Optional[bool] = None iot_protocol: Optional[str] = None iot_endpoint: Optional[str] = None iot_port: Optional[int] = None iot_config: Optional[dict] = None # Real-time monitoring supports_realtime: Optional[bool] = None poll_interval_seconds: Optional[int] = Field(None, ge=1) # Sensor capabilities temperature_zones: Optional[int] = Field(None, ge=1) supports_humidity: Optional[bool] = None supports_energy_monitoring: Optional[bool] = None supports_remote_control: Optional[bool] = None # Notes notes: Optional[str] = None # Support contact information support_contact: Optional[dict] = None # Status flag is_active: Optional[bool] = None model_config = ConfigDict( json_schema_extra={ "example": { "status": "maintenance", "last_maintenance_date": "2024-01-15T00:00:00Z", "next_maintenance_date": "2024-04-15T00:00:00Z", "efficiency_percentage": 88.0 } } ) class EquipmentResponse(BaseModel): """Schema for equipment response""" id: UUID tenant_id: UUID name: str type: EquipmentType model: Optional[str] = None serial_number: Optional[str] = None location: Optional[str] = None manufacturer: Optional[str] = None firmware_version: Optional[str] = None status: EquipmentStatus # Installation and maintenance install_date: Optional[datetime] = None last_maintenance_date: Optional[datetime] = None next_maintenance_date: Optional[datetime] = None maintenance_interval_days: Optional[int] = None # Performance metrics efficiency_percentage: Optional[float] = None uptime_percentage: Optional[float] = None energy_usage_kwh: Optional[float] = None # Specifications power_kw: Optional[float] = None capacity: Optional[float] = None weight_kg: Optional[float] = None # Temperature monitoring current_temperature: Optional[float] = None target_temperature: Optional[float] = None # IoT Connectivity iot_enabled: bool = False iot_protocol: Optional[str] = None iot_endpoint: Optional[str] = None iot_port: Optional[int] = None iot_connection_status: Optional[str] = None iot_last_connected: Optional[datetime] = None iot_config: Optional[dict] = None # Real-time monitoring supports_realtime: bool = False poll_interval_seconds: Optional[int] = None # Sensor capabilities temperature_zones: Optional[int] = None supports_humidity: bool = False supports_energy_monitoring: bool = False supports_remote_control: bool = False # Status is_active: bool notes: Optional[str] = None # Support contact information support_contact: Optional[dict] = None # Timestamps created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class EquipmentListResponse(BaseModel): """Schema for paginated equipment list response""" equipment: List[EquipmentResponse] total_count: int page: int page_size: int model_config = ConfigDict( json_schema_extra={ "example": { "equipment": [], "total_count": 10, "page": 1, "page_size": 50 } } ) class EquipmentDeletionSummary(BaseModel): """Schema for equipment deletion summary""" can_delete: bool = Field(..., description="Whether the equipment can be deleted") warnings: List[str] = Field(default_factory=list, description="List of warnings about deletion") production_batches_count: int = Field(default=0, description="Number of production batches using this equipment") maintenance_records_count: int = Field(default=0, description="Number of maintenance records") temperature_logs_count: int = Field(default=0, description="Number of temperature logs") equipment_name: Optional[str] = Field(None, description="Equipment name") equipment_type: Optional[str] = Field(None, description="Equipment type") equipment_location: Optional[str] = Field(None, description="Equipment location") model_config = ConfigDict( json_schema_extra={ "example": { "can_delete": True, "warnings": ["3 production batch(es) are using this equipment"], "production_batches_count": 3, "maintenance_records_count": 5, "temperature_logs_count": 120, "equipment_name": "Horno Principal #1", "equipment_type": "oven", "equipment_location": "Área de Horneado" } } ) # ================================================================ # IoT-SPECIFIC SCHEMAS # ================================================================ class EquipmentSensorReadingResponse(BaseModel): """Schema for equipment sensor reading response""" id: UUID tenant_id: UUID equipment_id: UUID batch_id: Optional[UUID] = None reading_time: datetime # Temperature readings temperature: Optional[float] = None temperature_zones: Optional[dict] = None target_temperature: Optional[float] = None # Humidity humidity: Optional[float] = None target_humidity: Optional[float] = None # Energy monitoring energy_consumption_kwh: Optional[float] = None power_current_kw: Optional[float] = None # Equipment status operational_status: Optional[str] = None cycle_stage: Optional[str] = None cycle_progress_percentage: Optional[float] = None time_remaining_minutes: Optional[int] = None # Process parameters motor_speed_rpm: Optional[float] = None door_status: Optional[str] = None steam_level: Optional[float] = None # Quality indicators product_weight_kg: Optional[float] = None moisture_content: Optional[float] = None # Additional sensor data additional_sensors: Optional[dict] = None # Data quality data_quality_score: Optional[float] = None is_anomaly: bool = False created_at: datetime model_config = ConfigDict(from_attributes=True) class EquipmentConnectionTestResponse(BaseModel): """Schema for IoT connection test response""" success: bool = Field(..., description="Whether connection test succeeded") status: str = Field(..., description="Connection status") message: str = Field(..., description="Detailed message") response_time_ms: Optional[int] = Field(None, description="Response time in milliseconds") protocol_tested: str = Field(..., description="Protocol that was tested") endpoint_tested: str = Field(..., description="Endpoint that was tested") error_details: Optional[str] = Field(None, description="Error details if connection failed") supported_features: Optional[List[str]] = Field(None, description="List of supported IoT features") model_config = ConfigDict( json_schema_extra={ "example": { "success": True, "status": "connected", "message": "Successfully connected to equipment", "response_time_ms": 145, "protocol_tested": "rest_api", "endpoint_tested": "https://connectedcooking.com/api/v1", "supported_features": ["temperature", "humidity", "energy_monitoring"] } } ) class RealTimeDataResponse(BaseModel): """Schema for real-time equipment data response""" equipment_id: UUID equipment_name: str timestamp: datetime connection_status: str # Current readings temperature: Optional[float] = None temperature_zones: Optional[dict] = None humidity: Optional[float] = None energy_consumption_kwh: Optional[float] = None power_current_kw: Optional[float] = None # Status operational_status: Optional[str] = None cycle_stage: Optional[str] = None cycle_progress_percentage: Optional[float] = None time_remaining_minutes: Optional[int] = None # Active batch active_batch_id: Optional[UUID] = None active_batch_name: Optional[str] = None model_config = ConfigDict( json_schema_extra={ "example": { "equipment_id": "123e4567-e89b-12d3-a456-426614174000", "equipment_name": "Horno Principal #1", "timestamp": "2025-01-12T10:30:00Z", "connection_status": "connected", "temperature": 185.5, "temperature_zones": {"zone1": 180, "zone2": 190, "zone3": 185}, "humidity": 65.0, "operational_status": "running", "cycle_stage": "baking", "cycle_progress_percentage": 45.0, "time_remaining_minutes": 12 } } ) class EquipmentIoTAlertResponse(BaseModel): """Schema for IoT alert response""" id: UUID tenant_id: UUID equipment_id: UUID batch_id: Optional[UUID] = None # Alert information alert_type: str severity: str alert_time: datetime # Alert details title: str message: str # Threshold information threshold_value: Optional[float] = None actual_value: Optional[float] = None deviation_percentage: Optional[float] = None # Status is_active: bool is_acknowledged: bool acknowledged_by: Optional[UUID] = None acknowledged_at: Optional[datetime] = None is_resolved: bool resolved_by: Optional[UUID] = None resolved_at: Optional[datetime] = None resolution_notes: Optional[str] = None # Automated response auto_resolved: bool corrective_action_taken: Optional[str] = None created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class EquipmentSensorHistoryResponse(BaseModel): """Schema for sensor reading history response""" equipment_id: UUID equipment_name: str start_time: datetime end_time: datetime total_readings: int readings: List[EquipmentSensorReadingResponse] model_config = ConfigDict( json_schema_extra={ "example": { "equipment_id": "123e4567-e89b-12d3-a456-426614174000", "equipment_name": "Horno Principal #1", "start_time": "2025-01-12T08:00:00Z", "end_time": "2025-01-12T12:00:00Z", "total_readings": 48, "readings": [] } } )