Skip to content

Instantly share code, notes, and snippets.

@dexterlabora
Last active July 19, 2017 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dexterlabora/a4d9b0b931c43cbb93f76961117bbf46 to your computer and use it in GitHub Desktop.
Save dexterlabora/a4d9b0b931c43cbb93f76961117bbf46 to your computer and use it in GitHub Desktop.
Node-RED Cisco Meraki API Demo Labs
[{"id":"23e64752.6bedb8","type":"tab","label":"Location API"},{"id":"466595c5.4621ec","type":"tab","label":"Captive Portal"},{"id":"1f491da9.9d14e2","type":"tab","label":"Dashboard API - Admin Form"},{"id":"394a1eba.47a102","type":"tab","label":"Cisco Spark"},{"id":"ff3c6aec.eaab38","type":"mongodb","hostname":"127.0.0.1","port":"27017","db":"test","name":""},{"id":"ddd53c8a.50174","type":"Spark Authentication","z":"","name":"Cory"},{"id":"d1246adf.32e488","type":"mongodb2","z":"23e64752.6bedb8","uri":"mongodb://localhost:27017/test","name":"test","options":"","parallelism":"-1"},{"id":"34e2ddd5.605be2","type":"mongodb in","z":"23e64752.6bedb8","mongodb":"ff3c6aec.eaab38","name":"cmx data","collection":"cmx","operation":"find","x":480,"y":620,"wires":[["5543ec24.5d4b14","61baad59.306584"]]},{"id":"2cd857e8.de1398","type":"mongodb out","z":"23e64752.6bedb8","mongodb":"ff3c6aec.eaab38","name":"cmx data","collection":"cmx","payonly":true,"upsert":false,"multi":false,"operation":"store","x":600,"y":340,"wires":[]},{"id":"61baad59.306584","type":"http response","z":"23e64752.6bedb8","name":"cmx response","x":800,"y":620,"wires":[]},{"id":"6d047597.20811c","type":"debug","z":"23e64752.6bedb8","name":"CMX Data","active":true,"console":"false","complete":"true","x":610,"y":260,"wires":[]},{"id":"35a99974.a8ff56","type":"http in","z":"23e64752.6bedb8","name":"[get] /cmxNative","url":"/cmxNative","method":"get","swaggerDoc":"","x":120,"y":120,"wires":[["6198d8f6.8fe428","fefd4222.3ad27"]]},{"id":"6198d8f6.8fe428","type":"function","z":"23e64752.6bedb8","name":"validate-validator - UPDATE","func":"// This node accepts a message with the validator defined in the URL\n// Example: http://yourserver:1880/cmx?validator=8e0846499d9a3f6d23f7868c4d55b9d6325035f5\n// By default, all API requests are accepted (for testing purposes)\n//~~~~~~~~~\n//validator = msg.payload.validator;\n\n\n\n//Alternatively, set the validator variable to match the Meraki network\n//The URL will not need to include the validator string, for enhanced security\n//~~~~~~~~~\nvalidator = \"8e0846499d9a3f6c23f7868c4c25b9d6325035f5\";\n\n\nmsg.payload = validator;\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":120,"wires":[["8783bcc1.17d18","b5282146.01cb6"]]},{"id":"8783bcc1.17d18","type":"http response","z":"23e64752.6bedb8","name":"cmx response","x":600,"y":120,"wires":[]},{"id":"fefd4222.3ad27","type":"debug","z":"23e64752.6bedb8","name":"CMX validator raw","active":true,"console":"false","complete":"payload","x":330,"y":160,"wires":[]},{"id":"f5a1acf2.34389","type":"http in","z":"23e64752.6bedb8","name":"[get] /showcmxNative","url":"/showcmxNative","method":"get","swaggerDoc":"","x":140,"y":620,"wires":[["91c90923.b71a28"]]},{"id":"965ee2b3.b3484","type":"http in","z":"23e64752.6bedb8","name":"[get] /showcmxhtml","url":"/showcmxhtml","method":"get","swaggerDoc":"","x":132,"y":758,"wires":[["71ed23c9.ccb47c","6cfcbf4f.e9953"]]},{"id":"45bb210d.35d93","type":"template","z":"23e64752.6bedb8","name":"Parse Data","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"\n{{#payload}}\n <h1>data.apMac = {{data.apMac}}</h1>\n {{#data.observations}}\n <table border=\"1\" style=\"width:100%\">\n <tr>\n <td >{{@index}}</td>\n <td width=\"300\">clientMac = {{clientMac}}</td>\n <td width=\"300\">manufacturer = {{manufacturer}}</td>\n <td width=\"300\">seenTime = {{seenTime}}</td>\n <td width=\"300\">lat = {{location.lat}}</td>\n <td width=\"300\">lng = {{location.lng}}</td>\n <td width=\"300\">unc = {{location.unc}}</td>\n <td width=\"300\">x = {{x}}</td>\n <td width=\"300\">y = {{y}}</td>\n </tr>\n </table>\n\n \n {{/data.observations}}\n <br>\n{{/payload}}\n\n\n","x":650,"y":760,"wires":[["eaee0082.0c467"]]},{"id":"eaee0082.0c467","type":"http response","z":"23e64752.6bedb8","name":"","x":790,"y":760,"wires":[]},{"id":"477d433a.c3b9dc","type":"mongodb in","z":"23e64752.6bedb8","mongodb":"ff3c6aec.eaab38","name":"cmx data","collection":"cmx","operation":"find","x":480,"y":760,"wires":[["45bb210d.35d93","71ce80c9.7bf5f"]]},{"id":"d0c29ae5.47c2d8","type":"comment","z":"23e64752.6bedb8","name":"Location Data - HTML table","info":"CMX in HTML table\n","x":137,"y":715,"wires":[]},{"id":"612b4c90.1476e4","type":"comment","z":"23e64752.6bedb8","name":"Location API core mechanics","info":"CMX/Location API core functions","x":140,"y":80,"wires":[]},{"id":"71ed23c9.ccb47c","type":"function","z":"23e64752.6bedb8","name":"limit results","func":"msg.limit = 2; \nmsg.sort = {\"_id\":-1};\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":760,"wires":[["477d433a.c3b9dc"]]},{"id":"71ce80c9.7bf5f","type":"function","z":"23e64752.6bedb8","name":"Extract GPS","func":"var coords = [];\n\nfor (i = 0 ; i < msg.payload.length; i++) {\n y = msg.payload[i];\n\n for(j = 0; j < y.data.observations.length; j++) {\n x = y.data.observations[j];\n coords.push({\"lat\" : x.location.lat, \"lng\" : x.location.lng});\n }\n}\n\nmsg.payload = coords;\nreturn msg;\n","outputs":1,"noerr":0,"x":490,"y":820,"wires":[["702b60ea.fbd45"]]},{"id":"702b60ea.fbd45","type":"debug","z":"23e64752.6bedb8","name":"Location Data HTML","active":false,"console":"false","complete":"payload","x":680,"y":820,"wires":[]},{"id":"91c90923.b71a28","type":"function","z":"23e64752.6bedb8","name":"limit results","func":"msg.limit = 2;\nmsg.sort = {\"_id\":-1};\nreturn msg;","outputs":1,"noerr":0,"x":327,"y":618,"wires":[["34e2ddd5.605be2"]]},{"id":"dce3f2cb.1279c","type":"comment","z":"23e64752.6bedb8","name":"Location Data - JSON format","info":"","x":140,"y":580,"wires":[]},{"id":"b5282146.01cb6","type":"debug","z":"23e64752.6bedb8","name":"CMX Validator","active":true,"console":"false","complete":"payload","x":600,"y":160,"wires":[]},{"id":"fb555e37.76109","type":"function","z":"23e64752.6bedb8","name":"validate-secret - UPDATE","func":"// This node verifies that the secrect configured\n// on the Meraki Dashboard Network, matches.\n//var secret = \"merakilous\"; \nvar secret = \"supersecret\";\n\nif(msg.payload.secret == secret){\n return msg;\n}else{\n // Secret is invalid\n \n}\n\n","outputs":1,"noerr":0,"x":350,"y":220,"wires":[["6d047597.20811c","d6faa94c.ff9828","2cd857e8.de1398","4f20f33e.5419fc"]]},{"id":"16e0d663.61272a","type":"comment","z":"23e64752.6bedb8","name":"Connect DB to function to store data","info":"","x":830,"y":340,"wires":[]},{"id":"464ec513.99627c","type":"debug","z":"23e64752.6bedb8","name":"CMX post","active":false,"console":"false","complete":"payload","x":300,"y":260,"wires":[]},{"id":"d6faa94c.ff9828","type":"http response","z":"23e64752.6bedb8","name":"cmx response","x":600,"y":220,"wires":[]},{"id":"ee6609b7.aa2728","type":"comment","z":"23e64752.6bedb8","name":"Meraki Location API - Using Native Nodes -- README","info":"This flow demonstrates how to interact with the\nMeraki CMX (Scanning) Location API.\n\n# Be sure to update the validator and secret\n\nThe \"CMX core functions\" consist of two REST endpoints.\nThe 'get' enpoint waits to hear from Meraki,\nwhich will send a request to this server. The flow will \nthen respond with the \"validator\", which was defined in \nthe Meraki Dashboard. If the correct validator is returned, \nMeraki has confirmed that it is sending location data to \nthe correct server.\n\nThe second enpoint accepts 'post' requests, which will\nbe receiving the JSON structured location data from Meraki.\n\nOnce the data has arrived in the `msg.payload`, the results\nwill be stored in a local MongoDB database if the supplied secret\nmatches what's defined in the global variables. This is to ensure\nthat it is in fact Meraki sending this data. \n\nThe data can then be retrieved by opening the other 'get' endpoints, such \nas /showcmxNative.\n\n","x":461,"y":27,"wires":[]},{"id":"6cfcbf4f.e9953","type":"debug","z":"23e64752.6bedb8","name":"","active":true,"console":"false","complete":"true","x":310,"y":800,"wires":[]},{"id":"38b92280.fdbc3e","type":"debug","z":"466595c5.4621ec","name":"excapSignOn raw data","active":true,"console":"false","complete":"payload","x":200,"y":480,"wires":[]},{"id":"1e12818.0d9077f","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapSignOn","method":"get","swaggerDoc":"","x":150,"y":440,"wires":[["38b92280.fdbc3e","393f68cf.d48a98"]]},{"id":"6ca346b3.4b4ff8","type":"http response","z":"466595c5.4621ec","name":"","x":770,"y":160,"wires":[]},{"id":"78d34df9.a686b4","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapClick","method":"get","swaggerDoc":"","x":140,"y":120,"wires":[["ab0e3134.28724","8ca98db1.694cf"]]},{"id":"bbd31662.434dc8","type":"http response","z":"466595c5.4621ec","name":"","x":770,"y":480,"wires":[]},{"id":"5e0dd8a.6daa128","type":"template","z":"466595c5.4621ec","name":"HTML Login Page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n{{{payload.css}}}\n\n\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n <title>Registration Form</title>\n\n</head>\n<body>\n\n \n\n\n <div class=\"main-content\">\n <form class=\"form-register\" method=POST action={{payload.login_url}} />\n <input type=\"hidden\" name=\"continue_url\" value={{payload.continue_url}} />\n <input type=\"hidden\" name=\"host\" value ={{host}}>\n <input type=\"hidden\" name=\"base_grant_url\" value = {{payload.base_grant_url}}/>\n <input type=\"hidden\" name=\"user_continue_url\" value = {{payload.user_continue_url}}/>\n <input type=\"hidden\" name=\"node_mac\" value = {{payload.node_mac}}/>\n <input type=\"hidden\" name=\"client_ip\" value = {{payload.client_ip}}/>\n <input type=\"hidden\" name=\"client_mac\" value = {{payload.client_mac}}/>\n <input type=\"hidden\" name=\"success_url\" value={{payload.continue_url}} />\n\n <div class=\"form-register-with-email\">\n\n <div class=\"form-white-background\">\n\n <div class=\"form-title-row\">\n <h1>Login to WiFi</h1>\n </div>\n\n <div class=\"form-row\">\n <label>\n <span>Email</span>\n <input type=\"email\" name=\"email\" required>\n </label>\n </div>\n\n <div class=\"form-row\">\n <label>\n <span>Password</span>\n <input type=\"password\" name=\"password\" required>\n </label>\n </div>\n\n <div class=\"form-row\">\n <label class=\"form-checkbox\">\n <input type=\"checkbox\" name=\"checkbox\" checked value=\"accepted\" required>\n <span>I agree to the <a href=\"/excapTerms\" target\"_blank\">terms and conditions</a></span>\n </label>\n </div>\n\n <div class=\"form-row\">\n <button type=\"submit\">Register</button>\n </div>\n\n </div>\n\n </div>\n\n <!-- Future Social Features\n <div class=\"form-sign-in-with-social\">\n\n <div class=\"form-row form-title-row\">\n <span class=\"form-title\">Sign in with</span>\n </div>\n\n <a href=\"#\" class=\"form-google-button\">Google</a>\n <a href=\"#\" class=\"form-facebook-button\">Facebook</a>\n <a href=\"#\" class=\"form-twitter-button\">Twitter</a>\n \n\n </div>\n -->\n\n </form>\n Your IP: {{payload.client_ip}}\n <br>\n Your MAC: {{payload.client_mac}}\n\n </div>\n\n</body>\n\n</html>","x":570,"y":480,"wires":[["bbd31662.434dc8"]]},{"id":"ab0e3134.28724","type":"function","z":"466595c5.4621ec","name":"Set login_url","func":"msg.payload.login_url = msg.payload.base_grant_url + '?continue_url=' + msg.payload.user_continue_url;\n\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":120,"wires":[["2ef98b9a.122aa4"]]},{"id":"8ca98db1.694cf","type":"debug","z":"466595c5.4621ec","name":"excapClick raw data","active":true,"console":"false","complete":"payload","x":200,"y":160,"wires":[]},{"id":"6bab932f.7c02bc","type":"comment","z":"466595c5.4621ec","name":"Meraki Click-through, read more...","info":"Configure by placing this host server address\nfollowed by /excapClick in the Custom Splash Page URL\nsection of the Meraki Dashboard.\n\nie. https://yourserver:1880/excapClick\n\nBe sure to update the \"walled garden\" in the \nMeraki Dashboard with the IP address of your \nserver and any other resources required before\nlogin, such as your website, images, CSS, etc.\n\nThe HTML page can be modified as needed. \n","x":173,"y":79,"wires":[]},{"id":"9b8abc89.d84f3","type":"comment","z":"466595c5.4621ec","name":"Meraki Sign-on, read more...","info":"Configure by placing this host server address\nfollowed by /excapClick in the Custom Splash Page URL\nsection of the Meraki Dashboard.\n\nie. https://yourserver:1880/excapSignOn\n\nBe sure to update the \"walled garden\" in the \nMeraki Dashboard with the IP address of your \nserver and any other resources required before\nlogin, such as your website, images, CSS, etc.\n\n","x":159,"y":396,"wires":[]},{"id":"f8926f6e.16bc6","type":"template","z":"466595c5.4621ec","name":"HTML Splash Page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n{{{payload.css}}}\n\n\n\t<meta charset=\"utf-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n\t<title>Registration Form</title>\n\n</head>\n<body>\n\n\t\n\n\n <div class=\"main-content\">\n\n <form class=\"form-register\" method=POST action=\"/excapClickLogin\">\n <input type=\"hidden\" name=\"continue_url\" value={{payload.continue_url}} />\n <input type=\"hidden\" name=\"host\" value ={{host}}>\n <input type=\"hidden\" name=\"base_grant_url\" value = {{payload.base_grant_url}}/>\n <input type=\"hidden\" name=\"user_continue_url\" value = {{payload.user_continue_url}}/>\n <input type=\"hidden\" name=\"node_mac\" value = {{payload.node_mac}}/>\n <input type=\"hidden\" name=\"client_ip\" value = {{payload.client_ip}}/>\n <input type=\"hidden\" name=\"client_mac\" value = {{payload.client_mac}}/>\n \n <div class=\"form-register-with-email\">\n\n <div class=\"form-white-background\">\n\n <div class=\"form-title-row\">\n <h1>Login to WiFi</h1>\n </div>\n\n <div class=\"form-row\">\n <label>\n <span>Name</span>\n <input type=\"text\" name=\"name\" required>\n </label>\n </div>\n\n <div class=\"form-row\">\n <label>\n <span>Email</span>\n <input type=\"email\" name=\"email\" required>\n </label>\n </div>\n\n <div class=\"form-row\">\n <label class=\"form-checkbox\">\n <input type=\"checkbox\" name=\"checkbox\" checked value=\"accepted\" required>\n <span>I agree to the <a href=\"/excapTerms\" target\"_blank\">terms and conditions</a></span>\n </label>\n </div>\n\n <div class=\"form-row\">\n <button type=\"submit\">Register</button>\n </div>\n\n </div>\n\n </div>\n\n <!-- Future Social Features\n <div class=\"form-sign-in-with-social\">\n\n <div class=\"form-row form-title-row\">\n <span class=\"form-title\">Sign in with</span>\n </div>\n\n <a href=\"#\" class=\"form-google-button\">Google</a>\n <a href=\"#\" class=\"form-facebook-button\">Facebook</a>\n <a href=\"#\" class=\"form-twitter-button\">Twitter</a>\n \n\n </div>\n -->\n\n </form>\n Your IP: {{payload.client_ip}}\n <br>\n Your MAC: {{payload.client_mac}}\n\n </div>\n\n</body>\n\n</html>\n\n","x":570,"y":160,"wires":[["6ca346b3.4b4ff8"]]},{"id":"34c2602a.81fe8","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapClickLogin","method":"post","swaggerDoc":"","x":160,"y":220,"wires":[["3efbb200.a52efe","6d193d01.b0e024","43628658.f491c8"]]},{"id":"3efbb200.a52efe","type":"function","z":"466595c5.4621ec","name":"Process login with 302 redirect","func":"// check if client has connected properly and received response from AP\nif (msg.payload.base_grant_url){\n msg.statusCode = 302;\n msg.headers = {\n 'Location': msg.payload.base_grant_url + '?continue_url=' + msg.payload.user_continue_url\n //add other headers here...\n };\n}else{\n // error: send client back to login\n msg.statusCode = 302;\n msg.headers = {\n 'Location': '/excapNotConnected'\n //add other headers here...\n };\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":530,"y":220,"wires":[["2c3a51ca.d324fe","ec564220.420f7"]]},{"id":"2c3a51ca.d324fe","type":"http response","z":"466595c5.4621ec","name":"","x":770,"y":220,"wires":[]},{"id":"6d193d01.b0e024","type":"debug","z":"466595c5.4621ec","name":"excapClick Login data","active":true,"console":"false","complete":"payload","x":200,"y":260,"wires":[]},{"id":"a0fb4abc.a684c8","type":"comment","z":"466595c5.4621ec","name":"Store form data - read more...","info":"The login data now can be sent somehwere to be \nlogged. A link node is attached to easily use\nthis data in other parts of the flow.","x":500,"y":260,"wires":[]},{"id":"cde96538.5029c8","type":"comment","z":"466595c5.4621ec","name":"Terms and Conditions","info":"","x":144,"y":750,"wires":[]},{"id":"afd2a0ed.e36b2","type":"comment","z":"466595c5.4621ec","name":"Success","info":"","x":106,"y":538,"wires":[]},{"id":"5e6c4c47.ff07a4","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapTerms","method":"get","swaggerDoc":"","x":150,"y":800,"wires":[["f8d5d081.e3955"]]},{"id":"9a95a3a5.dc7fd","type":"http response","z":"466595c5.4621ec","name":"","x":790,"y":840,"wires":[]},{"id":"d315a17c.320ac","type":"template","z":"466595c5.4621ec","name":"HTML Terms and Conditions","field":"payload","format":"handlebars","template":"<head>\n <title>Terms and Conditions</title>\n{{{payload}}}\n</head>\n<body>\n <div class=\"container\">\n <h1>Terms and Conditions</h1>\n <ul>\n <li>Please use our network responsibly. </li>\n <li>Your computer's MAC and IP address will be logged.</li>\n </ul>\n </div>\n</body>\n\n\n","x":600,"y":840,"wires":[["9a95a3a5.dc7fd"]]},{"id":"a175b8f8.b01bc8","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapSuccess","method":"get","swaggerDoc":"","x":150,"y":580,"wires":[["f0db334b.031be"]]},{"id":"a4e8a9d1.969868","type":"http response","z":"466595c5.4621ec","name":"","x":790,"y":620,"wires":[]},{"id":"790ec4db.c6f8fc","type":"template","z":"466595c5.4621ec","name":"HTML Success","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<head>\n <title>Success!</title>\n{{{payload.css}}}\n</head>\n<body>\n <div class=\"container\">\n <center><h1>Success!</h1>\n <h2>You can now use the network.</h2>\n </center>\n </div>\n</body>\n\n\n","x":560,"y":620,"wires":[["a4e8a9d1.969868"]]},{"id":"d4718bfc.4d3f18","type":"comment","z":"466595c5.4621ec","name":"Error: Not connected to AP","info":"","x":160,"y":873,"wires":[]},{"id":"79cade3b.fdbaa","type":"http in","z":"466595c5.4621ec","name":"","url":"/excapNotConnected","method":"get","swaggerDoc":"","x":170,"y":920,"wires":[["c23d557b.2ef068"]]},{"id":"3b4edc9d.f92bd4","type":"http response","z":"466595c5.4621ec","name":"","x":790,"y":960,"wires":[]},{"id":"a6eb073c.820558","type":"template","z":"466595c5.4621ec","name":"HTML Terms and Conditions","field":"payload","format":"handlebars","template":"<head>\n <title>Error: Not Connected</title>\n{{{payload}}}\n</head>\n<body>\n <div class=\"container\">\n <h1>Error: Not Connected</h1>\n <p>\n Hmm, somethings not right. It appears you\n are not connected to the correct wireless network.\n </p>\n </div>\n</body>\n\n\n","x":600,"y":960,"wires":[["3b4edc9d.f92bd4"]]},{"id":"9fa0059a.ad59c8","type":"comment","z":"466595c5.4621ec","name":"Cisco Meraki ExCap Service","info":"More information about the Meraki ExCap API:\nhttps://meraki.cisco.com/lib/pdf/meraki_whitepaper_captive_portal.pdf\n\nEnjoy!\n\nWritten by Cory Guynn, 2015.\nConsulting Engineer @ https://meraki.cisco.com/\nTechnical Blogger @ http://www.InternetOfLego.com","x":438.5,"y":31,"wires":[]},{"id":"2ef98b9a.122aa4","type":"template","z":"466595c5.4621ec","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style>\nhtml{\n background-color: #f3f3f3;\n}\n\n.form-register{\n max-width: 1000px;\n width: 100%;\n margin: 0 auto;\n\n font: bold 14px sans-serif;\n text-align: center;\n}\n\n.form-register-with-email{\n position: relative;\n display: inline-block;\n vertical-align: top;\n margin-right: 130px;\n text-align: center;\n}\n\n.form-register-with-email .form-white-background{\n width: 570px;\n box-sizing: border-box;\n background-color: #ffffff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n padding: 60px 80px;\n margin-bottom: 35px;\n}\n\n.form-register-with-email .form-row{\n text-align: left;\n margin-bottom: 23px;\n}\n\n.form-register-with-email .form-title-row{\n text-align: center;\n margin-bottom: 50px;\n}\n\n.form-register-with-email h1{\n display: inline-block;\n box-sizing: border-box;\n color: #4c565e;\n font-size: 24px;\n padding: 0 20px 15px;\n border-bottom: 2px solid #6caee0;\n margin: 0;\n}\n\n.form-register-with-email .form-row > label span{\n display: inline-block;\n box-sizing: border-box;\n color: #5f5f5f;\n width: 125px;\n text-align: right;\n padding-right: 25px;\n}\n\n.form-register-with-email input{\n color: #5f5f5f;\n box-sizing: border-box;\n width: 230px;\n box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n padding: 12px 18px;\n border: 1px solid #dbdbdb;\n}\n\n.form-register-with-email .form-checkbox input{\n margin-left: 128px;\n margin-right: 10px;\n width: auto;\n vertical-align: top;\n}\n\n.form-register-with-email .form-row .form-checkbox span{\n font-size: 12px;\n font-weight: normal;\n display: inline-block;\n text-align: left;\n width: 220px;\n margin: 0;\n}\n\n.form-register-with-email .form-checkbox span a{\n text-decoration: none;\n color: #6caee0;\n}\n\n.form-register-with-email button{\n display: block;\n border-radius: 2px;\n background-color: #6caee0;\n color: #ffffff;\n font-weight: bold;\n box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n padding: 15px 35px;\n border: 0;\n margin: 55px auto 0;\n cursor: pointer;\n}\n\n.form-register-with-email .form-log-in-with-existing{\n text-decoration: none;\n padding: 4px 8px;\n font-weight: normal;\n color: #7b9d62;\n background-color: #d6f0c3;\n}\n\n\n.form-sign-in-with-social{\n display: inline-block;\n max-width: 180px;\n box-sizing: border-box;\n vertical-align: top;\n text-align: center;\n margin-top: 100px;\n}\n\n.form-sign-in-with-social .form-title-row{\n margin-bottom: 50px;\n}\n\n.form-sign-in-with-social .form-title{\n box-sizing: border-box;\n color: #4c565e;\n font-size: 24px;\n padding: 15px 20px;\n border-bottom: 2px solid #6caee0;\n}\n\n.form-sign-in-with-social .form-google-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(222, 110, 60, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n.form-sign-in-with-social .form-facebook-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(75, 136, 194, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n.form-sign-in-with-social .form-twitter-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(123, 195, 226, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n/*\tMaking the form responsive. Remove these media queries\n if you don't need the form to work on mobile devices. */\n\n@media (max-width: 900px) {\n\n .form-register{\n margin: 20px auto;\n }\n\n .form-register-with-email{\n position: relative;\n display: block;\n margin: 0;\n }\n\n .form-register-with-email .form-white-background{\n margin: 0 auto 32px;\n }\n\n\n\n .form-sign-in-with-social {\n margin-top: 105px;\n }\n\n}\n\n@media (max-width: 600px) {\n\n .form-register-with-email .form-white-background{\n width: 300px;\n padding-left: 35px;\n padding-right: 35px;\n }\n\n .form-register-with-email .form-row > label span{\n display: block;\n text-align: left;\n padding: 0 0 10px;\n }\n\n .form-register-with-email input{\n display: block;\n margin: 0 auto;\n }\n\n .form-register-with-email .form-checkbox input{\n display: inline-block;\n margin-left: 0;\n }\n\n .form-register-with-email .form-checkbox span{\n width: 200px !important;\n }\n\n .form-register-with-email:after{\n bottom: -80px;\n left: 50%;\n margin-left: -25px;\n }\n\n}\n</style>","x":540,"y":120,"wires":[["f8926f6e.16bc6"]]},{"id":"393f68cf.d48a98","type":"template","z":"466595c5.4621ec","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style>\nhtml{\n background-color: #f3f3f3;\n}\n\n.form-register{\n max-width: 1000px;\n width: 100%;\n margin: 0 auto;\n\n font: bold 14px sans-serif;\n text-align: center;\n}\n\n.form-register-with-email{\n position: relative;\n display: inline-block;\n vertical-align: top;\n margin-right: 130px;\n text-align: center;\n}\n\n.form-register-with-email .form-white-background{\n width: 570px;\n box-sizing: border-box;\n background-color: #ffffff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n padding: 60px 80px;\n margin-bottom: 35px;\n}\n\n.form-register-with-email .form-row{\n text-align: left;\n margin-bottom: 23px;\n}\n\n.form-register-with-email .form-title-row{\n text-align: center;\n margin-bottom: 50px;\n}\n\n.form-register-with-email h1{\n display: inline-block;\n box-sizing: border-box;\n color: #4c565e;\n font-size: 24px;\n padding: 0 20px 15px;\n border-bottom: 2px solid #6caee0;\n margin: 0;\n}\n\n.form-register-with-email .form-row > label span{\n display: inline-block;\n box-sizing: border-box;\n color: #5f5f5f;\n width: 125px;\n text-align: right;\n padding-right: 25px;\n}\n\n.form-register-with-email input{\n color: #5f5f5f;\n box-sizing: border-box;\n width: 230px;\n box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n padding: 12px 18px;\n border: 1px solid #dbdbdb;\n}\n\n.form-register-with-email .form-checkbox input{\n margin-left: 128px;\n margin-right: 10px;\n width: auto;\n vertical-align: top;\n}\n\n.form-register-with-email .form-row .form-checkbox span{\n font-size: 12px;\n font-weight: normal;\n display: inline-block;\n text-align: left;\n width: 220px;\n margin: 0;\n}\n\n.form-register-with-email .form-checkbox span a{\n text-decoration: none;\n color: #6caee0;\n}\n\n.form-register-with-email button{\n display: block;\n border-radius: 2px;\n background-color: #6caee0;\n color: #ffffff;\n font-weight: bold;\n box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n padding: 15px 35px;\n border: 0;\n margin: 55px auto 0;\n cursor: pointer;\n}\n\n.form-register-with-email .form-log-in-with-existing{\n text-decoration: none;\n padding: 4px 8px;\n font-weight: normal;\n color: #7b9d62;\n background-color: #d6f0c3;\n}\n\n\n.form-sign-in-with-social{\n display: inline-block;\n max-width: 180px;\n box-sizing: border-box;\n vertical-align: top;\n text-align: center;\n margin-top: 100px;\n}\n\n.form-sign-in-with-social .form-title-row{\n margin-bottom: 50px;\n}\n\n.form-sign-in-with-social .form-title{\n box-sizing: border-box;\n color: #4c565e;\n font-size: 24px;\n padding: 15px 20px;\n border-bottom: 2px solid #6caee0;\n}\n\n.form-sign-in-with-social .form-google-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(222, 110, 60, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n.form-sign-in-with-social .form-facebook-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(75, 136, 194, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n.form-sign-in-with-social .form-twitter-button{\n color: #ffffff;\n display: block;\n width: 145px;\n height: 40px;\n font-size: 12px;\n line-height: 40px;\n background-color: rgba(123, 195, 226, 0.9);\n box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n border-radius: 2px;\n margin: 8px auto;\n text-decoration: none;\n}\n\n/*\tMaking the form responsive. Remove these media queries\n if you don't need the form to work on mobile devices. */\n\n@media (max-width: 900px) {\n\n .form-register{\n margin: 20px auto;\n }\n\n .form-register-with-email{\n position: relative;\n display: block;\n margin: 0;\n }\n\n .form-register-with-email .form-white-background{\n margin: 0 auto 32px;\n }\n\n\n\n .form-sign-in-with-social {\n margin-top: 105px;\n }\n\n}\n\n@media (max-width: 600px) {\n\n .form-register-with-email .form-white-background{\n width: 300px;\n padding-left: 35px;\n padding-right: 35px;\n }\n\n .form-register-with-email .form-row > label span{\n display: block;\n text-align: left;\n padding: 0 0 10px;\n }\n\n .form-register-with-email input{\n display: block;\n margin: 0 auto;\n }\n\n .form-register-with-email .form-checkbox input{\n display: inline-block;\n margin-left: 0;\n }\n\n .form-register-with-email .form-checkbox span{\n width: 200px !important;\n }\n\n .form-register-with-email:after{\n bottom: -80px;\n left: 50%;\n margin-left: -25px;\n }\n\n}\n</style>","x":540,"y":440,"wires":[["5e0dd8a.6daa128"]]},{"id":"f0db334b.031be","type":"template","z":"466595c5.4621ec","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style type=\"text/css\">\n.container{\n max-width: 500px;\n padding: 10px 20px;\n background: #f4f7f8;\n margin: 10px auto;\n padding: 20px;\n background: #f4f7f8;\n border-radius: 8px;\n font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":540,"y":580,"wires":[["790ec4db.c6f8fc"]]},{"id":"f8d5d081.e3955","type":"template","z":"466595c5.4621ec","name":"CSS Style","field":"payload","format":"html","template":"<style type=\"text/css\">\n.container{\n max-width: 500px;\n padding: 10px 20px;\n background: #f4f7f8;\n margin: 10px auto;\n padding: 20px;\n background: #f4f7f8;\n border-radius: 8px;\n font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":540,"y":800,"wires":[["d315a17c.320ac"]]},{"id":"c23d557b.2ef068","type":"template","z":"466595c5.4621ec","name":"CSS Style","field":"payload","format":"html","template":"<style type=\"text/css\">\n.container{\n max-width: 500px;\n padding: 10px 20px;\n background: #f4f7f8;\n margin: 10px auto;\n padding: 20px;\n background: #f4f7f8;\n border-radius: 8px;\n font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":540,"y":920,"wires":[["a6eb073c.820558"]]},{"id":"3e9bfe19.2a58d2","type":"comment","z":"466595c5.4621ec","name":"Supporting Pages","info":"","x":95,"y":689,"wires":[]},{"id":"ec564220.420f7","type":"debug","z":"466595c5.4621ec","name":"Process Login","active":true,"console":"false","complete":"payload","x":740,"y":260,"wires":[]},{"id":"c81f2449.80d548","type":"inject","z":"1f491da9.9d14e2","name":"Create Admin","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":460,"wires":[["5759b718.53c9c8"]]},{"id":"f061c93f.1f4488","type":"http request","z":"1f491da9.9d14e2","name":"","method":"use","ret":"obj","url":"","tls":"","x":810,"y":500,"wires":[["7f4329cf.7c4928","ea013c.9cbf6ec8","b19f2f9c.6a34c"]]},{"id":"7f4329cf.7c4928","type":"debug","z":"1f491da9.9d14e2","name":"Create Meraki Admin","active":true,"console":"false","complete":"payload","x":800,"y":560,"wires":[]},{"id":"c6e83f8f.caf","type":"http in","z":"1f491da9.9d14e2","name":"","url":"/meraki/admins","method":"get","swaggerDoc":"","x":110,"y":220,"wires":[["cdf5a50a.f0c008"]]},{"id":"cdf5a50a.f0c008","type":"function","z":"1f491da9.9d14e2","name":"msg.url = \"/meraki/newAdmin\";","func":"msg.url = \"/meraki/newAdmin\";\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":220,"wires":[["211cf939.c8c066"]]},{"id":"90eec72b.dd9338","type":"template","z":"1f491da9.9d14e2","name":"CSS","field":"payload.style","fieldType":"msg","format":"css","syntax":"mustache","template":"input[type=text], select {\n width: 100%;\n padding: 12px 20px;\n margin: 8px 0;\n display: inline-block;\n border: 1px solid #ccc;\n border-radius: 4px;\n box-sizing: border-box;\n}\n\ninput[type=email], select {\n width: 100%;\n padding: 12px 20px;\n margin: 8px 0;\n display: inline-block;\n border: 1px solid #ccc;\n border-radius: 4px;\n box-sizing: border-box;\n}\n\ninput[type=submit] {\n width: 50%;\n background-color: #4CAF50;\n color: white;\n padding: 14px 20px;\n margin: 8px 0;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n}\n\ninput[type=submit]:hover {\n background-color: #45a049;\n}\n\ndiv form {\n border-radius: 5px;\n background-color: #f2f2f2;\n padding: 20px;\n}\n\n.adminform {\n width: 90%;\n}\n","x":370,"y":300,"wires":[["60302eb5.4352b"]]},{"id":"211cf939.c8c066","type":"template","z":"1f491da9.9d14e2","name":"JavaScript","field":"payload.script","fieldType":"msg","format":"javascript","syntax":"mustache","template":"\n$(document).ready(function(e) {\n \n \n $.ajax({\n url: 'api/organizations',\n type: 'get',\n datatype: 'json',\n success: function(data){\n var toAppend = '';\n //if(typeof data === 'object'){\n for(var i=0;i<data.length;i++){\n toAppend += '<option value='+data[i][\"id\"]+'>'+data[i]['name']+'</option>';\n }\n //}\n console.log(\"orgs toAppend\",toAppend);\n $('#orgs').append(toAppend);\n }\n });\n \n $(\"form[ajax=true]\").submit(function(e) {\n \n e.preventDefault();\n \n var form_data = $(this).serialize();\n var form_url = $(this).attr(\"action\");\n var form_method = $(this).attr(\"method\").toUpperCase();\n \n var orgId = $(\"#orgs\").val();\n \n $(\"#loadingimg\").show();\n \n $.ajax({\n url: form_url+\"/\"+orgId, \n type: form_method, \n data: form_data, \n cache: false,\n success: function(data){\n \n // Create simple HTML response\n var response = \n \"<div>\"+\n \"<h2>Created Admin!</h2>\"+\n \"<h4>Name</h4><p>\"+data.name+\"</p>\"+\n \"<h4>E-Mail</h4><p>\"+data.email+\"</p>\"+\n \"<h4>ID</h4><p>\"+data.id+\"</p>\"+\n \"<h4>Tags</h4><p>\"+data.tags+\"</p>\"+\n \"<h4>Org Access</h4><p>\"+data.orgAccess+\"</p>\"+\n \"</div>\";\n \n console.log(\"response: \"+JSON.stringify(data));\n \n \n $(\"#result\").html(response); \n \n $(\"#loadingimg\").hide();\n $( '#createadmin' ).each(function(){\n this.reset();\n });\n },\n error: function(error){\n $(\"#result\").html(error.responseText);\n }\n }); \n \n });\n \n});","x":390,"y":260,"wires":[["90eec72b.dd9338"]]},{"id":"fe67769b.ba37b8","type":"comment","z":"1f491da9.9d14e2","name":"Create Admin Form","info":"","x":110,"y":140,"wires":[]},{"id":"3ec4833d.ec3b7c","type":"comment","z":"1f491da9.9d14e2","name":"Form Submission URL","info":"","x":420,"y":180,"wires":[]},{"id":"be2485f7.33ddc8","type":"http response","z":"1f491da9.9d14e2","name":"","x":710,"y":220,"wires":[]},{"id":"60302eb5.4352b","type":"template","z":"1f491da9.9d14e2","name":"HTML","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n <head>\n <title>Meraki Dasbhoard API - Admin User</title>\n <meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\">\n <meta charset=\"utf-8\">\n <!--\n <script src=\"http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js\"></script>\n -->\n <script\n src=\"https://code.jquery.com/jquery-3.2.1.min.js\"\n integrity=\"sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=\"\n crossorigin=\"anonymous\"></script>\n \n <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"> \n <script>{{{payload.jquery}}}</script>\n <style>{{{payload.style}}}</style>\n </head>\n \n<div class=\"container\">\n <h2>Create a Meraki Dashboard Administrator</h2>\n <h4><a href=\"http://developers.meraki.com\">Meraki Developers Portal</a></h4>\n\n<div class=\"col-md-6\">\n<div class=\"adminform\">\n <form id=\"createadmin\" method=\"post\" action=\"{{url}}\" ajax=\"true\">\n <select id=\"orgs\" name=\"orgs\">\n <option>Select Organization..</option>\n </select>\n <label>Contact Details</label>\n <input type=\"text\" id=\"fname\" name=\"firstname\" placeholder=\"First Name\" required=true/>\n <input type=\"text\" id=\"lname\" name=\"lastname\" placeholder=\"Last Name\" required=true/>\n <input type=\"email\" id=\"email\" name=\"email\" placeholder=\"E-mail\" required=true/>\n <br>\n\n <label>Organization Permissions</label>\n <select id=\"orgAccess\" name=\"orgAccess\" placeholder=\"Org Access\">\n <option value=\"full\">full</option>\n <option value=\"read-only\">read-only</option>\n </select>\n \n \n <input type=\"submit\" class=\"button\" value=\"Submit\">\n </form>\n</div>\n</div>\n\n<div class=\"col-md-6\">\n <span id=\"result\"></span>\n</div>\n</div>\n</body>\n</html>\n<script>{{{payload.script}}}</script>","x":370,"y":340,"wires":[["be2485f7.33ddc8"]]},{"id":"5759b718.53c9c8","type":"function","z":"1f491da9.9d14e2","name":"Sample Data","func":"msg.payload = {\n \"name\": \"NodeRED Test\",\n \"email\": \"cory@internetoflego.com\",\n \"orgAccess\": \"full\"\n };\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":460,"wires":[["54ae2286.028d2c"]]},{"id":"bb0b7d83.e29ba","type":"http in","z":"1f491da9.9d14e2","name":"","url":"/meraki/newAdmin/:orgId","method":"post","swaggerDoc":"","x":170,"y":500,"wires":[["8e63af69.effcf"]]},{"id":"ea013c.9cbf6ec8","type":"http response","z":"1f491da9.9d14e2","name":"","x":990,"y":500,"wires":[]},{"id":"8e63af69.effcf","type":"function","z":"1f491da9.9d14e2","name":"form data","func":"// Convert form data into Meraki API expected JSON\nmsg.orgId = msg.req.params.orgId;\nmsg.payload = {\n name: msg.req.body.firstname + \" \" + msg.req.body.lastname,\n email: msg.req.body.email,\n orgAccess: msg.req.body.orgAccess\n};\n\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":500,"wires":[["9ca39021.41a2b","54ae2286.028d2c"]]},{"id":"9ca39021.41a2b","type":"debug","z":"1f491da9.9d14e2","name":"newAdmin Form Data","active":true,"console":"false","complete":"payload","x":296.5555725097656,"y":558.6666631698608,"wires":[]},{"id":"e50d6724.15b258","type":"comment","z":"1f491da9.9d14e2","name":"Meraki Dashboard API Sample App","info":"Create a Meraki Dasbhoard Admin with a form.\n\nTo open the web form, navigate to \n\nhttp://yourserver:1880/meraki/admins\n","x":459,"y":24.000003814697266,"wires":[]},{"id":"a5b4aa9b.c71de8","type":"inject","z":"1f491da9.9d14e2","name":"List Organizations","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":130,"y":660,"wires":[["15632b8.22540d5"]]},{"id":"15632b8.22540d5","type":"function","z":"1f491da9.9d14e2","name":"Meraki API - List Organizations","func":"// Set Variables\nvar apiKey = global.get('apiKey');\n\n\n\n// API Call\nmsg.headers = {\n \"X-Cisco-Meraki-API-Key\": apiKey\n};\n\nmsg.url = \"https://dashboard.meraki.com/api/v0/organizations\";\nmsg.method = 'get';\n\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":660,"wires":[["23fdd666.9cf74a"]]},{"id":"23fdd666.9cf74a","type":"http request","z":"1f491da9.9d14e2","name":"","method":"use","ret":"txt","url":"","tls":"","x":670,"y":660,"wires":[["d6109831.8ca3a8"]]},{"id":"d02830a3.34bfa","type":"http in","z":"1f491da9.9d14e2","name":"","url":"/meraki/api/organizations","method":"get","swaggerDoc":"","x":160,"y":700,"wires":[["15632b8.22540d5"]]},{"id":"d6109831.8ca3a8","type":"function","z":"1f491da9.9d14e2","name":"Large Int Helper","func":"// Convert the org number to a string so that it does not become corrupted \n// when the JSON conversion happens. \nmsg.payload = msg.payload.replace(/\"id\":(.*?)(?:,)/g,\"\\\"id\\\"\\:\\\"$1\\\"\\,\");\nconsole.log(\"new json with regex replace \",msg.payload);\nreturn msg","outputs":1,"noerr":0,"x":860,"y":660,"wires":[["91f1eb0d.41a1e8"]]},{"id":"91f1eb0d.41a1e8","type":"json","z":"1f491da9.9d14e2","name":"","x":830,"y":700,"wires":[["4d7cb514.8d831c","3d5b0708.b38a88"]]},{"id":"4d7cb514.8d831c","type":"http response","z":"1f491da9.9d14e2","name":"","x":1030,"y":700,"wires":[]},{"id":"3d5b0708.b38a88","type":"debug","z":"1f491da9.9d14e2","name":"List Orgs JSON","active":true,"console":"false","complete":"payload","x":1000,"y":740,"wires":[]},{"id":"760533bc.b8681c","type":"inject","z":"1f491da9.9d14e2","name":"Sets Defaults - Injected at start","topic":"","payload":"Setting Environment Variables","payloadType":"str","repeat":"","crontab":"","once":true,"x":170,"y":60,"wires":[["d6bf7874.d504f8"]]},{"id":"d6bf7874.d504f8","type":"function","z":"1f491da9.9d14e2","name":"Env Variables: UPDATE THIS","func":"// ###### User Defined Variables ######\n\nconst API_KEY = 'YourAPIKey'; //Your API KEY (Keep this secret. Do not publish)\nvar shard = 'n143'; // https://n149.meraki.com , where n149 represent the shard number. This is defined to avoid redirect issues.\nvar orgId = ''; // Your default Organization ID\n\n\n\n\n\n// ###### Set and Get Global variables ######\n\n\n// Assign to Global Context \nglobal.set('apiKey', API_KEY); // pulling API key via \"secret\" node. This avoides publishing the API key when sharing the flow\nglobal.set('shard', shard);\n\nglobal.set('orgId', orgId);\n\n\nmsg.payload = \"settings set\";\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":60,"wires":[["2bd4e773.77a128"]]},{"id":"2bd4e773.77a128","type":"debug","z":"1f491da9.9d14e2","name":"Flow Env Variables","active":true,"console":"false","complete":"true","x":750,"y":60,"wires":[]},{"id":"54ae2286.028d2c","type":"function","z":"1f491da9.9d14e2","name":"Meraki API - Create Admin","func":"// Set Variables\nvar apiKey = global.get('apiKey');\nvar shard = global.get('shard');\n//var orgId = global.get('orgId'); // set via global variables\nvar orgId = msg.orgId; //set via request parameter\n\n// API Call\nmsg.headers = {\n \"X-Cisco-Meraki-API-Key\": apiKey\n};\nmsg.url = \"https://\"+shard+\".meraki.com/api/v0/organizations/\"+orgId+\"/admins\";\nmsg.method = 'post';\nreturn msg;","outputs":1,"noerr":0,"x":600,"y":500,"wires":[["f061c93f.1f4488"]]},{"id":"878db1a6.ac677","type":"comment","z":"1f491da9.9d14e2","name":"APIs","info":"","x":70,"y":400,"wires":[]},{"id":"43628658.f491c8","type":"link out","z":"466595c5.4621ec","name":"excapClick Login","links":["bc43f620.69aed8","e1337f3c.886c1"],"x":395,"y":300,"wires":[]},{"id":"cf79cb29.0c0eb8","type":"http request","z":"394a1eba.47a102","name":"","method":"use","ret":"txt","url":"","tls":"","x":530,"y":140,"wires":[["17363356.c60e6d"]]},{"id":"afc41bc7.693de8","type":"function","z":"394a1eba.47a102","name":"Spark Send Message (API) - UPDATE","func":"// ******************\n// Set Your Variables\n// ******************\nvar accessToken = \"EnterYourAccessTokenHere\"; // Your Access Token\nvar roomId = \"EnterYourRoomIDHere\"; // Your Room ID\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: msg.payload \n}\nmsg.method = \"post\";\n\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":140,"wires":[["cf79cb29.0c0eb8"]]},{"id":"5579c6e4.53fd58","type":"inject","z":"394a1eba.47a102","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":100,"y":240,"wires":[["29436644.96034a"]]},{"id":"17363356.c60e6d","type":"debug","z":"394a1eba.47a102","name":"Spark Message","active":true,"console":"false","complete":"true","x":740,"y":140,"wires":[]},{"id":"27483135.8b86fe","type":"link in","z":"394a1eba.47a102","name":"","links":["523164a5.83ef6c"],"x":255,"y":480,"wires":[["53058686.045058"]]},{"id":"93280cbb.4777e","type":"comment","z":"394a1eba.47a102","name":"Cisco Spark API Examples - README","info":"These sample flows simply take the results from\nthe linked sample flows, formats them and sends a message\nto a Cisco Spark room.\n\nUpdate the Spark API function with your `roomID`\nand your `accessToken`. These can be found on \nthe developers portal for Cisco Spark.\n\nThe `accessToken` can be found in the portal by\nclicking on your profile icon in the top right.\nCopy this token into the function variable.\n\nExample Token\n`ZGJjNzI0ODAtNmEwNS00YjU3LTkzOTYtMjthisisbogushmOWI3M2IyZGI4NzctZDVh`\n\n*API to List Rooms*\nhttps://developer.ciscospark.com/endpoint-rooms-get.html\n- you will get your roomId by running this call\nusing their \"Test Mode\", which will run the command\nand the resulting JSON will appear with the \nid, name, etc. Copy the `id` value into the function variable.\n`\n{\n\t\t\t\"id\": \"Y2lzY29zcGFyazovL3VzL1JPT00vNWExMjhhNTAtNTExZi0xMWU3LTk2NTctYjMzNWEyNmMzYmVj\",\n\t\t\t\"title\": \"Node-RED Testing Sandbox\",\n\t\t\t\"type\": \"group\",\n\t\t\t\"isLocked\": false,\n\t\t\t\"lastActivity\": \"2017-06-14T20:21:09.726Z\",\n\t\t\t\"creatorId\": \"Y2lzY29zcGFyazovL3VzL1BFT1BMRS80ZjY4OWNhZS1mYjNlLTRjNDEtODM3OC1hYmY1Mjc2Y2RmMzQ\",\n\t\t\t\"created\": \"2017-06-14T16:34:35.509Z\"\n\t\t}\n`\n\n*API to Send a Message*\nhttps://developer.ciscospark.com/endpoint-messages-post.html\n","x":430,"y":40,"wires":[]},{"id":"fdd34263.cf18b","type":"comment","z":"394a1eba.47a102","name":"Captive Portal Login Notification","info":"","x":150,"y":280,"wires":[]},{"id":"b19f2f9c.6a34c","type":"link out","z":"1f491da9.9d14e2","name":"Create Meraki Admin","links":["3bc01653.cdd71a"],"x":955,"y":540,"wires":[]},{"id":"3bc01653.cdd71a","type":"link in","z":"394a1eba.47a102","name":"","links":["b19f2f9c.6a34c"],"x":255,"y":400,"wires":[["5d9a02f6.0dec9c","37dd7674.35a98a"]]},{"id":"5d9a02f6.0dec9c","type":"function","z":"394a1eba.47a102","name":"Format Message","func":"var admin = msg.payload;\n\nmsg.payload = \"## New Admin Created! \\n\" +\n admin.name + \" \" + admin.email + \" **Access**: \"+admin.orgAccess;\nreturn msg;\n","outputs":1,"noerr":0,"x":410,"y":400,"wires":[["c1730bd.96dbbf8"]]},{"id":"e1337f3c.886c1","type":"link in","z":"394a1eba.47a102","name":"","links":["43628658.f491c8"],"x":255,"y":320,"wires":[["516ea3de.476cfc"]]},{"id":"516ea3de.476cfc","type":"function","z":"394a1eba.47a102","name":"Format Message","func":"\nvar client = msg.payload;\n\nmsg.payload = \"## New WiFi Client Joined! \\n\" +\n client.name + \" \" + client.email;\nreturn msg;\n","outputs":1,"noerr":0,"x":410,"y":320,"wires":[["10d00d3f.5039c3"]]},{"id":"3befd6e2.f3bd7a","type":"comment","z":"394a1eba.47a102","name":"Test Timestamp","info":"","x":100,"y":200,"wires":[]},{"id":"35b0ad40.a36302","type":"comment","z":"394a1eba.47a102","name":"Dashboard API Admin Creation","info":"","x":150,"y":360,"wires":[]},{"id":"e0e549e8.e9d978","type":"comment","z":"394a1eba.47a102","name":"Location API Notification","info":"","x":130,"y":440,"wires":[]},{"id":"4f20f33e.5419fc","type":"link out","z":"23e64752.6bedb8","name":"Location API All Data","links":["ee491f57.dbdb1"],"x":555,"y":300,"wires":[]},{"id":"d8024a5c.0aae98","type":"comment","z":"23e64752.6bedb8","name":"Workflow Example: Search string for the word Apple","info":"","x":210,"y":360,"wires":[]},{"id":"e86c8852.933938","type":"debug","z":"23e64752.6bedb8","name":"WiFi Device","active":true,"console":"false","complete":"true","x":610,"y":440,"wires":[]},{"id":"e7e49949.dfc088","type":"mongodb2 in","z":"23e64752.6bedb8","service":"_ext_","configNode":"d1246adf.32e488","name":"","collection":"cmx","operation":"removeMany","x":380,"y":900,"wires":[["6eb9db8d.fbe004"]]},{"id":"2150a44c.fb188c","type":"inject","z":"23e64752.6bedb8","name":"DELETE all clients","topic":"","payload":"{}","payloadType":"json","repeat":"","crontab":"","once":false,"x":130,"y":900,"wires":[["e7e49949.dfc088"]]},{"id":"6eb9db8d.fbe004","type":"debug","z":"23e64752.6bedb8","name":"DELETE mongo data","active":true,"console":"false","complete":"true","x":680,"y":900,"wires":[]},{"id":"313e2e28.792462","type":"mongodb2 in","z":"23e64752.6bedb8","service":"_ext_","configNode":"d1246adf.32e488","name":"","collection":"cmx","operation":"removeMany","x":380,"y":1000,"wires":[["ec795d40.5f185"]]},{"id":"c32cc1fd.b4e9e","type":"inject","z":"23e64752.6bedb8","name":"DELETE clients oder than..","topic":"","payload":"{}","payloadType":"json","repeat":"","crontab":"00 5 * * *","once":false,"x":160,"y":960,"wires":[["d2220e57.c26c9"]]},{"id":"ec795d40.5f185","type":"debug","z":"23e64752.6bedb8","name":"DELETE mongo data","active":true,"console":"false","complete":"true","x":680,"y":1000,"wires":[]},{"id":"d2220e57.c26c9","type":"function","z":"23e64752.6bedb8","name":"1 Day - filter","func":" var days = 1; //1 Day\n var date = new Date();\n date.setDate(date.getDate()-days);\nmsg.payload = {'seenString': {$gte: date}};\nreturn msg;","outputs":1,"noerr":0,"x":370,"y":960,"wires":[["313e2e28.792462"]]},{"id":"bee1d7a6.f5f678","type":"inject","z":"23e64752.6bedb8","name":"test","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":90,"y":660,"wires":[["91c90923.b71a28"]]},{"id":"795831e6.74c24","type":"inject","z":"23e64752.6bedb8","name":"test","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":90,"y":800,"wires":[["71ed23c9.ccb47c"]]},{"id":"bc5e81e9.2246f","type":"http in","z":"23e64752.6bedb8","name":"","url":"/cmxNative","method":"post","swaggerDoc":"","x":120,"y":220,"wires":[["fb555e37.76109","464ec513.99627c"]]},{"id":"ee491f57.dbdb1","type":"link in","z":"23e64752.6bedb8","name":"","links":["4f20f33e.5419fc"],"x":55,"y":440,"wires":[["484adcb7.52c454"]]},{"id":"beee9793.5dcd68","type":"comment","z":"23e64752.6bedb8","name":"Database Utilities","info":"","x":100,"y":860,"wires":[]},{"id":"5543ec24.5d4b14","type":"debug","z":"23e64752.6bedb8","name":"Location Data JSON","active":true,"console":"false","complete":"payload","x":760,"y":680,"wires":[]},{"id":"523164a5.83ef6c","type":"link out","z":"23e64752.6bedb8","name":"BLE Location API","links":["27483135.8b86fe"],"x":555,"y":480,"wires":[]},{"id":"a52cad9b.c415b","type":"function","z":"23e64752.6bedb8","name":"WiFi Split observations","func":"// send individual observation items to next node\nvar data = msg.payload.data;\n\nfor (i = 0; i < data.observations.length; i++) { \n msg.payload = data.observations[i];\n node.send(msg);\n}\n\n","outputs":1,"noerr":0,"x":360,"y":400,"wires":[["e86c8852.933938","5ace468e.0c7458"]]},{"id":"484adcb7.52c454","type":"switch","z":"23e64752.6bedb8","name":"WiFi or BLE","property":"payload.type","propertyType":"msg","rules":[{"t":"eq","v":"DevicesSeen","vt":"str"},{"t":"eq","v":"BluetoothDevicesSeen","vt":"str"}],"checkall":"true","outputs":2,"x":170,"y":440,"wires":[["a52cad9b.c415b"],["9ed4f8c4.4642f8"]]},{"id":"9ed4f8c4.4642f8","type":"function","z":"23e64752.6bedb8","name":"BLE Split observations","func":"// send individual observation items to next node\nvar data = msg.payload.data;\n\nfor (i = 0; i < data.observations.length; i++) { \n msg.payload = data.observations[i];\n node.send(msg);\n}\n\n","outputs":1,"noerr":0,"x":360,"y":480,"wires":[["523164a5.83ef6c","f6e15ccc.48c56"]]},{"id":"f6e15ccc.48c56","type":"debug","z":"23e64752.6bedb8","name":"BLE Device","active":true,"console":"false","complete":"true","x":610,"y":520,"wires":[]},{"id":"5ace468e.0c7458","type":"link out","z":"23e64752.6bedb8","name":"WiFi Location API","links":["2abfb269.2a29de"],"x":555,"y":400,"wires":[]},{"id":"5421c33d.8ab8ec","type":"switch","z":"394a1eba.47a102","name":"Search VIP Client- UPDATE","property":"payload.clientMac","propertyType":"msg","rules":[{"t":"cont","v":"74:da:38:56:0a:80","vt":"str"}],"checkall":"true","outputs":1,"x":420,"y":580,"wires":[["19f00608.ec549a"]]},{"id":"2abfb269.2a29de","type":"link in","z":"394a1eba.47a102","name":"","links":["5ace468e.0c7458"],"x":255,"y":540,"wires":[["19c66366.cb7b9d","5421c33d.8ab8ec"]]},{"id":"19c66366.cb7b9d","type":"function","z":"394a1eba.47a102","name":"Format Message","func":"// Write a message with Markdown and include the Google Maps encoded URL.\n// http://maps.google.com/maps?t=h&q=loc:35.487895,-87.332414&z=17 \nvar device = msg.payload;\nvar manufacturer = device.manufacturer || \"\"; // display manufacturer only if it is known\n\nmsg.payload = \"## WiFi Device Found! \\n\" +\n \"####\"+ manufacturer + \"#### \\n\"+\n \" **RSSI**:\" + device.rssi +\n \" **MAC**: \" + device.clientMac +\n \" [Map](https://maps.google.com/maps?t=h&q=loc:\"+device.location.lat +\",\"+ device.location.lng+\"&z=17)\";\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":540,"wires":[["2041d767.8ca148"]]},{"id":"a7724b54.ae9148","type":"link in","z":"394a1eba.47a102","name":"Cisco Spark","links":["29436644.96034a","10d00d3f.5039c3","c1730bd.96dbbf8","4d14d00.038253","2041d767.8ca148","b1608cf.984457"],"x":75,"y":140,"wires":[["afc41bc7.693de8"]]},{"id":"29436644.96034a","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":575,"y":240,"wires":[]},{"id":"10d00d3f.5039c3","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":575,"y":320,"wires":[]},{"id":"c1730bd.96dbbf8","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":575,"y":400,"wires":[]},{"id":"4d14d00.038253","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":835,"y":480,"wires":[]},{"id":"2041d767.8ca148","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":835,"y":540,"wires":[]},{"id":"1d6b9f0.6b62461","type":"comment","z":"394a1eba.47a102","name":"Send Message to Cisco Spark Room","info":"","x":170,"y":620,"wires":[]},{"id":"ac98324a.0bfaf","type":"comment","z":"394a1eba.47a102","name":"BLE","info":"","x":170,"y":480,"wires":[]},{"id":"8f3c8108.94f51","type":"comment","z":"394a1eba.47a102","name":"WiFi","info":"","x":170,"y":540,"wires":[]},{"id":"53058686.045058","type":"function","z":"394a1eba.47a102","name":"Format Message","func":"// Write a message with Markdown and include the Google Maps encoded URL.\n// http://maps.google.com/maps?t=h&q=loc:35.487895,-87.332414&z=17 \nvar device = msg.payload;\nmsg.payload = \"## BLE Device Found! \\n\" +\n \" **RSSI**:\" + device.rssi +\n \" **MAC**: \" + device.clientMac +\n \" [Map](https://maps.google.com/maps?t=h&q=loc:\"+device.location.lat +\",\"+ device.location.lng+\"&z=17)\";\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":480,"wires":[["4d14d00.038253"]]},{"id":"19f00608.ec549a","type":"function","z":"394a1eba.47a102","name":"Format Message","func":"// Write a message with Markdown and include the Google Maps encoded URL.\n// http://maps.google.com/maps?t=h&q=loc:35.487895,-87.332414&z=17 \nvar device = msg.payload;\nvar manufacturer = device.manufacturer || \"\"; // display manufacturer only if it is known\n\nmsg.payload = \"## VIP WiFi Device Found! \\n\" +\n \"####\"+ manufacturer + \"#### \\n\"+\n \" **RSSI**:\" + device.rssi +\n \" **MAC**: \" + device.clientMac +\n \" [Map](https://maps.google.com/maps?t=h&q=loc:\"+device.location.lat +\",\"+ device.location.lng+\"&z=17)\";\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":580,"wires":[["b1608cf.984457"]]},{"id":"b1608cf.984457","type":"link out","z":"394a1eba.47a102","name":"","links":["a7724b54.ae9148"],"x":835,"y":580,"wires":[]},{"id":"37dd7674.35a98a","type":"debug","z":"394a1eba.47a102","name":"Admin Data","active":true,"console":"false","complete":"payload","x":390,"y":440,"wires":[]},{"id":"aa443fc8.b2044","type":"comment","z":"394a1eba.47a102","name":"Send Message to Cisco Spark Room","info":"","x":170,"y":100,"wires":[]}]
@dexterlabora
Copy link
Author

A collection of Node-RED flows to demonstrate the Cisco Meraki and Spark APIs using native Node-RED nodes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment