Реализация уведомлений о критических показателях IoT-датчиков в мобильном приложении
Температура в серверной комнате поднялась до 45°C в 3 часа ночи. Push-уведомление пришло в 9 утра — когда смартфон подключился к Wi-Fi. За это время оборудование перегрелось. IoT-алерты — это задача, где «уведомление с задержкой» хуже, чем отсутствие уведомления.
Почему стандартный FCM не подходит для критических IoT-алертов
FCM нормальный приоритет (normal) буферизирует доставку когда устройство в Doze Mode. Для некритичных уведомлений это нормально. Для IoT-алертов — нет.
Нужен "priority": "high" в FCM payload + на iOS apns-priority: 10 с interruption-level: critical. Последнее — особый случай: UNNotificationInterruptionLevel.critical воспроизводит звук даже в режиме «Не беспокоить» и при включённом беззвучном режиме. Требует специального entitlement com.apple.developer.usernotifications.critical-alerts, который надо отдельно запрашивать у Apple.
Запрос разрешения на критические уведомления — отдельный промпт, отличается от стандартного:
UNUserNotificationCenter.current().requestAuthorization(
options: [.alert, .sound, .badge, .criticalAlert]
) { granted, error in ... }
Пользователь должен явно разрешить критические уведомления — нельзя включить их без согласия.
Архитектура IoT pipeline
Датчики → MQTT-брокер (Mosquitto или AWS IoT Core) → серверный обработчик → FCM/APNs.
MQTT — де-факто стандарт для IoT: лёгкий протокол, работает при нестабильном соединении, поддерживает QoS 0/1/2. Датчики публикуют данные в топик sensors/{device_id}/temperature, сервер подписывается на все топики устройств пользователя.
Серверный обработчик при получении сообщения проверяет значение против пороговых правил:
const rules = await getRulesForDevice(deviceId);
for (const rule of rules) {
if (rule.condition(value)) {
await sendCriticalAlert(userId, {
sensor: deviceId,
metric: rule.metric,
value,
threshold: rule.threshold,
severity: rule.severity
});
}
}
Дедупликация обязательна. Если датчик шлёт данные каждые 10 секунд и температура держится выше порога 30 минут — это не 180 уведомлений, а одно с обновлением статуса. Redis: SET alert:{device}:{metric}:active 1 EX 1800 — пока ключ существует, новые алерты по этому условию не отправляем.
Многоуровневая система алертов
| Уровень | Пример | FCM priority | iOS level | Действие |
|---|---|---|---|---|
| Info | Батарея датчика 20% | normal | passive | В шторке |
| Warning | Температура >35°C | high | active | Будит экран |
| Critical | Температура >45°C | high | critical | Звук в беззвучном |
| Emergency | Датчик CO >200 ppm | high | critical | Звук + вибрация |
На Android аналогично через notification channels с разным importance: IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, IMPORTANCE_MAX.
Мобильное приложение: экран мониторинга
Dashboard с live-данными датчиков — реализуем через WebSocket соединение (не polling, чтобы видеть обновления в реальном времени при открытом приложении). На Flutter: web_socket_channel пакет, данные в Riverpod StreamProvider.
Исторические графики — fl_chart или syncfusion_flutter_charts. Хранение истории на сервере в InfluxDB или TimescaleDB (PostgreSQL extension) — оба оптимизированы для временных рядов.
Настройка пороговых правил в приложении: пользователь выбирает датчик, метрику, оператор (>, <, ==), значение, уровень критичности. Правила сохраняются на сервере.
Процесс разработки
- Выбор MQTT-брокера и схемы топиков
- Разработка серверного обработчика с дедупликацией
- Настройка FCM + APNs critical alerts entitlement
- Разработка мобильного клиента (dashboard, настройки алертов)
- Тестирование доставки в Doze Mode и режиме «Не беспокоить»
- Нагрузочное тестирование (большое количество датчиков одновременно)
Сроки: от 4 недель (интеграция с существующей IoT-инфраструктурой) до 10–12 недель (разработка полного стека включая MQTT-брокер, серверную часть и мобильный клиент).







