Architettura Backend Macchine¶
Documentazione tecnica del backend Go per la gestione dei tipi macchina (pivot, lineare, motopompa, rotolone, ippodromo).
Indice¶
- Pattern comune
- Ciclo di vita di una richiesta
- Struttura dei package
- Confronto tra tipi macchina
- Dettagli per tipo
Pattern comune¶
Ogni tipo macchina segue lo stesso schema architetturale, implementato come package Go separato in internal/<tipo>/. Il framework condiviso in internal/shared/ gestisce il flusso generico tramite GenericDataHandler, parametrizzato con tipi e funzioni specifiche per macchina.
Endpoint¶
Ogni tipo macchina espone due endpoint HTTP (POST):
| Endpoint | Handler | Descrizione |
|---|---|---|
/<tipo>Data |
DataHandler |
Ricezione dati dalla macchina (variabili/costanti) |
/<tipo>Update |
UpdateHandler |
Invio comandi dall'app web alla macchina |
Esiste inoltre un endpoint condiviso POST /cleanCommands (autenticato) che invoca CleanCommands per tutti i tipi macchina.
Modello dati¶
Ogni tipo macchina utilizza un insieme di tabelle DB con prefisso convenzionale:
| Tabella | Prefisso esempio (lineare) | Contenuto |
|---|---|---|
<tipo>_stato |
lin_stato / lst_ |
Variabili real-time (telemetria) |
<tipo>_alarm |
lin_alarm / lal_ |
Flag di allarme |
<tipo>_costanti |
lin_costanti / lco_ |
Configurazione macchina |
<tipo>_portale |
lin_portale / lpo_ |
Comandi pendenti (bidirezionale) |
machine_log |
plo_ (condiviso) |
Log attivita per tutte le macchine |
Ciclo di vita di una richiesta¶
1. Macchina -> Server (DataHandler)¶
Macchina --[POST JSON]--> DataHandler ---> GenericDataHandler
|
+-----------------+-----------------+
| |
[Variables] [Constants]
| |
saveVariables() saveConstants()
| |
INSERT stato + alarm UPSERT costanti
UPDATE portale (reset) UPSERT portale
UPDATE machine_log (+ programmi/settori)
| |
+-----------------+-----------------+
|
[Check asincroni, timeout 10s]
checkTurnOff()
checkNotifications()
|
getCommands()
|
Risposta alla macchina
Risposta alla macchina¶
getCommands legge <tipo>_portale cercando record con aggiornato IN ('1', '3'):
| aggiornamento | Significato | Contenuto risposta |
|---|---|---|
0 |
Nessun comando pendente | {"aggiornamento": "0"} |
1 |
Comandi da applicare | Tutti i campi modificabili (costanti, comandi, settori...) |
3 |
Conferma ricezione | Solo aggiornamento + TimeStamp |
2. App Web -> Server (UpdateHandler)¶
App Web --[POST form]--> UpdateHandler
|
Parse machine_id + aggiornato + dati
|
+----------+----------+
| | |
aggiornato aggiornato default
= "1" = "0"/"3" -> 400
| |
Parse JSON UPDATE semplice
Build query (solo aggiornato + timestamp)
dinamica
|
UPDATE portale
(comandi + costanti + settori)
L'UpdateHandler costruisce la query SQL dinamicamente: solo i campi presenti nel JSON vengono aggiornati, tramite un strings.Builder con parametri posizionali incrementali.
3. Pulizia comandi scaduti (CleanCommands)¶
Eseguito periodicamente via cron. Resetta aggiornato = '0' per tutti i record pendenti la cui timestamp e piu vecchia di una soglia configurata, evitando che comandi obsoleti vengano inviati dopo una lunga disconnessione della macchina.
4. Check asincroni¶
Eseguiti in goroutine separate con timeout 10s dopo il salvataggio delle variabili:
checkTurnOff (opzionale):
- Legge gli ultimi 2 record da <tipo>_stato
- Se RunCiclo passa da 1 a 0, invia notifica di spegnimento al portale esterno
- Parametro tip: identifica il tipo macchina (P = pivot, L = lineare, R = rotolone, ecc.)
checkNotifications:
- Legge gli ultimi 2 record da <tipo>_alarm
- Per ogni flag di allarme, se passa da 0 a 1, invia notifica al servizio AWS
- Ogni tipo macchina ha action code distinti (vedi tabella sotto)
Struttura dei package¶
Ogni package macchina segue questa struttura:
internal/<tipo>/
handler.go -- DataHandler + UpdateHandler
saves.go -- saveVariables + saveConstants
commands.go -- getCommands + CleanCommands
checks.go -- checkTurnOff + checkNotifications
types.go -- struct Go: variables, constants, alarms, updateData
handler.go¶
DataHandler: istanziaGenericDataHandlerParamscon i tipi e le funzioni del package, poi delega ashared.GenericDataHandlerUpdateHandler: endpoint per l'app web, costruisce query UPDATE dinamica su<tipo>_portale
saves.go¶
saveVariables: in una transazione DB, inserisce stato + allarmi, resetta comandi pendenti confermati (aggiornato=3), aggiorna machine_logsaveConstants: in una transazione DB, upsert costanti + eventuale gerarchia (programmi, settori), upsert portale con valori di default
commands.go¶
getCommands: query su<tipo>_portale WHERE aggiornato IN ('1','3'), restituiscemap[string]anyserializzato come JSON nella rispostaCleanCommands: UPDATE batch per reset comandi scaduti
checks.go¶
checkTurnOff: confronto ultimi 2 RunCiclo, notifica spegnimentocheckNotifications: confronto ultimi 2 set allarmi, notifica transizioni 0->1
types.go¶
variables: campi telemetria (embedshared.BaseMachineData)constants: campi configurazione (embedshared.BaseMachineData)alarms: struct per pgx scan degli allarmi (tagdb:)updateData: struct per parsing JSON dall'UpdateHandler (campi puntatore per distinguere assenti da zero-value)
Confronto tra tipi macchina¶
Struttura file¶
| File | Pivot | Lineare | Motopompa | Rotolone | Ippodromo |
|---|---|---|---|---|---|
| handler.go (Data + Update) | si + si | si + si | si + si | si + si | si (stub) |
| saves.go | si | si | si | si | - |
| commands.go | si | si | si | si | stub |
| checks.go | si | si | si | si | - |
| types.go | si | si | si | si | - |
Strategia di storage¶
| Tipo | Variabili | Costanti | Note |
|---|---|---|---|
| Pivot | Colonne individuali | Colonne individuali | Schema classico |
| Lineare | Colonne individuali | Colonne + sotto-tabelle | Programmi/settori/gun in tabelle dedicate |
| Motopompa | JSON blob (mvr_data) |
JSON blob (mco_data) |
Schema semplificato |
| Rotolone | JSON blob (rst_data) |
Colonne + sotto-tabelle | Ibrido |
| Ippodromo | N/A | N/A | Solo stub, implementazione incompleta |
Funzionalita opzionali¶
| Feature | Pivot | Lineare | Motopompa | Rotolone | Ippodromo |
|---|---|---|---|---|---|
| CheckTurnOff | si | si | - | si | - |
| PreprocessInput | - | - | - | si | - |
| PutSpace | - | - | - | - | - |
Action code notifiche¶
| Tipo | Allarmi | Fine ciclo | Spegnimento |
|---|---|---|---|
| Pivot | 4 |
6 |
trigger tip=P |
| Lineare | 12 |
14 |
trigger tip=L |
| Motopompa | 15 (error), 16 (warn), 17 (spegnimento) |
- | via notifica |
| Rotolone | 8 |
10 |
trigger tip=R |
Dettagli per tipo¶
Pivot¶
Macchina irrigatrice a pivot centrale. Gestione settori angolari con angle boost e scheduler fino a 15 blocchi.
- Tabelle:
pivot_stato,pivot_alarm,pivot_portale - Comandi specifici: startAvanti, startIndietro, stop, stopInSlotAngle
- Costanti notevoli: 12 settori angolari (SectorPivotEnd), fertirrigazione avanti/indietro, scheduler (Day/Hour/Min Start/End x 15 blocchi)
- Allarmi: 7 flag (emergency line, encoder, comunicazione, pressione, fine ciclo, SIS, fuori campo)
Lineare¶
Macchina irrigatrice a movimento lineare. Gestione multi-programma con settori lineari e endgun.
- Tabelle:
lin_stato,lin_alarm,lin_costanti,lin_programmi,lin_settori,lin_settori_gun,lin_portale - Comandi specifici: startAvanti, startIndietro, stop
- Costanti notevoli: fino a 10 programmi, ciascuno con fino a 20 settori e 10 settori gun per gun (2 gun), posizioni cambio idrante
- Allarmi: 39 flag (inclusi opzionali Stonex GPS, encoder guida GA/GI)
Motopompa¶
Motopompa a controllo remoto. Schema dati semplificato con storage JSON.
- Tabelle:
motop_variabili(JSON),motop_costanti(JSON),motop_portale - Comandi specifici: start, stop
- Costanti notevoli: regolazione motore, set point velocita/pressione, start ritardato, ore/minuti di lavoro STOP
- Allarmi: estratti dinamicamente dal JSON (AllarmiAttivi_1..4), 20 error + 20 warn
Rotolone¶
Macchina irrigatrice a rotolone (avvolgitubo). Supporta preprocessamento input per JSON malformato.
- Tabelle:
roto_stato(JSON),roto_alarm,roto_costanti+ sotto-tabelle,roto_portale - Comandi specifici: start, stop
- PreprocessInput: regex per correggere JSON malformato dalla macchina
- Allarmi: 17 flag (emergenza, pressione, avvolgimento, fine ciclo, fuori campo, comunicazione)
Ippodromo¶
Implementazione stub. Solo DataHandler (senza logica di salvataggio) e CleanCommands.
- Da completare con saves.go, types.go, checks.go, UpdateHandler
Framework condiviso (internal/shared)¶
GenericDataHandler¶
Funzione generica parametrizzata con GenericDataHandlerParams[V, C]:
type GenericDataHandlerParams[V, C baseMachineDataInt] struct {
W, R // http writer/request
MachineType // tipo macchina (P/L/M/R/I)
SaveVariables saveFunc[V] // obbligatorio
SaveConstants saveFunc[C] // obbligatorio
GetCommands getCommandsFunc // obbligatorio
CheckTurnOff checkTurnOffFunc // opzionale
CheckNotifications checkNotificationsFunc // obbligatorio
PreprocessInput preprocessInputFunc // opzionale
PutSpace bool // opzionale
}
BaseMachineData¶
Struct base embedded in tutti i tipi variables/constants:
MachineId,Timestamp,TimestampAck: identificazione e sincronizzazioneDigitalSaveError,DigitalSaveType: tracciamento salvataggio su storage digitale
Tipi di conversione¶
BoolStr: boolean <-> "0"/"1" (DB text, JSON 0/1)StrBool: come BoolStr ma marshaled come boolean JSONStringInt: int <-> "123" (JSON string o number -> int)NumString: number <-> "123" (JSON string o number -> string)