IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 IToolS basics 1 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Sommario Configurazione di Visual Studio ..........................................................................................................................................................3 Definizione del sistema di comunicazione ..........................................................................................................................................3 Configurazione ed analisi del sistema di comunicazione ....................................................................................................................3 Utilizzo e caratteristiche del componente Variable ............................................................................................................................7 Variable scaling ..............................................................................................................................................................................7 Variable targets ..............................................................................................................................................................................8 Variable events ............................................................................................................................................................................10 Variable advising ..........................................................................................................................................................................11 Variable threading .......................................................................................................................................................................11 Utilizzo e caratteristiche del componente Client ..............................................................................................................................12 Client events ................................................................................................................................................................................13 Utilizzo e caratteristiche del componente IOServer .........................................................................................................................13 IOServer events ............................................................................................................................................................................13 2 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Configurazione di Visual Studio Prima di definire gli oggetti necessari al sistema di comunicazione è necessario impostare l’ambiente di sviluppo per l’utilizzo dei componenti IToolS. Una volta completate queste operazioni preliminari è possibile utilizzare tutti i componenti e controlli IToolS in modo visuale. Per preparare l’ambiente di sviluppo procedere con le seguenti operazioni: 1. 2. 3. 4. 5. 6. 7. Aprire VisualStudio e creare un progetto di tipo Windows Forms Application. Spostarsi con il mouse sulla Toolbox, tasto destro e selezionare “Add Tab.” Nel campo riservato al nome del Tab scrivere “IToolS”. Tasto destro sul nuovo Tab creato e selezionare dal menu a tendina “Choose items…”. Cliccare su “Browse…” e spostarsi nella directory in cui sono presenti gli assemblies IToolS. Selezionare l’assembly “IToolS.Components.dll”. Ripetere i punti 4,5,6 selezionando l’assembly “IToolS.Windows.dll”. La toolbox è ora popolata con tutti i controlli e componenti esposti dal framework IToolS. Definizione del sistema di comunicazione Il sistema di comunicazione IToolS è identificato da un insieme di componenti che consentono di instaurare comunicazioni con dispositivi remoti attraverso protocolli industriali. I componenti che definiscono questo insieme sono: - Group: rappresenta un contenitore di “Variable”. Le Variable (IToolS.Components.Communication.Variable) sono gli oggetti utilizzati per identificare e contenere le informazioni necessarie al sistema per instaurare la comunicazione con i dispositivi remoti: Ad esempio nella Variable è definito il tipo di dato che si vuole gestire, l’offset (indirizzo) del registro remoto che si vuole leggere o scrivere, ecc… - Clients: rappresenta il contenitore dei Client. I client sono degli oggetti che si preoccupano dei corretto aggiornamento delle Variable definite, inoltre mettono a disposizione una serie di metodi per eseguire operazioni sul sistema di comunicazione: Ad esempio sono presenti metodi per la lettura e scrittura delle Variable. - IOServer: questo oggetto è responsabile della corretta creazione del canale di comunicazione, della definizione del tipo di protocollo da utilizzare e della gestione delle richieste che vengono inoltrate dai client. Configurazione ed analisi del sistema di comunicazione Nel paragrafo precedente sono stati identificati gli oggetti che intervengono nel processo di comunicazione, ora analizziamo in modo sommario come è necessario configurare gli oggetti per instaurare una comunicazione con un dispositivo remoto, più avanti saranno presi in considerazione in modo dettagliato anche con un esempio di codice quali sono le proprietà che devono essere impostate per modificare il comportamento del sistema di comunicazione in base alle proprie esigenze. La prima operazione da eseguire per definire il sistema è quello dichiarare quali sono le informazioni che si vogliono leggere o scrivere dal dispositivo remoto, questo in linea di massima significa aver ben chiaro quali sono i registri del dispositivo remoto a cui si vuole accedere. In base ai registri remoti a cui si vuole accedere è necessario aggiungere al componente “Group” una serie di “Variable”, ognuna delle quali è identificata da un indirizzo che porta la variabile ad essere mappata su uno specifico registro del dispositivo remoto. 3 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Un esempio pratico di quanto detto può essere il seguente: Supponiamo di voler accedere in lettura e scrittura ad una specifica locazione di un dispositivo Siemens S7, in particolare al Merker 100 (MB100). Questo significa che vogliamo accedere al byte contenuto nel registro di memoria MB100 del dispositivo remoto. Selezionare un oggetto Group dalla Toolbox e trascinarlo nella Form, selezionare il componente group1 spostarsi sulla Properties Window e cliccare su Items, a questo punto si apre una finestra che consente di aggiungere e rimuovere Variable e modificarne le proprietà, premere una volta il bottone “Add” per aggiungere una Variable al group1. Di seguito viene mostrata la finestra di editor delle proprietà della Variable: Nella finestra di editor a lato è presente una Variable le cui proprietà sono elencate nella griglia, per aggiungere una nuova Variable è sufficiente premere nuovamente il pulsante “Add”. Per mappare la Variable sul registro MB100 è necessario modificare il valore di “Address” della variabile con 100, nel campo “Area” inserire “M” e nel campo “VariableType” selezionare “Byte”, come mostrato nell’immagine a lato.Le proprietà della Variable sono raggruppate in diverse categorie: Address: contiene le proprietà relative all’indirizzamento della Variable Design: contiene le proprietà di progettazione della Variable. IToolS Advanced: In questa categoria comune a tutti i componenti IToolS sono contenute le AdvancedProperties. Le proprietà avanzate sono delle associazioni Nome-Valore che consentono di aggiungere alla Variable delle proprietà da utilizzare in fase di esecuzione o come contenitori di informazioni. Misc: la proprietà VariableLink consente di legare il valore di una Variable a quello di un’altra Variable. Scaling: contiene le impostazioni di scalatura della Variable. Targets: categoria che contiene le impostazioni dei valori obiettivo della Variable (vedi più avanti). Trace: contiene le impostazioni per il tracciamento delle proprietà della Variable in fase di esecuzione Variable: contiene il nome della Variable. 4 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 A questo punto è necessario inserire un oggetto “IOServer” alla form, quindi dalla Toolbox selezionare un oggetto IOServer e trascinarlo sulla form, per completare il sistema di comunicazione è inoltre necessario inserire un oggetto “Clients”: Nella figura a lato sono presenti i tre oggetti fondamentali per il sistema di comunicazione: Group; IOServer; Clients; Questi oggetti opportunamente configurati consentono di instaurare comunicazioni con qualsiasi tipo di dispositivo remoto purché sia presente l’implementazione del protocollo necessario alla comunicazione con il dispositivo desiderato. Una volta aggiunti gli oggetti sopracitati è necessario configurarli, per quanto riguarda l’IOServer è necessario definire il tipo di protocollo da utilizzare e impostare le proprietà di rete e comunicazione in base alle proprie esigenze. Il Clients invece funge da contenitore di oggetti Client ognuno dei quali contiene una proprietà Group ed IOServer. Alla proprietà Group viene associato l’oggetto group1 che abbiamo inserito nella Form, alla proprietà IOServer viene associato l’oggetto ioServer1 che abbiamo inserito nella form. Nella immagine seguente è presente la griglia delle proprietà dell’IOServer: Per la configurazione dell’IOServer è necessario definire innanzitutto il nome del protocollo da utilizzare (proprietà Name). Facendo clieck sul campo Name si apre una finestra di dialogo che consente di selezionare il protocollo di comunicazione da una lista predefinita.Quindi devono essere configurati gli oggetti che definiscono le impostazioni di comunicazione: Config: contiene le impostazioni di funzionamento dell’ioserver: 1. ChannelDelay: consente di impostare un ritardo sull’accesso delle operazioni di lettura e scrittura del canale di comunicazione 2. CyclePeriod: consente di definire il periodo di tempo tra la gestione di una richiesta e l’altra. 3. CycleRequests: consente di definire il numero di richeste per ciclo 4. ReconnectionDelay: consente di definire un ritardo sull’operazione di riconnessione in caso di errori sul canale di comunicazione. 5. SlaveAddress: consente di impostare un indirizzo sul dispositivo remoto (solo se previsto dal protocollo utilizzato). 6. ThreadingRequest: “True” se le richieste inoltrate all’ioserver devono essere gestite da thread separati, “False” altrimenti. 7. Trace: “True” se deve essere abilitata la funzionalità di tracciamento dello stato dell’IOServer. NetConfig: contiene le impostazioni del canale ethernet: 1. Address: indirizzo ip del dispositivo remoto 2. Port: numero della porta socket da utilizzare. SerialConfig: contiene le impostazioni del canale seriale: 1. BaudRate: imposta la velocità di comunicazione. 2. DataBits: imposta il numero dei bit dati da utilizzare nella comunicazione seriale. 5 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 3. 4. 5. Parity: imposta il bit di parità per il controllo errori di comunicazione. PortName: Imposta il nome della porta seriale da utilizzare. StopBits: imposta il numero di bit di stop per il byte. La configurazione dell’IOServer si completa con una serie di ulteriori proprietà utilizzate per estendere la configurabilità di questo componente: - - BlockSize: consente di definire la dimensione della singola richiesta che può essere gestita dell’ioserver. Più precisamente le specifiche dei protocolli di comunicazione impongono che la dimensione del pacchetto trasmesso sul canale di comunicazione rientri entro un certo numero di byte. Questo parametro è dettato sia dal tipo di protocollo sia da limiti funzionali del canale di comunicazione. Inverted: consente di impostare l’ordinamento dei byte all’interno della parola. IOServerTraceEvent: consente di definire per quali eventi deve essere eseguito il tracciamento. Retries: imposta il numero di tentativi da eseguire per richiesta in caso si esito negativo di una operazione sul canale di comunicazione. Timeout: imposta il tempo massimo di attesa per ricevere la risposta sul canale di comunicazione. Trace: abilita la funzionalità di tracciamento dello stato dell’IOServer. TraceProperties: consente di definire quali proprietà devono essere tracciate. Per la configurazione dell’oggetto Clients è necessario selezionarlo, spostarsi sulla Properties Window e cliccare su Items, a questo punto si apre una finestra di dialogo che consente di definire e configurare i vari Client che compongono il sistema. Il Client è un oggetto che ha la funzione di collegamento tra il Group e l’IOServer, gestisce le richieste di aggiornamento automatico delle Variable definite è mette a disposizione del programmatore una serie di metodi ed eventi per eseguire operazioni sul dispositivo remoto attraverso l’ioserver. - Una volta aperta la finestra di editor dell’oggetto Clients è necessario aggiungere i vari Client di cui si necessità, occorre tenere presente che: Ad ogni client deve essere assegnato un Group ed un IOServer. Il Group assegnato al Client non può essere condiviso, ovvero ogni Client deve avere il proprio Group. Lo stesso IOServer può essere assegnato a Client differenti. Aggiunto un client è necessario impostare i parametri di configurazione, nel caso specifico assegniamo alla proprietà Group l’oggetto group1 ed alla proprietà IOServer l’oggetto ioServer1. Tra le ulteriori proprietà presenti nel client traviamo: UpdateTime: imposta il periodo di tempo alla scadenza del quale il client depositerà nella coda delle richieste dell’IOServer una richiesta di aggiornamento delle Variable da esso gestite. ClientProperties: contiene informazioni aggiuntive utili alla corretta configurazione del processo di comunicazione. Ad esempio è presente lo SlaveId, che identifica numericamente il dispositivo con cui si vuole intraprendere un processo di comunicazione all’interno della rete. Tipicamente è utilizzato nelle comunicazioni seriali. ClientTraceEvent: consente di definire per quali eventi deve essere eseguito il tracciamento. Trace: abilita la funzionalità di tracciamento dello stato del Client. TraceProperties: consente di definire quali proprietà devono essere tracciate. Come ulteriore nota è importante far notare che l’oggetto Variable può essere utilizzato anche singolarmente senza il bisogno di essere inserito in un Group e di conseguenza assegnato ad un Client. Il valore della Variable può essere impostato manualmente, 6 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 questo consente di utilizzare i meccanismi interni alla Variable in modo autonomo per soddisfare utilizzi personalizzati. Per impostare il valore della Variable (proprietà Value) è disponibile il metodo SetExternalValue che accetta in ingresso un Object: Esempio: IToolS.Components.Communication.Variable variable1; ... variable1.SetExternalValue(1234); Di seguito è presente un esempio in cui viene definito un sistema di comunicazione minimo in grado di leggere e scrivere il registro 0 dell’area Holding Register (“HR”) per un dispositivo che rende disponibile l’accesso ai dati attraverso il protocollo Modbus ethernet: private IToolS.Components.IOServers.IOServer m_ioServer1 = new IToolS.Components.IOServers.IOServer(); private IToolS.Components.Communication.Clients m_clients1= new IToolS.Components.Communication.Clients(); private IToolS.Components.Communication.Client m_client1= new IToolS.Components.Communication.Client(); private IToolS.Components.Communication.Group m_group1 = new IToolS.Components.Communication.Group(); private IToolS.Components.Communication.Variable m_variable1 =new IToolS.Components.Communication.Variable(); ... m_ioServer1.Name = "ModnetMaster"; m_clients1.Items.Add(m_client1); m_group1.Items.Add(m_variable1); m_client1.IOServer = m_ioServer1; m_client1.Group = m_group1; m_variable1.Area = "HR"; m_variable1.Address = "0"; m_clients1.Start(); Utilizzo e caratteristiche del componente Variable L’oggetto Variable è caratterizzato dal alcuni costrutti in grado di facilitare le funzionalità base che in generale sono richieste per processi di questo tipo ad esempio rappresentazioni del valore assunto dalla Variable in base a scalature lineari e non, oppure la notifica mediante eventi del raggiungimento da parte del valore della Variable di valori obiettivo (utilizzati ad esempio per la gestione di allarmi). Variable scaling Nell’immagine a lato evidenziato in rosso sono presenti le impostazioni per definire le proprietà di scalatura che deve avere l’oggetto Variable: ScalingMode: definisce il tipo di scalature da applicare: a. None: nessuna scalatura; b. Expression: le regole di scalatura sono definite in base all’espressione assegnata alle proprietà Expression ed InverseExpression; c. Linear: le regole di scalatura sono definite da una rappresentazione lineare in cui il valore minimo è definito da MinValue ed il valore massimo da MaxValue; d. Factor: al valore della Variable è applicato il fattore di scalatura definito dalla proprietà Factor; e. MinMax: il valore della variabile è limitato dai valori assegnati alle proprietà MinValue e MaxValue; Expression: definisce l’espressione da applicare al valore della Variable nel caso in cui ScalingMode sia impostato su Expression; InverseExpression: definisce l’espressione inversa da applicare al valore della Variable nel caso in cui ScalingMode sia impostato su Expression; 7 IToolS basics Version 1.1 - - Iprel Progetti s.r.l. 31/10/2011 Factor: definisce il fattore moltiplicativo da applicare al valore della Variable nel caso in cui ScalingMode sia impostato su Factor; MaxValue: nel caso in cui ScalingMode sia impostato su Linear definisce l’estremo superiore dell’espressione lineare che regola la scalatura, nel caso in cui ScalingMode sia impostato su MinMax definisce il massimo valore che può assumere la Variable. MinValue: nel caso in cui ScalingMode sia impostato su Linear definisce l’estremo inferiore dell’espressione lineare che regola la scalatura, nel caso in cui ScalingMode sia impostato su MinMax definisce il minimo valore che può assumere la Variable. Oltre alle possibili impostazioni di scalatura evidenziate è possibile implementare un’interfaccia specifica in grado di definire scalature complesse e completamente personalizzabili: Esempio: class MyScaling : IToolS.Data.IValueScale { public object Scale(IToolS.Data.IVariableInternal variable, object value) { return Convert.ToInt32(value) * 2; } public object Unscale(IToolS.Data.IVariableInternal variable, object value) { return Convert.ToInt32(value) / 2; } } ... m_variable1.SetValueScale(new MyScaling()); Variable targets Attraverso I target è possibile gestire stati particolari della Variable come ad esempio il raggiungimento o meno di valori obiettivo. In base allo stato del target è possibile ad esempio definire se una certa condizione del processo deve essere dichiarato come di allarme e di conseguenza eseguire o meno certe azioni necessarie per la corretta esecuzione. La proprietà CheckTargetMode definisce la modalità di controllo dello stato del target, questa proprietà può essere impostata come: a. VariableChange: il controllo dello stato del target viene eseguito ad ogni variazione del valore della Variable. b. VariableUpdate: il controllo dello stato del target viene eseguito ad ogni aggiornamento del valore della Variable. c. Manually: Il controllo dello stato dei target associati alla Variable deve essere esplicitamente eseguito invocando in metodo CheckTargets(): Esempio: ... m_variable1.CheckTargets(); Selezionando la proprietà Targets e cliccando sul bottone che appare alla destra di “(Collection)”, si apre una finestra di dialogo che consente la definizione dei target da associare alla Variable. Non vi sono limiti sul numero di target che possono essere definiti per una singola Variable. L’unico vincolo è piuttosto dettato da un incremento (seppur limitato) del ciclo di programma. Lo stato del target è regolato da un valore che lo definisce in “Reached” (raggiunto) o “Failed (fallito). Ogni qualvolta lo stato del target passa in “Reached” viene generato un evento di TargetReached. Ogni qualvolta lo stato del target passa in “Failed” viene generato un evento di TargetFailed”. Per definire quali sono i valori della Variable che provocano o meno lo 8 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 stato di Reached è necessario in primo luogo aggiungere un target quindi definirne le caratteristiche. La finestra di dialogo seguente consente di impostare tutte le proprietà principali che definiscono le caratteristiche del target. - - Category: definisce la categoria del target, si tratta di una stringa che ha la funzione di raggruppare i target in categorie utili, ad esempio nel caso in cui i target siano utilizzati come allarmi, per definire se un certa categoria debba essere serializzata o meno. Può anche essere utilizzata per definire il colore che il visualizzatore degli allarmi deve assumere per una certa categoria. Description: consente di definire una descrizione per il target, nel caso il target sia un allarme definisce il messaggio di allarme. Group: consente di raggruppare i target in gruppi, la sola funzionalità di questa proprietà è quella di utilità per i meccanismi di filtraggio ad esempio degli allarmi. Name: definisce il nome del target, ogni target deve essere identificato da un nome univoco che consente di identificare in modo inequivocabile ciuscun target. Priority: consente di impostare una priorità al target. Se il target è utilizzato per gestire degli allarmi, attraverso questa proprietà è possibile definire quale target deve essere visualizzato in modo prioritario nel banner degli allarmi. LowerValue: definisce il minimo valore del range entro il quale il target si può considerare raggiunto “Reached”. UpperValue: definisce il massimo valore del range entro il quale il target si può considerare raggiunto “Reached”. Ci sono poi ulteriori proprietà che definiscono le caratteristiche ed il comportamento del target : - - - CustomProperties: ogni target ha una lista di proprietà personalizzate che possono essere definite in fase di progettazione. Nel caso in cui il target sia utilizzato come allarme, questa lista di oggetto personalizzati sarà serializzata nei dispositivi di archiviazione. AdvancedProperties: ogni target ha una lista di proprietà avanzate che possono essere definite in fase di progettazione. Nel caso in cui il target sia utilizzato come allarme, questa lista di oggetto personalizzati non sarà serializzata nei dispositivi di archiviazione. ActiveTime: consente di ottenere l’istante di tempo in cui il target si è portato in stato di raggiunto. DeActiveTime: consente di ottenere l’istante di tempo in cui il target si è portato in stato di fallito. GuidCode: identificativo univoco di ciascun target. TargetState: consente di ottenere o impostare lo stato del target. VariableTargetCheck: consente di assegnare al target una interfaccia personalizzata in grado di valutare lo stato del target, normalmente questa proprietà ha valore nullo. Esempio: class MyTargetCheck : IToolS.Data.IVariableTargetCheck { public int GetTargetState(IToolS.Data.IVariableInternal variable, IToolS.Data.VariableTarget target, object value) { if (Convert.ToInt32(value) == 10) return IToolS.Data.VariableTarget.REACHED; else return IToolS.Data.VariableTarget.FAILED; } } ... m_variable1.Targets[0].VariableTargetCheck = new MyTargetCheck(); 9 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Attraverso l’implementazione di questa interfaccia è possibile definire meccanismi di controllo del valore della Variable personalizzati e complessi. La Variable dispone inoltre di un ulteriore caratteristica in grado di rendere personalizzabile la conversione del valore in essa contenuto. Per fare un esempio concreto si può pensare al caso in cui il valore contenuto nella variabile è definito da un intero a 16 bit ma si vuole gestire solo il byte alto o byte basso di questo valore. Esempio: class MyConverter : IToolS.Data.IValueConverter { public object Convert(IToolS.Data.IVariableInternal variable, object value) { int val = 0; int l = System.Convert.ToInt32(value); val = (byte)(l & 0xFF); if (val > 127) val = val - 256; return val; } public object Unconvert(IToolS.Data.IVariableInternal variable, object value) { int l; object oRet = 0; int oldValue = 0; oldValue = System.Convert.ToInt32(variable.TypeBase.MemoryValue) & 0xFF00; l = System.Convert.ToInt32(value) & 0xFF; oRet = (object)((int)(l) | (int)oldValue); variable.TypeBase.MemoryValue = oRet; return oRet; } } ... m_variable1.SetValueConverter(new MyConverter()); Variable events Per semplificare lo sviluppo dell’applicazione, che dovrà ad esempio gestire il processo produttivo o monitorare lo stato di un impianto industriale, l’oggetto Variable mette a disposizione un serie di eventi e proprietà in grado di notificare ad ogni variazione di stato gli oggetti che la stanno osservando. Di seguito sono elencati e descritti i vari eventi che caratterizzano l’oggetto Variable: - - Changed: evento generato ogni qual volta il valore della Variable viene modificato. Updated: evento generato ogni qual volta il valore della Variable viene aggiornato. PropertyChanged: evento generato come conseguenza della modificata di una qualsiasi proprietà della Variable. StateChanged: evento generato ad ogni variazione dello stato della Variable. Lo stato della Variable è contenuto e può essere ottenuto dall proprietà “State”, tra i valori che può assumere questa proprietà troviamo: a. None: lo stato della Variabile non è definito. b. Error: la Variable si trova in stato di errore. c. Changed: il valore della Varible è stato modificato. d. Updated: il valore della Variable è stato aggiornato. e. Valid: la definizione della Variable è considerata valida. f. NotValid: la definizione della Variable è considerata non valida. SynchronizationContextChanged: evento genrato ogni qual volta il contesto di sincronizzazione. TargetAdd: evento generato all’atto di inserimento di un nuovo target. TargetRemove: evento generato all’atto di rimozione di un target. TargetReached: evento generato ogni qual volta il target viene raggiunto. TargetFailed: evento generato ogni qual volta il target viene fallito. ValueChanged: evento generato ogni qual volta la proprietà Value cambia valore. (vedi evento Changed). NotifyEvent: evento generato ogni qual volta la proprietà Value cambia valore. (vedi evento Changed). 10 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Variable advising Mediante il Variable advising è possibile attivare o disattivare la richiesta di notifica del valore di una Variable in base a condizioni particolari in cui di trova l’applicazione. Normalmente questo meccanismo è disattivato in quanto il valore di default della proprietà “ActiveAdvise” presente nell’oggetto Variable è impostata a “false”. Nel caso in cui l’advise della Variabile viene attivato per richiedere la notifica del valore è necessario invocare il metodo AttachAdvise, al contrario per disattivare la notifica del valore è necessario invocare il metodo DetachAdvise. Esempio: private Guid guid = Guid.NewGuid(); private IToolS.Components.Communication.Variable m_variable1; ... // attivazione del meccanismo di advising m_variable1.ActiveAdvise = true; ... // la notifica della Variable viene abilitata m_variable1.AttachAdvise(ref guid); ... // la notifica della Variable viene disabilitata m_variable1.DetachAdvise(ref guid); Questo costrutto risulta particolarmente utile per tutti quei sistemi in cui occorre limitare il traffico dati o in cui il numero complessivo di dati che vengono scambiati con il dispositivo remoto risulta particolarmente elevato. Un esempio concreto può essere costituito da un applicazione in cui le Variable che vengono notificate sono solo quelle presenti nella finestra attualmente visualizzata. Le Variable in cui sono stati definiti dei target hanno sempre la notifica attivata, questo vincolo è stabilito dal fatto che per verificare lo stato del target il valore deve costantemente essere aggiornato. Variable threading L’oggetto Variable nel corso della sua vita viene gestito e modificato da thread differenti, questo consente di poter eseguire un modo parallelo operazioni differenti e di non bloccare l’esecuzione del codice principale nel caso in cui si verifichi l’attesa da parte di una certa operazione il verificarsi ci una certa condizione. Al contrario, questa gestione in multi-threading provoca o può provocare problemi di serializzazione degli eventi o nel caso in cui siano essi utilizzati per impostare proprietà in controlli grafici, dare luogo a problemi di cross-threading. Per evitare questi noiosi problemi che devono poi essere gestiti propriamente dal programmatore è presente in ogni componente IToolS e quindi anche nell’oggetto Variable un proprietà statica “RaiseEventOnMainThread”. Se questa proprietà è impostata a “true” tutti gli eventi generati dal framework IToolS vengono re instradati sul thread principale evitando così di dover gestire a valle i problemi di sincronizzazione evidenziati. Per far si che gli eventi siano re instradati sul thread corretto è disponibile un metodo comune a tutti i componenti che permette di impostare il contesto di sincronizzazione Esempio: m_variable1.SetSynchronizationContext(System.Threading.SynchronizationContext.Current); Attraverso questo metodo è possibile reimpostare il contesto di sincronizzazione nel caso in cui per vari motivi sia esso non corretto. Il contesto di sincronizzazione è normalmente impostato nel momento in cui viene creato l’oggetto (all’invocazione del costruttore), sono però presenti casi in cui per varie ragioni l’oggetto potrebbe essere creato da un thread secondario, in questi casi è possibile modificare il contesto di sincronizzazione attraverso il metodo evidenziato sopra in modo da evitare sincronizzazione sbagliate che darebbero luogo a risultati non attesi. 11 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Utilizzo e caratteristiche del componente Client L’oggetto client svolge funzionalità di gestione ed accesso al sistema di comunicazione, in particolare si occupa di mantenere aggiornate, in base al tempo di aggiornamento impostato, tutte le Variable presenti nel Group ad esso assegnato, inoltre mette a disposizione diversi metodi per eseguire operazione di accesso ai dati come letture e scritture. Nel momento in cui viene invocato il metodo “Start” vengono eseguiti i raggruppamenti delle Variable in modo da ottimizzare il processo di aggiornamento, un thread viene creato ed attraverso la propria esecuzione deposita una richiesta di aggiornamento delle Variable, contenute nel Group assegnato, nella coda delle richieste dell’IOServer. La frequenza con cui avviene questo deposito della richiesta è dettata dal valore della proprietà “UpdateTime” espressa in millisecondi, se il valore presente nella proprietà UpdateTime è maggiore di zero l’aggiornamento sarà periodico, diversamente nel caso in cui il valore di UpdateTime è uguale a zero viene inserita una sola richiesta all’atto dell’invocazione del metodo di start, infine se il valore di UpdateTime è minore di zero non viene depositata alcuna richiesta di aggiornamento. Riassumento: - UpdateTime > 0: aggiornamento ciclico, deposito di una richiesta di aggiornamento ogni “UpdateTime” millisecondi. UpdateTime = 0: viene depositata una sola richiesta di aggiornamento all’invocazione del metodo di “Start”. UpdateTime < 0: non viene depositata alcuna richiesta di aggiornamento. L’aggiornamento delle Variable deve essere eseguito manualmente. L’oggetto Client dispone di un overload di metodi grazie ai quali è possibile leggere e scrivere in modo sincrono o asincrono il valore di oggetti di tipo Variable: Operazioni asincrone: sono operazioni che non provocano il blocco dell’esecuzione del codice. Attraverso i metodi asincroni le richieste di accesso ai dati vengono depositate nella coda delle richieste dell’ioserver, che a sua volta le soddisferà in base ai parametri di schedulazione in esso definiti: o void ReadAsync(Variable[] variables, ClientResultEventHandler readCallBack, long deadline); Permette di leggere un gruppo di Variable in modo asincrono, questo significa che l’invocazione di questo metodo genera una richiesta che viene depositata nell’IOServer. È possibile indicare un metodo di “callback” da richiamare al termine dell’esecuzione della richiesta. La “deadline” indica la scadenza in millisecondi entro cui la richiesta dovrebbe essere soddisfatta, attraverso questo parametro è possibile dare una priorità alla richiesta. o void WriteAsync(Variable[] variables, object[] values, ClientResultEventHandler writeCallBack, bool reRead, long deadline); Attraverso I metodi di scrittura asincrona è possibile depositare un richiesta di scrittura di un gruppo di Variable, specificando i valori che si vogliono impostare (parametro “values”). Come per il metodo di lettura asincrona è possibile indicare un metodo di “callback” da richiamare al termine dell’esecuzione della richiesta. Il parametro “reRead” consente di indicare se prima di eseguire la scrittura le Variable specificate debbono essere aggiornate. Per la “deadline” valgono le stesse considerazioni fatte per il metodo di lettura asincrona. o void UpdateAsync(ClientResultEventHandler callBack, long deadline); Deposita nella coda delle richieste dell’IOServer una richiesta di aggiornamento del Group di Variable assegnato al Client. Per i parametri di “callback e “deadline” valgono le considerazioni fatte per i due precedenti metodi. Operazioni sincrone: sono operazioni che provocano il blocco dell’esecuzione del codice, ciò vale a dire che al ritorno dall’invocazione dei metodi sincroni l’operazione di accesso ai dati è stata completamente eseguita. o ClientResult ReadSync(Variable[] variables); Esegue la lettura di un gruppo di Variable, il valore di ritorno contiene tutte le informazioni circa le operazioni che sono state effettuate durante l’esecuzione di questo metodo. o ClientResult WriteSync(Variable[] variables, object[] values, bool reRead); 12 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Esegue la scrittura di un gruppo di Variable specificando I valori da impostare per ciascuna di esse (parametro “values”), il valore di ritorno contiene tutte le informazioni circa le operazioni che sono state effettuate durante l’esecuzione di questo metodo. o ClientResult UpdateSync(); Esegue l’aggiornamento in modo sincrono di tutte le Variable presenti nel Group assegnato al Client, il valore di ritorno contiene tutte le informazioni circa le operazioni che sono state effettuate durante l’esecuzione di questo metodo. Attraverso i metodi di “Start” e “Stop”, già citati in precedenza, è possibile rispettivamente avviare o arrestare il ciclo di esecuzione in grado di mantenere aggiornate le Variable del Group assegnato in modo automatico. Client events Come per l’oggetto Variable anche il Client possiede una lista di eventi in grado di notificare gli osservatori che si sono registrati sulle operazioni di accesso ai dati. Di seguito sono elencati e descritti i vari eventi che caratterizzano l’oggetto Client: - - EndAsyncRead: Evento generato al termine dell’esecuzione di una richiesta di lettura asincrona depositata attraverso il metodo di ReadAsync. EndAsyncWrite: Evento generato al termine dell’esecuzione di una richiesta di lettura asincrona depositata attraverso il metodo di WriteAsync. EndAutoUpdate: Evento generato al termine di ogni ciclo di aggiornamento automatico delle Variable presenti nel Group assegnato al Client. EndUpdate: Evento generato al termine di una richiesta di aggiornamento depositata attarverso il metodo di UpdateAsync. EndFirstUpdate: Evento generato al termine del primo aggiornamento automatico delle Variable presenti nel Group assegnato al Client. EndRequest: Evento generato al termine di ogni richiesta completata dall’IOServer. I metodi di accesso ai dati che sono stati menzionat, provocano la generazione di diverse richieste ognuna delle quali contiene le informazioni sull’operazione da eseguire su una o più Variable. EndSyncRead: Evento generato al completamento di un’operazione di lettura sincrona. EndSyncWrite: Evento generato al completamento di un’operazione di scrittura sincrona. BeginUpdate: Evento generato ogni qualvolta il processo di aggiornamento di un insieme di Variable sta iniziando. Utilizzo e caratteristiche del componente IOServer L’oggetto IOServer svolge la funzione di collettore di tutte le richieste di accesso ai dati che devono essere eseguite su un dispositivo remoto. La gestione delle richieste che vengono depositate dai vari Client avviene attraverso un thread secondario che estrae ed esegue dalla coda la richiesta più prioritaria, al termine dell’esecuzione della richiesta vengono richiamati i metodi di callback (se previsti). Differente è il caso in cui il Client richiede l’esecuzione di un’operazione sincrona, in questa situazione non viene depositata alcuna richiesta ma viene sincronizzato l’accesso al canale di comunicazione con le altre operazioni mediante un costrutto di accesso concorrente. Se lo stesso oggetto IOServer viene assegnato a Client differenti, questi condividono tra loro l’accesso al dispositivo remoto mediante le regole di sincronizzazione ed i parametri di schedulazione impostati sull’IOServer. IOServer events L’oggetto IOServer consente, ad oggetti osservatori opportunamente registrati, di essere notificati al verificarsi di eventi generati dalle operazioni eseguite durante il processo di comunicazione con il dispositivo remoto. 13 IToolS basics Version 1.1 Iprel Progetti s.r.l. 31/10/2011 Di seguito sono elencati e descritti i vari eventi che caratterizzano l’oggetto IOServer: - Changed: evento generato quando la proprietà “Name” dell’IOServer, e quindi il protocollo utilizzato, viene modificata. Connected: evento genrato nel momento in cui l’IOServer riesce ad instaurare una connessione con il dispositivo remoto. Disconnected: evento generato nel momento in cui viene interrotta la comunicazione con il dispositivo remoto. EndRequest: evento generato al completamento dell’esecuzione di ciascuna richiesta (vedi EndRequest per l’oggetto Client). Error: errore genrato ogni qual volta si verifica un errore nel processo di comunicazione. Exchanged: evento generato ogni qual volta vengono scambiati dati con il dispositivo remoto. Running: evento generato nel momento in cui l’IOServer passa nello stato di esecuzione e quindi si trova pronto per prendere in carico le richieste depositate dai Client. StateChanged: evento generato nel momento in cui lo stato dell’IOServer viene modificato, lo stato che l’IOServer può assumere sono: a. b. c. d. e. f. - Unknow: l’IOServer si trova in uno stato non sconosciuto Connecting: l’IOServer sta tentando la connessione al dispositivo remoto. Connected: l’IOServer è riuscito ad instaurare una connessione con il dispositivo remoto. Running: l’IOServer è pronto a ricevere richieste da parte del Client. Stopped: l’IOServer è stato arrestato e non è in grado di gestire alcuna richiesta. Error: l’IOServer di trova in uno stato di errore. Stopped: evento generato nel momento in cui l’IOServer viene arrestato. TraceEvent: evento generato nel momento in cui viene eseguita un’operazione tracciamento sullo stato dell’IOServer. 14