Главная → Академия → Основы Интернета вещей и практическое применение → Создание базового прототипа: от датчика до панели мониторинга

Создание базового прототипа: от датчика до панели мониторинга

COURSE-16-M07-LAB02 — Создание базового прототипа: от датчика до панели мониторинга

Введение

Данная лабораторная работа является ключевой в курсе Foundation. На этом этапе вы перейдете от теории к практике и создадите законченный, хотя и простой, контур системы мониторинга на базе контроллера HI. Вы научитесь физически подключать периферийное устройство, создавать логику его опроса в среде Node-RED, передавать данные по стандартному протоколу MQTT и визуализировать их на панели оператора.

Успешное выполнение этой работы подтвердит ваше умение работать с полным стеком технологий платформы HI: от физического уровня (подключение датчика) до уровня представления данных (дашборд).

Цели лабораторной работы

По завершении этой работы инженер сможет:

  • Физически подключить датчик температуры DS18B20 к универсальному входу контроллера HI, соблюдая стандарт цветового кодирования и правила монтажа.
  • Создать поток (flow) в Node-RED для периодического считывания данных с датчика 1-Wire, используя специализированный узел.
  • Реализовать паттерн "Контракт сообщения", преобразуя сырые данные в стандартизированный JSON-объект с обязательными полями (`value`, `source`, `ts`, `unit`).
  • Применить паттерн "Визуальный статус" для отображения состояния узла и актуальных показаний датчика непосредственно в редакторе Node-RED.
  • Опубликовать обработанные и валидированные данные в локальный MQTT-брокер, используя иерархическую структуру топиков для масштабируемости.
  • Создать простую панель мониторинга (dashboard) для отображения полученных данных в виде графика или прибора, корректно извлекая значения из JSON-сообщения.
  • Внедрить базовую обработку ошибок с использованием узла `Catch` для повышения надежности системы.

Необходимое оборудование и ПО

  • Контроллер HI: Любая модель контроллера HI с предустановленной операционной системой Linux (Debian) и средой Node-RED. Доступ к веб-интерфейсу Node-RED по адресу `http://:1880`.
  • Датчик температуры: DS18B20 (в любом корпусе, например, TO-92 или водонепроницаемый).
  • Кабель: Трехжильный кабель (например, ПВС 3х0.75 или аналогичный) длиной 1-2 метра.
  • Инструменты: Инструмент для зачистки проводов, отвертка (шлицевая или крестовая, в зависимости от типа клемм контроллера).
  • Программное обеспечение:
* Установленная палитра `node-red-dashboard` в Node-RED (если не установлена, см. Шаг 4).

* Установленная палитра для работы с 1-Wire датчиками (например, `node-red-contrib-ds18b20-sensor` или `node-red-contrib-rpi-ds18b20`). В стандартной сборке HI она обычно предустановлена.

* (Опционально) MQTT-клиент для ПК (например, MQTT Explorer) для проверки публикации сообщений.

---

Шаг 1: Физическое подключение датчика

На этом шаге мы подключим датчик температуры DS18B20 к одному из универсальных входов (UI) контроллера HI. Эти входы поддерживают протокол 1-Wire.

  • Подготовка кабеля: Зачистите концы трехжильного кабеля примерно на 5-7 мм. Для многожильных проводов рекомендуется использовать наконечники НШВИ.
  • Подключение к датчику: Датчики DS18B20 обычно имеют три вывода: VCC (питание), GND (земля) и Data (данные). Подключите провода к датчику согласно следующему цветовому кодированию, соответствующему стандарту Академии HI:
  • * Красный: VCC (+3.3V или +5V, в зависимости от модели контроллера HI и его универсальных входов).

    * Черный: GND (общий провод).

    * Желтый: Data (линия данных 1-Wire).

  • Подключение к контроллеру: Подключите другие концы кабеля к клеммной колодке одного из универсальных входов, например, UI-01. Контроллер HI обеспечивает питание и подтягивающий резистор для 1-Wire, поэтому внешние компоненты не требуются.
  • * Красный провод (VCC): Подключите к клемме `+3.3V` или `+5V` контроллера (уточните по документации контроллера HI).

    * Черный провод (GND): Подключите к клемме `GND` рядом с UI-01.

    * Желтый провод (Data): Подключите к сигнальной клемме `UI-01`.

    Схема подключения (WIRING-SENS-011)

    //======= WIRING-SENS-011: Подключение датчика DS18B20 к UI-01 =======
    
    

    [CTRL:HI-Core] (SENS:DS18B20-001)

    Клеммная колодка UI-01

    +3.3V ------ (Красный) -------------------- VCC

    UI-01 ------ (Желтый) --------------------- Data

    GND ------ (Черный) -------------------- GND

    // Легенда:

    // CTRL:HI-Core - Контроллер HI

    // SENS:DS18B20-001 - Датчик температуры DS18B20

    //

    // Примечание: Контроллер HI обеспечивает необходимый подтягивающий резистор

    // для шины 1-Wire. Внешний резистор не требуется.

    // Убедитесь, что универсальный вход UI-01 сконфигурирован для работы с 1-Wire.

    📋 Чек-лист проверки подключения:

    • [ ] Провода надежно зафиксированы в клеммах контроллера и датчика.
    • [ ] Цветовое кодирование проводников строго соблюдено согласно стандарту Академии HI (Красный: VCC, Черный: GND, Желтый: Data).
    • [ ] Отсутствуют оголенные участки проводов, способные вызвать короткое замыкание или контакт с другими элементами.
    • [ ] Для многожильных проводов использованы наконечники НШВИ.
    • [ ] Выбранный универсальный вход (UI-01) сконфигурирован в системных настройках контроллера HI для работы в режиме 1-Wire (обычно это делается автоматически или через веб-интерфейс настроек контроллера).

    ---

    Шаг 2: Создание потока Node-RED для сбора данных

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

  • Откройте редактор Node-RED в вашем браузере (`http://:1880`).
  • Создайте новую вкладку (flow) и назовите ее «Мониторинг температуры».
  • Перетащите на холст следующие узлы: `Inject`, `ds18b20-sensor` (или аналогичный для 1-Wire), `Function`, `Catch` и `Debug`.
  • ASCII-схема потока (FLOW-SENS-TEMP-001)

    // FLOW-SENS-TEMP-001: Сбор и обработка данных с датчика DS18B20
    
    

    +----------+ +---------------------------+ +---------------------------+ +---------+

    [Inject] -> | ds18b20 | -> | Function: | -> | mqtt out | -> | Debug |

    | (1-Wire) | | Validate & Format | | (telemetry/lab/room01/...) | | (msg.payload) |

    +----------+ +---------------------------+ +---------------------------+ +---------+

    |

    | (ошибки от всех узлов на этой вкладке)

    v

    +----------+ +---------------------------+ +---------------------------+

    | Catch | -> | Function: | -> | Debug |

    | (All) | | Format Error | | (msg.error) |

    +----------+ +---------------------------+ +---------------------------+

    Настройка узлов:

  • Узел `Inject` (Запуск опроса):
  • * `Payload`: `timestamp` (текущее время).

    * `Topic`: `poll_temperature`.

    * `Repeat`: `interval` с интервалом `10 секунд`. Это будет инициировать опрос каждые 10 секунд.

    * `Name`: `Опрос датчика (10с)`.

  • Узел `ds18b20-sensor` (Чтение датчика):
  • * `1-Wire Device ID`: Укажите ID вашего датчика. Обычно он имеет формат `28-xxxxxxxxxxxx`. Если вы не знаете ID, оставьте поле пустым — узел попытается найти первый доступный датчик.

    * `Name`: `Читать температуру с UI-01`.

    * Паттерн "Визуальный статус": Узел `ds18b20-sensor` обычно сам отображает статус (например, "OK" или "Error").

  • Узел `Function` (Валидация, форматирование и статус):
  • * `Name`: `Контракт и Статус`.

    * `Outputs`: 1.

    * Вставьте следующий код. Он реализует два важнейших паттерна: "Контракт сообщения" и "Визуальный статус".

        // COURSE-16-M07-LAB02: Function - Контракт и Статус

    // Получаем сырое значение температуры из msg.payload

    let temp = parseFloat(msg.payload);

    // 1. ВАЛИДАЦИЯ ДАННЫХ (Паттерн "Обработка ошибок")

    // Проверяем, что значение является числом и находится в разумном диапазоне для DS18B20

    if (isNaN(temp) || temp < -55 || temp > 125) {

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

    node.status({ fill: "red", shape: "dot", text: "Ошибка чтения: " + msg.payload });

    // Генерируем ошибку, которую поймает узел Catch

    node.error("Некорректное значение температуры: " + msg.payload + " (Source: " + msg.topic + ")", msg);

    return null; // Останавливаем дальнейшее движение сообщения по успешной ветке

    }

    // 2. ПАТТЕРН "КОНТРАКТ СООБЩЕНИЯ"

    // Формируем стандартный JSON-объект для msg.payload

    msg.payload = {

    "value": temp,

    "source": "DS18B20-UI01-28-01234567abcd", // 💡 Замените на реальный ID вашего датчика и UI

    "ts": Date.now(), // Временная метка в миллисекундах Unix epoch

    "unit": "°C",

    "meta": {

    "location": "lab_room_01",

    "sensor_type": "DS18B20",

    "connection_type": "1-Wire"

    }

    };

    // 3. ПАТТЕРН "ВИЗУАЛЬНЫЙ СТАТУС"

    // Отображаем актуальное значение и статус "ОК"

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

    // Возвращаем преобразованное сообщение для следующего узла

    return msg;

  • Узел `Catch` (Обработка ошибок):
  • * `Name`: `Перехват ошибок`.

    * `Catch messages from`: `all nodes on this flow`.

    * Соедините выход узла `Catch` со входом следующего узла `Function`.

  • Узел `Function` (Форматирование ошибки):
  • * `Name`: `Форматировать ошибку`.

    * `Outputs`: 1.

    * Код:

            // COURSE-16-M07-LAB02: Function - Форматировать ошибку

    // Паттерн "Контракт сообщения" для ошибок

    let errorMsg = {

    "error_type": "Node-RED Error",

    "message": msg.error.message,

    "node_id": msg.error.node.id,

    "node_name": msg.error.node.name,

    "flow_id": msg.error.flow.id,

    "original_payload": msg.payload, // Оригинальное сообщение, вызвавшее ошибку

    "ts": Date.now()

    };

    msg.payload = errorMsg;

    msg.topic = "system/errors/temperature_sensor"; // Топик для ошибок

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

    node.status({ fill: "red", shape: "dot", text: `Error: ${msg.error.message.substring(0, 20)}...` });

    return msg;

  • Узел `Debug` (Отладка ошибок):
  • * `Output`: `complete msg object`.

    * `Name`: `Отладка ошибок`.

    * Подключите к выходу узла `Function: Форматировать ошибку`.

    Разверните (Deploy) поток. Каждые 10 секунд в панели отладки вы должны видеть структурированное сообщение с температурой, а под узлом `Function: Контракт и Статус` — зеленый статус с текущей температурой. Если возникнет ошибка (например, вы отключите датчик), она будет перехвачена узлом `Catch` и отображена в панели отладки через `Debug: Отладка ошибок`.

    ---

    Шаг 3: Интеграция с MQTT

    Теперь, когда у нас есть чистые, стандартизированные и валидированные данные, опубликуем их в MQTT. Это позволит другим системам (или нашему дашборду) использовать эти данные, не завися от логики их сбора.

  • Добавьте на холст узел `mqtt out`.
  • Соедините выход узла `Function: Контракт и Статус` со входом узла `mqtt out`.
  • Настройка узла `mqtt out`:

    • Server: Нажмите на иконку карандаша для настройки брокера.
    * `Name`: `Локальный брокер HI`

    * `Server`: `localhost` (или `127.0.0.1`)

    * `Port`: `1883`

    * `Client ID`: `hi_controller_temp_publisher` (уникальный ID для клиента)

    * Остальные настройки оставьте по умолчанию. Нажмите `Add`.

    • Topic: Укажите топик в соответствии с иерархическим стандартом Академии HI. Это критически важно для масштабируемых систем.
    `telemetry/lab/room01/temperature`
    • QoS: `1` - At least once. Гарантирует доставку сообщения хотя бы один раз.
    • Retain: `false`. (Если `true`, брокер будет хранить последнее сообщение и отправлять его новым подписчикам).
    • Name: `Публикация температуры в MQTT`.
    • Паттерн "Визуальный статус": Узел `mqtt out` будет отображать статус подключения к брокеру (зеленый - подключен, красный - отключен).

    Разверните поток. Теперь данные с датчика не только выводятся в отладку, но и публикуются в MQTT-брокере на контроллере. Вы можете использовать MQTT Explorer на ПК для проверки публикации сообщений в топик `telemetry/lab/room01/temperature`.

    ---

    Шаг 4: Визуализация данных на дашборде

    Последний шаг — создание простого интерфейса для наблюдения за температурой в реальном времени.

    💡 Совет: Для наглядности и лучшей организации создайте для дашборда отдельную вкладку (flow) с названием «Дашборд».

  • Убедитесь, что у вас установлена палитра `node-red-dashboard`. Если нет, установите ее через `Menu -> Manage palette -> Install`. После установки перезагрузите Node-RED.
  • На новой вкладке разместите узлы `mqtt in` и `ui_gauge` (Прибор).
  • Настройка узлов:

  • Узел `mqtt in` (Подписка на данные):
  • * Server: Выберите ранее настроенный `Локальный брокер HI`.

    * Topic: `telemetry/lab/room01/temperature` (тот же топик, в который мы публикуем данные).

    * Action: `Subscribe`.

    * QoS: `1`.

    * Output: `a parsed JSON object`. Это важно, так как мы отправляем JSON-объект, и Node-RED должен его распарсить.

    * Name: `Подписка на температуру`.

    * Паттерн "Визуальный статус": Узел `mqtt in` будет отображать статус подключения к брокеру.

  • Узел `ui_gauge` (Визуальный прибор):
  • * Group: Нажмите на карандаш, чтобы создать новую группу на дашборде.

    * `Name`: `Мониторинг`.

    * `Tab`: Нажмите на карандаш, чтобы создать вкладку. `Name`: `Главная`. Нажмите `Add`, затем `Add`.

    * Type: `Gauge`.

    * Label: `Температура в серверной`.

    * Value format: `{{msg.payload.value | number:1}}`. Эта формула извлекает поле `value` из нашего JSON-контракта и форматирует его до одного знака после запятой.

    * Units: `°C`.

    * Range: Установите диапазон, например, от `0` до `50`.

    * Name: `Прибор температуры`.

    Дашборд доступен по адресу http://:1880/ui после развертывания потока и соединения выхода mqtt in с входом ui_gauge.

    Чтобы увидеть результат, откройте новую вкладку в браузере по адресу `http://:1880/ui`. Вы должны увидеть прибор, показывающий текущую температуру, которая обновляется каждые 10 секунд.

    ---

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

    ⚠️ Если вы столкнулись с проблемой, выполните диагностику по шагам:

  • Проблема: Узел `ds18b20-sensor` выдает ошибку или `null`, или не отображает статус.
  • * Диагностика:

    * Физическое подключение: Проверьте физическое подключение датчика. Не перепутаны ли провода `Data`, `GND`, `VCC`? Надежно ли они зажаты в клеммах?

    * Конфигурация UI: Убедитесь, что выбранный универсальный вход (UI-01) сконфигурирован в системных настройках контроллера HI для работы в режиме 1-Wire.

    * ID датчика: Если вы указали конкретный ID в узле `ds18b20-sensor`, убедитесь, что он верен. Попробуйте оставить поле `1-Wire Device ID` пустым, чтобы узел попытался найти первый доступный датчик.

    * Решение: Перепроверьте схему подключения `WIRING-SENS-011`. Попробуйте подключить датчик к другому универсальному входу. Проверьте логи системного журнала контроллера на наличие ошибок, связанных с 1-Wire.

  • Проблема: Узел `Function: Контракт и Статус` выдает ошибку или не формирует корректный JSON.
  • * Диагностика:

    * Входящие данные: Подключите узел `Debug` к выходу узла `ds18b20-sensor` и проверьте, какие данные он передает в `Function`. Должно быть число.

    * Код Function: Внимательно проверьте код узла `Function` на опечатки, особенно в строках `parseFloat(msg.payload)` и формировании JSON-объекта.

    * ID датчика: Убедитесь, что вы заменили `28-01234567abcd` на реальный ID вашего датчика в поле `source` JSON-контракта.

    * Решение: Исправьте код. Используйте `Debug` для пошаговой отладки.

  • Проблема: Данные не появляются в MQTT (проверить можно с помощью утилиты `mqtt-explorer`).
  • * Диагностика:

    * Статус `mqtt out`: Проверьте статус узла `mqtt out`. Если под ним красный квадрат и надпись "disconnected", значит, есть проблема с подключением к брокеру.

    * Настройки брокера: Откройте настройки узла `mqtt out` и проверьте параметры сервера: `localhost`, порт `1883`.

    * Запущен ли брокер: Убедитесь, что MQTT-брокер (например, Mosquitto) запущен на контроллере HI. Проверить можно командой `sudo systemctl status mosquitto` в терминале контроллера.

    * Топик: Убедитесь, что топик в `mqtt out` (`telemetry/lab/room01/temperature`) совпадает с тем, на который вы подписываетесь в `mqtt-explorer`.

    * Решение: Запустите брокер, если он неактивен. Исправьте настройки подключения.

  • Проблема: На дашборде (`http://:1880/ui`) пусто или прибор показывает `NaN` или `undefined`.
  • * Диагностика:

    Топик `mqtt in`: Убедитесь, что топик в узле `mqtt in` в точности* совпадает с топиком в узле `mqtt out`.

    * Парсинг JSON: Проверьте, что в узле `mqtt in` выбрано `Output: a parsed JSON object`.

    * Формат значения: Проверьте поле `Value format` в узле `ui_gauge`. Оно должно быть `{{msg.payload.value | number:1}}`. Если вы просто оставите `{{payload}}`, узел попытается отобразить весь JSON-объект, что приведет к ошибке.

    * Данные в `Debug`: Подключите узел `Debug` после узла `mqtt in` на вкладке дашборда, чтобы увидеть, какие данные приходят из MQTT и в каком формате.

    * Решение: Исправьте настройки в соответствии с диагностикой.

    ---

    Рубрика оценивания лабораторной работы

    | Критерий | 0 баллов (Не выполнено) | 1 балл (Базово) | 2 балла (Отлично) |

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

    | Физическое подключение | Датчик не подключен или подключен неверно. | Датчик подключен и работает, но с нарушением цветового кода или неаккуратно. | Датчик подключен аккуратно, в соответствии со схемой `WIRING-SENS-011` и стандартом цветового кодирования. |

    | Поток сбора данных | Поток не считывает данные или вызывает постоянные ошибки. | Поток считывает данные, но без валидации и обработки ошибок. | Поток стабильно считывает данные, включает валидацию, использует узел `Function` и `Catch` для обработки ошибок. |

    | Контракт сообщения | Данные передаются в сыром виде (строка/число). | Данные обернуты в JSON, но структура неполная (например, отсутствует `ts` или `source`). | Данные полностью соответствуют стандартизированному JSON-контракту (`value`, `source`, `ts`, `unit`, `meta`). |

    | Визуальный статус | Паттерн "Визуальный статус" не используется или используется неэффективно. | Статус отображается, но неинформативен (например, просто "OK"). | Узлы `Function` и `ds18b20-sensor` отображают информативный статус (значение, состояние, ошибки). |

    | Интеграция с MQTT | Данные не публикуются в MQTT. | Данные публикуются, но в плоский топик (например, `temp`) или с QoS 0. | Данные публикуются в иерархический топик (`telemetry/...`) с QoS 1. |

    | Визуализация на дашборде | Дашборд не создан или не отображает данные. | Дашборд отображает данные, но без форматирования (например, много знаков после запятой) или с ошибками. | Дашборд корректно отображает отформатированные данные, имеет осмысленные подписи и единицы измерения, корректно парсит JSON. |

    Итоговая оценка: Сумма баллов по всем критериям. Максимум: 12 баллов.

    Тест для самопроверки (COURSE-16-M07-QUIZ)

  • Какой протокол используется для связи с датчиком DS18B20?
  • * A) Modbus

    * B) I2C

    * C) 1-Wire

    * D) CAN

  • Какую функцию выполняет узел `Function` с кодом валидации и форматирования в созданном потоке?
  • * A) Только запуск опроса по таймеру.

    * B) Валидацию данных, приведение их к стандартному JSON-формату и отображение визуального статуса.

    * C) Непосредственное чтение данных с физического входа.

    * D) Отображение данных на дашборде.

  • Что означает `localhost` в настройках MQTT-брокера?
  • * A) Адрес удаленного облачного сервера.

    * B) IP-адрес вашего компьютера.

    * C) Указание на то, что брокер запущен на этом же устройстве (контроллере HI).

    * D) Имя Wi-Fi сети.

  • Какова цель использования иерархических топиков в MQTT (например, `telemetry/lab/room01/temperature`)?
  • * A) Это требование протокола MQTT.

    * B) Для красоты.

    * C) Для логической структуризации данных, гибкой подписки на группы данных и масштабируемости системы.

    * D) Для увеличения скорости передачи.

  • Что делает выражение `{{msg.payload.value | number:1}}` в настройках узла `ui_gauge`?
  • * A) Извлекает поле `value` из объекта `msg.payload` и форматирует его как число с 1 знаком после запятой.

    * B) Умножает значение на 1.

    * C) Отправляет значение в базу данных.

    * D) Проверяет, является ли значение числом.

  • Что произойдет, если в узле `mqtt in` выбрать `Output: a string` вместо `a parsed JSON object`?
  • * A) Ничего, все будет работать как прежде.

    * B) Узел `ui_gauge` получит строку вместо объекта и не сможет извлечь поле `value`, что приведет к ошибке `NaN` или `undefined`.

    * C) Скорость обновления дашборда увеличится.

    * D) Сообщение не будет получено из MQTT.

  • Какую проблему решает паттерн "Визуальный статус" (`node.status`)?
  • * A) Позволяет видеть состояние узла и ключевые данные прямо в редакторе Node-RED без открытия панели отладки.

    * B) Сохраняет данные в EEPROM.

    * C) Отправляет email с ошибкой.

    * D) Рисует график на дашборде.

  • Зачем нужен узел `Catch` в потоке?
  • * A) Для ловли рыбы.

    * B) Для перехвата и централизованной обработки ошибок, возникающих в других узлах на данной вкладке.

    * C) Для кэширования сообщений.

    * D) Для запуска потока по расписанию.

  • Какой параметр в узле `Inject` заставляет его срабатывать периодически?
  • * A) `Payload`

    * B) `Topic`

    * C) `Repeat`

    * D) `Name`

  • Что такое "Контракт сообщения" в контексте Node-RED?
  • * A) Юридический документ.

    * B) Соглашение о стандартной и предсказуемой структуре данных (например, JSON), передаваемых между узлами, для обеспечения надежности и масштабируемости.

    * C) Название прошивки контроллера.

    * D) Алгоритм шифрования.

    ---

    Заключение

    Поздравляем! Вы успешно создали свой первый полноценный IoT-прототип на платформе HI. Вы прошли весь путь от физического подключения оборудования до визуализации данных, применив на практике ключевые паттерны и технологии: 1-Wire, Node-RED, JSON, MQTT и Dashboard.

    На следующих этапах вы будете усложнять эту базовую систему: добавлять управление исполнительными устройствами (реле), интегрировать другие протоколы (Modbus), настраивать более сложную логику и сохранять данные в базу данных MySQL для последующего анализа.