Creating objects from a CSV file with a design-time script

È possibile importare qualsiasi tipo di oggetto utilizzando uno script di design time che legga un file CSV con la descrizione degli oggetti da creare.

Supponiamo ad esempio che si debba importare un CSV contentente descrizioni di allarmi da importare e variabili di modello utilizzate dagli allarmi stessi.

variable,var1,boolean
variable,var2,uint32
...
alarm,alarm1,digital,var1
alarm,alarm2,analog,var2
...

In questo esempio:

  • La prima colonna indica se occorre creare una variabile di progetto (keyword “variable”) oppure un allarme (keyword “alarm”).

  • La seconda colonna indica il nome del nodo da creare.

  • La terza per la variabile indica il dataype da usare per creare la variabile.

  • La terza per l’allarme indica il tipo di allarme da creare: digitale (keywork “digital”) o a limite (keywork “analog”).

  • La quarta colonna per l’allarme indica la variabile a cui fare puntare l’allarme.

Le variabili verranno create dentro la cartella Model, mentre gli allarmi dentro la cartella Alarms.

È possibile inoltre aggiungere delle variabili di modello all’oggetto NetLogic per permettere di configurarlo agevolmente dall’IDE stesso. Nell’esempio sotto mostrato viene usata una variabile di modello CSVPath con datatype Absolute resource URI che permette di selezionare un file in un qualsiasi punto del file system.

Sebbene nell’esempio il file CSV si trovi nella cartella del progetto ProjectFiles, il file potrebbe trovasi in qualsiasi altro punto.

Lo script di esempio è il seguente:

public class AlarmImporter : QPlatform.NetLogic.BaseNetLogic
{
    // Imports a CSV like this:
    //
    // variable,var1,boolean
    // variable,var2,uint32
    // alarm,alarm1,digital,var1
    // alarm,alarm2,analog,var2
    //
    // The first field tells what to create, the second is the name.
    // For variable the third field sets the data type
    // For alarms the third field says what kind of alarm to create and the fourth contains the name of the variable to link

    [QPlatform.NetLogic.ExportMethod]
    public void ImportAlarms()
    {
        // Reads the CSVPath property of the NetLogic. It is configured with datatype Absolute resource URI
        string csvPathVariable = LogicObject.GetVariable("CSVPath").Value;

        var csvPath = new ResourceUri(csvPathVariable).Uri;

        var modelFolder = Project.Current.Get("Model");
        var alarmsFolder = Project.Current.Get("Alarms");

        if (csvPath.Length == 0 || !System.IO.File.Exists(csvPath))
        {
            Log.Error("CSV not found. Please configure the CSV to parse in the NetLogic configuration");
            return;
        }

        // Clear the content of Model and Alarms folders, just for the sake of the example. It let you re-run the command
        // without adding the same alarm or variable again.
        modelFolder.Children.Clear();
        alarmsFolder.Children.Clear();

        string[] lines = System.IO.File.ReadAllLines(csvPath);

        foreach (string line in lines)
        {
            var tokens = line.Split(',');

            if (tokens[0] == "variable")
            {
                NodeId dataType = tokens[2] == "boolean" ? OpcUa.DataTypes.Boolean : OpcUa.DataTypes.UInt32;

                var newVariable = InformationModel.MakeVariable(tokens[1], dataType);
                modelFolder.Add(newVariable);
            }
            else if (tokens[0] == "alarm")
            {
                // Searches the variable to link before creating the alarm
                var inputVariable = modelFolder.GetVariable(tokens[3]);

                AlarmController newAlarm;

                if (tokens[2] == "digital")
                    newAlarm = InformationModel.MakeObject<DigitalAlarm>(tokens[1]);
                else
                    newAlarm = InformationModel.MakeObject<ExclusiveLevelAlarmController>(tokens[1]);

                // Creates a dynamic link from the InputValue property of the Alarm to the actual variable
                newAlarm.InputValueVariable.SetDynamicLink(inputVariable);
                alarmsFolder.Add(newAlarm);
            }
        }
    }
}

Scarica il progetto di esempio da qui.