131 lines
3.3 KiB
C++
131 lines
3.3 KiB
C++
#include "adsb_client.h"
|
|
#include <WiFiClientSecure.h>
|
|
#include <HTTPClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include <time.h>
|
|
|
|
namespace AdsbClient {
|
|
|
|
namespace {
|
|
const char* kNoValidate = nullptr;
|
|
|
|
WiFiClientSecure persistentClient;
|
|
bool clientConfigured = false;
|
|
}
|
|
|
|
void primeTime() {
|
|
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
|
|
time_t now = time(nullptr);
|
|
uint32_t start = millis();
|
|
while (now < 8 * 3600 * 2 && millis() - start < 5000) {
|
|
delay(100);
|
|
now = time(nullptr);
|
|
}
|
|
}
|
|
|
|
FetchResult fetch(double homeLat, double homeLon, float radiusKm,
|
|
Aircraft* table, uint8_t tableCapacity) {
|
|
FetchResult result;
|
|
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
return result;
|
|
}
|
|
|
|
if (!clientConfigured) {
|
|
persistentClient.setInsecure();
|
|
persistentClient.setTimeout(Config::HTTP_TIMEOUT_MS);
|
|
clientConfigured = true;
|
|
}
|
|
|
|
HTTPClient http;
|
|
char url[160];
|
|
snprintf(url, sizeof(url),
|
|
"https://%s/api/v3/lat/%.5f/lon/%.5f/dist/%.0f",
|
|
Config::ADSB_API_HOST, homeLat, homeLon, radiusKm);
|
|
|
|
http.setTimeout(Config::HTTP_TIMEOUT_MS);
|
|
if (!http.begin(persistentClient, url)) {
|
|
return result;
|
|
}
|
|
http.setReuse(true);
|
|
|
|
int code = http.GET();
|
|
result.httpCode = code;
|
|
|
|
if (code != HTTP_CODE_OK) {
|
|
http.end();
|
|
return result;
|
|
}
|
|
JsonDocument filter;
|
|
JsonObject filterAc = filter["ac"].add<JsonObject>();
|
|
filterAc["hex"] = true;
|
|
filterAc["flight"] = true;
|
|
filterAc["r"] = true;
|
|
filterAc["t"] = true;
|
|
filterAc["lat"] = true;
|
|
filterAc["lon"] = true;
|
|
filterAc["alt_baro"] = true;
|
|
filterAc["baro_rate"]= true;
|
|
filterAc["gs"] = true;
|
|
filterAc["track"] = true;
|
|
filterAc["squawk"] = true;
|
|
|
|
JsonDocument doc;
|
|
DeserializationError err = deserializeJson(
|
|
doc, http.getStream(), DeserializationOption::Filter(filter));
|
|
|
|
http.end();
|
|
|
|
if (err) {
|
|
result.ok = false;
|
|
return result;
|
|
}
|
|
|
|
JsonArray acArray = doc["ac"].as<JsonArray>();
|
|
uint8_t idx = 0;
|
|
for (JsonObject ac : acArray) {
|
|
if (idx >= tableCapacity) break;
|
|
|
|
Aircraft& a = table[idx];
|
|
a = Aircraft{};
|
|
|
|
const char* hex = ac["hex"] | "";
|
|
strncpy(a.hex, hex, sizeof(a.hex) - 1);
|
|
|
|
const char* flight = ac["flight"] | "";
|
|
strncpy(a.callsign, flight, sizeof(a.callsign) - 1);
|
|
|
|
const char* reg = ac["r"] | "";
|
|
strncpy(a.reg, reg, sizeof(a.reg) - 1);
|
|
|
|
const char* type = ac["t"] | "";
|
|
strncpy(a.typeCode, type, sizeof(a.typeCode) - 1);
|
|
|
|
a.lat = ac["lat"] | 0.0f;
|
|
a.lon = ac["lon"] | 0.0f;
|
|
|
|
if (ac["alt_baro"].is<const char*>()) {
|
|
a.altBaroFt = 0;
|
|
} else {
|
|
a.altBaroFt = ac["alt_baro"] | 0;
|
|
}
|
|
|
|
a.vertRateFtMin = ac["baro_rate"] | 0;
|
|
a.groundSpeedKt = ac["gs"] | 0.0f;
|
|
a.headingDeg = ac["track"] | 0.0f;
|
|
|
|
const char* squawk = ac["squawk"] | "";
|
|
strncpy(a.squawk, squawk, sizeof(a.squawk) - 1);
|
|
|
|
a.lastSeenMs = millis();
|
|
a.valid = (a.lat != 0.0f || a.lon != 0.0f);
|
|
|
|
if (a.valid) idx++;
|
|
}
|
|
|
|
result.ok = true;
|
|
result.aircraftCount = idx;
|
|
return result;
|
|
}
|
|
|
|
} |