Difference between revisions of "EspWifiTracker"

From RevSpace
Jump to navigation Jump to search
(Uploading has been fixed)
Line 161: Line 161:
 
* WiFi station whitelist, list of stations which are known to be really open to the internet
 
* WiFi station whitelist, list of stations which are known to be really open to the internet
 
* WiFi station blacklist, list of stations which are open (unencrypted), but not really open to the internet
 
* WiFi station blacklist, list of stations which are open (unencrypted), but not really open to the internet
 +
 +
== Results ==
 +
=== 2016-04-23 ===
 +
Shown here is a plot of locations from an AP scan done every 10 seconds, while traveling by car from RevSpace (The Hague area) to the train station of Gouda.
 +
Locations have been resolved using both the Google geo-location API (blue) and the Mozilla Location Service (red).
 +
In total, Google was able to resolve 220 locations, Mozilla was able to resolve 204 locations.
 +
 +
[[File:20160423_overview.jpg|right|thumb]]
 +
First of all an overview of the locations.
 +
You can see clearly that both Google and Mozilla give a lot of fixes in urban areas.
 +
We probably drove with a speed of around 50 km/h in the urban areas (and stopping for some traffic lights) and around 130 km/h on the highway.
 +
Noticeable is a huge gap on the A12 highway north of the town of Zevenhuizen, for both Google and Mozilla.
 +
 +
[[File:20160423_voorburg.jpg|right|thumb]]
 +
 +
[[File:20160423_gouda.jpg|right|thumb]]

Revision as of 12:46, 23 April 2016

Project EspWifiTracker
EspWifiTracker2.jpg
Location-tracker based on WiFi station ids
Status In progress
Contact bertrik
Last Update 2016-04-23

Status

Voorburg.jpg

Status:

  • 2016-04-19 Connected a LiFePO4 battery and made a scan of the trip from RevSpace to Gouda, one point every 20 seconds. Using this kind of battery to power the ESP8266 directly seems to work fine!
  • 2016-04-10 Made my first actual scan and processed the data using the Google location service. I'm using pin D5 to decide between "run mode" (scan, log, sleep) and "debug mode" (accept commands from the serial port)
  • 2016-03-26 I've been thinking about using the WiFiManager component, this component presents you with a web page to configure stuff, like the name/password of the AP to connect to the internet. It also allows you to configure extra properties. I could put the URL of the upload server in these extra properties (and just HTTP GET the rest of the settings from the server).
  • 2016-03-25 I got submission of wifi scan results to google working, Mozilla appears to use a compatible format (i.e. the google JSON format with some extensions).
  • 2016-03-17 Can't really get the wake-up using the DS3231 to work, the interrupt pin appears to be active all the time, keeping the ESP in reset. I think I'll just use the ESP built-in wake-up mechanism.
  • 2016-03-16 Working on a prototype using a NodeMCU with a DS3231 RTC

Next steps:

  • Make scanning WiFi and storing it on the file system just work without worrying about how to upload data yet.
  • Make data uploading from the ESP work reliably, right now it can't seem to handle large uploads
  • Make some nice Java service to accept the JSON data, store/convert the data to coordinates and host it somewhere
  • create a kind of blacklist/whitelist mechanism that scores each scanned AP for suitability to connect to the internet, based on AP name / security type / whether we know the password / etc. A negative score could mean that it should definitely NOT try to connect using a specific AP. The AP with the highest score is tried first

Open challenges:

  • first of all make a working prototype, not necessarily optimized yet for size / appearance / battery usage / etc
  • when using "WiFi hotspots": figure out how to handle so-called captive portals. Many open access points spoof DNS after connecting to the access point and re-direct you to a webpage where you either need to log in or click some 'I agree' button. It's easy for a human to understand this, possibly not so easy for an embedded device.
  • make it lower power: so we can use a smaller battery or get longer tracking time. First of all, I should get an idea of the power consumption in its current state.
  • make it smaller and lighter: so it can be attached to smaller items (e.g. a migrating bat)

Introduction

The idea of this project is to create a simple and low-cost WiFi location tracker.

It tracks location by periodically scanning for WiFi station ids, storing those in internal memory and using one of the various location services (google, mozilla, openwlanmap, etc.) to determine a geographical location from this.

This can be used to track various things, for example:

  • track your own bicycle
  • know where your cat goes
  • monitor movement of wild animals for research purposes, like bats or stone martens.

The basic operating principle is this:

  • the tracker is in deep-sleep most of the time, keeping only a low-power real-time-clock running.
  • every once in a while (say once a day) it wakes up, takes a reading of all WiFi stations in range and their signal strength. It stores these in internal memory.
  • if the tracker wakes up to find an open WiFi station (or one that it knows the WiFi password of), it tries to upload all previous readings to a server.
  • the server resolves the uploaded data into geographical locations using a service like Google or the Mozilla Location Service.

Tracker prototype

I'm working on a prototype of this.

Hardware

EspWifiTracker.jpg

I'm basing this off an inexpensive NodeMCU clone. The NodeMCU is basically an ESP8266-module on a break-out board with an USB-serial converter and a proper 3.3V power supply. The ESP8266 is a WiFi-capable microcontroller, capable of running at 80 MHz, it has 1 MB (or more) of flash onboard which enough spare flash sectors to hold a file system.

Pin D0 (GPIO16/WAKEn) is connected to RST to support wake-up-by-reset with the ESP internal deep sleep mode.

To keep time, I'm using a ZS-042 clock module, containing a Maxim DS3231 RTC chip (datasheet). This module is attached to the NodeMCU through the I2C-bus on pins D1 (GPIO5/SCL) and D2 (GPIO4/SDA). I removed the power LED on board the ZS-042 module, since one of the reasons to have an RTC is to save current and the power LED wastes current unnecessarily. It would be very nice if the RTC could wake up the ESP8266 using the alarm wake-up feature, but I cannot get this to work: the alarm output always seems to be low, keeping the ESP8266 in reset.

Pin D5 (GPIO14) is used to distinguish between run mode and debug mode during reset/wake-up. When this pin is pulled low (e.g. by a wire to GND), the tracker goes into debug mode. If this pin is left floating, an internal pull-up makes it high and the tracker goes into run mode.

I'm powering the ESP8266 directly off a single cell LiFePO4 battery. In particular I'm using a "14500" battery, which has the same dimensions as a common "AA"/"penlite" battery. A single cell of this type outputs about 3.2-3.4V, which is a good match for the ESP8266 voltage requirement of 3.3V.

NodeMCU schematic

Software

The NodeMCU can be conveniently programmed from the "Arduino" development environment using the Arduino core for ESP8266 WiFi chip

This already comes with a library for WiFi that allows you to scan for WiFi stations

Other libraries used:

  • Makuna RTC which can be installed into the Arduino environment by going to menu Sketch/Include Library/Manage libraries..., then searching for 'Makuna rtc' and installing it.

My prototype software can be found at: https://github.com/bertrik/wifitracker

modes

The software can run in one of two modes, run mode and debug mode.

If pin D5 is pulled low during start-up, the software goes into debug mode In debug mode, it runs a simple command interpreter, type 'help' at 115200 bps to get a list of supported commands.

If pin D5 is left unconnected, the software goes into run mode. In run mode, the device scans APs, saves the result to a time-stamped file in flash memory and goes back to sleep as soon as possible to save power.

AP selection

I'm thinking of a kind of whitelist/blacklist mechanism to select an AP for uploading data. The plan is to score each scanned AP against this list and then select the one with the highest score, excluding APs which have a negative score. The first match in the list determines the score, so the list is ordered from most specific to least specific. The score is based on network name and encryption type.

This way, we could select and AP on a preference order, for example:

  • first, try a secure network that we know the password of;
  • next, try an open network that we know is open to the internet (probably very rare...);
  • ignore any open network that we know is not really open or uses a captive portal (like "KPN Fon")
  • try any open network that is unknown to us.

For example, the entries in the list could look like this:

  • {score=100, ssid="my_home_network", pass="my_home_pass"}
  • {score=100, ssid="my_work_network", pass="my_work_pass"}
  • {score=-100, ssid="KPN Fon", pass=""}
  • {score=-100, ssid="WiFi in de trein", pass=""}
  • {score=-100, ssid="McDonalds FREE WIFI", pass=""}
  • {score=0, ssid="*", pass=""}

where an entry with an empty password represents an open network.

main program flow

The ESP wakes from sleep on reset:

  • read the RTC to determine if it's time to do a scan, else go to sleep again
  • scan wifi networks
  • append the results of the scan to file, the file name is based on the current date.
  • score each network for suitability for upload, if none is found, go to sleep again
  • connect to the network and probe for actual internet connectivity
  • upload the log files one by one, delete the file if successful
  • download new settings files
  • try to perform an NTP sync and update the RTC if successful
  • go to sleep.

data structures

The plan is to use JSON for data to be uploaded. The log file is also formatted as JSON, so during upload we can simply upload the log file without further processing. The advantage is that JSON is readable to humans, disadvantage is that it needs more space than a binary format. The log file contains one line per wifi scan, example of JSON:

{"deviceid":"18FE34XXXXXX","datetime":"2016-03-21 12:34:56","scan":[{"mac":"123456787878","rssi":-49},{"mac":"785634121212","rssi":-42}]}

The device id is the ESP MAC address. Times are in UTC.

The Google Location Service seems to be interested in the channel too (not sure why), we could also log this.

For the settings file, I'm thinking of a simple ini/properties file structure, with KEY=VALUE pairs in it, with empty lines and lines starting with "#" being ignored.

Server backend

The server backend receives uploads from the tracker and resolves the WiFi station ids into locations by using a location service, for example:

The MAC address of the ESP8266 should be unique and can be used to identify a specific tracker.

Communication between the tracker and the server is always initiated by the tracker. The protocol is REST (HTTP) and the format is JSON. I'm thinking of writing this in Java, with the use of Jackson 2.0 (JSON), Jersey 2.0 (REST) and Jetty libraries.

The REST service could have two endpoints:

  • one to upload collected WiFi data from the tracker to the server
  • one to download configuration data from the server to the tracker

Configuration data can be made specific for each tracker, and could consist of things like:

  • a new periodic wake-up schedule
  • list of known WiFi stations + passwords
  • WiFi station whitelist, list of stations which are known to be really open to the internet
  • WiFi station blacklist, list of stations which are open (unencrypted), but not really open to the internet

Results

2016-04-23

Shown here is a plot of locations from an AP scan done every 10 seconds, while traveling by car from RevSpace (The Hague area) to the train station of Gouda. Locations have been resolved using both the Google geo-location API (blue) and the Mozilla Location Service (red). In total, Google was able to resolve 220 locations, Mozilla was able to resolve 204 locations.

20160423 overview.jpg

First of all an overview of the locations. You can see clearly that both Google and Mozilla give a lot of fixes in urban areas. We probably drove with a speed of around 50 km/h in the urban areas (and stopping for some traffic lights) and around 130 km/h on the highway. Noticeable is a huge gap on the A12 highway north of the town of Zevenhuizen, for both Google and Mozilla.

20160423 voorburg.jpg
20160423 gouda.jpg