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 arrived

Written 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":[]}]
dexterlabora

Flow Info

created 1 year, 6 months ago

Node Types

Core
  • comment (x4)
  • debug (x5)
  • function (x5)
  • http in (x4)
  • http response (x4)
  • mongodb (x1)
  • mongodb in (x2)
  • mongodb out (x1)
  • template (x1)

Tags

  • cisco
  • meraki
  • cmx
  • json
  • wifi
  • location
  • analytics
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option