-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlocationscanningreceiver-mongodb.py
More file actions
177 lines (142 loc) · 5.41 KB
/
locationscanningreceiver-mongodb.py
File metadata and controls
177 lines (142 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!flask/bin/python
"""
Cisco Meraki Location Scanning Receiver
A simple example demonstrating how to interact with the CMX API.
How it works:
- Meraki access points will listen for WiFi clients that are searching for a network to join and log the events.
- The "observations" are then collected temporarily in the cloud where additional information can be added to
the event, such as GPS, X Y coordinates and additional client details.
- Meraki will first send a GET request to this CMX receiver, which expects to receieve a "validator" key that matches
the Meraki network's validator.
- Meraki will then send a JSON message to this application's POST URL (i.e. http://yourserver/ method=[POST])
- The JSON is checked to ensure it matches the expected secret, version and observation device type.
- The resulting data is sent to the "save_data(data)" function where it can be sent to a databse or other service
- This example will simply print the CMX data to the console.
Default port: 5000
Cisco Meraki CMX Documentation
https://documentation.meraki.com/MR/Monitoring_and_Reporting/CMX_Analytics#CMX_Location_API
Written by Cory Guynn
2016
www.InternetOfLEGO.com
Developers.Meraki.com
"""
# Libraries
from pprint import pprint
from flask import Flask
from flask import json
from flask import request
from flask import render_template
import sys, getopt
import json
from pymongo import MongoClient
############## USER DEFINED SETTINGS ###############
# MERAKI SETTINGS
validator = "EnterYourValidator"
secret = "EnterYourSecret"
version = "2.0" # This code was written to support the CMX JSON version specified
locationdata = 'Location Data Holder'
client = MongoClient("mongodb://localhost:27017")
db = client.locationdata
# Save Location Data
def save_data(data):
print("---- SAVING Location DATA ----")
pprint(data, indent=1)
## Adjust data before DB insert ##
# Add GeoJSON structure for MongoDB Compass (or similar) mapping
'''for i in data["data"]["observations"]:
print("i",i)
data["data"]["secret"] = "hidden"
lat = i["location"]["lat"]
lng = i["location"]["lng"]
clientMac = i["clientMac"]
data["data"]["geoJSON"] = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [lat,lng]
},
"properties": {
"name": clientMac
}
}
#data["data"]["locationGeoJSON"] = json.dumps(locationGeoJSON)
#data["data"].append({"geoJSON":{"type": "Feature","geometry": {"type": "Point","coordinates": [i["location"]["lat"], i[["location"]["lng"], i["location"]["unc"]]},"properties": {"name": i["clientMac"]}}})
'''
# Commit to database
result = db.locationdata.insert_one(data)
print("MongoDB insert result: ",result)
####################################################
app = Flask(__name__)
# Respond to Meraki with validator
@app.route('/', methods=['GET'])
def get_validator():
print("validator sent to: ",request.environ['REMOTE_ADDR'])
return validator
# Accept CMX JSON POST
@app.route('/', methods=['POST'])
def get_locationJSON():
global locationdata
if not request.json or not 'data' in request.json:
return("invalid data",400)
locationdata = request.json
pprint(locationdata, indent=1)
print("Received POST from ",request.environ['REMOTE_ADDR'])
# Verify secret
if locationdata['secret'] != secret:
print("secret invalid:", locationdata['secret'])
return("invalid secret",403)
else:
print("secret verified: ", locationdata['secret'])
# Verify version
if locationdata['version'] != version:
print("invalid version")
return("invalid version",400)
else:
print("version verified: ", locationdata['version'])
# Determine device type
if locationdata['type'] == "DevicesSeen":
print("WiFi Devices Seen")
elif locationdata['type'] == "BluetoothDevicesSeen":
print("Bluetooth Devices Seen")
else:
print("Unknown Device 'type'")
return("invalid device type",403)
# Return success message
return "Location POST Received"
@app.route('/go', methods=['GET'])
def get_go():
return render_template('index.html',**locals())
@app.route('/clients/', methods=['GET'])
def get_clients():
global locationdata
pprint(locationdata["data"]["observations"], indent=1)
return json.dumps(locationdata["data"]["observations"])
@app.route('/clients/<clientMac>', methods=['GET'])
def get_individualclients(clientMac):
global locationdata
for client in locationdata["data"]["observations"]:
if client["clientMac"] == clientMac:
return json.dumps(client)
return ''
# Launch application with supplied arguments
def main(argv):
global validator
global secret
try:
opts, args = getopt.getopt(argv,"hv:s:",["validator=","secret="])
except getopt.GetoptError:
print ('locationscanningreceiver-mongodb.py -v <validator> -s <secret>')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print ('locationscanningreceiver-mongodb.py -v <validator> -s <secret>')
sys.exit()
elif opt in ("-v", "--validator"):
validator = arg
elif opt in ("-s", "--secret"):
secret = arg
print ('validator: '+ validator)
print ('secret: '+ secret)
if __name__ == '__main__':
main(sys.argv[1:])
app.run(port=5000,debug=False)