Принципы работы IoT: от датчика до действия на платформе HI
COURSE-16-M01-L03 — Принципы работы IoT: от датчика до действия на платформе HI
Введение в жизненный цикл IoT-данных
В предыдущих уроках мы рассмотрели компоненты экосистемы Интернета вещей. Теперь мы детально разберем, как эти компоненты взаимодействуют между собой, формируя полный цикл работы IoT-системы: от сбора данных физическим датчиком до выполнения команды исполнительным устройством. Понимание этого четырехэтапного процесса является ключевым для проектирования надежных и эффективных решений по автоматизации на платформе HI.
Каждый этап мы будем рассматривать в контексте нашего стандартного контроллера HI (Debian, Node-RED) и его периферии, применяя стандарты Академии HI.
Этап 1: Сбор данных (Data Collection)
Отправной точкой любой IoT-системы являются устройства и датчики, которые преобразуют физические параметры реального мира в цифровые сигналы. Контроллер HI оснащен 22 универсальными входами, позволяющими подключать широкий спектр датчиков напрямую.
Типы собираемых данных и способы подключения к контроллеру HI:- Температура и влажность:
* Подключение: Подключаются к универсальным входам контроллера, сконфигурированным для работы с шиной 1-Wire. Каждый датчик на шине имеет уникальный адрес, что позволяет подключать несколько устройств на один вход.
* Схема подключения: `WIRING-SENS-004` (см. раздел "Стандарты схем подключения").
- Состояние объектов (открыто/закрыто, есть движение):
* Подключение: Используют выходы типа "сухой контакт" (Dry Contact). Подключаются к универсальным входам контроллера, которые регистрируют замыкание или размыкание цепи.
* Схема подключения: `WIRING-LIGHT-015` (см. раздел "Стандарты схем подключения").
- Параметры промышленных устройств (напряжение, ток, расход):
* Подключение: Взаимодействуют с контроллером по промышленным шинам, таким как RS-485 (Modbus RTU) или CAN. Контроллер HI выступает в роли Master-устройства, периодически опрашивая Slave-устройства на шине.
* Схема подключения: `WIRING-SENS-004` (для Modbus RTU).
* Подробнее о Modbus: См. скилл "Протоколы Modbus".
💡 Практический совет: Перед монтажом всегда присваивайте и документируйте уникальные идентификаторы (ID) для каждого датчика. Например, `temp-sensor-living-room-01` или `modbus-energymeter-main-01`. Это критически важно для дальнейшей настройки в Node-RED и соблюдения паттерна "Контракт сообщения".
Этап 2: Передача и агрегация данных (Data Transmission & Aggregation)
После сбора данные должны быть переданы для обработки. В экосистеме HI этот этап можно разделить на два уровня:
- Контроллер HI (Издатель): Публикует данные с датчиков в определенные топики (topics).
- MQTT-брокер: Сервер, который принимает сообщения и перенаправляет их всем подписчикам. Брокер может работать как на самом контроллере HI, так и в облаке.
- Приложение пользователя (Подписчик): Подписывается на топики и получает данные в реальном времени.
`telemetry/objects/office-1/room-101/temperature`
`commands/objects/office-1/room-101/light/set`
`status/objects/office-1/room-101/light/state`
⚠️ Предупреждение: Неструктурированные топики и форматы сообщений — прямой путь к созданию хаотичной и неподдерживаемой системы. Всегда следуйте заранее определенной иерархии топиков и контракту сообщений. Используйте паттерн "Контракт сообщения" для всех данных, передаваемых через MQTT.
Этап 3: Обработка данных и принятие решений (Processing & Decision Making)
Это центральный этап, где "сырые" данные превращаются в осмысленную информацию и команды. На платформе HI вся логика реализуется в Node-RED. Здесь мы применяем ключевые паттерны проектирования из стандартов Академии HI.
3.1. Валидация и форматирование по "Контракту сообщения"
Каждое сообщение, полученное от датчика или из внешнего источника, должно быть проверено и приведено к стандартному формату. Это обеспечивает предсказуемость данных и упрощает дальнейшую обработку.
ASCII-схема потока обработки датчика с учетом обработки ошибок:[Inject: Poll] --> [Sensor Input Node: DS18B20] --> [Function: Validate & Format] --> [MQTT Out: Telemetry]
| |
| (Error Output) | (Error Output)
v v
[Catch: All Errors] -----------------> [Function: Format Error] --> [Link Out: To Error Logger]
Пример кода для узла `Function: Validate & Format` (FLOW-SENS-TEMP-001):
// Входящее сообщение от узла ds18b20: msg.payload = 25.125
// Или от Modbus-Getter: msg.payload = { data: [255], buffer: }
let rawValue = msg.payload;
let temp;
// Обработка разных типов входных данных (для DS18B20 или Modbus)
if (typeof rawValue === 'number') { // Предполагаем, что это DS18B20
temp = parseFloat(rawValue);
} else if (rawValue && Array.isArray(rawValue.data) && rawValue.data.length > 0) { // Предполагаем, что это Modbus
temp = parseFloat(rawValue.data[0]) / 10.0; // Пример для Modbus, где значение * 10
} else {
node.status({fill:"red", shape:"dot", text:"Invalid input type"});
node.error("Некорректный тип входных данных", msg);
return null;
}
// 1. Валидация
if (isNaN(temp) || temp < -50 || temp > 120) {
node.status({fill:"red", shape:"dot", text:"Invalid value: " + temp});
// Вызываем ошибку, которая будет поймана узлом Catch
node.error("Некорректное значение температуры: " + temp, msg);
return null; // Останавливаем поток
}
// 2. Формирование сообщения по контракту (паттерн "Контракт сообщения")
msg.payload = {
value: temp,
source: "28-01234567abcd", // Уникальный ID датчика 1-Wire или Modbus Slave ID
ts: Date.now(),
unit: "°C"
};
msg.topic = "telemetry/objects/office-1/room-101/temperature"; // Стандартизированный топик
// 3. Обновление визуального статуса (паттерн "Визуальный статус")
node.status({fill:"green", shape:"dot", text:"OK: " + temp + " °C"});
return msg;
3.2. Реализация логики (Паттерн "Конечный автомат")
На основе обработанных данных система принимает решения. Для сложной логики рекомендуется использовать паттерн "Конечный автомат" (FSM).
Пример: Управление климатомПредставим систему, которая может находиться в состояниях "Ожидание", "Охлаждение", "Нагрев".
- Событие: Сообщение из топика `telemetry/objects/office-1/room-101/temperature` со значением `25.5`.
- Состояние: Текущее состояние системы хранится в `flow.climate_state` (например, "Ожидание"). Уставка `flow.setpoint` = `23.0`.
- Логика (узел `Switch`):
* Если `msg.payload.value < flow.setpoint - 1` и `flow.climate_state` == "Ожидание", то перейти в "Нагрев".
* Если `msg.payload.value` находится в пределах `flow.setpoint +/- 0.5` и `flow.climate_state` != "Ожидание", то перейти в "Ожидание".
- Действие: Сформировать команду на включение/выключение соответствующего исполнительного устройства (кондиционера или обогревателя).
[MQTT In: Temperature] --> [Function: Update Context] --> [Switch: Current State]
|
+-- (State: "Waiting") --> [Switch: Check Temp]
| |
| +-- (> Setpoint+1) --> [Change: Set State "Cooling"] --> [Call Subflow: AC ON]
| |
| +-- (< Setpoint-1) --> [Change: Set State "Heating"] --> [Call Subflow: Heater ON]
|
+-- (State: "Cooling") --> [Switch: Check Temp]
| |
| +-- (< Setpoint-0.5) --> [Change: Set State "Waiting"] --> [Call Subflow: AC OFF]
|
+-- (State: "Heating") --> [Switch: Check Temp]
|
+-- (> Setpoint+0.5) --> [Change: Set State "Waiting"] --> [Call Subflow: Heater OFF]
Этап 4: Выполнение действий (Action Execution)
Финальный этап, на котором цифровые команды преобразуются в физические действия. Контроллер HI оснащен 22 релейными выходами для управления нагрузками.
Пример: Управление освещением по MQTT-команде с использованием субпотока* Валидирует входящую команду.
* Преобразует ее в команду для физического реле (например, `rpi gpio out`).
* Управляет одним из 22 реле контроллера.
* Формирует обратную связь о статусе.
* Обрабатывает возможные ошибки (например, если реле не сработало).
[MQTT In: commands/light/set] --> [Subflow: FLOW-CTRL-RELAY-005] --> [MQTT Out: status/light/state]
| (Error Output)
v
[Link Out: To Error Logger]
Контракт сообщения для субпотока `FLOW-CTRL-RELAY-005`:
- Вход: `msg.payload = { "command": "ON" }` или `{ "command": "OFF" }`.
- Выход (успех): `msg.payload = { "status": "ON", "source": "light-office-main", "ts": 1678886500000 }`.
- Выход (ошибка): `msg.payload = { "error": "Invalid command", "details": "...", "ts": 1678886500000 }`.
Журналирование и аудит (Audit Log)
Важной частью любой IoT-системы является возможность отслеживать все значимые события: изменения состояния датчиков, выполнение команд, ошибки. На платформе HI для этого используется база данных MySQL.
Паттерн "Обработка ошибок" и "Контракт сообщения" для аудита:Все ошибки, перехваченные узлами `Catch`, а также все критические события (например, включение/выключение света, изменение уставки температуры) должны быть записаны в централизованный журнал аудита.
Пример структуры записи в `audit_log` (MySQL):{
"timestamp": "2023-03-15T10:30:00.123Z",
"level": "INFO", // INFO, WARN, ERROR, CRITICAL
"source_node": "FLOW-CTRL-RELAY-005", // ID узла или субпотока
"event_type": "RELAY_STATE_CHANGE",
"object_id": "light-office-main",
"old_state": "OFF",
"new_state": "ON",
"user_id": "admin", // Если команда пришла от пользователя
"details": "Command received via MQTT from mobile app"
}
ASCII-схема централизованного логгера ошибок/аудита:
[Link In: From Error Logger] --> [Function: Format Audit Log] --> [MySQL: Insert into audit_log]
Код для узла `Function: Format Audit Log`:
// msg.payload содержит информацию об ошибке или событии
// msg.error (если это ошибка) содержит source, message, stack
let logEntry = {
timestamp: new Date().toISOString(),
level: "INFO",
source_node: msg.flow_id || "unknown", // ID потока или узла
event_type: "UNKNOWN_EVENT",
object_id: "system",
details: JSON.stringify(msg.payload)
};
if (msg.error) {
logEntry.level = "ERROR";
logEntry.event_type = "NODE_ERROR";
logEntry.source_node = msg.error.source.id + " (" + msg.error.source.type + ")";
logEntry.details = msg.error.message + " Stack: " + msg.error.stack;
if (msg.payload && msg.payload.source) {
logEntry.object_id = msg.payload.source;
}
} else if (msg.payload && msg.payload.event_type) {
// Если сообщение уже отформатировано как событие аудита
logEntry = msg.payload;
logEntry.timestamp = new Date(logEntry.timestamp).toISOString(); // Убедимся в корректном формате
}
// Формируем payload для MySQL
msg.payload = {
query: "INSERT INTO audit_log (timestamp, level, source_node, event_type, object_id, details) VALUES (?, ?, ?, ?, ?, ?)",
params: [
logEntry.timestamp,
logEntry.level,
logEntry.source_node,
logEntry.event_type,
logEntry.object_id,
logEntry.details
]
};
return msg;
Заключение
Понимание и применение этих четырех этапов — сбор, передача, обработка и выполнение — с использованием стандартов Академии HI, является краеугольным камнем для создания профессиональных и надежных IoT-решений. Каждый этап взаимосвязан, и ошибки на одном из них могут привести к сбоям всей системы. Строгое следование паттернам Node-RED, таким как "Контракт сообщения", "Обработка ошибок", "Визуальный статус", "Переиспользуемый компонент" и "Конечный автомат", позволит вам создавать масштабируемые, легко поддерживаемые и отказоустойчивые системы автоматизации на платформе HI.
---
Тест для самопроверки (COURSE-16-M01-QUIZ)
---
Мини-runbook "Если что-то пошло не так"
- Проблема: Датчик DS18B20 не отдает данные или показывает `85` / `0`.
1. Проверьте подключение: Убедитесь, что провода `VCC`, `GND` и `DATA` не перепутаны. Используйте схему `WIRING-SENS-001`.
2. Проверьте ID датчика: Убедитесь, что в узле `ds18b20` указан правильный ID. Попробуйте очистить поле и посмотреть в отладке, какие ID находит система.
3. Проверьте кабель: На длинных линиях (>15м) могут быть проблемы. Используйте качественную витую пару.
4. Проверьте питание: Убедитесь, что на датчик подается стабильное питание (3.3V или 5V).
- Проблема: Реле не срабатывает по MQTT-команде.
1. Проверьте MQTT-клиент: Убедитесь, что вы отправляете команду в правильный топик (например, `commands/objects/office-1/room-101/light/set`) и сообщение в точности совпадает с тем, что ожидает узел `switch` или субпоток (например, `{ "command": "ON" }`, а не `"ON"` или `true`).
2. Проверьте поток Node-RED: Поставьте узлы `debug` после каждого шага (`mqtt in`, `switch`, входы/выходы субпотока), чтобы увидеть, где прерывается поток сообщений.
3. Проверьте конфигурацию GPIO: Убедитесь, что в узле `rpi gpio out` выбран правильный номер реле.
4. Проверьте физическое подключение: Убедитесь, что нагрузка (лампа) правильно подключена к клеммам реле согласно `WIRING-LIGHT-001`.
- Проблема: Данные не появляются в MQTT-клиенте.
1. Проверьте настройки брокера: Убедитесь, что адрес сервера, порт, логин и пароль в узле `mqtt out` указаны верно.
2. Проверьте статус подключения: Узел `mqtt out` показывает свой статус под собой. Если он "disconnected", проблема в сетевых настройках или доступности брокера.
3. Проверьте топик: Убедитесь, что вы подписаны в MQTT-клиенте именно на тот топик, в который публикует Node-RED (например, `telemetry/objects/office-1/room-101/temperature`). Остерегайтесь опечаток.
4. Проверьте узел `Function`: Убедитесь, что узел `Function` не возвращает `null` и корректно формирует `msg.topic` и `msg.payload`.
- Проблема: Ошибки Modbus (таймаут, CRC error).
1. Проверьте физическое подключение RS-485: Убедитесь, что провода A и B не перепутаны, и что есть надежное подключение GND.
2. Проверьте терминирование: Убедитесь, что на обоих концах шины RS-485 установлены терминирующие резисторы 120 Ом.
3. Проверьте параметры COM-порта: Скорость (Baud Rate), четность (Parity), биты данных (Data Bits) и стоповые биты (Stop Bits) должны точно совпадать на контроллере и Modbus-устройстве.
4. Проверьте Slave ID: Убедитесь, что `Unit-ID` в узле `Modbus-Read` соответствует адресу устройства.
5. Проверьте карту регистров: Убедитесь, что вы запрашиваете правильный адрес регистра и код функции (FC). Учтите ошибку "off-by-one".
- Проблема: Система работает нестабильно, "зависает" или перезагружается.
1. Проверьте логи: Изучите системные логи Debian (`journalctl -xe`) и логи Node-RED на предмет ошибок или предупреждений.
2. Оптимизируйте потоки: Убедитесь, что нет бесконечных циклов, чрезмерно частых опросов или сложных вычислений в узлах `Function`, которые могут блокировать основной поток Node-RED.
3. Используйте паттерн "Визуальный статус": Добавьте узлы `Status` к ключевым узлам, чтобы быстро определить, какой узел вызывает проблему.
4. Проверьте потребление ресурсов: Используйте команды `top` или `htop` в терминале контроллера, чтобы отследить загрузку CPU и RAM.