Создание базового прототипа: от датчика до панели мониторинга
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 метра.
- Инструменты: Инструмент для зачистки проводов, отвертка (шлицевая или крестовая, в зависимости от типа клемм контроллера).
- Программное обеспечение:
* Установленная палитра для работы с 1-Wire датчиками (например, `node-red-contrib-ds18b20-sensor` или `node-red-contrib-rpi-ds18b20`). В стандартной сборке HI она обычно предустановлена.
* (Опционально) MQTT-клиент для ПК (например, MQTT Explorer) для проверки публикации сообщений.
---
Шаг 1: Физическое подключение датчика
На этом шаге мы подключим датчик температуры DS18B20 к одному из универсальных входов (UI) контроллера HI. Эти входы поддерживают протокол 1-Wire.
* Красный: VCC (+3.3V или +5V, в зависимости от модели контроллера HI и его универсальных входов).
* Черный: GND (общий провод).
* Желтый: Data (линия данных 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 для сбора данных
Теперь создадим логику, которая будет опрашивать датчик, обрабатывать его показания и обеспечивать базовую обработку ошибок.
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) |
+----------+ +---------------------------+ +---------------------------+
Настройка узлов:
* `Payload`: `timestamp` (текущее время).
* `Topic`: `poll_temperature`.
* `Repeat`: `interval` с интервалом `10 секунд`. Это будет инициировать опрос каждые 10 секунд.
* `Name`: `Опрос датчика (10с)`.
* `1-Wire Device ID`: Укажите ID вашего датчика. Обычно он имеет формат `28-xxxxxxxxxxxx`. Если вы не знаете ID, оставьте поле пустым — узел попытается найти первый доступный датчик.
* `Name`: `Читать температуру с UI-01`.
* Паттерн "Визуальный статус": Узел `ds18b20-sensor` обычно сам отображает статус (например, "OK" или "Error").
* `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;
* `Name`: `Перехват ошибок`.
* `Catch messages from`: `all nodes on this flow`.
* Соедините выход узла `Catch` со входом следующего узла `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;
* `Output`: `complete msg object`.
* `Name`: `Отладка ошибок`.
* Подключите к выходу узла `Function: Форматировать ошибку`.
Разверните (Deploy) поток. Каждые 10 секунд в панели отладки вы должны видеть структурированное сообщение с температурой, а под узлом `Function: Контракт и Статус` — зеленый статус с текущей температурой. Если возникнет ошибка (например, вы отключите датчик), она будет перехвачена узлом `Catch` и отображена в панели отладки через `Debug: Отладка ошибок`.
---
Шаг 3: Интеграция с MQTT
Теперь, когда у нас есть чистые, стандартизированные и валидированные данные, опубликуем их в MQTT. Это позволит другим системам (или нашему дашборду) использовать эти данные, не завися от логики их сбора.
Настройка узла `mqtt out`:
- Server: Нажмите на иконку карандаша для настройки брокера.
* `Server`: `localhost` (или `127.0.0.1`)
* `Port`: `1883`
* `Client ID`: `hi_controller_temp_publisher` (уникальный ID для клиента)
* Остальные настройки оставьте по умолчанию. Нажмите `Add`.
- Topic: Укажите топик в соответствии с иерархическим стандартом Академии HI. Это критически важно для масштабируемых систем.
- QoS: `1` - At least once. Гарантирует доставку сообщения хотя бы один раз.
- Retain: `false`. (Если `true`, брокер будет хранить последнее сообщение и отправлять его новым подписчикам).
- Name: `Публикация температуры в MQTT`.
- Паттерн "Визуальный статус": Узел `mqtt out` будет отображать статус подключения к брокеру (зеленый - подключен, красный - отключен).
Разверните поток. Теперь данные с датчика не только выводятся в отладку, но и публикуются в MQTT-брокере на контроллере. Вы можете использовать MQTT Explorer на ПК для проверки публикации сообщений в топик `telemetry/lab/room01/temperature`.
---
Шаг 4: Визуализация данных на дашборде
Последний шаг — создание простого интерфейса для наблюдения за температурой в реальном времени.
💡 Совет: Для наглядности и лучшей организации создайте для дашборда отдельную вкладку (flow) с названием «Дашборд».
Настройка узлов:
* Server: Выберите ранее настроенный `Локальный брокер HI`.
* Topic: `telemetry/lab/room01/temperature` (тот же топик, в который мы публикуем данные).
* Action: `Subscribe`.
* QoS: `1`.
* Output: `a parsed JSON object`. Это важно, так как мы отправляем JSON-объект, и Node-RED должен его распарсить.
* Name: `Подписка на температуру`.
* Паттерн "Визуальный статус": Узел `mqtt in` будет отображать статус подключения к брокеру.
* 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://
Чтобы увидеть результат, откройте новую вкладку в браузере по адресу `http://
---
Мини-runbook: «Если что-то не работает»
⚠️ Если вы столкнулись с проблемой, выполните диагностику по шагам:
* Диагностика:
* Физическое подключение: Проверьте физическое подключение датчика. Не перепутаны ли провода `Data`, `GND`, `VCC`? Надежно ли они зажаты в клеммах?
* Конфигурация UI: Убедитесь, что выбранный универсальный вход (UI-01) сконфигурирован в системных настройках контроллера HI для работы в режиме 1-Wire.
* ID датчика: Если вы указали конкретный ID в узле `ds18b20-sensor`, убедитесь, что он верен. Попробуйте оставить поле `1-Wire Device ID` пустым, чтобы узел попытался найти первый доступный датчик.
* Решение: Перепроверьте схему подключения `WIRING-SENS-011`. Попробуйте подключить датчик к другому универсальному входу. Проверьте логи системного журнала контроллера на наличие ошибок, связанных с 1-Wire.
* Диагностика:
* Входящие данные: Подключите узел `Debug` к выходу узла `ds18b20-sensor` и проверьте, какие данные он передает в `Function`. Должно быть число.
* Код Function: Внимательно проверьте код узла `Function` на опечатки, особенно в строках `parseFloat(msg.payload)` и формировании JSON-объекта.
* ID датчика: Убедитесь, что вы заменили `28-01234567abcd` на реальный ID вашего датчика в поле `source` JSON-контракта.
* Решение: Исправьте код. Используйте `Debug` для пошаговой отладки.
* Диагностика:
* Статус `mqtt out`: Проверьте статус узла `mqtt out`. Если под ним красный квадрат и надпись "disconnected", значит, есть проблема с подключением к брокеру.
* Настройки брокера: Откройте настройки узла `mqtt out` и проверьте параметры сервера: `localhost`, порт `1883`.
* Запущен ли брокер: Убедитесь, что MQTT-брокер (например, Mosquitto) запущен на контроллере HI. Проверить можно командой `sudo systemctl status mosquitto` в терминале контроллера.
* Топик: Убедитесь, что топик в `mqtt out` (`telemetry/lab/room01/temperature`) совпадает с тем, на который вы подписываетесь в `mqtt-explorer`.
* Решение: Запустите брокер, если он неактивен. Исправьте настройки подключения.
* Диагностика:
Топик `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)
* A) Modbus
* B) I2C
* C) 1-Wire
* D) CAN
* A) Только запуск опроса по таймеру.
* B) Валидацию данных, приведение их к стандартному JSON-формату и отображение визуального статуса.
* C) Непосредственное чтение данных с физического входа.
* D) Отображение данных на дашборде.
* A) Адрес удаленного облачного сервера.
* B) IP-адрес вашего компьютера.
* C) Указание на то, что брокер запущен на этом же устройстве (контроллере HI).
* D) Имя Wi-Fi сети.
* A) Это требование протокола MQTT.
* B) Для красоты.
* C) Для логической структуризации данных, гибкой подписки на группы данных и масштабируемости системы.
* D) Для увеличения скорости передачи.
* A) Извлекает поле `value` из объекта `msg.payload` и форматирует его как число с 1 знаком после запятой.
* B) Умножает значение на 1.
* C) Отправляет значение в базу данных.
* D) Проверяет, является ли значение числом.
* A) Ничего, все будет работать как прежде.
* B) Узел `ui_gauge` получит строку вместо объекта и не сможет извлечь поле `value`, что приведет к ошибке `NaN` или `undefined`.
* C) Скорость обновления дашборда увеличится.
* D) Сообщение не будет получено из MQTT.
* A) Позволяет видеть состояние узла и ключевые данные прямо в редакторе Node-RED без открытия панели отладки.
* B) Сохраняет данные в EEPROM.
* C) Отправляет email с ошибкой.
* D) Рисует график на дашборде.
* A) Для ловли рыбы.
* B) Для перехвата и централизованной обработки ошибок, возникающих в других узлах на данной вкладке.
* C) Для кэширования сообщений.
* D) Для запуска потока по расписанию.
* A) `Payload`
* B) `Topic`
* C) `Repeat`
* D) `Name`
* A) Юридический документ.
* B) Соглашение о стандартной и предсказуемой структуре данных (например, JSON), передаваемых между узлами, для обеспечения надежности и масштабируемости.
* C) Название прошивки контроллера.
* D) Алгоритм шифрования.
---
Заключение
Поздравляем! Вы успешно создали свой первый полноценный IoT-прототип на платформе HI. Вы прошли весь путь от физического подключения оборудования до визуализации данных, применив на практике ключевые паттерны и технологии: 1-Wire, Node-RED, JSON, MQTT и Dashboard.
На следующих этапах вы будете усложнять эту базовую систему: добавлять управление исполнительными устройствами (реле), интегрировать другие протоколы (Modbus), настраивать более сложную логику и сохранять данные в базу данных MySQL для последующего анализа.