Node Red - Cisco Spark Integration: Code Review

Hi,

As I am new and also not a programmer I want to ask you to do a review of my Cisco Spark integration. Basically my flow is working, but I think it can be done much better.

Goal: Contact BOT and request Temperature of several rooms. Only one user should be allowed to do this.

image

  1. Webhook: Receiving Notification, when Bot is contacted
  2. Parse for MessageID
  3. Request Message, based on MessageID
  4. Check for valid Username
  5. Check for command

I think this part is ok, I do not know it here something could be improved.
But now lets go ahead with the second part, and I am pretty sure, this is not a good implementation:

Upper Flow:
6) Check 4 different TemperatureSensors from Home-Assistant
7) Write the Temperature in a Global Variable
8) Set a Delay to get always the same order
9) Join all 4 Values into one message
10) Store the combined message to another global variable

Lower Flow:
11) Delay to have the temperature values ready when this part is executed
12) Get all neccessary information and prepare new message
13) Send message to Cisco Spark

[{"id":"11f54195.f9ffae","type":"Spark Webhook","z":"2068111c.8b052e","profileConfig":"fafb13de.28f9d","resource":"messages","event":"created","host":"https://SERVER","name":"","x":290,"y":360,"wires":[["9e94bac7.4fd588","eb1f760b.33c7e8"]]},{"id":"9e94bac7.4fd588","type":"debug","z":"2068111c.8b052e","name":"Webhook","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":500,"y":320,"wires":[]},{"id":"eb1f760b.33c7e8","type":"Spark Payload Parser","z":"2068111c.8b052e","name":"","parsers":[{"key":"id","as":"messageId"}],"x":510,"y":360,"wires":[["604b58aa.aa3f98","65619f55.e13d8"]]},{"id":"604b58aa.aa3f98","type":"debug","z":"2068111c.8b052e","name":"MessageID","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":670,"y":320,"wires":[]},{"id":"65619f55.e13d8","type":"Spark API","z":"2068111c.8b052e","profileConfig":"637e9d73.264534","apiUrl":"https://SERVER/api/cisco_spark_v1.json","resource":"messages","method":"getMessage","name":"","x":730,"y":360,"wires":[["823c70d2.d728f","a104b87e.2ecc28"]]},{"id":"823c70d2.d728f","type":"debug","z":"2068111c.8b052e","name":"messages","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":950,"y":320,"wires":[]},{"id":"d0c7c09f.f7a0a","type":"switch","z":"2068111c.8b052e","name":"match & route commands","property":"payload.text","propertyType":"msg","rules":[{"t":"eq","v":"/temp","vt":"str"},{"t":"eq","v":"Node-Red-BOT /temp","vt":"str"},{"t":"neq","v":"/temp","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":1230,"y":360,"wires":[["b27548cc.a7fe38","b01cc36b.309f3","8caaef5e.726ec","14b92b4f.d22f65","bb2ba70c.6acd88","10f7cb25.c1b285"],["b27548cc.a7fe38","10f7cb25.c1b285"],["52002096.e17b4"]]},{"id":"b27548cc.a7fe38","type":"debug","z":"2068111c.8b052e","name":"OK","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1490,"y":320,"wires":[]},{"id":"52002096.e17b4","type":"debug","z":"2068111c.8b052e","name":"NOT OK","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1500,"y":400,"wires":[]},{"id":"b643af48.1ce16","type":"function","z":"2068111c.8b052e","name":"parse and format response","func":"// This function parses the Meraki Dashboard API response\n// and creates a message to POST to a Spark room.\n//response = msg.payload;\n//body = {}; //reset payload object for clarity\n//my_array = [];\n//counter = 0;\n//body.roomId = msg.roomId;\n\n//for (var key in response) {\n//  if (response.hasOwnProperty(key)) {\n//    counter += 1;\n//    var dev_mac = response[key].mac;\n//    var dev_serial = response[key].serial;\n//    var dev_model = response[key].model;\n//    my_array.push('`'+counter+\". model: \"+dev_model+\", serial: \"+dev_serial+ \", mac:\"+dev_mac+'`\\n');\n//  }\n//}\n//\n//var msg_markdown = my_array.join(\"\\n\");\n//body.markdown = msg_markdown;\n//msg.payload = {};\n//msg.payload.body = body;\n//return msg;\n//body = {};\n//body.roomId = msg.roomId;\n\n// ******************\n// Set Your Variables\n// ******************\nvar accessToken = \"TOKEN\"; // Your Access Token\nvar roomId = msg.payload.roomId;\nvar Temperatur = global.get(\"Temperatur-Webex\");\n\n// -- -- -- -- -- --\n// Build API Call\nmsg.url = \"https://api.ciscospark.com/v1/messages\";\nmsg.headers = { \n    'content-type': 'application/json',\n    'authorization': 'Bearer '+ accessToken \n};\nmsg.payload ={ \n    roomId: roomId,\n    markdown: Temperatur\n}\nmsg.method = \"post\";\n\nreturn msg;","outputs":1,"noerr":0,"x":1700,"y":360,"wires":[["92a89c8b.4cab6","52e70916.505608"]]},{"id":"92a89c8b.4cab6","type":"http request","z":"2068111c.8b052e","name":"","method":"use","ret":"txt","url":"","tls":"","x":1910,"y":360,"wires":[[]]},{"id":"52e70916.505608","type":"debug","z":"2068111c.8b052e","name":"Response","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1900,"y":320,"wires":[]},{"id":"a104b87e.2ecc28","type":"switch","z":"2068111c.8b052e","name":"match & route commands","property":"payload.personEmail","propertyType":"msg","rules":[{"t":"eq","v":"EMAIL","vt":"str"},{"t":"neq","v":"EMAIL","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":990,"y":360,"wires":[["d0c7c09f.f7a0a"],["ef2af161.ebac3"]]},{"id":"ef2af161.ebac3","type":"debug","z":"2068111c.8b052e","name":"Denied","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1180,"y":400,"wires":[]},{"id":"bb2ba70c.6acd88","type":"api-current-state","z":"2068111c.8b052e","name":"Kinderzimmer","server":"e76cb70.9b3bd48","halt_if":"","override_topic":true,"override_payload":true,"entity_id":"sensor.kinderzimmer_dominik_motion_sensor_temperature","x":1520,"y":120,"wires":[["725dc097.79c13"]]},{"id":"14b92b4f.d22f65","type":"api-current-state","z":"2068111c.8b052e","name":"Vorraum","server":"e76cb70.9b3bd48","halt_if":"","override_topic":true,"override_payload":true,"entity_id":"sensor.vorraum_dach_motion_sensor_temperature","x":1500,"y":160,"wires":[["7a2039a6.99a3e8"]]},{"id":"8caaef5e.726ec","type":"api-current-state","z":"2068111c.8b052e","name":"Arbeitszimmer","server":"e76cb70.9b3bd48","halt_if":"","override_topic":true,"override_payload":true,"entity_id":"sensor.arbeitszimmer_dach_motion_sensor_temperature","x":1520,"y":200,"wires":[["93a61f3b.04752"]]},{"id":"b01cc36b.309f3","type":"api-current-state","z":"2068111c.8b052e","name":"Außentemperatur","server":"e76cb70.9b3bd48","halt_if":"","override_topic":true,"override_payload":true,"entity_id":"sensor.pws_temp_c","x":1530,"y":240,"wires":[["e772e786.941c78"]]},{"id":"e772e786.941c78","type":"function","z":"2068111c.8b052e","name":"","func":"msg.payload = \"\\n\" + \"Außentemperatur: \" + msg.payload + \" °C\" + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":1690,"y":240,"wires":[["83565c04.3d48"]]},{"id":"93a61f3b.04752","type":"function","z":"2068111c.8b052e","name":"","func":"msg.payload = \"Arbeitszimmer: \" + msg.payload + \" °C\" + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":1690,"y":200,"wires":[["2ddde80d.6cb868"]]},{"id":"7a2039a6.99a3e8","type":"function","z":"2068111c.8b052e","name":"","func":"msg.payload = \"Vorraum: \" + msg.payload + \" °C\" + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":1690,"y":160,"wires":[["ad7daad0.7ad728"]]},{"id":"725dc097.79c13","type":"function","z":"2068111c.8b052e","name":"","func":"msg.payload = \"Kinderzimmer: \" + msg.payload + \" °C\";\nreturn msg;","outputs":1,"noerr":0,"x":1690,"y":120,"wires":[["79e16106.d65dd"]]},{"id":"79e16106.d65dd","type":"delay","z":"2068111c.8b052e","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1830,"y":120,"wires":[["83565c04.3d48"]]},{"id":"ad7daad0.7ad728","type":"delay","z":"2068111c.8b052e","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1830,"y":160,"wires":[["83565c04.3d48"]]},{"id":"2ddde80d.6cb868","type":"delay","z":"2068111c.8b052e","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1830,"y":200,"wires":[["83565c04.3d48"]]},{"id":"83565c04.3d48","type":"join","z":"2068111c.8b052e","name":"","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"4","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":2010,"y":180,"wires":[["68b1a53f.71007c","f178381.358b2c8"]]},{"id":"68b1a53f.71007c","type":"debug","z":"2068111c.8b052e","name":"Temperaturen","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":2180,"y":140,"wires":[]},{"id":"f178381.358b2c8","type":"function","z":"2068111c.8b052e","name":"Set Variable Temperaturen","func":"global.set(\"Temperatur-Webex\",msg.payload);","outputs":1,"noerr":0,"x":2220,"y":180,"wires":[[]]},{"id":"10f7cb25.c1b285","type":"delay","z":"2068111c.8b052e","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1500,"y":360,"wires":[["b643af48.1ce16"]]},{"id":"fafb13de.28f9d","type":"Spark Authentication","z":0,"name":"ebnerjoh_nr_bot"},{"id":"637e9d73.264534","type":"Spark Authentication","z":0,"name":"Webex Team Webhook"},{"id":"e76cb70.9b3bd48","type":"server","z":"","name":"Home Assistant","url":"https://SERVER","pass":"PASSWORD"}]

Best Regards,
Johannes

If you have to fudge in some delays so that your messages arrive in some expected order, then there is certainly room for improvement…

Since nodejs is single-threaded, I doubt there is any advantage to splitting your flow and trying to join the parts in a particular order. It would be simpler to wire all 4 HA calls in series, with a change node in between them to move the previous payload to some other property.