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

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

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

Andrey1883

  • Пользователь
  • **
  • Сообщений: 75
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1605 : 10 Декабря 2024, 12:45:01 »

Почему-то
sunriseMinutes:=Int((sunrise*60) div 60);
даёт ошибку incopatible types "SINGLE" and "INTRGER"

я так понимаю, потому что операция деления нацело определена в Паскале только для случая, когда по обе стороны от div указаны
целочисленные значения. а у вас  переменная sunrise имеет тип SINGLE


ARV

  • Постоялец
  • ***
  • Сообщений: 117
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1606 : 10 Декабря 2024, 15:56:02 »
Есть же round()...

B.B

  • Новичок
  • *
  • Сообщений: 22
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1607 : 12 Декабря 2024, 21:13:55 »

Почему-то
sunriseMinutes:=Int((sunrise*60) div 60);
даёт ошибку incopatible types "SINGLE" and "INTRGER"

я так понимаю, потому что операция деления нацело определена в Паскале только для случая, когда по обе стороны от div указаны
целочисленные значения. а у вас  переменная sunrise имеет тип SINGLE
Немного не так Int((sunrise*60) - целое, 60 - целое.
Поэтому "по обе стороны от div указаны целочисленные значения"

UPD Прошу прощения. Скобки! Порядок неправильный!! Действительно SINGLE получится, а выглядит как целое  :D
« Изменён: 12 Декабря 2024, 21:27:36 от B.B »

B.B

  • Новичок
  • *
  • Сообщений: 22
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1608 : 12 Декабря 2024, 21:22:53 »
Есть же round()...
Нам надо именно целую часть, а Round() Возвращает число X округленное до ближайшего целого..
Поэтому INT

Иначе из 7,55 (это 7 часов 33 минуты) получим 8 часов и 33 минуты. Что неверно.

ZWolol

  • Новичок
  • *
  • Сообщений: 27
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1609 : 13 Декабря 2024, 05:00:35 »
Int дает EXTENDED, и преобразовывать нужно оператор деления, а не результат.

sunriseMinutes:=integer(sunrise*60) div 60;

P.S.
Только Div не любит преобразование типа (это зависит от оптимизации компилятора).
Например, на Lazarus ругается, что первый элемент не может быть Double.

Лучше используй i:= integer(sunrise*60); и её подставляй для Div.

P.S.S.
А чем тебя это не устраивает?: sunriseMinutes:=integer(sunrise);
« Изменён: 13 Декабря 2024, 05:27:49 от ZWolol »

ARV

  • Постоялец
  • ***
  • Сообщений: 117
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1610 : 13 Декабря 2024, 07:50:10 »
Round() Возвращает число X округленное до ближайшего целого
Ну, тогда есть Trunc()

Принудительное преобразование типов по-настоящему требуется достаточно редко, и чаще всего свидетельствует о недопонимании чего-то важного...

AndreyA

  • Новичок
  • *
  • Сообщений: 35
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1611 : 26 Декабря 2024, 13:13:04 »
Здравствуйте!
Задача в следующем: необходимо подсчитывать время наработки механизмов и выводить часы наработки оператору (не рапорта) как переменные процесса.
сделал скрипт раз в секунду:
Код: (delphi)
const
  TIMEHOUR = 3600;
begin
  if (conv1.Value = 20) and (worksec_conv1.Value < TIMEHOUR) then
    worksec_conv1.Value := worksec_conv1.AsInt + 1;

  if (conv1.Value = 20) and (worksec_conv1.Value >= TIMEHOUR) then
  begin
    workhours_conv1.Value := workhours_conv1.AsInt + 1;
    worksec_conv1.Value := 0;
  end;
end.
Вопрос : как этот скрипт подвязать к 70 обьектам? В этом скрипте сделать копии или можно оптимизировать как шаблон?
conv1.Value = 20 - состояние конвейера (в работе)
Спасибо за внимание         
« Изменён: 26 Декабря 2024, 15:44:31 от Simple-Scada »

Simple Scada

  • Глобальный модератор
  • *****
  • Сообщений: 220
    • Просмотр профиля
    • Simple-Scada
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1612 : 26 Декабря 2024, 15:43:24 »
Здравствуйте.

Время наработки механизма можно получить более простым способом. Для этого нужно включить архивацию "По изменению" у переменных работы механизма и использовать процедуру ArchiveTimeOn для получения суммарного времени, в котором значение переменной было отлично от нуля. Перед началом работы с архивными процедурами, обязательно ознакомьтесь с примером их использования. Также не рекомендуем вызывать архивные процедуры слишком часто. Например, если достаточно обновлять данные наработки раз в час, то используйте скрипт "Начало часа".

Для вычисления времени наработки по архивным данным рекомендуем использовать Boolean переменные состояния механизма (включен/выключен) вместо целочисленных переменных отвечающих за несколько состояний механизма. Если таких переменных нет на ПЛК, то нужно создать внутренние Boolean переменные с однотипными именами (например conv1_Status, conv2_Status и т.д.) и в скрипте по изменению переменных (conv1, conv2 и т.д.) записывать в соответствующие внутренние переменные значение 1, когда "conv1.AsInt = 20" и записывать 0 в ином случае. Пример универсального скрипта по событию "Изменились переменные":
Код: (delphi)
var
  aVarStatus: TM_Variable;
begin
  aVarStatus := GetVariableByName(Variable.Name + '_Status');
  if aVarStatus <> nil then       // если переменная существует
    if Variable.AsInt = 20 then   // если переменная вызвавшая скрипт = 20, то
      aVarStatus.Value := True    // записываем True в переменную состояния механизма
    else                          // иначе
      aVarStatus.Value := False;  // записываем False в переменную состояния механизма
end.
Таким образом, в переменных conv1_Status, conv2_Status и т.д. будет сохраняться информация о работе механизмов (1 - включен, 0 - выключен). Далее, как уже было описано выше, для получения суммарного времени наработки можно использовать процедуру ArchiveTimeOn.

AndreyA

  • Новичок
  • *
  • Сообщений: 35
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1613 : 27 Декабря 2024, 08:51:00 »
Благодарю за ответ! Но получается что надо знать текущую дату и начальную чтобы вычислить разницу, и как я понял процедура будет запускаться 1 раз в час и вычислять время наработки. В моем случае подсчет может осуществляться несколько лет и наверно постоянный опрос 1 раз в час всего интервала у каждого механизма будет возможно замедлять работу скады. 
« Изменён: 27 Декабря 2024, 10:27:05 от AndreyA »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1273
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1614 : 06 Января 2025, 12:02:52 »
Здравствуйте.

Цитировать
Но получается что надо знать текущую дату и начальную чтобы вычислить разницу
Текущую дату/время можно получить с помощью функции "Now", а начальную дату если она будет постоянной можно сохранить как константу или задавать ее через переменную (если требуется периодически корректировать начальную дату). Если нужно получать наработку за фиксированный интервал времени (например за последний год), то при помощи методов для работы с датой/временем можно отнимать нужный интервал от текущей даты, например отнять 1 год:
Код: (delphi)
DateStart := IncYear(Now, -1); // вычисляем начальную дату

Цитировать
и как я понял процедура будет запускаться 1 раз в час и вычислять время наработки. В моем случае подсчет может осуществляться несколько лет и наверно постоянный опрос 1 раз в час всего интервала у каждого механизма будет возможно замедлять работу скады.
Можно обновлять данные реже чем раз в час, например раз в сутки. Для этого можно использовать скрипт "Начало часа" и добавить дополнительную проверку:
Код: (delphi)
var
  DateStart, DateEnd : TDateTime;
begin
  // запускаем скрипт раз в сутки в 00 часов
  if HourOf(Now) = 0 then
  begin
      DateEnd := Now;                 // текущие дата и время
      DateStart := IncYear(Now, -1);  // вычисляем начальную дату
      // вычислить время включенного состояния переменной "MyVariable" за период
      // от "DateStart" до "DateEnd" и записать результат в переменную "MyVariableRes"
      ArchiveTimeOn(MyVariable, MyVariableRes, DateStart, DateEnd);
   end;
end.

Также, чтобы снизить нагрузку на проект и БД при выборке данных за большие промежутки времени, можно:
1. Выполнять вычисления из прореженного слоя;
2. Вызывать процедуру ArchiveTimeOn порциями, например по 20 переменных.

rogalsky83

  • Новичок
  • *
  • Сообщений: 1
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1615 : 13 Января 2025, 16:35:39 »
Добрый день!
Есть таблица MySql, которую SCADA заполняет переменными. Эта таблица отображается в SCADA через метод RunSQL компонента таблица. Необходимо корректировать значения некоторых полей вручную из скады.
Пробовал подвязать такой скрипт на событие oncelldatachange таблицы
Код: (delphi)
var aID, aValue, aField, aQuery:string;
AisString:boolean;
begin
aID:=Table17.GetCell(0, Cell.Row).Text;
aValue:= Table17.GetCell(Cell.Col, Cell.Row).Text;
AisString:= false;
case Cell.Col of
0: exit;
1: aField:='cam';   //
2: aField:='poc';
3: aField:='vol';
4: begin aField:='sta'; AisString:= true; end;
5: begin aField:='end'; AisString:= true; end;
6: begin aField:='ope'; AisString:= true; end;
7: aField:='drd';
8: aField:='drh';
9: aField:='drs';
10: aField:='tck';
11: begin aField:='wid'; AisString:= true; end;
12: begin aField:='por'; AisString:= true; end;
13: begin aField:='typ'; AisString:= true; end;
14: aField:='wms';
15: aField:='wmf';
16: aField:='ene';
17: aField:='qen';
18: aField:='war';
19: aField:='qwa';
20: aField:='zag';
21: aField:='pro';
end;
if AisString then aQuery:= 'UPDATE `test` SET `'+aField+'`='+Quotedstr(aValue) +' WHERE `id`=' +aID+';'
else aQuery:= 'UPDATE `test` SET `'+aField+'`='+aValue +' WHERE `id`=' +aID+';';
RunSQL(aQuery, nil, 134);
end.
, но скрипт не выполняется вероятно из-за того, что не изменялись переменные, связанные с таблицей. Есть ли какая-нибудь возможность выполнить UPDATE поля таблицы БД при изменении соответствующего поля таблицы в SCADA?
« Изменён: 13 Января 2025, 17:05:28 от Simple Scada »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1273
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1616 : 14 Января 2025, 15:07:30 »
Здравствуйте.

Цитировать
Пробовал подвязать такой скрипт на событие oncelldatachange таблицы, но скрипт не выполняется вероятно из-за того, что не изменялись переменные, связанные с таблицей.
См. описание события "OnCellDatachange". Данное событие выполнится, только если изменится значение переменной, связанной с ячейкой таблицы. Но у Вас, скорее всего, ячейки не связаны с переменными, соответственно, скрипт выполняться не будет.

Посмотрите пример создания таблицы рецептов в БД. В нем реализовано изменение данных в выделенной пользователем строке таблицы и последующее обновление строки в БД – см. описание для кнопки "Изменить".

Alexey Golubev

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1617 : 21 Января 2025, 10:33:17 »
Как отключить компьютер с сервером simple-scada с использованием скрипта и команды shutdown.exe ?
OPC сервер по модбас опрашивает ПЛК. ПЛК имеет функцию контроля питания компьютера с установленной скадой. Если питание пропало, то есть резервный источник на 5 минут и ПЛК выдает битовый сигнал отключения. OPC опрашивает данный бит раз в секунду. Если бит установлен в 1 то корректно отключаем скаду. Нужно чтобы скада выполнила скрипт отключения . Как это можно сделать?

Simple Scada

  • Глобальный модератор
  • *****
  • Сообщений: 220
    • Просмотр профиля
    • Simple-Scada
Re: Вопросы по скриптам в Simple-Scada 2
« Ответ #1618 : 22 Января 2025, 10:38:42 »
Здравствуйте.

Через скрипты завершить работу сервера скады возможности нет.

Если на ПК-сервере запущен десктоп-клиент, то в настройках (Options.exe -> Simple-Client -> "Имя этого клиента") необходимо задать уникальное имя (например "Client_Server") для данного клиента и перед выключением ПК завершать его работу, используя процедуру "CloseApplicationClient". Далее, используя процедуру "RunApplication", можно завершить работу ПК-сервера. Пример скрипта на событие "Изменились переменные":
Код: (delphi)
begin
  if Variable.AsBool then  // если значение переменной вызвавшей скрипт = True(1), то
  begin
    CloseApplicationClient('Client_Server'); // закрыть десктоп-клиент с именем 'Client_Server'
    RunApplication(SS_SERVER_NAME, 'shutdown.exe', '/s /t 30'); // выключить ПК-сервер через 30 секунд
  end;
end.
Если используется битовая переменная, то для получения значения нужного бита используйте функцию "GetBit".
« Изменён: 22 Января 2025, 10:40:52 от Simple_Scada »