Генерация архива средствами скрипта может потребоваться в различных ситуациях, но чаще всего это требуется если необходимо обрабатывать внешние архивные источники данных – файлы или базы данных. В качестве примера рассмотрим чтение архива из CSV файла.
Допустим у нас существует CSV файл, из которого нужно периодически (по сигналу) выполнять считывание данных с последующей записью в архив. CSV файл состоит из 6 столбцов – метки времени в формате Дата-Время, и 5 вещественных значений, поля разделены символом «точка с запятой».



using System.IO; |
Приступим написанию кода. В секции класса объявим переменную M, в которую будем сохранять значение входа «Считать» - для выполнения кода по переднему фронту на входе. Также перед тем как выполнять код нужно убедится, что задан путь файла. Для этого проверим его на значение Null, а также убедимся, что имя не пустое – для этого нужно сравнить ее со свойством string.Empty или просто с пустой строкой - "".
public partial class ФБ : ScriptBase { bool? M=false; public override void Execute() { if (Считать==true && M==false && Файл!=string.Empty && Файл!=null) { } M=Считать; } } |
Для того чтобы открыть файл на чтение, создадим класс StreamReader. При создании класса вызывается его конструктор (метод который позволяет инициализировать параметры класса). Конструкторов у данного класса несколько (так называемый перегруженный конструктор). Мы вызовем конструктор с одним параметром – именем файла. Описание данного конструктора можно прочитать здесь:
https://msdn.microsoft.com/ru-ru/library/f2ke0fzy(v=vs.110).aspx
Поскольку у нас файл содержит только цифры и несколько символов, такого вызова будет достаточно. Однако если читать файл, содержащий символы (особенно кириллические), то следует вызывать метод с тремя аргументами – именем, кодировкой и флагом обнаружения порядка байта:
https://msdn.microsoft.com/ru-ru/library/ms143457(v=vs.110).aspx
При этом класс StreamReader мы вызовем через оператор using(не путайте с директивой using). Данный оператор предназначен для работы с неуправляемыми ресурсами – файлами, SQL соединениями и т.д. Вызов через данный оператор гарантирует очищение памяти после выполнения кода.
using(var file = new StreamReader(Файл)) //открытие файла для чтения { //здесь мы разместим код чтения файла } |
Итак, у нас создана переменная file, которую мы будем использовать для работы с нашим файлом. Файл состоит из строк, нам необходимо построчно считывать его, разбирать строку на компоненты (метка времени и значения) и записывать на выходы.
Для считывания строки используется метод ReadLine, метод возвращает строку.
var line=file.ReadLine();//считывание строк из файла |
var line=file.ReadLine();//считывание строк из файла while (line!=null) { //здесь мы обработаем строку line = file.ReadLine(); } |
String[] substrings = line.Split(';'); //разбор строки на составляющие |
var Time = DateTime.Parse(substrings[0]); |
При обработке времени, необходимо иметь ввиду, что при записи в архив MasterSCADA время должно быть в формате UTC (по Гринвичу). Если в вашем файле метки времени представлены в локальном времени, то необходимо сделать преобразование в формату UTC. Для этого есть специальный метод - ToUniversalTime.Пример:
Time = Time.ToUniversalTime(); |
SetValue("Выход", new PinValue(Value,Time)); |
Как можно видеть создается класс PinValue, в конструктор которого передается значение и метка времени.
Имена выходов у нас имеют имена Параметр1..Параметр5. Можно сделать 5 строк вызывающих метод SetValue, либо произвести запись в цикле. Остановимся на втором варианте – реализуем его с помощью цикла for.
for (int i=1;i<=5;i++) { SetValue("Параметр"+i.ToString(), new PinValue(Double.Parse(substrings[i]),Time)); } |
public partial class ФБ : ScriptBase { bool? M=false; public override void Execute() { if (Считать==true && M==false && Файл!=string.Empty && Файл!=null) { using(var file = new StreamReader(Файл)) //открытие файла для чтения { var line=file.ReadLine(); while (line!=null) { String[] substrings = line.Split(';'); //разбор строки на составляющие var Time = DateTime.Parse(substrings[0]); for (int i=1;i<=5;i++) { SetValue("Параметр"+i.ToString(), new PinValue(Double.Parse(substrings[i]),Time)); } line=file.ReadLine();//считывание строк из файла } } } M=Считать; } } |

MasterSCADA.Hlp.Pins.PinQuality |
var qual= new MasterSCADA.Hlp.Pins.PinQuality(192); |
var qual= new MasterSCADA.Hlp.Pins.PinQuality(192); SetValue("Параметр"+i.ToString(), new PinValue(Double.Parse(substrings[i]),qual,Time)); |
Скрипт можно считать завершенным, однако полезно обеспечить защиту кода от ошибок, например, если файла не окажется по указанному пути. Для этого используются операторы try – catch. Оператор try в случае появления исключения перехватывает исключение, и передает оператору catch. Это позволяет корректно обработать ошибки и должны образом проинформировать пользователя.
Пример описанного скрипта для чтения CSV файла, дополненного обработкой ошибок через try-catch с выводом сигнала ошибки на выход ФБ и в лог скады можно скачать по этой ссылке.