# La catena di conversione

> La conversione tipizzata che ogni tag condivide, dalla lettura grezza al valore ingegneristico, le due politiche di lettura non valida, le azioni per i valori fuori intervallo, le trasformazioni booleane e di stringa, e come una scrittura percorre le fasi all'indietro.

Ogni tag condivide una sola catena di conversione tipizzata che trasforma la lettura grezza nel valore ingegneristico. La catena vive nel tag stesso: la scheda Conversione della pagina [Tag](connector-tags#the-conversion-card) e la griglia del dispositivo mostrano le stesse fasi, e il valore che arriva in Logic, sulle dashboard, nel registratore e in ciò che la stazione pubblica è quello che esce dall'ultima fase. Il nodo OPC UA pubblico porta il valore grezzo.

## Prima il grezzo {#raw-first}

La catena parte dal **valore grezzo** convertito al tipo di dato del tag, non dall'oggetto proprio del driver: un driver che consegna 3,7 a un tag Int32 legge 4 in cima alla scheda, e ogni fase prosegue da quel 4. Una lettura che il tipo dichiarato non può proprio contenere (testo dove è dichiarato un numero) è una lettura vuota, mai uno zero di comodo. Le fasi calcolano in numeri reali, e all'altro capo il valore ingegneristico prende il suo tipo:

| Tag | Valore ingegneristico |
| --- | --- |
| Tipo di dato intero, Scalatura e Taratura spente, o accese con fattore 1 e scostamento 0 (come nasce ogni tag) | Il numero intero stesso, nel tipo di dato del tag. |
| Tipo di dato intero, Scalatura o Taratura che cambia il valore | Un numero reale (Double), arrotondato dalla fase Decimali: un tag Int16 che contiene una temperatura moltiplicata per dieci legge 235 sul dispositivo e 23,5 con scalatura 0,1. |
| Float o Double | Il tipo di dato del tag, quindi un tag Float si arrotonda a quello che un float può rappresentare. |

Il tipo di dato resta quello che portano il dispositivo e il nodo OPC UA pubblico. Accendere o spegnere Scalatura o Taratura cambia il tipo del valore ingegneristico da quel momento in poi: ciò che il registratore ha già registrato resta com'è stato registrato, e un canale mantiene il tipo che dichiara, quindi un canale Intero registra il valore arrotondato all'intero più vicino e un canale Decimale mantiene i decimali. La scheda Conversione si chiude sul valore fornito e segnala quando un tipo intero che Scalatura e Taratura lasciano com'è arrotonda via i decimali di un limite a cui Limiti riporta il valore.

## Le fasi {#the-stages}

Per i tipi numerici la catena è una successione di fasi, ciascuna con la propria casella di spunta; una fase disabilitata lascia passare il suo ingresso, e la scheda mostra il valore corrente alla fine di ogni fase, così si può seguire una lettura viva attraverso i calcoli:

| Fase | Valore predefinito | Che cosa fa |
| --- | --- | --- |
| **Scalatura** | attiva | `scalato = grezzo × Angolare + Lineare`. Angolare vale 1 all'inizio, Lineare 0. Un Angolare pari a 0 viene rifiutato dove viene scritto (« Un fattore di scala pari a 0 azzererebbe ogni lettura. Immettere il fattore per cui moltiplicare (1 mantiene il valore). »), perché azzererebbe ogni lettura e l'anteprima e la catena salvata non devono mai contraddirsi. |
| **Taratura** | disattiva | Una seconda coppia lineare applicata al valore scalato: `tarato = scalato × Angolare + Lineare`. Tenuta separata dalla Scalatura perché una correzione prima e dopo non disturbi i calcoli di campo, e governata da un permesso proprio; vedi [Taratura](connector-calibration). Un Angolare pari a 0 viene rifiutato allo stesso modo. |
| **Lettura non valida** | sempre mostrata | Due politiche per le letture che non portano un numero utilizzabile (qui sotto). Non è una casella di spunta: il suo « spento » è già una delle risposte. |
| **Limiti** | disattiva | Giudica il valore rispetto a **Min.** (predefinito 0) e **Max.** (predefinito 100) e applica l'azione scelta per i valori fuori intervallo (qui sotto). Gli estremi vengono normalizzati, quindi un Min sopra il Max non fallisce mai: il minore dei due è il pavimento. |
| **Decimali** | attiva | Arrotonda a **Decimali** cifre, predefinito 2, accettato da 0 a 15. |

Entrambe le fasi lineari portano una procedura guidata **Due punti** che calcola la coppia a partire da due punti di riferimento; è descritta passo per passo su [Taratura](connector-calibration#the-two-point-assistant).

## Il dispositivo ha risposto senza un numero {#the-device-answered-without-a-number}

Una termocoppia interrotta, un canale senza sensore: la lettura è arrivata, l'apparecchiatura parla, ma la misura è NaN. Solo tag numerici, e la qualità resta buona in entrambi i casi:

| Politica | Effetto |
| --- | --- |
| **Lascialo passare** (predefinita) | Il NaN viaggia oltre intatto e salta del tutto la fase Limiti, qualunque azione quella fase porti: i limiti giudicano numeri, e qui non ce n'è. L'infinito non è NaN e satura comunque sul campo. |
| **Sostituisci con un valore** | Il numero dichiarato prende il posto da questa fase in poi ed entra in Limiti, Decimali e nella conversione finale come qualunque lettura. |

## Il dispositivo non ha risposto {#the-device-did-not-answer}

Un timeout, un cavo tranciato, un'apparecchiatura spenta, un'eccezione del driver. Ogni tipo, benché a un
tag che legge testo, una marca temporale, un identificatore o un blocco di byte vengano offerte solo le prime due politiche:
un sostituto dichiarato è un numero, e una lettura di quei tipi non lo è.

| Politica | Effetto |
| --- | --- |
| **Mostra l'errore** (predefinita) | Il tag si legge vuoto e la sua qualità diventa cattiva, così il fallimento affiora ovunque nello stesso momento. |
| **Mantieni l'ultimo valore buono** | L'ultima lettura arrivata resta in vista, senza scadenza, finché l'apparecchiatura non risponde di nuovo. Le marche temporali continuano a puntare a quella lettura, perché è quello il momento in cui il numero è stato misurato. Prima che arrivi la prima lettura non viene tenuto nulla; allora il tag si legge vuoto. |
| **Sostituisci con un valore** | Il numero dichiarato viene presentato così com'è dichiarato: non c'è alcuna lettura da far passare per le fasi, quindi non viene scalato, tarato o arrotondato, solo convertito al tipo del valore ingegneristico. Offerta sui tipi numerici e sul Booleano, la cui lettura può nascere da un numero; non su String, DateTime, Guid né ByteString. |

Un sostituto non è mai silenzioso: la scheda Valore in tempo reale stampa il perché (« Ultimo valore buono, mantenuto mentre il dispositivo non risponde. »), il punto in tempo reale diventa ambra, il server OPC UA integrato pubblica il valore con uno stato di sostituzione invece che semplicemente buono, e un agente che legge il tag con `tag_read` sa quale sostituto è (`substitution`). Resta pubblicato per tutto il tempo che la politica richiede: un dispositivo che continua a non rispondere non fa alternare a un client esterno il sostituto e un errore di lettura, quindi quello che quel client legge è quello che il pannello mostra. La lettura stessa si riprende il punto nel momento in cui il dispositivo risponde, e lo stesso fa spegnere il sostituto. Scegliere un sostituto è scegliere la disponibilità, quindi allarmi ed espressioni continuano a giudicare il punto come se avesse un valore; quello che costa viene ripagato alla luce del sole, perché il diario registra comunque la lettura fallita e lo stato di salute riferisce comunque il dispositivo offline. Un sostituto risponde a « che cosa dovrebbe mostrare questo punto », mai a « l'apparecchiatura c'è ». Una sostituzione dichiarata fuori dai limiti abilitati riceve un avviso dove viene scritta: « Fuori dai limiti (da 0 a 100): il valore che sostituisce una lettura non riuscita. »

Una lettura che resta muta conta come una lettura non riuscita. Quando non arriva nessuna nuova lettura per l'intervallo di interrogazione del tag più 10 secondi, come quando un dispositivo accetta la connessione e poi smette di rispondere, la politica qui sopra si applica come se la lettura fosse fallita, per tutto ciò che legge il tag: le espressioni di Logic, le dashboard, ciò che viene registrato e gli agenti. Con **Mostra l'errore** il tag si legge vuoto e la sua qualità diventa cattiva, mentre il server OPC UA integrato tiene sul nodo l'ultimo valore del dispositivo con `UncertainLastUsableValue` invece di Good, così un client esterno vede il numero che aveva e sa che nulla lo rinnova; con un sostituto, il sostituto è presentato e pubblicato come sopra. Gli allarmi mantengono il loro stato finché la qualità è cattiva, come sempre. La scheda Valore in tempo reale dice il perché (« Nessuna nuova lettura è arrivata dopo la marca temporale dell'applicazione. Il tag lo considera una lettura non riuscita. »), le marche temporali continuano a datare l'ultima lettura arrivata, e la prossima lettura che arriva riporta il tag alla normalità.

Un tag di Sola scrittura non ha nessuna di queste politiche. La stazione non lo legge mai, quindi nessuna sua lettura può fallire: finché la stazione non ci scrive, il tag non ha un valore e lo dice, senza sostituto, senza punto ambra e senza niente pubblicato al suo posto su OPC UA, e il pannello non disegna questa riga per esso. Una politica scelta mentre il tag veniva letto resta salvata e viene ignorata finché il tag è di Sola scrittura; torna a valere appena l'accesso è Sola lettura o Lettura e scrittura.

## Valori fuori intervallo {#out-of-range-values}

Le azioni dei **Limiti** per un valore fuori da Min e Max:

| Azione | Il valore diventa | Qualità |
| --- | --- | --- |
| **Nessun valore** | Un vuoto (nessun valore). | buona |
| **Limitazione** (predefinita) | L'estremo più vicino. | buona |
| **Errore e nessun valore** | Un vuoto. | cattiva (guasto sui limiti) |
| **Errore e limitazione** | L'estremo più vicino. | cattiva (guasto sui limiti) |
| **NaN** | NaN. | buona. Offerta solo per i tag Float e Double, il cui tipo la può rappresentare; permette a un canale di Process di classificare il valore non valido. Un'azione NaN lasciata su un tag intero da una scrittura di agente o da un backup ripristinato degrada al vuoto di Nessun valore. |

Un guasto sui limiti confluisce nella qualità effettiva del tag, così il punto in tempo reale, le espressioni delle proprietà e gli allarmi vedono tutti il valore fuori limite come cattivo senza altri collegamenti, e la scheda Conversione stampa « Il valore 130 è fuori dai limiti (da 0 a 100). » Resta comunque una condizione di processo e non un problema di connessione, e lo [stato di salute del dispositivo](connector-health) non conta il dispositivo offline per questo.

## Booleani, stringhe e altri tipi {#boolean-string-and-other-types}

I tipi non numerici hanno le loro trasformazioni nella stessa scheda Conversione:

- **Booleano**: **Inverti** riferisce la negazione logica del valore grezzo.
- **String**: **Inizio della sottostringa** (a partire da 0) e **Lunghezza (vuoto = fino alla fine)** ritagliano una finestra dalla stringa grezza; una lunghezza vuota arriva fino alla fine, e gli estremi fuori intervallo vengono riportati dentro invece di far fallire la lettura.
- Ogni altro tipo (DateTime, Guid, ByteString) passa invariato. La sua scheda Conversione porta solo la fase Lettura non valida, con la politica per il dispositivo che non ha risposto, e un tag di Sola scrittura di quei tipi non mostra alcuna scheda.

Mostra l'errore e Mantieni l'ultimo valore buono valgono per ogni tipo; Sostituisci con un valore è
offerto solo sui tag numerici e booleani, quindi un tag String, DateTime, Guid o ByteString
non lo elenca. Una sostituzione già memorizzata su un tag di uno di quei tipi, come poteva salvarla
una versione precedente, viene obbedita come Mostra l'errore, e il salvataggio successivo del tag,
dal pannello o da un agente, memorizza Mostra l'errore al suo posto. La politica su NaN vale solo
per i tag numerici.

## Le scritture percorrono la catena all'indietro {#writes-reverse-the-pipeline}

Il campo di scrittura della scheda Valore in tempo reale prende un valore ingegneristico e percorre all'indietro, in ordine, le fasi abilitate e invertibili: riporta tra Min e Max quando Limiti è abilitata (una scrittura viene sempre riportata dentro, mai abbandonata, qualunque sia l'azione sui limiti), toglie la taratura (`(valore − Lineare) ÷ Angolare`), toglie la scalatura allo stesso modo, poi converte al tipo del tag. Un tag intero la cui Scalatura o Taratura cambia il valore accetta una frazione: 123,4 su un tag Int16 con scalatura 0,1 scrive 1234. Senza una fase di questo tipo, una frazione scritta in un tag intero viene arrotondata all'intero più vicino, con le metà lontano da zero (2,5 scrive 3). L'arrotondamento perde informazione e non viene percorso all'indietro. Un ingresso booleano riapplica Inverti. Una sottostringa è solo visualizzazione, quindi una scrittura di stringa invia il valore intero così com'è; DateTime, Guid e ByteString passano invariati. Un valore scritto da un client OPC UA esterno sul nodo pubblico è già grezzo e non attraversa nulla di tutto questo.
