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

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

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

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


Сообщения - Simple Scada

Страницы: [1] 2 3 ... 11
1
Здравствуйте.

В данном случае использовать локальную переменную скрипта нельзя – подробнее см. по ссылке (Изменение 1). В Вашем случае, для хранения значения количества продукции за предыдущую минуту нужно использовать внутреннюю переменную. Также, чтобы избежать ошибок, в правой части скрипта, при выполнении математических операций с переменными нужно использовать значение переменной приведенное к нужному типу. Пример исправленного скрипта для события "Начало минуты" или "Таймер" с интервалом в 60 секунд:

Код: (delphi)
begin
  if Dicount2.AsInt  = 0 then
    Speedbotle_min.Value := 0
  else
    Speedbotle_min.Value := Dicount2.AsInt - Speedbotle_temp.AsInt;
  Speedbotle_temp.Value := Dicount2.AsInt;
end.

2
Ваши вопросы / Re: Тип переменной Time
« : 18 Апреля 2024, 12:01:19 »
Здравствуйте.

У меня таких таймеров 30шт и надо сохранить в файл. Создавать 30 переменных и 30 скриптов?
См. комментарий к скрипту:
Цитировать
Это универсальный скрипт, его можно назначить множеству компонентов Текст и в них будет отображаться время в формате 00 дней 00:00:00.000 взятое из связанной переменной.
Соответственно, писать 30 отдельных скриптов не требуется. Если полученное значение нужно записывать в строковую переменную, то эту переменную можно указать в свойство "Доп. переменная" компонента "Текст" и в скрипт добавить запись в доп. переменную:
Код: (delphi)
var
  v: Int64;
  s: String;
  days, hours, minutes, seconds, msc: Integer;
begin
  if Sender is TM_Text then
    with Sender as TM_Text do
    begin
      v := AsInt64;
      days := v div 86400000;
      hours := (v div 3600000) mod 24;
      minutes := (v div 60000) mod 60;
      seconds := (v div 1000) mod 60;
      msc := v mod 1000;
      s :=  ZeroPad(days, 2) + ' дней ' + ZeroPad(hours, 2) + ':' + ZeroPad(minutes, 2) + ':' + ZeroPad(seconds, 2) + '.' + ZeroPad(msc, 3);
      VariableEx.Value := s;     // записываем полученную строку в доп. переменную
      Text := s;                 // выводим полученную строку в компонент "Текст"
    end
end.

Если наработку нужно записывать в строковые переменные и не требуется выводить на мнемосхему, то можно использовать скрипт с типом события "Изменились переменные" указав все 30 переменных в список скрипта и изменив код скрипта под используемый тип события. Например переменные таймеров (с OPC-сервера) имеют имена: vrMyTimer1 … vrMyTimer30. Тогда нужно создать внутренние строковые переменные с именами: vrMyTimer1_String … vrMyTimer30_String и использовать следующий код скрипта:
Код: (delphi)
var
  v: Int64;
  aVar: TM_Variable;
  days, hours, minutes, seconds, msc: Integer;
begin
  aVar := GetVariableByName(Variable.Name + '_String');
  if aVar <> nil then        // если переменная существует
  begin
    v := Variable.AsInt64;
    days := v div 86400000;
    hours := (v div 3600000) mod 24;
    minutes := (v div 60000) mod 60;
    seconds := (v div 1000) mod 60;
    msc := v mod 1000;
    // записываем полученную строку в переменную vrMyTimer#_String
    aVar.Value :=  ZeroPad(days, 2) + ' дней ' + ZeroPad(hours, 2) + ':' + ZeroPad(minutes, 2) + ':' + ZeroPad(seconds, 2) + '.' + ZeroPad(msc, 3);
  end;
end.

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

Получить предыдущее значение переменной можно только в скриптах с типами событий "Изменились переменные" и "Нарушена граница". См. функции PrevAsBool, PrevAsInt, PrevAsFloat, PrevAsStr.

Подобные вычисления лучше реализовать на контроллере. Для решения Вашей задачи в скада-системе можно создать отдельные внутренние переменные для всех переменных, по которым необходимо получать предыдущее значение. Имена внутренних переменных должны содержать: имя текущей переменной (например "vrMyVar1", "vrMyVar2" и тд.) + приставка (например "_Prev") =  "vrMyVar1_Prev", "vrMyVar2_Prev" и тд. Далее нужно создать скрипт с типом события "Изменились переменные", в список скрипта указать все переменных, для которых необходимо получать предыдущее значение, и написать скрипт:
Код: (delphi)
var
  aVar: TM_Variable;
begin
  aVar := GetVariableByName(Variable.Name + '_Prev');  // ищем переменную, в которую нужно записать предыдущее значение
  if aVar <> nil then                                  // если переменная существует
    aVar.Value := PrevAsFloat;                         // записываем предыдущее значение переменной
end.
Теперь внутренние переменные "vrMyVar1_Prev", "vrMyVar2_Prev" и тд. можно вывести в поля на мнемосхему проекта.

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

Для работы с дополнительной переменной необходимо использовать свойство переменной VariableEx. Также, Вы можете ознакомиться с этим разделом руководства - в нем рассмотрены частые ошибки при работе со скриптами, в том числе и ошибки в скриптах по событию OnDataChangeEx.

Если таких объектов будет несколько, то писать отдельные скрипты для каждого объекта не требуется. Можно написать один универсальный скрипт и использовать его для всех объектов. Судя по описанию, Ваши переменные имеют тип данных Boolean? Для обращения к значению переменной рекомендуется использовать явное приведение значения переменной к нужному типу. Например, при сравнении с True/False нужно брать значение переменной, переведенное в тип Boolean (свойство AsBool).

Пример универсального скрипта на событие OnDataChange:
Код: (delphi)
begin
  if Sender is TM_Shape then     // проверяем, что Sender это фигура
     with Sender as TM_Shape do  // приводим Sender к типу "TM_Shape"
       if AsBool then            // если значение основной переменной связанной с фигурой равно True/1
         Alpha := 255            // изменить прозрачность фигуры на 255
       else                      // иначе
         Alpha := 0              // изменить прозрачность фигуры на 0
end.

Пример универсального скрипта на событие OnDataChangeEx:
Код: (delphi)
begin
  if Sender is TM_Shape then      // проверяем, что Sender это фигура
     with Sender as TM_Shape do   // приводим Sender к типу "TM_Shape"
       if  VariableEx.AsBool then // если значение доп.переменной связанной с фигурой равно True/1
         FlashColor := clRed      // включить мигание объекта красным цветом
       else                       // иначе
         FlashColor := clNone;    // отключить мигание объекта
end.

5
Ваши вопросы / Re: Объединение отчетов
« : 10 Апреля 2024, 13:55:36 »
Здравствуйте.

Если эти данные Вы получаете из собственных таблиц в БД, то с помощью соответствующего SQL-запроса можно сразу получить необходимую таблицу с объединением по имени матриц и суммой массы отхода и заготовки. Например, имеются таблицы:
Table A:
Name            Mass
Workpiece_1  100
Workpiece_2  200
Workpiece_3  300
Workpiece_1  300
Workpiece_2  200
Workpiece_3  100

Table B:
Name            Mass
Workpiece_1  10
Workpiece_2  20
Workpiece_3  30
Workpiece_1  30
Workpiece_2  20
Workpiece_3  10

Тогда в отчет можно добавить свой источник данных и с помощью SQL-запроса:
Код: (sql)
SELECT A.Name, SUM(A.Mass) AS sum_WasteMass, b.SW AS sum_WorkpieceMass
FROM A
INNER JOIN
  (SELECT Name, SUM(Mass) AS SW FROM B GROUP BY Name) b ON b.Name = A.Name
GROUP BY Name
выполнить выборку необходимой информации (см. скриншот "SQL"). В итоге получаем сразу готовый результат (см. скриншот "Report").

6
Ваши вопросы / Re: HTTP GET POST, ZONT API
« : 10 Апреля 2024, 08:29:39 »
Здравствуйте.

В ZONT API изменился список доступных шифров (которые используются при подключении по https (SSL/TLS) к серверам Zont). Новые шифры были добавлены в Simple-Scada начиная с версии 2.6.7.3. Если Вы используете версию ниже 2.6.7.3, то выполните обновление до версии не ниже 2.6.7.3.

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

1. Если требуется выявить ошибки при выполнении SQL-запроса, то нужно использовать скрипт с типом события "Ошибка SQL-запроса". Также, для отладки скриптов работы с БД можно активировать опцию "Лог пользовательских SQL-запросов", тогда все пользовательские SQL-запросы будут записываться в лог-файл сервера. Данную опцию можно использовать только для отладки проекта, иначе она будет создавать лишнюю нагрузку на сервер скады.

2. Нужно использовать синтаксис используемой СУБД. В данном случае, если требуется выполнить запись в таблицу, расположенную в схеме "public", то указание схемы можно опустить:
Код: (delphi)
aQuery := 'INSERT INTO "equpment_operating"… ';
В случае, когда в SQL-запросе требуется указать определенную схему, нужно использовать следующий синтаксис:
Код: (delphi)
aQuery := 'INSERT INTO "my_schema"."equpment_operating"… ';

Также в скрипте используется архивная процедура "ArchiveTimeOn". Рекомендуем ознакомиться с принципом работы архивных процедур. В Вашем случае при выполнении скрипта, в БД могут записываться неверные значения, так как архивные процедуры не выполняются мгновенно. Скорость их выполнения зависит от производительности ПК, загруженности СУБД, качества связи между сервером Simple-Scada и СУБД. Поэтому, после вызова архивных процедур, скрипт продолжит выполняться, но результат вычислений может записаться в переменную "HPT_2_narabotka" позже, например через секунду после полного выполнения скрипта.

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

Можно выполнять проверку превышения оригинального значения переменной (например, используя свойство "OriginalAsInt") над максимумом шкалы переменной и выдавать соответствующее сообщение. Пример универсального скрипта на событие "OnDataChange" объекта, с которым связана переменная:
Код: (delphi)
begin
  if Sender is TM_Object then   // проверяем, что Sender это объект
    with Sender as TM_Object do // приводим Sender к типу "TM_Object"
      if Variable.OriginalAsInt > Maximum then
        AddMessage(Now, mkAlarm, 'Значение переменной "' + Variable.Name +
        '" вышло за пределы диапазона допустимых значений: ' + AsStr, True, False);
end.

9
Ваши вопросы / Re: Прозрачная кнопка
« : 20 Марта 2024, 11:42:27 »
Здравствуйте.

См. скриншот во вложении.

10
Ваши вопросы / Re: Время работы за сутки
« : 15 Марта 2024, 13:32:29 »
Здравствуйте.

Цитировать
Результат выводится в поле Calendar, с отключенным значением даты и временем в формате hh:mm:ss
Проблема в том, что если агрегат работал все 24 часа, то в поле Calendar выводится 00:00:00
В компонент "Календарь" и переменную типа "DateTime" нельзя вывести значение времени больше чем 23:59:59. Если время наработки/простоя может быть больше 23:59:59, то его можно выводить в компонент "Текст", как это описано в примере №2 по ссылке.

Цитировать
Как сделать так, чтобы в таком случае отображалось 24:00:00 ?
Значение 24:00:00 можно отобразить в компоненте "Текст". Для этого компонент "Текст" нужно связать с переменной "DateTime_Val" и на событие OnDataChange написать универсальный скрипт:

Код: (delphi)
var
  aSeconds: Int64;
begin
  if Sender is TM_Text then   // проверяем, что Sender это текст
    with Sender as TM_Text do // приводим Sender к типу "TM_Text"
    begin
      aSeconds := SecondsBetween(0, DateTime_Val.AsDateTime); // получить кол-во секунд
      Text := SecondsToStr(aSeconds);     // переводит секунды в строку вида "чч:мм:сс".
    end;
end.

11
Ваши вопросы / Re: Ошибки OPC серверов
« : 12 Марта 2024, 11:22:24 »
Здравствуйте.

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

Если дело не в этом, то пришлите нам на support@simple-scada.com конфигурацию OPC-сервера и текущую версию Вашего проекта для проверки.

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

В web-клиенте "Режим масштабирования" работает иначе, чем в десктоп-клиенте. Подробнее см. по ссылке.

13
Ваши вопросы / Re: Вопрос по таймерам
« : 07 Марта 2024, 10:27:32 »
Здравствуйте.

Данные скрипты так, как Вы описали, работать не будут. Таймерные процедуры рассмотрены по ссылке. Пример работы с таймерами можно найти в демо-проекте -> страница "Скрипты" -> "Простые скрипты (1)" -> пример №3). Если нужно поставить таймер на паузу, то нужно использовать процедуру "TimerPause". Если сбросить, то "TimerReset".

Чтобы при достижении значения переменной "vrTime" значения, заданного в календаре "Cal", таймер останавливался или сбрасывался, в скрипт (на событие "OnDataChange" компонента "Текст" с которым связана переменная "vrTime") нужно добавить соответствующую проверку и выполнение процедур "TimerPause" или "TimerReset":
Код: (delphi)
begin
  // если значение таймера >= значение календаря, то ставим таймер на паузу
  if CompareDateTime(vrTime.AsDateTime, Cal.AsDateTime) >= 0 then
    TimerPause(vrTime);

  Text.Text := IntToStr(TimerGetState(vrTime));
end.
Также, в скрипте на кнопку Пуск нужно удалить строку "vrTime.Value := Cal.Value;"

Если не разберетесь, то пришлите для проверки на support@simple-scada.com текущую версию Вашего проекта из директории "..\Simple-Scada 2\Projects\" и укажите скрипты, которые нужно проверить. Опишите подробно, какую именно задачу Вы пытаетесь решить? Если требуется включать/выключать какое-либо оборудование по расписанию, то для этого можно использовать компонент "Расписание".

14
Ваши вопросы / Re: Вопрос по SELECT, MSSQL и Quality.
« : 29 Февраля 2024, 10:22:14 »
Здравствуйте.

Да, это нормально. Если "Поле" не связано с переменной, то оно будет доступно для ввода и в него выведется значение, указанное в редакторе (см. свойство "Значение").

При необходимости "Поля" которые не связаны с переменной (не указана подстановка или переменной с указанным именем не существует) можно скрывать. Для этого на событие "OnInit" шаблона/шаблонного окна нужно написать такой код:
Код: (delphi)
var
  aObj: TM_Object;
begin
  aObj := GetTemplateObject('Field1');
  aObj.Visible := aObj.Variable <> nil;
 
  aObj := GetTemplateObject('Field2');
  aObj.Visible := aObj.Variable <> nil;
end.
В скрипте нужно перечислить все возможные объекты, которые предполагается скрывать.

15
Ваши вопросы / Re: Вопросы по WEB в Simple-Scada 2
« : 27 Февраля 2024, 19:04:09 »
Извините, допустили ошибку в скрипте "raport_LVP". Правильный код:
Код: (delphi)
var
  aReport: TM_Report;
begin
  if ArcGroupTag = 2 then
  begin
    aReport := ReportBuildEx('Рапорт электроэнергия ЛВП', ClientData);
    aReport.View(ClientData.Name);
  end;
end.

Страницы: [1] 2 3 ... 11