Files
ske087 bff6d70b17 Initial commit: aplicatie de cantarire si etichetare
Aplicatie Flask + SQLite pentru productie alimentara: cantarirea
componentelor unui produs finit si tiparirea etichetei prin QZ Tray.

- produse finite (retete) formate din componente cantarite
- designer vizual de etichete (mm/px, zona sigura, campuri variabile,
  cod QR cu continut din mai multe bucati)
- legare produs finit -> sablon de eticheta
- navigare pe doua taburi: Cantarire / Setari
- administrare: componente, produse finite, sabloane, campuri, istoric
- backup, resetare baza de date, checklist de pregatire, /healthz
- CLI de administrare si serviciu systemd pentru productie
- vendor/syncpulse-scale-bridge (GPL-3.0-or-later) pentru citirea cantarului
2026-10-18 23:38:45 +03:00

86 lines
3.0 KiB
Python

"""Monitor de port serial: identifica formatul unui cantar necunoscut."""
from __future__ import annotations
import math
from flask import Blueprint, current_app, flash, redirect, render_template, request, url_for
from ..probe import BAUD_RATES, FRAMINGS, ProbeError, list_ports, save_capture, sweep
from ..scale import get_scale
bp = Blueprint("monitor", __name__, url_prefix="/monitor")
def _form_values() -> dict:
def number(name: str, default: float) -> float:
raw = (request.form.get(name) or "").strip().replace(",", ".")
try:
value = float(raw)
except ValueError:
return default
return value if math.isfinite(value) else default
return {
"port": (request.form.get("port") or "").strip(),
"baud": int(number("baud", 9600)),
"framing": (request.form.get("framing") or "8N1").strip().upper(),
"seconds": min(max(number("seconds", 5), 0.5), 30),
"save": bool(request.form.get("save")),
"name": (request.form.get("name") or "capture").strip()[:60],
"scan": bool(request.form.get("scan")),
}
@bp.route("", methods=["GET", "POST"])
def index():
scale = get_scale(current_app)
values = _form_values() if request.method == "POST" else {
"port": "", "baud": 9600, "framing": "8N1", "seconds": 5.0,
"save": False, "name": "capture", "scan": False,
}
result = None
scan_hits = None
saved_path = None
error = None
if request.method == "POST":
if not values["port"]:
error = "Alege portul serial."
elif values["scan"]:
try:
rows = sweep(values["port"], seconds=min(values["seconds"], 2.0),
framings=(values["framing"],), bauds=BAUD_RATES)
scan_hits = [r for r in rows if r.get("bytes")]
if not scan_hits:
error = "Niciun byte primit la vitezele incercate. Verifica cablul si setarile cantarului."
except ProbeError as exc:
error = str(exc)
else:
result = scale.probe(values["port"], values["baud"], values["framing"], values["seconds"])
if not result.get("ok"):
error = result.get("error") or "Portul nu a putut fi deschis."
elif values["save"] and result.get("frames"):
try:
saved_path = save_capture(
current_app.config["INSTANCE_DIR"] / "captures",
values["name"],
result["frames"],
)
flash(f"Captura a fost salvata in {saved_path}.", "success")
except OSError as exc:
error = f"Captura nu a putut fi scrisa: {exc}"
return render_template(
"monitor.html",
values=values,
ports=list_ports(),
profiles=scale.profiles(),
result=result,
scan_hits=scan_hits,
saved_path=saved_path,
error=error,
baud_rates=BAUD_RATES,
framings=FRAMINGS,
)