ГлавнаяАкадемияCOURSE-16: Основы Интернета Вещей и практическое применение → Практические методы анализа данных на контроллере HI

Практические методы анализа данных на контроллере HI

Урок 4 · COURSE-16: Основы Интернета Вещей и практическое применение · theory

COURSE-16-M03-L05 — Практические методы анализа данных на контроллере HI

Введение в аналитику на Edge-устройствах

В экосистеме Интернета вещей (IoT) данные являются главным активом. Контроллер HI непрерывно собирает информацию с десятков датчиков и устройств. Однако сырые данные сами по себе бесполезны. Их ценность раскрывается только через анализ.

Вопреки распространенному мнению, сложный анализ данных — это не только прерогатива мощных облачных серверов. Значительную часть аналитической работы можно и нужно выполнять непосредственно на «краю» сети (Edge Computing), то есть на самом контроллере. Это обеспечивает высокую скорость реакции, автономность системы при потере связи с интернетом и снижение затрат на трафик.

В этом уроке мы разберем четыре уровня анализа данных и, что самое важное, научимся реализовывать их на практике с помощью Node-RED на контроллере HI. Мы превратим абстрактные концепции в работающие сценарии автоматизации для реальных объектов.

Четыре уровня аналитики данных в IoT

Анализ данных можно условно разделить на четыре ступени, каждая из которых отвечает на свой вопрос и повышает ценность системы.

  • Описательная (Descriptive) аналитика: Что произошло?
  • * Цель: Агрегировать и суммировать исторические данные для получения общей картины.

    * Пример: Расчет среднего расхода электроэнергии за последний час, определение максимальной температуры в помещении за сутки.

  • Диагностическая (Diagnostic) аналитика: Почему это произошло?
  • * Цель: Найти взаимосвязи и причины событий путем сопоставления различных данных.

    * Пример: Установить, что скачок энергопотребления совпал по времени с включением системы кондиционирования.

  • Предсказательная (Predictive) аналитика: Что произойдет?
  • * Цель: Использовать исторические данные для прогнозирования будущих состояний и событий.

    * Пример: Спрогнозировать, через сколько часов заполнится бак для сбора конденсата, на основе текущей скорости его наполнения.

  • Предписывающая (Prescriptive) аналитика: Что следует сделать?
  • * Цель: На основе анализа и прогнозов автоматически принимать оптимальные решения и выполнять действия.

    * Пример: Автоматически перевести систему отопления в экономичный режим, если прогноз погоды обещает потепление и в здании нет людей.

    Далее мы рассмотрим, как реализовать каждый из этих уровней на платформе HI.

    Описательная аналитика: «Что произошло?»

    Это базовый уровень, с которого начинается любой анализ. Наша задача — преобразовать поток сырых данных в осмысленную сводку.

    Практический сценарий: Анализ температуры в серверной. Необходимо каждые 10 минут получать минимальное, максимальное и среднее значение температуры за этот интервал и отправлять их в MQTT для отображения на дашборде. Реализация в Node-RED (FLOW-ANALYSIS-DESC-001):
  • Сбор данных: Узел `ds18b20 in` (1-Wire) считывает показания с датчика DS18B20 каждую минуту.
  • Валидация: Узел `Function` проверяет, что значение находится в допустимом диапазоне (например, от -10 до +85 °C), и формирует сообщение согласно контракту.
  • Агрегация: Узел `node-red-contrib-aggregator` собирает все сообщения за 10-минутный интервал.
  • Вычисление: Узел `Function` обрабатывает массив значений от агрегатора и вычисляет min, max, avg.
  • Публикация: Узел `mqtt out` отправляет результат в виде единого JSON-объекта.
  • ASCII-схема потока:
    [1-Wire In] -> [Function: Validate] -> [Aggregator: 10 min] -> [Function: Calculate Stats] -> [MQTT Out]
    

    | |

    +--------------------(on error)-----------------------------------+-> [Catch] -> [Log Error]

    Код для узла `Function: Calculate Stats`:
    // Входящее сообщение msg.payload - это массив значений, например:
    

    // [25.1, 25.2, 25.1, 25.3, 25.4, 25.3, 25.2, 25.3, 25.4, 25.5]

    const values = msg.payload;

    if (!Array.isArray(values) || values.length === 0) {

    node.status({fill:"yellow", shape:"ring", text:"No data in interval"});

    return null;

    }

    const sum = values.reduce((a, b) => a + b, 0);

    const avg = (sum / values.length) || 0;

    const min = Math.min(...values);

    const max = Math.max(...values);

    // Формируем исходящее сообщение по контракту

    msg.payload = {

    "avg_temp": parseFloat(avg.toFixed(2)),

    "min_temp": min,

    "max_temp": max,

    "period_sec": 600,

    "source": "temp-sensor-server-room",

    "ts": Date.now()

    };

    msg.topic = "telemetry/server-room/temperature/summary";

    // 💡 Паттерн "Визуальный статус": отображаем результат прямо на узле

    node.status({fill:"green", shape:"dot", text:`Avg: ${avg.toFixed(1)}°C`});

    return msg;

    Диагностическая аналитика: «Почему это произошло?»

    Этот уровень помогает находить скрытые зависимости. Мы не просто фиксируем событие, а пытаемся понять его причину, сопоставляя данные из разных источников.

    Практический сценарий: В офисном помещении резко ухудшилось качество воздуха (вырос уровень CO2). Необходимо выяснить причину: это произошло из-за большого скопления людей или из-за отключения вентиляции? Реализация в Node-RED (FLOW-ANALYSIS-DIAG-003):
  • Источники данных:
  • * Поток 1: Узел `Modbus-Read` опрашивает датчик CO2 (например, WB-MSW3) и отправляет значение.

    * Поток 2: Узел `Modbus-Read` опрашивает релейный модуль, чтобы узнать состояние вентилятора (включен/выключен).

    * Поток 3: Узел `Presence Detector` (например, на базе дискретного входа от датчика движения) считает количество людей.

  • Объединение данных: Узел `Join` настроен на объединение сообщений от трех источников в один объект. Он ждет, пока не придут все три части (`msg.parts.id`), и только потом передает управление дальше.
  • Логический анализ: Узел `Switch` или `Function` анализирует объединенный объект.
  • ASCII-схема потока:
    [Modbus: CO2] --+
    

    +--> [Join: 3 parts] -> [Function: Diagnose] -> [MQTT Alert]

    [Modbus: Fan] --+

    |

    [Presence In] --+

    Код для узла `Function: Diagnose`:
    // Входящий msg.payload после узла Join:
    

    // { "co2": 1250, "fan_state": "OFF", "presence_count": 5 }

    const co2_level = msg.payload.co2;

    const fan_state = msg.payload.fan_state;

    const people_count = msg.payload.presence_count;

    let diagnosis = "Причина не установлена";

    let alert_level = "info";

    // 💡 Простая логика корреляции

    if (co2_level > 1000) { // Порог превышен

    if (fan_state === "OFF") {

    diagnosis = "Высокий CO2: Вентиляция отключена!";

    alert_level = "critical";

    } else if (people_count > 4) {

    diagnosis = "Высокий CO2: Много людей в помещении.";

    alert_level = "warning";

    }

    } else {

    // Уровень CO2 в норме, ничего не делаем

    node.status({fill:"green", shape:"dot", text:`CO2 OK: ${co2_level} ppm`});

    return null;

    }

    msg.payload = {

    "alert_level": alert_level,

    "message": diagnosis,

    "details": {

    "co2_ppm": co2_level,

    "fan_state": fan_state,

    "people_count": people_count

    },

    "ts": Date.now()

    };

    msg.topic = "alerts/office/air_quality/diagnosis";

    node.status({fill:"red", shape:"dot", text: diagnosis});

    return msg;

    Предсказательная аналитика: «Что произойдет?»

    Здесь мы делаем шаг от анализа прошлого к прогнозированию будущего. На уровне контроллера это редко бывают сложные модели машинного обучения, но даже простые прогнозы на основе трендов чрезвычайно полезны.

    Практический сценарий: Мониторинг заполнения дренажного бака системы кондиционирования. Необходимо спрогнозировать, когда бак заполнится, чтобы вовремя отправить уведомление службе эксплуатации и избежать протечки. Реализация в Node-RED (FLOW-ANALYSIS-PRED-002):
  • Сбор данных: Узел, считывающий показания с аналогового датчика уровня (0-10В), подключенного к универсальному входу контроллера.
  • Фильтрация: Узел `rbe` (report-by-exception) пропускает значения только при существенном изменении, чтобы отсечь шум.
  • Расчет тренда: Узел `smooth` вычисляет скользящее среднее и, что важнее, скорость изменения значения (rate of change).
  • Прогнозирование: Узел `Function` использует текущий уровень и скорость его изменения для расчета времени до заполнения.
  • ASCII-схема потока:
    [Analog In: Level] -> [RBE] -> [Smooth] -> [Function: Predict Time] -> [Switch: Check Threshold] -> [MQTT Alert]
    
    Код для узла `Function: Predict Time`:
    // Входящий msg.payload от узла smooth может выглядеть так:
    

    // { "value": 75, "rate_min": 0.5 } // Уровень 75%, скорость +0.5% в минуту

    const TANK_CAPACITY_PERCENT = 100;

    const current_level = msg.payload.value;

    const rate_per_minute = msg.payload.rate_min;

    if (rate_per_minute <= 0) {

    // Уровень не растет или падает

    node.status({fill:"green", shape:"dot", text:`Level: ${current_level.toFixed(1)}%`});

    return null;

    }

    const remaining_capacity = TANK_CAPACITY_PERCENT - current_level;

    const minutes_to_full = remaining_capacity / rate_per_minute;

    // Формируем сообщение с прогнозом

    msg.payload = {

    "current_level_percent": current_level,

    "rate_percent_per_min": rate_per_minute,

    "predicted_minutes_to_full": parseFloat(minutes_to_full.toFixed(1))

    };

    // 💡 Обновляем статус для наглядности

    node.status({fill:"yellow", shape:"ring", text:`Full in ~${Math.round(minutes_to_full)} min`});

    return msg;

    Далее узел `Switch` проверяет, если `predicted_minutes_to_full < 60`, и отправляет предупреждение.

    Предписывающая аналитика: «Что следует сделать?»

    Высший уровень автоматизации. Система не просто информирует, а самостоятельно принимает и исполняет решения. Это — ядро умных сценариев.

    Практический сценарий: Интеллектуальное управление бойлером в умном доме для экономии электроэнергии. Логика (предписание): Реализация в Node-RED (SCN-WATER-HEATER-011):

    Здесь идеально подходит паттерн "Конечный автомат" (FSM).

  • Состояния: Определяем состояния бойлера: `OFF`, `ECO`, `COMFORT`. Текущее состояние хранится в переменной `flow.boiler_state` (с настроенным сохранением в файловой системе для надежности).
  • События: Входящие сообщения от датчика присутствия, расписания (время суток), кнопки ручного управления.
  • Логика переходов: Центральный узел `Switch` маршрутизирует поток в зависимости от текущего состояния (`flow.boiler_state`).
  • Действия: В каждой ветке логики (для каждого состояния) принимается решение о переходе в новое состояние и отправляется команда на Modbus-реле, управляющее бойлером.
  • ASCII-схема потока (упрощенно):
    // Inputs
    

    [Scheduler] --+

    +--> [Join] -> [Switch: Check State] --+-- (State: OFF) ----> [Logic for OFF] --+

    [Presence] ---+ | |

    +-- (State: ECO) ----> [Logic for ECO] --+--> [Change: Set State] -> [Modbus Write]

    [Manual UI] --+ | |

    +-- (State: COMFORT) -> [Logic for COMFORT]--+

    Эта реализация является классическим примером предписывающей аналитики: система анализирует контекст (`почему?`), прогнозирует потребность в горячей воде (`что будет?`) и отдает команду (`что делать?`).

    ---

    📋 Лабораторные работы

    COURSE-16-M03-LAB01: Описательный анализ температуры

    1. [ ] Узел `Inject` настроен на запуск каждые 5 секунд.

    2. [ ] `Function: Эмулятор датчика` генерирует случайное число в диапазоне 20-25.

    3. [ ] `Aggregator` настроен на сбор данных в течение 1 минуты.

    4. [ ] `Function: Расчет статистики` корректно вычисляет min, max, avg.

    5. [ ] Узел `Debug` выводит JSON-объект с тремя рассчитанными значениями.

    6. [ ] На узле расчета статистики настроен `node.status` для вывода среднего значения.

    COURSE-16-M03-LAB02: Диагностика и предписание для освещения

    * Поток 1: `[Inject: "dark"]` -> `[Change: set flow.light_level]`

    * Поток 2: `[Inject: "motion"]` -> `[Function: Проверка условий]` -> `[Debug: "Включить свет!"]`

    1. [ ] Созданы два узла `Inject` для имитации датчика света ("dark"/"light") и движения ("motion").

    2. [ ] Состояние освещенности сохраняется в `flow` контексте.

    3. [ ] `Function: Проверка условий` срабатывает от датчика движения.

    4. [ ] Внутри функции происходит чтение `flow.light_level`.

    5. [ ] Сообщение в `Debug` отправляется, только если `flow.light_level == "dark"`.

    ---

    📝 Квиз по модулю (COURSE-16-M03-QUIZ)

  • Какой тип аналитики отвечает на вопрос «Что произошло?»
  • * a) Диагностическая

    * b) Описательная

    * c) Предсказательная

  • Расчет среднего значения температуры за сутки — это пример...
  • * a) Описательной аналитики

    * b) Диагностической аналитики

    * c) Предписывающей аналитики

  • Для объединения данных из нескольких источников в Node-RED перед диагностическим анализом лучше всего использовать узел:
  • * a) `Switch`

    * b) `Function`

    * c) `Join`

  • Какой паттерн Node-RED идеально подходит для реализации предписывающей аналитики со сложной логикой состояний?
  • * a) Контракт сообщения

    * b) Конечный автомат (FSM)

    * c) Визуальный статус

  • Прогнозирование времени до заполнения бака на основе скорости изменения уровня — это...
  • * a) Диагностическая аналитика

    * b) Предсказательная аналитика

    * c) Описательная аналитика

  • Зачем выполнять анализ данных на контроллере (Edge), а не в облаке?
  • * a) Для снижения нагрузки на процессор контроллера

    * b) Для обеспечения автономности и быстрой реакции системы

    * c) Потому что в облаке нет нужных инструментов

  • Какой узел в Node-RED поможет рассчитать скорость изменения показаний датчика?
  • * a) `Delay`

    * b) `RBE`

    * c) `Smooth`

  • Сопоставление высокого уровня CO2 с отключенным вентилятором — это задача для...
  • * a) Диагностической аналитики

    * b) Предсказательной аналитики

    * c) Описательной аналитики

  • Что такое «контракт сообщения» в контексте Node-RED?
  • * a) Лицензионное соглашение на использование узла

    * b) Стандартный формат JSON-объекта `msg.payload` для обмена данными между узлами

    * c) Зашифрованное сообщение

  • Автоматическое включение экономичного режима отопления на основе прогноза погоды — это пример...
  • * a) Описательной аналитики

    * b) Диагностической аналитики

    * c) Предписывающей аналитики

    ---

    🆘 Мини-runbook «Если не работает»

    * Решение: Проверьте, что узел `Aggregator` получает данные. Подключите к его входу `Debug`. Убедитесь, что в `Function` для расчета вы проверяете, что `msg.payload` является массивом и он не пустой. Проверьте, что данные являются числами (`parseFloat`). * Решение: Данные с датчика слишком "шумные". Перед узлом `Smooth` поставьте узел `RBE` (report-by-exception), чтобы отфильтровать незначительные колебания. Увеличьте период усреднения в настройках узла `Smooth`. * Решение: Проверьте настройки узла `Join`. Он должен быть настроен на ожидание всех частей сообщения. Проверьте `msg.topic` или `msg.parts.id` у сообщений, приходящих на `Join`. Убедитесь, что имена свойств в объединенном объекте (`msg.payload.co2`, `msg.payload.fan_state`) совпадают с теми, что вы используете в логике. * Решение: Убедитесь, что вы храните состояние в `flow` контексте, а не в `global`. В файле `settings.js` вашего Node-RED необходимо настроить `contextStorage` на использование файловой системы, чтобы `flow` переменные были персистентными.

    ⚠️ Типовые ошибки и план тестирования при сдаче объекта

    * Отсутствие валидации: Поток "падает" при получении некорректных данных от датчика (null, "error"). Решение: Всегда ставьте `Function` или `Switch` узел после узла ввода-вывода для проверки данных.

    * Жестко заданные пороги: Пороги для тревог (например, 1000 ppm для CO2) зашиты прямо в коде. Решение: Выносите такие параметры в переменные `flow` контекста или используйте UI-элементы дашборда для их настройки.

    * Игнорирование единиц измерения: Смешивание в расчетах разных единиц (ватты и киловатты, градусы Цельсия и Фаренгейта). Решение: Используйте "контракт сообщения", где `unit` является обязательным полем.

    1. [ ] Тест описательной аналитики: Открыть дашборд. Убедиться, что виджеты, показывающие средние/минимальные/максимальные значения (температура, влажность, энергопотребление), обновляются и показывают правдоподобные цифры.

    2. [ ] Тест диагностической аналитики: Имитировать событие. Например, закрыть вентиляционную решетку у датчика CO2. Убедиться, что система сгенерировала корректное тревожное сообщение («Высокий CO2: возможно, проблема с вентиляцией»).

    3. [ ] Тест предсказательной аналитики: Имитировать тренд. Например, медленно подливать воду в емкость с датчиком уровня. Убедиться, что система показывает адекватное прогнозное время до заполнения и вовремя выдает предупреждение.

    4. [ ] Тест предписывающей аналитики: Проверить работу автоматических сценариев в разных режимах. Переключить дом в режим «Никого нет». Убедиться, что климатические системы перешли в экономичный режим, а бойлер снизил температуру нагрева. Вернуть режим «Дома» и проверить возврат к комфортным настройкам.