Help merging 2 Node Red flows in 1

isn’t attribute a state ‘member’?
I’m asking myself from time to time.
Anyway try to react on state change then compare attribute value with one stored in flow variable.

At this moment I’m not sure NR can create sensors with names generated dynamically in runtime. I guess it cannot.

I don’t think the state node will trigger if an entity’s attribute changes. I want it to trigger only when a light’s brightness or color temperature changes but only once it’s changed for a few seconds. The reason for this is that I can use a trigger-state node to trigger a flow when an attribute changes but it triggers a ridiculous amount of messages for any change to my Hue lights (it also triggers for several entity attribute changes that I don’t care to be listening to). So if I change the brightness and color of a light it triggers my flow several times on the way to its destination brightness/color. The problem is much worse when I change the brightness/color of more than 1 light, which I do way more often

Either option is doable.

I personally would go with the approach of monitoring the attributes and then continuing if x time has elapsed.

I can mock either way up if you want an example.

That would be great if you could do that. Just to be clear though, creating sensors dynamically through node red would not be the same as creating a template sensor in the config file, right? As in the sensor wouldn’t automatically update any time the entity whose attribute the sensor is referencing is updated?

You can make the sensor created in NR update just like a template sensor would. You would just need to listen for the change and update the sensor.

Not really tested all that much but example 1 shows creating real entities in HA and the second shows creating temp ones that will disappear after a HA reset and will only appear again after their state changes.

[{"id":"d5c4ef79.0c564","type":"ha-api","z":"b28195ad.c495e8","name":"Register Sensor","debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"","dataType":"json","location":"here","locationType":"msg","responseType":"json","x":912,"y":112,"wires":[["6cba3632.d10ad8"]]},{"id":"d872791e.7e3db8","type":"server-events","z":"b28195ad.c495e8","name":"","event_type":"home_assistant_client","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"waitForRunning":true,"x":168,"y":112,"wires":[["cab5b48c.7d4408"]]},{"id":"9ddb7a33.f8dad8","type":"ha-api","z":"b28195ad.c495e8","name":"Update Sensor","debugenabled":true,"protocol":"websocket","method":"get","path":"","data":"","dataType":"json","location":"payload","locationType":"msg","responseType":"json","x":912,"y":208,"wires":[[]]},{"id":"3066ba37.c8ef16","type":"comment","z":"b28195ad.c495e8","name":"Register Sensors","info":"","x":128,"y":64,"wires":[]},{"id":"9df1457d.2665c8","type":"comment","z":"b28195ad.c495e8","name":"Update Sensors","info":"","x":128,"y":160,"wires":[]},{"id":"cab5b48c.7d4408","type":"switch","z":"b28195ad.c495e8","name":"running?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"running","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":364,"y":112,"wires":[["28c3215c.c54dce"]]},{"id":"fe75725c.0db45","type":"comment","z":"b28195ad.c495e8","name":"Update Sensors after registering them","info":"","x":518,"y":160,"wires":[]},{"id":"a158770b.9ec218","type":"ha-get-entities","z":"b28195ad.c495e8","name":"get all lights","rules":[{"property":"entity_id","logic":"starts_with","value":"light.","valueType":"str"}],"output_type":"split","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":582,"y":112,"wires":[["cb2f3f76.c36ce"]]},{"id":"cb2f3f76.c36ce","type":"function","z":"b28195ad.c495e8","name":"","func":"const id = msg.payload.entity_id.split(\".\")[1];\nconst node_id = `${id}_brightness`;\nconst name = msg.payload.attributes.friendly_name ? `${msg.payload.attributes.friendly_name} Brightness` : `${id.replace(\"_\", \" \")} brightness`;\n\nmsg.data = msg.payload;\nmsg.payload = {\n    data: {\n        type:\"nodered/discovery\",\n        component: \"sensor\",\n        server_id: \"home\",\n        node_id,\n        config: {\n           name\n        }\n    }\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":748,"y":112,"wires":[["d5c4ef79.0c564"]]},{"id":"28c3215c.c54dce","type":"change","z":"b28195ad.c495e8","name":"","rules":[{"t":"delete","p":"createdEntities","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":463,"y":112,"wires":[["a158770b.9ec218"]],"l":false},{"id":"6cba3632.d10ad8","type":"function","z":"b28195ad.c495e8","name":"","func":"const id = msg.data.entity_id.split(\".\")[1];\nconst node_id = `${id}_brightness`;\nconst name = msg.data.attributes.friendly_name ? `${msg.data.attributes.friendly_name} Brightness` : `${id.replace(\"_\", \" \")} brightness`;\nconst brightness = msg.data.state !== \"on\" ? 0 : (msg.data.attributes.brightness || 0);\n\nmsg.payload = {\n    data: {\n        type:\"nodered/entity\",\n        server_id: \"home\",\t \n        node_id,\n        state: brightness\n    }\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":748,"y":208,"wires":[["9ddb7a33.f8dad8"]]},{"id":"1c0038cc.619de7","type":"server-state-changed","z":"b28195ad.c495e8","name":"","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"^light\\.(?!.*\\_brightness$).*","entityidfiltertype":"regex","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":208,"y":208,"wires":[["8c2a719c.02828"]]},{"id":"8c2a719c.02828","type":"change","z":"b28195ad.c495e8","name":"","rules":[{"t":"set","p":"data","pt":"msg","to":"msg.data.new_state","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":463,"y":208,"wires":[["6cba3632.d10ad8"]],"l":false}]
[{"id":"a0279b06.8882a8","type":"function","z":"b28195ad.c495e8","name":"","func":"const e = msg.data.new_state;\nconst state = e.state !== \"on\" ? 0 : (e.attributes.brightness || 0);\n\nmsg.payload = {\n    path: `states/${e.entity_id.replace(\"light.\", \"sensor.\")}_brightness`,\n    data: {\n        state\n    }\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":460,"y":416,"wires":[["49dc0d09.cd7074"]]},{"id":"47f2fcc.51cc604","type":"server-state-changed","z":"b28195ad.c495e8","name":"","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"^light\\.(?!.*\\_brightness$).*","entityidfiltertype":"regex","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":208,"y":416,"wires":[["a0279b06.8882a8"]]},{"id":"49dc0d09.cd7074","type":"ha-api","z":"b28195ad.c495e8","name":"create temp sensor","debugenabled":true,"protocol":"http","method":"post","path":"","data":"","dataType":"json","location":"payload","locationType":"msg","responseType":"json","x":666,"y":416,"wires":[[]]}]
2 Likes

Thank you again for the great examples!!
I saw that in the first flow, you are using websocket and HTTP on the second. Any reason why? I thought websocket is preferable…

the second one is using POST /api/states/<entity_id> https://developers.home-assistant.io/docs/api/rest/ because it doesn’t require you to create an HA entity first. It’s just a quick and dirty way to make temporary entities.

Updates or creates a state. You can create any state that you want, it does not have to be backed by an entity in Home Assistant.

Thanks. I am always using the quick and dirty way.
I couldn’t find the documentation to create entities the “nice” way using websocket. That part (AFAIK) is not documented on the websocket api page…
Is there a doc to explain why:

msg.payload = {
    data: {
        type:"nodered/discovery",
        component: "sensor",
        server_id: "home",
        node_id,
        config: {
           name
        }
    }
};

Should be like that?

I have tried to mimic @kermit example and it doesn’t work.

[{"id":"5614f8b6.1a8d08","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":990,"y":2640,"wires":[]},{"id":"49c6d3eb.60806c","type":"inject","z":"c07c0ac5.ca6f98","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":500,"y":2640,"wires":[["f81c7076.aca23"]]},{"id":"a08a12f1.8668a","type":"ha-api","z":"c07c0ac5.ca6f98","name":"","debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"","dataType":"json","location":"payload","locationType":"msg","responseType":"json","x":820,"y":2640,"wires":[["5614f8b6.1a8d08"]]},{"id":"f81c7076.aca23","type":"function","z":"c07c0ac5.ca6f98","name":"","func":"const node_id = 'conso_gaz';\nconst name = 'conso'\nmsg.data = msg.payload;\nmsg.payload = {\n    data: {\n        type:\"nodered/discovery\",\n        component: \"sensor\",\n        server_id: \"home\",\n        node_id,\n        config: {\n           name\n        }\n    }\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":660,"y":2640,"wires":[["a08a12f1.8668a"]]},{"id":"6b0a6ba0.949944","type":"ha-api","z":"c07c0ac5.ca6f98","name":"Update Sensor","debugenabled":true,"protocol":"websocket","method":"get","path":"","data":"","dataType":"json","location":"payload","locationType":"msg","responseType":"json","x":960,"y":2700,"wires":[["5614f8b6.1a8d08"]]},{"id":"664bf095.348d1","type":"function","z":"c07c0ac5.ca6f98","name":"","func":"const node_id = 'conso_gaz';\nconst name = 'conso;'\n\nmsg.payload = {\n    data: {\n        type:\"nodered/entity\",\n        server_id: \"home\",\t \n        node_id,\n        state: 234\n    }\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":796,"y":2700,"wires":[["6b0a6ba0.949944"]]},{"id":"d26c8c4d.65c8e","type":"inject","z":"c07c0ac5.ca6f98","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":620,"y":2700,"wires":[["664bf095.348d1"]]}]

The api node replies “success”… but, I can’t see the supposedly created sensor in HA.

There are no endpoints in HA core that allow you to create entities via a WebSocket. That’s why I created the NR custom integration the creates several endpoints that allows this. There is really no documentation as it was only meant to be used with NR as such everything is driven via the UI.

The closest thing you’ll find to documentation other than just looking through the code is this thread.

https://community.home-assistant.io/t/custom-component-for-node-red-contrib-home-assistant-websocket/150736/7?u=kermit

Your export works for me.

Thanks for your answer.

  • After having restarted HA, I can now see the entity being created in HA. All good (almost)!
  • I have just upgraded to 0.28.0. The flow that was giving me success yesterday, is now complaining with:
"TypeError: Cannot read property 'value' of undefined"

coming out of the API call…

Was there a change between 0.27.9 and 0.28.0 in this respect?

what node is throwing that error?

The “API” Node. Using the same flow copied 2 posts above.
Only difference being the upgrade to 0.28.0.

definitely broke it. accidentally committed a file

It happens, even to the best :slight_smile: (as we say in my home language)

Just upgraded to 0.29.0. The api call is fixed.
However (except if I messed up something) the “entity” node doesn’t seem to work any more. I am trying to create new entities. I can see the “Registered”. However, I can’t see it in the entities in HA. And I can’t (eg) toggle a newly created switch…

Here is a quick and dirty example that used to work…

[{"id":"123ae7c0.58ab28","type":"ha-entity","z":"c07c0ac5.ca6f98","name":"","server":"","version":1,"debugenabled":false,"outputs":2,"entityType":"switch","config":[{"property":"name","value":"try_me"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":450,"y":3000,"wires":[["e69a1437.7ee568"],["d0e0f784.4c23c8"]]},{"id":"e69a1437.7ee568","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":650,"y":2980,"wires":[]},{"id":"d0e0f784.4c23c8","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":650,"y":3040,"wires":[]},{"id":"6650a40f.6491dc","type":"inject","z":"c07c0ac5.ca6f98","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":440,"y":3100,"wires":[["d1ffd336.875a1"]]},{"id":"d1ffd336.875a1","type":"api-call-service","z":"c07c0ac5.ca6f98","name":"","server":"","version":1,"debugenabled":false,"service_domain":"switch","service":"toggle","entityId":"switch.try_me","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":640,"y":3100,"wires":[[]]}]

Nothing happens when I toggle the (supposedly) newly created switch.

For me it is working as intended. the switch goes from on to off. entity nodes of type switch don’t output anything on state change, change in the new future. If you want to have the node output you need to use the nodered.trigger service.

Still no luck with:

[{"id":"123ae7c0.58ab28","type":"ha-entity","z":"c07c0ac5.ca6f98","name":"","server":"","version":1,"debugenabled":false,"outputs":2,"entityType":"switch","config":[{"property":"name","value":"myswitch"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":450,"y":3000,"wires":[["e69a1437.7ee568"],["d0e0f784.4c23c8"]]},{"id":"e69a1437.7ee568","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":650,"y":2980,"wires":[]},{"id":"d0e0f784.4c23c8","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":650,"y":3040,"wires":[]},{"id":"6650a40f.6491dc","type":"inject","z":"c07c0ac5.ca6f98","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":440,"y":3100,"wires":[["d1ffd336.875a1"]]},{"id":"d1ffd336.875a1","type":"api-call-service","z":"c07c0ac5.ca6f98","name":"","server":"","version":1,"debugenabled":false,"service_domain":"nodered","service":"trigger","entityId":"switch.myswitch","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":650,"y":3100,"wires":[[]]},{"id":"88ff17c.f14c9e8","type":"api-current-state","z":"c07c0ac5.ca6f98","name":"","server":"","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"switch.myswitch","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":650,"y":3200,"wires":[["709bbe9f.a2274"]]},{"id":"c225acb5.9700e","type":"inject","z":"c07c0ac5.ca6f98","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":410,"y":3200,"wires":[["88ff17c.f14c9e8"]]},{"id":"709bbe9f.a2274","type":"debug","z":"c07c0ac5.ca6f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":910,"y":3200,"wires":[]}]

The current_state (last flow) gives me:

"Entity could not be found in cache for entity_id: switch.myswitch"