Node-Red Notification with Data from Separate Entities

I am trying to create a flow that will grab data from separate entities. The first will tell me how long someone slept in hours and minutes and the second will show the sleep score.

How can I display both in 1 notification. Here is my attempt at the flow:


[{"id":"43eaf1c4e1bc3c15","type":"time-range-switch","z":"cde85205.f62c6","name":"5:00 am - 12:00pm","lat":"","lon":"","startTime":"05:00","endTime":"12:00","startOffset":0,"endOffset":0,"x":430,"y":1680,"wires":[["b810d7c503d587c0"],[]]},{"id":"d3b992563f8d7f0d","type":"server-state-changed","z":"cde85205.f62c6","name":"Matthew is Awake","server":"6e751b1b.8f17c4","version":6,"outputs":2,"exposeAsEntityConfig":"","entities":{"entity":["sensor.jonathan_s_sleep_stage"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"awake","ifStateType":"str","ifStateOperator":"is","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":230,"y":1680,"wires":[["43eaf1c4e1bc3c15"],[]]},{"id":"b810d7c503d587c0","type":"trigger","z":"cde85205.f62c6","name":"","op1":"","op2":"0","op1type":"nul","op2type":"str","duration":"90","extend":false,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":610,"y":1680,"wires":[["7d8a8a5f9da9fe03"]]},{"id":"7d8a8a5f9da9fe03","type":"api-current-state","z":"cde85205.f62c6","name":"Time Slept","server":"6e751b1b.8f17c4","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.jonathan_s_time_slept","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"slept","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":810,"y":1680,"wires":[["d9af8095adb54534"]]},{"id":"a11da70c48a3b8bc","type":"inject","z":"cde85205.f62c6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":600,"y":1740,"wires":[["7d8a8a5f9da9fe03"]]},{"id":"d9af8095adb54534","type":"api-current-state","z":"cde85205.f62c6","name":"Sleep Score","server":"6e751b1b.8f17c4","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.jonathan_s_sleep_quality_score","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"score","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":890,"y":1760,"wires":[["c380d5a0a246b4dc"]]},{"id":"c380d5a0a246b4dc","type":"join","z":"cde85205.f62c6","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":false,"accumulate":true,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":990,"y":1680,"wires":[["f93a4703bf9ddaa2","63026a4ca16c3764"]]},{"id":"f93a4703bf9ddaa2","type":"function","z":"cde85205.f62c6","name":"","func":"// Calculate hours slept\nlet sleptMinutes = msg.payload.slept; // Minutes from the first api-current-state\nlet sleepScore = msg.payload.score; // Score from the second api-current-state\n\n// Calculate hours from minutes\nmsg.hours = (sleptMinutes / 60).toFixed(2);\nmsg.score = sleepScore; // Assign the score directly\n\n// Prepare the message for notification\nmsg.message = `${msg.hours} hours and score of ${msg.score}.`;\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1120,"y":1680,"wires":[["0fde64a0845b56af","2103974d058099ba"]]},{"id":"63026a4ca16c3764","type":"debug","z":"cde85205.f62c6","name":"debug 106","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1150,"y":1620,"wires":[]},{"id":"0fde64a0845b56af","type":"api-call-service","z":"cde85205.f62c6","name":"Notify","server":"6e751b1b.8f17c4","version":7,"action":"notify.all_iphones","data":"{\n   \"title\": \"Jonathan's Sleep\",\n   \"message\": \"{{ payload }} hours and score of {{ score }}.\"\n}","dataType":"jsonata","x":730,"y":1940,"wires":[[]]},{"id":"2103974d058099ba","type":"debug","z":"cde85205.f62c6","name":"debug 107","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1280,"y":1660,"wires":[]},{"id":"6e751b1b.8f17c4","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}]

You don’t need the join node. In the current state nodes, you can set the output properties to store the entity’s state in locations like msg.slept and msg.score. Then, update your function to reference msg.slept instead of msg.payload.slept

1 Like