SCN-SAFETY-015: Аварийное освещение (включение света при срабатывании датчиков безопасности)
Введение в сценарий "Аварийное освещение"
Аварийное освещение в контексте умного дома — это не просто резервный свет на случай отключения электричества. Это активный компонент комплексной системы безопасности, задача которого — немедленно и однозначно реагировать на тревожные события, обеспечивая визуальную информацию и помогая сориентироваться в потенциально опасной ситуации. В отличие от строго регламентированного эвакуационного освещения, которое регулируется государственными нормативами (ГОСТ, СНиП) и предназначено для безопасного покидания здания, наш сценарий преследует иные цели:Сценарий активируется по нескольким типам триггеров, каждый из которых сигнализирует о событии с высоким уровнем приоритета:
- Датчики пожарной безопасности: Срабатывание датчиков дыма, угарного газа (CO) или повышения температуры.
- Датчики охранной системы: Нарушение периметра (датчики открытия окон/дверей), фиксация движения внутри дома в режиме «Охрана».
- Тревожные кнопки: Ручная активация сценария через стационарную или носимую тревожную кнопку (Panic Button).
Этот сценарий является частью единой экосистемы безопасности. Его активация должна инициировать цепочку связанных действий, таких как перекрытие потенциально опасных коммуникаций (газ, приточная вентиляция), отправка push-уведомлений или SMS владельцу, включение сирены и, как мы увидим далее, получение абсолютного приоритета над всеми прочими сценариями управления светом.
---
Архитектура решения: от датчика к светильнику
Для построения надежного сценария аварийного освещения мы будем использовать слабосвязанную архитектуру, где центральным звеном выступает MQTT-брокер, развернутый на контроллере HI. Этот подход позволяет нам интегрировать устройства, работающие по разным протоколам, в единую логическую систему, где каждое устройство обменивается стандартизированными сообщениями.
> 🔗 Связанный материал: Для понимания базовых принципов работы с MQTT и настройки брокера на контроллере HI, обратитесь к материалам модуля COURSE-03-M02.
Аппаратные компоненты системы
| Компонент | Примеры устройств | Протокол/Шина подключения к контроллеру HI | Роль в сценарии |
| -------------------- | -------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- |
| Датчики дыма/газа | Болид ДИП-34А, Астра-421, System Sensor 2951J | Modbus RTU (через модуль расширения), "Сухой контакт" | Триггер тревоги типа "Пожар" или "Газ". |
| Охранные датчики | Gira KNX Motion Detector, герконы на дверях/окнах | KNX, "Сухой контакт" (на входы UI контроллера) | Триггер тревоги типа "Вторжение". |
| Тревожные кнопки | Настенные кнопки, носимые брелоки (Zigbee/BLE) | "Сухой контакт", Zigbee (через шлюз) | Триггер тревоги типа "Паника" для ручной активации. |
| Исполнители | Релейные выходы контроллера HI, KNX-актуаторы, DALI-драйверы | Реле, KNX, DALI (через шлюз) | Физическое включение осветительных приборов на 100% яркости. |
Стандартизация MQTT-событий
Ключ к масштабируемой и понятной системе — это единый формат сообщений и структура топиков. Все датчики безопасности, независимо от их физического протокола, должны публиковать свои события в MQTT в стандартизированном виде.
Стандарт топика: `hi/events/security/- `
`: Логическая зона объекта (например, `kitchen`, `living_room`, `hall_floor1`). - `
`: Тип датчика (например, `smoke`, `gas_co`, `motion`, `door`, `panic`).
При срабатывании датчик должен отправить JSON-сообщение со значением `true`. При возвращении в норму — `false`.
Пример сообщения от датчика дыма на кухне:
- Топик: `hi/events/security/kitchen/smoke`
- Payload (тревога):
{
"value": true,
"source": "modbus-smoke-sensor-01",
"ts": 1678886400000
}
- Payload (норма):
{
"value": false,
"source": "modbus-smoke-sensor-01",
"ts": 1678886900000
}
Для реализации этой логики необходимо предварительно настроить на контроллере HI соответствующие потоки-драйверы. Например, поток, который опрашивает Modbus-датчик дыма, при получении от него тревожного значения должен сформировать и опубликовать указанное выше MQTT-сообщение. Аналогично для датчиков, подключенных к "сухим контактам" или работающим по KNX. Этот уровень абстракции позволяет основному сценарию аварийного освещения не зависеть от физического способа подключения датчиков.
---
Реализация в Node-RED: обработка тревожных сигналов
Первый этап создания потока — это подписка на все релевантные события безопасности и их унификация. Мы создадим централизованный обработчик, который будет слушать все тревожные топики и приводить их к единому формату.
> 💡 Подсказка: Используйте wildcard-подписку (например, `hi/events/security/+/+`) в ноде `mqtt in` для одновременного прослушивания всех датчиков безопасности. Это упрощает масштабирование системы без изменения логики потока.
Создадим следующий поток:
[mqtt in] --> [json] --> [rbe] --> [function: Prepare Standard Alarm] --> [link out: To Light Control]
|
+-- (invalid json) --> [catch] --> [log]
Шаг 1: Подписка и фильтрация
Шаг 2: Формирование стандартизированного сообщения о тревоге
Ключевая задача этого этапа — извлечь из MQTT-топика тип тревоги и зону, а также определить, является ли событие активацией тревоги или ее отменой. Затем мы формируем унифицированный объект `msg`, который будет использоваться в последующей логике. Подключите к `rbe` узел `function` с именем "Prepare Standard Alarm".
// Код для узла "function: Prepare Standard Alarm"
// Получаем состояние из исходного сообщения: true - тревога, false - норма
const isAlarmActive = msg.payload.value;
// Разбираем топик, чтобы получить зону и тип датчика
// Пример msg.topic: "hi/events/security/living_room/smoke"
const parts = msg.topic.split('/');
if (parts.length < 5) {
node.error("Некорректный формат топика: " + msg.topic, msg);
return null;
}
const zone = parts[3];
const sensorType = parts[4];
// Определяем тип тревоги
let alarmType = 'unknown';
if (sensorType === 'smoke' || sensorType === 'gas_co' || sensorType === 'temp_high') {
alarmType = 'fire';
} else if (sensorType === 'motion' || sensorType === 'door' || sensorType === 'window') {
alarmType = 'intrusion';
} else if (sensorType === 'panic') {
alarmType = 'panic';
}
// Формируем новый, стандартизированный payload для дальнейшей обработки
msg.payload = {
alarm: isAlarmActive, // true (тревога) или false (сброс)
type: alarmType,
zone: zone,
source_topic: msg.topic,
original_payload: msg.payload // Сохраняем исходное сообщение для отладки
};
// Устанавливаем статус узла для визуальной диагностики
if (isAlarmActive) {
node.status({
fill: "red",
shape: "dot",
text: `ALARM: ${alarmType.toUpperCase()} in ${zone}`
});
} else {
node.status({
fill: "green",
shape: "dot",
text: `CLEAR: ${alarmType.toUpperCase()} in ${zone}`
});
}
return msg;
Этот узел-функция является сердцем первичной обработки. Он преобразует разрозненные сигналы от датчиков в единый, понятный для системы формат, сообщая не только о типе и месте тревоги, но и о её состоянии (активна или снята). Полученное сообщение мы отправляем дальше по цепочке с помощью узла `link out` в поток управления освещением.
---
Управление светом: отправка команд в шину
Получив стандартизированное сообщение о тревоге, наша следующая задача — сформировать команду на включение (или выключение) необходимых групп света. Мы не будем отправлять команды напрямую в шину, а воспользуемся ранее разработанным "Шлюзом приоритетов", отправив ему команду через MQTT.
> ⚠️ Внимание: Всегда используйте отдельные, зарезервированные групповые адреса (ГА) для аварийных сценариев в KNX. Не пересекайте их с ГА для повседневного управления (например, от выключателей), чтобы избежать логических конфликтов и цикличных команд.
Рассмотрим, как подготовить сообщение для шлюза, который затем уже сам отправит команду в нужную шину (например, KNX).
Динамический выбор групп света
Стратегия аварийного освещения может быть разной. Самый простой вариант — включить абсолютно весь свет в здании. Более сложный и целесообразный — включить свет в зоне сработки датчика и всех смежных зонах (пути эвакуации). Реализуем второй вариант с помощью узла `function`.
Этот узел будет принимать на вход наше стандартизированное сообщение о тревоге и, на основе `msg.payload.zone` и `msg.payload.alarm`, формировать сообщения для шлюза.
// Код для узла "function: Map Zone to Lights"
const zone = msg.payload.zone;
const alarmType = msg.payload.type;
const state = msg.payload.alarm; // true для включения, false для выключения
// Создаем карту соответствия зон и логических идентификаторов устройств/групп,
// которыми управляет "Шлюз приоритетов".
// В реальном проекте эту карту лучше вынести в глобальный контекст.
const lightZoneMap = {
"kitchen": ["light_kitchen_main", "light_kitchen_spot"],
"living_room": ["light_living_main", "light_living_spots"],
"hall_floor1": ["light_hall_1"],
"hall_floor2": ["light_hall_2"],
"all_halls": ["light_hall_1", "light_hall_2"],
"all_lights": ["group_all_lights"] // Логическая группа для всего света
};
let targetDevices = [];
// Логика выбора групп света
// При пожаре управляем ВСЕМ светом для максимальной видимости
if (alarmType === 'fire' || alarmType === 'gas' || alarmType === 'panic') {
targetDevices.push(lightZoneMap.all_lights[0]);
}
// При вторжении включаем свет в зоне вторжения и на путях эвакуации (коридоры)
else if (alarmType === 'intrusion') {
if (lightZoneMap[zone]) {
targetDevices = targetDevices.concat(lightZoneMap[zone]);
}
targetDevices = targetDevices.concat(lightZoneMap.all_halls);
}
// Если не найдено специфических правил, на всякий случай управляем всем светом
if (targetDevices.length === 0) {
targetDevices.push(lightZoneMap.all_lights[0]);
}
// Устанавливаем высокий приоритет для аварийного сценария
const priority = 2;
// Формируем массив сообщений для отправки в "Шлюз приоритетов"
const outputMessages = targetDevices.map(deviceID => {
return {
// Топик, который слушает шлюз управления
topic: `hi/control/${deviceID}/set`,
payload: {
value: state, // true (включить) или false (выключить)
priority: priority,
source: `emergency-scenario-${alarmType}` // Источник для отладки
}
};
});
// Отправляем массив сообщений на выход.
// Node-RED отправит каждое из них как отдельное сообщение.
return [outputMessages];
После этого `function`-узла разместите узел `mqtt out`, настроенный на ваш MQTT-брокер (поле Topic можно оставить пустым). Функция возвращает массив сообщений, и Node-RED автоматически отправит каждое из них как отдельное сообщение. Каждое сообщение будет опубликовано в свой MQTT-топик (например, `hi/control/group_all_lights/set`). Эти сообщения будут получены и обработаны централизованным "Шлюзом приоритетов", который, в свою очередь, уже отправит физическую команду в шину (KNX, DALI и т.д.).
---
Приоритеты и интеграция со Шлюзом Управления
Активация аварийного освещения — событие наивысшего приоритета. Никакие другие сценарии или действия пользователя (например, нажатие на выключатель "Выключить все") не должны ему помешать.
> ℹ️ Информация: Механизм приоритетов, который мы здесь используем, является практическим применением архитектурного паттерна «Шлюз приоритетов», изученного в уроке SCN-ARCH-010 «Паттерны управления состоянием и приоритетами». Рекомендуется ознакомиться с ним для полного понимания.
Вместо создания изолированного флага-блокировщика, мы интегрируем наш сценарий в единую систему управления на базе "Шлюза приоритетов". Такой подход делает систему более предсказуемой и модульной: аварийный сценарий становится одним из "клиентов" шлюза, но с наивысшим приоритетом.
Принцип работы через Шлюз приоритетов
* Цель (`topic`): Логический идентификатор устройства или группы (например, `hi/control/group_all_lights/set`).
* Действие (`payload.value`): `true` (включить) или `false` (выключить).
* Приоритет (`payload.priority`): Числовое значение. Для аварийных сценариев мы используем высокий приоритет, например `2`. Для обычных сценариев (выключатели, датчики движения) используется низкий приоритет, например `0` или `1`.
* Получив нашу команду с `priority: 2`, шлюз немедленно её выполняет (включает свет) и "захватывает" управление группой света на уровне `2`.
* Пока захват активен, любые команды для этой же группы света, приходящие с более низким приоритетом (например, от настенного выключателя с `priority: 0`), будут шлюзом проигнорированы. Свет останется включенным.
Этот подход избавляет от необходимости модифицировать каждый низкоприоритетный сценарий, добавляя в него проверку флага. Вся логика приоритетов инкапсулирована в одном месте — в Шлюзе управления.
---
Итоги и рекомендации по тестированию
В рамках этого урока мы разработали комплексный и отказоустойчивый сценарий "Аварийное освещение", интегрированный в общую архитектуру управления через "Шлюз приоритетов". Мы прошли путь от получения сигнала с разнородных датчиков до отправки стандартизированной приоритетной команды, обеспечив наивысший приоритет исполнения.
Ключевые этапы созданного потока:
Чек-лист для обязательного тестирования
Перед сдачей объекта в эксплуатацию необходимо провести полное тестирование сценария.
- [ ] Имитация тревоги "Пожар": Активируйте (тестовой кнопкой или специальным аэрозолем) датчик дыма. Убедитесь, что включился весь свет в здании.
- [ ] Имитация тревоги "Вторжение": Включите режим "Охрана" и активируйте датчик движения или открытия двери. Проверьте, что свет включился в целевой и смежных зонах (согласно вашей логике).
- [ ] Проверка ручной тревоги: Нажмите тревожную кнопку. Убедитесь, что реакция аналогична тревоге "Пожар".
- [ ] Проверка блокировки: Во время активной тревоги попробуйте выключить свет с настенного выключателя или через сценарий "Выключить все" (которые отправляют команды с низким приоритетом). Свет должен остаться включенным.
- [ ] Проверка сброса режима: Имитируйте возврат датчика в норму. Убедитесь, что аварийное освещение выключилось (с помощью команды с высоким приоритетом), и управление светом вернулось в штатный режим (низкоприоритетные команды снова работают).
- [ ] Проверка граничных условий: Протестируйте реакцию системы на быстрые последовательные срабатывания/отключения датчика (проверка работы узла `rbe`).
Обязательно задокументируйте все используемые MQTT-топики, логические идентификаторы устройств и принятую схему приоритетов. Эта документация критически важна для дальнейшей поддержки и модернизации системы.
Что дальше
Созданный сценарий можно и нужно развивать:
- Звуковое оповещение: Параллельно с включением света можно активировать сирену или транслировать голосовые сообщения через аудиосистему.
- Push-уведомления: Интегрируйте отправку мгновенных уведомлений на смартфоны владельцев с указанием типа и зоны тревоги.
- Интеграция с видеонаблюдением: При срабатывании охранного датчика можно дать команду системе видеонаблюдения повернуть камеру в нужную точку и начать запись.
- Визуализация: Выведите состояние "захвата" устройства из "Шлюза приоритетов" на главную панель управления, чтобы пользователь всегда видел, что свет заблокирован аварийным сценарием.