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

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

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

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


Сообщения - pan2000

Страницы: [1] 2 3 ... 13
1
Ваши вопросы / Re: Подстановки для сообщений
« : 30 Сентября 2024, 21:37:16 »
    Здравствуйте.
 
Универсальный скрипт конструирует сообщение  по изменению переменной xxxxx_Val, начинающиеся с описания этой переменной и текста, зависящего от значения переменной.
Далее в текст сообщения включаются атрибуты переменной xxxxx - описание, значение и единицы измерения. Тип сообщения, подтверждение и звук определены непосредственно в скрипте.
Код: (delphi)
var aVar: TM_Variable;
    aStr: string;
begin
  if IsFirstChange then exit;
  with Variable do
  begin
    aVar := GetVariableByName(Copy(Name, 1, Pos('_Val', Name) -1));
    if AsBool then
      aStr := Description + ' Включение. '
    else
      aStr := Description + ' Выключение. ';
  end;
  with aVar do
    AddMessage(Now, mkMessage, aStr + Description + AsStr + Units, true, false);
end.       

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

2
   Здравствуйте.
  Единственный слоёный объект по части раздачи окон - это кнопка вызова окна. Само окно ни с того ни с сего, [внушительно перебил неивестный,] не откроется. Да и в волчьем окне любой поросенок может быть поражен в правах доступа, равно как и наоборот.
  На мой взгляд, с точки зрения минимума затрат создания "картинки", слоёная структура превосходит вычислительно-модифицируемую, приемлимую для одноклиентских проектов (либо исскуственно сведенную к оным)
  Если есть возможность, то в имена объектов стопки можно добавить признак "стопочности", причем при удачном стечении обстоятельств вся стопка в инспектор объектов потянется за верхним. Кроме того в проект можно включить страницы с некоторыми пояснениями для продолжателей Вашего проекта.

P.S. Возможно несколько облегчит жизнь возможность ещё и переключение редактора с инспектором объектов в режим отдельного пользователя, обеспечивающий отображение его объектов и общих. Хотя ...

3
     Здравствуйте.
  Если открывать окно именно по событию OnClick, не используя свойство "Окно" объекта, то скриптом можно открыть нужное пользователю окно. В примере три группы пользователей - с индивидуальным окном, с монопольным окном и общим окном на группу.
  Монопольное окно исключает ситуацию, когда два пользователя "загибают" одну переменную в противоположные стороны, а третий с интересом наблюдает за ними (система коллективной безответственности им. Лебедя, Рака и Щуки).

4
   Здравствуйте.
...
1. Поля привязаны к переменным (привязываются при инициализации автоматически, примерно как в вашем скрипте при сбросе перебор полей, а не через подстановки)
2. Значение после сброса у каждого поля своё и берется их других переменных (т.е. дополнительная переменная уже занята полезным делом)
...
...либо пытается сделать рутину проще. Например, метод подстановки для шаблонов по сути означает, что имя переменной надо ввести вручную, а не выбрать из списка переменных, что сильно повышает вероятность ошибки ввода, найти которую потом будет сложно...
   Предпосылки для примера из вложения:
1. Все имена переменных и объектов имеют структуру <префикс>_<индекс от 1 до ...> и желательны непрерывные значения индекса;
2. У шаблона единственная подстановка - номер шаблона;
3. Объект связи должен иметь индекс совпадающий с номером шаблона и используется для передачи начальных имен переменной. Нужен для исключения ошибок редактирования, т.к. переменные выбираются из списка. Хотя по мне, так два имени вполне могут быть включены и в подстановки шаблона. Использование объекта оправдано при передаче чего-то из шаблона.
4. При инициализации шаблона выполняется несколько видов контроля - наличие объекта связи, наличие обоих переменных у объекта связи, наличие пар переменных с допустимыми префиксами.
5. Вид экземпляра шаблона настраивается по числу переменных.

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

  Ещё одним способом доступа к объектам шаблона является получение при инициализации шаблона цепочки ссылок на следующий объект начиная с объекта источника и передаче в приёмник ссылки на объект-источник.
  Примеры можно найти на форуме по поисковому запросу "Шаблон".

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

считаю вопрос закрыт тк мой скрипт криво, но справляется с уведомлениями.
Для однократной отправки сообщения необходим флаг "сообщение отправлено", причем в качестве оного можно использовать свойство Color объекта.
Вполне возможно, что дополнительно придется добавить гистерезис температуры для исключения отправки сообщений при "болтанке" температуры вблизи границы:
Код: (delphi)
const dT = 3;   // гистерезис температуры
begin
   if Sender is TM_Object then     // проверяем, что Sender это объект
     with Sender as TM_Object do   // приводим Sender к типу "TM_Object"
       if Color <> clRed then
       begin
         if AsSingle >= VariableEx.AsSingle then
         begin
           Color := clRed;
           AddMessage(Now, mkWarning, Variable.Description + ' превысила ' + Variable.AsStr + ' градуса ', True, True);
         end;
       end
      else
        if AsSingle < (VariableEx.AsSingle - dT) then Color := RGB(191,191,191);
end.
Для выполнения контроля при изменении границы можно добавить скрипт по изменению дополнительной переменной (границы):
Код: (delphi)
begin
    Sender.Color := RGB(191,191,191);     // обязательно выполнить сравнение с границей
    TM_Object(Sender).OnDataChangeEvent;
end.

Вполне рабочий вариант с использованием границ переменных.
{удалено, чтобы не повторять написанное Simple_Scada выше}

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

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

  Запрос к БД должен "расыпать" один столбец данных исходной таблицы на три столбца данных, причем с использованием фильтрации по ID данных и по времени.
  На фильтр по времени существнно влияет как формируется временная метка записи в БД, либо от внешней архивируемой переменной, либо от внутренней по временным событиям scada-сервера.
  В примере из вложения фильтр по одиночному значению метки времени в пределах первой минуты часа/получаса. При отсутствии метки времени в пределах фильтрации, выдается сообщение "нет данных". ЛКМ на выбранной ячейке удаляет соответствующую строку тестовой таблицы.
  Предварительно строится временная таблица меток времени от начала недели с интервалом в 12 часов, далее формируется запрос на объединение таблицы меток и трех таблиц данных, полученных подзапросами.
 
  P.S. Иллюзия "игнорирования" - в разделе "Ваши вопросы" обнаружено всего 12 вопросов без ответов :), да и то многие из них предполагают отсутствие ответов. 

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

  Запрос к БД должен содержать фильтры, ограничивающие выборку данных только за одну предыдущую неделю с прореживанием данных.
  Простой фильтры предполагает, что метки времени попадают в первый минутный интервал периода измерения, т.е. минуты = 0 или 30, а секунды = 00..59:
 
Код: (delphi)
var aFirstDay: TDateTime;
begin
  aFirstDay := IncDay(DATE, - (6 + integer(DayOfTheWeek(Now))));                    // первый день пред. недели
  Table5.RunSQL('SELECT DATE_FORMAT(`t`,''%d.%m.%Y  %H:%i'')'                       // форматирование даты-времени
              + ',FORMAT(`T_3`,2),FORMAT(`T_6`,2),FORMAT(`T_7`,2) FROM `my_table` ' // форматирование температур
              + 'WHERE (MINUTE(`t`) = 0) '                                          // фильтр: минуты=0 или начало часа
              + 'AND ((HOUR(`t`) MOD 12) = 0) '                                     // фильтр: час=0 или час=12
              + 'AND (`t` >=' + MySQLDateTime(aFirstDay, dttHour)                   // фильтр: предыдущая неделя - начало
              + ') AND (`t` <' + MySQLDateTime(IncDay(aFirstDay, 7), dttHour)       //         предыдущая неделя - конец
              + ') ;',
              tsSaveFixRow);
end.
Во вложении пример построения исходной таблицы за две предшествующие и начало текущей недели. Построение таблицы результатов.

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

 Вполне можно обойтись без таймера, достаточно в скрипте по изменению основной переменной переводить кнопку с фиксацией в начальное состояние:
Код: (delphi)
begin
  with Sender as TM_Button do
    if AsInt > 0 then                     //  для boolean: if AsBool then
      begin
        Value := 0;                       //  для boolean:  Value := false; 
// действие при нажатии кнопки, например счетчик числа нажатий на самой кнопке
        Tag := Tag + 1;
        States[0].Caption := IntToStr(Tag);
      end;
end.


Для кнопки с таймером реализация немножко сложнее. Набор скриптов для "самодостаточной" кнопки (т.е. не требующей изменения скриптов или добавления новых переменных):
- по изменению основной переменной:
Код: (delphi)
begin
  with Sender as TM_Object do
    if AsInt > 0 then Tag := 5;  // Tag - это таймерная переменная данной кнопки
// действие при нажатии кнопки
end.

- "Прошла секунда":
Код: (delphi)
begin
  timer.Inc(1, 0, 10000000);            // это единственная виртуальная переменная - таймера хватит на 7 лет
end.
- по изменению дополнительной переменной, в качестве которой выступает виртуальная переменная timer:
Код: (delphi)
begin
  with Sender as TM_Button do
    if Tag > 0 then
    begin
      if Tag = 1 then Value := 0; // обнуление основной переменной - сброс кнопки в начальное состояние
      Tag := Tag - 1;
// иллюстрация - изменение значения таймерной переменной
      States[1].Caption := IntToStr(Tag);   
    end;
end.
       

Для кнопок с изменяемым таймером можно использовать шаблон. Принудительное переключение кнопки в начальное состояние можно заблокировать, управляя свойством Enabled кнопки.
Все примеры во вложении.         

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

  Передать набор текстовых элементов в шаблон можно в свойстве Hint объекта. Текстовые элементы разделяются разделителем, не входящим ни в один элемент. Общая длина такой строки ограничена 255 символами. При подстановке текстовых элементов возможны два варианта - фиксированное число элементов (удобнее, но для разного числа нужно несколько шаблонов или частичная подстановка в самый "большой" ;D) или произвольное (шаблон один, предварительно подстановку можно подготовить текстовым редактором). Варианты выбора по основной переменной "один из двух" (boolean) или "по номеру" (integer).
  Управлять цветом можно посредством набора пар "цвет объекта" - "цвет шрифта" по номеру набора из дополнительной переменной.
  Бесскриптовый способ изменения текста с предустановленными цветами - объект "Кнопка".
Пример во вложении.

11
    Здравствйте.

В зависимости от желаемого правила изменения можно менять цвет с учетом двух переменных (один скрипт на оба события изменения переменных):
Код: (delphi)
begin
  with Sender as TM_Object do
    case SetBit(SetBit(0, 0, AsBool), 1, VariableEx.AsBool) of
    0: Color := clGray;     // оба выключены
    1: Color := clLime;     // насос с управлением по основной переменной
    2: Color := clYellow;   // насос с управлением по дополнительной переменной
    3: Color := clRed;      // а это - оба сразу !
    end;
end.
или независимо по каждой переменной:
Код: (delphi)
begin
  with Sender as TM_Object do
    if AsBool then Color := clLime else Color := clGray;
end.
Код: (delphi)
begin
  with Sender as TM_Object do
    if VariableEx.AsBool then Color := clYellow else Color := clGray;
end.
Пример во вложении.

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

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

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

Штатную систему трендов можно использовать для предварительного просмотра и подготовке к формированию отчета.
В основе предпросмотра - таблица графиков, управление архивированием переменной и переход в меню трендов.
При выполнении критерия начала запуска измерения (в примере - просто порог) в таблицу записывается текущее время, разрешается архивирование переменной и запускается таймер.
По окончании таймера архивирование переменной выключается.
По клику на строку таблицы вызывается просмотр тренда в пределах 1 минуты (самый минимальный интервал отображения, разрешение графики примерно 30 элементов на 1 секунду). Выключение архивирования дает слева и справа от графика пустые поля (разумеется если графики следуют по времени не слишком часто).
В примере для переменной используется возрастающая последовательность типа пилы. Генератор пилы дает примерно 20 отсчетов в секунду и работает после запуска ограниченное время (иначе графики "пилы" пойдут сплошным потоком :-\).
Устанавливаются порог начала измерения и начальное значение генератора. При маленькой разнице от момента запуска генератора до момента начала измерения могут получится два близко расположенных на тренде графика.   

14
Ваши вопросы / Re: Создать Амперметр
« : 05 Мая 2024, 08:35:25 »
   Здравствуйте.

  В Simple-Scada можно реализовать стрелку, а в качестве собственно стрелочного прибора использовать пользовательское изображение (да получится амперметр).
Во вложении пример амперметра. Пример построен с использованием шаблонов.
Шаблон имеет подстановки: измеряемая переменная, полный угол отклонения стрелки и внутренний радиус. Последние два параметра исключительно для правильного совмещения изображения и стрелок, и при желании могут быть забиты в объект изображение.
Стрелка состоит из двух тонких прямоугольников, представляющие радиальные сегменты с одинаковым внутренними радиусами и различными наружными. Для вращения такого объекта необходимы следующие параметры: координаты центра вращения, наружный радиус, высота объекта и угол поворота. В этом случае для всех "стрелок" достаточно одного универсального скрипта по изменению измеряемой переменной.
Угол поворота вычисляется из значения измеряемой величины, в пределах минимума и максимума переменной для полного угла отклонения стрелки. Высота объекта есть собственное свойство. Координаты центра вращения определяются при инициализации по одной из стрелок, которая должна быть вертикальна, а ее вертикальная проекция проходит через предполагаемый центр вращения стрелки прибора. Аналогично и для наружного радиуса, при инициализации он вычисляется как высота стрелки плюс внутренний радиус.
Файл примера не содержит графику прибора, и предварительно должен быть считан в пользовательские изображения из вложения предыдущего сообщения.

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

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

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