4#error "PoliticianStorage.h requires the Arduino framework. Use ESP-IDF VFS and nvs_flash APIs directly."
9#include <Preferences.h>
32 bool isNew = !fs.exists(path);
34 fs::File check = fs.open(path, FILE_READ);
36 isNew = (check.size() == 0);
41 fs::File file = fs.open(path, FILE_APPEND);
42 if (!file)
return false;
72 static bool appendPacket(fs::FS &fs,
const char* path,
const uint8_t* payload, uint16_t len, int8_t rssi, uint8_t channel, uint32_t ts_usec) {
73 bool isNew = !fs.exists(path);
75 fs::File check = fs.open(path, FILE_READ);
77 isNew = (check.size() == 0);
82 fs::File file = fs.open(path, FILE_APPEND);
83 if (!file)
return false;
94 file.write(buf, wlen);
116 fs::File file = fs.open(path, FILE_APPEND);
117 if (!file)
return false;
121 file.println(str.c_str());
150 float lat,
float lon,
float alt = 0.0,
float acc = 10.0,
151 const char* timestamp =
nullptr) {
152 fs::File file = _openWithHeader(fs, path);
153 if (!file)
return false;
156 snprintf(line,
sizeof(line),
"%02X:%02X:%02X:%02X:%02X:%02X,\"%s\",%s,%s,%d,%d,%.6f,%.6f,%.1f,%.1f,WIFI",
158 rec.
ssid, _authStr(rec.
enc), timestamp ? timestamp :
"1970-01-01 00:00:00",
181 float lat,
float lon,
float alt = 0.0,
float acc = 10.0,
182 const char* timestamp =
nullptr) {
183 fs::File file = _openWithHeader(fs, path);
184 if (!file)
return false;
187 snprintf(line,
sizeof(line),
"%02X:%02X:%02X:%02X:%02X:%02X,\"%s\",%s,%s,%d,%d,%.6f,%.6f,%.1f,%.1f,WIFI",
189 ap.
ssid, _authStr(ap.
enc), timestamp ? timestamp :
"1970-01-01 00:00:00",
199 static const char* _authStr(uint8_t enc) {
201 case 1:
return "[WEP][ESS]";
202 case 2:
return "[WPA-PSK-TKIP][ESS]";
203 case 3:
return "[WPA2-PSK-CCMP][ESS]";
204 case 4:
return "[WPA2-EAP-CCMP][ESS]";
205 default:
return "[ESS]";
209 static fs::File _openWithHeader(fs::FS &fs,
const char* path) {
210 bool isNew = !fs.exists(path);
212 fs::File check = fs.open(path, FILE_READ);
213 if (check) { isNew = (check.size() == 0); check.close(); }
215 fs::File file = fs.open(path, FILE_APPEND);
216 if (!file)
return file;
218 file.println(
"WigleWifi-1.4,appRelease=1.0,model=Politician,release=1.0,device=ESP32,display=1.0,board=ESP32,brand=Espressif");
219 file.println(
"MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type");
232 bool isNew = !fs.exists(path);
234 fs::File file = fs.open(path, FILE_APPEND);
235 if (!file)
return false;
238 file.println(
"Enterprise BSSID,Client MAC,Plaintext Identity,Channel,RSSI");
242 snprintf(line,
sizeof(line),
"%02X:%02X:%02X:%02X:%02X:%02X,%02X:%02X:%02X:%02X:%02X:%02X,\"%s\",%d,%d",
262 static const int MAX_STORED = 128;
263 uint8_t _cache[MAX_STORED][6];
269 Serial.println(
"[NvsBssidCache] WARNING: namespace name exceeds 15 chars and will be truncated");
270 strncpy(_ns, ns,
sizeof(_ns) - 1);
271 _ns[
sizeof(_ns) - 1] =
'\0';
272 memset(_cache, 0,
sizeof(_cache));
279 _prefs.begin(_ns,
false);
280 size_t bytes = _prefs.getBytes(
"bssids", _cache,
sizeof(_cache));
282 if (_count > MAX_STORED) _count = MAX_STORED;
290 for (
size_t i = 0; i < _count; i++) {
291 engine.markCaptured(_cache[i]);
300 bool add(
const uint8_t* bssid) {
301 for (
size_t i = 0; i < _count; i++) {
302 if (memcmp(_cache[i], bssid, 6) == 0)
return false;
304 if (_count >= MAX_STORED)
return false;
306 memcpy(_cache[_count], bssid, 6);
310 _prefs.putBytes(
"bssids", _cache, _count * 6);
317 size_t count()
const {
return _count; }
324 _prefs.remove(
"bssids");
The core WiFi handshake capturing engine.
Helper for logging harvested 802.1X Enterprise Credentials.
static bool append(fs::FS &fs, const char *path, const EapIdentityRecord &rec)
Helper for writing HandshakeRecords to an HC22000 text file.
static bool append(fs::FS &fs, const char *path, const HandshakeRecord &rec)
Appends a HandshakeRecord to a file as an HC22000 string.
Helper for persistently storing captured BSSIDs in NVS memory.
NvsBssidCache(const char *ns="wardrive")
bool add(const uint8_t *bssid)
Adds a newly captured BSSID to the cache and saves it to NVS.
size_t count() const
Returns the number of BSSIDs currently stored.
void loadInto(Politician &engine)
Feeds the loaded BSSIDs into the Politician engine so it knows to ignore them.
void begin()
Initializes the NVS memory and loads the cached BSSIDs into RAM.
void clear()
Clears the entire cache from NVS.
Helper for writing HandshakeRecords to a standard PCAPNG file.
static bool appendPacket(fs::FS &fs, const char *path, const uint8_t *payload, uint16_t len, int8_t rssi, uint8_t channel, uint32_t ts_usec)
Appends a raw 802.11 sniffer frame to a PCAPNG file (used for intel gathering).
static bool append(fs::FS &fs, const char *path, const HandshakeRecord &rec)
Appends a HandshakeRecord to a file as PCAPNG.
Helper for writing precise GPS location coordinates to a Wigle.net compatible CSV file.
static bool append(fs::FS &fs, const char *path, const HandshakeRecord &rec, float lat, float lon, float alt=0.0, float acc=10.0, const char *timestamp=nullptr)
Appends a HandshakeRecord's details alongside GPS coordinates to a Wigle CSV.
static bool appendAp(fs::FS &fs, const char *path, const ApRecord &ap, float lat, float lon, float alt=0.0, float acc=10.0, const char *timestamp=nullptr)
Appends any discovered ApRecord alongside GPS coordinates to a Wigle CSV.
Snapshot of a discovered Access Point from the internal cache.
A harvested 802.1X Enterprise plaintext identity, delivered to the IdentityCb callback.
A captured handshake or PMKID record delivered to the EapolCb callback.