UniSet  2.7.0
Хранение информации о состоянии с уведомлениями об изменении (IONotifyController)

Класс IONotifyController расширяет набор задач класса IOController. Для ознакомления с базовыми функциями см. page_IOController

Задачи решаемые IONotifyController-ом (IONC):

Механизм заказа датчиков

Главной задачей класса IONotifyController является уведомление объектов (заказчиков) об изменении состояния датчика (входа или выхода).

Механизм функционирует по следующей логике: "заказчики" уведомляют IONC об изменении какого именно датчика они хотят получать уведомление, после чего, если данный датчик меняет своё состояние, заказчику посылается сообщение uniset::SensorMessage содержащее информацию о текущем(новом) состоянии датчика, времени изменения и т.п. В случае необходимости можно отказатся от уведомления. Для заказа датчиков предусмотрен ряд функций. На данный момент рекомендуется пользоватся функцией IONotifyController::askSensor.

ConsumerMaxAttempts - максимальное число неудачных попыток послать сообщение "заказчику". Настраивается в конфигурационном файле. По умолчанию = 5.

Заказчики

В качестве "заказчиков" могут выступать любые UniSet-объекты (UniSetObject), обладающие "обратным адресом" (идентификатором), по которому присылается уведомление об изменении состояния. Свой обратный адрес, объекты указывают непосредственно при заказе (см. IONotifyController::askSensor).

Помимо "динамического" заказа во время работы процессов, существует возможность задавать список заказчиков на этапе конфигурирования системы ("статический" способ). Для этого в конфигурационном файле, в секции <sensors> у каждого датчика предусмотрена специальная секция <consumers>.

<sensors>
...
<item name="Sensors1" textname="sensor N1" iotype="AI" ...>
<consumers>
<consumer name="TestProc1" type="objects"/>
<consumer name="TestProc2" type="managers" node="RemoteNode"/>
...
</consumers>
</item>
...
</sensors>

"Статический" способ заказа гарантирует, что при перезапуске IONC список заказчиков будет восстановлен по конфигурационному файлу.

Пороговые датчики

Механизм зависимостей между датчиками

Механизм зависимостей позволяет задать зависимость одного датчика, от другого. Например пока "разрешающий" датчик не равен "1", у зависимого держится значение "0". Зависимость настраивается в конфигурационном файле, непосредственно у "зависимого датчика".
Доступные настройки:

...
<sensors ..>
...
<item id="11" iotype="AI" name="AI11_AS" textname="AI 11" depend="Input4_S" depend_off_value="-50"/>
...
</sensors>

В данном примере можно увидеть, что датчик AI11_AS зависит от датчика Input4_S и пока Input4_S=0, в AI11_AS будет записано значение -50. Как только Input4_S=1 в AI11_AS - появиться его истинное значение.

Заметки
Следует иметь ввиду, что для ЗАВИСИМОГО датчика функция setValue(..) действует как обычно и даже если он "заблокирован", значение в него можно сохранять. Оно "появиться" как только сниметься блокировка.

Оптимизация работы со списком "заказчиков"

Для оптимизации поиска списка заказчиков для конкретного датчика используется поле userdata (void*) у USensorInfo! Это опасный и "некрасивый" хак, но он позволяет избавиться от одного лишнего поиска по unordered_map<SensorID,ConsumerList>. Суть в том что к датчику через usedata мы привязываем указатель на список заказчиков. Сделано через userdata, т.к. сам map "хранится" в IOController и IONotifyController не может поменять тип (в текущей реализации по крайней мере). В userdata задействованы два места (см. UserDataID) для списка заказчиков и для списка порогов. При этом, чтобы гарантировать корректность работы, cписки заказчиков по тому или иному датчику, создаются (см. функцию ask()), но никогда не удаляются, даже если остаются пустыми. Это сделано, чтобы сохранённые указатели в userdata, оставались всегда валидными (т.к. используются из разных потоков).