# Punere în funcțiune Ghid pas cu pas pentru o stație de producție (cântar + imprimantă de etichete). Aplicația rulează local, fără servicii externe: Flask + SQLite, fișierele stau în `instance/`. ## 1. Cerințe pe stație | Ce | Detaliu | |---|---| | Python | 3.10+ (testat pe 3.13) | | Cântar | Bizerba BC800 pe RJ11/10P4C → adaptor USB-serial (apare ca `COMx`) | | Imprimantă | termică de etichete, separată de cântar | | QZ Tray | 2.2.x instalat și pornit (`localhost:8181`) pentru tipărire directă | | Rețea | nu e nevoie de internet; doar rețeaua locală dacă vrei acces din alt PC | ## 2. Instalare ```bash git clone cantarire-etichetare cd cantarire-etichetare python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt ``` Configurare (recomandat): copiază `.env.example` în `.env` și completează cel puțin cheia: ```bash python -c "import secrets; print(secrets.token_urlsafe(48))" ``` ## 3. Prima pornire ```bash python run.py ``` La prima rulare se creează automat `instance/cantarire.db`, cu schema completă, setările implicite și un șablon de etichetă. Sumarul din consolă arată calea bazei și ce mai lipsește: ``` Cantarire & etichetare - server flask URL http://127.0.0.1:5000/ Baza /.../instance/cantarire.db (64.0 kB, schema v5) Date 0 componente / 0 produse finite / 1 sabloane De completat: Datele firmei, Componente, Produse finite (lista apare pe pagina principală) ``` Pagina **Cântărire** afișează un checklist până când totul e pregătit. Ordinea firească: 1. **Setări → Date firmă** — denumirea care apare pe etichetă, telefon. 2. **Setări → Componente** — ce se cântărește (Fasole, Carne, ...). 3. **Setări → Produse finite** — denumirea de pe etichetă + componentele în ordinea cântăririi, opțional șablonul de etichetă propriu. 4. **Setări → Șabloane** — dacă vrei alt design decât cel implicit (designer vizual). 5. **Setări → Câmpuri** — opțional, texte reutilizabile pentru etichete. 6. **Setări → Cântar** — alege profilul activ din `instance/bridge.json`. Verificare rapidă, din consolă: ```bash python -m cantarire.tools.admin status python -m cantarire.tools.admin check ``` `check` întoarce cod 0 doar când elementele obligatorii sunt completate (util în scripturi). ## 4. Cântarul Profilul serial stă în `instance/bridge.json`. Dacă nu ai încă unul: ```bash python -m cantarire.tools.monitor --list python -m cantarire.tools.monitor COM7 --baud 9600 ``` Monitorul doar ascultă (nu scrie pe port), decodează cadrele cunoscute și poate salva o captură pentru analiză. Când ai o captură, profilul se adaugă în `bridge.json` (sau din **Setări → Monitor serial**). Pentru teste fără hardware: ```bash CANTARIRE_SIMULATE=mahak_mds python run.py ``` Fără profil activ aplicația funcționează normal, cu introducere manuală a greutății. ## 5. Imprimanta (QZ Tray) 1. Instalează QZ Tray pe stație și pornește-l. 2. Deschide aplicația: pastila **QZ Tray** din dreapta sus trebuie să devină verde. 3. **Setări → Imprimantă implicită** → alege imprimanta termică. 4. **Tipărește test** — trebuie să iasă o etichetă demo. Dacă QZ nu răspunde, aplicația cade automat pe tipărirea din browser (fereastră de print), deci eticheta iese oricum. ## 6. Producție ```bash python run.py --production # waitress, 0.0.0.0:5000 python run.py --production --port 8080 ``` Serverul de dezvoltare Flask nu se folosește în producție. `--production` pornește **waitress** (WSGI, 8 fire) și afișează un avertisment dacă `CANTARIRE_SECRET_KEY` lipsește. ### Linux (systemd) ```bash sudo useradd -r -s /usr/sbin/nologin cantarire sudo mkdir -p /opt/cantarire-etichetare /var/lib/cantarire sudo chown -R cantarire:cantarire /opt/cantarire-etichetare /var/lib/cantarire # copiază proiectul în /opt/cantarire-etichetare, apoi: sudo cp deploy/cantarire.service /etc/systemd/system/ sudo systemctl edit --full cantarire # verifică utilizatorul și calea sudo systemctl enable --now cantarire ``` `EnvironmentFile=-/etc/cantarire.env` conține variabilele din `.env.example`; fișierul e opțional. Serviciul rulează cu `ProtectSystem=full` și scrie doar în `/var/lib/cantarire`. ### Windows (stația de producție) Rulează `deploy\start-windows.bat`. Scriptul creează `.venv` dacă lipsește, generează o cheie de sesiune în `instance\secret.key` (refolosită la următoarele porniri) și pornește serverul. Pentru pornire automată: creează un shortcut către acel `.bat` în `shell:startup` (Win+R → `shell:startup`). ## 7. Backup și reset ```bash python -m cantarire.tools.admin backup # instance/backups/cantarire-.db python -m cantarire.tools.admin backup --keep 30 # păstrează ultimele 30 python -m cantarire.tools.admin reset --yes # golește datele (face backup automat) python -m cantarire.tools.admin seed-demo # repune datele demo pentru instruire ``` Backup-ul folosește API-ul SQLite (consistent și cu WAL activ), nu o simplă copiere de fișier. Din interfață: **Setări → Descarcă backup** produce un backup proaspăt și îl descarcă. `reset` șterge componente, produse finite, pachete, șabloane și câmpuri, readuce setările implicite și recreează șablonul de etichetă standard — exact starea de după o instalare nouă. ## 8. Monitorizare | Endpoint | Rol | |---|---| | `GET /healthz` | JSON cu starea bazei (integritate, schema, număr de înregistrări) și `setup.ready`; `503` dacă baza e inaccesibilă | | `GET /setari` | cardul **Sistem**: cale, mărime, integritate, backup-uri | Jurnalele ajung la stdout (systemd: `journalctl -u cantarire -f`). Polling-ul greutății (`/api/weight`) este filtrat din jurnal ca să nu umple discul. ## 9. Actualizare ```bash python -m cantarire.tools.admin backup git pull pip install -r requirements.txt sudo systemctl restart cantarire # Windows: închide și redeschide start-windows.bat ``` Migrările de schemă rulează automat la pornire (v1 → v5); coloanele noi se adaugă fără pierdere de date. Rulează `check` după actualizare. ## 10. Dacă ceva nu merge | Simptom | Cauză probabilă | |---|---| | Lista de pornire nu dispare | lipsește un produs finit **cu componente** active | | Pastila QZ e roșie | agentul QZ Tray nu e pornit; pornește-l și apasă **Conectează** | | Greutatea nu se mișcă | profil greșit sau port ocupat — verifică în **Monitor serial** | | `Database is locked` | două instanțe pe aceeași bază; oprește serviciul vechi | | Eticheta iese goală | produsul finit e legat de un șablon șters — verifică **Șabloane** și resetează designul | | `503` la `/healthz` | baza e coruptă sau fără drepturi de scriere; restaurează ultimul backup |