Salta al contenuto
Nessun risultato
  • Account
  • Articoli e libri
  • bbpress template
  • Calcolatrice legge di Ohm
  • Calcolatrici e convertitori
  • Convertitore Farad condensatori
  • Convertitore Ohm resistenze
  • Convertitore sistema numerico
  • Datasheet
  • Download
  • GeXY… Idea!
  • Login
  • Password Reset
  • Privacy e condizioni
  • Progetti
  • Video list
GeXY
Login/registrati
  • Progetti
  • Forum
  • Risorse
    • Datasheets
    • Calcolatrici & convertitori
    • Libri & articoli
    • Video
GeXY

OpenLab Developer

14
  • Custom port per LogicBlock
  • Creare un project storage
  • Creare un LogicBlock
  • Setup ambiente di sviluppo e installazione librerie
  • Creare un logger storage
  • Creare un plugin base

OpenLab Studio Developer

8
  • Gestore dei tipi di dati
  • Gestore degli errori
  • Schemi validazione configurazione
  • Elenco eventi standard
  • Logger standard
  • Logger base
  • Gestore degli eventi
  • Gestore della UI

GeJSON

3
  • Validazione json
  • Parsing json
  • Uso di GeJSON
View Categories
  • Home
  • OpenLab Docs
  • OpenLab Developer
  • Custom port per LogicBlock

Custom port per LogicBlock

5 min read

OpenLab Studio >= 1.30.0
OpenLab SDK >= 3.0.1
Linguaggi C#
Versione .NET 8

Generale #

Questa guida spiega come creare delle porte custom per un Logic Block. La creazione di una porta custom è necessaria ad esempio per gestire più tipi di dati permessi per la porta o usare un editor custom, oppure per eseguire delle verifiche di sintassi o coerenza sui dati(ad esempio in base al tipo di dato scelto nell’editor).

Un esempio pratico è la porta  Recive packet delimiter del logicblock SerialConnection, della stdlib. In questa porta sono permessi più tipi di delimitatore. Il pacchetto dati può essere delimitato in base alla lunghezza(numero di byte) o ad una stringa(ritorno a capo o una parola).

In questi casi dovremo verificare che i dati specificati immessi sia corretti prima di memorizzare il valore su questa porta, ad essempio, se come delimitatore si una la lunghezza,  l’utente non dovrebbe poter specificare -1 come valore.

Per il setup dell’ambiente di sviluppo e installare il plugin seguire questa guida, il codice completo è reperibile su GitHub

L’esempio completo è disponibile su GitHub

 

Implemetare le basi #

Per creare una porta custom va estesa la classe LogicBlockPort

public class LogicBlockCustomPort : LogicBlockPort
{
    public LogicBlockCustomPort(string name, Type[]? dataType, DataDirection dataDirection) : base(name, dataType, dataDirection){}
}

Al costruttore vengono passati:

  • il nome della porta, che verrà visualizzato sul LogicBlock
  • L’array con i tipi di dati permessi per questa porta
  • La direzione dei dati(input, output, bidirectional)

Tipi di dati fissi #

E’ possibile far in modo che i tipi di dati siano fissi e non possano essere specificati quando si instanzia la porta. Nell’esempio sequente vengono specificati i tipi int,string e l’enum System.Windows.Input.Key. Quando si andrà ad instanziare la porta nel LogicBlock verrà passato null come tipi di dati.

public LogicBlockCustomPort(string name, Type[]? dataType, DataDirection dataDirection) : base(name, [typeof(string), typeof(int), typeof(System.Windows.Input.Key)], dataDirection){}

Usare tipi non base #

Quando si utilizzano tipi non base, ad esempio classi, enum, etc. questi vanno registrati in DataTypes. In questo caso abbiamo bisongo di registrare il tipo System.Windows.Input.Key che è un enum che fa riferimento hai tasti premuti sulla tastiera.

public LogicBlockCustomPort(string name, Type[]? dataType, DataDirection dataDirection) : base(name, [typeof(string), typeof(int), typeof(Key)], dataDirection)
{
    IPluginsManager.commonsTypes.RegisterType("System.Windows.Input.Key", typeof(Key));
}

Per maggiori informazioni sul gestore dei dati guardare qui

Dati da e verso l’editor #

Quando viene aperto l’editor dei dati di una porta, questo, chiama il metodo getDataValueToEditor() che restituisce un istanza della classe DataEditorArgs con i quali vengono passati i dati dalla porta all’editor.

Quando l’editor deve salvare i dati nella porta chiama il metodo setDataValueByEditor() della porta, passandogli l’istanza della classe DataEditorArgs con i dati inseriti nell’editor.

Dopo di che, se non ci sono errori, l’editor chiama il metodo dataValueViewerFormatter() che scrive i dati memorizzati nella porta nel modo corretto secondo il tipo di dato e il valore.

 

Di default setDataValueByEditor() esegue il parse del valore in base al tipo di dato selezionato nell’editor. Gestisce i tipi di base(int,string,etc). Se il parse fallisce viene propagata l’eccezione che è stata lanciata all’interno di questo metodo.

 

DataEditorArgs contiene il valore passato dalla porta all’editor nella propprietà OldValue, mentre quando l’istanza arriva dall’editor il nuovo valore e il tipo scelto per il nuovo valore sono memorizzati rispettivamente in NewValue e Type.

 

In questo esempio verrà fatto l’override dei metodi setDataValueByEditor() e dataValueViewerFormatter() per verificare la correttezza dei dati in arrivo dall’editor e visualizzarli correttamente nella casella accanto alla porta.

override public void setDataValueByEditor(DataEditorArgs args)
{
    try
    {
        if (args.NewValue == null)
        {
            throw new Exception("The value can't be null");
        }


        if (args.Type == typeof(int))
        {
            int val = int.Parse(args.NewValue);
            if (val < 1)
            {
                throw new Exception("The value can't be < 1");
            }

            setData(val, args.OnDataChangeEventTempDisable, false);
        }
        else if (args.Type == typeof(string))
        {
            string val = ((string)args.NewValue);
            if (val == "" || val == string.Empty)
            {
                throw new Exception("The value can't be empty");
            }
            setData(val, args.OnDataChangeEventTempDisable, false);
        }
        else if (args.Type == typeof(Key))
        {
            string val = ((string)args.NewValue).Trim();
            if (val == "" || val == string.Empty || val.ToLower() == "null" || val == null)
            {
                throw new Exception("The value can't be empty or null");
            }

            // check if is insert string key of enum or integer value
            int enumVal;
            if(int.TryParse(val, out enumVal))
            {
                // if passe integer value
                setData(Enum.Parse(typeof(Key),val,true), args.OnDataChangeEventTempDisable, false);
            }
            // Enum.GetName(typeof(Key), 1)


        }

    }
    catch
    {
        throw;
    }

}

public override string dataValueViewerFormatter()
{
    if (data == null)
    {
        return "NULL";
    }
    else
    {
        if (settings.showDataTypeInDataValueViewer)
        {
            return data.GetType().GetElementType().Name;
        }
        else
        {
            if(data.GetType() == typeof(string))
            {
                return (string)data;
            }
            else if (data.GetType() == typeof(Key))
            {
                return "Key." + Enum.GetName(typeof(Key), (int)data);
            }
            else if(data.GetType() == typeof(int))
            {
                return ((int)data).ToString()+" Bytes";
            }
            else
            {
                return "Unknown";
            }
        }
    }
}

Instanziare la porta #

Di seguito un esempio del codice da usare nel LogicBlock per instanziare la porta

public LogicBlockPortTutorial10(IPluginsManager _pluginsManager, IEventsManager _eventsManager, IWindowsManager _windowsManager, InstrumentDefinition instrumentDefinition) : base(_pluginsManager, _eventsManager, _windowsManager, instrumentDefinition)
{
    logicBlockInfo = new Info();

    LogicBlockCustomPort p = new LogicBlockCustomPort("Recive packet delimiter", null, LogicBlockPort.DataDirection.Input);
    p.settings.horizontalPosition = LogicBlockPortDefaultSettings.Position.Left;
    p.settings.onDataChangeOperation = LogicBlockPort.OnDataChangeOperations.None;
    p.settings.onDataChangeOperationEditable = false;
    p.settings.toStartOperation = LogicBlockPort.ToStartOperations.None;
    p.settings.toStartOperationEditable = false;
    p.settings.dataValueEditable = true;
    p.settings.dataTypeEditable = true;
    p.setData(1, true, false);
    addPort(p);
}

 

Updated on 04/05/2026

What are your Feelings

  • Happy
  • Normal
  • Sad

Share This Article :

  • Facebook
  • X
  • LinkedIn
  • Pinterest

Powered by BetterDocs

Table of Contents
  • Generale
  • Implemetare le basi
    • Tipi di dati fissi
    • Usare tipi non base
  • Dati da e verso l'editor
  • Instanziare la porta
Copyright © 2026 - Tema WordPress sviluppato da CreativeThemes