Cisco Spark Bot webhook receiver with Meraki Dashboard API example
Overview
This flow shows a basic example using a Node-RED flow to process "commands" issued to a Cisco Spark Bot (such as making calls to the Meraki Dashboard API for inventory or wifi information)
This sample flow is setup to:
Receive a Cisco Spark webhook POST initiated by Bot message sent to the Bot
Parse and map data.id from the webhook's payload to messageId for the next step
Run an API call to Spark to get the clear message text (providing messageId)
Match on message text or “commands” and run Meraki Dashboard API calls to get different bits of information (Meraki is an example and any subsequent actions are possible !)
Format the relevant pieces of the Dashboard API response and use the Bot to send a custom response to the Spark room
Add more "command" matches and subsequent "actions" to easily expand your Bot's capabilities
Resources
- Cisco Spark node (Nick Marus): https://flows.nodered.org/node/node-red-contrib-spark
- Learning Blog (Cory Guynn): http://internetoflego.com
[{"id":"595bf5db.1ce5dc","type":"Spark Webhook","z":"f3640125.5d455","profileConfig":"e144b4cd.23fd58","resource":"messages","event":"created","host":"http://[URL from Lab Spark room]","name":"","x":211.66674041748047,"y":63.75783729553223,"wires":[["dfa96419.9f22a8","60ff1164.92834"]]},{"id":"60ff1164.92834","type":"Spark Payload Parser","z":"f3640125.5d455","name":"","parsers":[{"key":"id","as":"messageId"}],"x":501.1399841308594,"y":64.02315902709961,"wires":[["a196f999.43db88","36241624.9a587a"]]},{"id":"36241624.9a587a","type":"Spark API","z":"f3640125.5d455","profileConfig":"e144b4cd.23fd58","apiUrl":"http://54.191.231.29:59001/api/cisco_spark_v1.json","resource":"Messages","method":"getMessage","name":"","x":782.9091415405273,"y":118.0387773513794,"wires":[["61c3ed40.8ab1c4","5bdf736d.f3083c"]]},{"id":"dfa96419.9f22a8","type":"debug","z":"f3640125.5d455","name":"incoming webhook","active":true,"console":"false","complete":"payload","x":466.29390716552734,"y":117.4158878326416,"wires":[]},{"id":"a196f999.43db88","type":"debug","z":"f3640125.5d455","name":"parser output","active":true,"console":"false","complete":"payload","x":734.1247024536133,"y":64.09617567062378,"wires":[]},{"id":"61c3ed40.8ab1c4","type":"debug","z":"f3640125.5d455","name":"message text","active":true,"console":"false","complete":"payload","x":1058.8938751220703,"y":118.71154022216797,"wires":[]},{"id":"cc59e550.8a5368","type":"debug","z":"f3640125.5d455","name":"match","active":true,"console":"false","complete":"payload","x":561.7786064147949,"y":293.78854608535767,"wires":[]},{"id":"33e51682.d8d0ba","type":"debug","z":"f3640125.5d455","name":"no match","active":true,"console":"false","complete":"payload","x":573.3683280944824,"y":449.85272789001465,"wires":[]},{"id":"5bdf736d.f3083c","type":"switch","z":"f3640125.5d455","name":"match & route commands","property":"payload.text","propertyType":"msg","rules":[{"t":"cont","v":"get inventory","vt":"str"},{"t":"cont","v":"get wifi","vt":"str"},{"t":"else"}],"checkall":"true","outputs":3,"x":356.7938003540039,"y":360.2278242111206,"wires":[["661c5d6d.6c1b44"],["cc59e550.8a5368","cd47df29.04645"],["33e51682.d8d0ba"]]},{"id":"661c5d6d.6c1b44","type":"function","z":"f3640125.5d455","name":"Build Dashboard API headers","func":"// This function creates HTTP GET parameters\n// for sending to the Meraki Dashboard\napi_key = '[your dashboard api key]';\ndashboard_header = {\n 'x-cisco-meraki-api-key': api_key,\n 'Content-Type': 'application/json'\n};\n\nbot_cmd = msg.payload.text;\nmsg.headers = dashboard_header;\nmsg.roomId = msg.payload.roomId;\nreturn msg;\n","outputs":1,"noerr":0,"x":661.9321670532227,"y":347.41892528533936,"wires":[["56805abc.5c0ae4","96ae664d.290f18"]]},{"id":"c37fb715.262648","type":"function","z":"f3640125.5d455","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.\nresponse = msg.payload;\nbody = {}; //reset payload object for clarity\nmy_array = [];\ncounter = 0;\nbody.roomId = msg.roomId;\n\nfor (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\nvar msg_markdown = my_array.join(\"\\n\");\nbody.markdown = msg_markdown;\nmsg.payload = {};\nmsg.payload.body = body;\nreturn msg;","outputs":1,"noerr":0,"x":1335.8622131347656,"y":347.2817339897156,"wires":[["f819a305.f24d","c04fdc88.e7f49"]]},{"id":"56805abc.5c0ae4","type":"http request","z":"f3640125.5d455","name":"GET /organizations/[org_id]/inventory","method":"GET","ret":"obj","url":"https://dashboard.meraki.com/api/v0/organizations/650207196201616360/inventory","tls":"","x":1017.2724151611328,"y":347.816593170166,"wires":[["c37fb715.262648","c366a49c.8aece8"]]},{"id":"f13c8ce2.d1f5d","type":"http request","z":"f3640125.5d455","name":"GET /networks/[net_id]/ssids/0","method":"GET","ret":"obj","url":"https://dashboard.meraki.com/api/v0/networks/[networkId]/ssids/0","tls":"","x":999.2369995117188,"y":391.2841205596924,"wires":[["60d0f593.f3383c","58bd5d26.5cffa4"]]},{"id":"f819a305.f24d","type":"debug","z":"f3640125.5d455","name":"POST response","active":true,"console":"false","complete":"payload","x":1577.3046989440918,"y":300.6250352859497,"wires":[]},{"id":"c04fdc88.e7f49","type":"Spark API","z":"f3640125.5d455","profileConfig":"e144b4cd.23fd58","apiUrl":"http://54.191.231.29:59001/api/cisco_spark_v1.json","resource":"Messages","method":"createMessage","name":"","x":1660.5099411010742,"y":368.1543731689453,"wires":[[]]},{"id":"d14732e5.7875e","type":"debug","z":"f3640125.5d455","name":"POST response","active":true,"console":"false","complete":"payload","x":1567.30464553833,"y":433.1250286102295,"wires":[]},{"id":"60d0f593.f3383c","type":"function","z":"f3640125.5d455","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.\nresponse = msg.payload;\nbody = {}; //reset payload object for clarity\nbody.roomId = msg.roomId;\n\nfor (var key in response) {\n if (response.hasOwnProperty(key)) {\n if (response[key].number == 0) {\n ssid_name = response[key].name;\n ssid_psk = response[key].psk;\n }\n }\n}\n\nbody.markdown = \"Guest WiFi Name `\"+ssid_name+\"` Password `\"+ssid_psk+\"`\";\nmsg.headers = '';\nmsg.payload = {};\nmsg.payload.body = body;\nreturn msg;","outputs":1,"noerr":0,"x":1333.971321105957,"y":391.6250171661377,"wires":[["d14732e5.7875e","c04fdc88.e7f49"]]},{"id":"cd47df29.04645","type":"function","z":"f3640125.5d455","name":"Build Dashboard API headers","func":"// This function creates HTTP GET parameters\n// for sending to the Meraki Dashboard\napi_key = '[your dashboard api key]';\ndashboard_header = {\n 'x-cisco-meraki-api-key': api_key,\n 'Content-Type': 'application/json'\n};\n\nbot_cmd = msg.payload.text;\nmsg.headers = dashboard_header;\nmsg.roomId = msg.payload.roomId;\nreturn msg;\n","outputs":1,"noerr":0,"x":663.9713287353516,"y":391.45833587646484,"wires":[["f13c8ce2.d1f5d","8b301473.779318"]]},{"id":"c366a49c.8aece8","type":"debug","z":"f3640125.5d455","name":"Dashboard response","active":true,"console":"false","complete":"payload","x":1271.4713134765625,"y":284.7916564941406,"wires":[]},{"id":"96ae664d.290f18","type":"debug","z":"f3640125.5d455","name":"Dashboard GET params","active":true,"console":"false","complete":"payload","x":968.1380004882812,"y":283.125,"wires":[]},{"id":"8b301473.779318","type":"debug","z":"f3640125.5d455","name":"Dashboard GET params","active":true,"console":"false","complete":"payload","x":931.4713134765625,"y":493.1249694824219,"wires":[]},{"id":"58bd5d26.5cffa4","type":"debug","z":"f3640125.5d455","name":"Dashboard response","active":true,"console":"false","complete":"payload","x":1226.4713134765625,"y":478.95831298828125,"wires":[]},{"id":"e144b4cd.23fd58","type":"Spark Authentication","z":"","name":"lab bot"}]