RSSI mapper for muenchen.freifunk.net

Project Description

I wanted a really mobile setup to measure the RSSI for our installations of muenchen.freifunk.net. It should be easy to carry and easy to use.

Project Details

Client muenchen.freifunk.net
Date 2016/02/21
Skills Hacking, Tinkering and a lots of fun
View muenchen.freifunk.net for more information

Project Feature

As long it did not find a muenchen.freifunk.net node, it does display the number of surrounding Wifi nodes. When it did find one or more muenchen.freifunk.net nodes, it selects the one with the current highest RSSI and displays this via the NeoPixel ring. For the next 60 seconds, this node is fixed. If it is lost, the search starts from the beginning.

If you add a serial console all the found SSIDs and more information is available with 9600-8-n-1.

Updated the source code to display a ration between open and secure networks, when not displaying RSSI. Furthermore introduction of a watchdog timer to catch issues in the WiFi subsystem.

Live Project

Project resources

This is what you need:

  • Adafruit Huzzah ESP8266
  • Adadruit Neopixel 16 LED ring
  • some wires
  • a lipstick size LiPo battery pack
  • The source code last update 2016/02/27
See More
/*
   RSSI mapper V0.1
   Copyright 2016, -mat- filid brandy, brandy@linuxpinguin.de
   See /project/rssi-mapper-for-muenchen-freifunk-net/

*/
// The WiFi support library
#include <ESP8266WiFi.h>

// The Neopixel supprt library
#include <Adafruit_NeoPixel.h>
#define stripSize 16
#define stripPin 14
Adafruit_NeoPixel strip = Adafruit_NeoPixel( stripSize, stripPin, NEO_GRB + NEO_KHZ800 );

uint32_t red;
uint32_t blue;
uint32_t black;
uint32_t white;
uint32_t green;
uint32_t yellow;
uint32_t orange;
uint32_t turkis;
uint32_t violet;
int lumocity = 6; //[2-6]
uint32_t maxAPs = stripSize;

// Use a watchdog timer to catch issue inside the WiFi module
// This sometime triggers, when scanning for new networks and none are in the neighboorhood
// The WiFi subsystem in the chip hangs, the watchdog catches this and reset the whole system
#include <Ticker.h>
Ticker secondTick;
int watchdogCount = 0;
void ISRwatchdog() {
  watchdogCount++;
  if (watchdogCount > 10) {
    Serial.println();
    Serial.println("watchdog triggered reset!");
    ESP.reset();
  }
}

// The multitasking looping support via timeslots
// [0] = search for new ssids
// [1] = find out the RSSI for a known BSSID
//
uint32_t cTick;     // current Tick in millis()
uint32_t pTick[2];  // previous Tick in millis()
uint32_t dTick[2];  // difference between current and previous Tick
bool fTick[2];      // first time

// Handling the search and "rescue"
String ssidToBeFound = "muenchen.freifunk.net";
bool suppressRSSIscan = HIGH;
uint8_t holdBSSID[6];


// Set all LEDs on the ring to the same color
void allColor(uint32_t c) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
}

// read the encryption type and print out the name:
void printEncryptionType(int thisType) {
  switch (thisType) {
    case ENC_TYPE_WEP:
      Serial.println("WEP");
      break;
    case ENC_TYPE_TKIP:
      Serial.println("WPA");
      break;
    case ENC_TYPE_CCMP:
      Serial.println("WPA2");
      break;
    case ENC_TYPE_NONE:
      Serial.println("None");
      break;
    case ENC_TYPE_AUTO:
      Serial.println("Auto");
      break;
  }
}

void setup() {
  Serial.begin(9600);

  // Attach the interrupt 1 to the watchog
  secondTick.attach(1, ISRwatchdog);

  // Setup the timeslots
  dTick[0] = 60 * 1000; // Every 60 seconds
  dTick[1] = 2 * 1000; // Every 2 seconds
  fTick[0] = HIGH;
  fTick[1] = HIGH;
  suppressRSSIscan = HIGH;

  // Initialize the LED ring
  strip.begin();
  strip.show();

  // Setup all colors we use
  black = strip.Color(0, 0, 0);
  red = strip.Color(pow(2, lumocity), 0, 0);
  green = strip.Color(0, pow(2, lumocity), 0);
  blue = strip.Color(0, 0, pow(2, lumocity));
  turkis = strip.Color(0, pow(2, lumocity), pow(2, lumocity - 1));
  orange = strip.Color(pow(2, lumocity), pow(2, lumocity - 1), 0);
  yellow = strip.Color(pow(2, lumocity), pow(2, lumocity), 0);
  violet = strip.Color(pow(2, lumocity), 0, pow(2, lumocity + 1));
  white = strip.Color(pow(2, lumocity), pow(2, lumocity), pow(2, lumocity));

  // Setup the WiFi module
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  allColor(red);
  delay(100);
  Serial.println("Setup done");
  allColor(black);
}

void copyBSSID(uint8_t *thisBSSID) {
  for (int i = 0; i < 6; i++) {
    holdBSSID[i] = thisBSSID[i];
  }
}

void printBSSID(uint8_t *thisBSSID) {
  for (int i = 0; i < 6; i++) {
    Serial.print(thisBSSID[i], HEX);
    Serial.print(":");
  }
}

void printHoldBSSID() {
  for (int i = 0; i < 6; i++) {
    Serial.print(holdBSSID[i], HEX);
    Serial.print(":");
  }
}

bool cmpBSSID(uint8_t *thisBSSID) {
  bool result = ( 1 == 1);
  for (int i = 0; i < 6; i++) {
    result = result && (holdBSSID[i] == thisBSSID[i]);
  }
  return result;
}

void displayNodes(int ffmucnodes, int opennodes, int nodes) {
  Serial.print("# ");
  Serial.print(ffmucnodes); Serial.print(" "); Serial.print(ssidToBeFound); Serial.print(" | ");
  Serial.print(opennodes); Serial.print(" open | ");
  Serial.print(nodes - opennodes); Serial.print(" closed | ");
  Serial.print(nodes); Serial.println(" nodes\n");

  allColor(black);
  maxAPs = ( maxAPs < nodes) ? nodes : maxAPs;
  maxAPs = ( maxAPs <= 0 ) ? stripSize : maxAPs;
  int midpointAPs = ( stripSize * nodes / maxAPs );
  for (int i = 0; i < midpointAPs; i++) {
    strip.setPixelColor(i, green);
  }
  midpointAPs = ( stripSize * opennodes / maxAPs );
  for (int i = 0; i < midpointAPs; i++) {
    strip.setPixelColor(i, red);
  }
  midpointAPs = ( stripSize * ffmucnodes / maxAPs );
  for (int i = 0; i < midpointAPs; i++) {
    strip.setPixelColor(i, blue);
  }
  strip.show();
}

void displayRSSI(int rssi) {
  int _rssi = abs(rssi);
  _rssi = (_rssi > 0) ? _rssi : 0;
  _rssi = (_rssi < 100) ? _rssi : 100;

  uint32_t c = red;
  c = (_rssi < 90) ? orange : c;
  c = (_rssi < 80) ? yellow : c;
  c = (_rssi < 70) ? green : c;
  c = (_rssi < 60) ? turkis : c;
  c = (_rssi < 55) ? blue : c;
  c = (_rssi < 50) ? violet : c;

  allColor(c);
}

void loop() {

  cTick = millis();
  watchdogCount = 0;  // Feed the watchdog

  // Find best freifunk every 60 seconds
  if ( (cTick - pTick[0]) >= dTick[0] || HIGH == fTick[0] ) {
    pTick[0] = cTick;
    fTick[0] = LOW;
    int networks = WiFi.scanNetworks();
    yield();  // give the WiFi subsystem enough time to settle things
    if ( 0 == networks ) {
      suppressRSSIscan = HIGH;
      dTick[0] = 0;
    } else if ( networks > 0 ) {
      int ffmucFound = 0;
      int open_nodes = 0;
      int maxRSSI = 0;
      for (int network = 0; network < networks; network++) {
        String ssid_scan;
        int32_t rssi_scan;
        uint8_t sec_scan;
        uint8_t* BSSID_scan;
        int32_t chan_scan;
        bool hidden_scan;
        WiFi.getNetworkInfo(network, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan);
        if (ssidToBeFound.equals(ssid_scan)) {
          ffmucFound++;
          if (maxRSSI < (127 + rssi_scan)) {
            copyBSSID(BSSID_scan);
            maxRSSI = 127 + rssi_scan;
            Serial.print("+");
          } else {
            Serial.print("-");
          }
        } else {
          Serial.print(" ");
        }
        if (sec_scan == ENC_TYPE_NONE ) {
          open_nodes++;
        }
        Serial.print(ssid_scan); Serial.print(" ");
        printBSSID(BSSID_scan); Serial.print(" "); Serial.print(rssi_scan);
        Serial.print("dBm chan:"); Serial.print(chan_scan); Serial.print(" ");
        printEncryptionType(sec_scan);
      }
      if (ffmucFound > 0) {
        suppressRSSIscan = LOW;
        dTick[0] = 60 * 1000;
      } else {
        suppressRSSIscan = HIGH;
        dTick[0] = 0;
      }
      displayNodes(ffmucFound, open_nodes, networks);
      Serial.print("Did find ");
      Serial.print(ffmucFound); Serial.print(" "); Serial.print(ssidToBeFound); Serial.println();
    }
  }

  // Show RSSI for the choosen BSSID every 2 seconds
  if ( ( (cTick - pTick[1]) >= dTick[1] || HIGH == fTick[1] ) && (LOW == suppressRSSIscan) ) {
    pTick[1] = cTick;
    fTick[1] = LOW;

    int networks = WiFi.scanNetworks();
    yield();  // Give the WiFi subsytem enough time to settle things
    bool lostKnownBSSID = HIGH;
    if ( networks > 0 ) {
      for (int network = 0; network < networks; network++) {
        String ssid_scan;
        int32_t rssi_scan;
        uint8_t sec_scan;
        uint8_t* BSSID_scan;
        int32_t chan_scan;
        bool hidden_scan;
        WiFi.getNetworkInfo(network, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan);
        if (cmpBSSID(BSSID_scan)) {
          Serial.print( "  ");
          Serial.print(ssid_scan); Serial.print(" ");
          printBSSID(BSSID_scan); Serial.print(" ");
          Serial.print(rssi_scan); Serial.println("dBm");
          displayRSSI(rssi_scan);
          lostKnownBSSID = LOW;
          //pTick[0] = cTick;  // Keep this BSSID until it is really lost, or rescan for networks every 60 seconds
        }
      }
      if (HIGH == lostKnownBSSID ) {
        Serial.println("lost BSSID again");
        suppressRSSIscan = HIGH;
        dTick[0] = 0;
      }
    } else {
      Serial.println("0");
      suppressRSSIscan = HIGH;
      dTick[0] = 0;
    }
  }
}

Like What You See?

Contact Us