10 KiB
Ruolo ed Obiettivo
Agisci come un Software Architect ed Expert .NET Developer. Il tuo obiettivo è progettare e implementare un'applicazione modulare in .NET 8+ (Core) per la comunicazione industriale con PLC Siemens, ottimizzata per performance, affidabilità e manutenibilità.
Segui rigorosamente le fasi operative descritte di seguito, senza saltare alcun passaggio. Non scrivere codice prima di aver completato la Fase 1.
FASE 1: Documentazione e Pianificazione (PRIMA DI CONFIGURARE IL CODICE)
Come primissimo step, crea un file chiamato ARCHITECTURE_AND_SPEC.md
nella root del progetto. Questo file sarà la nostra "fonte di verità"
e dovrai aggiornarlo man mano che l'architettura si evolve. Il file
deve contenere:
- System Overview: Descrizione ad alto livello del sistema.
- Component Diagram (Testuale/Mermaid): Architettura dei moduli (Driver PLC, Configurazione, Orchestratore di Lettura, Storage/Persistence).
- Data Model: Struttura del dizionario in memoria (Key: DB Identifier, Value: Payload) e strategie di serializzazione.
- Config Schema: Bozza del file di configurazione (JSON o YAML).
Fermati dopo aver creato questo file e chiedimi conferma prima di procedere alla Fase 2.
FASE 2: Definizione della Configurazione e Modelli
Crea il sistema di configurazione (preferibilmente basato su
Microsoft.Extensions.Configuration con JSON o YAML).
Il file deve permettere di definire:
- Connessione PLC: IP, Rack, Slot, Modello PLC Siemens (es. S7-1200, S7-1500).
- Aree di Memoria (DB): Per ogni area definire ID, Numero DB,
Indirizzo di partenza, Dimensione (Byte), Tipo di dato (o array di
byte grezzi), e la Modalità di Lettura (
ContinuousoOnEvent). - Target di Persistence: Flag di attivazione e stringhe di connessione per File System, Redis e MariaDB.
FASE 3: Core Engine - Comunicazione PLC (S7NetPlus)
Implementa il servizio di comunicazione PLC utilizzando la libreria S7netplus.
- Sviluppa un'astrazione (es.
IPLcVanguardService) per disaccoppiare la libreria di comunicazione dal resto dell'applicazione. - Gestisci la riconnessione automatica in caso di caduta della linea con logica di retry/backoff.
- Implementa i due motori di polling in parallelo (utilizzando
TaskoHostedServices/BackgroundWorkerdi .NET):- Continuous Polling Loop: Cicla continuamente sulle aree
marcate come
Continuouscon un delay configurabile. - OnEvent Polling Engine: Un meccanismo (es. basato su
canali
System.Threading.Channelso eventi interni C#) che triggera la lettura delle areeOnEventsolo quando viene invocato un comando esterno o viene rilevato un cambio di stato specifico.
- Continuous Polling Loop: Cicla continuamente sulle aree
marcate come
FASE 4: State Management e Cache in Memoria
- I dati letti dal PLC devono essere memorizzati in un dizionario
thread-safe (es.
ConcurrentDictionary<string, byte[]>o un modello strutturato simile dove la chiave è l'identificativo della DB). - Questo stato in memoria deve supportare nativamente la
serializzazione/deserializzazione (es. tramite
System.Text.Json) per permettere snapshot rapidi dello stato della macchina.
FASE 5: Pipeline di Persistenza (Multi-Target Pipeline)
Crea un sistema di persistenza flessibile ed estensibile (Pattern Strategy o Observer). Quando viene completata una lettura (o aggiornato il dizionario di stato), i dati devono essere inviati ai target abilitati:
- File System: Salvataggio del dizionario serializzato in formato JSON (con logica di rotazione o sovrascrittura a seconda dell'area).
- Redis (Opzionale): Connessione tramite
StackExchange.Redis. Salva lo stato in strutture Key-Value o Hash usando la DB del PLC come chiave/campo. - MariaDB (Opzionale): Implementato tramite Entity Framework
Core utilizzando il provider Pomelo.EntityFrameworkCore.MySql.
Configura un DbContext snello che mappi le letture su una tabella
storica o di stato corrente (es.
Id,DbNumber,Timestamp,PayloadBytesoPayloadJson).
Linee Guida per il Codice (Requisiti Non Funzionali)
- Linguaggio e Framework: C# 12, .NET 8 (o superiore).
- Gestione degli Errori: Robusta. Errori di lettura da PLC non devono far crashare l'applicazione, ma attivare tentativi di riconnessione e tracciamento dello stato di salute (Health Check).
- Logging: Utilizza
Microsoft.Extensions.Logging(strutturato). Logga disconnessioni, errori di persistenza e tempi di ciclo critici. - Asincronia: Tutto il codice I/O (PLC, File, Redis, DB) deve
essere rigorosamente asincrono (
async/await). - Dipendenze: Usa la Dependency Injection nativa di .NET per orchestrare i vari servizi.
AGGIORNAMENTO ARCHITETTURALE: Cross-Platform e Modularità
L'applicazione deve essere strutturata in ottica multi-progetto (Soluzione .NET) per garantire il riutilizzo del codice e la massima portabilità sia su Windows (IIS / Servizi Windows) che su Linux (Kestrel / systemd):
- PlcVanguard.Core (Class Library): Deve contenere tutta la
logica di business. I motori di lettura PLC (Continuous e OnEvent), i
client di persistenza (Redis, EF Core Pomelo) e la gestione del
dizionario di stato in memoria devono essere incapsulati qui sotto
forma di servizi registrabili nella Dependency Injection tramite un
Extension Method (es.
services.AddPlcVanguardCore(Configuration)). - PlcVanguard.WebApi (ASP.NET Core Web API): Il punto di ingresso
principale dell'applicazione.
- Deve ospitare il motore del Core come
IHostedService(BackgroundService) per far girare i cicli di lettura PLC in background. - Deve esporre endpoint REST per consultare lo stato del dizionario
in memoria, forzare la lettura di un'area
OnEvente verificare la telemetria (es. stato connessione PLC). - Deve essere configurata per girare nativamente su Kestrel (cross-platform) e supportare il deployment dietro IIS tramite il reverse proxy out-of-the-box di .NET.
- Deve ospitare il motore del Core come
Assicurati che nella Fase 1 (ARCHITECTURE_AND_SPEC.md) questa
separazione in progetti e la gestione del ciclo di vita dei background
task in ASP.NET Core siano chiaramente documentate.
AGGIORNAMENTO REQUISITI: Logica PLC Specifica, Dashboard Blazor e Flusso Git
Modifichiamo la strategia e i requisiti del progetto. L'applicazione non è più solo un motore generico, ma deve implementare una logica di sincronizzazione tra DB e un'interfaccia utente in Blazor (.NET 8). Inoltre, viene introdotto un vincolo rigoroso sul flusso di lavoro (Git).
1. Specifica Logica PLC (Core Engine)
Implementa la seguente mappatura e logica di trigger nel modulo di comunicazione:
- DB 100 (Monitoraggio Continuo - 32 Byte totali):
- Byte 0-3 (Semafori di stato): Il primo bit (Byte 0, Bit 0) è
il flag
Dati Pronti. Quando questo bit passa a1, il motore deve triggerare IMMEDIATAMENTE la lettura "OnEvent" della DB101. Una volta letta con successo la DB101, l'applicazione deve gestire lo stato (opzionalmente resettando il flag se il PLC lo richiede, o semplicemente memorizzando l'avvenuto cambio di stato). - Byte 4-31 (Contatori vari): Sequenza di valori di tipo
REAL(4 byte ciascuno). Il primo contatoreREALinizia al Byte 4 (fino al Byte 7).
- Byte 0-3 (Semafori di stato): Il primo bit (Byte 0, Bit 0) è
il flag
- DB 101 (Lettura su Evento - 4000 Byte totali):
- Contiene un array di 1000 valori di tipo
REAL(4 byte * 1000 = 4000 byte). - Viene letta solo al trigger del semaforo della DB100. Ciascuna lettura di questa DB costituisce una "Registrazione" (Record) storica, a cui associare un ID univoco incrementale, un Timestamp (Data/Ora) ed eventuali metadati.
- Contiene un array di 1000 valori di tipo
2. Architettura della Solution .NET 8
La soluzione deve essere composta da:
- PlcVanguard.Core (Class Library): Logica PLC (DB100 e DB101),
memorizzazione nel
ConcurrentDictionary, archiviazione Multi-Target (File, Redis, MariaDB tramite Pomelo EF Core). - PlcVanguard.Web (Blazor Web App .NET 8): Interfaccia utente che funge sia da Web API/Service host per il Core, sia da Dashboard specidica.
3. Requisiti Interfaccia Utente (Pagina Blazor)
Crea una pagina di dashboard che includa:
- Sezione Live (DB100): * Visualizzazione testuale in tempo reale
del primo contatore
REAL(Byte 4-7 della DB100).- Un grafico temporale (Real-time Chart, es. usando librerie gratuite come ChartJs.Blazor, MudBlazor o Plotly.Blazor) che aggiunge un punto a ogni ciclo di polling continuo per tracciare l'andamento del contatore.
- Sezione Storico Registrazioni (DB101):
- Una tabella che elenca le ultime registrazioni della DB101 (ID, Data/Ora, e metadati).
- Selezionando una registrazione dalla tabella, i suoi 1000 valori
REALdevono essere mostrati come una linea su un grafico a dispersione/linee (Asse X: indice 0-999, Asse Y: valore REAL). - Funzione Confronto: Permetti all'utente di selezionare tramite checkbox fino a due registrazioni contemporaneamente dalla tabella per sovrapporre le loro linee sullo stesso grafico e confrontarle.
- Riferimento Live: Sul grafico dei 1000 valori della DB101, mostra una linea orizzontale di riferimento (o l'ultimo punto) che rappresenta il valore corrente letto live dal primo contatore della DB100 per un confronto immediato tra dato storico e dato attuale.
4. Regole Operative di Sviluppo (Flusso Git e Continuità)
Opererai all'interno di una cartella inizializzata come repository Git. Devi seguire tassativamente queste regole:
- Fase 1 Pre-requisito: Genera prima di tutto il file
ARCHITECTURE_AND_SPEC.mdincludendo queste nuove specifiche dettagliate. - Task-Driven Development: Suddividi lo sviluppo in task atomici (es. Creazione progetti -> Configurazione -> Driver PLC DB100 -> Logica Trigger DB101 -> Persistence EF Core -> Pagina Blazor).
- Commit Automatici: Ogni volta che completi un singolo task E
il codice compila correttamente senza errori, devi eseguire
autonomamente i comandi Git per fare il commit:
git add . git commit -m "feat/fix: descrivi accuratamente il task completato
e verificato" ``` 4. Autonomia fino al completamento: Non fermarti a chiedere conferme tra un task di codice e l'altro (a meno di blocchi critici). Procedi autonomamente implementando la solution completa, compilando e facendo commit ad ogni milestone superata, fino al completamento totale del progetto.