Here’s the code I made for the EXACT same purpose. Mind you it only allows 4 Wi-Fi networks to be sent, so it isn’t perfect, but it is still accurate to ~10m, depending on where you are.
#define SCANNED 4
WiFiAccessPoint aps[SCANNED];
String msg;
String mac;
unsigned long t = 0;
void setup() {
Particle.subscribe("hook-response/geolocation", getLoc, MY_DEVICES);
Serial.begin(9600);
while (!Serial.available()) Particle.process();
}
void loop() {
if (millis()-t > 3500) {
msg = "{ ";
WiFi.scan(aps, SCANNED);
Particle.process();
for (int x = 0; x < SCANNED; x++) {
mac = "";
for (int y= 0; y < 6; y++) {
mac = mac+String(aps[x].bssid[y], HEX);
if (y != 5) {
mac = mac+":";
}
}
mac.toUpperCase();
msg = msg+"\"mac"+String(x)+"\": \""+mac+"\", \"sig"+String(x)+"\": \""+String(aps[x].rssi)+"\", \"channel"+String(x)+"\": \""+String(aps[x].channel)+"\"";
if (x != 3) {
msg = msg+", ";
}
Particle.process();
}
msg = msg+" }";
Serial.println(msg);
Particle.publish("geolocation", msg, 60, PRIVATE);
t = millis();
}
}
void getLoc(const char *name, const char *data) {
Serial.println(data);
}
And the webhook:
{
"eventName": "geolocation",
"url": "https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_KEY",
"requestType": "POST",
"json": {
"wifiAccessPoints": [
{
"macAddress": "{{mac0}}",
"signalStrength": "{{sig0}}",
"channel": "{{channel0}}"
},
{
"macAddress": "{{mac1}}",
"signalStrength": "{{sig1}}",
"channel": "{{channel1}}"
},
{
"macAddress": "{{mac2}}",
"signalStrength": "{{sig2}}",
"channel": "{{channel2}}"
},
{
"macAddress": "{{mac3}}",
"signalStrength": "{{sig3}}",
"channel": "{{channel3}}"
}
]
},
"responseTemplate": "{{location.lat}}~{{location.lng}}~{{accuracy}}",
"mydevices": true
}