PDA

Просмотр полной версии : Можно ли из таблицы тревог получить ID последней аварии?



Солнечный заяц
14.03.2018, 15:34
Есть задача отправлять СМС с текстом аварийных сообщений. Можно ли из таблицы тревог, например, вытащить ID последней тревоги?

Евгений Кислов
14.03.2018, 15:42
Есть задача отправлять СМС с текстом аварийных сообщений. Можно ли из таблицы тревог, например, вытащить ID последней тревоги?

А зачем вообще привязываться к таблице тревог в данном случае?
Вы же знаете условия возникновения тревог - по ним и формируйте/отправляйте смс.

Осинский Алексей
14.03.2018, 15:44
Я правильно понимаю, что задача стоит следующая:
1) оповестить персонал в момент возникновения аварии;
2) текст оповещения должен содержать описание возникшей аварии?

Солнечный заяц
14.03.2018, 15:48
Я правильно понимаю, что задача стоит следующая:
1) оповестить персонал в момент возникновения аварии;
2) текст оповещения должен содержать описание возникшей аварии?

1. Да.
2. Да, при возникновении аварии, должно быть отправлено смс с текстом аварии. При этом, квитирование аварии не предусматривается.

Осинский Алексей
14.03.2018, 15:55
1. Да.
2. Да, при возникновении аварии, должно быть отправлено смс с текстом аварии. При этом, квитирование аварии не предусматривается.

Спасибо за быстрый ответ.
Дайте нам время до завтра, мы подготовим подробное описание возможных вариантов решения задачи.

Солнечный заяц
14.03.2018, 15:58
А зачем вообще привязываться к таблице тревог в данном случае?
Вы же знаете условия возникновения тревог - по ним и формируйте/отправляйте смс.

Получается нужно дублировать все проверки тревог, которые я задал в группе тревог. А если придется что-то добавить, или изменить? Это может привести к ошибкам.
Получается правильней будет формировать код ошибки в программе и отправлять **** а в группе тревог просто проверять коды ошибок, и выдавать нужный текст в таблицу.

Евгений Кислов
14.03.2018, 16:00
Получается нужно дублировать все проверки тревог, которые я задал в группе тревог. А если придется что-то добавить, или изменить? Это может привести к ошибкам.
Получается правильней будет формировать код ошибки в программе и отправлять **** а в группе тревог просто проверять коды ошибок, и выдавать нужный текст в таблицу.

Именно это я и подразумевал (формирование бит в программе и использование их в менеджере тревог).

Солнечный заяц
14.03.2018, 16:01
Спасибо за быстрый ответ.
Дайте нам время до завтра, мы подготовим подробное описание возможных вариантов решения задачи.

Ого. Спасибо за интерес к моему вопросу. Приятно удивлен :)

Осинский Алексей
15.03.2018, 11:12
На текущий момент вырисовывается 2 варианта отправки СМС по активации тревоги.
Каждый со своими плюсами и минусами. Опишу оба варианта, а Вы используйте тот, который Вам больше подойдет.

Допустим есть 2 параметра, которые могут послужить причиной тревог:

Температура в комнате (допустимый диапазон от 21 до 35 °С);
Температура на улице (допустимый диапазон от 10 до 25 °С);


Вариант 1: Обработка аварий в коде.
Идея этого способа заключается в том, что мы объявим для каждой тревоги переменную типа BOOL.
Будем менять ее значение в коде, а в AlarmManager'e добавим тревоги типа "Дискретный".

Плюсы:

легкий для понимания и адаптации под Ваши задачи.


Минусы:

Необходимость писать вручную много кода;
Небольшое дублирование кода (текст сообщения в таблице тревог и текст СМС).


Я приложил архив проекта с этим вариантом реализации к сообщению.


В PLC_PRG объявляем константы минимальных, максимальных температур и сообщений, которые будут отправлены при срабатывании аварии


VAR CONSTANT
m_c_rMinRoomTemperature : REAL := 21.0;
m_c_rMaxRoomTemperature : REAL := 35.0;
m_c_rMinTemperatureOutside : REAL := 10.0;
m_c_rMaxTemperatureOutside : REAL := 25.0;
m_c_wsRoomAlarmMessage : WSTRING :=
"Недопустимая температура в комнате";
m_c_wsOutsideAlarmMessage : WSTRING :=
"Недопустимая температура на улице";
END_VAR


Объявляем переменные


VAR
// Текущая температура в комнате
rCurrentRoomTemperature : REAL := 0.0;
// Текущая температура на улице
rCurrentTemperatureOutside : REAL := 15.0;
// Текстовое описание последней возникшей аварии
wsLastAlarmMessage : WSTRING := "";
// Текущее состояние тревоги комнатной температуры
m_xIsRoomTempAlarmActive : BOOL := FALSE;
// Состояние тревоги комнатной температуры в предыдущем цикле
m_xWasRoomTempAlarmActive : BOOL := FALSE;
// Текущее состояние тревоги уличной температуры
m_xIsOutsideTempAlarmActive : BOOL := FALSE;
// Состояние тревоги уличной температуры в предыдущем цикле
m_xWasOutsideTempAlarmActive : BOOL := FALSE;
END_VAR


Обрабатывем аварии в теле PLC_PRG (для примера температура в комнате. Температура на улице обрабатывается аналогично)


// Если температура в комнате вышла за диапазон - активировать тревогу
IF rCurrentRoomTemperature < m_c_rMinRoomTemperature OR
rCurrentRoomTemperature > m_c_rMaxRoomTemperature THEN
m_xIsRoomTempAlarmActive := TRUE;

// Если тревога не была активна - отправить СМС
IF NOT m_xWasRoomTempAlarmActive THEN
wsLastAlarmMessage := m_c_wsRoomAlarmMessage;
// Тут начните отправку СМС
END_IF
ELSE
m_xIsRoomTempAlarmActive := FALSE;
END_IF

m_xWasRoomTempAlarmActive := m_xIsRoomTempAlarmActive;


В AlarmManager добавляем группу тревог и конфигурируем ее следующим образом:
36050


Вариант №2 опишу отдельным сообщением.

Осинский Алексей
15.03.2018, 11:39
Условия для варианта 2 те же, что и раньше:



Допустим есть 2 параметра, которые могут послужить причиной тревог:

Температура в комнате (допустимый диапазон от 21 до 35 °С);
Температура на улице (допустимый диапазон от 10 до 25 °С);



Вариант 2: AlarmManager сообщает нам о изменении списка активных тревог

Плюсы:

минимум вспомогательного кода;
конфигурация тревог производится полностью через интерфейс AlarmManager'а;
отсутствует дублирование кода;
для использования в проекте Вам достаточно перенести к себе в проект часть примера (редактировать не придется);


Минусы:

Для людей не знакомых с ООП разобраться как это работает будет сложно;


Я приложил архив проекта с этим вариантом реализации к сообщению.

Для интеграции примера в Ваш проект:

перенесите директорию LastAlarmMessage в свой проект;
добавьте библиотеку Alarm Manager Interfaces (Intern) в свой проект;
в PLC_PRG объявите экземпляр ФБ


VAR
m_fb_LastAlarmMessage : GetLastAlarmMessage;
END_VAR

и добавьте вызов ФБ в теле


m_fb_LastAlarmMessage();

отправляйте СМС примерно так:


// xNewAlarmActivated будет равен TRUE в течение 1 цикла ПЛК с момента активации новой тревоги.
IF m_fb_LastAlarmMessage.xNewAlarmActivated THEN
// Отправляйте СМС с текстом m_fb_LastAlarmMessage.wsMessage
;
END_IF

AlarmManager настройте по вкусу. ФБ все равно узнает текст последней возникшей тревоги.
Для наших условий настройка выглядит так:
36052



Перед тем, как перейдем к описанию:
Мы понимаем, что нашим клиентам хотелось бы сконцентрироваться на разработке проектов, а не разбираться в ООП и особенностях реализации компонентов. Мы зафиксировали у себя необходимость получать текст последней возникшей тревоги. В будущем постараемся упростить это.

Собственно описание:
Получение информации от AlarmManager'a основано на использовании поведения Издатель-Подписчик (https://ru.wikipedia.org/wiki/%D0%98%D0%B7%D0%B4%D0%B0%D1%82%D0%B5%D0%BB%D1%8C-%D0%BF%D0%BE%D0%B4%D0%BF%D0%B8%D1%81%D1%87%D0%B8%D 0%BA_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF% D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0 %B2%D0%B0%D0%BD%D0%B8%D1%8F)).
Где издатель (AlarmManager) автоматически информирует подписчика о своих событиях (например, сообщает о активации-деактивации тревоги).
Для того, чтобы это стало возможным понадобится создать функциональный блок - обработчик активных аварий


FUNCTION_BLOCK LastAlarmMessageClient IMPLEMENTS
AlarmManager.IAlarmManagerClient


У этого ФБ должны быть следующие методы:


(*
Метод вызывается AlarmManager'ом каждый раз после того, как обновился
список активных тревог.
*)
METHOD ActiveAlarmsChanged
VAR
_iActiveAlarmsCount : INT;
_paitfActiveAlarms : POINTER TO ARRAY[0..0] OF AlarmManager.IAlarm
:= 0;
END_VAR





(*
Метод вызывается AlarmManager'ом каждый раз после того, как в архив тревог
добавлена новая тревога, или изменена уже присутствующая в архиве тревога
*)
METHOD AlarmStorageModified
VAR
udiResult : UDINT;
END_VAR




(*
Возвращает критерий по которому AlarmManager определит о каких тревогах
необходимо уведомлять этого подписчика
*)
METHOD GetFilterCriteria : AlarmManager_Interfaces.IAlarmFilterCriteria


AlarmManager'у необходимо дать знать о нашем подписчике. Сделать это можно разными способами.
Я использую метод FB_Init.
Этот метод вызывается во время "Создания" экземпляра ФБ. (В общем случае - в момент загрузки программы в ПЛК или после перезагрузки ПЛК).

Метод должен иметь следующий интерфейс


(*
Конструктор. Вызывается при создании экземпляра ФБ
*)
METHOD PUBLIC FB_Init : BOOL
VAR_INPUT
bInitRetains : BOOL; // TRUE: the Retain-variables are initialized (reset warm / reset cold)
bInCopyCode : BOOL; // TRUE the instance will be copied to the copy-code afterward (online change)
END_VAR


Наполнение метода следующее:


// Подписываюсь на события AlarmManager'а
AlarmManager.g_AlarmHandler.RegisterClient (THIS^, 0, 0);


где
THIS^ - сообщает AlarmManager'у, что подписчиком необходимо добавить этот экземпляр ФБ,
0, 0 - в данном примере не используется (описывают где и сколько AlarmManager может хранить тревог при чтении архива тревог).


Кроме этого подписчик должен сообщить AlarmManager'у какие именно тревоги ему интересны.
Это реализовано в ФБ ShowAllAlarms. Добавил максимум комментариев. Дублировать сюда не буду.

Итак, с созданием подписчика закончили.
Приступим к обработке тревог. Нас интересует метод ActiveAlarmsChanged, который AlarmManager будет вызывать каждый раз при активации-деактивации тревоги.

Получить перечень активных тревог можно выполнив следующий код:


// Получаем список активных тревог
AlarmManager.g_AlarmHandler.GetActiveAlarms(
itfAlarmManagerClient := THIS^,
iCountActiveAlarms => _iActiveAlarmsCount,
parritfActiveAlarms => _paitfActiveAlarms);


В переменную _iActiveAlarmsCount будет записано количество активных тревог, а
в _paitfActiveAlarms - указатель на массив активных тревог.
В этом массиве тревоги отсортированы по возрастанию ID, поэтому нам нужно будет найти тревогу, которая активировалась последней.
В примере это выполняет метод prv_getLastAlarmMessage, я добавил в него комментарии, поэтому не буду дублировать сюда.



Если у Вас появились вопросы\замечания - пишите, мы поможем.

Солнечный заяц
12.10.2018, 13:45
Здравствуйте. Делаю уже второй проект с использованием AlarmManager'а. В первом проекте все работало отлично, а сейчас возникла проблема:
Флаг m_fb_LastAlarmMessage.xNewAlarmActivated не устанавливается при некоторых аварийных сообщениях (например, авария по CH4), хотя в списке тревог сообщения появляются нормально.
Никак не могу найти причину.

Осинский Алексей
12.10.2018, 13:57
Здравствуйте. Делаю уже второй проект с использованием AlarmManager'а. В первом проекте все работало отлично, а сейчас возникла проблема:
Флаг m_fb_LastAlarmMessage.xNewAlarmActivated не устанавливается при некоторых аварийных сообщениях (например, авария по CH4), хотя в списке тревог сообщения появляются нормально.
Никак не могу найти причину.

Добрый день!
Посмотрю проект.

Осинский Алексей
16.10.2018, 10:16
Добрый день!
ФБ GetLastAlarmMessage выставляет флаг xNewAlarmActivated в том случае, если увеличилось количество аварий в списке активных.

В Вашем проекте для того, чтобы тревога класса "Ошибка" деактивировалась необходимо, чтобы ее подтвердил пользователь.
За это отвечает настройка на скриншоте ниже:
39240
иначе тревога остается активной, даже если условие ее возникновения уже не выполняется.

Т.е. с подтверждением "REP_ACK" для повторной отправки сообщения о тревоге необходима следующая цепочка действий:

Выполнились условия возникновения тревоги // Отправили сообщение
Условия возникновения тревоги перестали выполнятся
Пользователь подтвердил тревогу
Выполнились условия возникновения тревоги // Отправили сообщение


Если нужно так:

Выполнились условия возникновения тревоги // Отправили сообщение
Условия возникновения тревоги перестали выполнятся
Выполнились условия возникновения тревоги // Отправили сообщение

то условие деактивации тревоги необходимо установить равным "REP".
Более подробно о настройке AlarmManager'a описано в документе "СПК. Визуализация" (https://ftp.owen.ru//CoDeSys3/11_Documentation/01_SPK/SPK_Visu_v.1.2.pdf)

Солнечный заяц
18.10.2018, 16:19
Все отлично работает, спасибо!