So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By QuickFix
#66167
torntrousers wrote:A Wifi device does actually broadcast its presence


Interesting reading material, thanks @torntrousers! :D
User avatar
By QuickFix
#66194 Does anyone got the onSoftAPModeProbeRequestReceived event actually working?

I've tried the example in the GitHub repository (it's not included yet in the "Boards manager"-version), but I'm not getting any probe-events, while the connect- and disconnect-events work as expected.

Used a couple of different devices, including Android 5, Android 6 and IOS 7 (an old iPhone 4).
They all see the ESP, but the handler just isn't get called. :cry:

[EDIT]
It does actually work, but there's something wrong with the example: it only probes for the first 10 seconds, after which it disables the probe-event.

Will keep you updated. 8-)
User avatar
By QuickFix
#66200 My first try at a solution:
Code: Select all/*
    This sketch will try to keep a list of all devices in
    the vicinity by signaling probe requests it receives.

    When a device probes for AP's (and it's picked up by our ESP8266),
    the ESP will search a table to see if it's already known.
    If not: it is added to the list, if it's already known, the entry's
    timestanp will be updated.
    When a device is not seen for a certain amount of time, it is
    removed from the list again.


    Output to serial console:
    - When a new device is found
    - When an existing device has left (timed out)
   
    Input from serial console:
    - Any command (or just LF) will show a list of registered devices


    NOTE: This is my first sketch using C++ for the ESP8266 (in real
          life I'm actually a Pascal/Delphi programmer), so don't shoot
          me for any weird pieces of code.
          I hope to be as good as you in the near future.

    Code inspired by the WiFiEvents-example by Ivan Grokhotkov.
    This version of the code was written by Peter Luijer and
    is released into the public domain, or, at your option,
    CC0 licensed.
*/

#include <ESP8266WiFi.h>
#include <stdio.h>

typedef struct
  {
      uint8_t mac[6];
      int rssi;
      unsigned long ms;
  }  client_device;

const char* proberversion = "ESProber v.0.9b by QuickFix, (c)2017";
const int   maxdevices    = 255; // Max. number of devices to keep track off at a time
const int   listtimeout   = 120; // Consider device away if not seen for this numner of seconds
const char* ap_ssid       = "ESProber"; // Name for our AP
const char* ap_password   = "12345678"; // Password for our AP
                                 
WiFiEventHandler probeRequestHandler;
client_device devicelist[maxdevices];
String consolebuffer;

int adddevice(const uint8 mac[6], int rssi) {
  int d;
  d = -1; 
  int i;
  for (i = 0; i < maxdevices; i = i + 1) {
    if ((devicelist[i].mac[0] == 0) &&
        (devicelist[i].rssi == 0)) {
      d = i;
      devicelist[d].mac[0] = mac[0];
      devicelist[d].mac[1] = mac[1];
      devicelist[d].mac[2] = mac[2];
      devicelist[d].mac[3] = mac[3];
      devicelist[d].mac[4] = mac[4];
      devicelist[d].mac[5] = mac[5];
      devicelist[d].rssi   = rssi;
      devicelist[d].ms     = millis();
      break;
    }
  }
  return d;
}

void updatedevice(int index, int rssi) {
  devicelist[index].rssi = rssi;
  devicelist[index].ms   = millis();
}

void cleardevice(int index) {
  devicelist[index].mac[0] = 0;
  devicelist[index].rssi   = 0;
  devicelist[index].ms     = 0; 
}

void cleardevices() {
  int i;
  for (i = 0; i < maxdevices; i = i + 1) {
    cleardevice(i); 
  } 
}

int countdevices() {
  int d;
  d = 0; 
  int i;
  for (i = 0; i < maxdevices; i = i + 1) {
    if ((devicelist[i].mac[0] != 0) &&
        (devicelist[i].rssi != 0)) {
      d = d + 1;
    }
  }
  return d;
}

int finddevice(const uint8 mac[6]) {
  int d;
  d = -1; 
  int i;
  for (i = 0; i < maxdevices; i = i + 1) {
    if ((devicelist[i].mac[0] == mac[0]) &&
        (devicelist[i].mac[1] == mac[1]) &&
        (devicelist[i].mac[2] == mac[2]) &&
        (devicelist[i].mac[3] == mac[3]) &&
        (devicelist[i].mac[4] == mac[4]) &&
        (devicelist[i].mac[5] == mac[5])) {
      d = i;
      break;
    }   
  }
  return d;
}

void checklist() {
  int i; 
  for (i = 0; i < maxdevices; i = i + 1) {
    if ((devicelist[i].mac[0] != 0) &&
        (devicelist[i].rssi != 0) &&
        ((devicelist[i].ms + (listtimeout * 1000)) < millis())) {
      Serial.print("Device ");
      Serial.print(macToString(devicelist[i].mac));
      Serial.println(" has left");
      cleardevice(i);
    }
  }
}

void printlist() {
  int c;
  c = countdevices();
  Serial.println("");
  Serial.print(c); 
  Serial.print(" registered devices (prober running for ");
  Serial.print(millis() / 1000);
  Serial.println(" seconds):");
 
  if (c > 0) {
    int i;   
    for (i = 0; i < maxdevices; i = i + 1) {
      if ((devicelist[i].mac[0] != 0) &&
          (devicelist[i].rssi != 0))
      {
        Serial.print("MAC: ");
        Serial.print(macToString(devicelist[i].mac));
        Serial.print(" RSSI: ");
        Serial.print(devicelist[i].rssi);     
        Serial.print(" last seen ");
        Serial.print((millis() - devicelist[i].ms) / 1000);
        Serial.println(" seconds ago");
      }   
    }
  } 
}

String macToString(const uint8 mac[6]) {
  char buf[20];
  snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  return String(buf);
}

void checkconsole() {
  char c;
 
  while (Serial.available() > 0) {
    c = Serial.read();
    if (c == '\n') {
      printlist();     
      consolebuffer = "";
    } else {
      consolebuffer +=c;
    }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(proberversion); 
 
  Serial.println("Configuring wifi:");
  WiFi.mode(WIFI_AP);
 
  Serial.print("- SSID: ");
  Serial.println(ap_ssid);
  Serial.print("- Password: ");
  Serial.println(ap_password);
  WiFi.softAP(ap_ssid, ap_password);

  Serial.print("Maximum number of devices: ");
  Serial.println(maxdevices);
  cleardevices();
  Serial.print("Registration time-out (s): ");
  Serial.println(listtimeout);

  probeRequestHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequest);
  Serial.println("Probing started");
}

void onProbeRequest(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
  int i;
  i = finddevice(evt.mac);
  if (i < 0) {
    i = adddevice(evt.mac, evt.rssi);
    if (i < 0) {
      Serial.print("Unable to add new device to list");
    } else {
      Serial.print("New device found");
    }
    Serial.print(", MAC: ");
    Serial.print(macToString(evt.mac));
    Serial.print(" RSSI: ");
    Serial.println(evt.rssi);   
  } else {
    updatedevice(i, evt.rssi);
  }
}

void loop() {
  checklist();
  checkconsole(); 
  delay(10);
}

For the code to work, you'll need to have the latest ESP8266-library code from GitHub (the current release version in the Arduino Board Manager isn't up to date yet). :idea:

When compiled and flashed, you'll see output on the console similar to this:
Code: Select allESProber v.0.9b by QuickFix, (c)2017
Configuring wifi:
- SSID: ESProber
- Password: 12345678
Maximum number of devices: 255
Registration time-out (s): 120
Probing started
New device found, MAC: 2c:0e:3d:47:2d:bd RSSI: -68
New device found, MAC: b8:53:ac:9c:f1:99 RSSI: -80
Device 2c:0e:3d:47:2d:bd has left
New device found, MAC: 70:72:0d:3a:6b:e2 RSSI: -28
New device found, MAC: 54:60:09:79:4c:e6 RSSI: -78


To get a current list of registered devices, just send a LF on the console:
Code: Select all3 registered devices (prober running for 319 seconds):
MAC: e0:c7:67:36:47:f4 RSSI: -86 last seen 3 seconds ago
MAC: 54:60:09:79:4c:e6 RSSI: -87 last seen 24 seconds ago
MAC: bc:6e:64:83:b0:2a RSSI: -88 last seen 0 seconds ago

I know the code may look weird at places, but this is my first go at C++, since I'm actually a Pascal/Delphi developer in real life.
You're welcome to critize my code, but please be gentle. ;)

Greetz,

Peter
User avatar
By torntrousers
#66240
QuickFix wrote:I know the code may look weird at places, but this is my first go at C++, since I'm actually a Pascal/Delphi developer in real life. You're welcome to critize my code, but please be gentle. ;)


Looks fine to me.

I've wondered about how to do something useful with these probe events. Something like record the date/time of each device visit along with its closest RSSI, and have daily and weekly reporting to show who comes by and when?