168 lines
4.8 KiB
C++
168 lines
4.8 KiB
C++
#include "external/mtr/mtr.h"
|
|
#include "external/mtr/line_info.h"
|
|
#include "external/mtr/station_info.h"
|
|
#include "external/mtr/arrival.h"
|
|
#include "assets/MTR_LINE_STATION.h"
|
|
#include "network/network.h"
|
|
#include "network/http_handler.h"
|
|
#include "cJSON.h"
|
|
#include "esp_log.h"
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
static const char* TAG = "MTRNextTrainHandler";
|
|
|
|
// MTR Next Train API endpoint
|
|
// Note: This is a placeholder - replace with actual MTR API endpoint
|
|
static const char* MTR_API_BASE = "https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php";
|
|
|
|
MTRNextTrainHandler::MTRNextTrainHandler() {
|
|
ESP_LOGI(TAG, "Initializing MTR Next Train Handler");
|
|
mtr_data = cJSON_Parse(MTR_LINE_STATION_JSON);
|
|
if (!mtr_data) {
|
|
ESP_LOGE(TAG, "Failed to parse MTR line station JSON");
|
|
} else {
|
|
ESP_LOGI(TAG, "Successfully parsed MTR line station JSON");
|
|
}
|
|
}
|
|
|
|
MTRNextTrainHandler::~MTRNextTrainHandler() {
|
|
if (mtr_data) {
|
|
cJSON_Delete(mtr_data);
|
|
mtr_data = nullptr;
|
|
}
|
|
ESP_LOGI(TAG, "MTR Next Train Handler destroyed");
|
|
}
|
|
|
|
std::vector<LineInfo> MTRNextTrainHandler::get_lines() {
|
|
std::vector<LineInfo> lines;
|
|
|
|
if (!mtr_data) {
|
|
ESP_LOGE(TAG, "MTR data not initialized");
|
|
return lines;
|
|
}
|
|
|
|
// Iterate through all line objects in the JSON
|
|
cJSON* line_json = mtr_data->child;
|
|
while (line_json) {
|
|
if (cJSON_IsObject(line_json)) {
|
|
lines.push_back(LineInfo(line_json));
|
|
}
|
|
line_json = line_json->next;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Retrieved %zu MTR lines", lines.size());
|
|
return lines;
|
|
}
|
|
|
|
MtrArrivalErrorCode MTRNextTrainHandler::get_next_arrival_info(
|
|
NetworkHandler* network_handler,
|
|
std::string& line_code,
|
|
std::string& station_code,
|
|
StationArrivalInfo*& out_info,
|
|
Language lang
|
|
) {
|
|
if (!network_handler) {
|
|
ESP_LOGE(TAG, "NetworkHandler is null");
|
|
return MtrArrivalErrorCode::UNKNOWN;
|
|
}
|
|
|
|
if (!mtr_data) {
|
|
ESP_LOGE(TAG, "MTR data not initialized");
|
|
return MtrArrivalErrorCode::UNKNOWN;
|
|
}
|
|
|
|
// Verify line exists
|
|
cJSON* line_json = cJSON_GetObjectItem(mtr_data, line_code.c_str());
|
|
if (!line_json) {
|
|
ESP_LOGW(TAG, "Line not found: %s", line_code.c_str());
|
|
return MtrArrivalErrorCode::LINE_NOT_FOUND;
|
|
}
|
|
|
|
// Verify station exists in line
|
|
bool station_found = false;
|
|
cJSON* stations_json = cJSON_GetObjectItem(line_json, "stations");
|
|
if (stations_json && cJSON_IsArray(stations_json)) {
|
|
int station_count = cJSON_GetArraySize(stations_json);
|
|
for (int i = 0; i < station_count; i++) {
|
|
cJSON* station = cJSON_GetArrayItem(stations_json, i);
|
|
cJSON* code_json = cJSON_GetObjectItem(station, "code");
|
|
if (code_json && cJSON_IsString(code_json)) {
|
|
if (station_code == code_json->valuestring) {
|
|
station_found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!station_found) {
|
|
ESP_LOGW(TAG, "Station not found: %s in line %s", station_code.c_str(), line_code.c_str());
|
|
return MtrArrivalErrorCode::STATION_NOT_FOUND;
|
|
}
|
|
|
|
// Build API URL
|
|
std::ostringstream url;
|
|
url << MTR_API_BASE << "?line=" << line_code << "&sta=" << station_code;
|
|
if (lang == Language::EN) {
|
|
url << "&lang=en";
|
|
}
|
|
|
|
std::string url_str = url.str();
|
|
ESP_LOGI(TAG, "Fetching arrival info from: %s", url_str.c_str());
|
|
|
|
// Create HTTP client configuration
|
|
esp_http_client_config_t http_config = {};
|
|
http_config.url = url_str.c_str();
|
|
http_config.timeout_ms = 10000;
|
|
http_config.transport_type = HTTP_TRANSPORT_OVER_SSL;
|
|
http_config.use_global_ca_store = true;
|
|
http_config.skip_cert_common_name_check = false;
|
|
|
|
// Get HTTP handler and perform request
|
|
auto http_handler = network_handler->get_http_handler(std::move(http_config));
|
|
if (!http_handler) {
|
|
ESP_LOGE(TAG, "Failed to create HTTP handler");
|
|
return MtrArrivalErrorCode::UNKNOWN;
|
|
}
|
|
|
|
esp_err_t err = http_handler->perform_request();
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
|
|
return MtrArrivalErrorCode::NO_ARRIVAL_INFO;
|
|
}
|
|
|
|
// Get response body
|
|
char* buffer = nullptr;
|
|
int total_len = 0;
|
|
http_handler->get_body(buffer, total_len);
|
|
|
|
if (!buffer || total_len <= 0) {
|
|
ESP_LOGE(TAG, "Empty response from MTR API");
|
|
if (buffer) {
|
|
free(buffer);
|
|
}
|
|
return MtrArrivalErrorCode::NO_ARRIVAL_INFO;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Received %d bytes from MTR API", total_len);
|
|
ESP_LOGD(TAG, "Response: %s", buffer);
|
|
|
|
// Parse JSON response
|
|
cJSON* arrival_json = cJSON_Parse(buffer);
|
|
free(buffer);
|
|
|
|
if (!arrival_json) {
|
|
ESP_LOGE(TAG, "Failed to parse MTR API response");
|
|
return MtrArrivalErrorCode::NO_ARRIVAL_INFO;
|
|
}
|
|
|
|
// Create StationArrivalInfo object
|
|
out_info = new StationArrivalInfo(mtr_data, arrival_json, line_code, station_code);
|
|
|
|
cJSON_Delete(arrival_json);
|
|
|
|
ESP_LOGI(TAG, "Successfully retrieved arrival info for %s/%s", line_code.c_str(), station_code.c_str());
|
|
return MtrArrivalErrorCode::NONE;
|
|
}
|