feat(vision): il server esegue tramite worker e salva misure vere
Aggiunge POST /api/vision/execute: route l'immagine al worker di visione, mappa le uscite del grafo sulle quote e le salva con save_measurement - stesso verdetto, stesso gate del fuori tolleranza di ogni altra misura. Nuova tabella vision_results (una riga per acquisizione, non per quota) e input_method 'camera' su measurements. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"""One row per vision execution - not per quote."""
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import DateTime, Enum, ForeignKey, Integer, JSON, String, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from src.backend.database import Base
|
||||
|
||||
|
||||
class VisionResult(Base):
|
||||
__tablename__ = "vision_results"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
task_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("recipe_tasks.id"), nullable=False, index=True
|
||||
)
|
||||
image_path: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
||||
overlay_path: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
||||
engine_version: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
executed_on: Mapped[str] = mapped_column(
|
||||
Enum("server", "station", name="vision_executed_on_enum"), nullable=False
|
||||
)
|
||||
station_id: Mapped[Optional[int]] = mapped_column(
|
||||
Integer, ForeignKey("stations.id"), nullable=True
|
||||
)
|
||||
device_code: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
||||
# Copied, not referenced: a calibration redone six months from now must not
|
||||
# rewrite what a measurement already taken means. Same for the graph.
|
||||
calibration_snapshot: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
||||
graph_snapshot: Mapped[dict] = mapped_column(JSON, nullable=False)
|
||||
duration_ms: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
||||
executed_at: Mapped[datetime] = mapped_column(
|
||||
DateTime, nullable=False, server_default=func.now()
|
||||
)
|
||||
|
||||
__table_args__ = ({"mysql_engine": "InnoDB", "mysql_charset": "utf8mb4"},)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<VisionResult task={self.task_id} engine={self.engine_version}>"
|
||||
Reference in New Issue
Block a user