Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Вопросы по скриптам в Simple-Scada 2  (Прочитано 1222495 раз)

KungLao

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1260 : 18 Августа 2021, 06:40:33 »
Спасибо. Но наверное вы меня не правильно поняли. Кнопка и подсветка не в СКАДе. Это физическая кнопка (в OPC - Btn1), которая расположена на фабрике, и подсветка тоже на этой кнопке (24в постоянки которые коммутируются выходом контроллера (К1 в OPC)). И условие немного отличается, при повторном нажатии ( при условии, что уже прошло n секунд с момента последнего нажатия) на эту кнопку таймер должен сбрасываться, а вот если ее не нажимать(переменная Btn1 не изменялась) то по истечению 120 минут лампа на кнопке должна начать мигать.
« Изменён: 18 Августа 2021, 06:50:57 от KungLao »

KungLao

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1261 : 25 Августа 2021, 08:42:27 »
 По предыдущему вопросу все получилось отлично. Работает. Подскажите пожалуйста еще один момент? как реализовать маршрут: т.е. чтобы регистрация нажатия кнопок проходила только в определенной последовательности. Допустим есть кнопки Btn1, Btn2, Btn3 они находятся в помещении повышенной опасности, которое с заданной периодичностью должно осматриваться. Но осмотр должен идти по строго заданному маршруту, вдоль которого и расположены эти кнопки. Если кнопки нажаты не последовательно, то регистрация нажатия должна происходить с пометкой о нажатии не в правильной последовательности в виде сообщения.

Timothy Clement

  • Постоялец
  • ***
  • Сообщений: 166
  • ОАО Борисовский завод "Металлист"
    • Просмотр профиля
    • Полымя
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1262 : 25 Августа 2021, 09:41:46 »
Если кнопки нажаты не последовательно, то регистрация нажатия должна происходить с пометкой о нажатии не в правильной последовательности в виде сообщения.
Как один из вариантов решения задачи - Создать внутреннюю переменную типа Word, скрипт "Изменились переменные" - Btn1, Btn2, Btn3
Код: (delphi)
//Скрипт по изменению переменных Btn1, Btn2, Btn3. BtnWord внутренняя переменная типа Word
begin

  if Btn1.AsBool = True then
    BtnWord.Value := SetBit(BtnWord.Value, 0, True); //Если нажата кнопка 1 устанавливаем во внутренней переменной бит 0
  if Btn2.AsBool = True then
    BtnWord.Value := SetBit(BtnWord.Value, 1, True); //Если нажата кнопка 2 устанавливаем во внутренней переменной бит 1
  if Btn3.AsBool = True then
    BtnWord.Value := SetBit(BtnWord.Value, 2, True); //Если нажата кнопка 3 устанавливаем во внутренней переменной бит 2

   if BtnWord.Value=0 then Exit                                                                                   
   else if (BtnWord.Value<>1) and (BtnWord.Value<>3) and (BtnWord.Value<>7) then            //Нарушена последовательность нажатия
     AddMessage(Now, mkWarning, 'Нарушен маршрут осмотра помещения ...', True, False)
   else if BtnWord.Value=7 then BtnWord.Value := 0;       //Маршрут пройден, обнулить слово

end.
« Изменён: 25 Августа 2021, 11:48:36 от Timothy Clement »

KungLao

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1263 : 26 Августа 2021, 08:06:41 »
Спасибо. подскажите пожалуйста как модифицировать ваш скрипт, я задачу немного упростил. У меня на обьекте есть кнопки с световой индикацией, по истечению заданного промежутка времени они начинают мигать (в скада это сопровождается визуализацией), также выводится соответствующее сообщение. Мигание осуществляется посредством изменения переменной в плк. Как с помощью этого скрипта сделать так, чтобы мигание прекратилось только тогда, когда нажались все три кнопки(не одновременно и не обязательно в строгой последовательности) и в этот момент сбросилась переменная vrTimer в 0, чтобы начать отсчет по новой?
« Изменён: 26 Августа 2021, 12:32:51 от KungLao »

pan2000

  • Постоялец
  • ***
  • Сообщений: 226
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1264 : 26 Августа 2021, 20:17:22 »
   Здравствуйте.

Сброс таймера vrTimer в 0 по трем кнопкам Btn1, Btn2, Btn3 с управлением подсветкой кнопок К1, К2, К3.
Предполагается, что кнопки реагируют на нажатие только при завершению интервала контроля, т.е. когда кнопки мигают. Нажатия кнопок запоминаются в переменной состояние кнопок vrBtnState. Для разрешения реагирования на кнопки в любой момент времени достаточно удалить условие проверки состояния таймера: (vrTimer.AsInt < (Tmax - 2)).
После нажатия всех трех кнопок может выполняться проверка на правильный порядок нажатия 1-2-3 или 3-2-1.
Скрипт "Изменились переменные Btn1, Btn2, Btn3":
Код: (delphi)
const Tmax = 120 * 60;       // константа используется в двух скриптах - её можно перенести в глобальный модуль
begin
  if vrTimer.AsInt < (Tmax - 2) then exit;  // интервал контроля ещё не истек (рано кнопки нажимать). Для исключения контроля удалить оператор
  if not Variable.AsBool then exit;         // переход в false - игнорировать
  if Variable = btn1 then begin K1.Value := 29; vrBtnState.Value := SetBit(vrBtnState.AsInt, 0, true); end;    // запомнить нажатые кнопки
  if Variable = btn2 then begin K2.Value := 29; vrBtnState.Value := SetBit(vrBtnState.AsInt, 1, true); end;
  if Variable = btn3 then begin K3.Value := 29; vrBtnState.Value := SetBit(vrBtnState.AsInt, 2, true); end;

// СОСТОЯНИЕ КНОПОК - другой оператор должен быть закомментирован или удален
//  этот оператор контролирует порядок нажатия кнопок 1-2-3 или 3-2-1
  case vrBtnState.AsInt of
  2, 5: vrBtnState.Value := SetBit(vrBtnState.AsInt, 3, true);   // установить флаг ошибки порядка нажатия кнопок
     7: vrTimer.Value := 0;              // сброс таймера
    15: begin
          vrTimer.Value := 0;            // сброс таймера
          AddMessage(Now, mkWarning, 'Он шел на Одессу, а вышел к Херсону...(матрос-партизан Железняк)', true, false);
        end;
  end;
//   этот оператор контролирует факт нажатия всех кнопок
//  if vrBtnState.AsInt = 7 then vrTimer.Value := 0;              // сброс таймера

end.

Скрипт "Прошла секунда":
Код: (delphi)
const Tmax = 120 * 60;       // константа используется в двух скриптах - её можно перенести в глобальный модуль
begin
  vrTimer.inc(1, 0, Tmax);

  case vrTimer.AsInt of
  1: vrBtnState.Value := 0;       // сброс регистра нажатых кнопок
  2, Tmax - 1: begin
                 if not Getbit(vrBtnState.AsInt, 0) then K1.Value := 31;      // включать индикатор не нажатой кнопки
                 if not Getbit(vrBtnState.AsInt, 1) then K2.Value := 31;
                 if not Getbit(vrBtnState.AsInt, 2) then K3.Value := 31;
               end;
  Tmax: begin
          K1.Value := 29;     // выключить индикаторы кнопок
          K2.Value := 29;
          K3.Value := 29;
          vrTimer.inc( -2);
        end;
  end;
end.


Возможно ещё нужен контроль времени нажатия всех трёх кнопок.

Пример во вложении.
« Изменён: 26 Августа 2021, 20:38:34 от pan2000 »

KungLao

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1265 : 31 Августа 2021, 13:07:29 »
Спасибо большое за помощь. С помощью ваших инструкций и помощи форумчан я смог  за 2 недели разработать и внедрить готовую систему контроля пожарной безопасности(хоть и на довольно примитивном уровне). До всей этой работы я вообще не знал ничего о ОРС, о конструировании SCADA, о базах данных и о написании скриптов.  Тема очень интересная и было очень приятно с этим всем разбираться. Описание и разъяснение к вашему продукту написано настолько подробно и объемно, что у меня возникли вопросы только на финальном этапе наладки. Все подано в очень удобоваримом виде. Много иллюстраций. Огромная благодарность разработчикам и тем, кто помог на форуме.  :) :)

strs

  • Новичок
  • *
  • Сообщений: 36
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1266 : 05 Сентября 2021, 10:14:16 »
Здравствуйте!

Есть необходимость видеть в интерфейсе оператора, запущена ли служба опроса модемов. Нашел пример для Делфи (приведен ниже), но не знаю, можно ли его применить в скриптах скады или это невозможно.
При попытке вставить первую часть кода в скрипт типа "глобальный модуль", получаю ошибку File "WinSvc.PCU not found".

Если напрямую в скриптах скады это сделать невозможно, может посоветуете, как по-другому можно вывести статус службы в интерфейс?
Код: (delphi)
uses
  WinSvc;
 
function ServiceGetStatus(sMachine, sService: PChar): DWORD;
{******************************************}
  {*** Parameters: ***}
  {*** sService: specifies the name of the service to open
  {*** sMachine: specifies the name of the target computer
  {*** ***}
  {*** Return Values: ***}
  {*** -1 = Error opening service ***}
  {*** 1 = SERVICE_STOPPED ***}
  {*** 2 = SERVICE_START_PENDING ***}
  {*** 3 = SERVICE_STOP_PENDING ***}
  {*** 4 = SERVICE_RUNNING ***}
  {*** 5 = SERVICE_CONTINUE_PENDING ***}
  {*** 6 = SERVICE_PAUSE_PENDING ***}
  {*** 7 = SERVICE_PAUSED ***}
  {******************************************}
 
var
  SCManHandle, SvcHandle: SC_Handle;
  SS: TServiceStatus;
  dwStat: DWORD;
begin
  dwStat := 0;
  // Open service manager handle.
  SCManHandle := OpenSCManager(sMachine, nil, SC_MANAGER_CONNECT);
  if (SCManHandle > 0) then
  begin
    SvcHandle := OpenService(SCManHandle, sService, SERVICE_QUERY_STATUS);
    // if Service installed
    if (SvcHandle > 0) then
    begin
      // SS structure holds the service status (TServiceStatus);
      if (QueryServiceStatus(SvcHandle, SS)) then
        dwStat := ss.dwCurrentState;
      CloseServiceHandle(SvcHandle);
    end;
    CloseServiceHandle(SCManHandle);
  end;
  Result := dwStat;
end;
 
function ServiceRunning(sMachine, sService: PChar): Boolean;
begin
  Result := SERVICE_RUNNING = ServiceGetStatus(sMachine, sService);
end;

Код
if ServiceRunning(nil, 'Имя службы') then
begin
{Действия если служба запущена}
end else
begin
{Действия если служба не запущена}
end;

« Изменён: 06 Сентября 2021, 19:51:59 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3214
    • Просмотр профиля
    • Simple-Scada
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1267 : 06 Сентября 2021, 20:00:35 »
Здравствуйте.

Компилятор выдал правильную ошибку о том, что модуль WinSvc, подключенный в приведённом Вами коде не найден, ведь его нет.

Цитировать
Если напрямую в скриптах скады это сделать невозможно, может посоветуете, как по-другому можно вывести статус службы в интерфейс?
В скаде сейчас нет какого-то простого способа проверить статус службы. Если служба во время работы обновляет какие-то файлы, то можно через скаду проверять время последнего изменения и реагировать если время давно не менялось.

pan2000

  • Постоялец
  • ***
  • Сообщений: 226
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1268 : 08 Сентября 2021, 07:38:26 »
     Здравствуйте.
Есть необходимость видеть в интерфейсе оператора, запущена ли служба опроса модемов.
  Получить состояние служб можно с помощью командного процессора.
Однако командный процессор всегда запускается в видимом окне, что крайне нежелательно. Запустить командный процессор без видимого окна можно в файле сценария VBScript. Полученные данные перенаправляются в файл. Далее следует дождаться обновления данных в файле и обработать их.

Пример из вложения после ввода имени службы получает её состояние.
Создается и запускается файл сценария и запоминается текущее время. Скрипт запрашивает информацию о службе и записывает её в файл результата. Далее с периодом 1 сек сканируется директория файла результата до наступления критерия обновления файла - его наличие с датой превышающей запомненную и ненулевой длиной или до наступления тайм-аута. 

strs

  • Новичок
  • *
  • Сообщений: 36
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1269 : 09 Сентября 2021, 14:19:56 »
Пример из вложения после ввода имени службы получает её состояние.
Спасибо! Была проблема, из-за русского имени пользователя в винде не создавался текстовый файл. Но с переездом в "D:\" все заработало.
Вопрос: а зачем сканировать директорию на наличие файла, если мы точно знаем как он называется и можем открыть его напрямую?

pan2000

  • Постоялец
  • ***
  • Сообщений: 226
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1270 : 09 Сентября 2021, 17:51:39 »
Вопрос: а зачем сканировать директорию на наличие файла, если мы точно знаем как он называется и можем открыть его напрямую?
Файл результата открывается как перезаписываемый - т.е. новый замещает старый. Узнать что файл обновился можно по изменению даты записи файла, она должна быть больше чем дата начала выполнения скрипта.

strs

  • Новичок
  • *
  • Сообщений: 36
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1271 : 10 Сентября 2021, 08:42:44 »
Файл результата открывается как перезаписываемый - т.е. новый замещает старый. Узнать что файл обновился можно по изменению даты записи файла, она должна быть больше чем дата начала выполнения скрипта.

Все равно не понял. Мы же и так можем узнать дату файла, зная имя. Ну да ладно, в итоге привел к такому виду, вроде все работает:

Код: (delphi)
var
    aPath: String;
    i: integer;
    tempString: String;
const
    servName:string = 'iRZ_Collector_Server';
begin

if SecondOf(Now) = 0 then begin    //проверяем статус службы и создаем файл с информацией 1 раз в минуту
  aPath := GetProjectPath + 'User Files\';
  StartTime.Value := NOW;                                       // начало ожидания
// чтение состояния службы через VB скрипт для подавления вывода окна командной строки
  TextFileOpen('Service.vbs', aPath, fomRewrite, fcpUTF8);
  TextFileWriteLn('Set WshShell = CreateObject("WScript.Shell")');
  TextFileWriteLn('WshShell.Run "cmd /A /C sc query ' + servName + '> ""'                // выполнить команду чтения состояния службы
  + 'D:\Service.txt""", 0');                                                             //  и записать результат в файл
  TextFileWriteLn('Set WshShell = Nothing');
  TextFileClose;
  RunApplication(SS_SERVER_NAME, aPath + 'Service.vbs', '');    // выполнить VBS-файл

  end;

  /////////////////////////////////////////////////

   if SecondOf(Now) = 2 then begin    //считываем файл для анализа через 2 секунды после создания

    if (FileExists('Service.txt', 'D:\')) and (SecondsBetween(FileAge('D:\Service.txt'), StartTime.AsDateTime) < 10) then begin  // условия корректности файла

       TextFileOpen('Service.txt', 'D:\', fomReset, fcpCyrillic_windows866); //открываем файл

       tempString := UTF8Encode(TextFileReadLn);     //переходим к требуемой строчке в файле
       tempString := UTF8Encode(TextFileReadLn);
       tempString := UTF8Encode(TextFileReadLn);
       tempString := UTF8Encode(TextFileReadLn);
           if tempString = '        Состояние          : 4  RUNNING ' then
             begin txtService.Text := 'Служба опроса модемов работает';
                   txtService.BorderColor := clLime;
             end
           else if tempString = '        STATE              : 1  STOPPED ' then
             begin txtService.Text := 'Служба опроса модемов остановлена';
                   txtService.BorderColor := clRed;
             end
           else
             begin txtService.Text := 'Ошибка получения статуса службы опроса модемов';    //в нужной строчке не те данные, которых мы ожидали
                   txtService.BorderColor := clYellow;
             end;

        TextFileClose;          // закрыть файл
    end
    else begin txtService.Text := 'Ошибка получения статуса службы опроса модемов'; //файл не существует либо слишком старый
               txtService.BorderColor := clYellow;
         end;

    end;   // if SecondOf(Now) = 2
end.

Спасибо!
« Изменён: 10 Сентября 2021, 08:47:03 от strs »

pan2000

  • Постоялец
  • ***
  • Сообщений: 226
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1272 : 10 Сентября 2021, 14:02:02 »
   Здравствуйте.
Мы же и так можем узнать дату файла, зная имя.
Мой пример предполагает однократный запрос состояния службы с минимальным временем отклика, анализ наличия обновленного файла начинается с 0 секунды относительно запроса.

В Вашем случае это автомат состояний с периодом в 60 тактов, запрос выполняется в 0, а анализ во 2 тактах. Сам процесс получения данных асинхронный, и можно ожидать что он завершится за 2 секунды. Но если информация о состоянии файла обновится через 3 секунды и более, то возникнет ошибка.
Поскольку процесс получения состояния службы периодический и не связан с действиями оператора (как в примере), то анализ файла можно смело перенести до 55 такта (секунды).

Вывод названия параметра на разных языках ("Состояние" <-> "STATE") это, предположительно, отголосок локализации ОС. Я бы проверял строку на наличие подстрок ": 4  RUNNING" и ": 1  STOPPED".

И ещё одна особенность автомата при запуске проекта, с вероятностью 1/30 в течение первой минуты будет выдано сообщение "Ошибка получения статуса службы опроса модемов".
Для устранения этого можно использовать условие (начальное значение переменной - 0) :
Код: (delphi)
(if SecondOf(Now) = 2) and (StartTime.AsFloat > 1) then begin    //считываем файл для анализа через 2 секунды после создания и только после запуска скрипта
« Изменён: 10 Сентября 2021, 16:38:37 от pan2000 »

strs

  • Новичок
  • *
  • Сообщений: 36
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1273 : 13 Сентября 2021, 08:23:21 »
Поскольку процесс получения состояния службы периодический и не связан с действиями оператора (как в примере), то анализ файла можно смело перенести до 55 такта (секунды).
Так и сделаю пожалуй.

Вывод названия параметра на разных языках ("Состояние" <-> "STATE") это, предположительно, отголосок локализации ОС. Я бы проверял строку на наличие подстрок ": 4  RUNNING" и ": 1  STOPPED".
Проект работает на конкретном компьютере, универсальность не требуется, поэтому усложнять лишний раз не хочется.

И ещё одна особенность автомата при запуске проекта, с вероятностью 1/30 в течение первой минуты будет выдано сообщение "Ошибка получения статуса службы опроса модемов".
Для устранения этого можно использовать условие (начальное значение переменной - 0)
Совсем не критично, перезапуски - редкое явление. Но раз есть возможность улучшить - почему бы и нет.

Спасибо!
« Изменён: 13 Сентября 2021, 08:24:59 от strs »

KungLao

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1274 : 13 Сентября 2021, 12:41:58 »
Добрый день. В своем проекте использую скрипт из примера, который вывод на основной экран состояние связи с ПЛК (привязанно к пингу: Есть пинг - есть связь, нет пинга - нет связи).
Код выглядит следующим образом:
Код
begin
if pingdata.Result then
ping_plc.color := clgreen
else begin
ping_plc.color := clred;
AddMessage (Now, mkAlarm, 'Отсутствие связи с контроллером', true, false);
end;
end
В такой реализации аварийное сообщение о потере связи генерируется постоянно (в течении всего времени отсутствия связи).
Подскажите как реализовать однократное появление сообщения при потере связи и подобное сообщение когда связь востановилась?