Вопрос или проблема
Я в отчаянии из-за этого и надеюсь, что кто-то сможет помочь.
Проблема: в предстоящем потоке JSON node-red я создал автоматизацию для моего камина. Все, кажется, работает правильно, за исключением таймера автоматического отключения, который я внедрил. Таймер получает значение из ‘input_number.auto_off_fireplace_timing’ (устанавливается пользователем). Это число затем отправляется как msg.auto_off_timing = entity_state. Узел функции получает это и выполняет следующий JS:
const timingMinutes = Number(msg.auto_off_timing);
if (isNaN(timingMinutes) || timingMinutes <= 0) {
node.error("Неверное значение времени", msg);
return null;
}
const timingMilliseconds = timingMinutes * 60 * 1000;
msg.delay = timingMilliseconds;
delete msg.reset;
return msg;
Затем это сообщение отправляется в Узел-Запуск Таймера Авто-выключения, который, кажется, запускается (синий круг присутствует), но не подчиняется изложенной математике. На самом деле, я не могу заставить его продолжить после триггера, и учитывая тип узла, нет хорошего способа контролировать текущее состояние его обратного отсчета.
Я в замешательстве и надеюсь, что кто-то сможет помочь. Вот мой JSON (некоторые другие проверки безопасности, термостат, авто-выключение через 2 часа и т.д. были удалены, чтобы сосредоточиться на проблеме):
[
{
"id": "109ae81398e4db33",
"type": "subflow",
"name": "Автоматизация Ворота (5) (5) (2) (3)",
"info": "Этот подflow проверяет состояние input_boolean.nodered_enable и позволяет автоматизациям продолжать только если он 'включен'.",
"category": "",
"in": [
{
"x": 60,
"y": 80,
"wires": [
{
"id": "6a0e54df8bebfb35"
}
]
}
],
"out": [
{
"x": 460,
"y": 80,
"wires": [
{
"id": "6a0e54df8bebfb35",
"port": 0
}
]
}
],
"env": [],
"color": "#DDAA99",
"icon": "node-red/switch.svg",
"status": {
"x": 460,
"y": 140,
"wires": [
{
"id": "6a0e54df8bebfb35",
"port": 1
}
]
}
},
{
"id": "6a0e54df8bebfb35",
"type": "api-current-state",
"z": "109ae81398e4db33",
"name": "Проверка nodered_enable",
"server": "home_assistant",
"version": 3,
"outputs": 2,
"halt_if": "включен",
"halt_if_type": "str",
"halt_if_compare": "является",
"entity_id": "input_boolean.nodered_enable",
"state_type": "str",
"outputProperties": [
{
"property": "nodered_enable",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": 0,
"forType": "num",
"forUnits": "minutes",
"x": 260,
"y": 80,
"wires": [
[],
[]
]
},
{
"id": "home_assistant",
"type": "server",
"name": "Home Assistant",
"addon": true
},
{
"id": "e2022f3797213292",
"type": "tab",
"label": "Автоматизация Камины",
"disabled": false,
"info": ""
},
{
"id": "18112a371a5730af",
"type": "function",
"z": "e2022f3797213292",
"name": "Запуск или Сброс Таймеров",
"func": "if (msg.payload === 'включен') {\n // Камин включен\n return [msg, null]; // Запуск таймеров\n} else {\n // Камин выключен\n return [null, msg]; // Сброс таймеров\n}",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1140,
"y": 100,
"wires": [
[
"26de0bc92b3c1fa2"
],
[
"49c2de739512f63e"
]
]
},
{
"id": "26de0bc92b3c1fa2",
"type": "link out",
"z": "e2022f3797213292",
"name": "Запуск Таймеров",
"links": [
"9bb3cef0f93bc9ca",
"10192ba7e96e6de6"
],
"x": 1305,
"y": 60,
"wires": []
},
{
"id": "49c2de739512f63e",
"type": "link out",
"z": "e2022f3797213292",
"name": "Сброс Таймеров",
"links": [
"96384ada3ddffe94",
"9f9c274ad7a7daf4"
],
"x": 1305,
"y": 120,
"wires": []
},
{
"id": "9bb3cef0f93bc9ca",
"type": "link in",
"z": "e2022f3797213292",
"name": "Вход Таймера Авто-выключения",
"links": [
"26de0bc92b3c1fa2",
"3aaa3b66d3c867c9"
],
"x": 605,
"y": 340,
"wires": [
[
"07dd056055f5c8d0"
]
]
},
{
"id": "07dd056055f5c8d0",
"type": "api-current-state",
"z": "e2022f3797213292",
"name": "Включен ли Авто-выключатель?",
"server": "d262b87e.b0ac48",
"version": 3,
"outputs": 2,
"halt_if": "включен",
"halt_if_type": "str",
"halt_if_compare": "является",
"entity_id": "input_boolean.auto_off_fireplace",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "auto_off",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": 0,
"forType": "num",
"forUnits": "minutes",
"x": 740,
"y": 340,
"wires": [
[
"d77b4e28dd6bb6b7"
],
[]
]
},
{
"id": "d77b4e28dd6bb6b7",
"type": "api-current-state",
"z": "e2022f3797213292",
"name": "Получить Время Авто-выключения",
"server": "d262b87e.b0ac48",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "num",
"halt_if_compare": "является",
"entity_id": "input_number.auto_off_fireplace_timing",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "auto_off_timing",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": 0,
"forType": "num",
"forUnits": "minutes",
"x": 960,
"y": 340,
"wires": [
[
"be97b45c9eff76da"
]
]
},
{
"id": "be97b45c9eff76da",
"type": "function",
"z": "e2022f3797213292",
"name": "Установить Таймер Авто-выключения",
"func": "const timingMinutes = Number(msg.auto_off_timing);\n\nif (isNaN(timingMinutes) || timingMinutes <= 0) {\n node.error(\"Неверное значение времени\", msg);\n return null;\n}\n\nconst timingMilliseconds = timingMinutes * 60 * 1000;\n\nmsg.delay = timingMilliseconds;\ndelete msg.reset;\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1170,
"y": 340,
"wires": [
[
"d747581c05875140"
]
]
},
{
"id": "d747581c05875140",
"type": "trigger",
"z": "e2022f3797213292",
"name": "Таймер Авто-выключения",
"op1": "",
"op2": "",
"op1type": "nul",
"op2type": "pay",
"duration": "0",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "stop",
"bytopic": "all",
"topic": "delay",
"outputs": 1,
"x": 1420,
"y": 340,
"wires": [
[
"f1a9129f98b8ffe6"
]
]
},
{
"id": "96384ada3ddffe94",
"type": "link in",
"z": "e2022f3797213292",
"name": "Сброс Таймера Авто-выключения",
"links": [
"49c2de739512f63e"
],
"x": 605,
"y": 400,
"wires": [
[
"76c598a7f58e7ef2"
]
]
},
{
"id": "76c598a7f58e7ef2",
"type": "change",
"z": "e2022f3797213292",
"name": "Сброс Таймера Авто-выключения",
"rules": [
{
"t": "set",
"p": "reset",
"pt": "msg",
"to": "stop",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1160,
"y": 400,
"wires": [
[
"d747581c05875140"
]
]
},
{
"id": "3aaa3b66d3c867c9",
"type": "server-state-changed",
"z": "e2022f3797213292",
"name": "Изменено Время Авто-выключения",
"server": "d262b87e.b0ac48",
"version": 6,
"outputs": 1,
"exposeAsEntityConfig": "",
"entities": {
"entity": [
"input_number.auto_off_fireplace_timing"
],
"substring": [],
"regex": []
},
"outputInitially": false,
"stateType": "str",
"ifState": "",
"ifStateType": "str",
"ifStateOperator": "является",
"outputOnlyOnStateChange": true,
"for": "0",
"forType": "num",
"forUnits": "minutes",
"ignorePrevStateNull": false,
"ignorePrevStateUnknown": false,
"ignorePrevStateUnavailable": false,
"ignoreCurrentStateUnknown": false,
"ignoreCurrentStateUnavailable": false,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "eventData"
},
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "triggerId"
}
],
"x": 150,
"y": 360,
"wires": [
[
"0598fdc1b02c8e8a"
]
]
},
{
"id": "6aed46c49381ad76",
"type": "server-state-changed",
"z": "e2022f3797213292",
"name": "Переключатель Камина нажат",
"server": "d262b87e.b0ac48",
"version": 6,
"outputs": 1,
"exposeAsEntityConfig": "",
"entities": {
"entity": [
"switch.fireplace"
],
"substring": [],
"regex": []
},
"outputInitially": false,
"stateType": "str",
"ifState": "",
"ifStateType": "str",
"ifStateOperator": "является",
"outputOnlyOnStateChange": true,
"for": "0",
"forType": "num",
"forUnits": "minutes",
"ignorePrevStateNull": false,
"ignorePrevStateUnknown": false,
"ignorePrevStateUnavailable": false,
"ignoreCurrentStateUnknown": false,
"ignoreCurrentStateUnavailable": false,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "eventData"
},
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "triggerId"
}
],
"x": 150,
"y": 80,
"wires": [
[
"a1d29d4c48c3b409"
]
]
},
{
"id": "bcf26e334a507ef8",
"type": "switch",
"z": "e2022f3797213292",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "включен",
"vt": "str"
},
{
"t": "eq",
"v": "выключен",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 570,
"y": 80,
"wires": [
[
"ae08ca697b2675c4"
],
[
"e27da748b8161e01"
]
],
"outputLabels": [
"включен",
"выключен"
]
},
{
"id": "a1d29d4c48c3b409",
"type": "api-current-state",
"z": "e2022f3797213292",
"name": "Проверка Состояния Камины",
"server": "d262b87e.b0ac48",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "является",
"entity_id": "input_boolean.fireplace_onoff",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "fireplaceState",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": 0,
"forType": "num",
"forUnits": "minutes",
"x": 400,
"y": 80,
"wires": [
[
"bcf26e334a507ef8"
]
]
},
{
"id": "ae08ca697b2675c4",
"type": "api-call-service",
"z": "e2022f3797213292",
"name": "Включить Камин",
"server": "d262b87e.b0ac48",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_on",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.fireplace_onoff"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_on",
"output_location": "",
"output_location_type": "none",
"x": 830,
"y": 40,
"wires": [
[
"18112a371a5730af"
]
]
},
{
"id": "e27da748b8161e01",
"type": "api-call-service",
"z": "e2022f3797213292",
"name": "Выключить Камин",
"server": "d262b87e.b0ac48",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_off",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.fireplace_onoff"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_off",
"output_location": "",
"output_location_type": "none",
"x": 830,
"y": 120,
"wires": [
[
"18112a371a5730af"
]
]
},
{
"id": "f1a9129f98b8ffe6",
"type": "api-call-service",
"z": "e2022f3797213292",
"name": "Выключить Камин",
"server": "d262b87e.b0ac48",
"version": 7,
"debugenabled": false,
"action": "switch.turn_off",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"switch.fireplace"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": true,
"domain": "switch",
"service": "turn_off",
"x": 1670,
"y": 460,
"wires": [
[
"0bc53e3b2e62d06e"
]
]
},
{
"id": "0598fdc1b02c8e8a",
"type": "subflow:109ae81398e4db33",
"z": "e2022f3797213292",
"name": "Автоматизация Ворота",
"x": 370,
"y": 360,
"wires": [
[
"96384ada3ddffe94",
"9bb3cef0f93bc9ca"
]
]
},
{
"id": "0bc53e3b2e62d06e",
"type": "api-call-service",
"z": "e2022f3797213292",
"name": "Выключить Камин",
"server": "d262b87e.b0ac48",
"version": 7,
"debugenabled": false,
"action": "input_boolean.turn_off",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_boolean.fireplace_onoff"
],
"labelId": [],
"data": "",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "input_boolean",
"service": "turn_off",
"output_location": "",
"output_location_type": "none",
"x": 1870,
"y": 460,
"wires": [
[]
]
},
{
"id": "d262b87e.b0ac48",
"type": "server",
"name": "Home Assistant",
"version": 5,
"addon": true,
"rejectUnauthorizedCerts": true,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": true,
"cacheJson": true,
"heartbeat": false,
"heartbeatInterval": "30",
"areaSelector": "friendlyName",
"deviceSelector": "friendlyName",
"entitySelector": "friendlyName",
"statusSeparator": "at: ",
"statusYear": "hidden",
"statusMonth": "short",
"statusDay": "numeric",
"statusHourCycle": "h23",
"statusTimeFormat": "h:m",
"enableGlobalContextStore": true
}
]
Ответ или решение
Эффективное управление таймером в Node-RED с помощью триггерного узла
Введение
Node-RED представляет собой мощный инструмент для визуального программирования, который широко используется для автоматизации различных устройств и систем. В вашем случае задача заключается в реализации автоматического выключения камина по заданному времени с использованием триггерного узла. Мы рассмотрим, как правильно настроить таймер с учетом динамических значений, которые предоставляют пользователи.
Проблема
Ключевая проблема, с которой вы столкнулись, заключается в том, что триггерный узел работает некорректно, не соблюдая временные интервалы, заданные пользователем с помощью переменной input_number.auto_off_fireplace_timing
. В результате, несмотря на то что узел начинает свою работу (отображается синий круг), он не выполняет ожидаемые действия по окончании отсчитываемого времени.
Анализ существующего решения
Вы правильно установили функцию, которая обрабатывает значение времени и рассчитывает продолжительность в миллисекундах:
const timingMinutes = Number(msg.auto_off_timing);
if (isNaN(timingMinutes) || timingMinutes <= 0) {
node.error("Invalid timing value", msg);
return null;
}
const timingMilliseconds = timingMinutes * 60 * 1000;
msg.delay = timingMilliseconds;
delete msg.reset;
return msg;
Однако вместо того, чтобы использовать msg.delay
, вы должны передать это значение в триггерный узел, используя правильные поля конфигурации.
Рекомендации по настройке триггерного узла
-
Настройка полей триггерного узла: Убедитесь, что в вашем триггерном узле
Auto-Off Timer
назначено значение для длительности:- Операция 1 (
op1
): Оставьте пустым, если не требуется ее выполнения. - Операция 2 (
op2
): Установите значение наpayload
или оставьте пустым в зависимости от того, как это будет обрабатываться в следующих узлах. - Длительность: Убедитесь, что это выражение ссылается на
msg.delay
, изменив полеduration
наmsg.delay
.
- Операция 1 (
-
Использование свойства
bytopic
: Если вы хотите делать различные операции с различными темами, установитеbytopic
в значение, по которому будет производиться выборкаmsg.topic
. -
Не забывайте про сброс таймера: Убедитесь, что механизм сброса триггерного узла правильно настроен. Например, при получении сигнала на сброс, отправляйте сообщение с
msg.reset
равнымstop
.
Отладка и визуализация
Чтобы отслеживать состояние таймера, вы можете использовать узел debug
, чтобы выводить сообщения на различных этапах. Например, можно выводить значение msg.delay
, чтобы убедиться, что оно корректно присваивается. Также стоит использовать узел status
, чтобы видеть текущее состояние триггерного узла.
node.status({fill:"green", shape:"dot", text:"Таймер запущен на " + msg.auto_off_timing + " минут"});
Добавление таких сообщений в узлы значительно облегчит отладку и поможет вам понять, на каком этапе возникает ошибка.
Заключение
Настройка динамического таймера в Node-RED может показаться сложной задачей, однако, следуя приведенным рекомендациям, вы сможете успешно справиться с этой задачей. Обратная связь от узлов, правильная передача значений и функционирование триггерного узла являются ключевыми аспектами для реализации вашей автоматизации. Не забывайте тестировать каждую часть потока, чтобы гарантировать его надёжность и точность.