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

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

Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - Lorry P

Страницы: [1]
1
Да, после тестов тоже выяснил что OPC UA сервер Regul R500 оставляет подписку активной. Спасибо за подсказку про процедуру RecreateSubscriptions.  Ручной вариант пересоздания подписок добавил, но нужен был и автоматический режим, поэтому реализовал немного костыльное, но рабочее в данном случае решение.
Прилагаю скрипты, может кому-то потребуется или будет полезным.
Контроль связи берем по ссылке, контроль через пинг на AstraLinux 1.7 SE не работает в моем случае (не поддерживается системой - было упоминание в мануале SimpleSCADA в разделе линукс).

Итак, на ПЛК реализуем лайфбит Bool с частотой изменения фронта 1 секунда.
Далее создаем теги в зависимости от выбранного варианта скрипта далее(см.скриншот).
На скаде сделаем скрипт по контролю его изменения с проверкой качества обязательно:
Код: (delphi)
begin
  // обнуляем счетчик отсутствия связи если переменная лайфбита с OPC UA изменяется
if DIAG_LifeBit.IsGoodQuality then
  vrLinkTimer.Value := 0;
end.

Далее скрипт с временем выполнения 1 секунда (ниже будет 3 рабочих вариации в зависимости от задачи) :
Код: (delphi)
//Рабочий скрипт контроля двух OPC UA  и переключения клиентов серверов
const
  TIMEOUT = 10;
  RECREATE_INTERVAL = 60;
begin
  // ===== ПЛК А  =====
  vrLinkTimer.Value := vrLinkTimer.AsInt64 + 1;

  if (vrLost.AsBool = FALSE) and (vrLinkTimer.AsInt64 >= TIMEOUT) then
  begin
    vrLost.Value := True;
    AddMessage(Now, mkMessage, 'Потеряна связь с OPC UA сервером ПЛК А', TRUE, FALSE);
    UAServer1.RecreateSubscriptions;
    AddMessage(Now, mkMessage, 'Выполняется автоматическое пересоздание подписок OPC UA сервера ПЛК А.', True, False);
    vrRecreateTimer.Value := 0;
  end;

  if (vrLost.AsBool = True) then
  begin
    vrRecreateTimer.Value := vrRecreateTimer.AsInt64 + 1;
    if vrRecreateTimer.AsInt64 >= RECREATE_INTERVAL then
    begin
      UAServer1.RecreateSubscriptions;
      AddMessage(Now, mkMessage, 'Повторное пересоздание подписок OPC UA сервера ПЛК А (каждую 1 мин).', True, False);
      vrRecreateTimer.Value := 0;
    end;
  end;

  if (vrLost.AsBool = True) and (vrLinkTimer.AsInt64 < TIMEOUT) then
  begin
    vrLost.Value := False;
    AddMessage(Now, mkMessage, 'Cвязь с OPC UA сервером ПЛК А восстановлена', TRUE, FALSE);
    vrRecreateTimer.Value := 0;
  end;

  // ===== ПЛК Б  =====
  vrLinkTimer_B.Value := vrLinkTimer_B.AsInt64 + 1;

  if (vrLost_B.AsBool = FALSE) and (vrLinkTimer_B.AsInt64 >= TIMEOUT) then
  begin
    vrLost_B.Value := True;
    AddMessage(Now, mkMessage, 'Потеряна связь с OPC UA сервером ПЛК Б', TRUE, FALSE);
    UAServer2.RecreateSubscriptions;   // проверьте реальное имя объекта
    AddMessage(Now, mkMessage, 'Выполняется автоматическое пересоздание подписок OPC UA сервера ПЛК Б.', True, False);
    vrRecreateTimer_B.Value := 0;
  end;

  if (vrLost_B.AsBool = True) then
  begin
    vrRecreateTimer_B.Value := vrRecreateTimer_B.AsInt64 + 1;
    if vrRecreateTimer_B.AsInt64 >= RECREATE_INTERVAL then
    begin
      UAServer2.RecreateSubscriptions;
      AddMessage(Now, mkMessage, 'Повторное пересоздание подписок OPC UA сервера ПЛК Б (каждую 1 мин).', True, False);
      vrRecreateTimer_B.Value := 0;
    end;
  end;

  if (vrLost_B.AsBool = True) and (vrLinkTimer_B.AsInt64 < TIMEOUT) then
  begin
    vrLost_B.Value := False;
    AddMessage(Now, mkMessage, 'Cвязь с OPC UA сервером ПЛК Б восстановлена', TRUE, FALSE);
    vrRecreateTimer_B.Value := 0;
  end;

  // ===== Автопереключение серверов  =====
  //Кнопка автоматического переключения vrAutoFailoverEnabled !!
  if vrAutoFailoverEnabled.AsBool and IsMasterServer and vrLost.AsBool and (not vrLost_B.AsBool) and (not vrFailoverActive.AsBool) then
  begin
    Switch_to_Slave(nil);
    vrFailoverActive.Value := True;
    AddMessage(Now, mkAlarm, 'Автопереход на резервный сервер: потеряна связь с ПЛК А', True, False);
  end;

  if vrAutoFailoverEnabled.AsBool and IsMasterServer and vrFailoverActive.AsBool and (not vrLost.AsBool) then
  begin
    Switch_to_Master(nil);
    vrFailoverActive.Value := False;
    AddMessage(Now, mkMessage, 'Автовозврат на основной сервер: связь с ПЛК А восстановлена', True, False);
  end;
end.



(*
//Рабочий скрипт для одного сервера OPC UA. Функционал попытки переподключения через 1 минуту. Без переключения клиентов между серверами .
const
  TIMEOUT = 10;
  RECREATE_INTERVAL = 60;
begin
  vrLinkTimer.Value := vrLinkTimer.AsInt64 + 1;

  if (vrLost.AsBool = FALSE) and (vrLinkTimer.AsInt64 >= TIMEOUT) then
  begin
    vrLost.Value := True;
    AddMessage(Now, mkMessage, 'Потеряна связь с OPC UA сервером', TRUE, FALSE);
    UAServer1.RecreateSubscriptions;
    AddMessage(Now, mkMessage, 'Выполняется автоматическое пересоздание подписок OPC UA сервера.', True, False);
    vrRecreateTimer.Value := 0;
  end;

  if (vrLost.AsBool = True) then
  begin
    vrRecreateTimer.Value := vrRecreateTimer.AsInt64 + 1;
    if vrRecreateTimer.AsInt64 >= RECREATE_INTERVAL then
    begin
      UAServer1.RecreateSubscriptions;
      AddMessage(Now, mkMessage, 'Повторное пересоздание подписок OPC UA сервера (каждую 1 мин).', True, False);
      vrRecreateTimer.Value := 0;
    end;
  end;

  if (vrLost.AsBool = True) and (vrLinkTimer.AsInt64 < TIMEOUT) then
  begin
    vrLost.Value := False;
    AddMessage(Now, mkMessage, 'Cвязь с OPC UA сервером восстановлена', TRUE, FALSE);
    vrRecreateTimer.Value := 0;
  end;
end.

 *)

(*
//Рабочий скрипт попытки пересоздания подписок. Без повторных попыток
begin
  vrLinkTimer.Value := vrLinkTimer.AsInt64 + 1;
  // проверка на отсутствие связи
  if (vrLost.AsBool = FALSE) and (vrLinkTimer.AsInt64 >= TIMEOUT) then
  begin
    vrLost.Value := True;
    AddMessage(Now, mkMessage, 'Потеряна связь с OPC UA сервером', TRUE, FALSE);
    UAServer1.RecreateSubscriptions;    //Пересоздание подписок для регула (у них не стандартный сервер, подписка держится активной даже если данных нет)
    AddMessage(Now, mkMessage, 'Выполняется автоматическое пересоздание подписок OPC UA сервера.', True, False);
  end;

  // проверка на восстановление связи
  if (vrLost.AsBool) and (vrLinkTimer.AsInt64 < TIMEOUT) then
  begin
    vrLost.Value := False;
    AddMessage(Now, mkMessage, 'Cвязь с OPC UA сервером восстановлена', TRUE, FALSE);
  end;
end.
*)

2
Добрый день.
Имеем веселую конфигурацию на ПНР - Два резервированных сервера с AstraLinux , SimpleSCADA 2.7.1.0(21.04.2025) через wine (по мануалу). И резервированный ПЛК Регул R500 с OPC UA сервером без настроек безопасности и аутентификации.

Связь настроена, теги читаются. Если остановить ПЛК или загрузить в него ПО(с остановом), то теряется связь с OPC UA сервером (на мнемосхеме клиента вместо переменных желтые восклицательные знаки) и более не восстанавливается. Хотя через EDITOR или любой тестовый клиент конфигурация читается. Так же на сервере(веб форма) статус OPC UA работает. Ошибок в логах по отсутствию переменных или конфигурации нет.
Останавливаю проект на сервере, запускаю заново - все работает.

Меняли параметры в расширенных настройках(таймауты) OPC сервера в Editor, но не помогло. Что еще можно сделать? Обновить до последней версии SimpleSCADA не имеем возможности

Нашел похожую тему с ПЛК WAGO , но там ошибка по отсутствию тегов на OPC UA сервере.
https://simple-scada.com/forum/index.php?topic=1856.msg12952#msg12952

Вот эта тема тоже похожа по смыслу
https://simple-scada.com/forum/index.php?topic=2120.msg14280#msg14280

3
Ваши вопросы / Метод IsMasterServer
« : 24 Апреля 2025, 16:24:16 »
Добрый день.
При компиляции скрипта из мануала :
https://simple-scada.com/help/script/ismasterserver.html
Возникает ошибка
Код
IsMasterServer | Type of expression must be BOOLEAN в строке: 2, позиция: 19
Скрипт типа таймер, 5сек.  В настройках сервера пока не настроено резервирование, поскольку второго сервера пока нет.
Подскажите, ошибка в методе  IsMasterServer , который не Bool, или что-то нужно делать по-другому?)
Код: (delphi)
begin
  if IsMasterServer then
    Text246.Text := 'Работает основной сервер'
  else 
    Text246.Text := 'Работает резервный сервер';             
end.

4
    Здравствуйте.

  Для просмотра/редактирования одиночной переменной и её свойств можно создать обычное (или модальное) окно-форму.
При открывании окна в форму передаются переменная с набором просматриваемых/редактируемых свойств.
По заполнении данные из формы переписываются в свойства переменной.
Пример во вложении.

Использовал предложенный pan2000 вариант, все отлично. Но не получается передать из окна-формы тип границ ("Выключить границы", "Только аварийные границы" и "Аварийные и предупр. границы") из элемента список (работать с границами). Пробовал через выпадающий список с чекбоксом работать с границами, через кнопки, пробовал через индекс выбранной строки:
Код
     I := fldLimitType.ItemIndex;
     case I of
     0:fldValue.Variable.LimitType := ltNone;
     1:fldValue.Variable.LimitType := ltAlarmsOnly;
     2:fldValue.Variable.LimitType := ltAlarmsAndWarnings;
     end;

Работает только если напрямую прописать в скрипте FormDone тип границ, в остальных случаях выбор не сохраняется и при следующем вызове окна-формы LimitType = ltNone.
Это возможно как-то победить? :)

5
Добрый день.
Возникла проблема в подстановках при вызове нескольких шаблонных окон друг из друга.

Объясню на примере: Существует несколько шаблонов генераторов, по нажатию на любой из них вызывается шаблонное окно с подробной информацией о выбранном генераторе , например выводом значений с датчиков температуры. Необходимо по нажатию на поле датчика открывать еще шаблонное окно с данными датчика и его границами.
При создании шаблонного окна с подстановкой тега датчика, подстановку запрашивает шаблон в обход поля датчика. (см.вложение - при добавлении поля с вызовом окна MB_Ai_sens желтеет шаблон). Т.е нажатия на любой из датчиков будут вызывать одно и то же окно датчика из подстановки в шаблоне.

Подскажите возможно ли реализовать такой функционал и каким методом? 
Спасибо!

6
Добрый день. Подскажите есть ли возможность изменить стандартный шрифт в проекте?
 Где-то в старой теме видел что используется только шрифт Roboto, хотелось бы иметь возможность поменять его на другой для всего проекта.

Страницы: [1]