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

Принципы работы IoT: от датчика до действия на платформе HI

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

COURSE-16-M01-L03 — Принципы работы IoT: от датчика до действия на платформе HI

Введение в жизненный цикл IoT-данных

В предыдущих уроках мы рассмотрели компоненты экосистемы Интернета вещей. Теперь мы детально разберем, как эти компоненты взаимодействуют между собой, формируя полный цикл работы IoT-системы: от сбора данных физическим датчиком до выполнения команды исполнительным устройством. Понимание этого четырехэтапного процесса является ключевым для проектирования надежных и эффективных решений по автоматизации на платформе HI.

Каждый этап мы будем рассматривать в контексте нашего стандартного контроллера HI (Debian, Node-RED) и его периферии, применяя стандарты Академии HI.

Этап 1: Сбор данных (Data Collection)

Отправной точкой любой IoT-системы являются устройства и датчики, которые преобразуют физические параметры реального мира в цифровые сигналы. Контроллер HI оснащен 22 универсальными входами, позволяющими подключать широкий спектр датчиков напрямую.

Типы собираемых данных и способы подключения к контроллеру HI: * Датчики: DS18B20 (температура), DHT11/DHT22 (температура и влажность).

* Подключение: Подключаются к универсальным входам контроллера, сконфигурированным для работы с шиной 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 этот этап можно разделить на два уровня:

  • Внутренняя передача: От физического входа контроллера в среду исполнения Node-RED. За это отвечают системные драйверы Debian и специализированные узлы Node-RED (например, `node-red-contrib-ds18b20` для 1-Wire или `node-red-contrib-modbus` для RS-485). На этом уровне данные еще "сырые" и требуют первичной обработки.
  • Внешняя передача: От контроллера к другим системам (облачная платформа, мобильное приложение, другие контроллеры). Стандартом де-факто для этого является протокол MQTT.
  • MQTT (Message Queuing Telemetry Transport) — это легковесный протокол обмена сообщениями, идеально подходящий для IoT. Он работает по принципу "издатель-подписчик" (publish-subscribe). Пример структуры топиков (согласно стандарту Академии):

    `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).

    Пример: Управление климатом

    Представим систему, которая может находиться в состояниях "Ожидание", "Охлаждение", "Нагрев".

    * Если `msg.payload.value > flow.setpoint + 1` и `flow.climate_state` == "Ожидание", то перейти в "Охлаждение".

    * Если `msg.payload.value < flow.setpoint - 1` и `flow.climate_state` == "Ожидание", то перейти в "Нагрев".

    * Если `msg.payload.value` находится в пределах `flow.setpoint +/- 0.5` и `flow.climate_state` != "Ожидание", то перейти в "Ожидание".

    ASCII-схема FSM для управления климатом:
    [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-команде с использованием субпотока
  • Команда: Внешняя система (например, мобильное приложение) публикует сообщение `{ "command": "ON" }` в топик `commands/objects/office-1/room-101/light/set`.
  • Прием: Узел `MQTT In` в Node-RED, подписанный на этот топик, получает команду.
  • Обработка и исполнение: Сообщение поступает на субпоток `FLOW-CTRL-RELAY-005` (паттерн "Переиспользуемый компонент"). Этот субпоток:
  • * Валидирует входящую команду.

    * Преобразует ее в команду для физического реле (например, `rpi gpio out`).

    * Управляет одним из 22 реле контроллера.

    * Формирует обратную связь о статусе.

    * Обрабатывает возможные ошибки (например, если реле не сработало).

  • Обратная связь: После успешного выполнения команды субпоток отправляет сообщение `{ "status": "ON" }` в топик состояния `status/objects/office-1/room-101/light/state`, чтобы все подписчики знали актуальное состояние светильника.
  • ASCII-схема потока управления освещением:
    [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`:

    Журналирование и аудит (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)

  • Какой компонент контроллера HI используется для подключения датчика открытия двери ("сухой контакт")?
  • Назовите основной протокол для обмена сообщениями между IoT-устройствами и облаком в экосистеме HI.
  • Что такое "топик" в контексте протокола MQTT? Приведите пример стандартизированного топика для телеметрии.
  • Какая среда используется на контроллере HI для создания логики автоматизации?
  • Что такое "Контракт сообщения" и зачем он нужен?
  • Назовите как минимум три обязательных поля, которые должны присутствовать в стандартном `msg.payload` для данных с датчика согласно паттерну "Контракт сообщения".
  • Какой узел в Node-RED используется для перехвата и обработки ошибок в потоке, согласно паттерну "Обработка ошибок"?
  • Для чего предназначен узел `rpi gpio out` в контексте контроллера HI?
  • Опишите роль MQTT-брокера в двух словах.
  • Зачем нужна "обратная связь" при управлении исполнительным устройством (например, реле)?
  • ---

    Мини-runbook "Если что-то пошло не так"

    * Решение:

    1. Проверьте подключение: Убедитесь, что провода `VCC`, `GND` и `DATA` не перепутаны. Используйте схему `WIRING-SENS-001`.

    2. Проверьте ID датчика: Убедитесь, что в узле `ds18b20` указан правильный ID. Попробуйте очистить поле и посмотреть в отладке, какие ID находит система.

    3. Проверьте кабель: На длинных линиях (>15м) могут быть проблемы. Используйте качественную витую пару.

    4. Проверьте питание: Убедитесь, что на датчик подается стабильное питание (3.3V или 5V).

    * Решение:

    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`.

    * Решение:

    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`.

    * Решение:

    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.