常规更新

This commit is contained in:
2026-07-14 16:26:51 +08:00
parent 4697b2028a
commit 4fd18631d3
7 changed files with 1300 additions and 1453 deletions
+210 -210
View File
@@ -38,25 +38,25 @@
"function_name": "adsb_read" "function_name": "adsb_read"
}, },
"web_server": { "web_server": {
"webapp": "D:/ae/proj/projects/ECAP_Server/ver/v1.0.4/wwwroot", "webapp": "@/../third_party/eacp_webapp/wwwroot",
"tiles": "D:/tiles" "tiles": "D:/tiles"
}, },
"device": { "device": {
"net": [ "net": [
{ {
"key": "device", "key": "device",
"ip": "192.168.1.75", "ip": "192.168.1.75",
"port": 80, "port": 80,
"netmask": "255.255.255.0", "netmask": "255.255.255.0",
"gateway": "192.168.1.1" "gateway": "192.168.1.1"
}, },
{ {
"key": "wifi", "key": "wifi",
"ip": "192.168.10.193", "ip": "192.168.10.193",
"port": 80, "port": 80,
"netmask": "255.255.255.0", "netmask": "255.255.255.0",
"gateway": "192.168.10.1" "gateway": "192.168.10.1"
} }
] ]
}, },
"mode_acs": { "mode_acs": {
@@ -78,131 +78,131 @@
"tcp_server_default_connect_user_buffer_size": 409600, "tcp_server_default_connect_user_buffer_size": 409600,
"tcp_server_default_connect_system_buffer_size": 409600, "tcp_server_default_connect_system_buffer_size": 409600,
"list": [ "list": [
{ {
"type": "Data_Feed_TCP_Server", "type": "Data_Feed_TCP_Server",
"key": "Port_10003", "key": "Port_10003",
"enable": true, "enable": true,
"output_format": { "output_format": {
"type": "BIN", "type": "BIN",
"use_status": true, "use_status": true,
"mode_s_output_type": "ALL_Mode_S", "mode_s_output_type": "ALL_Mode_S",
"use_mode_ac": true, "use_mode_ac": true,
"sbs_only_pos": true "sbs_only_pos": true
}, },
"port": 10003, "port": 10003,
"connect_user_buffer_size": 409600, "connect_user_buffer_size": 409600,
"connect_system_buffer_size": 409600 "connect_system_buffer_size": 409600
}, },
{ {
"type": "Data_Feed_UDP_Server", "type": "Data_Feed_UDP_Server",
"key": "22333", "key": "22333",
"enable": false, "enable": false,
"output_format": { "output_format": {
"type": "BIN", "type": "BIN",
"use_status": false, "use_status": false,
"mode_s_output_type": "ALL_Mode_S", "mode_s_output_type": "ALL_Mode_S",
"use_mode_ac": false, "use_mode_ac": false,
"sbs_only_pos": false "sbs_only_pos": false
}, },
"port": 50001 "port": 50001
}, },
{ {
"type": "Data_Feed_UDP_Client", "type": "Data_Feed_UDP_Client",
"key": "Port_10004", "key": "Port_10004",
"enable": false, "enable": false,
"output_format": { "output_format": {
"type": "AVR", "type": "AVR",
"use_status": false, "use_status": false,
"mode_s_output_type": "DF_11_17_18", "mode_s_output_type": "DF_11_17_18",
"use_mode_ac": false, "use_mode_ac": false,
"sbs_only_pos": true "sbs_only_pos": true
}, },
"port": 30004, "port": 30004,
"url": "192.168.1.75" "url": "192.168.1.75"
}, },
{ {
"type": "Data_Feed_TCP_Client", "type": "Data_Feed_TCP_Client",
"key": "Port_10005", "key": "Port_10005",
"enable": false, "enable": false,
"output_format": { "output_format": {
"type": "BIN", "type": "BIN",
"use_status": true, "use_status": true,
"mode_s_output_type": "NO_POS_Mode_S", "mode_s_output_type": "NO_POS_Mode_S",
"use_mode_ac": true, "use_mode_ac": true,
"sbs_only_pos": true "sbs_only_pos": true
}, },
"url": "192.168.1.167", "url": "192.168.1.167",
"port": 10005 "port": 10005
}, },
{ {
"type": "Data_Feed_TCP_Server", "type": "Data_Feed_TCP_Server",
"key": "Port_30003", "key": "Port_30003",
"enable": false, "enable": false,
"output_format": { "output_format": {
"type": "SBS", "type": "SBS",
"use_status": false, "use_status": false,
"mode_s_output_type": "ALL_Mode_S", "mode_s_output_type": "ALL_Mode_S",
"use_mode_ac": true, "use_mode_ac": true,
"sbs_only_pos": true "sbs_only_pos": true
}, },
"port": 30003, "port": 30003,
"connect_user_buffer_size": 0, "connect_user_buffer_size": 0,
"connect_system_buffer_size": 0 "connect_system_buffer_size": 0
} }
] ]
}, },
"data_source": { "data_source": {
"list": [ "list": [
{ {
"type": "Dll_Data_Source", "type": "Dll_Data_Source",
"key": "lzy_dll", "key": "lzy_dll",
"enable": true, "enable": true,
"base_station_show": true, "base_station_show": true,
"aircraft_show": true, "aircraft_show": true,
"color": "#454641", "color": "#454641",
"aircraft_pixel_size": 28, "aircraft_pixel_size": 28,
"lat": 37.433547, "lat": 37.433547,
"lon": 121.408730, "lon": 121.408730,
"alt": 23.000000, "alt": 23.000000,
"update_form_gps": true, "update_form_gps": true,
"show_icao": true, "show_icao": true,
"show_call_sign": false, "show_call_sign": false,
"show_fly_status": false, "show_fly_status": false,
"keep_mode": true, "keep_mode": true,
"library_path": "@/dll_source.dll", "library_path": "@/dll_source.dll",
"function_name": "adsb_read", "function_name": "adsb_read",
"data_type": "BIN_Blank_Text", "data_type": "BIN_Blank_Text",
"buffer_size": 200000 "buffer_size": 200000
}, },
{ {
"type": "File_Data_Source", "type": "File_Data_Source",
"key": "aaaa", "key": "aaaa",
"enable": false, "enable": false,
"base_station_show": true, "base_station_show": true,
"aircraft_show": true, "aircraft_show": true,
"color": "#d1a54c", "color": "#d1a54c",
"aircraft_pixel_size": 20, "aircraft_pixel_size": 20,
"lat": 37.000000, "lat": 37.000000,
"lon": 121.000000, "lon": 121.000000,
"alt": 0.000000, "alt": 0.000000,
"update_form_gps": false, "update_form_gps": false,
"show_icao": true, "show_icao": true,
"show_call_sign": true, "show_call_sign": true,
"show_fly_status": true, "show_fly_status": true,
"keep_mode": true, "keep_mode": true,
"file_path": "D:\\ae\\proj\\projects\\ECAP_Server\\data\\BIN_Blank_Text\\ADS-B_195_0205.txt", "file_path": "D:\\ae\\proj\\projects\\ECAP_Server\\data\\BIN_Blank_Text\\ADS-B_195_0205.txt",
"data_type": "BIN_Blank_Text", "data_type": "BIN_Blank_Text",
"play_mode": "loop" "play_mode": "loop"
} }
] ]
}, },
"source_feed_relation": { "source_feed_relation": {
"list": [ "list": [
{ {
"key": "key_10003", "key": "key_10003",
"enable": true, "enable": true,
"type": "First_Source_To_All_Feed_Relation" "type": "First_Source_To_All_Feed_Relation"
} }
] ]
} }
}, },
@@ -218,85 +218,85 @@
"mlat_server": true "mlat_server": true
}, },
"external_database": { "external_database": {
"ecap_sqlite_path": "D:/ae/proj/projects/ECAP_Server/sqlite/ecap.sqlite", "ecap_sqlite_path": "@/../data/sqlite/ecap.sqlite",
"list": [ "list": [
{ {
"name": "tar1090_db_aircraft", "name": "tar1090_db_aircraft",
"download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz", "download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz",
"description": "wiedehopf/tar1090-db 发布的轻量 ICAO24 飞机静态库,提供注册号、机型、年份和运营方备注。", "description": "wiedehopf/tar1090-db 发布的轻量 ICAO24 飞机静态库,提供注册号、机型、年份和运营方备注。",
"update_interval_seconds": 604800, "update_interval_seconds": 604800,
"last_updated_at": 1780388281 "last_updated_at": 1780388281
}, },
{ {
"name": "wiedehopf_tar1090_db_aircraft", "name": "wiedehopf_tar1090_db_aircraft",
"download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz", "download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz",
"description": "wiedehopf/tar1090-db 项目发布的飞机静态数据库镜像,供 tar1090 本地识别飞机。", "description": "wiedehopf/tar1090-db 项目发布的飞机静态数据库镜像,供 tar1090 本地识别飞机。",
"update_interval_seconds": 604800, "update_interval_seconds": 604800,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "mictronics_aircraft_database", "name": "mictronics_aircraft_database",
"download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz", "download_url": "https://raw.githubusercontent.com/wiedehopf/tar1090-db/refs/heads/csv/aircraft.csv.gz",
"description": "Mictronics 社区飞机数据库的 tar1090 汇总镜像,可按 ICAO24 查询注册号、机型和运营方。", "description": "Mictronics 社区飞机数据库的 tar1090 汇总镜像,可按 ICAO24 查询注册号、机型和运营方。",
"update_interval_seconds": 604800, "update_interval_seconds": 604800,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "opensky_aircraft_database", "name": "opensky_aircraft_database",
"download_url": "https://opensky-network.org/datasets/metadata/aircraftDatabase.csv", "download_url": "https://opensky-network.org/datasets/metadata/aircraftDatabase.csv",
"description": "OpenSky Network 飞机元数据 CSV,包含制造商、型号、注册号和运营方等字段。", "description": "OpenSky Network 飞机元数据 CSV,包含制造商、型号、注册号和运营方等字段。",
"update_interval_seconds": 604800, "update_interval_seconds": 604800,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "faa_aircraft_registry", "name": "faa_aircraft_registry",
"download_url": "https://registry.faa.gov/database/ReleasableAircraft.zip", "download_url": "https://registry.faa.gov/database/ReleasableAircraft.zip",
"description": "FAA 官方可公开下载的美国飞机注册库,MASTER.txt 包含 Mode-S Hex 注册信息。", "description": "FAA 官方可公开下载的美国飞机注册库,MASTER.txt 包含 Mode-S Hex 注册信息。",
"update_interval_seconds": 86400, "update_interval_seconds": 86400,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "icao_doc_8643_aircraft_type_designators", "name": "icao_doc_8643_aircraft_type_designators",
"download_url": "", "download_url": "",
"description": "ICAO Doc 8643 机型代码表,用于将 A320、B738 等 designator 映射为制造商、型号和类别。", "description": "ICAO Doc 8643 机型代码表,用于将 A320、B738 等 designator 映射为制造商、型号和类别。",
"update_interval_seconds": 2419200, "update_interval_seconds": 2419200,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "vrs_routes", "name": "vrs_routes",
"download_url": "https://vrs-standing-data.adsb.lol/routes.csv", "download_url": "https://vrs-standing-data.adsb.lol/routes.csv",
"description": "VRS 航线表,以 callsign 查询机场代码序列,用于推断起飞机场、经停机场和目的机场。", "description": "VRS 航线表,以 callsign 查询机场代码序列,用于推断起飞机场、经停机场和目的机场。",
"update_interval_seconds": 3600, "update_interval_seconds": 3600,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "vrs_airports", "name": "vrs_airports",
"download_url": "https://vrs-standing-data.adsb.lol/airports.csv", "download_url": "https://vrs-standing-data.adsb.lol/airports.csv",
"description": "VRS 机场字典,提供机场代码、名称、国家、经纬度和高度。", "description": "VRS 机场字典,提供机场代码、名称、国家、经纬度和高度。",
"update_interval_seconds": 3600, "update_interval_seconds": 3600,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "adsblol_vrs_standing_data_routes", "name": "adsblol_vrs_standing_data_routes",
"download_url": "https://vrs-standing-data.adsb.lol/routes.csv", "download_url": "https://vrs-standing-data.adsb.lol/routes.csv",
"description": "ADSB.lol 发布的 VRS standing-data 航线镜像,以 callsign 查询机场代码序列。", "description": "ADSB.lol 发布的 VRS standing-data 航线镜像,以 callsign 查询机场代码序列。",
"update_interval_seconds": 3600, "update_interval_seconds": 3600,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "vradarserver_standing_data_routes", "name": "vradarserver_standing_data_routes",
"download_url": "https://vrs-standing-data.adsb.lol/routes.csv", "download_url": "https://vrs-standing-data.adsb.lol/routes.csv",
"description": "Virtual Radar Server standing-data 的航线适配表;当前在线更新使用 ADSB.lol 公共镜像。", "description": "Virtual Radar Server standing-data 的航线适配表;当前在线更新使用 ADSB.lol 公共镜像。",
"update_interval_seconds": 3600, "update_interval_seconds": 3600,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
}, },
{ {
"name": "opensky_flightdata_api_cache", "name": "opensky_flightdata_api_cache",
"download_url": "", "download_url": "",
"description": "OpenSky FlightData API 查询缓存,按 ICAO24 和时间范围保存历史航班起降机场结果。", "description": "OpenSky FlightData API 查询缓存,按 ICAO24 和时间范围保存历史航班起降机场结果。",
"update_interval_seconds": 0, "update_interval_seconds": 0,
"last_updated_at": 1780381804 "last_updated_at": 1780381804
} }
] ]
} }
} }
File diff suppressed because it is too large Load Diff
+418 -333
View File
@@ -5,377 +5,462 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <string_view> #include <string_view>
BaseLogger* server_logger = nullptr;
BaseLogger *server_logger = nullptr;
Debug_Logger_Info_Manager debug_logger_info_manager; Debug_Logger_Info_Manager debug_logger_info_manager;
void Global::handle_old_logs() { void Global::handle_old_logs() {
auto mode = log_config.open_mode; auto mode = log_config.open_mode;
std::string dirPath = get_exe_dir() + "/" + "logs"; std::string dirPath = get_exe_dir() + "/" + "logs";
namespace fs = std::filesystem; namespace fs = std::filesystem;
try { try {
switch (mode) { switch (mode) {
case Log_Config::Open_Mode::Rename: { case Log_Config::Open_Mode::Rename: {
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now); auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::ostringstream oss; std::ostringstream oss;
oss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d_%H-%M-%S"); oss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d_%H-%M-%S");
fs::path newDirPath = dirPath + "_" + oss.str(); fs::path newDirPath = dirPath + "_" + oss.str();
if (fs::exists(newDirPath)) { if (fs::exists(newDirPath)) {
std::cout << "New directory name already exists!" << std::endl; std::cout << "New directory name already exists!" << std::endl;
return; return;
} }
fs::rename(dirPath, newDirPath); fs::rename(dirPath, newDirPath);
std::cout << "Directory renamed to: " << newDirPath << std::endl; std::cout << "Directory renamed to: " << newDirPath << std::endl;
break; break;
}
case Log_Config::Open_Mode::Delete: {
if (fs::exists(dirPath)) {
fs::remove_all(dirPath); // 删除目录及其所有内容
std::cout << "Directory and its contents deleted: " << dirPath
<< std::endl;
}
if (fs::create_directories(dirPath)) {
std::cout << "Directory created: " << dirPath << std::endl;
} else {
std::cout << "创建目录失败: " << dirPath << std::endl;
Psc::fail_fast();
}
fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all |
fs::perms::others_all);
break;
}
case Log_Config::Open_Mode::Append:
break;
default:
std::cerr << "未知的打开模式!" << std::endl;
break;
}
} catch (const std::exception &ex) {
std::cerr << "Error: " + Psc::platform_2_utf8(ex.what()) + "\n";
}
}
Global::Global() {
auto j = load();
log_config.from_base_json(j.get("log"));
handle_old_logs();
Base_Logger_Manager::instance()
->set_thread_num(1)
.set_flush_seconds(3)
.init();
int piece_num = log_config.piece_num;
int size_MB = log_config.size_MB;
int MB = 1024 * 1024;
asio_socket::socket_logger =
new BaseLogger("@/logs/socket", MB * size_MB, piece_num);
serial::serial_logger =
new BaseLogger("@/logs/serial", MB * size_MB, piece_num);
SSR::mode_s_logger =
new BaseLogger("@/logs/mode_s", MB * size_MB * 10, piece_num);
dsp_logger = new BaseLogger("@/logs/dsp", MB * size_MB, piece_num);
// libais::libais_logger = new BaseLogger("@/logs/libais", MB * size_MB,
// piece_num);
server_logger = new BaseLogger("@/logs/server", MB * size_MB, piece_num);
asio_socket::socket_logger->set_redirect(
[](const BaseLogger::Log_Info &log_info) {
auto msg = "[" + std::string("func") + "~" + log_info.func_pattern +
"] " + log_info.log_type.to_string() + log_info.content;
debug_logger_info_manager.push_info(msg);
});
serial::serial_logger->set_redirect([](const BaseLogger::Log_Info &log_info) {
auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " +
log_info.log_type.to_string() + log_info.content;
debug_logger_info_manager.push_info(msg);
});
fromJson(&j);
#ifdef Cache_Some_Mode_S
auto old_parse_ok_json = SSR::parse_ok_json;
SSR::parse_ok_json = [old_parse_ok_json](Aircraft_Info *aircraft_info,
SSR::P_S mode_s_msg,
Psc::JSON json) {
old_parse_ok_json(aircraft_info, mode_s_msg, json);
auto f = static_cast<Aircraft *>(aircraft_info);
f->add_msg_limit(mode_s_msg);
};
#endif
SSR::cpr_cb = [](SSR::CPR_Error_Type t, std::string_view log,
SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
Mode_S_Statistic_Data *ss = &src->mode_s_statistic;
if (t != SSR::CPR_Error_Type::Normal) {
ss->add_cpr_error(t);
}
SSR::mode_s_logger->debug("CPR/" + to_string(t), {}, log);
};
// 处理错误
SSR::parse_call_back =
[this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info *info,
std::string_view field_name, std::vector<std::string> bds_list,
void *, SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
Mode_S_Statistic_Data *ss = &src->mode_s_statistic;
if (type == SSR::Parse_Call_Back_Type::Unknown_DF) {
// std::cout << "Unknown DF type!" << (int)(msg->df) << std::endl;
return;
} }
DF_Statistic_Data *dfs = ss->get_create_df_statistic_data(msg->df); case Log_Config::Open_Mode::Delete: {
if (fs::exists(dirPath)) {
fs::remove_all(dirPath); // 删除目录及其所有内容
std::cout << "Directory and its contents deleted: " << dirPath
<< std::endl;
}
if (fs::create_directories(dirPath)) {
std::cout << "Directory created: " << dirPath << std::endl;
}
else {
std::cout << "创建目录失败: " << dirPath << std::endl;
Psc::fail_fast();
}
fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all |
fs::perms::others_all);
break;
}
case Log_Config::Open_Mode::Append:
break;
default:
std::cerr << "未知的打开模式!" << std::endl;
break;
}
}
catch (const std::exception& ex) {
std::cerr << "Error: " + Psc::platform_2_utf8(ex.what()) + "\n";
}
}
Global::Global() {
auto j = load();
log_config.from_base_json(j.get("log"));
handle_old_logs();
Base_Logger_Manager::instance()
->set_thread_num(1)
.set_flush_seconds(3)
.init();
int piece_num = log_config.piece_num;
int size_MB = log_config.size_MB;
int MB = 1024 * 1024;
asio_socket::socket_logger =
new BaseLogger("@/logs/socket", MB * size_MB, piece_num);
serial::serial_logger =
new BaseLogger("@/logs/serial", MB * size_MB, piece_num);
SSR::mode_s_logger =
new BaseLogger("@/logs/mode_s", MB * size_MB * 10, piece_num);
dsp_logger = new BaseLogger("@/logs/dsp", MB * size_MB, piece_num);
// libais::libais_logger = new BaseLogger("@/logs/libais", MB * size_MB,
// piece_num);
server_logger = new BaseLogger("@/logs/server", MB * size_MB, piece_num);
asio_socket::socket_logger->set_redirect(
[](const BaseLogger::Log_Info& log_info) {
auto msg = "[" + std::string("func") + "~" + log_info.func_pattern +
"] " + log_info.log_type.to_string() + log_info.content;
debug_logger_info_manager.push_info(msg);
});
serial::serial_logger->set_redirect([](const BaseLogger::Log_Info& log_info) {
auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " +
log_info.log_type.to_string() + log_info.content;
debug_logger_info_manager.push_info(msg);
});
fromJson(&j);
#ifdef Cache_Some_Mode_S
auto old_parse_ok_json = SSR::parse_ok_json;
SSR::parse_ok_json = [old_parse_ok_json](Aircraft_Info* aircraft_info,
SSR::P_S mode_s_msg,
Psc::JSON json) {
old_parse_ok_json(aircraft_info, mode_s_msg, json);
auto f = static_cast<Aircraft*>(aircraft_info);
f->add_msg_limit(mode_s_msg);
};
#endif
SSR::cpr_cb = [](SSR::CPR_Error_Type t, std::string_view log,
SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
Mode_S_Statistic_Data* ss = &src->mode_s_statistic;
if (t != SSR::CPR_Error_Type::Normal) {
ss->add_cpr_error(t);
}
SSR::mode_s_logger->debug("CPR/" + to_string(t), {}, log);
};
// 处理错误
SSR::parse_call_back =
[this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info* info,
std::string_view field_name, std::vector<std::string> bds_list,
void*, SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
Mode_S_Statistic_Data* ss = &src->mode_s_statistic;
if (type == SSR::Parse_Call_Back_Type::Unknown_DF) {
// std::cout << "Unknown DF type!" << (int)(msg->df) << std::endl;
return;
}
DF_Statistic_Data* dfs = ss->get_create_df_statistic_data(msg->df);
dfs->add(); dfs->add();
if (type == SSR::Parse_Call_Back_Type::Normal_Block) { if (type == SSR::Parse_Call_Back_Type::Normal_Block) {
dfs->add_sub_part(field_name); dfs->add_sub_part(field_name);
info->update(msg); info->update(msg);
} else if (type == SSR::Parse_Call_Back_Type::CRC_Error) { }
dfs->add_crc_error(); else if (type == SSR::Parse_Call_Back_Type::CRC_Error) {
// std::cout << field_name << " :crc_error msg:" << msg->msg_hex << dfs->add_crc_error();
// " df:" << (int)msg->df << std::endl; // std::cout << field_name << " :crc_error msg:" << msg->msg_hex <<
} else if (type == SSR::Parse_Call_Back_Type::Length_Error) { // " df:" << (int)msg->df << std::endl;
ss->add_length_error(field_name); }
// std::cout << field_name << " :length_error msg:" << msg->msg_hex else if (type == SSR::Parse_Call_Back_Type::Length_Error) {
// << " df:" << (int)msg->df << std::endl; ss->add_length_error(field_name);
// std::cout << field_name << " :length_error msg:" << msg->msg_hex
// << " df:" << (int)msg->df << std::endl;
} }
// else if (type == Mode_S::Parse_Call_Back_Type::UNKNOWN_ERROR) {} else // else if (type == Mode_S::Parse_Call_Back_Type::UNKNOWN_ERROR) {} else
// {} // {}
}; };
auto str = toJson().to_json_string(); auto str = toJson().to_json_string();
server_logger->debug("启动", {}, str); server_logger->debug("启动", {}, str);
SSR::mode_s_logger->debug("启动", {}, str); SSR::mode_s_logger->debug("启动", {}, str);
// libais::libais_logger->debug("启动", {}, str); // libais::libais_logger->debug("启动", {}, str);
std::cout << str << std::endl; std::cout << str << std::endl;
// libais::log = normal_log; // libais::log = normal_log;
// libais::log = ais_log; // libais::log = ais_log;
// mode_s_log_info = mode_s_log; // mode_s_log_info = mode_s_log;
init_web_server(); init_web_server();
} }
Global::~Global() { std::cout << "Global::~Global()" << std::endl; } Global::~Global() {
std::cout << "Global::~Global()" << std::endl;
void replace(std::string &originalStr, std::string_view findStr, }
void replace(std::string& originalStr, std::string_view findStr,
std::string_view replaceStr) { std::string_view replaceStr) {
size_t pos = originalStr.find(findStr); size_t pos = originalStr.find(findStr);
while (pos != std::string::npos) { while (pos != std::string::npos) {
originalStr.replace(pos, findStr.length(), replaceStr); originalStr.replace(pos, findStr.length(), replaceStr);
pos = originalStr.find(findStr, pos + replaceStr.length()); pos = originalStr.find(findStr, pos + replaceStr.length());
} }
} }
std::string oneLine(std::string_view str) { std::string oneLine(std::string_view str) {
auto ret = std::string(str); auto ret = std::string(str);
replace(ret, "\n", "[n]"); replace(ret, "\n", "[n]");
return ret; return ret;
} }
bool isHexadecimal(std::string_view str) { bool isHexadecimal(std::string_view str) {
return std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::all_of(str.begin(), str.end(), [](unsigned char c) {
return std::isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); return std::isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}); });
} }
void handle_buffer_muti_start( void handle_buffer_muti_start(
std::string &buffer, std::string_view data, std::string& buffer, std::string_view data,
const std::set<std::string> &prefix_list, const std::set<std::string>& prefix_list,
const std::function<void(std::string &)> &callback) { const std::function<void(std::string&)>& callback) {
if (!data.empty()) { if (!data.empty()) {
buffer += data; buffer += data;
// std::cout << "[data]:" + data + "\n"; // std::cout << "[data]:" + data + "\n";
// std::cout << "[buffer]:" + buffer + "\n"; // std::cout << "[buffer]:" + buffer + "\n";
while (!buffer.empty() && buffer.back() == '\n') { while (!buffer.empty() && buffer.back() == '\n') {
buffer.pop_back(); buffer.pop_back();
} }
while (true) { while (true) {
std::string c; std::string c;
size_t pos = 0, n = buffer.size(); size_t pos = 0, n = buffer.size();
for (; pos < n; pos++) { for (; pos < n; pos++) {
bool find = false; bool find = false;
for (std::string_view prefix : prefix_list) { for (std::string_view prefix : prefix_list) {
if (pos + prefix.size() <= n) { if (pos + prefix.size() <= n) {
if (buffer.substr(pos, prefix.size()) == prefix) { if (buffer.substr(pos, prefix.size()) == prefix) {
c = prefix; c = prefix;
find = true; find = true;
break; break;
} }
} }
}
if (find)
break;
}
if (pos == n)
break;
std::string line = c + buffer.substr(0, pos); // 截取从开头到!之前的数据
buffer = buffer.substr(pos + 1); // 更新buffer为剩余数据
// std::cout << "[line]:" + line + "\n";
if (pos != 0)
callback(line);
} }
if (find)
break;
}
if (pos == n)
break;
std::string line = c + buffer.substr(0, pos); // 截取从开头到!之前的数据
buffer = buffer.substr(pos + 1); // 更新buffer为剩余数据
// std::cout << "[line]:" + line + "\n";
if (pos != 0)
callback(line);
} }
}
} }
void handle_buffer_head_tail( void handle_buffer_head_tail(
std::string &buffer, std::string_view data, std::string_view prefix, std::string& buffer, std::string_view data, std::string_view prefix,
std::string_view suffix, std::string_view suffix,
const std::function<void(std::string &)> &callback) { const std::function<void(std::string&)>& callback) {
// 只在数据可用时进行读取 // 只在数据可用时进行读取
if (!data.empty()) { if (!data.empty()) {
buffer += data; buffer += data;
size_t pos; size_t pos;
while ((pos = buffer.find_first_of(suffix)) != std::string::npos) { while ((pos = buffer.find_first_of(suffix)) != std::string::npos) {
size_t start = buffer.find_first_of(prefix); size_t start = buffer.find_first_of(prefix);
if (start == std::string::npos) if (start == std::string::npos)
break; break;
std::string packet = buffer.substr(start + 1, pos - start - 1); std::string packet = buffer.substr(start + 1, pos - start - 1);
buffer.erase(0, pos + 1); buffer.erase(0, pos + 1);
// 处理尾部空格 // 处理尾部空格
while (!buffer.empty() && buffer.back() == '\n') { while (!buffer.empty() && buffer.back() == '\n') {
buffer.pop_back(); buffer.pop_back();
} }
if (!packet.empty()) { if (!packet.empty()) {
callback(packet); callback(packet);
} }
}
} }
}
} }
void read_ais_serial_data(std::atomic<bool>& running) {
void read_ais_serial_data(std::atomic<bool> &running) { // static int t = config.ais.read_serial_milliseconds;
// static int t = config.ais.read_serial_milliseconds; // static bool ais_log = config.console_config.ais_serial;
// static bool ais_log = config.console_config.ais_serial; // static bool use_ais_serial = !config.ais_mock.enable ||
// static bool use_ais_serial = !config.ais_mock.enable || // config.ais_mock.use_real_serial; static auto lm =
// config.ais_mock.use_real_serial; static auto lm = // Light_Manager::instance(); serial::Serial* ais_serial{}; if
// Light_Manager::instance(); serial::Serial* ais_serial{}; if // (use_ais_serial) ais_serial = create_serial(config.ais.port_name,
// (use_ais_serial) ais_serial = create_serial(config.ais.port_name, // config.ais.baud_rate); libais::VdmStream stream; std::string ais_buffer;
// config.ais.baud_rate); libais::VdmStream stream; std::string ais_buffer; // while (running.load(std::memory_order_acquire) == true)
// while (running.load(std::memory_order_acquire) == true) // {
// { // std::string ais_data = use_ais_serial ? ais_serial->read() :
// std::string ais_data = use_ais_serial ? ais_serial->read() : // mock_ais_serial.read(); if (!ais_data.empty())
// mock_ais_serial.read(); if (!ais_data.empty()) // {
// { // if (ais_log && !ais_data.empty())
// if (ais_log && !ais_data.empty()) // {
// { // std::cout << "read:[ais_serial]:" << ais_data << std::endl;
// std::cout << "read:[ais_serial]:" << ais_data << std::endl; // }
// } // libais::libais_logger->debug("ais_serial_read/ais_serial_read", {},
// libais::libais_logger->debug("ais_serial_read/ais_serial_read", {}, // ais_data + "\n"); handle_buffer_muti_start(ais_buffer, ais_data,
// ais_data + "\n"); handle_buffer_muti_start(ais_buffer, ais_data, // {"!", "$"}, [&](std::string& line) {
// {"!", "$"}, [&](std::string& line) { // lm->light_control(Light_Type::AIS, true);
// lm->light_control(Light_Type::AIS, true); // stream.AddLine(line);
// stream.AddLine(line); // while (auto msg = stream.PopOldestMessage())
// while (auto msg = stream.PopOldestMessage()) // {
// { // parse_ais(msg.get());
// parse_ais(msg.get()); // }
// } // lm->light_control(Light_Type::AIS, false);
// lm->light_control(Light_Type::AIS, false); // });
// }); // }
// } // std::this_thread::sleep_for(std::chrono::milliseconds(t));
// std::this_thread::sleep_for(std::chrono::milliseconds(t)); // }
// } // delete ais_serial;
// delete ais_serial;
} }
bool is_10004(SSR::Mode_S_Msg &msg) { bool is_10004(SSR::Mode_S_Msg& msg) {
bool DF_11_17_18 = bool DF_11_17_18 =
msg.df == SSR::Downlink_Format::All_Call_Reply_11 || msg.df == SSR::Downlink_Format::All_Call_Reply_11 ||
msg.df == SSR::Downlink_Format::Extended_Squitter_17 || msg.df == SSR::Downlink_Format::Extended_Squitter_17 ||
msg.df == SSR::Downlink_Format::Extended_Squitter_Non_Transponder_18; msg.df == SSR::Downlink_Format::Extended_Squitter_Non_Transponder_18;
return DF_11_17_18; return DF_11_17_18;
} }
std::string to_file_name(std::string_view str) { std::string to_file_name(std::string_view str) {
auto ret = std::string(str); auto ret = std::string(str);
// 定义允许的合法字符 // 定义允许的合法字符
auto is_valid_char = [](char c) { auto is_valid_char = [](char c) {
return std::isalnum(c) || c == '_' || c == '-' || return std::isalnum(c) || c == '_' || c == '-' ||
c == '.'; // 允许字母、数字、下划线、连字符、点 c == '.'; // 允许字母、数字、下划线、连字符、点
}; };
// 替换非法字符为下划线 '_' // 替换非法字符为下划线 '_'
std::transform(ret.begin(), ret.end(), ret.begin(), std::transform(ret.begin(), ret.end(), ret.begin(),
[&](char c) { return is_valid_char(c) ? c : '_'; }); [&](char c) {
// 检查结果字符串是否全是替换字符,防止生成全是下划线的文件名 return is_valid_char(c) ? c : '_';
if (ret.find_first_not_of('_') == std::string::npos) { });
return "default_file_name"; // 返回一个默认文件名 // 检查结果字符串是否全是替换字符,防止生成全是下划线的文件名
} if (ret.find_first_not_of('_') == std::string::npos) {
return ret; return "default_file_name"; // 返回一个默认文件名
}
return ret;
} }
void Debug_Logger_Info_Manager::push_info(std::string_view c) { void Debug_Logger_Info_Manager::push_info(std::string_view c) {
std::lock_guard g(mtx); std::lock_guard g(mtx);
std::string content = std::to_string(cur_serial_number) + ": " + std::string(c); std::string content = std::to_string(cur_serial_number) + ": " + std::string(c);
size_t content_length = content.size(); size_t content_length = content.size();
info_list.push_back({cur_serial_number, content}); info_list.push_back({cur_serial_number, content});
current_total_length += content_length; current_total_length += content_length;
while (current_total_length > max_length && !info_list.empty()) { while (current_total_length > max_length && !info_list.empty()) {
current_total_length -= info_list.front().content.size(); current_total_length -= info_list.front().content.size();
info_list.pop_front(); // 删除最早的记录 info_list.pop_front(); // 删除最早的记录
} }
cur_serial_number++; cur_serial_number++;
} }
Serial_Number_Type Debug_Logger_Info_Manager::get_cur_serial_number() { Serial_Number_Type Debug_Logger_Info_Manager::get_cur_serial_number() {
std::lock_guard g(mtx); std::lock_guard g(mtx);
return cur_serial_number; return cur_serial_number;
} }
JSON Debug_Logger_Info_Manager::to_json() { JSON Debug_Logger_Info_Manager::to_json() {
JSON ret = JSON::object(); JSON ret = JSON::object();
ret.append({"cur_serial_number", cur_serial_number}); ret.append({"cur_serial_number", cur_serial_number});
return ret; return ret;
} }
bool Web_Server::listen(std::string_view host, int port) { bool Web_Server::listen(std::string_view host, int port) {
drogon::HttpAppFramework *app = &drogon::app(); drogon::HttpAppFramework* app = &drogon::app();
auto g = Global::instance(); auto g = Global::instance();
Json::Value drogon_config; Json::Value drogon_config;
{ {
auto jsonStr = g->drogon_config.to_json_string(); auto jsonStr = g->drogon_config.to_json_string();
std::cout << "drogon::app().run(); " << jsonStr << std::endl; std::cout << "drogon::app().run(); " << jsonStr << std::endl;
Json::CharReaderBuilder builder; Json::CharReaderBuilder builder;
std::string errs; std::string errs;
auto reader = builder.newCharReader(); auto reader = builder.newCharReader();
if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(),
&drogon_config, &errs)) { &drogon_config, &errs)) {
// 解析失败 // 解析失败
std::cout << "drogon 配置文件加载失败!json格式解析失败!" << jsonStr std::cout << "drogon 配置文件加载失败!json格式解析失败!" << jsonStr
<< std::endl; << std::endl;
Psc::fail_fast(); Psc::fail_fast();
}
delete reader;
} }
delete reader; app->loadConfigJson(drogon_config);
} app->disableSigtermHandling(); // 关闭服务器信号处理
app->loadConfigJson(drogon_config); app->addListener(std::string(host), port);
app->disableSigtermHandling(); // 关闭服务器信号处理 auto base_dir = get_exe_dir();
app->addListener(std::string(host), port); // app->setLogPath(base_dir + "/logs/drogon.log");
auto base_dir = get_exe_dir(); app->setUploadPath(base_dir + "/../drogon_uploads");
// app->setLogPath(base_dir + "/logs/drogon.log"); app->run();
app->setUploadPath(base_dir + "/../drogon_uploads"); return true;
app->run(); }
return true; Web_Server& Web_Server::Post(std::string_view pattern, Handler handler) {
drogon::app().registerHandler(
std::string(pattern),
[handler](const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
handler(request, resp);
callback(resp);
},
{drogon::Post}
);
return *this;
}
Web_Server& Web_Server::Post_Coro(std::string_view pattern, CoroHandler handler) {
drogon::app().registerHandler(std::string(pattern), [handler = std::move(handler)](
const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
drogon::async_run(
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
try {
co_await handler(request, resp);
}
catch (const std::exception& error) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
std::terminate();
}
catch (...) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
std::terminate();
}
callback(resp);
co_return;
});
},
{drogon::Post}
);
return *this;
}
Web_Server& Web_Server::Get(std::string_view pattern, Handler handler) {
drogon::app().registerHandlerViaRegex(
std::string(pattern),
[handler](const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
handler(request, resp);
callback(resp);
},
{drogon::Get}
);
return *this;
}
Web_Server& Web_Server::Get_Coro(std::string_view pattern, CoroHandler handler) {
drogon::app().registerHandlerViaRegex(
std::string(pattern),
[handler = std::move(handler)](
const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
drogon::async_run(
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
try {
co_await handler(request, resp);
}
catch (const std::exception& error) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
std::terminate();
}
catch (...) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
std::terminate();
}
callback(resp);
co_return;
});
},
{drogon::Get}
);
return *this;
} }
std::string std::string
Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) { Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) {
std::lock_guard g(mtx); std::lock_guard g(mtx);
std::string result; std::string result;
if (serial_number == cur_serial_number) { if (serial_number == cur_serial_number) {
return ""; return "";
}
// 从后向前遍历 data 列表
for (auto it = info_list.rbegin(); it != info_list.rend(); ++it) {
// std::cout << "max_length: " << max_length << " size: " <<
// info_list.size() << " serial_number " << serial_number << "cur_sequence"
// << it->sequence << " content.size" << it->content.size() << std::endl;
if (it->sequence >= serial_number) {
result = it->content + result; // 叠加 content
} else {
break;
} }
} // 从后向前遍历 data 列表
return result; for (auto it = info_list.rbegin(); it != info_list.rend(); ++it) {
// std::cout << "max_length: " << max_length << " size: " <<
// info_list.size() << " serial_number " << serial_number << "cur_sequence"
// << it->sequence << " content.size" << it->content.size() << std::endl;
if (it->sequence >= serial_number) {
result = it->content + result; // 叠加 content
}
else {
break;
}
}
return result;
} }
std::string inet_address_to_string(const trantor::InetAddress& addr) {
std::string inet_address_to_string(const trantor::InetAddress &addr) { char buf[INET6_ADDRSTRLEN] = {0};
char buf[INET6_ADDRSTRLEN] = {0}; if (!addr.isIpV6()) {
// IPv4
if (!addr.isIpV6()) { auto sa = reinterpret_cast<const struct sockaddr_in*>(addr.getSockAddr());
// IPv4 inet_ntop(AF_INET, &(sa->sin_addr), buf, sizeof(buf));
auto sa = reinterpret_cast<const struct sockaddr_in *>(addr.getSockAddr()); uint16_t port = ntohs(sa->sin_port);
inet_ntop(AF_INET, &(sa->sin_addr), buf, sizeof(buf)); return std::string(buf) + ":" + std::to_string(port);
uint16_t port = ntohs(sa->sin_port); }
return std::string(buf) + ":" + std::to_string(port); else {
} else { // IPv6
// IPv6 auto sa6 =
auto sa6 = reinterpret_cast<const struct sockaddr_in6*>(addr.getSockAddr());
reinterpret_cast<const struct sockaddr_in6 *>(addr.getSockAddr()); inet_ntop(AF_INET6, &(sa6->sin6_addr), buf, sizeof(buf));
inet_ntop(AF_INET6, &(sa6->sin6_addr), buf, sizeof(buf)); uint16_t port = ntohs(sa6->sin6_port);
uint16_t port = ntohs(sa6->sin6_port); return "[" + std::string(buf) + "]:" + std::to_string(port);
return "[" + std::string(buf) + "]:" + std::to_string(port); }
}
} }
+26 -151
View File
@@ -1,8 +1,5 @@
#pragma once #pragma once
#include <string_view> #include <string_view>
#include "Core/Base/ThreadManager.h" #include "Core/Base/ThreadManager.h"
#include "../Data_Source/export.h" #include "../Data_Source/export.h"
#include "../State_Report/State_Report.h" #include "../State_Report/State_Report.h"
@@ -10,9 +7,7 @@
#include "Ucoro_Drogon_Glue.h" #include "Ucoro_Drogon_Glue.h"
#include "Config.h" #include "Config.h"
#include <drogon/drogon.h> #include <drogon/drogon.h>
#include "Config.h" #include "Config.h"
#include "../../Radarcape_Core/cpp-httplib/httplib.h" #include "../../Radarcape_Core/cpp-httplib/httplib.h"
#include "../Data_Source/export.h" #include "../Data_Source/export.h"
#include "Core/Net_Adapter/Net_Adapter.h" #include "Core/Net_Adapter/Net_Adapter.h"
@@ -20,13 +15,11 @@
#include <filesystem> #include <filesystem>
#include <list> #include <list>
#include <utility> #include <utility>
// 集中 管理日志 // 集中 管理日志
using namespace Psc; using namespace Psc;
extern BaseLogger* server_logger; extern BaseLogger* server_logger;
std::string to_file_name(std::string_view str); std::string to_file_name(std::string_view str);
std::string inet_address_to_string(const trantor::InetAddress &addr); std::string inet_address_to_string(const trantor::InetAddress& addr);
using Serial_Number_Type = unsigned int; using Serial_Number_Type = unsigned int;
struct Debug_Logger_Info_Manager { struct Debug_Logger_Info_Manager {
void push_info(std::string_view content); void push_info(std::string_view content);
@@ -47,24 +40,17 @@ private:
std::mutex mtx; std::mutex mtx;
}; };
extern Debug_Logger_Info_Manager debug_logger_info_manager; extern Debug_Logger_Info_Manager debug_logger_info_manager;
#define RET_OK \ #define RET_OK \
res.status = StatusCode::OK_200; \ res.status = StatusCode::OK_200; \
res.set_content("{\"status\": 200}", "application/json"); res.set_content("{\"status\": 200}", "application/json");
inline JSON warp(const JSON& data) { inline JSON warp(const JSON& data) {
// Json ret = Json::object(); // Json ret = Json::object();
// ret.append({"status", 200}); // ret.append({"status", 200});
// ret.append({"data", data}); // ret.append({"data", data});
// return ret; // return ret;
return data; return data;
} }
#define HTTP_Param const drogon::HttpRequestPtr& req, const drogon::HttpResponsePtr& res #define HTTP_Param const drogon::HttpRequestPtr& req, const drogon::HttpResponsePtr& res
class Web_Server { class Web_Server {
public: public:
std::string update = "update_"; std::string update = "update_";
@@ -76,125 +62,22 @@ public:
using Handler = std::function<void(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>; using Handler = std::function<void(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
using CoroHandler = std::function<drogon::Task<>(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>; using CoroHandler = std::function<drogon::Task<>(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
bool listen(std::string_view host, int port); bool listen(std::string_view host, int port);
~Web_Server() = default; ~Web_Server() = default;
static void stop() { static void stop() {
std::cout << "开始停止web服务" << std::endl; std::cout << "开始停止web服务" << std::endl;
drogon::app().quit(); drogon::app().quit();
} }
Web_Server& Post(std::string_view pattern, Handler handler);
Web_Server& Post(std::string_view pattern, Handler handler) { Web_Server& Post_Coro(std::string_view pattern, CoroHandler handler);
drogon::app().registerHandler( Web_Server& Get(std::string_view pattern, Handler handler);
std::string(pattern), Web_Server& Get_Coro(std::string_view pattern, CoroHandler handler);
[handler](const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
handler(request, resp);
callback(resp);
},
{drogon::Post}
);
return *this;
}
Web_Server& PostCoro(std::string_view pattern, CoroHandler handler) {
drogon::app().registerHandler(
std::string(pattern),
[handler = std::move(handler)](
const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
drogon::async_run(
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
try {
co_await handler(request, resp);
} catch (const std::exception& error) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
} catch (...) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
}
callback(resp);
co_return;
});
},
{drogon::Post}
);
return *this;
}
Web_Server& Get(std::string_view pattern, Handler handler) {
drogon::app().registerHandlerViaRegex(
std::string(pattern),
[handler](const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
handler(request, resp);
callback(resp);
},
{drogon::Get}
);
return *this;
}
Web_Server& GetCoro(std::string_view pattern, CoroHandler handler) {
drogon::app().registerHandlerViaRegex(
std::string(pattern),
[handler = std::move(handler)](
const drogon::HttpRequestPtr& request,
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
drogon::async_run(
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
try {
co_await handler(request, resp);
} catch (const std::exception& error) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
} catch (...) {
resp->setStatusCode(drogon::k500InternalServerError);
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
}
callback(resp);
co_return;
});
},
{drogon::Get}
);
return *this;
}
}; };
// 这个对象不释放 // 这个对象不释放
class Mlat_MSG { class Mlat_MSG {
public: public:
explicit Mlat_MSG(const std::shared_ptr<SSR::Mode_Msg>& first) { list.push_back(first);} explicit Mlat_MSG(const std::shared_ptr<SSR::Mode_Msg>& first) {
list.push_back(first);
}
[[nodiscard]] std::optional<std::string> icao() const { [[nodiscard]] std::optional<std::string> icao() const {
auto a = list[0]; auto a = list[0];
auto t = a->type; auto t = a->type;
@@ -203,21 +86,26 @@ public:
} }
return std::nullopt; return std::nullopt;
} }
[[nodiscard]] std::string msg_hex() const { return list[0]->msg_hex;} [[nodiscard]] std::string msg_hex() const {
[[nodiscard]] SSR::Mode_Msg::T type() const { return static_cast<SSR::Mode_Msg::T>(list[0]->type);} return list[0]->msg_hex;
[[nodiscard]] SSR::MLAT_timestamp& timestamp() const { return list[0]->mlat_timestamp;} }
[[nodiscard]] std::shared_ptr<SSR::Data_Source_Interface> data_source() const { return list[0]->source;} [[nodiscard]] SSR::Mode_Msg::T type() const {
return static_cast<SSR::Mode_Msg::T>(list[0]->type);
}
[[nodiscard]] SSR::MLAT_timestamp& timestamp() const {
return list[0]->mlat_timestamp;
}
[[nodiscard]] std::shared_ptr<SSR::Data_Source_Interface> data_source() const {
return list[0]->source;
}
void add(const std::shared_ptr<SSR::Mode_Msg>& t) { void add(const std::shared_ptr<SSR::Mode_Msg>& t) {
list.push_back(t); list.push_back(t);
} }
[[nodiscard]] size_t size() const { return list.size(); } [[nodiscard]] size_t size() const {
return list.size();
}
std::vector<std::shared_ptr<SSR::Mode_Msg>> list; std::vector<std::shared_ptr<SSR::Mode_Msg>> list;
}; };
class Mlat_Handler { class Mlat_Handler {
public: public:
std::list<Mlat_MSG> get_all() { std::list<Mlat_MSG> get_all() {
@@ -227,18 +115,14 @@ public:
std::swap(ok_list, ret); std::swap(ok_list, ret);
return ret; return ret;
} }
void push(const std::shared_ptr<SSR::Mode_Msg>& msg) { void push(const std::shared_ptr<SSR::Mode_Msg>& msg) {
std::lock_guard<std::mutex> g(mtx); std::lock_guard<std::mutex> g(mtx);
if (list.empty()) { if (list.empty()) {
list.emplace_back(msg); list.emplace_back(msg);
return; return;
} }
auto time = msg->mlat_timestamp; auto time = msg->mlat_timestamp;
auto p = list.rbegin(); auto p = list.rbegin();
while (p != list.rend()) { while (p != list.rend()) {
auto cur_time = p->timestamp(); auto cur_time = p->timestamp();
// 往前最多找3秒 // 往前最多找3秒
@@ -261,12 +145,7 @@ protected:
std::mutex ok_mtx; std::mutex ok_mtx;
std::mutex mtx; std::mutex mtx;
}; };
class Global : public Config, public Singleton<Global> {
class Global : public Config, public Singleton<Global>{
public: public:
// asio::io_context ctx; // asio::io_context ctx;
std::atomic<bool> init_ok{false}; std::atomic<bool> init_ok{false};
@@ -277,8 +156,7 @@ public:
return mode_acs.data_source_config.map.get(std::string(data_source_key)).value_or(nullptr); return mode_acs.data_source_config.map.get(std::string(data_source_key)).value_or(nullptr);
} }
std::shared_ptr<Data_Source> total_source() { std::shared_ptr<Data_Source> total_source() {
for (auto i : mode_acs.data_source_config.map.list()) for (auto i : mode_acs.data_source_config.map.list()) {
{
if (i->enable) return i; if (i->enable) return i;
} }
return mode_acs.data_source_config.map.list().at(0); return mode_acs.data_source_config.map.list().at(0);
@@ -291,9 +169,6 @@ public:
std::time_t start_server_time; std::time_t start_server_time;
DELETE_COPY(Global) DELETE_COPY(Global)
}; };
void handle_buffer_muti_start(std::string& buffer, std::string_view data, const std::set<std::string>& prefix_list, void handle_buffer_muti_start(std::string& buffer, std::string_view data, const std::set<std::string>& prefix_list,
const std::function<void(std::string&)>& callback); const std::function<void(std::string&)>& callback);
void handle_buffer_head_tail(std::string& buffer, std::string_view data, std::string_view prefix, void handle_buffer_head_tail(std::string& buffer, std::string_view data, std::string_view prefix,
+1 -5
View File
@@ -10,11 +10,7 @@ fetch_repo() {
local branch="$2" local branch="$2"
local dir="$3" local dir="$3"
if [ -d "$dir" ]; then if [ -d "$dir" ]; then
git -C "$dir" rev-parse --is-inside-work-tree >/dev/null echo "文件夹【$dir】已存在 跳过初始化 "
git -C "$dir" remote set-url origin "$repo"
git -C "$dir" fetch origin "$branch"
git -C "$dir" checkout "$branch"
git -C "$dir" pull --ff-only origin "$branch"
else else
git clone --branch "$branch" --single-branch "$repo" "$dir" git clone --branch "$branch" --single-branch "$repo" "$dir"
fi fi
-44
View File
@@ -1,44 +0,0 @@
$ErrorActionPreference = "Stop"
$scriptDir = $PSScriptRoot
if ( [string]::IsNullOrWhiteSpace($scriptDir))
{
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
}
$root = (Resolve-Path -LiteralPath (Join-Path $scriptDir "..")).Path
Set-Location -LiteralPath $root
$origin = git remote get-url origin
$origin = $origin.TrimEnd("/")
$remoteRoot = $origin -replace "/[^/]+(\.git)?$", ""
function Fetch-Repo
{
param(
[string]$Repo,
[string]$Branch,
[string]$Dir
)
if (Test-Path -LiteralPath $Dir -PathType Container)
{
git -C $Dir rev-parse --is-inside-work-tree *> $null
git -C $Dir remote set-url origin $Repo
git -C $Dir fetch origin $Branch
git -C $Dir checkout $Branch
git -C $Dir pull --ff-only origin $Branch
}
else
{
git clone --branch $Branch --single-branch $Repo $Dir
}
}
function Fetch-RepoEx
{
param(
[string]$Name
)
$repo = "$remoteRoot/$Name"
$branch = "master"
Fetch-Repo -Repo $repo -Branch $branch -Dir "third_party/$Name"
}
Fetch-RepoEx "build_infra"
Fetch-RepoEx "CPP_Core"
Fetch-RepoEx "SSR"
Fetch-RepoEx "eacp_webapp"
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
node_dir="/c/Users/wyc/AppData/Roaming/JetBrains/WebStorm2026.1/node/versions/24.18.0"
export PATH="$node_dir:$PATH"
cd "$root/third_party/eacp_webapp"
node --version
npm --version
npm run dev -- --host 0.0.0.0