Sviluppo Software

Strumenti, idee e visione per diventare uno sviluppatore consapevole, ambizioso e pronto a costruire il proprio futuro con coraggio e competenza.

Simulatore industriale in C#
Dal terminale scarno alle interfacce strutturate: costruire ponti tra software gestionale ed hardware industriale.

Dal terminale al PLC: costruire un industrial bridge in C# (e perché gli errori sono i migliori alleati)

Scritto da Marco Morello il 22 luglio 2026

💡 In sintesi: torno da tre settimane di trasferta in cantiere. Quando rientri a casa stanco ma con l'adrenalina addosso, senti il bisogno di riaccendere la passione sporcandoti le mani con il codice. Così è nato PlcBridge, un simulatore TCP/IP in C# per colmare la distanza tra il software gestionale e l'hardware industriale, accettando l'errore come parte fondamentale del processo di crescita.


Torno da tre settimane di trasferta in cantiere. Quando rientri a casa dopo giorni passati a risolvere grane sul campo, stanco ma con quella tipica adrenalina addosso, senti il bisogno di riaccendere la passione. Volevo qualcosa che mi restituisse la costanza, che mi costringesse a sedermi alla scrivania e a sporcarmi le mani con il codice.

La verità è che, a rigor di logica, avrei dovuto finire MotoLogPro e gli altri mille progetti personali che ho in cantiere. Ma sono fatto così: con i progetti personali tendo a spaziare, a saltare da un'idea all'altra seguendo l'ispirazione del momento. Sul lavoro invece sono una macchina, cerco di chiudere un task prima di passare al successivo per non lasciare nulla in sospeso e non accumulare mille code aperte. A casa, però, il codice è libertà pura.

Così è nato PlcBridge, un progetto di studio nato per colmare la distanza tra il software gestionale in .NET e l'hardware industriale, costruendo un simulatore TCP/IP passo dopo passo. Senza la pretesa di aver inventato nulla, ma con la determinazione di capire come funzionano le cose sotto il cofano.


1. La filosofia del "learn by doing": perché la teoria non basta

Nel software industriale, la distanza tra un concetto astratto e la sua implementazione pratica è immensa. Puoi leggere quanti libri vuoi sui socket TCP/IP, ma capirai cosa significa davvero gestire una connessione solo quando la porta 5000 rimarrà bloccata in background per un processo zombie, impedendoti di compilare.

Il learn by doing non significa improvvisare a caso. Significa:


2. L'architettura: perché il polling batte il push continuo

All'inizio la tentazione è semplice: creare un server che spara dati a raffica verso chiunque si connetta. Ma nel mondo industriale la realtà è diversa. I PLC parlano quando è necessario, e i sistemi di supervisione interrogano i registri secondo una logica precisa.

Ho scelto quindi un'architettura request-response di tipo master-slave:


4. Refactoring Architetturale: Dallo "Spaghetti" al Modulare (IoC & DI)

Durante lo sviluppo, mi sono accorto che il mio Program.cs stava diventando troppo pesante. Il Server creava direttamente il PLC (new PlcController()). Questo creava un accoppiamento forte: se avessi voluto cambiare logica o testare il PLC isolatamente, avrei dovuto modificare il server stesso.

Per risolvere questo problema strutturale, ho applicato l'Inversione di Controllo (IoC) e la Dependency Injection (DI). Il salto di qualità è evidente:

IL PASSATO: Accoppiamento Forte

Il server istanzia direttamente il controller tramite la parola chiave new. I due componenti sono saldati insieme, rendendo impossibile testare il PLC isolatamente.

// Accoppiamento rigido (Tight Coupling)
public class PlcServer 
{
    // Il Server 'possiede' direttamente l'istanza
    private PlcController _plc = new PlcController();
}
Server ──new──► PlcController
IL PRESENTE: Clean Architecture

Il server riceve un'astrazione. Posso testare il PLC isolatamente iniettando finte istanze nel Server tramite l'interfaccia IPlcController.

// Inversione di controllo (Dependency Injection)
public class PlcServer 
{
    private readonly IPlcController _plc;

    // Il Server riceve il contratto via costruttore
    public PlcServer(IPlcController plc) => _plc = plc;
}
Server ──► IPlcController ◄── PlcController
Il server ora non sa cosa stia usando, conosce solo il "contratto" IPlcController. Questo mi permette di sostituire l'implementazione o testare la logica di business senza far partire un intero server TCP. Il "new" è il nemico della manutenibilità, e imparare a passare le dipendenze via costruttore è stato il salto di qualità definitivo verso un software professionale.

4. Dalla riga di comando scarna a una TUI professionale

Un programma che funziona ma è illeggibile è un software a metà. Se un operatore in cleanroom deve monitorare un impianto, non può interpretare stringhe grezze perse in un terminale nero.

Prima di fare il salto verso il web, ho scelto di evolvere la user interface introducendo una libreria per creare interfacce a riga di comando avanzate, le cosiddette TUI:

PS C:\PROGETTI CSHARP\PlcBridge> dotnet run client

▶ CLIENT/MONITOR di Supervisione (TUI)

? Seleziona il comando di controllo o lettura:
  READ_PRESSURE
  READ_TEMP
> START_PUMP
  STOP_PUMP
  SYSTEM_STATUS

[Invio]
Connessione al PLC in corso (127.0.0.1:5000)...
✔ SUCCESS: Pump is now RUNNING

5. Da stateless a stateful: la memoria del PLC

Un vero PLC non si limita a generare numeri casuali: ha uno stato interno. Accendere una pompa richiede che il sistema ricordi l'azione nel tempo.

Nel mio PlcBridge ho introdotto una memoria di stato persistente per variabili come lo stato della pompa e i valori correnti. Ora il sistema accetta comandi di scrittura e controllo attuatori, trasformandosi da semplice script di test in un vero nodo bidirezionale.

// Stato interno del PLC simulato (memoria dei registri)
private bool _isPumpRunning = false;
private double _currentPressure = 12.0;

public string StartPump()
{
    _isPumpRunning = true;
    return "SUCCESS: Pump is now RUNNING";
}

6. Lezioni dal cantiere digitale: gli errori come indicatori di rotta

Costruire software significa inevitabilmente sbattere contro i muri. Invece di nascondere la polvere sotto il tappeto, ho tracciato ogni singola anomalia di questo sprint. Ecco le cicatrici tecniche che mi hanno insegnato di più:

💡 Il vero valore non è scrivere codice che funziona al primo colpo, ma capire perché si è rotto. La fase di troubleshooting è la vera palestra dell'architetto software.

Ma la soddisfazione più grande? Vedere la pipeline CI/CD su GitHub Actions illuminarsi di verde. Sapere che ogni singola modifica viene compilata e validata dai miei test unitari in un ambiente cloud isolato, mi dà la tranquillità e la solidità di un workflow aziendale vero e proprio.


E adesso? Verso il web con Blazor

Questo progetto non è un punto d'arrivo, ma una solida fondamenta. Ho un server robusto, un protocollo chiaro, una CLI curata e una pipeline CI/CD pronta all'uso.

Il prossimo passo? Prenderò questo backend di comunicazione e lo porterò sul web con Blazor, per creare una dashboard interattiva accessibile da qualsiasi browser o tablet industriale.

La strada è lunga e l'umiltà tanta, ma i mattoni sono posati dritti. Meglio fatto ma non perfetto che niente: rimettere in movimento il sito e continuare a scrivere codice un pezzetto alla volta è l'unico modo per crescere davvero. Ci risentiamo alla prossima iterazione.

Prossimamente...

Porteremo questo backend TCP/IP nel mondo web moderno con Blazor, trasformando la nostra console in una dashboard grafica interattiva accessibile da qualsiasi tablet in officina.

← Torna indietro