
Part Production Cell — MES & OEE
OpenPLC, Ignition Perspective e SQLite: eventi, KPI e cause dei fermi macchina organizzati in modo chiaro.
Questo caso didattico mostra un vertical slice tra ERP, MES e SCADA. Odoo resta il proprietario dell'ordine di produzione e della conferma finale. Il MES aggiunge admission, identità dell'execution e outbox. Ignition esegue l'SFC e resta la fonte dei fatti di linea.
Ho seguito un ordine lungo tutto il ciclo: l'operatore lo avvia da Odoo, Node-RED prende il release, il MES ammette una sola execution e Ignition riceve il comando via OPC UA. Il completamento torna poi in ERP come risultato verificato.
Il punto non era solo inviare un comando. La parte importante era mantenere chiari i confini: l'ERP non scrive tag di linea, Node-RED non inventa fatti produttivi e Odoo non può chiudere l'ordine prima che il MES restituisca il risultato.
ERP, MES e SCADA risolvono compiti diversi. Odoo conosce ordine, prodotto, BoM e conferma finale. Il MES sa quale execution è stata accettata e quale risultato deve ancora tornare. Ignition conosce lo stato della linea, l'SFC e i tag runtime. Node-RED collega i sistemi, ma non diventa il proprietario dei fatti produttivi.
Odoo conserva Manufacturing Order, BoM, quantità, componenti e conferma ERP finale. Non scrive tag di linea e non decide cosa è successo nell'SFC.
Il MES DB crea una execution durabile, protegge la linea da un secondo ordine attivo e conserva il completion fino alla consegna all'ERP.
Ignition SFC esegue il runtime Line01 e scrive stato, contatori good/reject e consumo materiali. Questi fatti non sono calcolati in Node-RED.
Dopo Start in Odoo, l'ordine viene messo in coda per il MES. Node-RED prende il release successivo e crea una request identity stabile. Il MES DB ammette una sola execution attiva per la linea, quindi un poll ripetuto non diventa un secondo ordine di produzione.
WH/MO/00032 passa a In Progress. Il blocco MES mostra che l'ordine è in coda per il release.
Flow 10 prende da Odoo il prossimo ordine queued e costruisce una request MES canonica con identità stabile.
Il MES accetta l'execution, verifica se la linea è occupata e pubblica uno Start command solo per l'ordine accettato.
Node-RED scrive i campi di comando in Ignition solo dopo l'admission del MES. RequestSequence viene scritto per ultimo, così lo script Gateway vede un payload completo. Ignition verifica ordine, execution, prodotto, quantità e stato corrente della linea. Solo dopo l'SFC avvia il runtime.
Node-RED scrive CommandId, WorkOrderId, MesExecutionId, ProductCode e TargetGoodQty nei tag comando di Ignition.
RequestSequence viene scritto per ultimo. È il confine che indica a Ignition che il comando è pronto per la validazione.
Ignition SFC scrive STARTING, RUNNING, COMPLETED, good count, reject count e consumption facts. Node-RED osserva soltanto.
cmdPaths = [
"[default]Line01/Cmd/Start/CommandId",
"[default]Line01/Cmd/Start/WorkOrderId",
"[default]Line01/Cmd/Start/MesExecutionId",
"[default]Line01/Cmd/Start/ProductCode",
"[default]Line01/Cmd/Start/TargetGoodQty",
]
values = system.tag.readBlocking(cmdPaths)
# RequestSequence is the commit boundary.
# When it changes, the full command payload is already written.
if requestSequence <= previousAckSequence:
return
chartInstanceId = system.sfc.startChart(
"Line01_DemoExecution",
chartParameters,
)
Ignition pubblica il completamento dopo il cambio di CompletionSequence. Il MES salva i fatti produttivi e crea una riga per l'outbox ERP. Un flow separato di Node-RED consegna il risultato pending a Odoo e lo marca come delivered solo dopo una risposta ERP riuscita.
Flow 30 vede un nuovo CompletionSequence via OPC UA e pubblica un evento production-completed.
Il MES DB salva il completion e crea una riga erp_outbox. Un resultId ripetuto non crea un secondo ERP posting.
Flow 40 invia il pending outbox a Odoo e marca la riga come delivered solo dopo una risposta ERP riuscita.
La conferma anticipata in Odoo è nascosta finché il MES non restituisce un risultato. Dopo la receipt, l'operatore ottiene l'azione finale Produce All. Odoo resta il proprietario del posting ERP, ma non può più chiudere l'ordine prima della linea.
WH/MO/00032 è in progress: prodotto PKG-A, quantità target 10.00 e MES release in coda.
Odoo riceve good quantity 10.00 e il consumo di MAT-BASE-A, MAT-LABEL-A e MAT-PACK-A.
Dopo il risultato MES, WH/MO/00032 è chiuso in Odoo. Il MES release è confermato in ERP e l'execution ID resta sull'ordine.
Cosa mostra il caso:

OpenPLC, Ignition Perspective e SQLite: eventi, KPI e cause dei fermi macchina organizzati in modo chiaro.

OPC UA, SQLite e Ignition: dallo stato live della pompa alla cronologia persistente e alla verifica dello scenario.

OpenPLC, Modbus TCP e Ignition: dalla logica Ladder a uno scenario operatore verificabile.