WiFi Triangulation

Triangulate access points using an ESP8266 and a GPS module.

Similar projects worth following
In my neighborhood there is a Wi-Fi router with a nasty name. While I was playing with my ESP8266 I saw it again…
The AT+CWLAP (List Access Points) command return the AP names, their MAC address and the RRSI: Received signal strength indication. I had immediately the idea to try to triangulate that nasty router. So I hooked up a PIC18F25K22 with a GPS module, a ESP8266 (ESP-07 with an external antenna) and an OLED color display. Then I went for a walk...

Back home the data is dumped on my PC, imported in a MS Access database (to simplify some math) and a HTML file calling Google Maps is generated.

The router name in red is open. The yellow one is WEP or WPA_PSK or WPA2_PSK. The white ones are WPA_WPA2_PSK.

The red dots are the sampling points. The markers are the other routers. The red lines show the points that were used to triangulate. The streets names and the MAC address were erased on purpose.

Disclaimer: This is an approximate triangulation and the signal strength depends where is the source inside the home which impact the results. Also, the triangulation I’m doing is kinda wrong. You cannot just use the coordinates as XY like I did because they are on a sphere but for short distance it's OK.


To understand how I did it, see the triangulation as vectors with different signal strengths. Each one "pulling" with its own strength. All of the triangulation computing is done with some queries in the database. This saves A LOT of code.

The RSSI (Received signal strength indication) is an attenuation given in negative dB: -90db is less than -60dB and so on. To simplify things, I work with positive numbers as a kind of “signal strength”:

Strength = (100 + RSSI)

Why 100? Because the RSSI given by the ESP never goes below -99dB. So a -90dB signal give me a strength of 10, -60dB = 40 and so on.

Some simple math now. For a given Access Point (AP) I do a sum of all the measured signal strength: let's call it [RSSI_Sum].

Then for each sample (Strength @ coordinate) I compute a strength ratio (the vector "Strength"):

SignalRatio_@LatLong1 = Strength_@LatLong1 / [RSSI_Sum]
SignalRatio_@LatLong2 = Strength_@LatLong2 / [RSSI_Sum]
SignalRatio_@LatLong_n = Strengt_@LatLong_n / [RSSI_Sum]

Here is some partial results:

Then I triangulate (ok, approximate a triangulation) the lat/long by doing a sum of... I don't know how to explain it in English...

For each GPS coordinate I do apply the SignalRatio of that coordinate then sum them all:

Latitude = Sum( Lat_n * [SignalRatio_n] ) 
Longitude = Sum( Long_n * [SignalRatio_n] )

Kind look like this in SQL:

SELECT SSID, Sum(Lat*[SignalRatio]) AS Lat, Sum(Lng*[SignalRatio]) AS Lng

It's a really rough triangulation because the coordinates are on a sphere (our planet) but I think it's OK for a few meters.

Finally, a dotNET app is used to build a HTML file with some generated JavaScript for the Google Maps API. It’s ugly but for a one-time project that’s OK.

There you are MutherF***er…

View project log

Enjoy this project?



arre_diels wrote 05/30/2016 at 14:18 point

I was so stunned by the simplicity of your solultion, that it made me think quite alot more. And I came to the conclusion that perhaps you should not immediately start calling that neighbour the m**f**ker:)

Your calculation is very simple, but even in flat-space a very rough approximation. You sort of weighted-average the position based on the gps coordinates and wifi strengths. Although this is somewhat intuitively in the right direction, it is definitely only an approximation.
For starters, it assumes the signal fades linearly over distance, and secondly ignores the fact that the source should be radiating out from a single point in space. 

Especially that last bit should mean that any result is only an estimate, and it is possible to come up with a "certainty" of a result, and see if adding more measurements makes it converge or not. (In your case it will always give "an" output, but possibly a very wrong one)

Regarding the first problem: even in free space the signalpower drops with the distance^2, and due to obsticales, results may be widely inacurrate. (you might be very close and get a bad signal, and vice versa). 

A toy examples where both approaches differ greatly:

- Assume you walked 20 meters west of the target, in a line from south to north

 |   (*)

 In your calculation the target would be exactly on that line. (which it obviously isn't). A more proper calculation could look at the signal power more carefully, and would find that the signals match better a situation of a source not on the line. (For the simple reason that following the line does not drop the signal level as much as it would if the source was on it)

But aside from the fact that the result might not be so accurate, all the rest in the post remains pretty neat, and I'm pretty sure you never assumed it to be super accurate in the first place. So please don't take this as any criticism, but rather as a funny thought that you made someone think a lot about something that was not the point:)

  Are you sure? yes | no

arre_diels wrote 05/30/2016 at 13:25 point

Awesome post, especially the elegance of the sql calc!

  Are you sure? yes | no

Michel wrote 05/29/2016 at 13:08 point

LOL! +1 for the goat!

  Are you sure? yes | no

Jarrett wrote 05/12/2016 at 16:17 point

I like to name my router APs things like "I am watching you pee" or "I can hear you having sex" because the thought of people getting really offended over something that is hurting literally no one and doesn't really matter makes me laugh

  Are you sure? yes | no

johnowhitaker wrote 05/29/2016 at 09:47 point

My default was 'FBI surveillance van'. 

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates