Нода `Change`: установка, изменение, перемещение и удаление свойств `msg`
Введение в ноду Change: Основной инструмент трансформации данных
Нода `Change` — один из самых фундаментальных и часто используемых узлов в палитре Node-RED. Её основное назначение — манипулирование объектом `msg` без необходимости написания кода на JavaScript. Она предоставляет декларативный интерфейс для выполнения простых и атомарных операций: установки, изменения, перемещения и удаления свойств сообщения. В экосистеме контроллера HI, где важны читаемость, надежность и скорость разработки, нода `Change` является ключевым инструментом для подготовки данных перед отправкой на исполнительные устройства или в системы верхнего уровня, такие как MQTT или MySQL.
> 💡 Подсказка: Для простых и атомарных операций с `msg` всегда отдавайте предпочтение ноде `Change` перед нодой `Function`. Это упрощает отладку, повышает производительность и делает логику потока (flow) очевидной даже для инженера, который не знаком с проектом.
Обзор интерфейса и операций
При двойном клике на ноду `Change` открывается её панель настроек, которая состоит из списка правил. Каждое правило выполняется последовательно, сверху вниз. Для каждого правила можно определить одну из четырех основных операций:
- Set (Установить): Задает значение для указанного свойства. Если свойство не существует, оно будет создано. Если существует — его значение будет перезаписано.
- Change (Изменить): Выполняет поиск и замену внутри строкового свойства. Эта операция идеально подходит для очистки данных или изменения их формата.
- Move (Переместить): Переименовывает свойство, перемещая его содержимое в новое место в объекте `msg`. Фактически это эквивалентно комбинации "копировать + удалить оригинал".
- Delete (Удалить): Полностью удаляет указанное свойство из объекта `msg`.
Преимущества перед нодой `Function`
Хотя нода `Function` предоставляет неограниченную гибкость благодаря JavaScript, для стандартных задач трансформации нода `Change` имеет ряд неоспоримых преимуществ.
| Критерий | Нода `Change` | Нода `Function` |
| ----------------- | ------------------------------------------------------------- | --------------------------------------------------------------- |
| Наглядность | Логика видна сразу в интерфейсе, без необходимости входа в код. | Требуется открытие редактора кода для понимания логики. |
| Производительность | Операции выполняются оптимизированным встроенным кодом Node-RED. | Каждый раз создается "песочница" для выполнения JS-кода, что несколько медленнее. |
| Простота | Не требует знаний программирования. Интуитивно понятный интерфейс. | Требует знания синтаксиса JavaScript и асинхронной модели Node.js. |
| Надежность | Меньше вероятность допустить синтаксическую или логическую ошибку. | Легко допустить ошибку (опечатку, null pointer), которая может остановить поток. |
Нода `Change` не заменяет, а дополняет другие узлы-трансформеры. Например, нода `Split` используется для разделения массива или строки на последовательность отдельных сообщений, а `Join` — для обратной операции. Нода `Change` же работает с целостной структурой одного `msg` объекта на каждом шаге потока.
---
Операция 'Set' (Установить): Создание и перезапись свойств
перация 'Set' (Установить): Создание и перезапись свойств
Операция `Set` — самая распространенная в ноде `Change`. Она используется для присвоения конкретного значения свойству объекта `msg`. Это может быть как `msg.payload`, так и любое другое свойство, например, `msg.topic`, `msg.qos` или кастомное поле `msg.audit`.
Установка различных типов данных
Панель настройки правила `Set` позволяет выбрать тип данных для устанавливаемого значения, что крайне важно для соблюдения "контракта сообщений".
- string (строка): Установка текстового значения. Например, формирование топика для MQTT.
- number (число): Установка числового значения. Например, жестко заданная уставка температуры.
- boolean (булево): Установка `true` или `false`. Например, для отправки команды на включение реле.
- JSON: Установка сложного объекта или массива в формате JSON. Это позволяет формировать структурированный `payload` прямо в ноде.
- timestamp (временная метка): Установка текущего времени в виде Unix timestamp (ms).
- flow / global: Установка значения из переменной контекста потока (`flow`) или глобального контекста (`global`).
Практический пример: Подготовка команды для DALI
Предположим, нам нужно отправить команду для установки яркости светильника в шину DALI. Нода `dali-out` ожидает на входе `msg.payload` в виде JSON-объекта. Исходное сообщение приходит от кнопки на панели управления и содержит лишь простую команду.
Исходное `msg` после ноды `Inject`:{
"payload": "set_max_brightness",
"topic": "control_panel/button_1",
"_msgid": "a1b2c3d4.e5f6a7"
}
Задача: Преобразовать это сообщение в команду, понятную для DALI-драйвера, установив `msg.payload` в объект с параметрами адресации и значения.
Конфигурация ноды `Change`:
* `Set`: `msg.payload`
* `to`: `JSON`
* В текстовом поле вводим JSON-объект управления:
{
"address": 5,
"addressType": 0,
"command": "DAPC",
"value": 254
}
Итоговое `msg` после ноды `Change`:
{
"payload": {
"address": 5,
"addressType": 0,
"command": "DAPC",
"value": 254
},
"topic": "control_panel/button_1",
"_msgid": "a1b2c3d4.e5f6a7"
}
Теперь это сообщение может быть напрямую подано на вход ноды управления DALI. Аналогично, мы могли бы добавить еще одно правило `Set` для установки `msg.topic` в нужный нам формат, например `lighting/office/zone1/cmd`.
Операция 'Change' (Изменить): Поиск и замена внутри свойства
Операция `Change` (не путать с названием самой ноды) предназначена для внутренних модификаций строковых свойств. Она выполняет поиск указанной подстроки или паттерна и заменяет все найденные вхождения на новое значение. Это мощный инструмент для очистки и нормализации "сырых" данных, поступающих от внешних устройств.
> ⚠️ Внимание: При использовании регулярных выражений будьте внимательны с экранированием специальных символов. Неправильный паттерн может привести к неожиданным результатам, ошибкам в потоке или, в худшем случае, к высокой нагрузке на CPU контроллера из-за "катастрофического возврата" (catastrophic backtracking). Всегда тестируйте свои RegEx на онлайн-валидаторах.
Простая замена подстроки
Самый простой сценарий — замена одной фиксированной строки на другую. Например, если текстовый датчик присылает состояние в виде "STATE=OPEN", а нам для дальнейшей обработки требуется только "OPEN".
Настройка правила:- `Change`: `msg.payload`
- `Search for`: `string` `STATE=`
- `Replace with`: `string` (оставить поле пустым)
Использование регулярных выражений (RegEx)
Для более сложных задач на помощь приходят регулярные выражения. Они позволяют находить не просто строки, а целые паттерны.
Практический пример: Очистка данных с устройства по RS-485Многие простые устройства, работающие по ASCII-протоколам через RS-485, могут присылать данные, обрамленные служебными символами, например, символами перевода строки `\r\n`.
Исходное `msg` от ноды `serial in`:{
"payload": "T:23.5;H:45.1\r\n",
"_msgid": "b2c3d4e5.f6a7b8"
}
Задача: Удалить из `msg.payload` все управляющие символы (`\r`, `\n`) и оставить только полезные данные.
Конфигурация ноды `Change`:
* `Change`: `msg.payload`
* `Search for`: `regex` `[\r\n]` (квадратные скобки означают "любой из символов внутри")
* `Replace with`: `string` (оставить поле пустым)
* В поле `in` выбираем `msg.payload`.
Итоговое `msg` после ноды `Change`:{
"payload": "T:23.5;H:45.1",
"_msgid": "b2c3d4e5.f6a7b8"
}
Теперь `msg.payload` имеет чистый и предсказуемый формат, который можно легко разобрать на составные части с помощью нод `Split` или `Function`. Эта простая операция значительно повышает надежность всего потока, так как он становится нечувствительным к незначительным вариациям в формате входящих данных.
---
Операции 'Move' (Переместить) и 'Delete' (Удалить): Оптимизация структуры `msg`
По мере прохождения сообщения по потоку, объект `msg` может "обрастать" множеством служебных и промежуточных свойств. Это затрудняет отладку и может приводить к избыточной передаче данных. Операции `Move` и `Delete` служат для поддержания `msg` в чистоте и порядке.
Правило `Move` (Переместить)
Правило `Move` используется для переименования свойства. Оно берет значение из одного свойства и помещает его в другое, при этом исходное свойство удаляется.
Пример: Протокольный узел (например, `knx-in`) вернул значение в `msg.payload.value`. Для ясности и соответствия нашему внутреннему стандарту мы хотим, чтобы это свойство называлось `msg.payload.temperature`. Исходное `msg`:{
"payload": {
"value": 24.5,
"source": "1/1/1"
},
"_msgid": "c3d4e5f6.a7b8c9"
}
Конфигурация ноды `Change`:
- `Move`: `msg.payload.value`
- `to`: `msg.payload.temperature`
{
"payload": {
"temperature": 24.5,
"source": "1/1/1"
},
"_msgid": "c3d4e5f6.a7b8c9"
}
Правило `Delete`(Удалить)
Правило `Delete` — это гигиенический инструмент. Оно полностью удаляет указанное свойство из объекта `msg`. Это необходимо делать перед отправкой данных в системы, где важен минимальный размер сообщения (например, MQTT в сетях LoRaWAN) или перед записью в базу данных, чтобы не хранить ненужную информацию.
Пример: После всех преобразований у нас в `msg` остались временные данные в свойстве `msg.temp_buffer`. Перед отправкой в MQTT нам нужно от них избавиться. Конфигурация ноды `Change`:- `Delete`: `msg.temp_buffer`
Комбинация правил для комплексной трансформации
Сила ноды `Change` раскрывается при использовании нескольких правил в одном узле. Они выполняются последовательно, что позволяет произвести сложную трансформацию за один шаг.
Задача:Такой подход делает поток компактным и логически сгруппированным. Вся трансформация инкапсулирована в одном узле, который можно назвать "Подготовка данных влажности".
---
Практический пример: Обработка ответа от Modbus RTU устройства
Рассмотрим реальный сценарий на объекте. Контроллер HI опрашивает по шине RS-485 Modbus-счетчик электроэнергии. Нам нужно получить значение активной мощности, которое содержится в одном из регистров.
Нода `modbus-read` возвращает сообщение, содержащее не только полезные данные, но и служебную информацию, например, буфер ответа.
Исходное `msg` от ноды `modbus-read`:Предположим, нода `modbus-read` после успешного опроса вернула следующий объект. Значение мощности (например, `5200` Ватт) находится в `msg.payload`, а также есть избыточное поле `msg.responseBuffer`.
{
"payload": 5200,
"topic": "ModbusPolling",
"responseBuffer": {
"data": [5200],
"buffer": ""
},
"_msgid": "d4e5f6a7.b8c9d0"
}
> ℹ️ Информация: Структура `msg` от ноды `modbus-read` может отличаться в зависимости от её настроек. В данном примере мы рассматриваем распространенный случай, когда `payload` уже содержит готовое число.
Задача:{
"payload": {
"value": 5200,
"unit": "W",
"source": "energymeter-main-01",
"ts": 1678890000000
},
"topic": "hi/office/main-panel/energymeter-01/active-power/state",
"_msgid": "d4e5f6a7.b8c9d0"
}
Для решения этой задачи в один шаг мы используем ноду `Change` с несколькими правилами.
Конфигурация ноды `Change`:* `Move`: `msg.payload`
* `to`: `msg.payload.value`
(Это правило магическим образом создаст объект `msg.payload` и поместит туда ключ `value`)
* `Set`: `msg.payload.unit`
* `to`: `string` `W`
* `Set`: `msg.payload.source`
* `to`: `string` `energymeter-main-01`
* `Set`: `msg.payload.ts`
* `to`: `timestamp`
* `Set`: `msg.topic`
* `to`: `string` `hi/office/main-panel/energymeter-01/active-power/state`
* `Delete`: `msg.responseBuffer`
Последовательное применение этих шести правил в одной ноде `Change` полностью преобразует "сырое" сообщение от Modbus-устройства в стандартизированное сообщение, готовое к публикации в MQTT и дальнейшей обработке другими подсистемами.
---
Итоги и лучшие практики
В этом уроке мы детально рассмотрели ноду `Change` — основной декларативный инструмент для манипуляции данными в Node-RED. Вы научились использовать ее четыре ключевые операции для приведения объекта `msg` к требуемой структуре.
> 🔗 Связанный материал: Для запуска потоков и тестирования правил в этом уроке используйте ноду `Inject` для генерации исходных сообщений, как было рассмотрено в уроке `COURSE-06-M03-L01`.
Ключевые выводы:- Нода `Change` предоставляет четыре операции: Set (установить/создать), Change (найти и заменить), Move (переименовать/переместить) и Delete (удалить).
- Для простых задач трансформации она является более наглядной, производительной и надежной альтернативой ноде `Function`.
- Использование нескольких правил в одной ноде позволяет инкапсулировать всю логику подготовки данных в одном месте, что улучшает читаемость потока.
- Поддержание "гигиены" объекта `msg` путем удаления ненужных свойств — это важная практика для создания эффективных и легко отлаживаемых систем автоматизации.
Соблюдение этих практик позволит вам создавать потоки, которые не только работают, но и легко поддерживаются и масштабируются.
Что дальше
Мы освоили базовые операции ноды `Change`. Однако её возможности гораздо шире. В следующем уроке мы расширим возможности этого узла, изучив мощный язык запросов JSONata, который позволяет выполнять сложнейшие преобразования, вычисления и форматирование данных прямо внутри правил ноды `Change`. Это откроет новые горизонты для обработки даже самых сложных структур данных без единой строчки JavaScript-кода.