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

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

Автор Тема: Скрипт (прошел час)  (Прочитано 9396 раз)

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Скрипт (прошел час)
« : 28 Сентября 2018, 14:23:34 »
Добрый день подскажите как правильно реализовать задачу?
Есть переменная с датой, нужно что бы когда текущая дата приблизится к переменной на 2 месяца загоралась авария (переменная аварии переходила в 1)
вот скрипт:
Код: (delphi)
begin
  { если между текущим временем и vrCheckDate осталось меньше 2 месяцев }
  if MonthsBetween(Now, data_poverki_1_1.AsDateTime) < 2 then
    bahilova4_alarm_poverki_1.Value := 1
  else
    bahilova4_alarm_poverki_1.Value := 0;
end.

Проблема в том что он работает правильно и выполняет мои требования но когда проходит 2 месяца после указанной переменной авария пропадает, а мне нужно чтобы авария сохранялась постоянно, пока переменная не поменяется!

и второй вопрос этот скрипт можно использовать только для одной переменной , для другой нужно изменять название переменных.. и так постоянно, это очень неудобно так как их очень много! возможно ли сделать какой нибудь универсальный чтобы использовать для всех?
« Изменён: 30 Сентября 2018, 09:21:32 от Simple-Scada »

pan2000

  • Постоялец
  • ***
  • Сообщений: 225
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #1 : 28 Сентября 2018, 16:10:19 »
vyacheslav!
Судя по описанию, значение функции MonthsBetween это интервал между двумя значениями дат, т.е всегда неотрицательно.
Можно сравнивать заданную и текущую дату воспользовавшись определением типа TDateTime в Delphi и сравнивая "по дням":
Код
begin
  bahilova4_alarm_poverki_1.Visible := (NOW() + 60)  >= data_poverki_1_1.AsDateTime;
end.
Сравнение по дням более логично, чем сравнение по месяцам.
Пример во вложении.
« Изменён: 01 Октября 2018, 14:02:59 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3210
    • Просмотр профиля
    • Simple-Scada
Re: Скрипт (прошел час)
« Ответ #2 : 30 Сентября 2018, 09:52:28 »
Здравствуйте.

Цитировать
но когда проходит 2 месяца после указанной переменной авария пропадает
Как выше отметил pan2000, функция MonthsBetween всегда возвращает положительное значение, поэтому в ваше условие нужно добавить проверку
Код: (delphi)
var
  myDate: TDateTime;
begin
  myDate := data_poverki_1_1.AsDateTime;
  { если между текущим временем и vrCheckDate осталось меньше 2 месяцев }
  if (Now > myDate) and (MonthsBetween(Now, myDate) < 2) then
    bahilova4_alarm_poverki_1.Value := 1
  else
    bahilova4_alarm_poverki_1.Value := 0;
end.

Цитировать
возможно ли сделать какой нибудь универсальный чтобы использовать для всех?
У Вас переменная даты/времени "data_poverki_1_1" привязана к какому-либо объекту? Допустим она привязана к объекту Календарь в качестве основной переменной. Тогда назначаем этому же календарю переменную "bahilova4_alarm_poverki_1" в качестве дополнительной (см. скрин во вложении) в меню скриптов создаём новый универсальный скрипт со следующим кодом:
Код: (delphi)
var
  aObject: TM_Object;
  myDate: TDateTime;
begin
  { прерываем скрипт, если он вызван не объектом }
  if not (Sender is TM_Object) then Exit;
  aObject := Sender as TM_Object;

  { дату/время берём из основной переменной объекта }
  myDate := aObject.AsDateTime;
  {  меняем доп. переменную в зависимости от условия }
  if (Now > myDate) and (MonthsBetween(Now, myDate) < 2) then
    aObject.VariableEx.Value := 1
  else
    aObject.VariableEx.Value := 0;
end.

Теперь этот скрипт привязываем к событию OnDataChange календаря. Далее можно создать сколько угодно объектов, назначить им основную и дополнительную переменную и привязать данный универсальный скрипт на событие OnDataChange. Напишите если что-то непонятно.
« Изменён: 30 Сентября 2018, 09:53:36 от Simple-Scada »

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #3 : 01 Октября 2018, 09:24:33 »
Цитировать
Как выше отметил pan2000, функция MonthsBetween всегда возвращает положительное значение, поэтому в ваше условие нужно добавить проверку
var
  aObject: TM_Object;
  myDate: TDateTime;
begin
  { прерываем скрипт, если он вызван не объектом }
  if not (Sender is TM_Object) then Exit;
  aObject := Sender as TM_Object;
 
  { дату/время берём из основной переменной объекта }
  myDate := aObject.AsDateTime;
  {  меняем доп. переменную в зависимости от условия }
  if (Now > myDate) and (MonthsBetween(Now, myDate) < 2) then
    aObject.VariableEx.Value := 1
  else
    aObject.VariableEx.Value := 0;
end.
что то не пойму, этот скрипт не работает так как нужно мне. он переводит переменную bahilova4_alarm_poverki_1 в 1, только когда значение переменной data_poverki_1_1 равно текущей дате и держит ее в 1, 2 месяца и потом переводит в 0. А по моему условию перемененная bahilova4_alarm_poverki_1 должно становиться 1, когда значение переменной data_poverki_1_1 становиться меньше текущей на 2 месяца и держит ее постоянно в 1, пока я не поменяю значение переменной в дату которая больше текущей минимум на 2 месяца.
« Изменён: 01 Октября 2018, 09:37:22 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3210
    • Просмотр профиля
    • Simple-Scada
Re: Скрипт (прошел час)
« Ответ #4 : 01 Октября 2018, 09:53:19 »
Цитировать
А по моему условию перемененная bahilova4_alarm_poverki_1 должно становиться 1, когда значение переменной data_poverki_1_1 становиться меньше текущей на 2 месяца и держит ее постоянно в 1, пока я не поменяю значение переменной в дату которая больше текущей минимум на 2 месяца.
Тогда нужно брать условия из кода Вашего первого сообщения, без изменений и использовать их:
Код: (delphi)
var
  aObject: TM_Object;
  myDate: TDateTime;
begin
  { прерываем скрипт, если он вызван не объектом }
  if not (Sender is TM_Object) then Exit;
  aObject := Sender as TM_Object;
 
  { дату/время берём из основной переменной объекта }
  myDate := aObject.AsDateTime;
  { меняем доп. переменную в зависимости от условия }
  if (MonthsBetween(Now, myDate) < 2) then
    aObject.VariableEx.Value := 1
  else
    aObject.VariableEx.Value := 0;
end.
Учитывайте также, что данный универсальный скрипт ставится на событие OnDataChange и будет срабатывать только при изменении переменной даты (data_poverki_1_1). Соответственно переменная аварии (bahilova4_alarm_poverki_1) будет меняться только в эти моменты.

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #5 : 01 Октября 2018, 10:09:41 »
ну в таком случае одна проблема ушла.. у меня появился универсальный скрипт.
но вторая проблема осталась, если значение переменной data_poverki_1_1 ставлю ниже текущей даты на 2 месяца то переменная bahilova4_alarm_poverki_1 остается в 0, а по проекту это авараия и должна быть 1
« Изменён: 01 Октября 2018, 10:27:14 от Simple-Scada »

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #6 : 01 Октября 2018, 10:18:59 »
Цитировать

Учитывайте также, что данный универсальный скрипт ставится на событие OnDataChange и будет срабатывать только при изменении переменной даты (data_poverki_1_1). Соответственно переменная аварии (bahilova4_alarm_poverki_1) будет меняться только в эти моменты.
то есть я правильно понял если переменная bahilova4_alarm_poverki_1 перевелась в 1, то ей и останется пока переменная data_poverki_1_1 не поменяется. в не зависимости от тога прошло 2 и более месяца с даты (data_poverki_1_1).?

но проблема в том если вносишь дату переменной data_poverki_1_1 сразу ниже текущей на 2 месяца (это аварийное событие) то она не переводит bahilova4_alarm_poverki_1 в еденицу (не считает ее аварией)
« Изменён: 01 Октября 2018, 10:27:01 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3210
    • Просмотр профиля
    • Simple-Scada
Re: Скрипт (прошел час)
« Ответ #7 : 01 Октября 2018, 10:26:49 »
Цитировать
то есть я правильно понял если переменная bahilova4_alarm_poverki_1 перевелась в 1, то ей и останется пока переменная data_poverki_1_1 не поменяется. в не зависимости от тога прошло 2 и более месяца с даты (data_poverki_1_1).?
Да, т.е. весь скрипт и его проверки будут выполнены только при изменении переменной даты data_poverki_1_1.

Этот код:
Код: (delphi)
if (MonthsBetween(Now, myDate) < 2) then
  aObject.VariableEx.Value := 1
else
  aObject.VariableEx.Value := 0;
работает очень примитивно. Он записывает 1 в переменную аварии всегда, когда переменная даты приблизилась к текущей дате менее чем на 2 месяца (с любой стороны, с будущего, либо с прошедшего времени) и 0 во всех иных случаях.

Цитировать
но проблема в том если вносишь дату переменной data_poverki_1_1 сразу ниже текущей на 2 месяца (это аварийное событие) то она не переводит bahilova4_alarm_poverki_1 в еденицу (не считает ее аварией)
Верно, потому что в Вашем коде, приведённом выше, в переменную аварии запишется 0, если переменная даты ушла от текущей даты на 2 и более месяца. Чтобы было наоборот, можно изменить знак в условии:
Код: (delphi)
if (MonthsBetween(Now, myDate) >= 2) then
  aObject.VariableEx.Value := 1
else
  aObject.VariableEx.Value := 0;

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #8 : 01 Октября 2018, 13:52:10 »
Цитировать
Верно, потому что в Вашем коде, приведённом выше, в переменную аварии запишется 0, если переменная даты ушла от текущей даты на 2 и более месяца. Чтобы было наоборот, можно изменить знак в условии:
Код: (delphi)
if (MonthsBetween(Now, myDate) >= 2) then
  aObject.VariableEx.Value := 1
else
  aObject.VariableEx.Value := 0;
Это совсем не то..... меня полностью устраивает первый скрипт, за исключением того что через два месяца после даты , авария снимается.. можно дописать код чтобы авария работала и дальше пока переменная не поменяется на новую?
« Изменён: 01 Октября 2018, 14:01:14 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3210
    • Просмотр профиля
    • Simple-Scada
Re: Скрипт (прошел час)
« Ответ #9 : 01 Октября 2018, 14:16:36 »
Цитировать
за исключением того что через два месяца после даты , авария снимается
Просто добавьте нужное Вам условие перед снятием аварии, чтобы авария не снималась:
Код: (delphi)
if (MonthsBetween(Now, myDate) < 2) then
  aObject.VariableEx.Value := 1
else
  { снимаем аварию только если заданная дата находится "до" текущей даты }
  if (myDate < Now) then
    aObject.VariableEx.Value := 0;
В этом варианте переменная аварии не будет сниматься если значение даты больше (т.е. стоит после) текущей даты (не важно на сколько месяцев).

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #10 : 01 Октября 2018, 15:12:21 »
Цитировать
за исключением того что через два месяца после даты , авария снимается
Просто добавьте нужное Вам условие перед снятием аварии, чтобы авария не снималась:
Код: (delphi)
if (MonthsBetween(Now, myDate) < 2) then
  aObject.VariableEx.Value := 1
else
  { снимаем аварию только если заданная дата находится "до" текущей даты }
  if (myDate < Now) then
    aObject.VariableEx.Value := 0;
В этом варианте переменная аварии не будет сниматься если значение даты больше (т.е. стоит после) текущей даты (не важно на сколько месяцев).


Точно, все верно, тоько знак нужно поменять в другую сторону! (myDate > Now) Спасибо большое.   

pan2000

  • Постоялец
  • ***
  • Сообщений: 225
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #11 : 04 Октября 2018, 00:56:56 »
Конструкции из вложенных if:
Код: (delphi)
if (MonthsBetween(Now, myDate) < 2) then
  aObject.VariableEx.Value := 1
else
  { снимаем аварию только если заданная дата находится "до" текущей даты }
  if (myDate > Now) then
    aObject.VariableEx.Value := 0;

определяет значение переменной aObject.VariableEx.Value следующим образом:
Код
   относительное значение Now - myDate |   -2             0              +2     
 -----------------------------------------------------------------------------------> время (месяцев)
      (MonthsBetween(NOW, myDate) < 2) |  false  |      true       |  false
 -----------------------------------------------------------------------------------------------
                       (myDate > Now)  |  true   |         х       |  false
 -----------------------------------------------------------------------------------------------
              aObject.VariableEx.Value |     0   |         1       |  сохраняет значение
 -----------------------------------------------------------------------------------------------

Значение переменной aObject.VariableEx.Value в случае "когда проходит 2 месяца после указанной переменной" (NOW - myDate) > 2
определено предисторией, т.е. при перезапуске проекта в этом временном интервале пременная будет инициализирована 0.

Доопределить значение переменной для всего временого интервала можно добавив альтернативу else с присвоением переменной 1 или
объеденив два условия:
Код: (delphi)
if (MonthsBetween(Now, myDate) < 2) or (myDate < Now) then  // интервал между датами < 2 месяцев ИЛИ дата поверки уже прошла
  aObject.VariableEx.Value := 1
else
  aObject.VariableEx.Value := 0;

« Изменён: 04 Октября 2018, 09:53:06 от Simple-Scada »

vyacheslav

  • Новичок
  • *
  • Сообщений: 40
    • Просмотр профиля
Re: Скрипт (прошел час)
« Ответ #12 : 04 Октября 2018, 07:09:25 »
Спасибо большое за помощь, вы правы!
« Изменён: 04 Октября 2018, 09:53:15 от Simple-Scada »