Архив

Просмотр 9 сообщений - с 16 по 24 (из 24 всего)
  • Автор
    Сообщения
  • #17105
    vg
    Участник

    Разобрался. Действительно нужно прописывать всю логику внутрь методов подобным этому public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients) и выставлять условия, по которым сервер будет определять когда отрабатывать те или иные методы в модуле.

    Примерный вариант:

    public class ModTestLogic : ModLogic
        {
            public override string Name
            {
                get
                {
                    return "ModTest";
                }
            }
            public const string Path = "какой то путь";
    
            public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients)
            {
                // the method executes when a command has been received
                // метод выполняется после приёма команды ТУ
                if(ctrlCnlNum == 7)
                {
                    SrezTableLight snapshotTable = new SrezTableLight();
                    SrezAdapter adapter = new SrezAdapter();
                    adapter.FileName = @"C:\SCADA\ArchiveDAT\Cur\current.dat";
                    adapter.Fill(snapshotTable);
                    File.Create(Path).Close();
                    using (StreamWriter sw = new StreamWriter(Path, false, System.Text.Encoding.Default))
                    {
                        for (int i = 0; i < snapshotTable.SrezList.Count; i++)
                        {
                            sw.WriteLine(snapshotTable.SrezList.Values[i].ToString());
                        }
                    }
                    File.AppendAllText(Path, "Свободу попугаям");
                }
                WriteToLog("Process command by the module " + Name, Log.ActTypes.Action);
            }
        }

    Правда StreamWriter пока не записывает в txt-файл сохранённый(по крайней мере предполагается, что он сохранён) в таблицу срез, но это я одолею.
    Зато теперь по нажатию кнопки в веб-приложении, благодаря строке кода
    File.AppendAllText(Path, "Свободу попугаям");,

    в нужный файл добавляется текст «Свободу попугаям»!

    Ещё раз спасибо за ответы.

    #17112
    Mikhail
    Модератор

    Если Вы хотите работать с текущим срезом из модуля, используйте объект ServerData, доступный в логике модуля. Здесь его методы.

    #17116
    vg
    Участник

    В продолжение темы работы со своими модулями.

    Набросал пример для формирования файла Word с отчётом. По принятию команды ТУ запускаю шаблон Word и заполняю его значениями.

    Секунды на 4, 5 подвисает веб-приложение, затем отвисает и продолжает работать как обычно.

    Ввиду того, что в коде запускается шаблон документа Word, использую ScadaServerMono, иначе вообще виснет всё и не оживает.

    Засёк время выполнения кода в консольном приложении — около 4 секунд. То есть как раз где то время подвисания.

    Выходит, что если я хочу добиться своего, то мне нужно запускать формирование отчёта в фоновом процессе?

    Собственно сам код:

    public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients)
            {
                // the method executes when a command has been received
                // метод выполняется после приёма команды ТУ
                if (ctrlCnlNum == 7)
                {
                    long dtStart = DateTime.Now.Ticks;
                    long dtEnd;
                    SrezTableLight snapshotTable = new SrezTableLight();
                    SrezAdapter adapter = new SrezAdapter();
                    adapter.FileName = @"C:\SCADA\ArchiveDAT\Cur\current.dat";
                    adapter.Fill(snapshotTable);
                    File.Create(PATH).Close();
                    using (StreamWriter sw = new StreamWriter(PATH, false, System.Text.Encoding.Default))
                    {
                        for (int i = 0; i < snapshotTable.SrezList.Values[0].CnlData.Length; i++)
                        {
                            for (int j = 0; j < inputChannelArray.Length; j++)
                            {
                                if (snapshotTable.SrezList.Values[0].CnlNums[i] == inputChannelArray[j])
                                {
                                    sw.WriteLine(snapshotTable.SrezList.Values[0].CnlData[i].Val.ToString());
                                }
                            }
                        }
                    }
    
                    Word._Application application;
                    Word._Document document = null;
                    Object missingObj = System.Reflection.Missing.Value;
                    Object trueObj = true;
                    Object falseObj = false;
                    //создаем обьект приложения word
                    application = new Word.Application();
                    // создаем путь к файлу
                    Object templatePathObj = REPORT_SCHEME_PATH;
    
                    // если вылетим не этом этапе, приложение останется открытым
                    try
                    {
                        document = application.Documents.Add(ref templatePathObj, ref missingObj, ref missingObj, ref missingObj);
                    }
                    catch (Exception error)
                    {
                        document.Close(ref falseObj, ref missingObj, ref missingObj);
                        application.Quit(ref missingObj, ref missingObj, ref missingObj);
                        document = null;
                        application = null;
                        throw error;
                    }
    
                    Word.Table table = document.Tables[1];
                    table.Cell(1, 2).Range.Text = MACHINE_NAME;
                    table.Cell(2, 2).Range.Text = OPERATION_NUMBER;
                    table.Cell(3, 2).Range.Text = OPERATION_DATE;
                    table.Cell(5, 2).Range.Text = START_TIME;
                    table.Cell(5, 3).Range.Text = END_TIME;
                    table.Cell(6, 2).Range.Text = OPERATOR_SURNAME;
    
                    Word.Table dataTable = document.Tables[2];
                    dataTable.Cell(3, 3).Range.Text = t1VertMin.ToString();
                    dataTable.Cell(3, 4).Range.Text = t1VertMax.ToString();
                    dataTable.Cell(4, 3).Range.Text = t1GorMin.ToString();
                    dataTable.Cell(4, 4).Range.Text = t1GorMax.ToString();
                    dataTable.Cell(5, 3).Range.Text = t2VertMin.ToString();
                    dataTable.Cell(5, 4).Range.Text = t2VertMax.ToString();
                    dataTable.Cell(6, 3).Range.Text = t2GorMin.ToString();
                    dataTable.Cell(6, 4).Range.Text = t2GorMax.ToString();
                    dataTable.Cell(7, 3).Range.Text = t3VertMin.ToString();
                    dataTable.Cell(7, 4).Range.Text = t3VertMax.ToString();
                    dataTable.Cell(8, 3).Range.Text = t3GorMin.ToString();
                    dataTable.Cell(8, 4).Range.Text = t3GorMax.ToString();
                    dataTable.Cell(9, 3).Range.Text = t4VertMin.ToString();
                    dataTable.Cell(9, 4).Range.Text = t4VertMax.ToString();
                    dataTable.Cell(10, 3).Range.Text = t4GorMin.ToString();
                    dataTable.Cell(10, 4).Range.Text = t4GorMax.ToString();
                    dataTable.Cell(11, 3).Range.Text = oMin.ToString();
                    dataTable.Cell(11, 4).Range.Text = oMax.ToString();
    
                    string SAVE_PATH = @"путь_" +
                             DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString() + "_" + 
                             DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + 
                             ".doc";
                    Object pathToSaveObj = SAVE_PATH;
                    document.SaveAs(ref pathToSaveObj, Word.WdSaveFormat.wdFormatDocument, ref missingObj,
                        ref missingObj, ref missingObj, ref missingObj, ref missingObj, ref missingObj, ref missingObj,
                        ref missingObj, ref missingObj, ref missingObj, ref missingObj, ref missingObj, ref missingObj,
                        ref missingObj);
                    dtEnd = DateTime.Now.Ticks;
                    File.AppendAllText(PATH, dtStart.ToString() + " " + dtEnd.ToString());
                    /*try
                    {
                        System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName("Microsoft Word");
                        proc[0].Kill();
                    }
                    catch (InvalidCastException e)
                    {
    
                    }*/
    #17123
    vg
    Участник

    Удалось разрешить проблему подвисания выносом создания отчёта Word в фоновый процесс:

    public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients)
            {
                // the method executes when a command has been received
                // метод выполняется после приёма команды ТУ
                if (ctrlCnlNum == 7)
                {
                    new Thread(ExecWord).Start();   // Вызов ExecWord() в новом потоке.
                }
                WriteToLog("Process command by the module " + Name, Log.ActTypes.Action);
            }

    Собственно метод ExecWord реализуется ниже в этом же классе ModTestLogic : ModLogic

    #17124
    vg
    Участник

    Mikhail, спасибо за наводку по ServerData и его методам.

    #17126
    Mikhail
    Модератор

    Желательно формировать документы Word в новом формате docx без использования технологии COM, чтобы само приложение Word не запускалось. Дело в том, что возможны ситуации, что Word не будет выгружаться из памяти, а будут создаваться его новые и новые процессы.

    #17131
    vg
    Участник

    Mikhail, да, если не убивать процесс, то они остаются в фоновых.

    Поэтому я добавил следующий код:

    try
                {
                    System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName("WINWORD");
                    proc[0].Kill();
                }
                catch (InvalidCastException e)
                {
    
                }
    #17134
    Mikhail
    Модератор

    Формирование отчётов лучше бы вообще вынести в отдельное приложение, т.к. оно имеет более низкие требования к надёжности по сравнению со SCADA-Сервером в целом.

    #17136
    vg
    Участник

    Согласен, всё равно нужно ScadaServerMono запускать. В своём приложении будет проще, но для практики разработки модулей сгодится. 🙂

Просмотр 9 сообщений - с 16 по 24 (из 24 всего)
  • Вы должны авторизироваться для ответа в этой теме.