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

Первая лабораторная работа: Компоненты и концепции IoT

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

COURSE-16-M01-LAB01 — Первая лабораторная работа: Компоненты и концепции IoT

Введение

Данная лабораторная работа является первым практическим заданием в рамках курса "COURSE-16: Основы IoT для инженеров автоматизации". Цель работы — закрепить на практике базовые знания об экосистеме Интернета вещей (IoT), её ключевых компонентах и концепциях. Вы научитесь идентифицировать элементы системы, применять стандартный формат данных для телеметрии и спроектируете свой первый поток для симуляции данных с устройства на платформе контроллера HI.

Цели обучения: Оборудование и программное обеспечение: Критерии выполнения и сдачи:

Работа считается выполненной при предоставлении единого файла в формате Markdown (`.md`), содержащего:

  • Ответы на задания из теоретической части.
  • Скриншоты и экспортированный JSON-код потока для каждого этапа практической работы.
  • Соответствие всем пунктам в рубрике оценивания.
  • ---

    Часть 1: Теоретическая подготовка и анализ

    Перед началом практической работы необходимо продемонстрировать понимание ключевых концепций. Выполните следующие задания.

    Задание 1.1: Идентификация компонентов системы

    Сопоставьте компоненты платформы HI из первого списка с их основными функциями в рамках экосистемы IoT из второго списка.

    Компоненты платформы HI:
  • Универсальный вход контроллера (UI), настроенный как "сухой контакт" и подключенный к настенному выключателю.
  • Релейный выход контроллера (RELAY), управляющий питанием группы розеток.
  • Программный сценарий в Node-RED, реализующий логику климат-контроля (FLOW-CLIMATE-001).
  • Датчик температуры DS18B20, подключенный к шине 1-Wire.
  • Функции: Формат ответа: Предоставьте сопоставление в виде `1-C, 2-B, ...`.

    Задание 1.2: Анализ телеметрии и работа с данными

    Представьте, что вы анализируете данные, поступающие с двух универсальных входов (UI) контроллера HI, к которым подключены датчики температуры в разных помещениях.

    | Идентификатор входа | Среднее значение за час (°C) | Максимальное пиковое значение (°C) |

    | :--- | :--- | :--- |

    | UI-05 (Гостиная) | 22.5 | 24.0 |

    | UI-06 (Спальня) | 21.0 | 21.5 |

    Вопросы:
  • Какой тип физического датчика, совместимого с универсальным входом контроллера HI, вероятнее всего используется для получения этих данных (например, NTC-термистор, PT1000)?
  • Напишите пример JSON-объекта, который представляет одно измерение от датчика в гостиной (`UI-05`) в соответствии со стандартным "контрактом сообщения" Академии HI. Используйте текущую временную метку (timestamp).
  • Задание 1.3: Практическое применение IoT

    Опираясь на возможности контроллера HI (22 универсальных входа, 22 релейных выхода, поддержка Modbus, DALI, Node-RED), опишите в 50-100 словах, как его установка в загородном доме может повысить комфорт и безопасность жильцов. Приведите 2-3 конкретных примера сценариев автоматизации (например, `SCN-LIGHT-005`, `SCN-SAFETY-011`).

    Задание 1.4: Оценка нагрузки на сеть (трафик)

    Инженер проектирует систему мониторинга для небольшого складского комплекса. Система включает 100 Modbus-датчиков, опрашиваемых контроллером HI. Контроллер агрегирует данные и отправляет их на центральный сервер каждый час. Размер пакета данных от одного датчика составляет 128 байт.

  • Рассчитайте, какой общий объем данных (в килобайтах) будет передан на сервер за одни сутки (24 часа).
  • Какой протокол (MQTT или HTTP POST) будет более эффективным для такой задачи и почему? (Краткий ответ, 1-2 предложения).
  • ---

    Часть 2: Практическая работа в Node-RED

    В этой части вы создадите и настроите свой первый поток в Node-RED, который пройдет два этапа: от простой симуляции до внедрения механизмов отказоустойчивости.

    Этап 1: Симуляция датчика и отправка данных

    Цель: Научиться создавать базовые потоки, генерировать данные, форматировать их согласно "контракту сообщения" и публиковать в MQTT. Требования к потоку:
  • Генерация данных: Использовать узел `Inject` для периодической отправки сообщения каждые 5 секунд.
  • Эмуляция датчика: Использовать узел `Function` для генерации случайного значения температуры в диапазоне от 20.0 до 25.0 °C.
  • Форматирование сообщения: В узле `Function` сформировать `msg.payload` в соответствии со стандартным "контрактом сообщения" Академии HI.
  • Публикация в MQTT: Использовать узел `mqtt out` для публикации сообщения в топик `telemetry/lab01/temperature`.
  • Визуальный статус: Настроить узел `Function` так, чтобы он отображал текущее сгенерированное значение температуры в своем статусе, применяя паттерн "Визуальный статус".
  • ASCII-схема потока:
    [Inject] --(payload: timestamp)--> [Function: Generate & Format Temp] --(msg.payload)--> [mqtt out: telemetry/lab01/temperature]
    

    |

    +-----------------------------------------------------> [Debug: msg.payload]

    Шаги выполнения:
  • Откройте Node-RED в вашем браузере (обычно `http://:1880`).
  • Перетащите на рабочую область узлы `Inject`, `Function`, `mqtt out` и `Debug`. Соедините их, как показано на схеме.
  • Настройте узел `Inject`:
  • * `Payload`: `timestamp`

    * `Repeat`: `interval` every `5` seconds

    * `Name`: "Каждые 5 секунд"

  • Настройте узел `Function`:
  • * `Name`: "Генератор температуры"

    * Вставьте следующий код:

            // Генерируем случайное значение температуры от 20.0 до 25.0

    let temperature = (Math.random() * 5 + 20).toFixed(1);

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

    msg.payload = {

    value: parseFloat(temperature), // Преобразуем в число

    unit: "°C",

    source: "virtual-temp-sensor-lab01",

    ts: Date.now() // Текущая временная метка в миллисекундах

    };

    // Обновляем визуальный статус узла (Паттерн "Визуальный статус")

    node.status({fill:"green", shape:"dot", text:`OK: ${temperature} °C`});

    return msg;

  • Настройте узел `mqtt out`:
  • * `Server`: Выберите или добавьте MQTT-брокер (обычно `localhost:1883` для контроллера HI).

    * `Topic`: `telemetry/lab01/temperature`

    * `QoS`: `0`

    * `Name`: "Отправить в MQTT"

  • Настройте узел `Debug`:
  • * `Output`: `msg.payload`

    * `Name`: "Проверка данных"

  • Нажмите кнопку `Deploy` (Развернуть).
  • Откройте вкладку `Debug` и убедитесь, что JSON-сообщения появляются каждые 5 секунд.
  • Откройте MQTT Explorer, подпишитесь на топик `telemetry/lab01/temperature` и убедитесь, что вы получаете сообщения.
  • Результат этапа:

    ---

    Этап 2: Внедрение валидации и обработки ошибок

    Цель: Усложнить поток, добавив симуляцию ошибок и реализовав паттерны "Контракт сообщения" (валидация) и "Обработка ошибок" для создания отказоустойчивой логики. Требования к потоку:
  • Введение ошибок: Модифицировать узел `Function: Генератор температуры` так, чтобы с вероятностью 20% он генерировал некорректные данные (например, `NaN` или значение вне допустимого диапазона).
  • Валидация данных: Добавить новый узел `Function` ("Валидатор"), который будет проверять `msg.payload` на полное соответствие контракту. При несоответствии узел должен вызывать ошибку (`node.error()`) и останавливать поток.
  • Обработка ошибок: Добавить узел `Catch`, который будет перехватывать ошибки от узла валидации и выводить их в отдельный узел `Debug` для логирования.
  • ASCII-схема потока:
                                                                          +--> [mqtt out]
    

    |

    [Inject] --> [Function: Generate Temp (with errors)] --> [Function: Validate Data] --+

    | +--> [Debug: Valid Data]

    v (on error)

    [Catch: All Nodes] --> [Debug: Error Log]

    Шаги выполнения:
  • Откройте ваш поток из Этапа 1.
  • Модифицируйте узел `Function: Генератор температуры`:
  •     let temperature;

    // 20% вероятность генерации некорректных данных

    if (Math.random() < 0.2) {

    temperature = (Math.random() < 0.5) ? "invalid_string" : 99.0; // Некорректный тип или значение вне диапазона

    } else {

    temperature = (Math.random() * 5 + 20).toFixed(1);

    }

    msg.payload = {

    value: typeof temperature === 'string' ? temperature : parseFloat(temperature),

    unit: "°C",

    source: "virtual-temp-sensor-lab01",

    ts: Date.now()

    };

    node.status({fill:"blue", shape:"dot", text:`Generated: ${temperature}`});

    return msg;

  • Добавьте новый узел `Function` после `Генератора температуры` и назовите его "Валидатор данных". Вставьте код:
  •     const payload = msg.payload;

    const { value, unit, source, ts } = payload;

    // Проверка контракта: тип и диапазон значения

    if (typeof value !== 'number' || isNaN(value) || value < 0 || value > 50) {

    node.status({fill:"red", shape:"dot", text:`ERROR: Invalid value (${value})`});

    node.error(`Contract violation: Invalid temperature value: ${value}`, msg);

    return null; // Останавливаем поток

    }

    // Другие проверки контракта (наличие полей, типы и т.д.)

    if (!unit || !source || !ts) {

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

    node.error("Contract violation: Missing required fields", msg);

    return null;

    }

    // Если все проверки пройдены

    node.status({fill:"green", shape:"dot", text:`OK: ${value} °C`});

    return msg; // Передаем валидное сообщение дальше

  • Добавьте узел `Catch`. В его настройках выберите `All nodes`.
  • Добавьте новый узел `Debug` и назовите его "Лог ошибок". Подключите к нему выход узла `Catch`. Настройте вывод на `complete msg object` для получения полной информации об ошибке.
  • Переименуйте существующий узел `Debug` в "Валидные данные".
  • Нажмите `Deploy`.
  • Наблюдайте за вкладкой `Debug`. Вы должны видеть как валидные сообщения в одном отладчике, так и сообщения об ошибках (перехваченные узлом `Catch`) в другом.
  • Результат этапа:

    ---

    Рубрика оценивания и чек-лист для самопроверки

    | Критерий | Макс. балл | Описание | Ваш чек-лист |

    | :--- | :--- | :--- | :--- |

    | Часть 1: Теория | 20 | Даны полные и корректные ответы на все вопросы (1.1 - 1.4). | `[ ]` |

    | Этап 1: Базовый поток | 30 | Поток создан согласно схеме. Данные генерируются и отправляются в MQTT в правильном формате. Статус узла отображается. | `[ ]` |

    | Этап 2: Поток с обработкой ошибок | 30 | Поток модифицирован, включает генерацию ошибок, узел валидации и узел `Catch`. Ошибки корректно перехватываются и логируются. | `[ ]` |

    | Документация и сдача | 20 | Предоставлены все требуемые скриншоты (поток, `Debug`, MQTT Explorer) и JSON-коды для обоих этапов. Файл оформлен в формате Markdown. | `[ ]` |

    | Итого | 100 | | |

    ---

    Мини-runbook: Диагностика проблем

    Этот раздел поможет вам диагностировать и устранить наиболее распространенные проблемы при выполнении данной лабораторной работы.

    Проблема 1: Поток Node-RED не отправляет сообщения. 1. Нажата ли кнопка `Deploy` после последних изменений?

    2. Узел `Inject` настроен на периодический запуск и активирован (не "disabled")?

    3. Все узлы соединены линиями связи согласно схеме?

    4. Нет ли красных треугольников над узлами, сигнализирующих об ошибке конфигурации?

    Проблема 2: Сообщения не появляются в MQTT Explorer. 1. Запущен ли MQTT-брокер на контроллере? (Проверить в терминале: `sudo systemctl status mosquitto`).

    2. В узле `mqtt out` указан правильный адрес брокера (`localhost` или IP контроллера) и порт (`1883`)?

    3. В MQTT Explorer вы подключены к тому же брокеру?

    4. В MQTT Explorer вы подписаны на правильный топик (`telemetry/lab01/temperature`)? ⚠️ Попробуйте подписаться на `#` для отладки, чтобы увидеть все сообщения.

    Проблема 3: Узел `Catch` не перехватывает ошибки. 1. Узел `Catch` настроен на перехват со всех узлов (`Scope: All nodes`)?

    2. Узел-валидатор действительно вызывает ошибку с помощью `node.error("Сообщение", msg);`? (Вызов `node.warn()` или возврат `null` не генерируют ошибку для `Catch`).

    Проблема 4: Визуальный статус узла не обновляется. 1. В коде узла `Function` присутствует вызов `node.status({fill:"...", shape:"...", text:"..."});`?

    2. Сообщения вообще доходят до этого узла? (Подключите к его входу узел `Debug`).