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

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

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

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


Сообщения - pan2000

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

Добрый день. Вопрос в следующем:
Хочу реализовать выбор режима работы по расписанию или по кнопке. Думаю реализовать с помощью метода OnActive.
При наличии ручного режима для управления ОРС-переменной хорошо подходит кнопка с двумя состояниями. Кнопку можно настроить либо на запись двух значений, либо на изменение одиночного бита.
А расписание уже просто управляет этой кнопкой, недоступной/невидимой.  В примере с двумя кнопками - "РУЧНОЕ-АВТОМАТ" и "ВЫКЛ.-ВКЛ." приведены два вида шаблонного окна - кнопки в окне или кнопки на странице.
Правила функционирования кнопок:
- кнопка "ВЫКЛ.-ВКЛ." непосредственно управляет ОРС-переменной, либо пара значений, либо одиночный бит. Для каждой пары шаблонное окно уникально, для одиночных бит достаточно одного шаблонного окна (для кнопок в окне +1 подстановка "номер бита");
- кнопка "РУЧНОЕ-АВТОМАТ" управляет видимостью или доступностью кнопки "ВЫКЛ.-ВКЛ." (для кнопок на странице может быть индикатором состояния ОРС-переменной);
- В состоянии "АВТОМАТ" расписание управляет кнопкой "ВЫКЛ.-ВКЛ." по значению основной переменной, к которой (по ID и имени проекта) собственно и привязана таблица интервалов этого расписания. В случае двух режимов использовать событий OnActivate и OnDeacnivate нецелесообразно, т.к. для правильного изменения значения ОРС-переменной при переключении режимов нужно знать текущее состояние расписания (внутри/вне интервала) и, следовательно придется его восстанавливать по событиям (что собственно и есть значение основной переменной).

Особенности варианта с кнопками на странице (поскольку приходится связывать реальные и виртуальные объекты, а очень желательно обойтись без уникальных скриптов для каждого), причем достаточно всего одного шаблонного окна:
- создать кнопку управления режимами "РУЧНОЕ-АВТОМАТ" с основной переменной и без событий;
- создать кнопку управления ОРС-переменной "ВЫКЛ.-ВКЛ." с соответствующим управлением ОРС-переменной и без событий;
- в подстановке шаблонного окна "кнопка_режима</>кнопка_переменной" записать имена кнопок через знак "наклонная черта";
- в подстановке шаблонного окна "переменная_расписания" указать уникальную переменную.
Связи (цепочка ссылок на объекты) устанавливаются при инициализации конкретного экземпляра шаблонного окна.

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

... Заказчик попросил, чтобы при возникновении критических аварий, всплывало окно с аварийным оповещением ...
Всплывающее окно может содержать гораздо больше информации чем сообщение. В примере индикатором аварий выступает вектор аварий у которого каждая авария связана с определенным битом.
При возникновении любой аварии открывается окно с мигающей рамкой (в примере для всех клиентов, т.к. авария это серверное событие, но для многопользовательского проекта окно должно быть связано именно с пользователем и необходимо селективное открывание окна, например только для первого присутствующего из списка пользователей). 
Каждой из трёх аварий соответствует сообщение о причинах аварии и кнопка "Подтверждение" для сброса бита аварии.
Окно закроется только после подтверждения всех аварий.
Возможны дополнительные действия/сообщения при некоторой комбинации аварий, например при всех трех.

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

Для начала нужно определить в какое состояние переходит вентилятор при отключении расписания (сохраняет текущее, выключен), а дальше два варианта:
- перевод расписания в неактивное состояние с последующей блокировкой его редактирования;
- блокировка формирования управляющих сигналов без блокировки редактирования.
Во вложении пример с кнопкой переключения режимов редактирование-работа, причем в режиме редактирования блокируются управляющие сигналы, сохраняется состояние вентилятора и разрешается режим ручного управления вентилятором.
Так что если оператор включит редактирование при работающем вентиляторе и просто уйдет на обед, то вентилятор продолжит дуть :-\

4
   Здравствуйте.
...записывает себе в базу данных очень маленькие значения переменных. ... Приходится удалять их вручную...
Т.е. речь идет от отбрасывании заведомо недопустимых значений.

Если найти причину образования некорректных данных поступающих в скада-систему не получится, то можно попробовать отфильтровать некорректные значения переменной... в настройках переменной включить Фильтр мин. макс.
Судя по описанию и интерактивной картинке фильтра в редакторе, "Фильтр мин. макс" не отбрасывает недопустимое значение, а конвертирует его в минимум/максимум.
На картинке зеленым цветом показано поведение переменной при условии игнорирования недопустимых значений. Хорошо видно, что площадь под кривой заметно различается для фильтра и при отбрасывании значения.
В этом случае отчет-то может и будет строится, а вот его корректность ещё придется доказать (понятно, что недопустимые значения весьма редкие, и отчет скорее всего не пострадает, но "не аккуратненько").

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

Для начала нужно убедиться, что от ОРС-сервера не поступают ошибочные данные. Индикация наличия ошибочных - скрипт "Изменились переменные":
Код: (delphi)
// ОТЛОВ МИНИМАЛЬНЫХ ЗНАЧЕНИЙ
begin
  with Variable do
// выбор минимального порога
//    if (Value <= LowAlarm) and (not IsFirstChange) then  // индивидуальный
    if (Value <= 5) and (not IsFirstChange) then       // общий

      AddMessage(Now, mkAlarm, Name + '=' + AsStr, True, True);
end.
При наличии ошибок желательно их ликвидировать как явление.
И как последнее средство - введение фильтра минимальных значений перед архивированием. Т.е. переменная разделяется на входную (не архивируемую), по изменению которой происходит контроль величины и выходную (архивируемую), перезаписываемую из входной при прохождении контроля.
При условии, что имена входной и выходной переменной отличаются только суффиксом у выходной переменной - скрипт по событию "Изменились переменные":
Код: (delphi)
// ФИЛЬТР МИНИМАЛЬНЫХ ЗНАЧЕНИЙ
begin
  with Variable do
// выбор минимального порога
//    if (Value > LowAlarm) and (not IsFirstChange) then
    if (Value > 5) and (not IsFirstChange) then

      GetVariableByName(Name + '_out').Value := Value;
end.
См. пример.

6
Ваши вопросы / Re: Вопрос по рассписанию.
« : 29 Апреля 2025, 02:20:35 »
   Здравствуйте.

  Поскольку нет аппаратного условия сброса управляющих сигналов, то остается формировать длительности управляющих сигналов сервером Simple-Scada.
Скрипт по событию "Текущее время вошло в установленный интервал объекта "Расписание"":
Код: (delphi)
begin
  SCI_Pusk.Value := true;
  RunDelay(3000, 1);
end.
Скрипт по событию "Текущее время вышло из установленного интервала объекта "Расписание"":
Код: (delphi)
begin
  SCI_Stop.Value := true;
  RunDelay(3000, 2);
end.
Скрипт по событию "Выполнена задержка":
Код: (delphi)
begin
  case DelayEventData.Tag of
  1: SCI_Pusk.Value := false;
  2: SCI_Stop.Value := false;
  end;
end.
Пример во вложении.

7
Ваши вопросы / Re: Границы переменных
« : 25 Апреля 2025, 00:57:48 »
   Здравствуйте.

Появление баннера при нарушении "Верхней аварийной" границы и пропадание по выходу из зоны нечувствительности:

1.Если для прочих нужд проекта не используется "Верхняя предупредительная" граница, скрипт "Нарушена граница":
Код: (delphi)
begin
  Shape5.Visible := Variable.GetValueZone = 2;
end.
, в вариациях задания зоны нечувствительности:
- "Только аварийные" границы - сама "Зона нечувствительности";
- "Аварийные и предупредительные" границы - либо нижняя граница зоны нечувствительности задается "Верхней предупредительной" границей при "Зоне нечувствительности"=0, либо "Зоной нечувствительности" при "Верхней предупредительной"="Верхней аварийной".

2. Без использования стандартной процедуры контроля границ, скрипт "Изменилась переменная":
- с нулевой зоной:
Код: (delphi)
begin
  Shape5.Visible := Variable.AsFloat >= Variable.HighAlarm;
end.
- с ненулевой зоной:
Код: (delphi)
const hist = 4.00;  // величина зоны в единицах измерения переменной
begin
  if (Variable.AsFloat >= Variable.HighAlarm) then Shape5.Visible := true;
  if Shape5.Visible and (Variable.AsFloat < (Variable.HighAlarm - hist)) then Shape5.Visible := false;
end.
.
Вариант 1 более предпочтительный, т.к. и скрипт проще, и событий меньше. Примеры для некоторых вариантов во вложении.

8
Ваши вопросы / Re: Работа с таблицами
« : 16 Апреля 2025, 22:12:31 »
    Здравствуйте.

Красный лучше оставь белым.
(Если время пребывания меньше - время сушки - красный, если время пребывания больше - время сушки - зеленый.)
Раскраска строк в два цвета (красный-зеленый) не соответствует Вашему первому сообщению - там красный цвет (предупреждающий/аварийный) означает что сушка закончилась преждевременно, и лучше не использовать его для нормально идущего процесса. Должна быть явная индикация (в общей таблице или в отдельной). Это позволяет визуально контролировать ошибки (сейчас выкатил тележку раньше времени и концы в воду) операторов тележки. Да и то только если таблицы видит начальник.
Цитировать
... корректно записываются и удаляются данные.
На мой взгляд более правильно использовать БД именно как БД, а не как некоторый сохраняемый массив данных. Т.е. по хорошему в БД при заезде тележки должно фиксироваться дата-время заезда и некоторая идентифицирующая информация о загрузке тележки (доски, брус, ... кирпич и т.д.)
При выезде тележки БД дополняется временем сушки, текущем интервалом контроля и идентификатором выкатившего тележку оператора/бригады. В этом случае начальник может контролировать многие очень интересные вещи.

Замечание по скрипту обработки SQL-запроса - к сожалению окончание скрипта не видно, но если у условия "if DataSet.IsEmpty = false then" нет альтернативы "else" с очисткой таблицы, то группа тележек, умудрившаяся выкатиться, полностью освободив помещение в течение последней минуты, может и не удалиться из таблиц формы.
Можно обрезать "жирок" со скриптов:
Код: (delphi)
begin
  // запрашиваем первые до 20 строк
  RunSQL('SELECT numberCart,timeCart1,timeCart2 FROM cart1 LIMIT 20;', Table1, 3);
  // запрашиваем остаток строк
  RunSQL('SELECT numberCart,timeCart1,timeCart2 FROM cart1 LIMIT 20 OFFSET 20;', Table2, 3);
end.
Код: (delphi)
var aRow, i: integer;
    aColor: cardinal;
begin
  if DataSet.Tag = 3 then
    with DataSet.Sender as TM_Table do
      for aRow := 0 to 19 do
        if not DataSet.EOF then
        begin
          if DataSet.Fields[2].AsInt > dryingTime1.AsInt then aColor := clGreen
          else aColor := clRed;
          for i := 0 to DataSet.FieldCount - 1 do
          begin
            GetCell(i, aRow).Text := DataSet.Fields[i].AsStr;
            GetCell(i, aRow).Color := aColor;
          end;
          DataSet.Next;
        end
        else
          for i := 0 to 2 do
          begin
            GetCell(i, aRow).Text := '';
            GetCell(i, aRow).Color := clNone;
          end;
end.

Что касается упорядочивания строк в порядке заезда тележек, то только одни времена суток (без даты) сортировкой упорядочить не удастся. Для случая только времени суток можно добавить в качестве первичного ключа новый столбец с автоинкрементом (см. в примере).

С проблемой считывателя меток нужно разбираться по его документации. Без этого пытаться городить всевозможные фильтры и логику бесполезно, т.к. доподлинно не известно всегда ли это будет работать или перестанет по изменению погоды, скоростью движения тележки и т.д.
В качестве шаманства с бубном, можно изменить фронт срабатывания TagRead (в предположении что один фронт индицирует начало считывания, а другой собственно завершение).

9
Ваши вопросы / Re: Работа с таблицами
« : 12 Апреля 2025, 06:23:56 »
 Здравствуйте.

И есть ли возможность заполнения таблицы из БД полностью на всю форму без прокручивания (на картинке). В таблице количество строк равно 40.
Заполнить таблицу, состоящую из нескольких групп однотипных столбцов, "змейкой" можно (по крайней мере в MySQL версии 8.0) с использованием оконной функции LEAD.
Так для таблицы my_table из БД со столбцами col1, col2, col3 запрос на заполнение таблицы в Simple-Scada из двух групп не более чем в 20 строк:
SELECT *, LEAD(col1,20) OVER(),LEAD(col2,20) OVER(),LEAD(col3,20) OVER() FROM my_table LIMIT 20; 
Реальный запрос может быть усложнен за счёт замены NULL на пустую строку, форматирования данных, добавления вычисляемых столбцов. Скрин показывает результаты работы запроса по таблице из предыдущих примеров. Запрос для левой половины таблицы включает замену NULL, вычисление и форматирование столбца, правая - только вычисления.


10
Ваши вопросы / Re: Работа с таблицами
« : 10 Апреля 2025, 12:27:28 »
   Здравствуйте.
Я это воспринял как автоматическое с датчика, а если заносится ручками, то смотрите пример @pan2000.
Наличие раздельных переменных для меток заезда и выезда не обязательно указывает на "ручки" :-\, равно как и ввод значения метки в поле. Достаточно изменить события на "Изменилась основная переменная" и это будет вариант для помещения с раздельным заездом и выездом (например, туннельная печь).
Для единственного поля ввода метки (считывателя) - заезд/выезд определяется по наличию тележки в помещении. Пример во вложении.

11
Ваши вопросы / Re: Работа с таблицами
« : 09 Апреля 2025, 20:44:07 »
   Здравствуйте.

  Размер таблицы ограничен 40 строками, резонно предположить что больше тележек просто-напросто не входит в помещение или в наличии не больше 40 меток тележек.
  В примере (для БД MySQL, не более 40 меток) используется пара совмещенных таблиц: верхняя - прозрачная, содержащая собственно данные о тележках (метки событий урезаны только до времени), нижняя - с широкими колонками, перекрывающими набор колонок верхней, и полным значением времени заезда (дата-время).
Такое решение позволяет избежать нудных перекрашиваний группы ячеек из верхней таблицы и получать правильное значение времени нахождения в помещении (независимо от перезапусков сервера), как разность текущего времени и времени заезда.

Таблица содержит все последние завершенные (в том числе удачные) и все текущие переезды тележек. Можно исключить из таблицы удачно завершенные переезды, однако гарантировано увеличить количество меток (при условии что в помещении одновременно не более 40 тележек) не получится, т.к. в таблице могут присутствовать красные строки для тележек вне помещения.
При новом заезде тележки информация о предыдущем заезде удаляется из таблицы посредством смены знака у идентификатора тележки, что позволяет сохранять предысторию.
При запуске проекта и по событиям "Заезд тележки №№", "Выезд тележки №№", "Удаление из таблицы тележки №№" происходит заполнение таблицы из БД с раскладкой данных из набора данных DataSet.
Вычисление текущего времени нахождения в помещении  тележек и "раскраска" нижней таблицы осуществляются по таймеру 1 сек.

P.S. Для уменьшения скрипта раскладки данных используется более сложная форма запроса, при желании можно свести запрос к минимальному и усложнить обработку в скрипте (это по поводу смены БД).
Пример только для иллюстрации: задание интервала контроля ограничено 23:59:59, длительность нахождения в помещении ограничена ~ 800 часами, нет контроля общего числа тележек в помещении.
При условии не более 40 тележек в помещении, было бы правильно отображать в таблице состояния присутствующих в помещении тележек, а преждевременный выезд тележек перенести в отдельную таблицу.

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

По видимому, объекты формы используются только для задания части начальных значений перед работой с окном-формой, и не предполагают изменения свойств входящих в форму объектов.
Для исключения возможных ошибок/конфликтов в скрипте обработки формы следует использовать данные только из FormData. Пример ошибки подобного сорта:
- в моём предыдущем примере обнаружен КОНФЛИКТ при работе нескольких клиентов - способ передачи выбранной переменной в скрипт обработки формы посредством основной переменной поля-формы ввода значения переменной, которая не локализуется в форме и является общей для всех клиентов. При отправки формы изменялись свойства переменной из последнего открытого окна-формы.
Исправление: имя выбранной переменной передается через дополнительное невидимое поле, локализуемое в форме.

Пример с исправлениями и возможностью изменения типа границ во вложении.

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

13
Ваши вопросы / Re: Ввод данных типа Single
« : 26 Марта 2025, 15:15:41 »
   Здравствуйте.

  Для ограниченного набора возможных значений переменной ввода (в Вашем случае 10001 значение) можно использовать целочисленную переменную PositionTC со сдвигом запятой -1.
Код: (delphi)
begin
   case PositionTC.AsVariant of
        0..160      : wNumberPlace.Value := 1;
        161..1000   : wNumberPlace.Value := 2;
        1001..5000  : wNumberPlace.Value := 3;
        5001..7000  : wNumberPlace.Value := 4;
        7001..10000 : wNumberPlace.Value := 5;
      end;
end.

Для вещественной переменной можно использовать округление до ближайшего целого:
Код: (delphi)
...
  case Round(PositionTC_1.AsSingle * 10) of
...

14
Ваши вопросы / Re: Страница трендов
« : 18 Марта 2025, 10:31:11 »
   Здравствуйте.

Если достаточно просмотра тренда с момента клика по ячейке, то можно использовать временной тренд с одном трендом и переключением переменной.
В противном случае (поскольку данные накапливаются) необходим индивидуальный тренд для каждой переменной. В зависимости от общего количества трендов это может быть один временной тренд или несколько. Нужный тренд выбирается управлением видимостью тренда/временного тренда.
Наиболее простой вариант это единственный временной тренд (в предположении, что количество трендов не превысит максимального для временного тренда ?) и следующие правила:
- тренд выбирается по клику по строке таблицы;
- для выбора тренда используется поиск по их переменным до совпадения с дополнительной переменной ячейки;
- шкала устанавливается по минимуму-максимуму переменной;
- количество меток шкалы и линий по Y определяются шкалой переменной в свойстве "Единица измерения". Если это свойство используется в проекте, то простых решений, кроме фиксированного значения в редакторе, нет.
Пример с двумя просто переменными и одной с генератором пилы во вложении. 

При необходимости можно выбирать для одновременного просмотра и тренды нескольких переменных (определивши как отображать шкалу и т.д.), но это уже другая история...

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

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

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