Адаптер ioBroker для WACHALARM IP-Web (WAIP-Web)
Подключается через Socket.IO к монитору диспетчеризации WAIP-Web и отображает инциденты («Einsatz»), отзывы операторов («Rückmeldung»), маршруты и объявления TTS в состояниях ioBroker - без необходимости держать открытой вкладку браузера.
Оглавление
- Практические примеры использования
- [Описание ключевых слов](#описание ключевых слов)
- [Панель управления](#панель управления)
- info · статус · einsatzAktuell ·
einsatzAktuell.json · einsatzAktuell.tts · [dashboard-states · [debug]](#debug)
Об этом адаптере
Этот адаптер является независимым проектом, созданным сообществом и не имеет никакого отношения к проекту WAIP-Web, к Robert-112 или к оператору какого-либо конкретного экземпляра (например, Интегрированного регионального диспетчерского центра Лаузиц / Integrierte Regionalleitstelle Lausitz). Он был создан на основе анализа поведения интерфейса (client_waip.js), который экземпляр WAIP-Web публично предоставляет любому браузеру, чтобы воспроизвести те же события и поля данных Socket.IO, которые получает обычный браузерный клиент.
Адаптер подключается без авторизации и, следовательно, получает только общедоступные данные уровня доступа WAIP-Web (ключевое слово, местоположение, приблизительное местоположение, оповещаемые ресурсы, обратная связь) - те же данные, которые увидит любой анонимный посетитель браузера без авторизации. Никакие ограничения доступа не обходятся.
Примечание: Постоянно работающий автоматизированный клиент, подобный этому адаптеру, отличается от периодически открываемой вкладки браузера. Прежде чем запускать его в рабочей среде, кратко уточните у оператора/вашего диспетчерского центра, приветствуется ли постоянное автоматизированное подключение.
О WAIP-Web
Wachalarm IP-Web - это веб-приложение с открытым исходным кодом от Robert-112, которое отображает информацию о вызовах/оповещениях для пожарных служб и служб скорой медицинской помощи независимо от устройства в браузере (Windows, Linux, Mac, смартфон - установка не требуется). Среди прочего оно предлагает:
- Монитор сигналов тревоги - тип инцидента, ключевое слово, специальный сигнал, местоположение,
карта, оповещенные ресурсы, обратная связь от служб реагирования через приложение, включая голосовые объявления.
- Панель мониторинга - обзор всех текущих инцидентов.
- Функция обратной связи - обратная связь от пользователей через приложение, сгруппированная по ролям.
(EK/GF/ZF/VF) и дополнительная квалификация (AGT/FZF/MA/MED)
- Администрирование - управление пользователями, данные станций, обзор мониторов.
Сам WAIP-Web распространяется под лицензией Лицензия Creative Commons BY-SA 4.0. Этот адаптер не содержит кода из проекта WAIP-Web; он реализует независимый клиент для своего интерфейса Socket.IO.
Практические примеры использования
В этом разделе рассказывается о том, что вы можете реально создать с помощью состояний, предоставляемых этим адаптером - типичное использование в пожарной части/службе скорой помощи:
- Настенный дисплей сигнализации. Привяжите
einsatzAktuell.json.currentк VIS
На настенном планшете или телевизоре в комнате отдыха/автомобильном холле автоматически отображаются табличный виджет: тип инцидента, ключевое слово, адрес и оповещенные ресурсы, без необходимости держать открытой вкладку браузера на этом экране (в этом и заключается основная причина существования этого адаптера).
- Ключевые слова, написанные простым языком, на экранах и в уведомлениях.
einsatzAktuell.beschreibung преобразует загадочный код отправки (B:Wald groß/WSP, R1N0) в читаемое описание ("Wald-/Getreidefeldbrand (groß)", "Rettungswagen: 1, Notfalleinsatzfahrzeug: 0") - прикрепите его рядом с einsatzAktuell.stichwort на настенном дисплее или включите в push-уведомление/сообщение TTS, чтобы участникам не приходилось запоминать каждое ключевое слово.
- Запускайте автоматические сценарии мгновенно по сигналу тревоги. Смотрите
einsatzAktuell.alarmAktiv (или info.connection вместе с ним) в правиле script/blockly для включения света в зале для транспортных средств, открытия ворот/двери, отправки push-уведомления (например, через адаптер Telegram/Pushover) с einsatzAktuell.stichwort/einsatzAktuell.beschreibung + einsatzAktuell.ort или мигания сценария умного освещения - все это через несколько секунд после фактического оповещения пейджера, без необходимости опроса, поскольку изменения состояния ioBroker срабатывают мгновенно.
- Произнесите сигнал тревоги вслух.
einsatzAktuell.tts.last- это
Готовый к воспроизведению абсолютный URL-адрес mp3; укажите на него автоматизацию в стиле sonos/snapcast/text2speech (или просто воспроизведите URL напрямую), чтобы о происшествии объявили через громкоговорители здания в момент срабатывания io.playtts - это полезно, когда не все члены группы смотрят на экран.
- Живая численность персонала/доска отзывов.
einsatzAktuell.rueckmeldungen.*
Счетчики (rollen.ek/.gf/.zf/.vf для каждой роли, funktionen.agt/.fzf/ .ma/.med для каждой квалификации) обновляются в режиме реального времени по мере подтверждения участниками через приложение - привяжите их к виджетам с индикаторами или цифрами для быстрого обзора «кто прибудет» во время реагирования.
- Анализ инцидента / статистика.
einsatzAktuell.json.historyхранит
Последние N завершенных инцидентов (настраиваемое значение, по умолчанию 10) в виде плоской таблицы - привяжите ее ко второму представлению VIS или экспортируйте периодически (например,
с помощью скрипта, считывающего состояние в io.standby), чтобы вести более длительный журнал или передавать количество инцидентов в адаптер панели мониторинга/статистики.
- Обзор маршрута/транспортного средства на карте.
einsatzAktuell.json.routenсодержит
lat/lon и color для каждой станции реагирования - привяжите их к виджету карты VIS для быстрого визуального отображения того, кто находится в пути, независимо от самой карты WAIP-Web.
- Взаимодействие с другими системами автоматизации ioBroker. Потому что каждое поле - это
Используя обычное состояние ioBroker, он взаимодействует со всем остальным, что уже запущено в экземпляре - пересылает einsatzAktuell.* в механизм сценариев умного дома, историю Grafana/InfluxDB для анализа времени отклика или поток в стиле Node-RED через адаптер ioBroker MQTT, не записывая ни одной строки в WAIP-Web API.
Функции
- Подключается к пространству имен
/waipчерезsocket.io-client, регистрируется через
emit('WAIP', monitorId) один раз (использует REGISTRATION_TIMEOUT_MS в качестве резервного варианта, а не повторные отправки, поскольку избыточная отправка лишь заставляет сервер отвечать снова, не повышая надежность доставки)
- Ручная обработка переподключения (автоматическое переподключение, встроенное в библиотеку, выполняется автоматически).
отключено) с настраиваемой задержкой
- Истекло время ожидания регистрации с записью в журнал аудита (
debug.monitorAudit) - Нормализация геоданных (поля wgs84,
positionили GeoJSONgeometry)
→ центроид)
- История последних N завершенных инцидентов (настраиваемое значение, по умолчанию 10);
einsatzAktuell.json.history)
- Отдельные обработчики для сигнала тревоги (
io.new_waip) и обратной связи (io.new_rmld),
маршруты (io.routes), TTS (io.playtts) и резервный режим (io.standby)
- Автоматическое управление сессионными cookie-файлами (см. ниже), что обеспечивает доставку оповещений.
продолжает работать бесконечно без открытой сессии браузера.
- Обнаружение перезапуска сервера с помощью
io.version, с автоматической настройкой сессии.
обновить + переподключиться
- Данные об инцидентах, обратной связи, маршрутах и оповещенных ресурсах доступны в следующем виде:
Отдельные плоские JSON-массивы в разделе einsatzAktuell.json.* - без вложенности, поэтому виджеты таблиц VIS могут напрямую к ним привязываться.
- Сводные счетчики обратной связи по каждой роли/возможности, отражающие текущую ситуацию.
значки в веб-интерфейсе
- Сброс состояния при каждом перезапуске: все состояния активно сбрасываются до исходных значений.
Пустое значение (false/0/null/[]) при запуске адаптера, за исключением einsatzAktuell.json.history и debug.monitorAudit (оба сохраняются после перезапуска). Обратите внимание, что если адаптер перезапускается во время активного инцидента, его активные поля (einsatzAktuell.*) также очищаются и заполняются заново только после того, как сервер отправит следующее событие для этого инцидента.
- Защита от устаревших данных: когда новый инцидент возникает до предыдущего.
Поступили события маршрутизации/обратной связи для нового инцидента, einsatzAktuell.json.routen/.rueckmeldungen, и счетчики обратной связи обнуляются немедленно, а не в ожидании этих событий. И если io.standby когда-либо пропускается для инцидента (например, из-за разрыва соединения в неподходящий момент), сторожевой таймер автоматически завершает инцидент, как только ablaufzeit истекает с задержкой более чем в 60 секунд, вместо того, чтобы оставлять устаревшие «активные» данные на неопределенный срок.
- Отображается только один последний активный инцидент; несколько инцидентов
В настоящее время одновременно активные инциденты можно просмотреть только на панели управления самого экземпляра WAIP-Web.
- Необязательное описание на простом языке для
einsatzAktuell.stichwort
(einsatzAktuell.beschreibung), определяется локально из поддерживаемой пользователем таблицы ключевых слов плюс необязательный декодер для схемы ключевых слов службы спасения R<RTW>N<NEF>, используемой несколькими диспетчерскими центрами - см. Спасательная служба
- Происшествия, связанные со спасательными службами, можно полностью игнорировать (ни штатов, ни...).
история, без TTS) - полезно в тех случаях, когда WAIP изначально подает им ненадежные сигналы, см. Спасательная служба
- Дополнительное изображение карты происшествия: PNG-файл, центрированный на месте происшествия.
Координаты, составленные локально из тайлов OpenStreetMap, с областью инцидента, отправляемой WAIP-Web, отображаемой в виде контура с настраиваемым цветом/толщиной (можно заменить на обычную точку-маркер), автоматически уменьшаются по мере необходимости, чтобы вся область оставалась видимой, путь к файлу отображается как состояние - см. Изображение карты инцидента
- Дополнительная панель мониторинга: отображает последние N инцидентов, соответствующих этому событию.
Монитор экземпляра, обозначенный как dashboard.einsatz1 … einsatzN, периодически опрашивается через кратковременные соединения (без постоянного подключения к панели управления) - см. Панель управления
Конфигурация
В административном интерфейсе экземпляра адаптера настройки сгруппированы по четырем вкладкам: Подключение, Служба восстановления, Описание ключевых слов и Изображение карты инцидента - все четыре вкладки описаны ниже.
Связь
| Поле | Описание | По умолчанию |
|---|---|---|
| URL сервера WAIP | Базовый URL экземпляра WAIP-Web | https://wachalarm.leitstelle-lausitz.de |
| Время ожидания регистрации (с) | Время до регистрации отсутствия подтверждения регистрации | 10 |
| Задержка переподключения (с) | Время ожидания перед ручным переподключением после отключения/ошибки | 5 |
| Количество инцидентов в истории | Сколько завершенных инцидентов следует сохранить в einsatzAktuell.json.history (сначала самые последние). Существующие записи, превышающие установленный лимит, удаляются при следующем перезапуске адаптера | 10 |
| Количество инцидентов в истории | Сколько завершенных инцидентов хранить в einsatzAktuell.json.history (сначала самые последние). Существующие записи, превышающие установленный лимит, удаляются при следующем перезапуске адаптера | 10 |
Интервал поддержания активности сессии не подлежит настройке - он определяется полностью автоматически при каждом обновлении на основе срока действия cookie-файла, сообщаемого сервером (мин. 55 с, макс. 5 мин., соответствует /js/session_keepalive.js на самом сайте).
Зачем нужен сессионный cookie
Сервер WAIP-Web связывает доставку оповещений с сеансовым cookie-файлом Express, который браузер автоматически обновляет каждые несколько минут с помощью встроенного скрипта. Обычный клиент Socket.IO никогда не получает этот cookie-файл автоматически - поэтому адаптер получает его самостоятельно через GET /session/keepalive и прикрепляет к соединению Socket.IO.
Согласно исходному коду WAIP-Web, срок действия cookie-файла настраивается для каждого экземпляра с помощью переменной среды (по умолчанию на сервере: 60 секунд; в данном экземпляре, по-видимому, используется 10 минут) - поэтому фиксированный интервал обновления потенциально был бы некорректным для других экземпляров WAIP-Web. Вместо этого адаптер определяет фактический интервал адаптивно на основе времени истечения срока действия, которое сервер сообщает при каждом вызове (80% от наблюдаемого срока действия, не менее 55 секунд, не более фиксированного 5-минутного предела) - точно такое же ограничение, которое используется в /js/session_keepalive.js на самом сайте.
Спасательная служба
Обрабатывать инциденты службы спасения (флажок администратора, включено по умолчанию): инциденты, einsatzart идентифицирующие их как вызов службы спасения (содержат «Rettung» или «Krankentransport», регистр нечувствительный - см. примеры einsatzart в einsatzAktuell), по умолчанию обрабатываются в обычном режиме, как и в любой предыдущей версии адаптера. Снятие флажка приводит к тому, что адаптер полностью игнорирует такие инциденты: состояния einsatzAktuell.* не обновляются, запись в историю не записывается, объявление TTS не запускается.
- как будто инцидента и не было. Это существует потому, что
Сообщается, что сообщения о происшествиях, требующих помощи спасательных служб, передаются через систему WAIP только в некоторых регионах/диспетчерских центрах - там, где это не требуется или нежелательно, этот флажок отключает оповещения. Все, что находится ниже этого флажка на вкладке (флажок декодирования и поля с его метками), отображается только пока он отмечен - если он не отмечен, сообщения о происшествиях, требующих помощи спасательных служб, полностью игнорируются, поэтому декодирование их ключевых слов не имеет значения.
einsatzAktuell.stichwort передается с сервера без изменений, как чистый код (например, B2, H:VU mit P) - сам WAIP-Web не объясняет, что это значит, и нет общенационального стандарта: каждый диспетчерский центр использует свой собственный каталог ключевых слов. einsatzAktuell.beschreibung заполняет этот пробел полностью локально, данные никуда не передаются. Эта вкладка является первой из двух проверяемых источников по порядку (см. Описание ключевых слов для второго):
Декодирование службы спасения (флажок администратора, включено по умолчанию): если ключевое слово соответствует шаблону R<RTW-count>N<NEF-count>[p][f][-NT] (например, R1N0 → "Rettungswagen: 1, Notfalleinsatzfahrzeug: 0"), описание генерируется автоматически. Распознаются два варианта написания части p/f/NT: без пробела и с дефисом перед NT (например, R1N1p, R1N0-NT, см. Документированное объяснение Лейтстелле Лаузитц), а также с пробелом и без дефиса (например, R1N1 p, R1N0 nt, как используется IRLS Brandenburg) - эта схема (в любом варианте написания) используется несколькими немецкими диспетчерскими центрами, а не только этими двумя - не имеет эффекта, если ваш диспетчерский центр не использует один из этих шаблонов, поскольку ключевое слово просто не будет соответствовать. Текст для каждой части можно настроить (после включения флажка появляются 5 дополнительных текстовых полей), поскольку адаптер многоязычный, и эти метки не переводятся автоматически:
| Часть | Значение | Метка по умолчанию |
|---|---|---|
R<n> | Количество машин скорой помощи (Rettungswagen) | Rettungswagen |
p суффикс | Политраума | Polytrauma |
f суффикс | Включая сотрудников экстренных служб | First Responder |
-NT/ nt суффикс | Специальная скорая транспортировка | Notfalltransport mit Notfallkrankenwagen |
-NT/ nt суффикс | Специальный санитарный транспорт | Notfalltransport mit Notfallkrankenwagen |
Описание ключевых слов
Проверка выполняется только в том случае, если декодер на вкладке Спасательная служба не совпал со следующим списком строк {keyword pattern, description, match type} - тип совпадения starts with или contains, сравнение нечувствительно к регистру и рассматривает пробелы и дефисы как эквивалентные (любая последовательность любого из них сводится к единице перед сравнением), поэтому, например, H:VU mit P, H:VU-mit-P и H:VU - mit - P соответствуют одной и той же строке - нет необходимости добавлять отдельную строку для каждого варианта написания. Если совпадает несколько строк, автоматически побеждает наиболее специфический (длинный) шаблон - порядок строк не влияет на совпадение, поэтому таблицу можно свободно сортировать по любому столбцу (щелкните заголовок столбца) без изменения поведения. Таблица предварительно заполнена примером списка ключевых слов для пожарной охраны/спасательных служб (B:.../H:...) только в качестве отправной точки - не гарантируется ее соответствие реальному каталогу какого-либо конкретного диспетчерского центра; при необходимости отредактируйте или полностью замените ее.
Для резервного копирования или переноса этой таблицы используйте стандартный экспорт/импорт конфигурации экземпляра ioBroker (JSON). После использования этого импорта перезагрузите страницу администрирования перед проверкой этой таблицы - диалоговое окно открытия конфигурации не обновляет ее автоматически из внешнего импорта (это ограничение синхронизации состояния самого компонента таблицы администрирования, а не то, что контролируется этим адаптером).
Если ни эта таблица, ни приведенный выше декодер не совпадают, то einsatzAktuell.beschreibung - это просто null, а не ошибка.
Изображение карты инцидента
Создавать изображение карты для каждого инцидента (флаг администратора, по умолчанию отключен): если включено и инцидент имеет действительные координаты, адаптер загружает необходимые тайлы с общедоступного сервера tile.openstreetmap.org, объединяет их в один PNG-файл, центрированный на местоположении инцидента, и добавляет отметку об авторстве OpenStreetMap (требуемую лицензией ODbL) в нижний левый угол.
По умолчанию область инцидента, которую WAIP-Web отправляет в поле geometry события (обычно это многоугольник в форме круга вокруг местоположения, а не только его центр), отображается на изображении в виде контура с настраиваемым цветом и толщиной - исходная форма, отправленная сервером, а не маркер в его центре. Показать многоугольник области инцидента (флаг администратора, включен по умолчанию) управляет этим: снимите его, чтобы всегда отображать простую точку-маркер в центре, даже если многоугольник доступен. Точка также используется автоматически, если событие вообще не содержит многоугольника (например, только точку) - в этом случае это единственный вариант независимо от флажка. Область инцидента всегда остается полностью видимой при отрисовке многоугольника: если она не помещается на изображении при настроенном уровне масштабирования, адаптер автоматически уменьшает масштаб (никогда не увеличивает) ровно настолько, чтобы поместилась вся область, вместо того, чтобы обрезать ее по краям.
Уровень масштабирования, Цвет маркера и контура и Ширина/высота изображения расположены выше этого флажка, поскольку они применяются к любому режиму отображения: к уровню масштабирования, как описано выше для многоугольника, или как к фиксированному значению для точки маркера; к цвету контура многоугольника или к ядру точки маркера; к ширине/высоте самого изображения в любом случае. Ниже флажка отображается только Толщина контура, поскольку она действительно влияет только на контур многоугольника - размер точки маркера фиксирован и не настраивается.
Путь к файлу записывается в einsatzAktuell.kartenbildPfad (см. einsatzAktuell) - обычно этот файл прикрепляется из скрипта Blockly/JavaScript, например, в качестве вложения к уведомлению Pushover.
На диске хранятся только 10 самых последних сгенерированных изображений; более старые автоматически удаляются при каждой записи нового. Обработка тревожных сигналов ожидает завершения обработки изображения, прежде чем продолжить, поэтому гарантируется, что einsatzAktuell.kartenbildPfad уже будет содержать правильное значение к моменту, когда станут доступны остальные поля инцидента (например,
einsatzAktuell.alarmAktiv) - но только до настраиваемого тайм-аута OSM: если загрузка/составление плитки не завершено в течение этого времени, регистрируется предупреждение, и einsatzAktuell.kartenbildPfad остается пустым для этого инцидента, не блокируя обработку тревожных сигналов на неопределенный срок.
| Поле | Описание | По умолчанию |
|---|---|---|
| Тайм-аут OSM (с) | Максимальное время ожидания изображения (загрузка и компоновка тайла) перед продолжением работы без него (1-60) | 10 |
| Цвет маркера и контура | Цвет центральной точки маркера или контура зоны инцидента, если вместо маркера нарисован многоугольник | #DD2020 |
| Ширина изображения (пиксели) | Ширина сгенерированного PNG-файла | 600 |
| Высота изображения (пиксели) | Высота сгенерированного PNG-файла | 400 |
| Высота изображения (пиксели) | Высота сгенерированного PNG | 400 |
| Толщина контура (пиксели) | Толщина линии контура в пикселях (1-12) | 4 |
| Толщина контура (пиксели) | Толщина линии контура в пикселях (1-12) | 4 |
Изображения хранятся в собственном каталоге данных этого экземпляра адаптера (iobroker-data/<instance>/maps/), а не в виде файловых объектов ioBroker - einsatzAktuell.kartenbildPfad, следовательно, представляет собой реальный абсолютный путь к файловой системе, который скрипт, работающий на том же хосте, может прочитать напрямую. Этот каталог не удаляется автоматически при остановке адаптера или сбросе его конфигурации экземпляра; чтобы удалить его при удалении, установите флажок «Также удалить данные экземпляра» в диалоговом окне подтверждения при удалении экземпляра/адаптера в Admin (доступно начиная с js-controller 4.0 / Admin 5 для любого каталога данных экземпляра адаптера - по умолчанию флажок снят).
Примечание: Используется официальный бесплатный сервер
tile.openstreetmap.org, предназначенный для эпизодического/неинтенсивного использования (см. Политика использования тайлов OSM). Одно изображение на инцидент - это вполне допустимо. Не уменьшайте масштаб, чтобы охватить огромные области, и не превращайте это в массовую загрузку тайлов.
Панель управления
Включить панель мониторинга (флаг администратора, по умолчанию выключено): отображает последние N инцидентов, соответствующих настроенному монитору этого экземпляра, как dashboard.einsatz1 … dashboard.einsatzN, в дополнение к единственному текущему инциденту, уже доступному в einsatzAktuell. Это полезно с идентификатором монитора, ограниченным «всеми диспетчерскими мониторами» (0) или более широким районом/перевозчиком, где одновременно может быть активно несколько инцидентов, и einsatzAktuell.* отображает только самый последний.
В отличие от постоянно активного соединения /waip, которое этот адаптер поддерживает, панель мониторинга обновляется периодически: адаптер получает общедоступную страницу обзора инцидентов /dbrd/, фильтрует ее, отбирая инциденты, соответствующие монитору этого экземпляра (та же корреляция l/a/b/c Leitstelle/Kreis/Träger/Wache, что и в выпадающем списке идентификаторов мониторов - см. Связь), и для каждого из N соответствующих инцидентов по очереди открывает одно кратковременное соединение Socket.IO (никогда не параллельно), чтобы получить его текущее состояние, а затем закрывает его снова. Таким образом, полное обновление в реальности занимает несколько секунд на каждый занятый einsatzN, а не миллисекунды - минимальный интервал обновления, указанный ниже, отражает это.
| Поле | Описание | По умолчанию |
|---|---|---|
| Количество инцидентов для отображения | Сколько самых последних соответствующих инцидентов следует отобразить, dashboard.einsatz1 … einsatzN (1-20) | 10 |
| Интервал обновления (с) | Как часто обновляется панель мониторинга (30-300) | 60 |
Обновление также выполняется один раз сразу после каждого (пере)запуска адаптера (чтобы панель мониторинга не оставалась пустой в течение заданного интервала), и один раз при получении нового сигнала тревоги для собственного монитора этого экземпляра (einsatzAktuell.*) - в дополнение к обычному таймеру. Ручное обновление можно запустить в любое время с помощью состояния кнопки dashboard.refreshNow, например, с помощью кнопки VIS или скрипта.
Изображения карт, обозначенные как dashboard.einsatzN.kartenbildPfad, не генерируются отдельно для панели мониторинга - они ищутся в той же истории файлов, которую Изображение карты инцидента уже создает для собственного монитора этого экземпляра. einsatzN имеет изображение карты только тогда, когда этот адаптер уже сгенерировал его для этого конкретного инцидента с помощью собственной обработки тревожных сигналов einsatzAktuell.* - наиболее полная обработка происходит, когда идентификатор монитора равен 0 (все диспетчерские мониторы) и включена опция Генерировать изображение карты для каждого инцидента, поскольку в этом случае каждый инцидент, который может появиться на панели мониторинга, также прошел через einsatzAktuell.* хотя бы один раз.
При более узком идентификаторе монитора записи einsatzN для инцидентов вне собственной истории тревожных сигналов этого монитора не будут иметь изображения карты - это ожидаемое поведение, а не ошибка.
Отключение этой функции удаляет всё дерево объектов dashboard.* (каналы и состояния, а не только их значения); уменьшение количества отображаемых инцидентов удаляет только теперь неиспользуемые записи einsatzN в конце (например, изменение с 10 на 5 удаляет dashboard.einsatz6 … einsatz10).
Оба изменения вступают в силу только при следующем перезапуске адаптера после сохранения (ioBroker перезапускает экземпляр при любом изменении конфигурации - удаление не происходит мгновенно, пока открыто диалоговое окно администратора).
Штаты (в соответствии с waip-web.0.*)
Обратная связь и маршруты представляют собой списки 1:n для каждого инцидента. Они хранятся в виде плоских JSON-массивов в einsatzAktuell.json.* (без вложенных объектов/массивов внутри строки), поэтому их можно напрямую привязать к виджетам таблиц VIS - дополненных быстро привязываемыми счетчиками, так что для привязок и триггеров вообще не требуется разбор JSON.
Информация
| Штат | Тип | Описание |
|---|---|---|
connection | логическое значение | Стандартный индикатор ioBroker: соединение с сервером WAIP активно |
Статус
| Штат | Тип | Описание |
|---|---|---|
connected | логическое значение | Технически установлено соединение Socket.IO |
registeredMonitorName | строка | Отображаемое имя этого монитора без идентификатора (например, "Leitstelle: Lausitz"); определяется один раз при запуске с той же страницы обзора /waip/, что и выпадающее меню администратора, null, если его не удалось определить |
registrationAccepted | логическое значение | true после получения первого события, false сразу после подключения или по истечении времени ожидания регистрации |
registrationPending | логическое значение | true сразу после подключения, пока ожидается ответ от сервера, false после принятия или истечения времени ожидания |
registrationPending | логическое значение | true сразу после подключения, пока ожидается ответ от сервера, false после принятия или истечения времени ожидания |
EinsatzAktuell
Плоские поля текущего инцидента. Очищено (null/0) на io.standby, что соответствует официальному интерфейсу - alarmAktiv, следовательно, является надежным переключателем, указывающим, содержат ли эти поля в данный момент реальные данные.
Последний завершенный инцидент остается доступным через einsatzAktuell.json.history:
Примечание: Адаптер всегда отображает только самый последний активный инцидент (
einsatzAktuell.*/einsatzAktuell.json.current) - > соответствующий монитору оповещений официального интерфейса WAIP-Web. В принципе, в WAIP-Web может быть одновременно активно несколько инцидентов (например, два оповещения, поступающие с небольшим интервалом). Эти состояния не являются массивом одновременно работающих инцидентов - они перезаписываются каждым новым событиемio.new_waip, поэтому второй инцидент, работающий параллельно, в настоящее время не виден через этот адаптер. Полный обзор всех активных в данный момент инцидентов доступен только через панель управления подключенного экземпляра WAIP-Web.
Примечание: Сервер WAIP-Web заполняет только
einsatznummer,objekt/ >objektteil,besonderheiten,strasse/hausnummer, >einsatzdetailsи флаг разрешения для включенных клиентов > (db_user_check_permission_for_waip()в собственном >server/waip.jsсервера) - поскольку этот адаптер подключается без авторизации по своей конструкции (см. Об этом адаптере), сервер > всегда отправляет эти пустые значения/false. Поэтому они вообще не отображаются как состояния, а вместо этого навсегда содержат мертвые значения.
| Штат | Тип | Описание |
|---|---|---|
alarmAktiv | логическое значение | true с момента последнего io.new_waip, false с момента последнего io.standby |
id | номер | Внутренний идентификатор инцидента |
uuid | строка | Уникальный UUID инцидента (также используется для привязки обратной связи) |
einsatzart | строка | например «Brandeinsatz» (пожар), «Hilfeleistungseinsatz» (техническая помощь), «Rettungseinsatz» (спасение/скорая помощь), «Krankentransport» (транспортировка пациентов) |
stichwort | строка | Ключевое слово тревоги |
beschreibung | строка | Описание для stichwort, определено локально (не отправлено сервером) - см. Служба спасения/[Описание ключевых слов] ниже. null если ничего не найдено |
ort | строка | Местоположение/город |
ortsteil | строка | Район (если отличается от ort) |
alarmierungszeit | строка (дата) | Время будильника |
ablaufzeit | строка (дата) | Окончание времени отображения в режиме ожидания, основание для restzeit |
sondersignal | номер | 1 = специальный сигнал (фары и сирена), в противном случае - нет |
latitude / longitude | номер | Местоположение инцидента (нормализовано по полям wgs84 или центроиду GeoJSON) |
kartenbildPfad | строка | Путь к последнему сгенерированному изображению карты инцидентов (PNG) - см. Изображение карты инцидента. Пустое до тех пор, пока не будет готово первое изображение для текущего инцидента; также очищается (остается пустым) в начале нового инцидента, если генерация не удалась или не завершилась в течение времени ожидания OSM, и - как и другие поля выше - при io.standby. Сам файл изображения не удаляется при очистке состояния (удаляются только файлы, хранящиеся в течение 10 дней, см. [Изображение карты инцидента]) |
routenGesamt | номер | Количество маршрутов в текущем инциденте |
rueckmeldungenGesamt | число | Общее количество отзывов по текущему инциденту |
rueckmeldungen.rollen.ek | номер | Обратная связь учитывается как член команды («Einsatzkraft») |
rueckmeldungen.rollen.gf | номер | Обратная связь засчитывается как командир экипажа («группенфюрер») |
rueckmeldungen.rollen.zf | номер | Обратная связь учитывается как начальник отдела («Цугфюрер») |
rueckmeldungen.rollen.vf | число | Обратная связь учитывается как у командира группы ("Verbandsführer") |
rueckmeldungen.funktionen.agt | номер | Учет обратной связи с аттестацией дыхательного аппарата («Atemschutzgeräteträger») |
rueckmeldungen.funktionen.fzf | номер | Отзыв засчитывается как командир машины («Фарцойгфюрер») |
rueckmeldungen.funktionen.ma | число | Отзывы учитываются как отзывы водителя/оператора ("машиниста") |
rueckmeldungen.funktionen.med | число | Количество отзывов с медицинской квалификацией |
rueckmeldungen.funktionen.med | число | Количество отзывов с медицинской квалификацией |
EinsatzAktuell.json
Плоские JSON-объекты/массивы, максимум на один уровень вложенности, предназначены для прямой привязки к виджетам таблиц VIS (вложенные структуры, такие как простой объект {routen, rueckmeldungen, ...}, обычно не отображаются этими виджетами). routen/rueckmeldungen/emAlarmiert/emWeitere содержат только данные текущего инцидента - они очищаются ([]) при io.standby и не являются частью истории. Как и в случае с einsatzAktuell.* выше, current содержит только самый последний активный инцидент - см. примечание в разделе einsatzAktuell.
| Штат | Тип | Описание |
|---|---|---|
current | строка (массив JSON) | Плоские данные текущего инцидента: те же 12 полей, что и в отдельных состояниях einsatzAktuell.* выше (id … sondersignal, плюс beschreibung, alarmierungszeit, lat/lon), плюс registeredMonitor/registeredMonitorName (монитор, к которому адаптер был зарегистрирован в тот момент), объединенные в один объект внутри одноэлементного массива ([], если нет активного инцидента) - обертка массива необходима, потому что большинство виджетов таблиц требуют массив в корне, а не простого объекта |
routen | строка (массив JSON) | Маршруты текущего инцидента; каждая запись содержит nr_wache, name_wache, color, lat, lon (position преобразуется в плоский lat/lon - см. примечание ниже о том, что представляет собой lat/lon для маршрута) |
rueckmeldungen | строка (массив JSON) | Записи обратной связи по текущему инциденту, полученные с сервера |
emAlarmiert | строка (массив JSON) | Ресурсы, получившие оповещения по текущему инциденту; каждая запись содержит name, zeit, wache, zeit_alarmierung_iso, zeit_ausgerueckt_iso |
emWeitere | строка (массив JSON) | Дополнительные ресурсы текущего инцидента, той же формы, что и emAlarmiert |
emWeitere | строка (массив JSON) | Дополнительные ресурсы текущего инцидента, той же формы, что и emAlarmiert |
Примечание:
routen[].lat/.lon- это местоположение станции, получившей оповещение, а не точка на фактическом маршруте движения и не место происшествия. Сервер отправляет каждый маршрут либо как полныйLineString(рассчитанный путь от станции до места происшествия), либо, если путь рассчитать не удалось, как одну пару координат для самой станции - в обоих случаях адаптер преобразуетlat/lonв местоположение станции (первая точка линии в случаеLineString) для обеспечения согласованного значения для всех записей. Полная геометрия маршрута не отображается как состояние.
EinsatzAktuell.tts
Голосовое объявление (io.playtts) для текущего инцидента - находится в канале einsatzAktuell, а не в отдельном канале верхнего уровня, поскольку не имеет смысла без инцидента. История отсутствует: объявление TTS имеет значение только в данный момент, поэтому сохраняется только самое последнее.
| Штат | Тип | Описание |
|---|---|---|
last | строка (URL) | Полный абсолютный URL-адрес файла mp3 последнего голосового объявления. Сервер отправляет только простой (часто относительный) путь, предназначенный для использования в качестве audio.src в браузере, имеющем тот же источник; адаптер преобразует его в URL-адрес, настроенный для сервера WAIP, поэтому ссылка также работает за пределами веб-страницы WAIP (например, в аудиовиджете VIS) |
lastTimestamp | строка (дата) | Время последнего объявления |
Панель управления
Присутствует только при включении Панель управления - см. там информацию о жизненном цикле дерева объектов при включении/отключении/изменении размера. dashboard.einsatzN (N = 1 … заданное количество отображаемых инцидентов) имеет ту же форму, что и einsatzAktuell/einsatzAktuell.json выше, для N-го по счету последнего инцидента, соответствующего монитору этого экземпляра - не ограничивается единственным текущим инцидентом. Все поля занятого einsatzN всегда перезаписываются при каждом обновлении (а не только при изменении), поэтому постоянная обратная связь для инцидента, который остается на том же уровне einsatzN при каждом обновлении, продолжает обновляться; В незанятом поле einsatzN (меньшее количество соответствующих инцидентов, чем настроено) все поля имеют пустые значения, точно так же, как в поле einsatzAktuell.*, когда нет активных инцидентов.
Намеренно без restzeit/ablaufzeit (данные /dbrd/ инцидента в WAIP-Web не имеют эквивалентного поля, в отличие от потока тревожных сигналов в реальном времени /waip) и без эквивалента einsatzAktuell.tts (в пространстве имен /dbrd нет события TTS). dashboard.einsatzN.json.wachen не имеет аналога einsatzAktuell.json.* в обратном порядке - он берется из поля (wachen[], участвующие станции инцидента), которое включается только в полезную нагрузку /dbrd.
| Штат | Тип | Описание |
|---|---|---|
refreshNow | логическое значение (кнопка) | Напишите true, чтобы запустить немедленное обновление панели мониторинга, например, с помощью кнопки VIS или скрипта. Сбрасывается до false после завершения обновления |
einsatzN.id | номер | Внутренний идентификатор инцидента |
einsatzN.uuid | строка | Уникальный UUID инцидента |
einsatzN.einsatzart | строка | То же значение, что и einsatzAktuell.einsatzart |
einsatzN.stichwort | строка | Ключевое слово тревоги |
einsatzN.beschreibung | строка | Описание для stichwort, разрешается так же, как и einsatzAktuell.beschreibung |
einsatzN.ort | строка | Местоположение/город |
einsatzN.ortsteil | строка | Район (если отличается от ort) |
einsatzN.alarmierungszeit | строка (дата) | Время будильника |
einsatzN.sondersignal | номер | 1 = специальный сигнал (фары и сирена), в противном случае - нет |
einsatzN.latitude / einsatzN.longitude | номер | Место происшествия, та же нормализация, что и в einsatzAktuell |
einsatzN.kartenbildPfad | строка | Путь к соответствующему, ранее сгенерированному изображению карты инцидента - см. Панель управления выше. Пусто, если изображение не найдено |
einsatzN.routenGesamt | номер | Количество маршрутов для инцидента einsatzN |
einsatzN.rueckmeldungenGesamt | число | Общее количество отзывов по инциденту einsatzN |
einsatzN.rueckmeldungen.rollen.* / .funktionen.* | число | Те же восемь счетчиков обратной связи, что и в einsatzAktuell.rueckmeldungen, согласно einsatzN |
einsatzN.json.current | строка (массив JSON) | einsatzN - плоские данные об инциденте, той же формы, что и einsatzAktuell.json.current (без registeredMonitor/registeredMonitorName) |
einsatzN.json.routen | строка (массив JSON) | Маршруты инцидента einsatzN, той же формы, что и einsatzAktuell.json.routen |
einsatzN.json.rueckmeldungen | строка (массив JSON) | Отзывы об инциденте einsatzN |
einsatzN.json.emAlarmiert | строка (массив JSON) | Ресурсы, получившие оповещение об инциденте einsatzN |
einsatzN.json.wachen | строка (массив JSON) | Станции, участвовавшие в инциденте einsatzN (em_station_id/em_station_name) - доступны только через /dbrd, аналога для einsatzAktuell.json.* нет |
einsatzN.json.wachen | строка (массив JSON) | Станции, участвующие в инциденте einsatzN (em_station_id/em_station_name) - доступны только через /dbrd, без аналога einsatzAktuell.json.* |
Отладка
| Штат | Тип | Описание |
|---|---|---|
lastEvent | строка (массив JSON) | Последнее полученное событие сокета (имя + метка времени), для диагностики соединения; массив из одного элемента ([], если еще не было), для совместимости с виджетом таблицы VIS |
rawPayloadShort | строка | Предварительный просмотр (500 символов) необработанного, ненормализованного полезного содержимого io.new_waip |
ignoredCount | число | Количество отброшенных событий (полезная нагрузка явно указана с другим идентификатором монитора) |
monitorAudit | строка (массив JSON) | Хронологический журнал событий подключения/регистрации/повторного подключения (200 записей) |
sessionExpires | строка (дата) | Время истечения срока действия сессионного cookie на момент последнего обновления |
lastError | строка | Последнее сообщение об ошибке, сообщенное сервером (io.error); обычный текст, а не JSON, поскольку сервер отправляет это как обычную строку |
serverVersion | строка | Последний зарегистрированный идентификатор экземпляра сервера (io.version); изменение указывает на необходимость перезапуска сервера |
serverVersion | string | Последний зарегистрированный идентификатор экземпляра сервера (io.version); изменение указывает на перезапуск сервера |
Ведение журнала
Весь текст логов на английском языке. Повторяющиеся сбои (обновление cookie-сессии, регистрация WAIP, соединение Socket.IO, поток событий от неправильного монитора) регистрируются один раз в warn при первом возникновении, затем в debug, пока они сохраняются, и один раз в info при восстановлении - в соответствии с Официальные правила ведения логов ioBroker.
См. LOGGING.md для получения полной информации обо всех сообщениях журнала, которые может создавать адаптер, сгруппированных по уровню, с указанием причины и примером.
Changelog
WORK IN PROGRESS
registrationTimeoutSecandreconnectDelaySecare now clamped in code to their admin UI range (1-120s), matching how every other numeric configuration value (e.g.historySize,mapImageWidth) was already handled - a direct instance config JSON edit/import can no longer set them outside that range.- The
stateChangelistener (used only fordashboard.refreshNow) is now registered only while the Dashboard feature is enabled, matching itssubscribeStates()call, instead of unconditionally in the constructor.
1.0.0 (2026-08-30)
- Breaking change: the
einsatzchannel is renamed toeinsatzAktuell(to distinguish it from thedashboard.einsatz1…einsatzNdashboard channels), andeinsatzAktuell.json.history10is renamed toeinsatzAktuell.json.history, now holding a configurable number of entries (new "Number of incidents in history" setting on the Connection tab, 1-100, default 10). Update any VIS bindings/scripts referencing the oldeinsatz.*/einsatz.json.history10paths - they are removed automatically on upgrade, along with their values. - Dashboard channel/state display names are now consistent: they use
"Einsatz N" throughout, matching the
einsatzAktuell.*naming, and the redundant "flat JSON array" phrase was removed from every state name. Object IDs are unaffected, only the display names shown in Admin/VIS.
0.12.1 (2026-08-30)
- Fixed the Dashboard admin config: the tab was mistranslated as "Armaturenbrett" (car dashboard) in German instead of "Dashboard", its help texts used wrong/mistranslated terms ("Versandzentrum"/"Vorfall" instead of "Leitstelle"/"Einsatz"), and the refresh interval label was missing its "(s)" unit suffix.
- Fixed
routen[].lat/.lon(botheinsatz.json.routenanddashboard.einsatzN.json.routen): previously resolved to the geometric bounding-box center of the entire route line - a point with no real meaning, since it lies "somewhere along the way" rather than at any actual location. Now resolves to the alerted station's own location instead (the first point of the route line, matching a separate coordinate-pair format the server sends when no route could be calculated for a station). Also fixeddashboard.einsatzN.json.routenspecifically: it was missing the same geo normalizationeinsatz.json.routenalready applied, so a route's raw, unresolved geometry (dozens of coordinate pairs) or the raw fallback coordinate field ended up in the written JSON instead of flatlat/lon.
0.12.0 (2026-08-28)
- New optional Dashboard feature: mirrors the last N
incidents matching this instance's monitor as
dashboard.einsatz1…einsatzN(off by default). Uses short-lived Socket.IO connections to WAIP-Web's/dbrdnamespace polled on a configurable interval, not a permanent connection - see Dashboard and dashboard states for the full behavior, including the manual refresh button and the object-deletion behavior when disabling the feature or reducing the number of incidents to show.
0.7.38 (2026-08-27)
- Fixed a race condition where a routes update (
io.routes) or TTS announcement (io.playtts) arriving while an incident was being finalized could still repopulateeinsatz.json.current,einsatz.json.routenandeinsatz.routenGesamtfor the already finished incident. The 0.7.37 guard checked a flag that was only cleared at the very end of the finalization, leaving a window open across severalawaitpoints. - Fixed lost entries in
debug.monitorAudit: the log was written with an unsynchronized read-modify-write, so two entries created within milliseconds of each other (e.g.connect_calledfollowed byemit_WAIP) could overwrite one another. Writes are now serialized. - Fixed configuration values falling back to the minimum instead of the default when a numeric admin field is left empty - an empty zoom field produced zoom 1 (the whole world map) instead of the configured default, and an empty width field produced 100px instead of 600px.
- Added a unit test suite (
npm run test:unit, 75 tests) covering the geo normalization, the keyword decoder/table, the monitor matching and the state-definition consistency.npm testnow runs it alongside the package tests.
0.7.37 (2026-08-26)
- Fixed a bug where a routes update (
io.routes) or TTS announcement (io.playtts) arriving after an incident had already ended (io.standby) could reviveeinsatz.json.current/.routen/einsatz.routenGesamtoreinsatz.tts.last/.lastTimestampfor the already-finished incident, while every othereinsatz.*field correctly stayed cleared. Both handlers now ignore such events while no incident is active.
Older entries have been moved to CHANGELOG_OLD.md.
License
MIT License (this adapter) – see LICENSE.
The adapter connects to instances of WAIP-Web, which is licensed under CC BY-SA 4.0 by Robert-112. This adapter contains no code from that project.
Copyright (c) 2026 rnc11
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.