Wifi density with ESP8266 and LoRa module

Hi All,

At the Sodaq event in Hilversum a few weeks ago, I remember talking to someone who had written some code on the ESP8266 that counts the number of nearby Wifi stations (i.e. people with mobile phones) and relays the metric via LoRaWAN. The idea being that the device would report a metric showing the relative density of people in a given area.

While there seems to be lots code out there that finds Wifi APs, I can not find any code that finds stations. I also saw the following youtube video (https://www.youtube.com/watch?v=GQMZg5FPE watch 2:00-3:00) indicating that the ESP libraries in arduino allows for some basic snooping of Wifi stations.

Any pointers to whoever wrote this code or even a github link would be greatly appreciated.



I’ve been working on an ESP8266 node that scans for wifi stations, stores them in internal memory and uploads them when in wifi range (at least that’s the plan)
There are various services that can give you a location based on a list of wifi stations in range. Most easy to use are the APIs provided by Google (you can request some API keys) and Mozilla (you can use a test API key). If you just use wifi base station ids, you can even use the same JSON encoding for both services.

See my project page at:

Hi Bertrik,

Thanks for the response but we may be using the term station to mean different things. In my case, I am not looking for wifi access points. I am looking for stations. By stations, I mean mobile phones. In your application using the ESP8266, you are putting the device in Station mode to look for APs. I think your application is actually looking for APs and storing their GPS location…

Thanks for the reply just the same.


Inspired by @waltert who pointed me to https://github.com/pulkin/esp8266-injection-example/blob/master/user/user_main.c I wrote a simple Arduino sketch that does a scan on a certain channel, keeps a list of unique MACs encountered so far and prints them to serial output. This sketch scans not just APs but any wifi device sending data.

This is still very simple code, processing only one type of wifi client promiscuous frames. You’ll probably need to add code to hop channels (it only scans channel 6 now), but the basics are there in a simple and short sketch.

You can find my code here:

1 Like

Thanks Bertrik. Thanks for the code!

I managed to add in some logic that takes 15 second samples from channels 1, 6, 11 and then 14 and reports the total number of detected IP addresses over MQTT. I then took the device with me on trip into Amsterdam. In the Amsterdam Central station, over 440 mac addresses were collected in one sampling at around 6pm. In the Utrecht-Amsterdam train, it was averaging at around 95 mac addresses. While not totally accurate, it provides a course estimation of crowds in a given area…


Hi Mark,

Some other points:

  • It seems I get promiscuous frames that are either 128 or 60 bytes long. Initially my code only considered the 128-byte ones, but the shorter frames seem to use the same format, so I see no need anymore to only process the 128-byte frames.
  • Looking a bit closer at the wifi spec, I see there’s a “frame control” word that contains bits indicating the “direction” of the traffic in the FromDs and ToDS bits. A frame with FromDS=0 should indicate that a frame originates from a wifi station (not an AP). It took me a lot of head scratching to find out how these bits are encoded (little-endian byte order with an unusual bit order in the specification), but I think I get it right now.
  • I was told that some Apple devices obfuscate their mac address by changing it at periodic intervals under some circumstances (when scanning for APs), so you might get some duplicates from this.
  • You need to be a bit careful what you do with MAC address data from a privacy standpoint. There have already been some dutch court cases where organisations collecting MAC addresses were fined / forbidden from storing MACs.

Indeed. And I feel companies that perform these kind of measurements should be forced to use LoRaWAN to transmit their results; its limited bandwidth ensures only statistics are transmitted and stored. :slight_smile:

(Like only send 3 numbers x, y and z, where x is the number of devices seen for less than 5 minutes, y the number seen less than 10 minutes, z less than 60 minutes. Yes, that means one cannot track to which other tracking location a device might have moved, but it still gives one a nice indication about how crowded a place is.)

Can you publish your code?