Rela AIRela AI Docs
Agenti Macchina

Connessione Modbus TCP — Guida Tecnica

Come collegare un PLC Modbus TCP a Rela AI: campi del form, mappa dei registri, modalità cloud_direct vs edge, emit policies, test della connessione e troubleshooting per tipo di errore.

Connessione Modbus TCP

Modbus TCP è il protocollo più comune negli impianti industriali per esporre registri di PLC, RTU e dispositivi di I/O. Rela AI lo supporta nativamente: il tuo PLC si collega direttamente al worker Cloud Run (o via edge gateway) senza middleware aggiuntivi.

A cosa serve

Leggere lo stato dell'apparecchiatura in tempo quasi reale: temperatura del reattore, RPM del motore, contatori di produzione, allarmi di sicurezza, setpoint di processo. Ogni registro che configuri diventa un evento nel pipeline predittivo — viene normalizzato, correlato, alimenta l'Asset Health Index e valuta le regole che hai definito.

Come funziona

Il worker Rela AI apre una connessione TCP al PLC (porta 502 di default), esegue read_holding_registers / read_coils / ecc. a intervalli configurabili (default 5 secondi), decodifica il valore in base al tipo di dato dichiarato (int16, uint32, float32, IEEE-754…), ed emette un evento solo quando il valore cambia in modo significativo (deadband + emit policy). Il circuit breaker sospende i retry dopo 10 cicli falliti consecutivi ed emette l'allarme canonico PLC_UNREACHABLE che l'operatore vede.

Benefici

Nessun middlewareConnessione diretta PLC → Rela AI. Nessuno SCADA intermedio, nessun broker MQTT obbligatorio.
Decodifica dichiarativaScegli data type + byte order nell'UI; il worker fa il decode (IEEE-754, two's complement, word swap, ecc.).
Polling ottimizzatoRegistri contigui raggruppati in una sola read_holding_registers (fino a 125 words per call) per minimizzare round-trip.
Emit policies configurabiliPer registro: data_change (delta assoluta/relativa), threshold_crossed, bit_flip per i booleani.
Osservabilità SRE-gradeMetriche Prometheus per tenant+source: modbus_poll_latency_seconds, modbus_connection_state, modbus_tag_staleness_seconds.

Creare una fonte Modbus — passo per passo

1. Vai a fonti

Dashboard → Allarmi → FontiNuova fonte. Scegli il protocollo Modbus TCP.

2. Compila i campi principali

CampoOrigineEsempio
NomeLibero (identifica la fonte nell'inbox)Reattore Linea 3
HostIP o hostname del PLC nella tua rete10.200.7.50
Porta502 di default (standard Modbus)502
Unit IDSlave ID del dispositivo (1 per un PLC diretto, >1 se c'è un gateway RS-485)1
Deployment Modecloud_direct se il PLC è raggiungibile da GCP via VPN/VPC; edge se dietro firewall strettocloud_direct
Edge Gateway IDSolo se deployment_mode=edge — riferimento al gateway registratogw_a1b2c3

Se hai configurato una VPN in Impostazioni → Connettività VPN, l'host del PLC è l'IP privato dentro la tua subnet OT (es. 192.168.10.20). Altrimenti il PLC deve essere raggiungibile tramite tunnel — mai diretto su internet.

3. Aggiungi la mappa dei registri

Ogni riga della mappa descrive un registro da leggere. Campi:

CampoSignificato
Tipo di registroholding (FC03), input (FC04), coil (FC01), discrete (FC02). holding è il più comune.
NomeEtichetta leggibile — es. reactor.temperature. Usata come tag nelle metriche Prometheus e nell'inbox.
AddressBase 0. Se il PLC documenta in base 1 (Modicon: 40001 = holding[0]), sottrai 1.
CountQuante words leggere. 1 per int16/uint16, 2 per int32/uint32/float32, 4 per float64.
Data typeint16, uint16, int32, uint32, float32, float64. Per coil/discrete: sempre booleano.
Byte orderbig_endian (ABCD, default), little_endian (DCBA), big_endian_swap (BADC), little_endian_swap (CDAB).
Poll intervalSecondi tra le letture (5 default). Minore = più traffico + carico sul PLC.

4. Configura l'emit policy per registro

Tre modalità, pensate per diversi tipi di segnale:

  • data_change — emette quando il valore cambia oltre il deadband (assoluto o relativo %). Per analogici rumorosi dove ogni jitter non conta.
  • threshold_crossed — emette esattamente una volta quando il valore attraversa una soglia. Richiede operatore (>, >=, <, <=) + valore. Utile per allarmi rigidi tipo "temperatura > 90 °C".
  • bit_flip — emette ad ogni cambio 0→1 o 1→0. Obbligatorio per coil/discrete (booleani).

5. Salva e testa la connessione

Al salvataggio, vedi il pulsante Test connection sopra la lista dei registri. Cliccandolo:

  1. Apre una connessione TCP al PLC.
  2. Legge ogni registro della mappa una volta.
  3. Mostra RTT in ms + valori decodificati + warnings se qualche registro è fallito.

Se vedi rtt_ms tra 50 e 300 con i valori attesi, sei a posto. Il listener si avvia automaticamente e inizia a emettere eventi al pipeline.

Deployment modes — quando usare ciascuno

cloud_direct

Il worker Rela AI (Cloud Run in europe-west1) apre la connessione TCP. Richiede che l'IP del PLC sia raggiungibile dal nostro VPC — tipicamente tramite Connettività VPN (WireGuard dedicato, vedi VPN / Configurazione).

Usa questa modalità quando:

  • Hai WireGuard VPN o site-to-site configurata.
  • Il firewall dell'impianto permette connessioni in ingresso sulla porta 502 dall'IP VPN assegnato (10.200.X.X).
  • La rete OT è segmentata ma raggiungibile dalla DMZ o dalla rete corporate.

edge

Installi un container rela-ai-edge su un mini-PC / Raspberry Pi dentro l'impianto. Il container apre una connessione in uscita (HTTPS outbound) al worker Cloud Run, e il polling Modbus avviene localmente nell'impianto.

Usa questa modalità quando:

  • Il firewall permette solo traffico in uscita HTTPS (443) verso domini specifici.
  • Non puoi configurare la VPN (IT non approva, apparecchiatura vecchia, ecc.).
  • Vuoi buffering locale in caso di perdita temporanea di internet.

Vedi Edge Gateway per la guida completa di installazione del container.

Decodifica dei dati — riferimento rapido

Analogici (int16, uint16)

Una sola word, 16 bit. int16 interpreta il MSB come segno (two's complement); uint16 va da 0 a 65535.

Esempio: il tuo PLC espone reactor.temperature × 10 in holding[0]:

data_type: uint16
count: 1

Poi dividi per 10 nella logica dell'agente (via field mapping o in una regola).

Interi 32-bit (int32, uint32)

Due words consecutive. L'ordine dei byte conta: big_endian (ABCD) è il default di Modicon/Schneider; big_endian_swap (BADC) è usato da Siemens e alcuni dispositivi Allen-Bradley.

Esempio: runtime.hours come uint32 in holding[4-5]:

address: 4
count: 2
data_type: uint32
byte_order: big_endian

Se vedi valori assurdi (numero enorme che dovrebbe essere piccolo), prova big_endian_swap — è l'errore più comune.

Virgola mobile (float32 IEEE-754)

Come int32 ma interpretato come float. Il 99% dei PLC usa big_endian (ABCD) ma Siemens spesso usa big_endian_swap (BADC).

Se il test della connessione ti restituisce un numero tipo 3.14e38, hai il byte order sbagliato.

Coil / Discrete (booleani)

Address per bit, non per byte. Ogni coil = 1 bit. Count controlla quanti bit leggi in una singola richiesta (fino a 2000).

Per un E-stop in coil[1]:

register_type: coil
address: 1
count: 1
emit_as: bit_flip

Troubleshooting per tipo di errore

Connection refused

Il PLC rifiuta l'handshake TCP. Cause:

  • Il servizio Modbus TCP è spento nel PLC (verifica nella config del PLC).
  • Il firewall dell'impianto blocca la porta 502 tra l'origine (gateway VPN o Cloud Run) e il PLC.
  • C'è un altro client Modbus che occupa l'unico slot disponibile (alcuni PLC accettano solo 1-2 client concorrenti).

Check: dal gateway VPN o dal container edge, nc -zv <PLC_IP> 502. Se fallisce lì, il problema è di rete.

Connection timeout

Il TCP si avvia ma non risponde. Cause:

  • PLC spento o in modalità STOP.
  • Latenza di rete eccessiva (VPN con molti hop).
  • MTU mismatch nel tunnel WireGuard (1420 vs 1500 — raro con Modbus perché i packet sono piccoli, ma possibile).

Check: ping <PLC_IP> dalla stessa origine del worker. RTT >200 ms di solito indica un problema di rete.

Illegal data address (Modbus exception 02)

Stai chiedendo un indirizzo che il PLC non espone. Cause:

  • Offset 0-based vs 1-based: Modicon documenta 40001 ma l'indirizzo Modbus reale è 0.
  • Word contate male: float32 richiede address + count=2 per leggere 2 word consecutive. Se hai chiesto count=1, il registro successivo legge "la seconda word del float precedente" — caos.

Check: apri il manuale del PLC nella sezione "Mapping Table" e conferma l'indirizzo esatto.

Illegal function (Modbus exception 01)

Stai chiedendo una funzione che il PLC non supporta. Alcuni PLC (vecchi, MicroLogix, ecc.) supportano solo FC03 (holding) e FC06 (write). Tentare FC04 (input registers) fallisce.

Check: cambia register_type a holding e riprova.

Valori assurdi (molto grandi, molto piccoli, 0xFFFF)

Problemi di decodifica, quasi sempre byte order.

SintomoCausa probabileFix
Valore atteso 25.0, letto ~3.4e38float32 con byte order invertitoProva big_endian_swap
Valore atteso 1800, letto 0x0708 (1800) come uint16 ma ci si aspettava uint32Data type sbagliatoCambia a uint16 o aggiusta count
Valore atteso 1800, letto 1799 o 1801Nulla di rotto — il sensore ha jitterAggiusta il deadband

ConnectionError: operation on closed connection

Il PLC ha chiuso la connessione. Tipicamente:

  • Idle timeout del PLC (alcuni Schneider M340 chiudono dopo 30s senza richieste).
  • Keepalive TCP disabilitato nel worker — poll_interval_seconds: 5 evita questo ma se qualche valore è >30s, può succedere.

Check: keepalive_seconds sulla fonte (default: TCP_KEEPIDLE=30). Se c'è un timeout noto del PLC, abbassalo sotto quel valore.

Il test della connessione funziona ma non arrivano eventi all'inbox

Il polling parte ma i registri non emettono. Cause:

  • Emit policy = threshold_crossed: se il valore non ha ancora attraversato la soglia, non emette nulla. Abbassa la soglia per validare.
  • Agente disabilitato: verifica che il machine agent assegnato alla fonte sia enabled: true.
  • Severità minima dell'agente: se l'agent ha min_severity=critical, gli eventi info vengono filtrati prima di arrivare all'inbox.

Come testare la connessione end-to-end

Checklist operativo (in ordine):

  1. Dashboard → Allarmi → Fonti → la-tua-fonte-modbus: il banner di stato è verde (connected).
  2. Test connection: rtt_ms < 300 e i sample_values mostrano il valore atteso.
  3. Dashboard → Allarmi → Inbox: entro pochi minuti devi vedere eventi con event_type che corrisponde al nome del registro (reactor.temperature, motor.speed, ecc.).
  4. Metriche (se Grafana collegato): modbus_connection_state{source_id="<tuo-id>"} == 1 e modbus_register_reads_total che sale.
  5. Circuit breaker sano: non devi vedere eventi PLC_UNREACHABLE nell'inbox. Se li vedi, il tunnel o il firewall hanno un problema intermittente.

Template di dispositivi

Per PLC popolari (Schneider M340, Siemens S7-1500, Allen-Bradley MicroLogix, ecc.), abbiamo device template con la mappa di registri pre-configurata. All'alta di una fonte, clicca Usa template e scegli il tuo modello — i campi principali si auto-riempiono e devi solo aggiustare host, port, unit_id.

Se il tuo dispositivo non c'è, crea una fonte custom e — opzionalmente — converti la configurazione in un template per-tenant da riutilizzare su futuri impianti.

Limitazioni note

  • Scritture: al momento solo lettura. Per scritture (setpoint, comandi) usa uno strumento di write Modbus dall'agente.
  • Max registri per fonte: 64 registri simultanei. Se ne servono di più, dividi in fonti multiple.
  • Precisione temporale: polling ogni 5s (configurabile a 1s minimo). Non è per controllo di ciclo — è condition monitoring.

In questa pagina