Simple-Scada forum

Simple-Scada 2 => Ваши вопросы => Тема начата: alan54 от 26 Ноября 2018, 17:44:33

Название: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 26 Ноября 2018, 17:44:33
Не могу сообразить сам, подскажите, пожалуйста - как вывести в отчет интервалы времени между определенными событиями, например, выходами готовых щитов (см. вложение)?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 28 Ноября 2018, 11:00:08
Здравствуйте.
Извините за задержку с ответом. Т.е. нужно вывести время прошедшее между временем предыдущей строки и временем текущей строки? Для этого можно в бэнде данных разместить компонент Текст, дважды кликнуть его для редактирования и использовать следующее выражение:
Код: (c#)
{DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время"))}
Данный код получает разницу во времени между текущей и предыдущей строкой. Также не забудьте выставить у компонента Текст формат "Время". Для этого кликните его ПКМ и выберите пункт "Формат".
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 28 Ноября 2018, 11:26:02
Все понятно, я не знал функцию system.datetime. Большое спасибо!
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 28 Ноября 2018, 11:33:56
Это явное приведение к типу данных DateTime. Дело в том, что функция Previous возвращает указатель на объект предыдущей строки, без определённого типа данных. А функция DateDiff работает только с типами DateTime. Поэтому мы должны явно указывать тип данных и вместо "Previous(Данные, "Время")" писать "(System.DateTime)Previous(Данные, "Время")"
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 28 Ноября 2018, 12:39:46
Наберусь наглости и задам еще вопрос: как написать условие для выделения ячейки отчета цветом, если значение разности времен больше 5 минут?  Пытаюсь написать Minute(полученное_выражение_ в_ячейке) > 5 - ругается...
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 28 Ноября 2018, 13:56:49
Нашел, вроде надо так:
РазницаВоВремени.Minutes > 5
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 28 Ноября 2018, 14:45:15
Результатом функции DateDiff является структура TimeSpan (https://docs.microsoft.com/ru-ru/dotnet/api/system.timespan?view=netframework-4.7.2). Обращаясь к свойствам этой структуры, можно получить различные значения. Свойство Minutes для Вашей задачи не подходит и нужно использовать TotalMinutes:
Код
РазницаВоВремени.TotalMinutes > 5
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 28 Ноября 2018, 18:01:07
Очень Вам благодарен за оказанную помощь!
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 29 Ноября 2018, 18:16:30
Дальше опять зашел в тупик. В итоге отчета надо просуммировать интервалы более 5 минут. Написал такую формулу, пока без условия (просуммировать все):
{SumTime(Источник_1.ВремяМеждуВыходомЩитов)}
Почему-то выдает 00:00:00, хотя в колонке полно ненулевых значений.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 29 Ноября 2018, 23:32:47
Как мы поняли, "Источник_1.ВремяМеждуВыходомЩитов" у Вас - это рассчитываемая колонка с типом данных TimeSpan? Из-за особенностей при взятии значения из рассчитываемых колонок источника данных, проще всего суммировать время следующим способом:
Теперь в нём будет выводиться суммарное время для всех строк. Но если нужны условия (суммировать только интервалы больше 5 минут), то придется использовать более сложный способ:
Код: (c#)
if (!PreviousIsNull(Источник_1, "Время")){
  TimeSpan aTime = Источник_1.ВремяМеждуВыходомЩитов;
  if (aTime.TotalMinutes > 5)
    vrTotalTime += aTime;
}
Теперь при построении отчета в переменную vrTotalTime будут просуммированы все интервалы "Источник_1.ВремяМеждуВыходомЩитов" с значениями более 5 минут. Значение переменной vrTotalTime можно вынести в любое место отчета.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 30 Ноября 2018, 07:07:32
Большое спасибо за подробные разъяснения! Что бы я без Вас делал...
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 07 Декабря 2018, 17:34:03
...Значение переменной vrTotalTime можно вынести в любое место отчета.
А можно ли значение переменной vrTotalTime экспортировать из отчета в архив базы данных, чтобы затем использовать ее для построения другого отчета? Если да, то каким образом?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 07 Декабря 2018, 23:25:33
Такой возможности нет.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 08 Декабря 2018, 08:31:08
Тогда подскажите пожалуйста, как создать такую вычисляемую переменную в скрипте проекта, чтобы затем вывести ее в другой отчет, точнее, диаграмму? Нужно ли создавать отдельную таблицу в БД, куда писать дату-время и сам параметр (количество выпущенных щитов) для каждого его изменения, или их можно как то вытащить из существующих таблиц для трендов и отчетов? 
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 09 Декабря 2018, 10:42:37
Создать свою таблицу и записывать в неё можно. Вывести данные в отчет затем можно как описано в этой статье (https://simple-scada.com/help/report/rep-user-data.html).
Если у переменной включена архивация, то можно брать данные из стандартных таблиц. Этот вариант обычно проще. Когда Вы создаёте в отчете источник данных с типом "Периодический" (https://simple-scada.com/help/report/per-rep.html), или "По-изменению" (https://simple-scada.com/help/report/change-rep.html), то этот источник будет работать именно со стандартными архивными данными. Пример вывода трендов в отчет (в компонент Диаграмма) описан здесь (https://simple-scada.com/help/report/rep-trends.html).
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 09 Декабря 2018, 11:21:44
Создать свою таблицу и записывать в неё можно. Вывести данные в отчет затем можно как описано в этой статье (https://simple-scada.com/help/report/rep-user-data.html).
Эту статью я изучил довольно детально. Но зачем городить отдельную таблицу, если все данные есть в стандартном архиве?
Если у переменной включена архивация, то можно брать данные из стандартных таблиц. Этот вариант обычно проще.
Да, я тоже так считаю. Но переменная ВЫЧИСЛЯЕМАЯ как разница времен между выходами щитов, вот я и спрашивал, можно ли эти времена вытащить из стандартной таблицы?
Когда Вы создаёте в отчете источник данных с типом "Периодический" (https://simple-scada.com/help/report/per-rep.html), или "По-изменению" (https://simple-scada.com/help/report/change-rep.html), то этот источник будет работать именно со стандартными архивными данными. Пример вывода трендов в отчет (в компонент Диаграмма) описан здесь (https://simple-scada.com/help/report/rep-trends.html).
Это я тоже все изучил. Но мне нужно вывести в диаграмму эффективность производства по суткам, которую рассчитываю как отношение потерь времени к общей продолжительности смены, а этих данных в стандартной базе нет.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 09 Декабря 2018, 11:26:52
Мы говорим о переменной, значение которой рассчитывается в скаде. Тогда не имеет значения рассчитываемая это переменная, или какая-то ещё, если у неё включить архивацию, то её значения будут записываться в БД и затем эти значения можно будет вывести в источник данных. Вы хотите вывести в отчет переменную, которая  рассчитывается не в скаде, а при построении отчета?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 09 Декабря 2018, 11:57:27
Мы говорим о переменной, значение которой рассчитывается в скаде. Тогда не имеет значения рассчитываемая это переменная, или какая-то ещё, если у неё включить архивацию, то её значения будут записываться в БД и затем эти значения можно будет вывести в источник данных. Вы хотите вывести в отчет переменную, которая  рассчитывается не в скаде, а при построении отчета?
Экспортировать из отчета в скаду вычисляемую переменную невозможно, это Вы мне уже объяснили. Поэтому я хочу создать аналогичную переменную (vrTotalTime) в скаде и заархивировать ее в стандартной БД. Но для ее вычисления необходимы значения времен выхода щитов (изменения их количества), которые сидят в стандартном архиве. Вот я и пытаюсь выяснить - можно ли их оттуда вытащить? Или придется создать свою таблицу?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 09 Декабря 2018, 20:00:44
Можно выполнить совершенно любой SQL-запрос к любой таблице из БД (не важно сами Вы её создали, или она создана скадой), для этого используется процедура RunSQL, которая подробно описана в руководстве (https://simple-scada.com/help/script/workbd.html). Чтобы выбрать данные какой-то конкретной переменной, достаточно указать её ID в запросе. ID любой переменной можно посмотреть через Редактор, меню Переменные -> Редактировать (https://simple-scada.com/help/manual/variable-editor.html). После выполнения выборки из БД, результат можно как угодно обработать в скрипте с типом события "Выполнен SQL-запрос". Вот подробный пример выборки (https://simple-scada.com/help/script/getvardb.html) из руководства. Если результат выборки содержит множество строк, то пройти по ним можно в таком цикле:
Код: (delphi)
begin
  if DataSet.Tag = 1 then  // если это результат выполнения запроса с тегом = 1
    { выполняем цикл пока не дойдём до конца набора данных }
    while not DataSet.EOF do
    begin
      { здесь можем работать с текущей строкой и её ячейками, для
        примера обратимся к первой ячейке текущей строки }
      Text1.Text := DataSet[0].AsUTF8String;
 
      { переходим на следующую строку набора данных }
      DataSet.Next;
    end;
end.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 09 Декабря 2018, 20:16:36
Все на что Вы ссылаетесь, я изучил. ID переменной тоже умею находить. Запросы писать тоже могу. Мне непонятно, к какой из таблиц БД обращаться - action_data, messages_data, trends_*? При просмотре в MySQL Workbench я не вижу в них  ID переменных...
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 09 Декабря 2018, 20:30:26
Цитировать
При просмотре в MySQL Workbench я не вижу в них  ID
Значит Вы плохо искали. "action_data" - таблица для списка действий оператора, "messages_data" - для сообщений и эти таблицы действительно не содержат ID-переменной, он им не нужен. Переменные архивируются в таблицы "trends_data" (все данные, без прореживания), "trends_day", "trends_hour", "trends_minute" (прореженные данные). Все эти таблицы содержат столбец ID, который совпадает с ID архивируемой переменной. Вам нужно делать выборку из полной таблицы "trends_data". Пример с выборкой из "trends_data" тоже есть в руководстве (https://simple-scada.com/help/script/minmaxdb.html).
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 09 Декабря 2018, 20:38:03
В этой таблице я вижу только ID = 0 и ID = 2 и последняя дата записи 2018-10-10. А где остальные?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 09 Декабря 2018, 20:55:05
Если у Вас в таблицах есть только данные с ID = 0 и 2 и Вы уверены, что правильно сделали выборку, значит у Вас архивируются переменные с такими же ID, а у остальных архивация выключена, либо они ещё не успели сброситься в БД. Другие варианты: Вы сделали выборку из другой БД (например БД другого проекта), либо просто выбрали не все данные из таблицы и т.п. Также учитывайте, что архивные данные не сразу попадают в БД, особенно для переменных которые редко меняются. Они сбрасываются в архив не реже одного раза в 5 минут и при перезапусках проекта.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 09 Декабря 2018, 20:57:41
Все, разобрался - был установлен лимит строк. Спасибо, что навели на нужную таблицу, а уж данные я вытащу и обработаю.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 10 Декабря 2018, 21:05:29
Здравствуйте.
Опять нужна ваша помощь. Данные я вытащил, но обработать их по алгоритму, аналогичному в отчете, затрудняюсь.
Код: (delphi)
begin
  if DataSet.Tag = 1 then  // если это результат выполнения запроса с тегом = 1
    { выполняем цикл пока не дойдём до конца набора данных }
    while not DataSet.EOF do
    begin
      { здесь можем работать с текущей строкой и её ячейками, для
       примера обратимся к первой ячейке текущей строки }
       TimestampValue := DataSet[0].AsUTF8String;
       CounterValue := DataSet[1].AsUTF8String;

        ???????????????????????????????????????
       
       { переходим на следующую строку набора данных }
        DataSet.Next;
    end;
end.
Тут (где знаки вопроса) нужен какой-то оператор, вычисляющий разницу времени текущей и предыдущей записи
TimestampCurrent  - TimestampPrevious,
и если эта разница больше 5 минут, суммировать это время в некую переменную, например, IdleTime (время простоев).
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 11 Декабря 2018, 13:25:31
Нашел какую-то функцию LAG(), но как ее прописать применительно к дате-времени, не знаю. Подскажите, плиз.
P.S. Похоже, что функция LAG() в Delphi не работает... Но должна же быть какая-то аналогичная! Очень жду ответа.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 11 Декабря 2018, 15:44:39
Здравствуйте.

У Вас ведь колонка с датой и временем, поэтому её нужно переводить не в строку (DataSet[0].AsUTF8String), а в дату-время (DataSet[0].AsDateTime (https://simple-scada.com/help/script/tmdbfield.html)). Для работы с переменными даты-времени используются эти функции (https://simple-scada.com/help/script/datetime.html). Например:
Код: (delphi)
var
  aSeconds: Int64;
  aTime, aPrevTime: TDateTime; // время в текущей и пред. строке
  aIdleTime: Int64;            // полученная сумма в секундах
  aResultDateTime: TDateTime;  // полученная сумма как дата-время
begin
  if DataSet.Tag = 1 then  // если это результат выполнения запроса с тегом = 1
  begin
    aIdleTime := 0;        // обнуляем переменную в которую будем суммировать сремя
    aPrevTime := -1;       // "обнуляем" переменную времени предыдущей строки
    { выполняем цикл пока не дойдём до конца набора данных }
    while not DataSet.EOF do
    begin
      { берём время из текущей строки в переменную aTime }
      aTime := DataSet[0].AsDateTime;

      { далее код для суммирования интервалов более 5 минут }
      if aPrevTime > -1 then
      begin
        aSeconds := SecondsBetween(aTime, aPrevTime);
        if aSeconds > 5 * 60 then
          aIdleTime := aIdleTime + aSeconds;
      end;

      { в переменную времени пред. строки записываем время текущей строки }
      aPrevTime := aTime;
      { переходим на следующую строку набора данных }
      DataSet.Next;
    end;

    { расчеты окончены, в переменной aIdleTime будет сумма всех интервалов
      более 5 минут (сумма будет в секундах!). При желании можем эти секунды
      перевести в переменную даты-времени }
    aResultDateTime := SecondsToDateTime(aIdleTime);
  end;
end.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 11 Декабря 2018, 17:39:46
Спасибо огромное! Вы за меня сделали половину работы!
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 01 Марта 2019, 11:52:20
...нужно вывести время прошедшее между временем предыдущей строки и временем текущей строки? Для этого можно в бэнде данных разместить компонент Текст, дважды кликнуть его для редактирования и использовать следующее выражение:
Код: (c#)
{DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время"))}
Данный код получает разницу во времени между текущей и предыдущей строкой...
Здравствуйте. Возникла такая проблема. Как на этот код синтаксически правильно наложить условие, чтобы разница времени рассчитывалась только для строк с ненулевыми значениями счетчика (vrCounter != 0). Фильтр для DataBand не годится, так как первый нуль в начале смены надо учитывать.
Или, как вариант - можно ли выключить запись в архив нулевых показателей параметра с архивацией "по изменению" каждый час, и если да, то как?
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 04 Марта 2019, 10:35:58
Цитировать
Как на этот код синтаксически правильно наложить условие, чтобы разница времени рассчитывалась только для строк с ненулевыми значениями счетчика (vrCounter != 0). Фильтр для DataBand не годится, так как первый нуль в начале смены надо учитывать.
Уникальные условия придется реализовывать через собственные переменные. Например:
1. создать в отчете новую переменную с типом данных "timespan". С именем, например, vrDiff;
2. выделить бэнд данных и на событие "перед печатью" описать нужные условия и вычисления, например:
Код: (c#)
if (!PreviousIsNull(Данные, "Время"))
  if (vrCounter != 0) {
    vrDiff = DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время"));
  } else {
    vrDiff = new TimeSpan(0, 0, 0);
  }
3. Вывести полученную переменную vrDiff в любом месте отчета.


Цитировать
Или, как вариант - можно ли выключить запись в архив нулевых показателей параметра с архивацией "по изменению" каждый час, и если да, то как?
Архивация "по-изменению" просто записывает каждое изменение переменной в архив. Если значение переменной не будет меняться на ноль, то и в архив нули не попадут. Исключить из архивации какие-то определённые изменения нельзя.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: alan54 от 04 Марта 2019, 20:07:36
Спасибо за ответ. Я немного подправил код так:
Код: (c#)
if (!PreviousIsNull(Источник_1, "Время"))
{
if (Источник_1.vrCounter_Top != 0)
{
vrDiffTime = DateDiff(Источник_1.Время, (System.DateTime)Previous(Источник_1, "Время"));
}
else
{
vrDiffTime = new TimeSpan(0, 0, 0);
}
}
else
{ vrDiffTime = new TimeSpan(0, 0, 0);
}
А насчет архивации "по изменению" - переменная равна 0 и остается нулем, то есть не меняется, но все равно пишется в архив каждый час. Видимо от этого никак не избавиться.
Название: Re: Как вывести в отчет интервалы времени?
Отправлено: Simple-Scada от 05 Марта 2019, 09:49:26
Цитировать
А насчет архивации "по изменению" - переменная равна 0 и остается нулем, то есть не меняется, но все равно пишется в архив каждый час. Видимо от этого никак не избавиться.
Теперь ясно. Да, от этих "точек" не избавиться, они нужны для быстрого взятия значений с периодических источниках данных и при отрисовке трендов.