#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <Arduino.h>
#include <ArduinoJson.h>
// WiFi Configuration
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// TransportAPI Credentials (Get yours at developer.transportapi.com)
const char* appId = "70b87b9d";
const char* appKey = "2ff56b85a460a25208d8333ee48b10fa";
// Station Code (CRS code. e.g., "BTH" for Bath Spa, "VIC" for London Victoria)
const String station_crs = "BTH";
// API Endpoint URL
//String url = "https://transportapi.com" + station_crs + "/live.json" +
// "?app_id=" + app_id + "&app_key=" + app_key + "&train_status=passenger";
String url = "https://transportapi.com/v3/uk/bus/stop_timetables/6280326150.json?app_id=" + String(appId) + "&app_key=" + String(appKey);
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi!");
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
// TransportAPI uses HTTPS. For testing, we bypass strict SSL fingerprint checks:
client.setInsecure();
HTTPClient http;
Serial.println("Fetching data from TransportAPI...");
if (http.begin(client, url)) {
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
// Stream the response directly to the JSON parser to save RAM
WiFiClient* stream = http.getStreamPtr();
// 2. Build the structural Filter Document
JsonDocument filter;
// Use "[0]" to instruct the filter to apply this schema across ALL arrays inside departures
filter["departures"]["all"][0]["line"] = true;
filter["departures"]["all*"][0]["best_departure_estimate"] = true;
filter["departures"]["all*"][0]["direction"] = true;
// 3. Parse the data applying our filtering constraints
JsonDocument doc;
DeserializationError error = deserializeJson(doc, *stream, DeserializationOption::Filter(filter));
if (error) {
Serial.print(F("Filtered Parsing failed: "));
Serial.println(error.f_str());
return;
// 4. Extract data safely from the slimmed memory block
JsonObject departures = doc["departures"];
Serial.println("line");
//for (JsonPair kv : departures) {
for (JsonPair kv : departures) {
JsonArray services = kv.value().as<JsonArray>();
for (JsonObject bus : services) {
// Safely read the filtered keys (operator, source, etc., are completely purged)
const char* line_name = bus["line"];
const char* expected_time = bus["best_departure_estimate"] ;
const char* direction = bus["direction"] ;
Serial.print("Line: ");
Serial.print(line_name);
Serial.print(" | Expected: ");
Serial.print(expected_time);
Serial.print(" | Target Direction: ");
Serial.println(direction);
Serial.println("Webby1");
} }
} else {
Serial.print("JSON Deserialization failed: ");
Serial.println(error.c_str());
Serial.print(F("Failed with Code: "));
Serial.println(error.code());
Serial.println("Webby2");
}
} else {
Serial.printf("HTTP GET failed, error code: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
}
// Poll the API once every 60 seconds (do not spam the free tier)
delay(60000);
}