Cisco Meraki CMX
Overview
This flow provides an example CMX listener to capture WiFi based location analytics provided by a Cisco Meraki wireless network and stores it into a mongodb database.
More info about the CMX system https://meraki.cisco.com/lib/pdf/meraki_whitepaper_cmx.pdf
Usage
In the Cisco Meraki dashboard, enable the CMX API and take note of the "validator" key that is provided.
Next, enter the post URL, which will resemble the following example. For testing, enter your provided validator key as part of the post query. This can be further secured by placing this key in a "validate-validator" function block to perform a validation.
Example http://yourserver:1880/cmx?validator=8e0846499d9a3f6d23f7868c4d55b9d6325035f5
Enter a Secret on the Meraki dashboard and then update the "validate-secret" function block in node-red to match.
Post URL http://yourserver:1880/cmx
List CMX JSON http://yourserver:1880/showcmx
Simple HTML table of data http://yourserver:1880/showcmxhtml
Fun Ideas
* send the location data to a Google Map for visual tracking * send an SMS with Twilio or Tweet when a VIP guest has arrivedWritten by Cory Guynn, 2015
More great projects at http://www.InternetOfLego.com
[{"id":"6ed1115c.912ef","type":"mongodb","hostname":"127.0.0.1","port":"27017","db":"test","name":""},{"id":"83fdf63f.7c0208","type":"http in","name":"[post] /cmx","url":"/cmx","method":"post","swaggerDoc":"","x":90,"y":181,"z":"3621d812.c9de28","wires":[["46f0f848.b90f08","21af9334.de506c","f172aa31.0e8d58"]]},{"id":"e55cc9d8.1aa338","type":"mongodb in","mongodb":"6ed1115c.912ef","name":"cmx data","collection":"cmx","operation":"find","x":453,"y":323,"z":"3621d812.c9de28","wires":[["a37b9a5c.5c8468"]]},{"id":"d9d7d480.262828","type":"mongodb out","mongodb":"6ed1115c.912ef","name":"cmx data","collection":"cmx","payonly":true,"upsert":false,"multi":false,"operation":"store","x":535,"y":272,"z":"3621d812.c9de28","wires":[]},{"id":"a37b9a5c.5c8468","type":"http response","name":"cmx response","x":637,"y":322,"z":"3621d812.c9de28","wires":[]},{"id":"1cc8879b.e33778","type":"debug","name":"CMX Data","active":true,"console":"false","complete":"true","x":537,"y":200,"z":"3621d812.c9de28","wires":[]},{"id":"3aea25a6.c515da","type":"http in","name":"[get] /cmx Validator","url":"/cmx","method":"get","swaggerDoc":"","x":115,"y":72,"z":"3621d812.c9de28","wires":[["54771d95.ab88e4","6c9eb49a.93614c"]]},{"id":"54771d95.ab88e4","type":"function","name":"validate-validator","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//~~~~~~~~~\nvalidator = msg.payload.validator;\nmsg.payload = validator;\nreturn msg;\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//~~~~~~~~~\n//validator = \"8e0846499d9a3f6c23f7868c4c25b9d6325035f5\";\n//msg.payload = validator;\n//return msg;","outputs":1,"noerr":0,"x":310,"y":90,"z":"3621d812.c9de28","wires":[["e557075a.1aa8f8","5601778a.a9fe88"]]},{"id":"e557075a.1aa8f8","type":"http response","name":"cmx response","x":598,"y":78,"z":"3621d812.c9de28","wires":[]},{"id":"6c9eb49a.93614c","type":"debug","name":"CMX validator raw","active":false,"console":"false","complete":"payload","x":339,"y":41,"z":"3621d812.c9de28","wires":[]},{"id":"1efcb74f.e10349","type":"http in","name":"[get] /showcmx","url":"/showcmx","method":"get","swaggerDoc":"","x":107,"y":323,"z":"3621d812.c9de28","wires":[["d7d2081f.282df8"]]},{"id":"acf96047.5306a","type":"http in","name":"[get] /showcmxhtml","url":"/showcmxhtml","method":"get","swaggerDoc":"","x":125,"y":461,"z":"3621d812.c9de28","wires":[["b02e2940.4fd1d8"]]},{"id":"a414e870.5beb18","type":"template","name":"Parse Data","field":"payload","format":"handlebars","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":520,"y":461,"z":"3621d812.c9de28","wires":[["282e8c3f.d7d174"]]},{"id":"282e8c3f.d7d174","type":"http response","name":"","x":662,"y":460,"z":"3621d812.c9de28","wires":[]},{"id":"4e878f5.fb1787","type":"mongodb in","mongodb":"6ed1115c.912ef","name":"cmx data","collection":"cmx","operation":"find","x":363.75,"y":457.25,"z":"3621d812.c9de28","wires":[["a414e870.5beb18","fd7224e4.028dd8"]]},{"id":"96bebb9a.694148","type":"comment","name":"CMX in HTML table","info":"CMX in HTML table\n","x":100,"y":418,"z":"3621d812.c9de28","wires":[]},{"id":"bafdd665.450228","type":"comment","name":"CMX core functions","info":"CMX core functions","x":93,"y":29,"z":"3621d812.c9de28","wires":[]},{"id":"b02e2940.4fd1d8","type":"function","name":"limit results","func":"msg.limit = 2;\nmsg.sort = {\"_id\":-1};\nreturn msg;","outputs":1,"noerr":0,"x":276.05765533447266,"y":387.80774688720703,"z":"3621d812.c9de28","wires":[["4e878f5.fb1787"]]},{"id":"fd7224e4.028dd8","type":"function","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":469.423095703125,"y":528.1922912597656,"z":"3621d812.c9de28","wires":[["1d54eed0.e2ab11"]]},{"id":"1d54eed0.e2ab11","type":"debug","name":"","active":false,"console":"true","complete":"payload","x":657.8077392578125,"y":529.4999389648438,"z":"3621d812.c9de28","wires":[]},{"id":"d7d2081f.282df8","type":"function","name":"limit results","func":"msg.limit = 2;\nmsg.sort = {\"_id\":-1};\nreturn msg;","outputs":1,"noerr":0,"x":292,"y":322,"z":"3621d812.c9de28","wires":[["e55cc9d8.1aa338"]]},{"id":"304d4b6e.cfb2b4","type":"comment","name":"CMX in JSON view","info":"","x":91,"y":281,"z":"3621d812.c9de28","wires":[]},{"id":"5601778a.a9fe88","type":"debug","name":"CMX Validator","active":true,"console":"false","complete":"payload","x":599,"y":117,"z":"3621d812.c9de28","wires":[]},{"id":"21af9334.de506c","type":"function","name":"validate-secret","func":"// This node verifies that the secrect configured\n// on the Meraki Dashboard Network, matches.\n//var secret = \"merakilous\"; \nvar secret = \"testing123\";\n\nif(msg.payload.secret == secret){\n return msg;\n}else{\n // Secret is invalid\n \n}\n\n","outputs":1,"noerr":0,"x":303,"y":209,"z":"3621d812.c9de28","wires":[["1cc8879b.e33778","20f2bbcb.df0d44","d9d7d480.262828"]]},{"id":"e8acb38.f17535","type":"comment","name":"Connect DB to function to store data","info":"","x":542,"y":237,"z":"3621d812.c9de28","wires":[]},{"id":"f172aa31.0e8d58","type":"debug","name":"CMX post","active":false,"console":"false","complete":"payload","x":309,"y":144,"z":"3621d812.c9de28","wires":[]},{"id":"20f2bbcb.df0d44","type":"http response","name":"cmx response","x":545,"y":162,"z":"3621d812.c9de28","wires":[]}]