diff --git a/config/config.json b/config/config.json index 7bc9290..5bb100c 100644 --- a/config/config.json +++ b/config/config.json @@ -53,9 +53,9 @@ "directories": [ ], "files": [ - "C:/tiles/卫星-世界-0-8.mbtiles", - "C:/tiles/卫星-中国-9-10.mbtiles", - "C:/tiles/卫星-中国-11.mbtiles" + "C:/tiles/混合图-世界-0-8.mbtiles", + "C:/tiles/混合图-中国-9-10.mbtiles", + "C:/tiles/混合图-中国-11.mbtiles" ], "path_layout": "z/x/y", "y_axis": "tms", @@ -90,49 +90,6 @@ "encoding": "terrarium" } }, - { - "key": "imagery", - "name": "本地卫星影像", - "tile_type": "imagery", - "request_method": "GET", - "resource": { - "file_format": "directory", - "directories": [ - "D:/ae/tiles/Esri_World_Imagery_0-9", - "D:/ae/tiles/Esri_World_Imagery_10-12" - ], - "files": [ - ], - "path_layout": "z/x/y", - "y_axis": "xyz", - "projection": "web_mercator", - "extension": ".png", - "tile_size": 256, - "minimum_level": 0, - "maximum_level": 11 - } - }, - { - "key": "google_imagery", - "name": "本地Google瓦片", - "tile_type": "imagery", - "request_method": "GET", - "resource": { - "file_format": "directory", - "directories": [ - "D:/tiles" - ], - "files": [ - ], - "path_layout": "z/x/y", - "y_axis": "xyz", - "projection": "web_mercator", - "extension": ".png", - "tile_size": 256, - "minimum_level": 1, - "maximum_level": 10 - } - }, { "key": "osm_online", "name": "OpenStreetMap在线", @@ -501,8 +458,8 @@ "net": [ { "key": "device", - "ip": "192.168.1.75", - "port": 80, + "ip": "0.0.0.0", + "port": 9081, "netmask": "255.255.255.0", "gateway": "192.168.1.1" }, diff --git a/module/Local_Server/DSP/DSP_Config.h b/module/Local_Server/DSP/DSP_Config.h index ab3e367..5d0d8b0 100644 --- a/module/Local_Server/DSP/DSP_Config.h +++ b/module/Local_Server/DSP/DSP_Config.h @@ -1,11 +1,8 @@ #ifndef PLANTSUNCAT_DSP2_H #define PLANTSUNCAT_DSP2_H - #include "../server/WebSocket_Manager.h" #include "global.h" - class Global; - #define USE_PROCESS 0 #ifdef USE_PROCESS #include "Core/Shared_Memory/Shared_Memory.h" @@ -14,11 +11,8 @@ class Global; // #define USE_PROCESS 1 // #endif // #define USE_PROCESS 1 - enum Demod_Mode { LSB, USB, AM, FM }; - -extern BaseLogger *dsp_logger; - +extern BaseLogger* dsp_logger; class DSP_Config_Data { public: std::string url; @@ -33,75 +27,63 @@ public: std::int64_t color_gain; PSC_USE_JSON }; - -class DSP_Config : public Base_DSP, public DSP_Config_Data{ +class DSP_Config : public Base_DSP, public DSP_Config_Data { public: - - ~DSP_Config(); - void close_dsp_device() const; - void init_update(const Psc::JSON *that_json) { - Get_J(port); - Get_J(center_freq); - Get_J(band_width); - Get_J(sample_rate); - Get_J(fft_point_number); - Get_J(power_min); - Get_J(power_max); - Get_J(power_offset); - Get_J(demod_mode); - Get_J(audio_gain); - Get_J(color_gain); - } - void from_json(const Psc::JSON *that_json) { - Base_DSP::from_base_json(that_json); - DSP_Config_Data::from_base_json(that_json); - } - Psc::JSON to_base_json() const { - return Base_DSP::to_base_json() += DSP_Config_Data::to_base_json(); - } - void init_env(); - void set_fft_point_number(uint64_t fft_point_number, bool force = false); - std::atomic record_iq_stream_ing = false; - struct Memory_Buffer { - std::vector get_all() { - std::vector empty; - std::lock_guard lock(m); - std::swap(empty, data); - return empty; + ~DSP_Config(); + void close_dsp_device() const; + void init_update(const Psc::JSON* that_json) { + Get_J(port); + Get_J(center_freq); + Get_J(band_width); + Get_J(sample_rate); + Get_J(fft_point_number); + Get_J(power_min); + Get_J(power_max); + Get_J(power_offset); + Get_J(demod_mode); + Get_J(audio_gain); + Get_J(color_gain); } - void push(void *pdata, uint64_t length) { - std::lock_guard lock(m); - data.emplace_back((char *)pdata, length); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + Base_DSP::from_base_json(that_json, not_exist_use_default_value); + DSP_Config_Data::from_base_json(that_json, not_exist_use_default_value); } - - protected: - std::vector data; - Psc::Spin_Lock m; - }; - + Psc::JSON to_base_json() const { + return Base_DSP::to_base_json() += DSP_Config_Data::to_base_json(); + } + void init_env(); + void set_fft_point_number(uint64_t fft_point_number, bool force = false); + std::atomic record_iq_stream_ing = false; + struct Memory_Buffer { + std::vector get_all() { + std::vector empty; + std::lock_guard lock(m); + std::swap(empty, data); + return empty; + } + void push(void* pdata, uint64_t length) { + std::lock_guard lock(m); + data.emplace_back((char*)pdata, length); + } + protected: + std::vector data; + Psc::Spin_Lock m; + }; #if USE_PROCESS - - void adsb_set_less_30Mhz_ddc_param(double center_freq, double sample_rate, - double band_width, int sw); - void adsb_set_less_30Mhz_fft_param(UHD_FFTWin fft_win_type, - size_t fft_point_number, - size_t fft_period_ms, int sw); - - Psc::SM_Block_RingBuffer json_func_call = - Psc::SM_Block_RingBuffer("json_func_call2", 1000); - Psc::SM_Block_RingBuffer rb = Psc::SM_Block_RingBuffer("rb", 2112 * 1000); - Psc::Pure_Share_Memory psm = Psc::Pure_Share_Memory("fft_data", 65536); - void restart_device(); + void adsb_set_less_30Mhz_ddc_param(double center_freq, double sample_rate, double band_width, int sw); + void adsb_set_less_30Mhz_fft_param(UHD_FFTWin fft_win_type, size_t fft_point_number, size_t fft_period_ms, int sw); + Psc::SM_Block_RingBuffer json_func_call = Psc::SM_Block_RingBuffer("json_func_call2", 1000); + Psc::SM_Block_RingBuffer rb = Psc::SM_Block_RingBuffer("rb", 2112 * 1000); + Psc::Pure_Share_Memory psm = Psc::Pure_Share_Memory("fft_data", 65536); + void restart_device(); #else - - void server(Global *g); - std::shared_ptr ws_fft; - std::shared_ptr ws_iq; - Memory_Buffer iq_memory_buffer; - std::vector fft_data; - std::mutex fft_mtx; - void *lib{}; + void server(Global* g); + std::shared_ptr ws_fft; + std::shared_ptr ws_iq; + Memory_Buffer iq_memory_buffer; + std::vector fft_data; + std::mutex fft_mtx; + void* lib{}; #endif }; - #endif diff --git a/module/Local_Server/Data_Feed/Data_Feed.cpp b/module/Local_Server/Data_Feed/Data_Feed.cpp index dd3f844..ce9cb0f 100644 --- a/module/Local_Server/Data_Feed/Data_Feed.cpp +++ b/module/Local_Server/Data_Feed/Data_Feed.cpp @@ -1,174 +1,168 @@ #include "Local_Server/Data_Feed/Data_Feed.h" -#include "../server/Global.h" #include +#include "../server/Global.h" bool Data_Feed::registered() { - auto all_feed = Global::instance()->mode_acs.data_feed_config.map.list(); - for (auto& item : all_feed) { - if (item.get() == this) { - return true; - } - } - return false; + auto all_feed = Global::instance()->mode_acs.data_feed_config.map.list(); + for (auto& item : all_feed) { + if (item.get() == this) { + return true; + } + } + return false; } asio::awaitable Data_Feed_UDP_Server::handle_in_loop_coro() { - co_await svr.tick_coro(); - co_return; + co_await svr.tick_coro(); + co_return; } asio::awaitable Data_Feed_UDP_Server::send_coro(std::string_view data) { - co_await svr.write_to_all_clients_coro(data); - co_return; + co_await svr.write_to_all_clients_coro(data); + co_return; } asio::awaitable Data_Feed_UDP_Server::_open() { - svr.set_bind_address("0.0.0.0", port); - svr.create(); - server_logger->c_debug({}, {}, to_string() + "开启!"); - co_return; + svr.set_bind_address("0.0.0.0", port); + svr.create(); + server_logger->c_debug({}, {}, to_string() + "开启!"); + co_return; } JSON Data_feed_Config::get_feed(std::string_view key) { - auto ret = map.get(std::string(key)); - if (ret.has_value()) { - auto r = ret.value().get(); - return r->to_json(); - } - return {nullptr}; + auto ret = map.get(std::string(key)); + if (ret.has_value()) { + auto r = ret.value().get(); + return r->to_json(); + } + return {nullptr}; } -void Data_feed_Config::server(Global *g) { - auto& svr = g->svr; - auto& api = g->api; - std::string name = "data_feed"; - svr.Post(api + "get_data_feed_state", [this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) - auto t = map.get(key); - JSON ret{nullptr}; - if (t.has_value()) { - ret = t.value()->get_state_json(); - } - res->setBody(warp(ret).to_json_string()); - }); - svr.Post(api + "update_data_feed_config", [this](HTTP_Param) { - CHECK_JSON_PARAM - Get_J(packet_byte_size) - Get_J(empty_wait_milliseconds) - res->setBody(warp(to_json()).to_json_string()); - Global::save(); - }); - svr.Post(api + "get_data_feed_config", [this](HTTP_Param) { - res->setBody(warp(to_json()).to_json_string()); - }); - svr.Post(api + "get_data_feed_server_connect", [this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) - auto t = map.get(key); - JSON ret{nullptr}; - if (t.has_value()) { - auto dfs = dynamic_cast(t.value().get()); - if (dfs) { - ret = dfs->get_clients_json(); - } - auto dfs2 = dynamic_cast(t.value().get()); - if (dfs2) { - ret = dfs2->get_clients_json(); - } - } - res->setBody(warp(ret).to_json_string()); - }); - svr.Post(api + svr.search + name, [this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(type, params.try_get_string("key")) - res->setBody(warp(get_feed(type)).to_json_string()); - }); - svr.Post(api + svr.update + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) - HTTP_REQUIRE_VALUE(df, map.get(key)) - // 直接关闭 - // t->close(); - df->from_json(¶ms); - Global::save(); - g->mode_acs.source_feed_relation_config.set_need_refresh(); - }); - svr.Post(api + svr.insert + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_PTR(data, params.get("data")) - HTTP_REQUIRE_VALUE(t, data->try_get_string("type")) - auto df = create_data_feed_from_type(t); - df->from_json(data); - HTTP_REQUIRE_VALUE(enable, data->try_get_bool("enable")) - HTTP_REQUIRE_TRUE(map.insert(index, df), "index") - res->setBody(warp(to_json()).to_json_string()); - Global::save(); - g->mode_acs.source_feed_relation_config.set_need_refresh(); - }); - svr.Post(api + svr.remove + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_VALUE(df, map.try_get(index)) - df->async_stop(); - HTTP_REQUIRE_TRUE(map.remove(index), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - g->mode_acs.source_feed_relation_config.set_need_refresh(); - }); - svr.Post(api + svr.rise + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_TRUE(map.swap(index, index - 1), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - g->mode_acs.source_feed_relation_config.set_need_refresh(); - }); - svr.Post(api + svr.fall + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_TRUE(map.swap(index, index + 1), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - g->mode_acs.source_feed_relation_config.set_need_refresh(); - }); +void Data_feed_Config::server(Global* g) { + auto& svr = g->svr; + auto& api = g->api; + std::string name = "data_feed"; + svr.Post(api + "get_data_feed_state", [this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) + auto t = map.get(key); + JSON ret{nullptr}; + if (t.has_value()) { + ret = t.value()->get_state_json(); + } + res->setBody(warp(ret).to_json_string()); + }); + svr.Post(api + "update_data_feed_config", [this](HTTP_Param) { + CHECK_JSON_PARAM + Get_J(packet_byte_size) Get_J(empty_wait_milliseconds) res->setBody(warp(to_json()).to_json_string()); + Global::save(); + }); + svr.Post(api + "get_data_feed_config", [this](HTTP_Param) { res->setBody(warp(to_json()).to_json_string()); }); + svr.Post(api + "get_data_feed_server_connect", [this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) + auto t = map.get(key); + JSON ret{nullptr}; + if (t.has_value()) { + auto dfs = dynamic_cast(t.value().get()); + if (dfs) { + ret = dfs->get_clients_json(); + } + auto dfs2 = dynamic_cast(t.value().get()); + if (dfs2) { + ret = dfs2->get_clients_json(); + } + } + res->setBody(warp(ret).to_json_string()); + }); + svr.Post(api + svr.search + name, [this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(type, params.try_get_string("key")) + res->setBody(warp(get_feed(type)).to_json_string()); + }); + svr.Post(api + svr.update + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Data_Feed:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) + HTTP_REQUIRE_VALUE(df, map.get(key)) + // 直接关闭 + // t->close(); + df->from_json(¶ms, true); + Global::save(); + g->mode_acs.source_feed_relation_config.set_need_refresh(); + }); + svr.Post(api + svr.insert + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Data_Feed:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_PTR(data, params.get("data")) + HTTP_REQUIRE_VALUE(t, data->try_get_string("type")) + std::shared_ptr df = create_data_feed_from_type(t); + df->from_json(data, true); + HTTP_REQUIRE_VALUE(enable, data->try_get_bool("enable")) + HTTP_REQUIRE_TRUE(map.insert(index, df), "index") + res->setBody(warp(to_json()).to_json_string()); + Global::save(); + g->mode_acs.source_feed_relation_config.set_need_refresh(); + }); + svr.Post(api + svr.remove + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Data_Feed:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_VALUE(df, map.try_get(index)) + df->async_stop(); + HTTP_REQUIRE_TRUE(map.remove(index), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + g->mode_acs.source_feed_relation_config.set_need_refresh(); + }); + svr.Post(api + svr.rise + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_TRUE(map.swap(index, index - 1), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + g->mode_acs.source_feed_relation_config.set_need_refresh(); + }); + svr.Post(api + svr.fall + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_TRUE(map.swap(index, index + 1), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + g->mode_acs.source_feed_relation_config.set_need_refresh(); + }); } void BIN_Msg_Buffer::push(std::string_view msg) { - auto output_packet_size = - Global::instance()->mode_acs.data_feed_config.packet_byte_size.load(); - std::lock_guard g(mtx); - auto& pool = Global::instance()->mode_acs.data_feed_config.pool_; - if (msg_list_cache.empty() || - msg_list_cache.back()->size() > output_packet_size) { - auto t = pool.get(); - t->append(msg); - msg_list_cache.push_back(t); - } - else { - msg_list_cache.back()->append(msg); - } + auto output_packet_size = Global::instance()->mode_acs.data_feed_config.packet_byte_size.load(); + std::lock_guard g(mtx); + auto& pool = Global::instance()->mode_acs.data_feed_config.pool_; + if (msg_list_cache.empty() || msg_list_cache.back()->size() > output_packet_size) { + auto t = pool.get(); + t->append(msg); + msg_list_cache.push_back(t); + } + else { + msg_list_cache.back()->append(msg); + } } const std::vector& BIN_Msg_Buffer::get_all() { - std::lock_guard g(mtx); - std::swap(msg_list_cache, msg_list); - msg_list_cache.clear(); - mode_s_msg_num = 0; - mode_other_msg_num = 0; - return msg_list; + std::lock_guard g(mtx); + std::swap(msg_list_cache, msg_list); + msg_list_cache.clear(); + mode_s_msg_num = 0; + mode_other_msg_num = 0; + return msg_list; } BIN_Msg_Buffer::BIN_Msg_Buffer() { - msg_list_cache.reserve(8 * 1024); - msg_list.reserve(8 * 1024); + msg_list_cache.reserve(8 * 1024); + msg_list.reserve(8 * 1024); } Psc::JSON BIN_Msg_Buffer::state_json() { - auto output_packet_size = - Global::instance()->mode_acs.data_feed_config.packet_byte_size.load(); - size_t size, cache_size, pool_capacity, pool_free_count; - { - std::lock_guard g(mtx); - auto& pool = Global::instance()->mode_acs.data_feed_config.pool_; - size = msg_list.size(); - cache_size = msg_list_cache.size(); - pool_capacity = pool.capacity(); - pool_free_count = pool.free_count(); - } - return VAR_JSON_7(mode_s_msg_num, mode_other_msg_num, output_packet_size, - cache_size, size, pool_capacity, pool_free_count); + auto output_packet_size = Global::instance()->mode_acs.data_feed_config.packet_byte_size.load(); + size_t size, cache_size, pool_capacity, pool_free_count; + { + std::lock_guard g(mtx); + auto& pool = Global::instance()->mode_acs.data_feed_config.pool_; + size = msg_list.size(); + cache_size = msg_list_cache.size(); + pool_capacity = pool.capacity(); + pool_free_count = pool.free_count(); + } + return VAR_JSON_7(mode_s_msg_num, mode_other_msg_num, output_packet_size, cache_size, size, pool_capacity, + pool_free_count); } - - diff --git a/module/Local_Server/Data_Feed/Data_Feed.h b/module/Local_Server/Data_Feed/Data_Feed.h index bae5a6f..be644ff 100644 --- a/module/Local_Server/Data_Feed/Data_Feed.h +++ b/module/Local_Server/Data_Feed/Data_Feed.h @@ -1,365 +1,318 @@ #pragma once +#include #include #include "Local_Server/server/With_Loop_Coro.h" #include "global.h" -#include enum class Output_Data_Format { AVR, AVR_MLAT, BIN, SBS, BIN_ID }; enum class Mode_S_Output_Type { DF_11_17_18, NO_POS_Mode_S, ALL_Mode_S }; struct Output_Format { - Output_Data_Format type = Output_Data_Format::BIN; - Psc::Copyable_Atomic use_status = false; - Mode_S_Output_Type mode_s_output_type = Mode_S_Output_Type::DF_11_17_18; - Psc::Copyable_Atomic use_mode_ac = false; - Psc::Copyable_Atomic sbs_only_pos = false; - PSC_USE_JSON + Output_Data_Format type = Output_Data_Format::BIN; + Psc::Copyable_Atomic use_status = false; + Mode_S_Output_Type mode_s_output_type = Mode_S_Output_Type::DF_11_17_18; + Psc::Copyable_Atomic use_mode_ac = false; + Psc::Copyable_Atomic sbs_only_pos = false; + PSC_USE_JSON }; class Data_Feed : public With_Loop_Coro { public: - BIN_Msg_Buffer msg_buffer{}; - Output_Format output_format; - Frequency_Limit_Multi sbs_flm{}; - asio::awaitable loop_coro() final; - virtual void handle_in_loop() {} - - virtual asio::awaitable handle_in_loop_coro() { - handle_in_loop(); - co_return; - } - - virtual asio::awaitable send_coro(std::string_view) { - co_return; - } - - virtual Psc::JSON to_json() { - Psc::JSON ret = With_Loop_Coro::to_base_json(); - ret.append(Psc::JSON("output_format", output_format.to_base_json())); - return ret; - } - - virtual void from_json(const Psc::JSON* that_json) { - With_Loop_Coro::from_base_json(that_json); - output_format.from_base_json(that_json->get("output_format")); - } - - virtual Psc::JSON get_custom_state_json() { - return Psc::JSON::object(); - } - - virtual Psc::JSON get_state_json() { - Psc::JSON ret = msg_buffer.state_json(); - ret += get_custom_state_json(); - return ret; - } - - std::string to_string() { - return "Data_Feed{" + VAR_STR_3(key, enable, type) + "}"; - } - - bool registered(); + BIN_Msg_Buffer msg_buffer{}; + Output_Format output_format; + Frequency_Limit_Multi sbs_flm{}; + asio::awaitable loop_coro() final; + virtual void handle_in_loop() { + } + virtual asio::awaitable handle_in_loop_coro() { + handle_in_loop(); + co_return; + } + virtual asio::awaitable send_coro(std::string_view) { + co_return; + } + virtual Psc::JSON to_json() { + Psc::JSON ret = With_Loop_Coro::to_base_json(); + ret.append(Psc::JSON("output_format", output_format.to_base_json())); + return ret; + } + virtual void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + With_Loop_Coro::from_base_json(that_json, not_exist_use_default_value); + output_format.from_base_json(that_json->get("output_format"), not_exist_use_default_value); + } + virtual Psc::JSON get_custom_state_json() { + return Psc::JSON::object(); + } + virtual Psc::JSON get_state_json() { + Psc::JSON ret = msg_buffer.state_json(); + ret += get_custom_state_json(); + return ret; + } + std::string to_string() { + return "Data_Feed{" + VAR_STR_3(key, enable, type) + "}"; + } + bool registered(); protected: - Data_Feed() = default; - Frequency_Limit too_many_msg_limit; + Data_Feed() = default; + Frequency_Limit too_many_msg_limit; }; class Data_Feed_TCP_Server_Data { public: - std::uint16_t port{}; - size_t connect_user_buffer_size{}; - size_t connect_system_buffer_size{}; - PSC_USE_JSON + std::uint16_t port{}; + size_t connect_user_buffer_size = 409600; + size_t connect_system_buffer_size = 409600; + PSC_USE_JSON }; class Data_Feed_TCP_Server : public Data_Feed, public Data_Feed_TCP_Server_Data { public: - Psc::asio_socket::TCP_Server_Coro svr; - - Psc::JSON get_custom_state_json() override { - auto& state = svr.state; - Psc::JSON ret = Psc::JSON::object(); - Ret_J(connect_system_buffer_size) - Ret_J(connect_user_buffer_size) - ret.key = "fixed"; - auto t = VAR_JSON_1(state); - t.append(ret); - return t; - } - - ~Data_Feed_TCP_Server() override = default; - - asio::awaitable handle_in_loop_coro() override { - co_await svr.flush_clients_coro(); - co_await svr.tick_coro(); - co_return; - } - - asio::awaitable send_coro(std::string_view data) override { - co_await svr.write_to_all_clients_coro(data); - co_return; - } - - void from_json(const Psc::JSON* that_json) override { - Data_Feed::from_json(that_json); - Data_Feed_TCP_Server_Data::from_base_json(that_json); - } - - Psc::JSON to_json() override { - Psc::JSON ret = Data_Feed::to_json(); - ret += Data_Feed_TCP_Server_Data::to_base_json(); - return ret; - } - - asio::awaitable _close() override { - co_await svr.close_coro(); - co_return; - } - - asio::awaitable _open() override { - svr.set_connect_user_buffer_size(connect_user_buffer_size); - svr.set_connect_system_buffer_size(connect_system_buffer_size); - svr.set_tcp_no_delay(false); - svr.create(); - co_await svr.listen_coro("0.0.0.0", port); - co_return; - } - - Psc::JSON get_clients_json() { - Psc::JSON ret = Psc::JSON::array(); - for (const auto& conn : svr.get_all_clients()) { - auto& info = conn->info; - Psc::JSON cur = Psc::JSON::object(); - auto& fd = info.fd; - auto& cur_ip = info.sockaddr.ip; - auto& cur_port = info.sockaddr.port; - cur.append({"base", VAR_STR_3(cur_ip, cur_port, fd)}); - cur.append({"state", conn->send_buffer.state_str()}); - { - auto& ins = conn->push_speed.instant_speed; - auto& avr = conn->push_speed.average_speed; - cur.append({"send_speed(KB/s)", VAR_STR_2(ins, avr)}); - } - { - auto& ins = conn->lose_speed.instant_speed; - auto& avr = conn->lose_speed.average_speed; - cur.append({"lose_speed(KB/s)", VAR_STR_2(ins, avr)}); - } - { - auto& ins = conn->send_num.instant; - auto& avr = conn->send_num.average; - cur.append({"send_num(byte/count)", VAR_STR_2(ins, avr)}); - } - ret.append(cur); - } - return ret; - } + Psc::asio_socket::TCP_Server_Coro svr; + Psc::JSON get_custom_state_json() override { + auto& state = svr.state; + Psc::JSON ret = Psc::JSON::object(); + Ret_J(connect_system_buffer_size) Ret_J(connect_user_buffer_size) ret.key = "fixed"; + auto t = VAR_JSON_1(state); + t.append(ret); + return t; + } + ~Data_Feed_TCP_Server() override = default; + asio::awaitable handle_in_loop_coro() override { + co_await svr.flush_clients_coro(); + co_await svr.tick_coro(); + co_return; + } + asio::awaitable send_coro(std::string_view data) override { + co_await svr.write_to_all_clients_coro(data); + co_return; + } + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Feed::from_json(that_json, not_exist_use_default_value); + Data_Feed_TCP_Server_Data::from_base_json(that_json, not_exist_use_default_value); + } + Psc::JSON to_json() override { + Psc::JSON ret = Data_Feed::to_json(); + ret += Data_Feed_TCP_Server_Data::to_base_json(); + return ret; + } + asio::awaitable _close() override { + co_await svr.close_coro(); + co_return; + } + asio::awaitable _open() override { + svr.set_connect_user_buffer_size(connect_user_buffer_size); + svr.set_connect_system_buffer_size(connect_system_buffer_size); + svr.set_tcp_no_delay(false); + svr.create(); + co_await svr.listen_coro("0.0.0.0", port); + co_return; + } + Psc::JSON get_clients_json() { + Psc::JSON ret = Psc::JSON::array(); + for (const auto& conn : svr.get_all_clients()) { + auto& info = conn->info; + Psc::JSON cur = Psc::JSON::object(); + auto& fd = info.fd; + auto& cur_ip = info.sockaddr.ip; + auto& cur_port = info.sockaddr.port; + cur.append({"base", VAR_STR_3(cur_ip, cur_port, fd)}); + cur.append({"state", conn->send_buffer.state_str()}); + { + auto& ins = conn->push_speed.instant_speed; + auto& avr = conn->push_speed.average_speed; + cur.append({"send_speed(KB/s)", VAR_STR_2(ins, avr)}); + } + { + auto& ins = conn->lose_speed.instant_speed; + auto& avr = conn->lose_speed.average_speed; + cur.append({"lose_speed(KB/s)", VAR_STR_2(ins, avr)}); + } + { + auto& ins = conn->send_num.instant; + auto& avr = conn->send_num.average; + cur.append({"send_num(byte/count)", VAR_STR_2(ins, avr)}); + } + ret.append(cur); + } + return ret; + } }; class Data_Feed_TCP_Client_Data { public: - std::string url; - std::uint16_t port{}; - PSC_USE_JSON + std::string url; + std::uint16_t port{}; + PSC_USE_JSON }; class Data_Feed_TCP_Client : public Data_Feed, public Data_Feed_TCP_Client_Data { public: - asio::awaitable handle_in_loop_coro() override { - co_await cli.tick_coro(); - co_return; - } - - asio::awaitable send_coro(std::string_view data) override { - co_await cli.send_coro(data); - co_return; - } - - std::string url; - - Psc::JSON get_custom_state_json() override { - auto& state = cli.state; - return VAR_JSON_1(state); - } - - std::uint16_t port{}; - Psc::asio_socket::TCP_Client_Coro cli; - ~Data_Feed_TCP_Client() override = default; - - asio::awaitable _close() override { - co_await cli.close_coro(); - co_return; - } - - asio::awaitable _open() override { - Psc::asio_socket::Sockaddr_In sockaddr_in; - sockaddr_in.ip = url; - sockaddr_in.port = port; - cli.set_dest_address(sockaddr_in); - cli.create(); - co_await cli.connect_coro(); - co_return; - } - - void from_json(const Psc::JSON* that_json) override { - Data_Feed::from_json(that_json); - Data_Feed_TCP_Client_Data::from_base_json(that_json); - } - - Psc::JSON to_json() override { - return Data_Feed::to_json() += Data_Feed_TCP_Client_Data::to_base_json(); - } + asio::awaitable handle_in_loop_coro() override { + co_await cli.tick_coro(); + co_return; + } + asio::awaitable send_coro(std::string_view data) override { + co_await cli.send_coro(data); + co_return; + } + std::string url; + Psc::JSON get_custom_state_json() override { + auto& state = cli.state; + return VAR_JSON_1(state); + } + std::uint16_t port{}; + Psc::asio_socket::TCP_Client_Coro cli; + ~Data_Feed_TCP_Client() override = default; + asio::awaitable _close() override { + co_await cli.close_coro(); + co_return; + } + asio::awaitable _open() override { + Psc::asio_socket::Sockaddr_In sockaddr_in; + sockaddr_in.ip = url; + sockaddr_in.port = port; + cli.set_dest_address(sockaddr_in); + cli.create(); + co_await cli.connect_coro(); + co_return; + } + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Feed::from_json(that_json, not_exist_use_default_value); + Data_Feed_TCP_Client_Data::from_base_json(that_json, not_exist_use_default_value); + } + Psc::JSON to_json() override { + return Data_Feed::to_json() += Data_Feed_TCP_Client_Data::to_base_json(); + } }; class Data_Feed_UDP_Server_Data { public: - std::uint16_t port{}; - PSC_USE_JSON + std::uint16_t port{}; + PSC_USE_JSON }; class Data_Feed_UDP_Server : public Data_Feed, public Data_Feed_UDP_Server_Data { public: - Psc::JSON get_custom_state_json() override { - auto& state = svr.state; - return VAR_JSON_1(state); - } - - Data_Feed_UDP_Server() = default; - ~Data_Feed_UDP_Server() override = default; - asio::awaitable handle_in_loop_coro() override; - asio::awaitable send_coro(std::string_view data) override; - - [[nodiscard]] Psc::JSON get_clients_json() const { - Psc::JSON ret = Psc::JSON::array(); - for (const auto& i : svr.clients) { - Psc::JSON cur = Psc::JSON::object(); - cur.append({"ip", i.ip}); - cur.append({"port", i.port}); - ret.append(cur); - } - return ret; - } - - void from_json(const Psc::JSON* that_json) override { - Data_Feed::from_json(that_json); - Data_Feed_UDP_Server_Data::from_base_json(that_json); - } - - Psc::JSON to_json() override { - return Data_Feed::to_json() += Data_Feed_UDP_Server_Data::to_base_json(); - } - - asio::awaitable _close() override { - co_await svr.close_coro(); - co_return; - } - - asio::awaitable _open() override; - Psc::asio_socket::UDP_Server_Coro svr; + Psc::JSON get_custom_state_json() override { + auto& state = svr.state; + return VAR_JSON_1(state); + } + Data_Feed_UDP_Server() = default; + ~Data_Feed_UDP_Server() override = default; + asio::awaitable handle_in_loop_coro() override; + asio::awaitable send_coro(std::string_view data) override; + [[nodiscard]] Psc::JSON get_clients_json() const { + Psc::JSON ret = Psc::JSON::array(); + for (const auto& i : svr.clients) { + Psc::JSON cur = Psc::JSON::object(); + cur.append({"ip", i.ip}); + cur.append({"port", i.port}); + ret.append(cur); + } + return ret; + } + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Feed::from_json(that_json, not_exist_use_default_value); + Data_Feed_UDP_Server_Data::from_base_json(that_json, not_exist_use_default_value); + } + Psc::JSON to_json() override { + return Data_Feed::to_json() += Data_Feed_UDP_Server_Data::to_base_json(); + } + asio::awaitable _close() override { + co_await svr.close_coro(); + co_return; + } + asio::awaitable _open() override; + Psc::asio_socket::UDP_Server_Coro svr; }; class Data_Feed_UDP_Client_Data { public: - std::uint16_t port{}; - std::string url{}; - PSC_USE_JSON + std::uint16_t port{}; + std::string url{}; + PSC_USE_JSON }; class Data_Feed_UDP_Client : public Data_Feed, public Data_Feed_UDP_Client_Data { public: - Data_Feed_UDP_Client() {} - ~Data_Feed_UDP_Client() override {} - - Psc::JSON get_custom_state_json() override { - auto& state = cli.state; - return VAR_JSON_1(state); - } - - asio::awaitable handle_in_loop_coro() override { - co_await cli.tick_coro(); - co_return; - } - - asio::awaitable send_coro(std::string_view data) override { - co_await cli.send_coro(data); - co_return; - } - - Psc::asio_socket::UDP_Client_Coro cli; - - void from_json(const Psc::JSON* that_json) override { - Data_Feed::from_json(that_json); - Data_Feed_UDP_Client_Data::from_base_json(that_json); - } - - Psc::JSON to_json() override { - return Data_Feed::to_json() += Data_Feed_UDP_Client_Data::to_base_json(); - } - - asio::awaitable _close() override { - std::cout << "udp client target address:" << cli.dest_address.to_string() - << " closed" << std::endl; - co_await cli.close_coro(); - co_return; - } - - asio::awaitable _open() override { - cli.create(); - cli.set_dest_address(url, port); - co_await cli.connect_coro(); - co_return; - } + Data_Feed_UDP_Client() { + } + ~Data_Feed_UDP_Client() override { + } + Psc::JSON get_custom_state_json() override { + auto& state = cli.state; + return VAR_JSON_1(state); + } + asio::awaitable handle_in_loop_coro() override { + co_await cli.tick_coro(); + co_return; + } + asio::awaitable send_coro(std::string_view data) override { + co_await cli.send_coro(data); + co_return; + } + Psc::asio_socket::UDP_Client_Coro cli; + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Feed::from_json(that_json, not_exist_use_default_value); + Data_Feed_UDP_Client_Data::from_base_json(that_json, not_exist_use_default_value); + } + Psc::JSON to_json() override { + return Data_Feed::to_json() += Data_Feed_UDP_Client_Data::to_base_json(); + } + asio::awaitable _close() override { + std::cout << "udp client target address:" << cli.dest_address.to_string() << " closed" << std::endl; + co_await cli.close_coro(); + co_return; + } + asio::awaitable _open() override { + cli.create(); + cli.set_dest_address(url, port); + co_await cli.connect_coro(); + co_return; + } }; - inline std::shared_ptr create_data_feed_from_type(std::string_view t) { - std::shared_ptr ret{}; - if (t == "Data_Feed_TCP_Server") - ret = std::make_shared(); - else if (t == "Data_Feed_UDP_Server") - ret = std::make_shared(); - else if (t == "Data_Feed_TCP_Client") - ret = std::make_shared(); - else if (t == "Data_Feed_UDP_Client") - ret = std::make_shared(); - else { - std::ostringstream oss; - oss << "unknown Data_Feed type: " << t << " " << LOG_POS_SIMPLE - << std::endl; - std::cout << oss.str(); - throw std::invalid_argument(oss.str()); - } - return ret; + std::shared_ptr ret{}; + if (t == "Data_Feed_TCP_Server") + ret = std::make_shared(); + else if (t == "Data_Feed_UDP_Server") + ret = std::make_shared(); + else if (t == "Data_Feed_TCP_Client") + ret = std::make_shared(); + else if (t == "Data_Feed_UDP_Client") + ret = std::make_shared(); + else { + std::ostringstream oss; + oss << "unknown Data_Feed type: " << t << " " << LOG_POS_SIMPLE << std::endl; + std::cout << oss.str(); + throw std::invalid_argument(oss.str()); + } + return ret; } - class Data_feed_Config_Data { public: - Psc::Copyable_Atomic empty_wait_milliseconds{}; - Psc::Copyable_Atomic packet_byte_size{}; - size_t tcp_server_default_connect_user_buffer_size{}; - size_t tcp_server_default_connect_system_buffer_size{}; - PSC_USE_JSON + Psc::Copyable_Atomic empty_wait_milliseconds{}; + Psc::Copyable_Atomic packet_byte_size{}; + size_t tcp_server_default_connect_user_buffer_size{}; + size_t tcp_server_default_connect_system_buffer_size{}; + PSC_USE_JSON }; class Data_feed_Config : public Data_feed_Config_Data { public: - Psc::String_Pool pool_ = - Psc::String_Pool(1600, 8 * 1024); // 8192 * 1600 12.5 MB - Ordered_Map> map; - Data_feed_Config() = default; - - void init(const Psc::JSON* that_json) { - auto connect = that_json->get("list"); - for (auto& it : connect->children) { - auto type = it.get_string("type"); - std::shared_ptr t = create_data_feed_from_type(type); - t->from_json(&it); - map.push_back(t); - } - Data_feed_Config_Data::from_base_json(that_json); - } - - Psc::JSON list() { - auto connect_json = Psc::JSON::array(); - for (auto& it : map.list()) { - connect_json.children.emplace_back(it->to_json()); - } - return connect_json; - } - - Psc::JSON to_json() { - Psc::JSON ret = Data_feed_Config_Data::to_base_json(); - ret.append({"list", list()}); - return ret; - } - - Psc::JSON get_feed(std::string_view key); - void server(Global* g); + Psc::String_Pool pool_ = Psc::String_Pool(1600, 8 * 1024); // 8192 * 1600 12.5 MB + Ordered_Map> map; + Data_feed_Config() = default; + void init(const Psc::JSON* that_json, bool not_exist_use_default_value) { + auto connect = that_json->get("list"); + for (auto& it : connect->children) { + auto type = it.get_string("type"); + std::shared_ptr t = create_data_feed_from_type(type); + t->from_json(&it, not_exist_use_default_value); + map.push_back(t); + } + Data_feed_Config_Data::from_base_json(that_json, not_exist_use_default_value); + } + Psc::JSON list() { + auto connect_json = Psc::JSON::array(); + for (auto& it : map.list()) { + connect_json.children.emplace_back(it->to_json()); + } + return connect_json; + } + Psc::JSON to_json() { + Psc::JSON ret = Data_feed_Config_Data::to_base_json(); + ret.append({"list", list()}); + return ret; + } + Psc::JSON get_feed(std::string_view key); + void server(Global* g); }; diff --git a/module/Local_Server/Data_Source/Data_Source.cpp b/module/Local_Server/Data_Source/Data_Source.cpp index 7b59889..4a50f2e 100644 --- a/module/Local_Server/Data_Source/Data_Source.cpp +++ b/module/Local_Server/Data_Source/Data_Source.cpp @@ -1,10 +1,9 @@ #include "Data_Source.h" #include +#include #include "../server/Global.h" #include "Database.h" -#include -Psc::serial::Serial* create_serial(std::string_view serial_name, - Baud_Rate_Type baud_rate) { +Psc::serial::Serial* create_serial(std::string_view serial_name, Baud_Rate_Type baud_rate) { auto serial = new Psc::serial::Serial; serial->set_serial_name(serial_name); serial->set_baud_rate(baud_rate); @@ -14,8 +13,7 @@ Psc::serial::Serial* create_serial(std::string_view serial_name, serial->set_flow_control(Psc::serial::FlowControl::HardwareControl); serial->set_buffer_byte_size(10 * 1024); if (!serial->open()) { - std::cerr << "createSerial " + std::string(serial_name) + ":" + - std::to_string(baud_rate) + " 打开串口失败!\n"; + std::cerr << "createSerial " + std::string(serial_name) + ":" + std::to_string(baud_rate) + " 打开串口失败!\n"; Psc::fail_fast(); return nullptr; } @@ -25,14 +23,10 @@ Psc::serial::Serial* create_serial(std::string_view serial_name, } return serial; } -std::shared_ptr create_from_json(const JSON* that_json) { +std::shared_ptr create_from_json(const JSON* that_json, bool not_exist_use_default_value) { std::string type = that_json->get_string("type"); std::shared_ptr ret = create_data_source_from_type(type); - ret->from_json(that_json); - // if (ret->enable) - // { - // ret->open(); - // } + ret->from_json(that_json, not_exist_use_default_value); return ret; } std::shared_ptr Data_Source::that() { @@ -87,8 +81,7 @@ void File_Data_Source::before_handle_msg(std::shared_ptr& msg) { std::vector readLines(std::string_view path) { std::vector lines; auto path_string = std::string(path); - std::filesystem::path p = - std::filesystem::path((const char8_t*)path_string.c_str()); + std::filesystem::path p = std::filesystem::path((const char8_t*)path_string.c_str()); // std::filesystem::path p = std::filesystem::u8path(path); std::ifstream istream(p); if (!istream) { @@ -134,9 +127,8 @@ std::vector readLines(std::string_view path) { lines.push_back(line); } std::ostringstream oss; - oss << path_string + " 总行数:" + std::to_string(lines.size()) + " 有效行数:" + - std::to_string(lines.size()) + "\n" - << std::flush; + oss << path_string + " 总行数:" + std::to_string(lines.size()) + " 有效行数:" + std::to_string(lines.size()) + + "\n" << std::flush; std::cout << oss.str() << std::flush; return lines; } @@ -168,17 +160,13 @@ std::tuple extractID2(std::string_view logLine) { size_t lastSpacePos = logLine.rfind(" "); // 查找最后一个空格 time_t t = convert_to_timestamp(logLine.substr(0, 19)); if (lastSpacePos != std::string::npos) { - return { - std::string(logLine.substr(lastSpacePos + 1)), - t - }; // 从最后一个空格之后提取字符串 + return {std::string(logLine.substr(lastSpacePos + 1)), t}; // 从最后一个空格之后提取字符串 } return {std::string(logLine), t}; } std::string bin_format(std::string_view hex, time_t t) { std::tm* currentTime = std::localtime(&t); - auto sec = currentTime->tm_hour * 3600 + currentTime->tm_min * 60 + - currentTime->tm_sec; + auto sec = currentTime->tm_hour * 3600 + currentTime->tm_min * 60 + currentTime->tm_sec; SSR::MLAT_timestamp a(sec, 0); return create_Binary_Format_memory(hex, 0, &a); } @@ -196,9 +184,8 @@ std::optional File_Data_Source::get_raw_line(int& ret_index) { if (!have_report_play_back_all_success) { std::ostringstream oss; oss << SSR::get_current_date() << " " << SSR::get_current_time() - << " [进程:" << std::this_thread::get_id() << "] " - << file_path + " 全部加载成功!\n" - << std::flush; + << " [进程:" << std::this_thread::get_id() << "] " << file_path + " 全部加载成功!\n" + << std::flush; std::cout << oss.str() << std::flush; have_report_play_back_all_success = true; } @@ -210,8 +197,7 @@ std::optional File_Data_Source::get_raw_line(int& ret_index) { return part_infos[index++]; } // 1A 33 1A 1A F1 FB 87 73 7E 7F a8001d81a87543b0a80000 -std::string get_true_from_raw_line(Data_Source* ds, File_Data_Type data_type, - int index, std::string_view log_info) { +std::string get_true_from_raw_line(Data_Source* ds, File_Data_Type data_type, int index, std::string_view log_info) { std::string ret; // 2025-01-06 07:20:17 [info] dc2541e65001401a3119b2dd1c7af67132201 if (data_type == File_Data_Type::BIN) { @@ -242,8 +228,7 @@ std::string get_true_from_raw_line(Data_Source* ds, File_Data_Type data_type, } else { std::ostringstream oss; - oss << "存在非法字符[" << c << "]: value:" << (int)c << " in:" - << log_info << LOG_POS; + oss << "存在非法字符[" << c << "]: value:" << (int)c << " in:" << log_info << LOG_POS; server_logger->c_debug("非法字符:", {}, oss.str()); return ""; } @@ -287,8 +272,7 @@ std::string get_true_from_raw_line(Data_Source* ds, File_Data_Type data_type, int size = result.size(); if (size != 2 * 2 && size != 7 * 2 && size != 14 * 2) { std::cout << "line_offset:[" << index << "] " << "大小" << size - << " 不为偶数,或不为2,7,14 不能转换成二进制格式:" << result - << std::endl; + << " 不为偶数,或不为2,7,14 不能转换成二进制格式:" << result << std::endl; return ""; } std::string head("\x1a"); @@ -304,8 +288,7 @@ std::string get_true_from_raw_line(Data_Source* ds, File_Data_Type data_type, else if (size == 14 * 2) { type = R"(3)"; } - ret = SSR::packet_to_escape_format(head + type + time_stamp + signal_level + - hex2mem(result)); + ret = SSR::packet_to_escape_format(head + type + time_stamp + signal_level + hex2mem(result)); // std::cout << ret.size() << std::endl; } else { @@ -337,8 +320,7 @@ asio::awaitable File_Data_Source::_open() { state = "已加载" + to_string(part_infos.size()) + "长度数据!"; co_return; } -std::vector File_Data_Source::readBinaryFileAsString(std::string_view filepath, - size_t part_size) { +std::vector File_Data_Source::readBinaryFileAsString(std::string_view filepath, size_t part_size) { // 打开文件(以二进制模式) std::ifstream file(filepath.data(), std::ios::binary); if (!file) { @@ -376,10 +358,7 @@ void File_Data_Source::origin_data_transform_mode_data(std::string& mode_data) { int ret_index = 0; if (play_mode != Play_Mode::analysis) { std::optional log_info = get_raw_line(ret_index); - mode_data = log_info.has_value() - ? get_true_from_raw_line(this, data_type, ret_index, - log_info.value()) - : ""; + mode_data = log_info.has_value() ? get_true_from_raw_line(this, data_type, ret_index, log_info.value()) : ""; } else { int num = 0; @@ -400,10 +379,12 @@ void File_Data_Source::origin_data_transform_mode_data(std::string& mode_data) { mode_data = ret; } } -void File_Data_Source::handle_mode_s(std::shared_ptr msg) { - if (!msg) return; +void File_Data_Source::handle_mode_s(std::shared_ptr& msg) { + if (!msg) + return; cache_list.push_back(std::make_shared(std::move(msg))); - if (cache_list.empty()) return; + if (cache_list.empty()) + return; if (pre_cache == nullptr) { pre_cache = cache_list.front(); cache_list.pop_front(); @@ -413,7 +394,8 @@ void File_Data_Source::handle_mode_s(std::shared_ptr msg) { } auto sys_time = player_clock.get_cur_time_point(); while (true) { - if (cache_list.empty()) break; + if (cache_list.empty()) + break; auto pre = pre_cache; auto cur = cache_list.front(); cur->day_num = pre->day_num; @@ -430,23 +412,21 @@ void File_Data_Source::handle_mode_s(std::shared_ptr msg) { } void Dll_Data_Source::origin_data_transform_mode_data(std::string& mode_data) { auto start = std::chrono::steady_clock::now(); - if (read_func_ptr == nullptr) return; + if (read_func_ptr == nullptr) + return; auto buf = reinterpret_cast(buffer.data()); auto len = read_func_ptr(buf, buffer_size); vs.update(len); std::string data(buf, len); if (data.empty()) { auto end = std::chrono::steady_clock::now(); - auto cost = - std::chrono::duration_cast(end - start) - .count(); + auto cost = std::chrono::duration_cast(end - start).count(); // std::cout << "Dll_Data_Source::read cost: " << cost << " us\n"; return; } auto ret = get_true_from_raw_line(this, data_type, -1, data); auto end = std::chrono::steady_clock::now(); - auto cost = std::chrono::duration_cast(end - start) - .count(); + auto cost = std::chrono::duration_cast(end - start).count(); // std::cout << "Dll_Data_Source::read cost: " << cost << " us\n"; mode_data = ret; } @@ -459,8 +439,7 @@ asio::awaitable Shared_Memory_Data_Source::_close() { sm.reset(); co_return; } -void Shared_Memory_Data_Source::origin_data_transform_mode_data( - std::string& mode_data) { +void Shared_Memory_Data_Source::origin_data_transform_mode_data(std::string& mode_data) { auto size = sm->shm.size(); size_t length = size; std::string data; @@ -503,36 +482,37 @@ void Data_Source_Config::server(Global* g) { } res->setBody(warp(ret).to_json_string()); }); - svr.Post(api + "get_mode_s_data_source_config", [this](HTTP_Param) { - res->setBody(warp(to_json()).to_json_string()); - }); + svr.Post(api + "get_mode_s_data_source_config", + [this](HTTP_Param) { res->setBody(warp(to_json()).to_json_string()); }); svr.Post(api + svr.update + name, [this, g](HTTP_Param) { CHECK_JSON_PARAM + std::cout << "Data_Source:" << req->path() << that_json->to_json_string(); HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) HTTP_REQUIRE_VALUE(ds, map.get(key)) - ds->from_json(¶ms); + ds->from_json(¶ms, true); g->save(); g->mode_acs.source_feed_relation_config.set_need_refresh(); res->setBody(warp(ds->to_json()).to_json_string()); }); svr.Post(api + svr.insert + name, [g, this](HTTP_Param) { CHECK_JSON_PARAM + std::cout << "Data_Source:" << req->path() << that_json->to_json_string(); HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) HTTP_REQUIRE_PTR(data, params.get("data")) HTTP_REQUIRE_VALUE(t, data->try_get_string("type")) std::cout << params.to_json_string() << std::endl; std::shared_ptr ds = create_data_source_from_type(t); - ds->from_json(data); + ds->from_json(data, true); HTTP_REQUIRE_VALUE(enable, data->try_get_bool("enable")) (void)enable; - HTTP_REQUIRE_TRUE(map.insert(index, ds), "index") - // std::cout << params.to_json_string() << std::endl; + HTTP_REQUIRE_TRUE(map.insert(index, ds), "index"); g->mode_acs.source_feed_relation_config.set_need_refresh(); Config::save(); res->setBody(warp(to_json()).to_json_string()); }); svr.Post(api + svr.remove + name, [g, this](HTTP_Param) { CHECK_JSON_PARAM + std::cout << "Data_Source:" << req->path() << that_json->to_json_string(); HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) HTTP_REQUIRE_VALUE(ds, map.try_get(index)) ds->async_stop(); @@ -558,6 +538,3 @@ void Data_Source_Config::server(Global* g) { g->mode_acs.source_feed_relation_config.set_need_refresh(); }); } - - - diff --git a/module/Local_Server/Data_Source/Data_Source.h b/module/Local_Server/Data_Source/Data_Source.h index d955c73..ba3d391 100644 --- a/module/Local_Server/Data_Source/Data_Source.h +++ b/module/Local_Server/Data_Source/Data_Source.h @@ -5,7 +5,7 @@ namespace Psc { class SM_RingBuffer; } class Data_Source; -std::shared_ptr create_from_json(const Psc::JSON* that_json); +std::shared_ptr create_from_json(const Psc::JSON* that_json, bool not_exist_use_default_value); class Input_Format { public: Input_Format() { @@ -17,7 +17,8 @@ public: for (auto e : magic_enum::enum_values()) { std::string_view value_view = magic_enum::enum_name(e); std::string value(value_view.begin(), value_view.end()); - if (value == Psc::to_string(SSR::Downlink_Format::Unknown)) continue; + if (value == Psc::to_string(SSR::Downlink_Format::Unknown)) + continue; auto ev = static_cast(e); bool it = test_v[ev]; ret.append({value, it}); @@ -29,7 +30,8 @@ public: for (auto e : magic_enum::enum_values()) { std::string_view value_view = magic_enum::enum_name(e); std::string value(value_view.begin(), value_view.end()); - if (value == Psc::to_string(SSR::Downlink_Format::Unknown)) continue; + if (value == Psc::to_string(SSR::Downlink_Format::Unknown)) + continue; auto use = json->get_bool(value); auto ev = static_cast(e); test_v[ev] = use; @@ -38,12 +40,14 @@ public: bool test(SSR::Downlink_Format df) { std::lock_guard g(mtx); auto dfv = static_cast(df); - if (dfv >= static_cast(SSR::Downlink_Format::Unknown)) return false; + if (dfv >= static_cast(SSR::Downlink_Format::Unknown)) + return false; return test_v[dfv]; } bool test(std::uint8_t dfv) { std::lock_guard g(mtx); - if (dfv >= static_cast(SSR::Downlink_Format::Unknown)) return false; + if (dfv >= static_cast(SSR::Downlink_Format::Unknown)) + return false; return test_v[dfv]; } protected: @@ -77,12 +81,12 @@ public: ret.append({"map3d", map3d.to_base_json()}); return ret; } - void from_base_json(const Psc::JSON* that_json) { + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { if (that_json == nullptr || that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_display"); } - map2d.from_base_json(that_json->get("map2d")); - map3d.from_base_json(that_json->get("map3d")); + map2d.from_base_json(that_json->get("map2d"), not_exist_use_default_value); + map3d.from_base_json(that_json->get("map3d"), not_exist_use_default_value); } }; class Data_Source_Data { @@ -97,29 +101,18 @@ public: Psc::Copyable_Atomic keep_mode = true; [[nodiscard]] Psc::JSON to_base_json() const { auto ret = Psc::JSON::object(); - Ret_J(base_station_has_valid_position) - ret.append({"map_display", map_display.to_base_json()}); - Ret_J(lat) - Ret_J(lon) - Ret_J(alt) - Ret_J(ignore_msg_time) - Ret_J(update_form_gps) - Ret_J(keep_mode) - return ret; + Ret_J(base_station_has_valid_position) ret.append({"map_display", map_display.to_base_json()}); + Ret_J(lat) Ret_J(lon) Ret_J(alt) Ret_J(ignore_msg_time) Ret_J(update_form_gps) Ret_J(keep_mode) return ret; } - void from_base_json(const Psc::JSON* that_json) { + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { Get_J(base_station_has_valid_position) - map_display.from_base_json(that_json->get("map_display")); - Get_J(lat) - Get_J(lon) - Get_J(alt) - Get_J(ignore_msg_time) - Get_J(update_form_gps) - Get_J(keep_mode) + map_display.from_base_json(that_json->get("map_display"), not_exist_use_default_value); + Get_J(lat) Get_J(lon) Get_J(alt) Get_J(ignore_msg_time) Get_J(update_form_gps) Get_J(keep_mode) } }; class Data_Source : public std::enable_shared_from_this, - public Data_Source_Handler, public Data_Source_Data { + public Data_Source_Handler, + public Data_Source_Data { public: std::shared_ptr that(); virtual asio::awaitable read_coro() { @@ -149,9 +142,9 @@ public: virtual Psc::JSON to_json() { return With_Loop_Coro::to_base_json() += Data_Source_Data::to_base_json(); } - virtual void from_json(const Psc::JSON* that_json) { - With_Loop_Coro::from_base_json(that_json); - Data_Source_Data::from_base_json(that_json); + virtual void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + With_Loop_Coro::from_base_json(that_json, not_exist_use_default_value); + Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); } std::string buffer; std::atomic_bool ask_sleep = false; @@ -193,9 +186,9 @@ public: Psc::JSON to_json() override { return Data_Source::to_json() += TCP_Client_Data_Source_Data::to_base_json(); } - void from_json(const Psc::JSON* that_json) override { - Data_Source::from_json(that_json); - TCP_Client_Data_Source_Data::from_base_json(that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Source::from_json(that_json, not_exist_use_default_value); + TCP_Client_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); } asio::awaitable read_coro() override { co_return co_await cli.read_coro(); @@ -226,8 +219,7 @@ public: serial->set_buffer_byte_size(10 * 1024); bool ok = serial->open(); if (!ok) { - std::cerr << "createSerial " + port_name + ":" + - std::to_string(baud_rate) + " 打开串口失败!\n"; + std::cerr << "createSerial " + port_name + ":" + std::to_string(baud_rate) + " 打开串口失败!\n"; } else { // std::cerr << "createSerial " + serial_name + ":" + @@ -236,7 +228,8 @@ public: co_return; } asio::awaitable _close() override { - if (serial) serial->close(); + if (serial) + serial->close(); co_return; } asio::awaitable handle_in_loop_coro() override { @@ -254,9 +247,9 @@ public: Psc::JSON to_json() override { return Data_Source::to_json() += Serial_Data_Source_Data::to_base_json(); } - void from_json(const Psc::JSON* that_json) override { - Data_Source::from_json(that_json); - Serial_Data_Source_Data::from_base_json(that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Source::from_json(that_json, not_exist_use_default_value); + Serial_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); } std::unique_ptr serial{}; ~Serial_Data_Source() override { @@ -291,8 +284,7 @@ public: Psc::JSON get_custom_state_json() override { auto cur_virtual_time = player_clock.get_cur_time_point(); auto playback_speed_rate = player_clock.playback_speed_rate; - return VAR_JSON_5(cur_virtual_time, playback_speed_rate, state, index, - part_infos.size()); + return VAR_JSON_5(cur_virtual_time, playback_speed_rate, state, index, part_infos.size()); } File_Data_Source() { this->type = "File_Data_Source"; @@ -300,7 +292,8 @@ public: ~File_Data_Source() override = default; void before_handle_msg(std::shared_ptr& msg) override; struct Cache_Msg { - explicit Cache_Msg(std::shared_ptr msg) : msg(std::move(msg)) {} + explicit Cache_Msg(std::shared_ptr msg) : msg(std::move(msg)) { + } SSR::Play_Back_Time_Point time() const { return SSR::Play_Back_Time_Point{day_num, msg->mlat_timestamp.daysec}; } @@ -315,17 +308,16 @@ public: } asio::awaitable _close() override; asio::awaitable _open() override; - std::vector readBinaryFileAsString(std::string_view filepath, - size_t part_size); - void from_json(const Psc::JSON* that_json) override { - Data_Source::from_json(that_json); - File_Data_Source_Data::from_base_json(that_json); + std::vector readBinaryFileAsString(std::string_view filepath, size_t part_size); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Source::from_json(that_json, not_exist_use_default_value); + File_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); } Psc::JSON to_json() override { return Data_Source::to_json() += File_Data_Source_Data::to_base_json(); } void origin_data_transform_mode_data(std::string& data) override; - void handle_mode_s(std::shared_ptr msg) override; + void handle_mode_s(std::shared_ptr& msg) override; protected: std::optional get_raw_line(int& ret_index); long long index = 0; @@ -353,9 +345,9 @@ public: } ~Dll_Data_Source() override = default; std::vector buffer; - void from_json(const Psc::JSON* that_json) override { - Data_Source::from_json(that_json); - Dll_Data_Source_Data::from_base_json(that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Source::from_json(that_json, not_exist_use_default_value); + Dll_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); buffer.resize(buffer_size); } Psc::JSON to_json() override { @@ -385,8 +377,7 @@ public: auto r = Psc::try_load_function(lib, function_name); if (!r) { state = r.error().message(); - std::cout << LOG_POS << " [" << function_name << "] 函数指针加载失败!" - << std::endl; + std::cout << LOG_POS << " [" << function_name << "] 函数指针加载失败!" << std::endl; co_return; } read_func_ptr = (Func_Type)r.value(); @@ -408,9 +399,9 @@ public: Psc::JSON get_custom_state_json() override { return Psc::JSON::object(); } - void from_json(const Psc::JSON* that_json) override { - Data_Source::from_json(that_json); - Shared_Memory_Data_Source_Data::from_base_json(that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) override { + Data_Source::from_json(that_json, not_exist_use_default_value); + Shared_Memory_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value); } Psc::JSON to_json() override { return Data_Source::to_json() += Shared_Memory_Data_Source_Data::to_base_json(); @@ -423,13 +414,18 @@ protected: }; inline std::shared_ptr create_data_source_from_type(std::string_view t) { std::shared_ptr ret{}; - if (t == "Serial_Data_Source") ret = std::make_shared(); - else if (t == "TCP_Client_Data_Source") ret = std::make_shared(); - else if (t == "File_Data_Source") ret = std::make_shared(); - else if (t == "Dll_Data_Source") ret = std::make_shared(); - else if (t == "Shared_Memory_Data_Source") ret = std::make_shared(); + if (t == "Serial_Data_Source") + ret = std::make_shared(); + else if (t == "TCP_Client_Data_Source") + ret = std::make_shared(); + else if (t == "File_Data_Source") + ret = std::make_shared(); + else if (t == "Dll_Data_Source") + ret = std::make_shared(); + else if (t == "Shared_Memory_Data_Source") + ret = std::make_shared(); else { - std::cout << "未知�?Data_Source type类型!" << std::endl; + std::cout << "未知 Data_Source type类型!" << std::endl; throw std::invalid_argument("unknown Data_Source type: " + std::string(t)); } return ret; @@ -437,10 +433,10 @@ inline std::shared_ptr create_data_source_from_type(std::string_vie struct Data_Source_Config { Ordered_Map> map; Data_Source_Config() = default; - void init(const Psc::JSON* that_json) { + void init(const Psc::JSON* that_json, bool not_exist_use_default_value) { auto list = that_json->get("list"); for (auto& it : list->children) { - auto ds = create_from_json(&it); + auto ds = create_from_json(&it, not_exist_use_default_value); map.push_back(ds); } } diff --git a/module/Local_Server/Data_Source/Data_Source_Handler.cpp b/module/Local_Server/Data_Source/Data_Source_Handler.cpp index eab314f..4ac4559 100644 --- a/module/Local_Server/Data_Source/Data_Source_Handler.cpp +++ b/module/Local_Server/Data_Source/Data_Source_Handler.cpp @@ -136,7 +136,9 @@ size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data) } else if (mode_s) { // 拓展点 - handle_mode_s(std::dynamic_pointer_cast(msg)); + auto mode_s_msg = std::dynamic_pointer_cast(msg); + source->push_to_feed(mode_s_msg); + handle_mode_s(mode_s_msg); } else { source->push_to_feed(msg); @@ -156,17 +158,16 @@ size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data) SSR::Binary_Format_handle_buffer(source->buffer, mode_data, f); return ret; } -void Data_Source_Handler::handle_mode_s(std::shared_ptr mode_s_msg) { +void Data_Source_Handler::handle_mode_s(std::shared_ptr& mode_s_msg) { auto source = ds(this); std::string t = mode_s_msg->mlat_timestamp.to_memory() + mode_s_msg->signal_level + Psc::hex2mem(mode_s_msg->msg_hex); auto p = mode_s_msg->packet.substr(2); if (t != p) { - std::cout << mem2hex(t, true, " ") << std::endl; - std::cout << mem2hex(mode_s_msg->packet, true, " ") << std::endl; - std::cout << VAR_STR_2(t, mode_s_msg->packet) << std::endl; + auto data = std::format("编解码出问题了(组合的数据,拼接的数据) hex:[{}] [{}] bin:[{}] [{}]", + mem2hex(t, true, " "), mem2hex(mode_s_msg->packet, true, " "), t, mode_s_msg->packet); + Psc::fail_fast(data); } - source->push_to_feed(mode_s_msg); auto& cfg = Global::instance()->mode_acs; bool time_space_filter = cfg.time_space_filter.load(); bool speed_filter = cfg.speed_filter.load(); @@ -180,16 +181,9 @@ void Data_Source_Handler::handle_mode_s(std::shared_ptr mode_s_ SSR::ADS_B_T::Constraint air_constraint{cfg.max_speed_m_s, cfg.air_pos_timeout, SSR::cpr_cb, time_space_filter, speed_filter, use_system_time, base_station_pos, source->alt, range_filter, range_factor}; - SSR::ADS_B_T::Constraint surface_constraint{cfg.max_speed_m_s, - cfg.surface_pos_timeout, - SSR::cpr_cb, - time_space_filter, - speed_filter, - use_system_time, - base_station_pos, - source->alt, - range_filter, - range_factor}; + SSR::ADS_B_T::Constraint surface_constraint{ + cfg.max_speed_m_s, cfg.surface_pos_timeout, SSR::cpr_cb, time_space_filter, speed_filter, + use_system_time, base_station_pos, source->alt, range_filter, range_factor}; SSR::parse_mode_s_bin(source.get(), mode_s_msg, base_station_pos, air_constraint, surface_constraint); auto base = source->get_aircraft(mode_s_msg->icao); if (base) { diff --git a/module/Local_Server/Data_Source/Data_Source_Handler.h b/module/Local_Server/Data_Source/Data_Source_Handler.h index 8c53b91..63bceb3 100644 --- a/module/Local_Server/Data_Source/Data_Source_Handler.h +++ b/module/Local_Server/Data_Source/Data_Source_Handler.h @@ -8,35 +8,33 @@ #include "Core/transmit_protocol/core/statistics.h" #include "Database.h" #include "Local_Server/global_include.h" -#include "global.h" #include "PlayBack.h" +#include "global.h" // 这个函数专门装cpu密集函数 放到线程池去处理 class Data_Source_Handler : public DataBase { public: - std::shared_ptr create_msg(std::string_view packet); - virtual void origin_data_transform_mode_data(std::string& origin_data) {}; - virtual void before_handle_msg(std::shared_ptr& msg) {}; - virtual void handle_mode_s(std::shared_ptr msg); - void handle_HULC(std::string_view packet); - size_t process_mode_acs_data(std::string_view mode_data); - Mode_AC_Statistic_Data mode_ac_statistic; - Mode_S_Statistic_Data mode_s_statistic; - Psc::Speed_Statistics read_speed; - Psc::Value_Statistics value_statistics; - ~Data_Source_Handler() override = default; - // 推送到 data_feed 相关代码 - void push_to_feed(const std::shared_ptr& msg); - void refresh_data_feed_key_list(); - struct Cached_Source_Info { - std::string key; - Psc::Value_Statistics mode_s_cache_num; - Psc::Value_Statistics mode_other_cache_num; - }; - std::atomic need_refresh_data_feed_key_list = true; - std::vector cached_data_feed_key_list{}; - Psc::JSON get_all_connect_feed_status(); - Psc::JSON get_all_connect_feed(); - std::mutex cdf_mtx; + std::shared_ptr create_msg(std::string_view packet); + virtual void origin_data_transform_mode_data(std::string& origin_data) {}; + virtual void before_handle_msg(std::shared_ptr& msg) {}; + virtual void handle_mode_s(std::shared_ptr& msg); + void handle_HULC(std::string_view packet); + size_t process_mode_acs_data(std::string_view mode_data); + Mode_AC_Statistic_Data mode_ac_statistic; + Mode_S_Statistic_Data mode_s_statistic; + Psc::Speed_Statistics read_speed; + Psc::Value_Statistics value_statistics; + ~Data_Source_Handler() override = default; + // 推送到 data_feed 相关代码 + void push_to_feed(const std::shared_ptr& msg); + void refresh_data_feed_key_list(); + struct Cached_Source_Info { + std::string key; + Psc::Value_Statistics mode_s_cache_num; + Psc::Value_Statistics mode_other_cache_num; + }; + std::atomic need_refresh_data_feed_key_list = true; + std::vector cached_data_feed_key_list{}; + Psc::JSON get_all_connect_feed_status(); + Psc::JSON get_all_connect_feed(); + std::mutex cdf_mtx; }; - - diff --git a/module/Local_Server/External_Database/External_Database.cpp b/module/Local_Server/External_Database/External_Database.cpp index 772f5c8..5afb5bb 100644 --- a/module/Local_Server/External_Database/External_Database.cpp +++ b/module/Local_Server/External_Database/External_Database.cpp @@ -1,33 +1,31 @@ -#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../server/Global.h" #include "../server/Performance_Monitor.h" #include "Core/Base/Coro_Result.h" #include "Resource_Utils.h" #include "Resources.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "global.h" namespace { -Psc::JSON -external_resource_status_to_json(const External_Resource_Status& status) { +Psc::JSON external_resource_status_to_json(const External_Resource_Status& status) { return Psc::JSON::object({ - {"name", status.name}, - {"row_count", status.row_count}, - {"downloaded", status.downloaded}, - {"imported", status.imported}, - {"message", status.message}, + {"name", status.name}, + {"row_count", status.row_count}, + {"downloaded", status.downloaded}, + {"imported", status.imported}, + {"message", status.message}, }); } -Psc::JSON external_resource_status_list_to_json( - const std::vector& status_list) { +Psc::JSON external_resource_status_list_to_json(const std::vector& status_list) { auto result = Psc::JSON::array(); for (const auto& status : status_list) { result.append(external_resource_status_to_json(status)); @@ -40,36 +38,31 @@ trantor::ConcurrentTaskQueue& external_database_task_queue() { } template void run_external_database_async(Work&& work, Callback&& callback) { - auto callback_holder = std::make_shared>( - std::forward(callback)); - external_database_task_queue().runTaskInQueue( - [work = std::forward(work), callback_holder]() mutable { - try { - (*callback_holder)(nullptr, work()); - } - catch (...) { - (*callback_holder)(std::current_exception(), T{}); - } - }); + auto callback_holder = std::make_shared>(std::forward(callback)); + external_database_task_queue().runTaskInQueue([work = std::forward(work), callback_holder]() mutable { + try { + (*callback_holder)(nullptr, work()); + } + catch (...) { + (*callback_holder)(std::current_exception(), T{}); + } + }); } template asio::awaitable await_external_database_callback(Starter starter) { - auto result = co_await Psc::coro::callback_result( - [starter = std::move(starter)](auto done) mutable { - starter([done = std::move(done)](std::exception_ptr exception, - T value) mutable { - if (exception) { - done.set_exception(exception); - return; - } - done(std::move(value)); - }); + auto result = co_await Psc::coro::callback_result([starter = std::move(starter)](auto done) mutable { + starter([done = std::move(done)](std::exception_ptr exception, T value) mutable { + if (exception) { + done.set_exception(exception); + return; + } + done(std::move(value)); }); + }); co_return std::move(result); } } // namespace -std::optional -External_Database_Row::get(std::string_view column) const { +std::optional External_Database_Row::get(std::string_view column) const { const auto iter = columns.find(std::string(column)); return iter == columns.end() ? std::nullopt : iter->second; } @@ -80,9 +73,9 @@ Psc::JSON External_Database_Row::to_json() const { } return result; } -External_Resources::External_Resources( - std::string_view name, std::string_view cache_file_name, std::string_view download_url, - std::string_view description, const std::uint64_t update_interval_seconds) { +External_Resources::External_Resources(std::string_view name, std::string_view cache_file_name, + std::string_view download_url, std::string_view description, + const std::uint64_t update_interval_seconds) { this->name = std::string(name); this->cache_file_name = std::string(cache_file_name); this->download_url = std::string(download_url); @@ -97,16 +90,12 @@ void External_Resources::clear_last_updated_at() { } std::size_t External_Resources::row_count(SQLite::Database& db) const { return static_cast( - db.execAndGet("SELECT COUNT(*) FROM " + - External_Database_Utils::quote_identifier(name)) - .getInt64()); + db.execAndGet("SELECT COUNT(*) FROM " + External_Database_Utils::quote_identifier(name)).getInt64()); } -std::filesystem::path -External_Resources::source_file(const std::filesystem::path& cache_pos) const { +std::filesystem::path External_Resources::source_file(const std::filesystem::path& cache_pos) const { return cache_pos / cache_file_name; } -bool External_Resources::fetch(const std::filesystem::path& cache_pos, - const bool force_download) const { +bool External_Resources::fetch(const std::filesystem::path& cache_pos, const bool force_download) const { const auto target_file = source_file(cache_pos); if (!force_download) return false; @@ -134,9 +123,7 @@ External_Resource_Status External_Resources::update(SQLite::Database& db, const } const auto local_file = source_file(cache_pos); if (!std::filesystem::exists(local_file)) { - result.message = download_url.empty() - ? "offline import or dynamic query required" - : "cache file unavailable"; + result.message = download_url.empty() ? "offline import or dynamic query required" : "cache file unavailable"; return result; } result.row_count = import_file(db, local_file); @@ -145,9 +132,8 @@ External_Resource_Status External_Resources::update(SQLite::Database& db, const mark_updated(); return result; } -External_Resource_Status -External_Resources::import_offline(SQLite::Database& db, - const std::filesystem::path& source_file) { +External_Resource_Status External_Resources::import_offline(SQLite::Database& db, + const std::filesystem::path& source_file) { create_table(db); External_Resource_Status result{name, 0, false, false, ""}; result.row_count = import_file(db, source_file); @@ -156,47 +142,37 @@ External_Resources::import_offline(SQLite::Database& db, mark_updated(); return result; } -External_Resource_Status -External_Resources::clear_table(SQLite::Database& db, - const std::filesystem::path& cache_pos) { +External_Resource_Status External_Resources::clear_table(SQLite::Database& db, const std::filesystem::path& cache_pos) { SQLite::Transaction transaction(db); - db.exec("DROP TABLE IF EXISTS " + - External_Database_Utils::quote_identifier(name)); + db.exec("DROP TABLE IF EXISTS " + External_Database_Utils::quote_identifier(name)); create_table(db); transaction.commit(); if (!cache_file_name.empty()) { std::error_code error; std::filesystem::remove(source_file(cache_pos), error); if (error) { - throw std::runtime_error("Cannot remove cache file for resource " + name + - ": " + error.message()); + throw std::runtime_error("Cannot remove cache file for resource " + name + ": " + error.message()); } } clear_last_updated_at(); return {name, 0, false, false, "table cleared"}; } -std::optional External_Resources::query_one( - SQLite::Database& db, - const std::vector& primary_key_values) const { +std::optional +External_Resources::query_one(SQLite::Database& db, const std::vector& primary_key_values) const { const auto& columns = primary_key_columns(); if (columns.size() != primary_key_values.size()) { - throw std::invalid_argument( - "primary key value count mismatch for resource: " + name); + throw std::invalid_argument("primary key value count mismatch for resource: " + name); } - std::string sql = "SELECT * FROM " + - External_Database_Utils::quote_identifier(name) + " WHERE "; + std::string sql = "SELECT * FROM " + External_Database_Utils::quote_identifier(name) + " WHERE "; for (std::size_t index = 0; index < columns.size(); ++index) { if (index != 0) sql += " AND "; - sql += External_Database_Utils::quote_identifier(columns[index]) + - " = ? COLLATE NOCASE"; + sql += External_Database_Utils::quote_identifier(columns[index]) + " = ? COLLATE NOCASE"; } sql += " LIMIT 1"; SQLite::Statement statement(db, sql); for (std::size_t index = 0; index < primary_key_values.size(); ++index) { - statement.bind( - static_cast(index + 1), - External_Database_Utils::normalize_key(primary_key_values[index])); + statement.bind(static_cast(index + 1), External_Database_Utils::normalize_key(primary_key_values[index])); } if (!statement.executeStep()) return std::nullopt; @@ -225,7 +201,7 @@ External_Resources_Manager::External_Resources_Manager() { register_external_resource(make_vradarserver_standing_data_resource()); register_external_resource(make_opensky_flightdata_api_resource()); } -void External_Resources_Manager::init(const Psc::JSON* that_json) { +void External_Resources_Manager::from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { if (!that_json) return; const auto list = that_json->get("list"); @@ -248,8 +224,7 @@ void External_Resources_Manager::init(const Psc::JSON* that_json) { Psc::JSON External_Resources_Manager::to_base_json() const { std::lock_guard lock(mtx_); auto ret = Psc::JSON::object(); - Ret_J(ecap_sqlite_path) - auto list = Psc::JSON::array(); + Ret_J(ecap_sqlite_path) auto list = Psc::JSON::array(); for (const std::unique_ptr& resource : resources_) { list.children.emplace_back(resource->to_json()); } @@ -258,8 +233,7 @@ Psc::JSON External_Resources_Manager::to_base_json() const { } void External_Resources_Manager::load_sqlite_db(std::string_view path) { try { - db_ = std::make_unique(path, SQLite::OPEN_READWRITE | - SQLite::OPEN_CREATE); + db_ = std::make_unique(path, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); } catch (SQLite::Exception& error) { Psc::fail_fast(std::string("load_sqlite_db error: ") + error.what()); @@ -272,215 +246,164 @@ void External_Resources_Manager::load_sqlite_db(std::string_view path) { sync_missing(*db_); } std::vector -External_Resources_Manager::refresh_external_databases( - const bool force_download) { +External_Resources_Manager::refresh_external_databases(const bool force_download) { return refresh_all(require_db(), force_download); } -External_Resource_Status External_Resources_Manager::refresh_external_database( - std::string_view resource_name, const bool force_download) { +External_Resource_Status External_Resources_Manager::refresh_external_database(std::string_view resource_name, + const bool force_download) { return refresh_one(require_db(), resource_name, force_download); } -External_Resource_Status External_Resources_Manager::import_external_database( - std::string_view resource_name, - const std::filesystem::path& source_file) { +External_Resource_Status +External_Resources_Manager::import_external_database(std::string_view resource_name, + const std::filesystem::path& source_file) { return import_offline(require_db(), resource_name, source_file); } -External_Resource_Status -External_Resources_Manager::clear_external_database_table( - std::string_view resource_name) { +External_Resource_Status External_Resources_Manager::clear_external_database_table(std::string_view resource_name) { return clear_table(require_db(), resource_name); } std::optional -External_Resources_Manager::query_external_database( - std::string_view resource_name, - const std::vector& primary_key_values) const { +External_Resources_Manager::query_external_database(std::string_view resource_name, + const std::vector& primary_key_values) const { return query_one(require_db(), resource_name, primary_key_values); } std::map> -External_Resources_Manager::query_aircraft_external_databases( - std::string_view icao24) const { +External_Resources_Manager::query_aircraft_external_databases(std::string_view icao24) const { return query_aircraft(require_db(), icao24); } std::map> -External_Resources_Manager::query_callsign_external_databases( - const std::optional& callsign) const { +External_Resources_Manager::query_callsign_external_databases(const std::optional& callsign) const { return query_callsign(require_db(), callsign); } -std::vector -External_Resources_Manager::external_database_status() const { +std::vector External_Resources_Manager::external_database_status() const { return status(require_db()); } -void External_Resources_Manager::async_refresh_external_databases( - const bool force_download, Status_List_Callback callback) { +void External_Resources_Manager::async_refresh_external_databases(const bool force_download, + Status_List_Callback callback) { run_external_database_async>( - [this, force_download]() { - return refresh_external_databases(force_download); - }, - std::move(callback)); + [this, force_download]() { return refresh_external_databases(force_download); }, std::move(callback)); } -void External_Resources_Manager::async_refresh_external_database( - std::string_view resource_name, const bool force_download, - Status_Callback callback) { +void External_Resources_Manager::async_refresh_external_database(std::string_view resource_name, + const bool force_download, Status_Callback callback) { run_external_database_async( - [this, resource_name = std::move(resource_name), force_download]() { - return refresh_external_database(resource_name, force_download); - }, - std::move(callback)); + [this, resource_name = std::move(resource_name), force_download]() { + return refresh_external_database(resource_name, force_download); + }, + std::move(callback)); } -void External_Resources_Manager::async_import_external_database( - std::string_view resource_name, std::filesystem::path source_file, - Status_Callback callback) { +void External_Resources_Manager::async_import_external_database(std::string_view resource_name, + std::filesystem::path source_file, + Status_Callback callback) { run_external_database_async( - [this, resource_name = std::move(resource_name), - source_file = std::move(source_file)]() { - return import_external_database(resource_name, source_file); - }, - std::move(callback)); + [this, resource_name = std::move(resource_name), source_file = std::move(source_file)]() { + return import_external_database(resource_name, source_file); + }, + std::move(callback)); } -void External_Resources_Manager::async_clear_external_database_table( - std::string_view resource_name, Status_Callback callback) { +void External_Resources_Manager::async_clear_external_database_table(std::string_view resource_name, + Status_Callback callback) { run_external_database_async( - [this, resource_name = std::move(resource_name)]() { - return clear_external_database_table(resource_name); - }, - std::move(callback)); + [this, resource_name = std::move(resource_name)]() { return clear_external_database_table(resource_name); }, + std::move(callback)); } -void External_Resources_Manager::async_query_external_database( - std::string_view resource_name, std::vector primary_key_values, - Row_Callback callback) const { +void External_Resources_Manager::async_query_external_database(std::string_view resource_name, + std::vector primary_key_values, + Row_Callback callback) const { run_external_database_async>( - [this, resource_name = std::move(resource_name), - primary_key_values = std::move(primary_key_values)]() { - return query_external_database(resource_name, primary_key_values); - }, - std::move(callback)); + [this, resource_name = std::move(resource_name), primary_key_values = std::move(primary_key_values)]() { + return query_external_database(resource_name, primary_key_values); + }, + std::move(callback)); } -void External_Resources_Manager::async_query_aircraft_external_databases( - std::string_view icao24, Row_Map_Callback callback) const { - run_external_database_async< - std::map>>( - [this, icao24 = std::move(icao24)]() { - return query_aircraft_external_databases(icao24); - }, - std::move(callback)); +void External_Resources_Manager::async_query_aircraft_external_databases(std::string_view icao24, + Row_Map_Callback callback) const { + run_external_database_async>>( + [this, icao24 = std::move(icao24)]() { return query_aircraft_external_databases(icao24); }, std::move(callback)); } -void External_Resources_Manager::async_query_callsign_external_databases( - std::optional callsign, Row_Map_Callback callback) const { - run_external_database_async< - std::map>>( - [this, callsign = std::move(callsign)]() { - return query_callsign_external_databases(callsign); - }, - std::move(callback)); +void External_Resources_Manager::async_query_callsign_external_databases(std::optional callsign, + Row_Map_Callback callback) const { + run_external_database_async>>( + [this, callsign = std::move(callsign)]() { return query_callsign_external_databases(callsign); }, + std::move(callback)); } -void External_Resources_Manager::async_external_database_status( - Status_List_Callback callback) const { - run_external_database_async>( - [this]() { - return external_database_status(); - }, std::move(callback)); +void External_Resources_Manager::async_external_database_status(Status_List_Callback callback) const { + run_external_database_async>([this]() { return external_database_status(); }, + std::move(callback)); } asio::awaitable> -External_Resources_Manager::refresh_external_databases_coro( - const bool force_download) { - co_return co_await await_external_database_callback< - std::vector>( - [this, force_download](Status_List_Callback callback) { - async_refresh_external_databases(force_download, std::move(callback)); - }); +External_Resources_Manager::refresh_external_databases_coro(const bool force_download) { + co_return co_await await_external_database_callback>( + [this, force_download](Status_List_Callback callback) { + async_refresh_external_databases(force_download, std::move(callback)); + }); } asio::awaitable -External_Resources_Manager::refresh_external_database_coro( - std::string_view resource_name, const bool force_download) { +External_Resources_Manager::refresh_external_database_coro(std::string_view resource_name, const bool force_download) { co_return co_await await_external_database_callback( - [this, resource_name = std::move(resource_name), - force_download](Status_Callback callback) mutable { - async_refresh_external_database(std::move(resource_name), - force_download, std::move(callback)); - }); + [this, resource_name = std::move(resource_name), force_download](Status_Callback callback) mutable { + async_refresh_external_database(std::move(resource_name), force_download, std::move(callback)); + }); } asio::awaitable -External_Resources_Manager::import_external_database_coro( - std::string_view resource_name, std::filesystem::path source_file) { +External_Resources_Manager::import_external_database_coro(std::string_view resource_name, + std::filesystem::path source_file) { co_return co_await await_external_database_callback( - [this, resource_name = std::move(resource_name), - source_file = std::move(source_file)](Status_Callback callback) mutable { - async_import_external_database(std::move(resource_name), - std::move(source_file), - std::move(callback)); - }); + [this, resource_name = std::move(resource_name), + source_file = std::move(source_file)](Status_Callback callback) mutable { + async_import_external_database(std::move(resource_name), std::move(source_file), std::move(callback)); + }); } asio::awaitable -External_Resources_Manager::clear_external_database_table_coro( - std::string_view resource_name) { +External_Resources_Manager::clear_external_database_table_coro(std::string_view resource_name) { co_return co_await await_external_database_callback( - [this, resource_name = - std::move(resource_name)](Status_Callback callback) mutable { - async_clear_external_database_table(std::move(resource_name), - std::move(callback)); - }); + [this, resource_name = std::move(resource_name)](Status_Callback callback) mutable { + async_clear_external_database_table(std::move(resource_name), std::move(callback)); + }); } asio::awaitable> -External_Resources_Manager::query_external_database_coro( - std::string_view resource_name, - std::vector primary_key_values) const { - co_return co_await await_external_database_callback< - std::optional>( - [this, resource_name = std::move(resource_name), - primary_key_values = - std::move(primary_key_values)](Row_Callback callback) mutable { - async_query_external_database(std::move(resource_name), - std::move(primary_key_values), - std::move(callback)); - }); +External_Resources_Manager::query_external_database_coro(std::string_view resource_name, + std::vector primary_key_values) const { + co_return co_await await_external_database_callback>( + [this, resource_name = std::move(resource_name), + primary_key_values = std::move(primary_key_values)](Row_Callback callback) mutable { + async_query_external_database(std::move(resource_name), std::move(primary_key_values), std::move(callback)); + }); } asio::awaitable> -External_Resources_Manager::query_aircraft_external_databases_coro( - std::string_view icao24) const { - auto result = co_await Psc::coro::callback_result< - std::shared_ptr>( - [this, icao24 = std::move(icao24)](auto done) mutable { - async_query_aircraft_external_databases( - std::move(icao24), - [done = std::move(done)](std::exception_ptr exception, - External_Database_Row_Map value) mutable { - if (exception) { - done.set_exception(exception); - return; - } - done(std::make_shared( - std::move(value))); - }); +External_Resources_Manager::query_aircraft_external_databases_coro(std::string_view icao24) const { + auto result = co_await Psc::coro::callback_result>( + [this, icao24 = std::move(icao24)](auto done) mutable { + async_query_aircraft_external_databases( + std::move(icao24), + [done = std::move(done)](std::exception_ptr exception, External_Database_Row_Map value) mutable { + if (exception) { + done.set_exception(exception); + return; + } + done(std::make_shared(std::move(value))); }); + }); co_return result; } asio::awaitable> -External_Resources_Manager::query_callsign_external_databases_coro( - std::optional callsign) const { - auto result = co_await Psc::coro::callback_result< - std::shared_ptr>( - [this, callsign = std::move(callsign)](auto done) mutable { - async_query_callsign_external_databases( - std::move(callsign), - [done = std::move(done)](std::exception_ptr exception, - External_Database_Row_Map value) mutable { - if (exception) { - done.set_exception(exception); - return; - } - done(std::make_shared( - std::move(value))); - }); +External_Resources_Manager::query_callsign_external_databases_coro(std::optional callsign) const { + auto result = co_await Psc::coro::callback_result>( + [this, callsign = std::move(callsign)](auto done) mutable { + async_query_callsign_external_databases( + std::move(callsign), + [done = std::move(done)](std::exception_ptr exception, External_Database_Row_Map value) mutable { + if (exception) { + done.set_exception(exception); + return; + } + done(std::make_shared(std::move(value))); }); + }); co_return result; } asio::awaitable> External_Resources_Manager::external_database_status_coro() const { - co_return co_await await_external_database_callback< - std::vector>( - [this](Status_List_Callback callback) { - async_external_database_status(std::move(callback)); - }); + co_return co_await await_external_database_callback>( + [this](Status_List_Callback callback) { async_external_database_status(std::move(callback)); }); } void External_Resources_Manager::server(Global* g) { auto& svr = g->svr; @@ -489,187 +412,141 @@ void External_Resources_Manager::server(Global* g) { auto t = warp(to_base_json()).to_json_string(); res->setBody(t); }); - svr.Post_Coro( - api + "get_external_database_status", - [this](HTTP_Param) -> drogon::Task<> { - auto status_list = - co_await Ecap_Coro::to_drogon(external_database_status_coro()); - res->setBody(warp(external_resource_status_list_to_json(status_list)) - .to_json_string()); - co_return; - }); - svr.Post_Coro( - api + "refresh_external_database", - [this, g](HTTP_Param) -> drogon::Task<> { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) - const auto result = co_await Ecap_Coro::to_drogon( - refresh_external_database_coro(name, true)); - g->save(); - res->setBody( - warp(external_resource_status_to_json(result)).to_json_string()); - co_return; - }); - svr.Post_Coro(api + "refresh_external_databases", - [this, g](HTTP_Param) -> drogon::Task<> { - const auto result = co_await Ecap_Coro::to_drogon( - refresh_external_databases_coro(true)); - g->save(); - res->setBody( - warp(external_resource_status_list_to_json(result)) - .to_json_string()); - co_return; - }); - svr.Post_Coro( - api + "import_external_database", - [this, g](HTTP_Param) -> drogon::Task<> { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) - HTTP_REQUIRE_VALUE(source_file, params.try_get_string("source_file")) - const auto result = co_await Ecap_Coro::to_drogon( - import_external_database_coro(name, source_file)); - g->save(); - res->setBody( - warp(external_resource_status_to_json(result)).to_json_string()); - co_return; - }); - svr.Post_Coro( - api + "upload_external_database", - [this, g](HTTP_Param) -> drogon::Task<> { - drogon::MultiPartParser parser; - if (parser.parse(req) != 0) { - throw_invalid_http_param("multipart"); + svr.Post_Coro(api + "get_external_database_status", [this](HTTP_Param) -> drogon::Task<> { + auto status_list = co_await Ecap_Coro::to_drogon(external_database_status_coro()); + res->setBody(warp(external_resource_status_list_to_json(status_list)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "refresh_external_database", [this, g](HTTP_Param) -> drogon::Task<> { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) + const auto result = co_await Ecap_Coro::to_drogon(refresh_external_database_coro(name, true)); + g->save(); + res->setBody(warp(external_resource_status_to_json(result)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "refresh_external_databases", [this, g](HTTP_Param) -> drogon::Task<> { + const auto result = co_await Ecap_Coro::to_drogon(refresh_external_databases_coro(true)); + g->save(); + res->setBody(warp(external_resource_status_list_to_json(result)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "import_external_database", [this, g](HTTP_Param) -> drogon::Task<> { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) + HTTP_REQUIRE_VALUE(source_file, params.try_get_string("source_file")) + const auto result = co_await Ecap_Coro::to_drogon(import_external_database_coro(name, source_file)); + g->save(); + res->setBody(warp(external_resource_status_to_json(result)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "upload_external_database", [this, g](HTTP_Param) -> drogon::Task<> { + drogon::MultiPartParser parser; + if (parser.parse(req) != 0) { + throw_invalid_http_param("multipart"); + } + const auto name = parser.getOptionalParameter("name"); + if (!name || parser.getFiles().size() != 1) { + throw_invalid_http_param("name or file"); + } + const auto& upload = parser.getFiles().front(); + const auto serial = std::chrono::steady_clock::now().time_since_epoch().count(); + auto extension = std::string(upload.getFileExtension()); + if (!extension.empty() && extension.front() != '.') { + extension.insert(extension.begin(), '.'); + } + const auto saved_name = "external_database_" + std::to_string(serial) + extension; + if (upload.saveAs(saved_name) != 0) { + throw std::runtime_error("Cannot save uploaded external database file"); + } + const auto source_file = std::filesystem::path(drogon::app().getUploadPath()) / saved_name; + const auto result = co_await Ecap_Coro::to_drogon(import_external_database_coro(*name, source_file)); + g->save(); + res->setBody(warp(external_resource_status_to_json(result)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "clear_external_database_table", [this, g](HTTP_Param) -> drogon::Task<> { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) + const auto result = co_await Ecap_Coro::to_drogon(clear_external_database_table_coro(name)); + g->save(); + res->setBody(warp(external_resource_status_to_json(result)).to_json_string()); + co_return; + }); + svr.Post_Coro(api + "query_external_database", [this](HTTP_Param) -> drogon::Task<> { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) + HTTP_REQUIRE_PTR(primary_key_values_json, params.get("primary_key_values")) + std::vector primary_key_values; + for (const auto& value : primary_key_values_json->children) { + if (value.valueType != Psc::JsonType::String) { + throw_invalid_http_param("primary_key_values"); } - const auto name = parser.getOptionalParameter("name"); - if (!name || parser.getFiles().size() != 1) { - throw_invalid_http_param("name or file"); - } - const auto& upload = parser.getFiles().front(); - const auto serial = - std::chrono::steady_clock::now().time_since_epoch().count(); - auto extension = std::string(upload.getFileExtension()); - if (!extension.empty() && extension.front() != '.') { - extension.insert(extension.begin(), '.'); - } - const auto saved_name = - "external_database_" + std::to_string(serial) + extension; - if (upload.saveAs(saved_name) != 0) { - throw std::runtime_error( - "Cannot save uploaded external database file"); - } - const auto source_file = - std::filesystem::path(drogon::app().getUploadPath()) / saved_name; - const auto result = co_await Ecap_Coro::to_drogon( - import_external_database_coro(*name, source_file)); - g->save(); - res->setBody( - warp(external_resource_status_to_json(result)).to_json_string()); - co_return; - }); - svr.Post_Coro( - api + "clear_external_database_table", - [this, g](HTTP_Param) -> drogon::Task<> { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) - const auto result = co_await Ecap_Coro::to_drogon( - clear_external_database_table_coro(name)); - g->save(); - res->setBody( - warp(external_resource_status_to_json(result)).to_json_string()); - co_return; - }); - svr.Post_Coro( - api + "query_external_database", [this](HTTP_Param) -> drogon::Task<> { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(name, params.try_get_string("name")) - HTTP_REQUIRE_PTR(primary_key_values_json, - params.get("primary_key_values")) - std::vector primary_key_values; - for (const auto& value : primary_key_values_json->children) { - if (value.valueType != Psc::JsonType::String) { - throw_invalid_http_param("primary_key_values"); - } - primary_key_values.push_back(value.val); - } - const auto row = co_await Ecap_Coro::to_drogon( - query_external_database_coro(name, std::move(primary_key_values))); - res->setBody(row - ? warp(row->to_json()).to_json_string() - : Psc::JSON(nullptr).to_json_string()); - co_return; - }); + primary_key_values.push_back(value.val); + } + const auto row = + co_await Ecap_Coro::to_drogon(query_external_database_coro(name, std::move(primary_key_values))); + res->setBody(row ? warp(row->to_json()).to_json_string() : Psc::JSON(nullptr).to_json_string()); + co_return; + }); } -void External_Resources_Manager::register_external_resource( - std::unique_ptr external_res) { +void External_Resources_Manager::register_external_resource(std::unique_ptr external_res) { if (!external_res) throw std::invalid_argument("external resource is null"); resources_.push_back(std::move(external_res)); } -void External_Resources_Manager::initialize(SQLite::Database& db, - std::filesystem::path cache_pos) { +void External_Resources_Manager::initialize(SQLite::Database& db, std::filesystem::path cache_pos) { std::lock_guard lock(mtx_); cache_pos_ = std::move(cache_pos); for (const auto& resource : resources_) resource->create_table(db); } -std::vector -External_Resources_Manager::sync_missing(SQLite::Database& db) { +std::vector External_Resources_Manager::sync_missing(SQLite::Database& db) { return update_all(db, false, true); } -std::vector -External_Resources_Manager::refresh_all(SQLite::Database& db, - const bool force_download) { +std::vector External_Resources_Manager::refresh_all(SQLite::Database& db, + const bool force_download) { return update_all(db, force_download, false); } -External_Resource_Status -External_Resources_Manager::refresh_one(SQLite::Database& db, - std::string_view resource_name, - const bool force_download) { +External_Resource_Status External_Resources_Manager::refresh_one(SQLite::Database& db, std::string_view resource_name, + const bool force_download) { std::lock_guard lock(mtx_); - return get_resource(resource_name) - .update(db, cache_pos_, force_download, false); + return get_resource(resource_name).update(db, cache_pos_, force_download, false); } -External_Resource_Status External_Resources_Manager::import_offline( - SQLite::Database& db, std::string_view resource_name, - const std::filesystem::path& source_file) { +External_Resource_Status External_Resources_Manager::import_offline(SQLite::Database& db, + std::string_view resource_name, + const std::filesystem::path& source_file) { std::lock_guard lock(mtx_); return get_resource(resource_name).import_offline(db, source_file); } -External_Resource_Status -External_Resources_Manager::clear_table(SQLite::Database& db, - std::string_view resource_name) { +External_Resource_Status External_Resources_Manager::clear_table(SQLite::Database& db, std::string_view resource_name) { std::lock_guard lock(mtx_); return get_resource(resource_name).clear_table(db, cache_pos_); } -std::optional External_Resources_Manager::query_one( - SQLite::Database& db, std::string_view resource_name, - const std::vector& primary_key_values) const { +std::optional +External_Resources_Manager::query_one(SQLite::Database& db, std::string_view resource_name, + const std::vector& primary_key_values) const { std::lock_guard lock(mtx_); return get_resource(resource_name).query_one(db, primary_key_values); } std::map> -External_Resources_Manager::query_aircraft(SQLite::Database& db, - std::string_view icao24) const { - Scope_Timer timer( - "external_database.query_aircraft", - Global::instance()->http_monitor_config.slow_scope_threshold_ms); +External_Resources_Manager::query_aircraft(SQLite::Database& db, std::string_view icao24) const { + Scope_Timer timer("external_database.query_aircraft", + Global::instance()->http_monitor_config.slow_scope_threshold_ms); static const std::vector kAircraftResourceKeys = { - "tar1090_db_aircraft", "wiedehopf_tar1090_db_aircraft", - "mictronics_aircraft_database", "opensky_aircraft_database", - "faa_aircraft_registry", + "tar1090_db_aircraft", "wiedehopf_tar1090_db_aircraft", "mictronics_aircraft_database", + "opensky_aircraft_database", "faa_aircraft_registry", }; std::lock_guard lock(mtx_); std::map> result; - const auto add_row = [&](std::string_view resource_name, - const std::vector& primary_key_values, + const auto add_row = [&](std::string_view resource_name, const std::vector& primary_key_values, std::string_view result_name = std::string{}) { auto& resource = get_resource(resource_name); auto row = resource.query_one(db, primary_key_values); if (!row) return std::shared_ptr{}; auto shared_row = std::make_shared(std::move(*row)); - result.emplace(std::string(result_name.empty() ? resource_name : result_name), - shared_row); + result.emplace(std::string(result_name.empty() ? resource_name : result_name), shared_row); return shared_row; }; std::optional type_code; @@ -686,28 +563,24 @@ External_Resources_Manager::query_aircraft(SQLite::Database& db, return result; } std::map> -External_Resources_Manager::query_callsign( - SQLite::Database& db, const std::optional& callsign) const { - Scope_Timer timer( - "external_database.query_callsign", - Global::instance()->http_monitor_config.slow_scope_threshold_ms); +External_Resources_Manager::query_callsign(SQLite::Database& db, const std::optional& callsign) const { + Scope_Timer timer("external_database.query_callsign", + Global::instance()->http_monitor_config.slow_scope_threshold_ms); static const std::vector kRouteResourceKeys = { - "vrs_routes", - "adsblol_vrs_standing_data_routes", - "vradarserver_standing_data_routes", + "vrs_routes", + "adsblol_vrs_standing_data_routes", + "vradarserver_standing_data_routes", }; std::lock_guard lock(mtx_); std::map> result; - const auto add_row = [&](std::string_view resource_name, - const std::vector& primary_key_values, + const auto add_row = [&](std::string_view resource_name, const std::vector& primary_key_values, std::string_view result_name = std::string{}) { auto& resource = get_resource(resource_name); auto row = resource.query_one(db, primary_key_values); if (!row) return std::shared_ptr{}; auto shared_row = std::make_shared(std::move(*row)); - result.emplace(result_name.empty() ? resource_name : result_name, - shared_row); + result.emplace(result_name.empty() ? resource_name : result_name, shared_row); return shared_row; }; std::set airport_codes; @@ -736,13 +609,11 @@ External_Resources_Manager::query_callsign( } return result; } -std::vector -External_Resources_Manager::status(SQLite::Database& db) const { +std::vector External_Resources_Manager::status(SQLite::Database& db) const { std::lock_guard lock(mtx_); std::vector result; for (const auto& resource : resources_) { - result.push_back( - {resource->name, resource->row_count(db), false, false, ""}); + result.push_back({resource->name, resource->row_count(db), false, false, ""}); } return result; } @@ -752,8 +623,7 @@ SQLite::Database& External_Resources_Manager::require_db() const { } return *db_; } -External_Resources& External_Resources_Manager::get_resource( - std::string_view resource_name) const { +External_Resources& External_Resources_Manager::get_resource(std::string_view resource_name) const { for (const auto& resource : resources_) { if (resource->name == resource_name) return *resource; @@ -761,27 +631,21 @@ External_Resources& External_Resources_Manager::get_resource( throw std::invalid_argument("unknown external resource: " + std::string(resource_name)); } std::vector -External_Resources_Manager::update_all(SQLite::Database& db, - const bool force_download, - const bool only_when_empty) { +External_Resources_Manager::update_all(SQLite::Database& db, const bool force_download, const bool only_when_empty) { std::lock_guard lock(mtx_); std::vector result; for (const auto& resource : resources_) { External_Resource_Status status; try { - status = - resource->update(db, cache_pos_, force_download, only_when_empty); - std::cout << "External database [" << status.name << "] " - << status.message << ", rows=" << status.row_count << std::endl; + status = resource->update(db, cache_pos_, force_download, only_when_empty); + std::cout << "External database [" << status.name << "] " << status.message << ", rows=" << status.row_count + << std::endl; result.push_back(std::move(status)); } catch (const std::exception& error) { - std::cerr << "External database [" << resource->name - << "] update failed: [" << error.what() << "]" << " status.message:" << status.message << std::endl; - result.push_back({ - resource->name, resource->row_count(db), false, false, - error.what() - }); + std::cerr << "External database [" << resource->name << "] update failed: [" << error.what() << "]" + << " status.message:" << status.message << std::endl; + result.push_back({resource->name, resource->row_count(db), false, false, error.what()}); } } return result; diff --git a/module/Local_Server/External_Database/global.h b/module/Local_Server/External_Database/global.h index 889c04d..2efa231 100644 --- a/module/Local_Server/External_Database/global.h +++ b/module/Local_Server/External_Database/global.h @@ -1,6 +1,4 @@ #pragma once -#include -#include "Core/Base/JSON.h" #include #include #include @@ -14,7 +12,9 @@ #include #include #include +#include #include +#include "Core/Base/JSON.h" class Global; struct External_Database_Row { std::map> columns; @@ -26,8 +26,7 @@ struct External_Database_Row { [[nodiscard]] std::optional get(std::string_view column) const; [[nodiscard]] Psc::JSON to_json() const; }; -using External_Database_Row_Map = -std::map>; +using External_Database_Row_Map = std::map>; struct External_Resource_Status { std::string name; std::size_t row_count{}; @@ -46,18 +45,19 @@ public: }; class External_Resources : public External_Resources_Data { public: - External_Resources(std::string_view name, std::string_view cache_file_name, - std::string_view download_url, std::string_view description, - std::uint64_t update_interval_seconds); + External_Resources(std::string_view name, std::string_view cache_file_name, std::string_view download_url, + std::string_view description, std::uint64_t update_interval_seconds); virtual ~External_Resources() = default; [[nodiscard]] std::size_t row_count(SQLite::Database& db) const; virtual void create_table(SQLite::Database& db) const = 0; - External_Resource_Status update(SQLite::Database& db, const std::filesystem::path& cache_pos, bool force_download, bool only_when_empty); + External_Resource_Status update(SQLite::Database& db, const std::filesystem::path& cache_pos, bool force_download, + bool only_when_empty); External_Resource_Status import_offline(SQLite::Database& db, const std::filesystem::path& source_file); External_Resource_Status clear_table(SQLite::Database& db, const std::filesystem::path& cache_pos); - [[nodiscard]] std::optional query_one(SQLite::Database& db, const std::vector& primary_key_values) const; + [[nodiscard]] std::optional + query_one(SQLite::Database& db, const std::vector& primary_key_values) const; void init(const Psc::JSON* that_json) { - External_Resources_Data::from_base_json(that_json); + External_Resources_Data::from_base_json(that_json, false); } [[nodiscard]] Psc::JSON to_json() const { return External_Resources_Data::to_base_json(); @@ -65,63 +65,76 @@ public: std::string cache_file_name; protected: [[nodiscard]] virtual std::filesystem::path source_file(const std::filesystem::path& cache_pos) const; - virtual bool fetch(const std::filesystem::path& cache_pos, - bool force_download) const; - virtual std::size_t import_file(SQLite::Database& db, - const std::filesystem::path& source_file) const = 0; + virtual bool fetch(const std::filesystem::path& cache_pos, bool force_download) const; + virtual std::size_t import_file(SQLite::Database& db, const std::filesystem::path& source_file) const = 0; [[nodiscard]] virtual const std::vector& primary_key_columns() const = 0; void mark_updated(); void clear_last_updated_at(); }; class External_Resources_Manager { public: - using Status_Callback = - std::function; - using Status_List_Callback = std::function)>; - using Row_Callback = std::function)>; - using Row_Map_Callback = - std::function; + using Status_Callback = std::function; + using Status_List_Callback = std::function)>; + using Row_Callback = std::function)>; + using Row_Map_Callback = std::function; External_Resources_Manager(); - void init(const Psc::JSON* that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; void server(Global* g); void load_sqlite_db(std::string_view path); std::vector refresh_external_databases(bool force_download = true); External_Resource_Status refresh_external_database(std::string_view resource_name, bool force_download = true); - External_Resource_Status import_external_database(std::string_view resource_name, const std::filesystem::path& source_file); + External_Resource_Status import_external_database(std::string_view resource_name, + const std::filesystem::path& source_file); External_Resource_Status clear_external_database_table(std::string_view resource_name); - [[nodiscard]] std::optional query_external_database(std::string_view resource_name, const std::vector& primary_key_values) const; - [[nodiscard]] std::map> query_aircraft_external_databases(std::string_view icao24) const; - [[nodiscard]] std::map> query_callsign_external_databases(const std::optional& callsign) const; + [[nodiscard]] std::optional + query_external_database(std::string_view resource_name, const std::vector& primary_key_values) const; + [[nodiscard]] std::map> + query_aircraft_external_databases(std::string_view icao24) const; + [[nodiscard]] std::map> + query_callsign_external_databases(const std::optional& callsign) const; [[nodiscard]] std::vector external_database_status() const; void async_refresh_external_databases(bool force_download, Status_List_Callback callback); void async_refresh_external_database(std::string_view resource_name, bool force_download, Status_Callback callback); - void async_import_external_database(std::string_view resource_name, std::filesystem::path source_file, Status_Callback callback); + void async_import_external_database(std::string_view resource_name, std::filesystem::path source_file, + Status_Callback callback); void async_clear_external_database_table(std::string_view resource_name, Status_Callback callback); - void async_query_external_database(std::string_view resource_name, std::vector primary_key_values, Row_Callback callback) const; + void async_query_external_database(std::string_view resource_name, std::vector primary_key_values, + Row_Callback callback) const; void async_query_aircraft_external_databases(std::string_view icao24, Row_Map_Callback callback) const; void async_query_callsign_external_databases(std::optional callsign, Row_Map_Callback callback) const; void async_external_database_status(Status_List_Callback callback) const; - [[nodiscard]] asio::awaitable> refresh_external_databases_coro(bool force_download = true); - [[nodiscard]] asio::awaitable refresh_external_database_coro(std::string_view resource_name, bool force_download = true); - [[nodiscard]] asio::awaitable import_external_database_coro(std::string_view resource_name, std::filesystem::path source_file); - [[nodiscard]] asio::awaitable clear_external_database_table_coro(std::string_view resource_name); - [[nodiscard]] asio::awaitable> query_external_database_coro(std::string_view resource_name, std::vector primary_key_values) const; - [[nodiscard]] asio::awaitable> query_aircraft_external_databases_coro(std::string_view icao24) const; - [[nodiscard]] asio::awaitable> query_callsign_external_databases_coro(std::optional callsign) const; + [[nodiscard]] asio::awaitable> + refresh_external_databases_coro(bool force_download = true); + [[nodiscard]] asio::awaitable + refresh_external_database_coro(std::string_view resource_name, bool force_download = true); + [[nodiscard]] asio::awaitable + import_external_database_coro(std::string_view resource_name, std::filesystem::path source_file); + [[nodiscard]] asio::awaitable + clear_external_database_table_coro(std::string_view resource_name); + [[nodiscard]] asio::awaitable> + query_external_database_coro(std::string_view resource_name, std::vector primary_key_values) const; + [[nodiscard]] asio::awaitable> + query_aircraft_external_databases_coro(std::string_view icao24) const; + [[nodiscard]] asio::awaitable> + query_callsign_external_databases_coro(std::optional callsign) const; [[nodiscard]] asio::awaitable> external_database_status_coro() const; void register_external_resource(std::unique_ptr external_res); void initialize(SQLite::Database& db, std::filesystem::path cache_pos); std::vector sync_missing(SQLite::Database& db); std::vector refresh_all(SQLite::Database& db, bool force_download = true); - External_Resource_Status refresh_one(SQLite::Database& db, std::string_view resource_name, bool force_download = true); - External_Resource_Status import_offline(SQLite::Database& db, std::string_view resource_name, const std::filesystem::path& source_file); + External_Resource_Status refresh_one(SQLite::Database& db, std::string_view resource_name, + bool force_download = true); + External_Resource_Status import_offline(SQLite::Database& db, std::string_view resource_name, + const std::filesystem::path& source_file); External_Resource_Status clear_table(SQLite::Database& db, std::string_view resource_name); - [[nodiscard]] std::optional query_one(SQLite::Database& db, std::string_view resource_name, const std::vector& primary_key_values) const; - [[nodiscard]] std::map> query_aircraft(SQLite::Database& db, std::string_view icao24) const; - [[nodiscard]] std::map> query_callsign(SQLite::Database& db, const std::optional& callsign) const; + [[nodiscard]] std::optional + query_one(SQLite::Database& db, std::string_view resource_name, + const std::vector& primary_key_values) const; + [[nodiscard]] std::map> + query_aircraft(SQLite::Database& db, std::string_view icao24) const; + [[nodiscard]] std::map> + query_callsign(SQLite::Database& db, const std::optional& callsign) const; [[nodiscard]] std::vector status(SQLite::Database& db) const; std::string ecap_sqlite_path; std::filesystem::path cache_pos_; diff --git a/module/Local_Server/server/Config.cpp b/module/Local_Server/server/Config.cpp index 2495e6f..fc56ffe 100644 --- a/module/Local_Server/server/Config.cpp +++ b/module/Local_Server/server/Config.cpp @@ -1,697 +1,579 @@ #include "Config.h" -#include "Core/Base/Check.h" -#include "Core/Net_Adapter/Net_Adapter.h" -#include "Global.h" #include #include #include #include +#include "Core/Base/Check.h" +#include "Core/Net_Adapter/Net_Adapter.h" +#include "Global.h" #undef interface - std::string default_config_path; - std::string get_config_path() { - // #ifdef WIN32 - // get_exe_dir() - // return "D:/ae/proj/projects/ECAP_Server/config/config.json"; - // #endif - static bool first = true; - if (!default_config_path.empty()) - return default_config_path; - std::string ret; - std::ostringstream oss; - std::string file_name = "config.json"; - ret = get_exe_dir() + "/" + file_name; - if (first) { - std::cout << oss.str() << std::endl; - first = false; - } - return ret; + // #ifdef WIN32 + // get_exe_dir() + // return "D:/ae/proj/projects/ECAP_Server/config/config.json"; + // #endif + static bool first = true; + if (!default_config_path.empty()) + return default_config_path; + std::string ret; + std::ostringstream oss; + std::string file_name = "config.json"; + ret = get_exe_dir() + "/" + file_name; + if (first) { + std::cout << oss.str() << std::endl; + first = false; + } + return ret; } static std::vector read_string_array(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr || field->valueType != Psc::Array) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - std::vector ret; - ret.reserve(field->children.size()); - for (const auto& child : field->children) { - if (child.valueType != Psc::String) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + auto field = json->get(key); + if (field == nullptr || field->valueType != Psc::Array) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } - ret.emplace_back(child.val); - } - return ret; + std::vector ret; + ret.reserve(field->children.size()); + for (const auto& child : field->children) { + if (child.valueType != Psc::String) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + ret.emplace_back(child.val); + } + return ret; } static std::vector read_optional_string_array(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr) { - return {}; - } - if (field->valueType != Psc::Array) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - std::vector ret; - ret.reserve(field->children.size()); - for (const auto& child : field->children) { - if (child.valueType != Psc::String) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + auto field = json->get(key); + if (field == nullptr) { + return {}; } - ret.emplace_back(child.val); - } - return ret; + if (field->valueType != Psc::Array) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + std::vector ret; + ret.reserve(field->children.size()); + for (const auto& child : field->children) { + if (child.valueType != Psc::String) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + ret.emplace_back(child.val); + } + return ret; } static Psc::JSON write_string_array(std::string_view key, const std::vector& list) { - auto array = Psc::JSON::array(); - for (const auto& path : list) { - array.append(Psc::JSON(path)); - } - return Psc::JSON(key, array); + auto array = Psc::JSON::array(); + for (const auto& path : list) { + array.append(Psc::JSON(path)); + } + return Psc::JSON(key, array); } static const std::pair kDefaultAircraftModelUrls[] = { - {"no_category_information", "/ui/model/aircraft-no-category-information.glb"}, - {"surface_emergency_vehicle", "/ui/model/aircraft-surface-emergency-vehicle.glb"}, - {"surface_service_vehicle", "/ui/model/aircraft-surface-service-vehicle.glb"}, - {"ground_obstruction_4", "/ui/model/aircraft-ground-obstruction-4.glb"}, - {"ground_obstruction_5", "/ui/model/aircraft-ground-obstruction-5.glb"}, - {"ground_obstruction_6", "/ui/model/aircraft-ground-obstruction-6.glb"}, - {"ground_obstruction_7", "/ui/model/aircraft-ground-obstruction-7.glb"}, - {"glider", "/ui/model/aircraft-glider.glb"}, - {"lighter_than_air", "/ui/model/aircraft-lighter-than-air.glb"}, - {"parachutist", "/ui/model/aircraft-parachutist.glb"}, - {"ultralight_hangglider_paraglider", "/ui/model/aircraft-ultralight-hangglider-paraglider.glb"}, - {"reserved_3_5", "/ui/model/aircraft-reserved-3-5.glb"}, - {"unmanned_aerial_vehicle", "/ui/model/aircraft-unmanned-aerial-vehicle.glb"}, - {"space_transatmospheric_vehicle", "/ui/model/aircraft-space-transatmospheric-vehicle.glb"}, - {"light_aircraft", "/ui/model/aircraft-light-aircraft.glb"}, - {"medium_1_aircraft", "/ui/model/aircraft-medium-1-aircraft.glb"}, - {"medium_2_aircraft", "/ui/model/aircraft-medium-2-aircraft.glb"}, - {"high_vortex_aircraft", "/ui/model/aircraft-high-vortex-aircraft.glb"}, - {"heavy_aircraft", "/ui/model/aircraft-heavy-aircraft.glb"}, - {"high_performance_aircraft", "/ui/model/aircraft-high-performance-aircraft.glb"}, - {"rotorcraft", "/ui/model/aircraft-rotorcraft.glb"} -}; +{"no_category_information", "/ui/model/aircraft-no-category-information.glb"}, +{"surface_emergency_vehicle", "/ui/model/aircraft-surface-emergency-vehicle.glb"}, +{"surface_service_vehicle", "/ui/model/aircraft-surface-service-vehicle.glb"}, +{"ground_obstruction_4", "/ui/model/aircraft-ground-obstruction-4.glb"}, +{"ground_obstruction_5", "/ui/model/aircraft-ground-obstruction-5.glb"}, +{"ground_obstruction_6", "/ui/model/aircraft-ground-obstruction-6.glb"}, +{"ground_obstruction_7", "/ui/model/aircraft-ground-obstruction-7.glb"}, +{"glider", "/ui/model/aircraft-glider.glb"}, +{"lighter_than_air", "/ui/model/aircraft-lighter-than-air.glb"}, +{"parachutist", "/ui/model/aircraft-parachutist.glb"}, +{"ultralight_hangglider_paraglider", "/ui/model/aircraft-ultralight-hangglider-paraglider.glb"}, +{"reserved_3_5", "/ui/model/aircraft-reserved-3-5.glb"}, +{"unmanned_aerial_vehicle", "/ui/model/aircraft-unmanned-aerial-vehicle.glb"}, +{"space_transatmospheric_vehicle", "/ui/model/aircraft-space-transatmospheric-vehicle.glb"}, +{"light_aircraft", "/ui/model/aircraft-light-aircraft.glb"}, +{"medium_1_aircraft", "/ui/model/aircraft-medium-1-aircraft.glb"}, +{"medium_2_aircraft", "/ui/model/aircraft-medium-2-aircraft.glb"}, +{"high_vortex_aircraft", "/ui/model/aircraft-high-vortex-aircraft.glb"}, +{"heavy_aircraft", "/ui/model/aircraft-heavy-aircraft.glb"}, +{"high_performance_aircraft", "/ui/model/aircraft-high-performance-aircraft.glb"}, +{"rotorcraft", "/ui/model/aircraft-rotorcraft.glb"}}; static std::map make_default_aircraft_models() { - std::map ret; - for (const auto& item : kDefaultAircraftModelUrls) { - ret.emplace(std::string(item.first), Map_Model_Item_Config{std::string(item.second), 50.0, -90.0, 0.0, 0.0}); - } - return ret; -} -static std::map read_optional_model_object_field(const Psc::JSON* json, std::string_view key, std::map fallback) { - auto field = json->get(key); - if (field == nullptr) { - return fallback; - } - if (field->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - for (const auto& child : field->children) { - if (child.valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + std::map ret; + for (const auto& item : kDefaultAircraftModelUrls) { + ret.emplace(std::string(item.first), Map_Model_Item_Config{std::string(item.second), 50.0, -90.0, 0.0, 0.0}); } - fallback[child.key].from_base_json(&child); - } - return fallback; + return ret; +} +static std::map +read_optional_model_object_field(const Psc::JSON* json, std::string_view key, + std::map fallback, + bool not_exist_use_default_value) { + auto field = json->get(key); + if (field == nullptr) { + return fallback; + } + if (field->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + for (const auto& child : field->children) { + if (child.valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + fallback[child.key].from_base_json(&child, not_exist_use_default_value); + } + return fallback; } static Psc::JSON write_model_object(std::string_view key, const std::map& values) { - auto object = Psc::JSON::object(); - for (const auto& item : values) { - object.append({item.first, item.second.to_base_json()}); - } - return Psc::JSON(key, object); -} -static std::string read_string_field(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr || field->valueType != Psc::String) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->val; -} -static std::uint32_t read_uint32_field(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr || field->valueType != Psc::Number) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->number_val(); + auto object = Psc::JSON::object(); + for (const auto& item : values) { + object.append({item.first, item.second.to_base_json()}); + } + return Psc::JSON(key, object); } static std::string read_optional_string_field(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr) { - return {}; - } - if (field->valueType != Psc::String) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->val; + auto field = json->get(key); + if (field == nullptr) { + return {}; + } + if (field->valueType != Psc::String) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + return field->val; } static std::string read_optional_string_field(const Psc::JSON* json, std::string_view key, std::string_view fallback) { - auto field = json->get(key); - if (field == nullptr) { - return std::string(fallback); - } - if (field->valueType != Psc::String) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->val; -} -static bool read_optional_bool_field(const Psc::JSON* json, std::string_view key, bool fallback) { - auto field = json->get(key); - if (field == nullptr) { - return fallback; - } - if (field->valueType != Psc::Bool) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->bool_val(); + auto field = json->get(key); + if (field == nullptr) { + return std::string(fallback); + } + if (field->valueType != Psc::String) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + return field->val; } static std::uint32_t read_optional_uint32_field(const Psc::JSON* json, std::string_view key, std::uint32_t fallback) { - auto field = json->get(key); - if (field == nullptr) { - return fallback; - } - if (field->valueType != Psc::Number) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->number_val(); + auto field = json->get(key); + if (field == nullptr) { + return fallback; + } + if (field->valueType != Psc::Number) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + return field->number_val(); } static double read_optional_double_field(const Psc::JSON* json, std::string_view key, double fallback) { - auto field = json->get(key); - if (field == nullptr) { - return fallback; - } - if (field->valueType != Psc::Number) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - return field->number_val(); + auto field = json->get(key); + if (field == nullptr) { + return fallback; + } + if (field->valueType != Psc::Number) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + return field->number_val(); } -void Map_Tile_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr || that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map tile config"); - } - file_format = read_optional_string_field(that_json, "file_format", "directory"); - directories = read_optional_string_array(that_json, "directories"); - files = read_optional_string_array(that_json, "files"); - path_layout = read_string_field(that_json, "path_layout"); - y_axis = read_string_field(that_json, "y_axis"); - projection = read_string_field(that_json, "projection"); - extension = read_string_field(that_json, "extension"); - tile_size = read_uint32_field(that_json, "tile_size"); - minimum_level = read_uint32_field(that_json, "minimum_level"); - maximum_level = read_uint32_field(that_json, "maximum_level"); - encoding = read_optional_string_field(that_json, "encoding"); +void Map_Tile_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr || that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map tile config"); + } + Map_Tile_Config_Data::from_base_json(that_json, not_exist_use_default_value); + directories = read_optional_string_array(that_json, "directories"); + files = read_optional_string_array(that_json, "files"); + encoding = read_optional_string_field(that_json, "encoding"); } Psc::JSON Map_Tile_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"file_format", file_format}); - ret.append(write_string_array("directories", directories)); - ret.append(write_string_array("files", files)); - ret.append({"path_layout", path_layout}); - ret.append({"y_axis", y_axis}); - ret.append({"projection", projection}); - ret.append({"extension", extension}); - ret.append({"tile_size", tile_size}); - ret.append({"minimum_level", minimum_level}); - ret.append({"maximum_level", maximum_level}); - if (!encoding.empty()) { - ret.append({"encoding", encoding}); - } - return ret; + auto ret = Map_Tile_Config_Data::to_base_json(); + ret.append(write_string_array("directories", directories)); + ret.append(write_string_array("files", files)); + if (!encoding.empty()) { + ret.append({"encoding", encoding}); + } + return ret; } Psc::JSON Map_Tile_Config::to_public_json(std::string_view url) const { - auto ret = Psc::JSON::object(); - ret.append({"url", std::string(url)}); - ret.append({"minimum_level", minimum_level}); - ret.append({"maximum_level", maximum_level}); - ret.append({"tile_size", tile_size}); - ret.append({"projection", projection}); - ret.append({"y_axis", y_axis}); - if (!encoding.empty()) { - ret.append({"encoding", encoding}); - } - return ret; + auto ret = Psc::JSON::object(); + ret.append({"url", std::string(url)}); + ret.append({"minimum_level", minimum_level}); + ret.append({"maximum_level", maximum_level}); + ret.append({"tile_size", tile_size}); + ret.append({"projection", Psc::to_string(projection)}); + ret.append({"y_axis", Psc::to_string(y_axis)}); + if (!encoding.empty()) { + ret.append({"encoding", encoding}); + } + return ret; } -void Map_Tile_Source_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr || that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map tile source config"); - } - key = read_string_field(that_json, "key"); - name = read_string_field(that_json, "name"); - tile_type = read_optional_string_field(that_json, "tile_type", "imagery"); - request_method = read_optional_string_field(that_json, "request_method", "GET"); - url = read_optional_string_field(that_json, "url"); - resource.from_base_json(that_json->get("resource")); +void Map_Tile_Source_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr || that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map tile source config"); + } + Map_Tile_Source_Config_Data::from_base_json(that_json, not_exist_use_default_value); + url = read_optional_string_field(that_json, "url"); + resource.from_base_json(that_json->get("resource"), not_exist_use_default_value); } Psc::JSON Map_Tile_Source_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"key", key}); - ret.append({"name", name}); - ret.append({"tile_type", tile_type}); - ret.append({"request_method", request_method}); - if (!url.empty()) { - ret.append({"url", url}); - } - ret.append({"resource", resource.to_base_json()}); - return ret; + auto ret = Map_Tile_Source_Config_Data::to_base_json(); + if (!url.empty()) { + ret.append({"url", url}); + } + ret.append({"resource", resource.to_base_json()}); + return ret; } Psc::JSON Map_Tile_Source_Config::to_public_json(std::string_view local_url) const { - auto ret = Psc::JSON::object(); - ret.append({"key", key}); - ret.append({"name", name}); - ret.append({"tile_type", tile_type}); - ret.append({"request_method", request_method}); - ret.append({"resource", resource.to_public_json(local() ? local_url : url)}); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"key", key}); + ret.append({"name", name}); + ret.append({"tile_type", Psc::to_string(tile_type)}); + ret.append({"request_method", Psc::to_string(request_method)}); + ret.append({"resource", resource.to_public_json(local() ? local_url : url)}); + return ret; } -static std::vector read_optional_tile_source_array(const Psc::JSON* json, std::string_view key) { - auto field = json->get(key); - if (field == nullptr) { - return {}; - } - if (field->valueType != Psc::Array) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); - } - std::vector ret; - ret.reserve(field->children.size()); - for (const auto& child : field->children) { - Map_Tile_Source_Config item; - item.from_base_json(&child); - ret.push_back(std::move(item)); - } - return ret; +static std::vector read_optional_tile_source_array(const Psc::JSON* json, std::string_view key, + bool not_exist_use_default_value) { + auto field = json->get(key); + if (field == nullptr) { + return {}; + } + if (field->valueType != Psc::Array) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); + } + std::vector ret; + ret.reserve(field->children.size()); + for (const auto& child : field->children) { + Map_Tile_Source_Config item; + item.from_base_json(&child, not_exist_use_default_value); + ret.push_back(std::move(item)); + } + return ret; } static Psc::JSON write_tile_source_array(std::string_view key, const std::vector& list) { - auto array = Psc::JSON::array(); - for (const auto& source : list) { - array.append(source.to_base_json()); - } - return Psc::JSON(key, array); + auto array = Psc::JSON::array(); + for (const auto& source : list) { + array.append(source.to_base_json()); + } + return Psc::JSON(key, array); } -void Map_Resources_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr || that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_resources"); - } - current_imagery_key = read_optional_string_field(that_json, "current_imagery_key"); - if (current_imagery_key.empty()) { - current_imagery_key = "imagery"; - } - tile_sources = read_optional_tile_source_array(that_json, "tile_sources"); - if (!is_imagery_key(current_imagery_key)) { - auto source = std::ranges::find_if(tile_sources, [](const Map_Tile_Source_Config& item) { - return item.tile_type == "imagery"; - }); - current_imagery_key = source == tile_sources.end() ? "" : source->key; - } +void Map_Resources_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr || that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_resources"); + } + current_imagery_key = read_optional_string_field(that_json, "current_imagery_key"); + if (current_imagery_key.empty()) { + current_imagery_key = "imagery"; + } + tile_sources = read_optional_tile_source_array(that_json, "tile_sources", not_exist_use_default_value); + if (!is_imagery_key(current_imagery_key)) { + auto source = std::ranges::find_if( + tile_sources, [](const Map_Tile_Source_Config& item) { return item.tile_type == Map_Tile_Type::imagery; }); + current_imagery_key = source == tile_sources.end() ? "" : source->key; + } } Psc::JSON Map_Resources_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"current_imagery_key", current_imagery_key}); - ret.append(write_tile_source_array("tile_sources", tile_sources)); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"current_imagery_key", current_imagery_key}); + ret.append(write_tile_source_array("tile_sources", tile_sources)); + return ret; } Psc::JSON Map_Resources_Config::to_public_json() const { - auto ret = Psc::JSON::object(); - auto sources = Psc::JSON::array(); - auto imagery_sources = Psc::JSON::array(); - auto terrain_sources = Psc::JSON::array(); - auto terrain = Psc::JSON::object(); - bool has_terrain = false; - for (const auto& source : tile_sources) { - auto url = "/map/tile_sources/" + source.key + "/{z}/{x}/{y}"; - auto public_source = source.to_public_json(url); - sources.append(public_source); - if (source.tile_type == "imagery") { - imagery_sources.append(public_source); + auto ret = Psc::JSON::object(); + auto sources = Psc::JSON::array(); + auto imagery_sources = Psc::JSON::array(); + auto terrain_sources = Psc::JSON::array(); + auto terrain = Psc::JSON::object(); + bool has_terrain = false; + for (const auto& source : tile_sources) { + auto url = "/map/tile_sources/" + source.key + "/{z}/{x}/{y}"; + auto public_source = source.to_public_json(url); + sources.append(public_source); + if (source.tile_type == Map_Tile_Type::imagery) { + imagery_sources.append(public_source); + } + else if (source.tile_type == Map_Tile_Type::terrain) { + terrain_sources.append(public_source); + if (!has_terrain) { + terrain = *public_source.get("resource"); + has_terrain = true; + } + } } - else if (source.tile_type == "terrain") { - terrain_sources.append(public_source); - if (!has_terrain) { - terrain = *public_source.get("resource"); - has_terrain = true; - } + ret.append({"current_imagery_key", current_imagery_key}); + ret.append({"tile_sources", sources}); + ret.append({"imagery_sources", imagery_sources}); + ret.append({"terrain_sources", terrain_sources}); + if (has_terrain) { + ret.append({"terrain", std::move(terrain)}); } - } - ret.append({"current_imagery_key", current_imagery_key}); - ret.append({"tile_sources", sources}); - ret.append({"imagery_sources", imagery_sources}); - ret.append({"terrain_sources", terrain_sources}); - if (has_terrain) { - ret.append({"terrain", std::move(terrain)}); - } - return ret; + return ret; } bool Map_Resources_Config::is_imagery_key(std::string_view key) const { - return std::ranges::any_of(tile_sources, [key](const Map_Tile_Source_Config& source) { - return source.tile_type == "imagery" && source.key == key; - }); + return std::ranges::any_of(tile_sources, [key](const Map_Tile_Source_Config& source) { + return source.tile_type == Map_Tile_Type::imagery && source.key == key; + }); } -void Map_Camera_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr) { - return; - } - if (that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map camera"); - } - longitude = read_optional_double_field(that_json, "longitude", longitude); - latitude = read_optional_double_field(that_json, "latitude", latitude); - height = read_optional_double_field(that_json, "height", height); - heading = read_optional_double_field(that_json, "heading", heading); - pitch = read_optional_double_field(that_json, "pitch", pitch); - roll = read_optional_double_field(that_json, "roll", roll); -} -Psc::JSON Map_Camera_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"longitude", longitude}); - ret.append({"latitude", latitude}); - ret.append({"height", height}); - ret.append({"heading", heading}); - ret.append({"pitch", pitch}); - ret.append({"roll", roll}); - return ret; +bool Map_Resources_Config::is_terrain_key(std::string_view key) const { + return std::ranges::any_of(tile_sources, [key](const Map_Tile_Source_Config& source) { + return source.tile_type == Map_Tile_Type::terrain && source.key == key; + }); } bool Map_View_Config::is_scene_mode(std::string_view mode) { - return mode == "2d" || mode == "2.5d" || mode == "3d"; + return mode == "2d" || mode == "2.5d" || mode == "3d"; } -bool Map_Tile_View_Config::is_tile_zoom_mode(std::string_view mode) { - return mode == "native" || mode == "upscale" || mode == "both"; -} -void Map_Tile_View_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr) { - return; - } - if (that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_tile_view"); - } - current_imagery_key = read_optional_string_field(that_json, "current_imagery_key", current_imagery_key); - auto next_tile_zoom_mode = read_optional_string_field(that_json, "tile_zoom_mode", tile_zoom_mode); - if (!is_tile_zoom_mode(next_tile_zoom_mode)) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "tile_zoom_mode"); - } - tile_zoom_mode = next_tile_zoom_mode; - tile_display_maximum_level = std::clamp(read_optional_uint32_field(that_json, "tile_display_maximum_level", tile_display_maximum_level), 0u, 24u); +void Map_Tile_View_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr) { + return; + } + if (that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_tile_view"); + } + current_imagery_key = read_optional_string_field(that_json, "current_imagery_key", current_imagery_key); + current_terrain_key = read_optional_string_field(that_json, "current_terrain_key", current_terrain_key); + tile_zoom_mode = Psc::to_enum( + read_optional_string_field(that_json, "tile_zoom_mode", Psc::to_string(tile_zoom_mode))); + tile_display_maximum_level = std::clamp( + read_optional_uint32_field(that_json, "tile_display_maximum_level", tile_display_maximum_level), 0u, 24u); } Psc::JSON Map_Tile_View_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"current_imagery_key", current_imagery_key}); - ret.append({"tile_zoom_mode", tile_zoom_mode}); - ret.append({"tile_display_maximum_level", tile_display_maximum_level}); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"current_imagery_key", current_imagery_key}); + ret.append({"current_terrain_key", current_terrain_key}); + ret.append({"tile_zoom_mode", Psc::to_string(tile_zoom_mode)}); + ret.append({"tile_display_maximum_level", tile_display_maximum_level}); + return ret; } -void Map_View_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr) { - return; - } - if (that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_view"); - } - auto next_scene_mode = read_optional_string_field(that_json, "scene_mode", scene_mode); - if (!is_scene_mode(next_scene_mode)) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "scene_mode"); - } - scene_mode = next_scene_mode; - map2d.from_base_json(that_json->get("map2d")); - map3d.from_base_json(that_json->get("map3d")); - camera.from_base_json(that_json->get("camera")); - base_station_fly_to_height_offset_meters = std::max(100.0, read_optional_double_field(that_json, "baseStationFlyToHeightOffsetMeters", base_station_fly_to_height_offset_meters)); +void Map_View_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr) { + return; + } + if (that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_view"); + } + auto next_scene_mode = read_optional_string_field(that_json, "scene_mode", scene_mode); + if (!is_scene_mode(next_scene_mode)) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "scene_mode"); + } + scene_mode = next_scene_mode; + map2d.from_base_json(that_json->get("map2d"), not_exist_use_default_value); + map3d.from_base_json(that_json->get("map3d"), not_exist_use_default_value); + camera.from_base_json(that_json->get("camera"), not_exist_use_default_value); + base_station_fly_to_height_offset_meters = + std::max(100.0, + read_optional_double_field(that_json, "baseStationFlyToHeightOffsetMeters", + base_station_fly_to_height_offset_meters)); } Psc::JSON Map_View_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"scene_mode", scene_mode}); - ret.append({"map2d", map2d.to_base_json()}); - ret.append({"map3d", map3d.to_base_json()}); - ret.append({"camera", camera.to_base_json()}); - ret.append({"baseStationFlyToHeightOffsetMeters", base_station_fly_to_height_offset_meters}); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"scene_mode", scene_mode}); + ret.append({"map2d", map2d.to_base_json()}); + ret.append({"map3d", map3d.to_base_json()}); + ret.append({"camera", camera.to_base_json()}); + ret.append({"baseStationFlyToHeightOffsetMeters", base_station_fly_to_height_offset_meters}); + return ret; } -void Cesium_Graphics_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr) { - return; - } - if (that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "cesium_graphics"); - } - debug_show_frames_per_second = read_optional_bool_field(that_json, "debug_show_frames_per_second", debug_show_frames_per_second); - target_frame_rate = std::clamp(read_optional_uint32_field(that_json, "target_frame_rate", target_frame_rate), 1u, 120u); - use_browser_recommended_resolution = read_optional_bool_field(that_json, "use_browser_recommended_resolution", use_browser_recommended_resolution); - resolution_scale = std::clamp(read_optional_double_field(that_json, "resolution_scale", resolution_scale), 0.2, 1.5); - msaa_samples = std::clamp(read_optional_uint32_field(that_json, "msaa_samples", msaa_samples), 1u, 8u); - fxaa = read_optional_bool_field(that_json, "fxaa", fxaa); - shadows = read_optional_bool_field(that_json, "shadows", shadows); - enable_lighting = read_optional_bool_field(that_json, "enable_lighting", enable_lighting); - solar_lighting = read_optional_bool_field(that_json, "solar_lighting", solar_lighting); - solar_light_intensity = read_optional_double_field(that_json, "solar_light_intensity", solar_light_intensity); - maximum_screen_space_error = std::clamp(read_optional_uint32_field(that_json, "maximum_screen_space_error", maximum_screen_space_error), 1u, 16u); - terrain_enabled_in_3d = read_optional_bool_field(that_json, "terrain_enabled_in_3d", terrain_enabled_in_3d); - terrain_exaggeration = read_optional_double_field(that_json, "terrain_exaggeration", terrain_exaggeration); - terrain_limit_maximum_level = read_optional_bool_field(that_json, "terrain_limit_maximum_level", terrain_limit_maximum_level); - terrain_maximum_level = std::clamp(read_optional_uint32_field(that_json, "terrain_maximum_level", terrain_maximum_level), 0u, 24u); - terrain_cache_tiles = std::clamp(read_optional_uint32_field(that_json, "terrain_cache_tiles", terrain_cache_tiles), 16u, 2048u); - terrain_occlusion_enabled = read_optional_bool_field(that_json, "terrain_occlusion_enabled", terrain_occlusion_enabled); - surface_navigation_reference_visible = read_optional_bool_field(that_json, "surface_navigation_reference_visible", surface_navigation_reference_visible); - view_axes_visible = read_optional_bool_field(that_json, "view_axes_visible", view_axes_visible); - performance_panel_x = std::max(0.0, read_optional_double_field(that_json, "performance_panel_x", performance_panel_x)); - performance_panel_y = std::max(0.0, read_optional_double_field(that_json, "performance_panel_y", performance_panel_y)); - view_axes_panel_x = read_optional_double_field(that_json, "view_axes_panel_x", view_axes_panel_x); - view_axes_panel_y = std::max(0.0, read_optional_double_field(that_json, "view_axes_panel_y", view_axes_panel_y)); - view_axes_panel_size = std::clamp(read_optional_double_field(that_json, "view_axes_panel_size", view_axes_panel_size), 48.0, 240.0); - occlusion_sample_spacing_meters = std::clamp(read_optional_double_field(that_json, "occlusion_sample_spacing_meters", occlusion_sample_spacing_meters), 10.0, 5000.0); - occlusion_clearance_margin_meters = read_optional_double_field(that_json, "occlusion_clearance_margin_meters", occlusion_clearance_margin_meters); +void Cesium_Graphics_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr) { + return; + } + if (that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "cesium_graphics"); + } + Cesium_Graphics_Config_Data::from_base_json(that_json, not_exist_use_default_value); + target_frame_rate = std::clamp(target_frame_rate, 1u, 120u); + resolution_scale = std::clamp(resolution_scale, 0.2, 1.5); + msaa_samples = std::clamp(msaa_samples, 1u, 8u); + maximum_screen_space_error = std::clamp(maximum_screen_space_error, 1u, 16u); + terrain_maximum_level = std::clamp(terrain_maximum_level, 0u, 24u); + terrain_cache_tiles = std::clamp(terrain_cache_tiles, 16u, 2048u); + performance_panel_x = std::max(0.0, performance_panel_x); + performance_panel_y = std::max(0.0, performance_panel_y); + view_axes_panel_y = std::max(0.0, view_axes_panel_y); + view_axes_panel_size = std::clamp(view_axes_panel_size, 48.0, 240.0); + occlusion_sample_spacing_meters = std::clamp(occlusion_sample_spacing_meters, 10.0, 5000.0); } Psc::JSON Cesium_Graphics_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"debug_show_frames_per_second", debug_show_frames_per_second}); - ret.append({"target_frame_rate", target_frame_rate}); - ret.append({"use_browser_recommended_resolution", use_browser_recommended_resolution}); - ret.append({"resolution_scale", resolution_scale}); - ret.append({"msaa_samples", msaa_samples}); - ret.append({"fxaa", fxaa}); - ret.append({"shadows", shadows}); - ret.append({"enable_lighting", enable_lighting}); - ret.append({"solar_lighting", solar_lighting}); - ret.append({"solar_light_intensity", solar_light_intensity}); - ret.append({"maximum_screen_space_error", maximum_screen_space_error}); - ret.append({"terrain_enabled_in_3d", terrain_enabled_in_3d}); - ret.append({"terrain_exaggeration", terrain_exaggeration}); - ret.append({"terrain_limit_maximum_level", terrain_limit_maximum_level}); - ret.append({"terrain_maximum_level", terrain_maximum_level}); - ret.append({"terrain_cache_tiles", terrain_cache_tiles}); - ret.append({"terrain_occlusion_enabled", terrain_occlusion_enabled}); - ret.append({"surface_navigation_reference_visible", surface_navigation_reference_visible}); - ret.append({"view_axes_visible", view_axes_visible}); - ret.append({"performance_panel_x", performance_panel_x}); - ret.append({"performance_panel_y", performance_panel_y}); - if (view_axes_panel_x >= 0.0) { - ret.append({"view_axes_panel_x", view_axes_panel_x}); - } - ret.append({"view_axes_panel_y", view_axes_panel_y}); - ret.append({"view_axes_panel_size", view_axes_panel_size}); - ret.append({"occlusion_sample_spacing_meters", occlusion_sample_spacing_meters}); - ret.append({"occlusion_clearance_margin_meters", occlusion_clearance_margin_meters}); - return ret; + return Cesium_Graphics_Config_Data::to_base_json(); } -Map_Model_Item_Config::Map_Model_Item_Config(std::string url) - : url(std::move(url)) {} -Map_Model_Item_Config::Map_Model_Item_Config(std::string url, double built_in_size, double heading, double pitch, double roll) - : url(std::move(url)), built_in_size(built_in_size), heading_offset_degrees(heading), pitch_offset_degrees(pitch), roll_offset_degrees(roll) {} -void Map_Model_Item_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr || that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_model_item"); - } - url = read_optional_string_field(that_json, "url", url); - built_in_size = read_optional_double_field(that_json, "built_in_size", built_in_size); - heading_offset_degrees = read_optional_double_field(that_json, "heading_offset_degrees", heading_offset_degrees); - pitch_offset_degrees = read_optional_double_field(that_json, "pitch_offset_degrees", pitch_offset_degrees); - roll_offset_degrees = read_optional_double_field(that_json, "roll_offset_degrees", roll_offset_degrees); +Map_Model_Item_Config::Map_Model_Item_Config(std::string url) : url(std::move(url)) { +} +Map_Model_Item_Config::Map_Model_Item_Config(std::string url, double built_in_size, double heading, double pitch, + double roll) : + url(std::move(url)), built_in_size(built_in_size), heading_offset_degrees(heading), pitch_offset_degrees(pitch), + roll_offset_degrees(roll) { +} +void Map_Model_Item_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr || that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_model_item"); + } + url = read_optional_string_field(that_json, "url", url); + built_in_size = read_optional_double_field(that_json, "built_in_size", built_in_size); + heading_offset_degrees = read_optional_double_field(that_json, "heading_offset_degrees", heading_offset_degrees); + pitch_offset_degrees = read_optional_double_field(that_json, "pitch_offset_degrees", pitch_offset_degrees); + roll_offset_degrees = read_optional_double_field(that_json, "roll_offset_degrees", roll_offset_degrees); } Psc::JSON Map_Model_Item_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"url", url}); - ret.append({"built_in_size", built_in_size}); - ret.append({"heading_offset_degrees", heading_offset_degrees}); - ret.append({"pitch_offset_degrees", pitch_offset_degrees}); - ret.append({"roll_offset_degrees", roll_offset_degrees}); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"url", url}); + ret.append({"built_in_size", built_in_size}); + ret.append({"heading_offset_degrees", heading_offset_degrees}); + ret.append({"pitch_offset_degrees", pitch_offset_degrees}); + ret.append({"roll_offset_degrees", roll_offset_degrees}); + return ret; } -Map_Model_Config::Map_Model_Config() - : aircraft_models(make_default_aircraft_models()) {} -void Map_Model_Config::from_base_json(const Psc::JSON* that_json) { - if (that_json == nullptr) { - return; - } - if (that_json->valueType != Psc::Object) { - throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_models"); - } - aircraft_model.from_base_json(that_json->get("aircraft_model")); - aircraft_models = read_optional_model_object_field(that_json, "aircraft_models", make_default_aircraft_models()); - base_station_model.from_base_json(that_json->get("base_station_model")); - device_model.from_base_json(that_json->get("device_model")); +Map_Model_Config::Map_Model_Config() : aircraft_models(make_default_aircraft_models()) { +} +void Map_Model_Config::from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + if (that_json == nullptr) { + return; + } + if (that_json->valueType != Psc::Object) { + throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_models"); + } + aircraft_model.from_base_json(that_json->get("aircraft_model"), not_exist_use_default_value); + aircraft_models = read_optional_model_object_field(that_json, "aircraft_models", make_default_aircraft_models(), + not_exist_use_default_value); + base_station_model.from_base_json(that_json->get("base_station_model"), not_exist_use_default_value); + device_model.from_base_json(that_json->get("device_model"), not_exist_use_default_value); } Psc::JSON Map_Model_Config::to_base_json() const { - auto ret = Psc::JSON::object(); - ret.append({"aircraft_model", aircraft_model.to_base_json()}); - ret.append(write_model_object("aircraft_models", aircraft_models)); - ret.append({"base_station_model", base_station_model.to_base_json()}); - ret.append({"device_model", device_model.to_base_json()}); - return ret; + auto ret = Psc::JSON::object(); + ret.append({"aircraft_model", aircraft_model.to_base_json()}); + ret.append(write_model_object("aircraft_models", aircraft_models)); + ret.append({"base_station_model", base_station_model.to_base_json()}); + ret.append({"device_model", device_model.to_base_json()}); + return ret; } - -void Mode_ACS_Config::server(Global *g) { - auto &svr = g->svr; - auto &api = g->api; - data_source_config.server(g); - data_feed_config.server(g); - source_feed_relation_config.server(g); - - svr.Post(api + "get_mode_s_basic_config", [this](HTTP_Param) { - CHECK_JSON_PARAM - res->setBody(warp(to_base_json()).to_json_string()); - }); - svr.Post(api + "set_mode_s_basic_config", [this](HTTP_Param) { - CHECK_JSON_PARAM - auto &j = o_params.value(); - init_base_json(&j); - if (auto min_points = j.try_get_number("aircraft_change_list_min_position_points")) { - aircraft_change_list_min_position_points = min_points.value(); - } - if (auto range_filter = j.try_get_bool("aircraft_change_list_adsb_range_filter")) { - aircraft_change_list_adsb_range_filter = range_filter.value(); - } - if (auto range_factor = j.try_get_number("aircraft_change_list_adsb_range_factor")) { - aircraft_change_list_adsb_range_factor = range_factor.value(); - } - if (auto target_altitude = j.try_get_number("adsb_theoretical_target_altitude_meters")) { - adsb_theoretical_target_altitude_meters = target_altitude.value(); - } - Global::save(); - res->setBody(warp(to_base_json()).to_json_string()); - }); +void Mode_ACS_Config::server(Global* g) { + auto& svr = g->svr; + auto& api = g->api; + data_source_config.server(g); + data_feed_config.server(g); + source_feed_relation_config.server(g); + svr.Post(api + "get_mode_s_basic_config", [this](HTTP_Param) { + CHECK_JSON_PARAM + res->setBody(warp(to_base_json()).to_json_string()); + }); + svr.Post(api + "set_mode_s_basic_config", [this](HTTP_Param) { + CHECK_JSON_PARAM + auto& j = o_params.value(); + init_base_json(&j, false); + if (auto min_points = j.try_get_number("aircraft_change_list_min_position_points")) { + aircraft_change_list_min_position_points = min_points.value(); + } + if (auto range_filter = j.try_get_bool("aircraft_change_list_adsb_range_filter")) { + aircraft_change_list_adsb_range_filter = range_filter.value(); + } + if (auto range_factor = j.try_get_number("aircraft_change_list_adsb_range_factor")) { + aircraft_change_list_adsb_range_factor = range_factor.value(); + } + if (auto target_altitude = j.try_get_number("adsb_theoretical_target_altitude_meters")) { + adsb_theoretical_target_altitude_meters = target_altitude.value(); + } + Global::save(); + res->setBody(warp(to_base_json()).to_json_string()); + }); } - -void Device_Config::server(Global *g) { - auto &svr = g->svr; - auto &api = g->api; - svr.Post(api + "get_device_config", [this](HTTP_Param) { - res->setBody(warp(to_base_json()).to_json_string()); - }); - - svr.Post(api + "get_net_adapter_list", [this](HTTP_Param) { - JSON ret = JSON::object(); - auto arr = JSON::array(); - for (auto &it: Psc::get_net_adapter_info_map()) { - arr.append(it.second.to_Json()); - } - ret.append({"list", arr}); - res->setBody(warp(ret).to_json_string()); - }); - - svr.Post(api + "set_device_config", [this](HTTP_Param) { - CHECK_JSON_PARAM - JSON old_device_config; - { - old_device_config = to_base_json(); - } - HTTP_REQUIRE_PTR(net, params.get("net")) - Net_Config device, wifi; - bool has_device = false; - bool has_wifi = false; - for (const auto &it: net->children) { - HTTP_REQUIRE_VALUE(net_key, it.try_get_string("key")) - if (net_key == "device") { - device.from_base_json(&it); - has_device = true; - } - if (net_key == "wifi") { - wifi.from_base_json(&it); - has_wifi = true; - } - } - HTTP_REQUIRE_TRUE(has_device && has_wifi, "net") - - bool it1 = - check_ip_netmask_gateway(device.ip, device.netmask, device.gateway); - bool it2 = check_ip_netmask_gateway(wifi.ip, wifi.netmask, wifi.gateway); - bool p1 = check_port(device.port); - bool p2 = check_port(wifi.port); - if (!it1 || !it2 || !p1 || !p2) { - server_logger->error("", {}, - LOG_POS + " ip port! " + device.ip + ":" + - std::to_string(device.port)); - res->setBody(warp(old_device_config).to_json_string()); - return; - } - +void Device_Config::server(Global* g) { + auto& svr = g->svr; + auto& api = g->api; + svr.Post(api + "get_device_config", [this](HTTP_Param) { res->setBody(warp(to_base_json()).to_json_string()); }); + svr.Post(api + "get_net_adapter_list", [this](HTTP_Param) { + JSON ret = JSON::object(); + auto arr = JSON::array(); + for (auto& it : Psc::get_net_adapter_info_map()) { + arr.append(it.second.to_Json()); + } + ret.append({"list", arr}); + res->setBody(warp(ret).to_json_string()); + }); + svr.Post(api + "set_device_config", [this](HTTP_Param) { + CHECK_JSON_PARAM + JSON old_device_config; + { + old_device_config = to_base_json(); + } + HTTP_REQUIRE_PTR(net, params.get("net")) + Net_Config device, wifi; + bool has_device = false; + bool has_wifi = false; + for (const auto& it : net->children) { + HTTP_REQUIRE_VALUE(net_key, it.try_get_string("key")) + if (net_key == "device") { + device.from_base_json(&it, true); + has_device = true; + } + if (net_key == "wifi") { + wifi.from_base_json(&it, true); + has_wifi = true; + } + } + HTTP_REQUIRE_TRUE(has_device && has_wifi, "net") + bool it1 = check_ip_netmask_gateway(device.ip, device.netmask, device.gateway); + bool it2 = check_ip_netmask_gateway(wifi.ip, wifi.netmask, wifi.gateway); + bool p1 = check_port(device.port); + bool p2 = check_port(wifi.port); + if (!it1 || !it2 || !p1 || !p2) { + server_logger->error("", {}, LOG_POS + " ip port! " + device.ip + ":" + std::to_string(device.port)); + res->setBody(warp(old_device_config).to_json_string()); + return; + } #if WIN32 - bool use = false; + bool use = false; #else bool use = true; #endif - { - auto &w = *this; - *w.list.get("device").value() = device; - *w.list.get("wifi").value() = wifi; - } - Global::save(); - if (use) { - std::string interface; - { - std::string path = get_exe_dir() + "/interface"; - std::ifstream ifs(path); - if (!ifs.is_open()) { - server_logger->error("", {}, LOG_POS + " 无法打开文件! " + path); - res->setBody(warp(old_device_config).to_json_string()); - return; + { + auto& w = *this; + *w.list.get("device").value() = device; + *w.list.get("wifi").value() = wifi; } - std::stringstream buffer; - buffer << ifs.rdbuf(); - interface = buffer.str(); - } - static auto set = [](std::string &interface, std::string_view token, - std::string_view value) { - std::string var_name = "${" + std::string(token) + "}"; - auto size = var_name.size(); - size_t pos = interface.find(var_name); - while (pos != std::string::npos) { - interface.replace(pos, size, value); - pos = interface.find(var_name); + Global::save(); + if (use) { + std::string interface; + { + std::string path = get_exe_dir() + "/interface"; + std::ifstream ifs(path); + if (!ifs.is_open()) { + server_logger->error("", {}, LOG_POS + " 无法打开文件! " + path); + res->setBody(warp(old_device_config).to_json_string()); + return; + } + std::stringstream buffer; + buffer << ifs.rdbuf(); + interface = buffer.str(); + } + static auto set = [](std::string& interface, std::string_view token, std::string_view value) { + std::string var_name = "${" + std::string(token) + "}"; + auto size = var_name.size(); + size_t pos = interface.find(var_name); + while (pos != std::string::npos) { + interface.replace(pos, size, value); + pos = interface.find(var_name); + } + }; + set(interface, "ip", device.ip); + set(interface, "gateway", device.gateway); + set(interface, "netmask", device.netmask); + set(interface, "wifi_ip", wifi.ip); + set(interface, "wifi_gateway", wifi.gateway); + set(interface, "wifi_netmask", wifi.netmask); + std::cout << interface << std::endl; + std::string path = "/etc/network/interfaces"; + std::ofstream outfile(path); + if (!outfile.is_open()) { + server_logger->error("", {}, LOG_POS + " 无法打开文件!" + path); + res->setBody(warp(old_device_config).to_json_string()); + return; + } + outfile << interface; + outfile.close(); + std::string bash_path = get_exe_dir() + "/restart_net_service.sh"; + if (!std::filesystem::exists(bash_path)) { + server_logger->error("", {}, LOG_POS + " !" + bash_path); + res->setBody(warp(old_device_config).to_json_string()); + return; + } + int result = system(bash_path.c_str()); + if (result != 0) { + server_logger->error("", {}, LOG_POS + " 脚本执行失败!" + bash_path); + res->setBody(warp(old_device_config).to_json_string()); + return; + } } - }; - set(interface, "ip", device.ip); - set(interface, "gateway", device.gateway); - set(interface, "netmask", device.netmask); - set(interface, "wifi_ip", wifi.ip); - set(interface, "wifi_gateway", wifi.gateway); - set(interface, "wifi_netmask", wifi.netmask); - std::cout << interface << std::endl; - std::string path = "/etc/network/interfaces"; - std::ofstream outfile(path); - if (!outfile.is_open()) { - server_logger->error("", {}, LOG_POS + " 无法打开文件!" + path); - res->setBody(warp(old_device_config).to_json_string()); - return; - } - outfile << interface; - outfile.close(); - std::string bash_path = get_exe_dir() + "/restart_net_service.sh"; - if (!std::filesystem::exists(bash_path)) { - server_logger->error("", {}, LOG_POS + " !" + bash_path); - res->setBody(warp(old_device_config).to_json_string()); - return; - } - int result = system(bash_path.c_str()); - if (result != 0) { - server_logger->error("", {}, LOG_POS + " 脚本执行失败!" + bash_path); - res->setBody(warp(old_device_config).to_json_string()); - return; - } - } - res->setBody(warp(params).to_json_string()); - }); + res->setBody(warp(params).to_json_string()); + }); } - void Config::save() { - std::ofstream config_file; - config_file.open(get_config_path()); - std::string json = Global::instance()->toJson().to_json_string(); - config_file.write(json.c_str(), static_cast(json.size())); - config_file.close(); + std::ofstream config_file; + config_file.open(get_config_path()); + std::string json = Global::instance()->toJson().to_json_string(); + config_file.write(json.c_str(), static_cast(json.size())); + config_file.close(); } diff --git a/module/Local_Server/server/Config.h b/module/Local_Server/server/Config.h index 72d84b5..3093fba 100644 --- a/module/Local_Server/server/Config.h +++ b/module/Local_Server/server/Config.h @@ -1,14 +1,14 @@ #ifndef CONFIG_H_H #define CONFIG_H_H +#include +#include +#include #include "../DSP/export.h" #include "../Data_Feed/export.h" #include "../Data_Source/export.h" #include "Core/spdlog/export.h" #include "MLAT.h" #include "Source_Feed_Relation.h" -#include -#include -#include inline bool delete_log = false; extern std::string default_config_path; std::string get_config_path(); @@ -79,16 +79,15 @@ struct Mode_ACS_Config : Mode_ACS_Config_Base_Data, Mode_ACS_Config_Data { Psc::JSON to_base_json() const { return Mode_ACS_Config_Base_Data::to_base_json(); } - void init_base_json(const Psc::JSON* that_json) { - Mode_ACS_Config_Base_Data::from_base_json(that_json); + void init_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + Mode_ACS_Config_Base_Data::from_base_json(that_json, not_exist_use_default_value); } - void init(const Psc::JSON* that_json) { - Mode_ACS_Config_Base_Data::from_base_json(that_json); - Mode_ACS_Config_Data::from_base_json(that_json); - data_feed_config.init(that_json->get("data_feed")); - data_source_config.init(that_json->get("data_source")); - source_feed_relation_config.from_json( - that_json->get("source_feed_relation")); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + Mode_ACS_Config_Base_Data::from_base_json(that_json, not_exist_use_default_value); + Mode_ACS_Config_Data::from_base_json(that_json, not_exist_use_default_value); + data_feed_config.init(that_json->get("data_feed"), not_exist_use_default_value); + data_source_config.init(that_json->get("data_source"), not_exist_use_default_value); + source_feed_relation_config.from_json(that_json->get("source_feed_relation"), not_exist_use_default_value); if (monitor_msg_live) { SSR::Monitor_Mode_ACS_Message_Num = this->monitor_msg_live; } @@ -98,8 +97,7 @@ struct Mode_ACS_Config : Mode_ACS_Config_Base_Data, Mode_ACS_Config_Data { ret += Mode_ACS_Config_Data::to_base_json(); ret.append(Psc::JSON("data_feed", data_feed_config.to_json())); ret.append(Psc::JSON("data_source", data_source_config.to_json())); - ret.append(Psc::JSON("source_feed_relation", - source_feed_relation_config.to_json())); + ret.append(Psc::JSON("source_feed_relation", source_feed_relation_config.to_json())); return ret; } void server(Global* g); @@ -111,17 +109,26 @@ struct Web_Server_Config { PSC_USE_JSON std::string webapp; }; -struct Map_Tile_Config { - std::string file_format = "directory"; - std::vector directories; - std::vector files; +enum class Map_Tile_File_Format { directory, mbtiles, online }; +enum class Map_Tile_Y_Axis { xyz, tms }; +enum class Map_Tile_Projection { web_mercator }; +enum class Map_Tile_Type { imagery, terrain }; +enum class Map_Tile_Request_Method { GET }; +enum class Map_Tile_Zoom_Mode { native, upscale, both }; +struct Map_Tile_Config_Data { + Map_Tile_File_Format file_format = Map_Tile_File_Format::directory; std::string path_layout; - std::string y_axis; - std::string projection; + Map_Tile_Y_Axis y_axis = Map_Tile_Y_Axis::xyz; + Map_Tile_Projection projection = Map_Tile_Projection::web_mercator; std::string extension; std::uint32_t tile_size{}; std::uint32_t minimum_level{}; std::uint32_t maximum_level{}; + PSC_USE_JSON +}; +struct Map_Tile_Config : Map_Tile_Config_Data { + std::vector directories; + std::vector files; std::string encoding; [[nodiscard]] std::vector get_true_directories() const { std::vector ret; @@ -139,31 +146,35 @@ struct Map_Tile_Config { } return ret; } - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; [[nodiscard]] Psc::JSON to_public_json(std::string_view url) const; }; -struct Map_Tile_Source_Config { +struct Map_Tile_Source_Config_Data { std::string key; std::string name; - std::string tile_type = "imagery"; - std::string request_method = "GET"; + Map_Tile_Type tile_type = Map_Tile_Type::imagery; + Map_Tile_Request_Method request_method = Map_Tile_Request_Method::GET; + PSC_USE_JSON +}; +struct Map_Tile_Source_Config : Map_Tile_Source_Config_Data { std::string url; Map_Tile_Config resource; [[nodiscard]] bool local() const { - return resource.file_format != "online"; + return resource.file_format != Map_Tile_File_Format::online; } - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; [[nodiscard]] Psc::JSON to_public_json(std::string_view local_url) const; }; struct Map_Resources_Config { std::string current_imagery_key = "imagery"; std::vector tile_sources; - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; [[nodiscard]] Psc::JSON to_public_json() const; [[nodiscard]] bool is_imagery_key(std::string_view key) const; + [[nodiscard]] bool is_terrain_key(std::string_view key) const; }; struct Map_Camera_Config { double longitude = 121.27; @@ -172,16 +183,15 @@ struct Map_Camera_Config { double heading = 0.0; double pitch = -90.0; double roll = 0.0; - void from_base_json(const Psc::JSON* that_json); - [[nodiscard]] Psc::JSON to_base_json() const; + PSC_USE_JSON }; struct Map_Tile_View_Config { std::string current_imagery_key = "imagery"; - std::string tile_zoom_mode = "native"; + std::string current_terrain_key = "terrain"; + Map_Tile_Zoom_Mode tile_zoom_mode = Map_Tile_Zoom_Mode::native; std::uint32_t tile_display_maximum_level = 19; - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; - [[nodiscard]] static bool is_tile_zoom_mode(std::string_view mode); }; struct Map_View_Config { std::string scene_mode = "3d"; @@ -189,11 +199,11 @@ struct Map_View_Config { Map_Tile_View_Config map3d; Map_Camera_Config camera; double base_station_fly_to_height_offset_meters = 8000.0; - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; [[nodiscard]] static bool is_scene_mode(std::string_view mode); }; -struct Cesium_Graphics_Config { +struct Cesium_Graphics_Config_Data { bool debug_show_frames_per_second = true; std::uint32_t target_frame_rate = 30; bool use_browser_recommended_resolution = true; @@ -220,7 +230,10 @@ struct Cesium_Graphics_Config { double view_axes_panel_size = 84.0; double occlusion_sample_spacing_meters = 250.0; double occlusion_clearance_margin_meters = 10.0; - void from_base_json(const Psc::JSON* that_json); + PSC_USE_JSON +}; +struct Cesium_Graphics_Config : Cesium_Graphics_Config_Data { + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; }; struct Map_Model_Item_Config { @@ -232,7 +245,7 @@ struct Map_Model_Item_Config { Map_Model_Item_Config() = default; explicit Map_Model_Item_Config(std::string url); Map_Model_Item_Config(std::string url, double built_in_size, double heading, double pitch, double roll); - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; }; struct Map_Model_Config { @@ -241,7 +254,7 @@ struct Map_Model_Config { Map_Model_Item_Config base_station_model{"/ui/model/base-station.glb", 16.635522, 0.0, 0.0, 0.0}; Map_Model_Item_Config device_model{"/ui/model/device.glb", 80.0, 0.0, 0.0, 0.0}; Map_Model_Config(); - void from_base_json(const Psc::JSON* that_json); + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value); [[nodiscard]] Psc::JSON to_base_json() const; }; struct Net_Config { @@ -272,10 +285,10 @@ struct Device_Config { return ret; } Device_Config() = default; - void init(const Psc::JSON* that_json) { + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { for (auto& li : that_json->get("net")->children) { auto cur = new Net_Config(); - cur->from_base_json(&li); + cur->from_base_json(&li, not_exist_use_default_value); list.push_back(cur); } } @@ -317,8 +330,7 @@ public: Psc::fail_fast(); } else { - std::cout << get_current_date_string() << " 启动加载配置文件: 【" - << config_path << "】" << std::endl; + std::cout << get_current_date_string() << " 启动加载配置文件: 【" << config_path << "】" << std::endl; } std::stringstream ss; std::stringstream buffer; @@ -326,40 +338,39 @@ public: std::string fileContents = buffer.str(); return Psc::parse_json(fileContents); } - void fromJson(Psc::JSON* that_json) { - Get_J(version) - mlat.init(that_json->get("mlat")); - web_server_config.from_base_json(that_json->get("web_server")); - map_resources_config.from_base_json(that_json->get("map_resources")); - map_view_config.from_base_json(that_json->get("map_view")); - cesium_graphics_config.from_base_json(that_json->get("cesium_graphics")); - map_model_config.from_base_json(that_json->get("map_models")); - device_config.init(that_json->get("device")); - mode_acs.init(that_json->get("mode_acs")); - console_config.from_base_json(that_json->get("console")); - dsp_config.from_json(that_json->get("dsp")); + void from_base_json(Psc::JSON* that_json, bool not_exist_use_default_value) { + Get_J(version) mlat.from_json(that_json->get("mlat"), not_exist_use_default_value); + web_server_config.from_base_json(that_json->get("web_server"), not_exist_use_default_value); + map_resources_config.from_base_json(that_json->get("map_resources"), not_exist_use_default_value); + map_view_config.from_base_json(that_json->get("map_view"), not_exist_use_default_value); + cesium_graphics_config.from_base_json(that_json->get("cesium_graphics"), not_exist_use_default_value); + map_model_config.from_base_json(that_json->get("map_models"), not_exist_use_default_value); + device_config.from_json(that_json->get("device"), not_exist_use_default_value); + mode_acs.from_json(that_json->get("mode_acs"), not_exist_use_default_value); + console_config.from_base_json(that_json->get("console"), not_exist_use_default_value); + dsp_config.from_json(that_json->get("dsp"), not_exist_use_default_value); drogon_config = *that_json->get("drogon"); - http_monitor_config.from_base_json(that_json->get("http_monitor")); - external_resources_manager.init(that_json->get("external_database")); + http_monitor_config.from_base_json(that_json->get("http_monitor"), not_exist_use_default_value); + external_resources_manager.from_json(that_json->get("external_database"), not_exist_use_default_value); } Psc::JSON toJson() { auto ret = Psc::JSON::object({ - {"version", version}, - {"dsp", dsp_config.to_base_json()}, - {"drogon", drogon_config}, - {"http_monitor", http_monitor_config.to_base_json()}, - {"mlat", mlat.to_base_json()}, - {"web_server", web_server_config.to_base_json()}, - {"map_resources", map_resources_config.to_base_json()}, - {"map_view", map_view_config.to_base_json()}, - {"map_models", map_model_config.to_base_json()}, - {"device", device_config.to_base_json()}, - {"mode_acs", mode_acs.to_base_json()}, - //{"ais", ais.to_json()}, - {"log", log_config.to_base_json()}, - {"console", console_config.to_base_json()}, - {"external_database", external_resources_manager.to_base_json()}, - {"cesium_graphics", cesium_graphics_config.to_base_json()}, + {"version", version}, + {"dsp", dsp_config.to_base_json()}, + {"drogon", drogon_config}, + {"http_monitor", http_monitor_config.to_base_json()}, + {"mlat", mlat.to_base_json()}, + {"web_server", web_server_config.to_base_json()}, + {"map_resources", map_resources_config.to_base_json()}, + {"map_view", map_view_config.to_base_json()}, + {"map_models", map_model_config.to_base_json()}, + {"device", device_config.to_base_json()}, + {"mode_acs", mode_acs.to_base_json()}, + //{"ais", ais.to_json()}, + {"log", log_config.to_base_json()}, + {"console", console_config.to_base_json()}, + {"external_database", external_resources_manager.to_base_json()}, + {"cesium_graphics", cesium_graphics_config.to_base_json()}, }); return ret; } diff --git a/module/Local_Server/server/Global.cpp b/module/Local_Server/server/Global.cpp index 29ac169..f0c08f1 100644 --- a/module/Local_Server/server/Global.cpp +++ b/module/Local_Server/server/Global.cpp @@ -30,8 +30,7 @@ void Global::handle_old_logs() { case Log_Config::Open_Mode::Delete: { if (fs::exists(dirPath)) { fs::remove_all(dirPath); // 删除目录及其所有内容 - std::cout << "Directory and its contents deleted: " << dirPath - << std::endl; + std::cout << "Directory and its contents deleted: " << dirPath << std::endl; } if (fs::create_directories(dirPath)) { std::cout << "Directory created: " << dirPath << std::endl; @@ -40,8 +39,7 @@ void Global::handle_old_logs() { std::cout << "创建目录失败: " << dirPath << std::endl; Psc::fail_fast(); } - fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all | - fs::perms::others_all); + fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all); break; } case Log_Config::Open_Mode::Append: @@ -57,42 +55,33 @@ void Global::handle_old_logs() { } Global::Global() { auto j = load(); - log_config.from_base_json(j.get("log")); + log_config.from_base_json(j.get("log"), false); handle_old_logs(); - Base_Logger_Manager::instance() - ->set_thread_num(1) - .set_flush_seconds(3) - .init(); + 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); + 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; + 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); }); - fromJson(&j); + 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); + }); + from_base_json(&j, false); #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) { + 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_info); f->add_msg_limit(mode_s_msg); @@ -105,10 +94,8 @@ Global::Global() { SSR::mode_s_logger->debug("CPR/" + to_string(t) + "/" + to_string(err_type), {}, log); }; // 处理错误 - SSR::parse_call_back = - [this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info* info, - std::string_view field_name, std::vector bds_list, - void*, SSR::P_S msg) { + SSR::parse_call_back = [this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info* info, std::string_view field_name, + std::vector bds_list, void*, SSR::P_S msg) { auto src = std::dynamic_pointer_cast(msg->source); Mode_S_Statistic_Data* ss = &src->mode_s_statistic; if (type == SSR::Parse_Call_Back_Type::Unknown_DF) { @@ -147,8 +134,7 @@ Global::Global() { Global::~Global() { std::cout << "Global::~Global()" << std::endl; } -void replace(std::string& originalStr, std::string_view findStr, - std::string_view replaceStr) { +void replace(std::string& originalStr, std::string_view findStr, std::string_view replaceStr) { size_t pos = originalStr.find(findStr); while (pos != std::string::npos) { originalStr.replace(pos, findStr.length(), replaceStr); @@ -165,10 +151,8 @@ bool isHexadecimal(std::string_view str) { return std::isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }); } -void handle_buffer_muti_start( - std::string& buffer, std::string_view data, - const std::set& prefix_list, - const std::function& callback) { +void handle_buffer_muti_start(std::string& buffer, std::string_view data, const std::set& prefix_list, + const std::function& callback) { if (!data.empty()) { buffer += data; // std::cout << "[data]:" + data + "\n"; @@ -203,10 +187,8 @@ void handle_buffer_muti_start( } } } -void handle_buffer_head_tail( - std::string& buffer, std::string_view data, std::string_view prefix, - std::string_view suffix, - const std::function& callback) { +void handle_buffer_head_tail(std::string& buffer, std::string_view data, std::string_view prefix, + std::string_view suffix, const std::function& callback) { // 只在数据可用时进行读取 if (!data.empty()) { buffer += data; @@ -261,8 +243,7 @@ void read_ais_serial_data(std::atomic& running) { // delete ais_serial; } bool is_10004(SSR::Mode_S_Msg& msg) { - bool DF_11_17_18 = - msg.df == SSR::Downlink_Format::All_Call_Reply_11 || + bool DF_11_17_18 = msg.df == SSR::Downlink_Format::All_Call_Reply_11 || msg.df == SSR::Downlink_Format::Extended_Squitter_17 || msg.df == SSR::Downlink_Format::Extended_Squitter_Non_Transponder_18; return DF_11_17_18; @@ -271,14 +252,10 @@ std::string to_file_name(std::string_view str) { auto ret = std::string(str); // 定义允许的合法字符 auto is_valid_char = [](char c) { - return std::isalnum(c) || c == '_' || c == '-' || - c == '.'; // 允许字母、数字、下划线、连字符、点 + return std::isalnum(c) || c == '_' || c == '-' || c == '.'; // 允许字母、数字、下划线、连字符、点 }; // 替换非法字符为下划线 '_' - std::transform(ret.begin(), ret.end(), ret.begin(), - [&](char c) { - return is_valid_char(c) ? c : '_'; - }); + std::transform(ret.begin(), ret.end(), ret.begin(), [&](char c) { return is_valid_char(c) ? c : '_'; }); // 检查结果字符串是否全是替换字符,防止生成全是下划线的文件名 if (ret.find_first_not_of('_') == std::string::npos) { return "default_file_name"; // 返回一个默认文件名 @@ -316,11 +293,9 @@ bool Web_Server::listen(std::string_view host, int port) { Json::CharReaderBuilder builder; std::string errs; auto reader = builder.newCharReader(); - if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), - &drogon_config, &errs)) { + if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), &drogon_config, &errs)) { // 解析失败 - std::cout << "drogon 配置文件加载失败!json格式解析失败!" << jsonStr - << std::endl; + std::cout << "drogon 配置文件加载失败!json格式解析失败!" << jsonStr << std::endl; Psc::fail_fast(); } delete reader; @@ -336,94 +311,85 @@ bool Web_Server::listen(std::string_view host, int port) { } Web_Server& Web_Server::Post(std::string_view pattern, Handler handler) { drogon::app().registerHandler( - std::string(pattern), - [handler](const drogon::HttpRequestPtr& request, - std::function&& callback) { - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - handler(request, resp); - callback(resp); - }, - {drogon::Post} - ); + std::string(pattern), + [handler](const drogon::HttpRequestPtr& request, std::function&& 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&& 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} - ); + drogon::app().registerHandler( + std::string(pattern), + [handler = std::move(handler)](const drogon::HttpRequestPtr& request, + std::function&& 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&& callback) { - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - handler(request, resp); - callback(resp); - }, - {drogon::Get} - ); + std::string(pattern), + [handler](const drogon::HttpRequestPtr& request, std::function&& 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&& 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} - ); + std::string(pattern), + [handler = std::move(handler)](const drogon::HttpRequestPtr& request, + std::function&& 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 -Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) { +std::string Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) { std::lock_guard g(mtx); std::string result; if (serial_number == cur_serial_number) { @@ -454,8 +420,7 @@ std::string inet_address_to_string(const trantor::InetAddress& addr) { } else { // IPv6 - auto sa6 = - reinterpret_cast(addr.getSockAddr()); + auto sa6 = reinterpret_cast(addr.getSockAddr()); inet_ntop(AF_INET6, &(sa6->sin6_addr), buf, sizeof(buf)); uint16_t port = ntohs(sa6->sin6_port); return "[" + std::string(buf) + "]:" + std::to_string(port); diff --git a/module/Local_Server/server/MLAT.cpp b/module/Local_Server/server/MLAT.cpp index d9be0a8..0d22bc2 100644 --- a/module/Local_Server/server/MLAT.cpp +++ b/module/Local_Server/server/MLAT.cpp @@ -1,191 +1,172 @@ #include "MLAT.h" - -#include "Global.h" - #include #include - +#include "Global.h" time_t datetime_to_timestamp(std::string_view datetime) { - std::tm tm = {}; - std::istringstream ss{std::string(datetime)}; - ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); - if (ss.fail()) { - throw std::runtime_error("时间格式错误"); - } - // std::mktime按本地时区转换 - return std::mktime(&tm); + std::tm tm = {}; + std::istringstream ss{std::string(datetime)}; + ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); + if (ss.fail()) { + throw std::runtime_error("时间格式错误"); + } + // std::mktime按本地时区转换 + return std::mktime(&tm); } - std::multimap hex_mlat_map; std::vector read_lines() { - Base_Logger_Manager::instance()->init(); - - std::multimap ordered_multimap; - std::ifstream fin("C:/wyc/CLionProjects/plantSunCat/mainProjects/Radarcape/" - "data/0701/info.txt"); - if (!fin) { - std::cerr << "无法打开文件!" << std::endl; - return {}; - } - std::string line; - while (std::getline(fin, line)) { - if (line.empty()) - continue; - - std::vector fields; - std::stringstream ss(line); - std::string item; - while (std::getline(ss, item, ';')) { - fields.push_back(item); + Base_Logger_Manager::instance()->init(); + std::multimap ordered_multimap; + std::ifstream fin("C:/wyc/CLionProjects/plantSunCat/mainProjects/Radarcape/" + "data/0701/info.txt"); + if (!fin) { + std::cerr << "无法打开文件!" << std::endl; + return {}; } - // 检查字段数 - if (fields.size() < 9) - continue; - // 2025-07-03 10:16:21;VG_MSDW;28069B;2025-06-27 - // 08:00:14;A800103FFF9CCB27FFFCA89DE0D3;121.691398;37.344925;8000;;0000;2_1_3 - // 按 1-base 提取 - std::string icao = fields[2]; - icao.resize(6, '_'); - std::string msg = fields[4]; - std::string lon = fields[5]; - std::string lat = fields[6]; - - std::string time = fields[3]; - std::string hex = fields[4]; - // 输出(或者你可以存到 vector 里) - // std::cout << icao << " " << lat << " " << lon << " " << alt << std::endl; - - Base_MLAT_Data b; - // cur.icao = icao; - b.mlat_data.lon = stod(lon); - b.mlat_data.lat = stod(lat); - b.msg = line; - b.hex = hex; - b.icao = icao; - strncpy(b.mlat_data.icao, icao.c_str(), 6); - // std::cout << cur.lat << " " << cur.lon << std::endl; - // if (35 < cur.lat && cur.lat < 37 - // && - // 120 < cur.lon && cur.lon < 122 - // ) { - // - // pure_log("@/logs/mlat_.log", line + "\n"); - // } - ordered_multimap.insert({datetime_to_timestamp(time), b}); - } - std::vector list; - for (auto it : ordered_multimap) { - Base_MLAT_Data &b = it.second; - list.push_back(b.mlat_data); - auto icao = std::string(b.mlat_data.icao, 6); - // if (icao == "78139F") { - // pure_log("@/logs/icao/" + icao + "_mlat_result.log", b.msg + "\n"); - // } - hex_mlat_map.insert({b.hex, b}); - } - return list; + std::string line; + while (std::getline(fin, line)) { + if (line.empty()) + continue; + std::vector fields; + std::stringstream ss(line); + std::string item; + while (std::getline(ss, item, ';')) { + fields.push_back(item); + } + // 检查字段数 + if (fields.size() < 9) + continue; + // 2025-07-03 10:16:21;VG_MSDW;28069B;2025-06-27 + // 08:00:14;A800103FFF9CCB27FFFCA89DE0D3;121.691398;37.344925;8000;;0000;2_1_3 + // 按 1-base 提取 + std::string icao = fields[2]; + icao.resize(6, '_'); + std::string msg = fields[4]; + std::string lon = fields[5]; + std::string lat = fields[6]; + std::string time = fields[3]; + std::string hex = fields[4]; + // 输出(或者你可以存到 vector 里) + // std::cout << icao << " " << lat << " " << lon << " " << alt << std::endl; + Base_MLAT_Data b; + // cur.icao = icao; + b.mlat_data.lon = stod(lon); + b.mlat_data.lat = stod(lat); + b.msg = line; + b.hex = hex; + b.icao = icao; + strncpy(b.mlat_data.icao, icao.c_str(), 6); + // std::cout << cur.lat << " " << cur.lon << std::endl; + // if (35 < cur.lat && cur.lat < 37 + // && + // 120 < cur.lon && cur.lon < 122 + // ) { + // + // pure_log("@/logs/mlat_.log", line + "\n"); + // } + ordered_multimap.insert({datetime_to_timestamp(time), b}); + } + std::vector list; + for (auto it : ordered_multimap) { + Base_MLAT_Data& b = it.second; + list.push_back(b.mlat_data); + auto icao = std::string(b.mlat_data.icao, 6); + // if (icao == "78139F") { + // pure_log("@/logs/icao/" + icao + "_mlat_result.log", b.msg + "\n"); + // } + hex_mlat_map.insert({b.hex, b}); + } + return list; } std::vector all; - -void read(MLAT_Data *buf, std::uint16_t *len) { - if (all.empty()) { - all = read_lines(); - } - static size_t pos = 0; // 上一次拷贝结束后的位置 - const size_t BATCH = 100; - size_t total = all.size(); - size_t n = std::min(BATCH, total - pos); // 本次实际要拷贝多少 - - for (size_t i = 0; i < n; ++i) { - buf[i] = all[pos + i]; - } - *len = static_cast(n); - - pos += n; - if (pos >= total) { - pos = 0; // 如果需要循环一轮后归零,否则你可以不归零 - } -} - -MLAT_Config::MLAT_Config() {} -void MLAT_Config::init(const Psc::JSON *that_json) { - MLAT_Config_Data::from_base_json(that_json); - if (enable) { - { - auto r = Psc::try_load_library(Psc::get_abs_path(library_path)); - if (!r) { - Psc::fail_fast(); - } - lib = r.value(); +void read(MLAT_Data* buf, std::uint16_t* len) { + if (all.empty()) { + all = read_lines(); } - { - auto r = Psc::try_load_function(lib, function_name); - if (!r) { - Psc::fail_fast(); - } - read_func_ptr = (Func_Type)r.value(); + static size_t pos = 0; // 上一次拷贝结束后的位置 + const size_t BATCH = 100; + size_t total = all.size(); + size_t n = std::min(BATCH, total - pos); // 本次实际要拷贝多少 + for (size_t i = 0; i < n; ++i) { + buf[i] = all[pos + i]; + } + *len = static_cast(n); + pos += n; + if (pos >= total) { + pos = 0; // 如果需要循环一轮后归零,否则你可以不归零 + } +} +MLAT_Config::MLAT_Config() { +} +void MLAT_Config::from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + MLAT_Config_Data::from_base_json(that_json, not_exist_use_default_value); + if (enable) { + { + auto r = Psc::try_load_library(Psc::get_abs_path(library_path)); + if (!r) { + Psc::fail_fast(); + } + lib = r.value(); + } + { + auto r = Psc::try_load_function(lib, function_name); + if (!r) { + Psc::fail_fast(); + } + read_func_ptr = (Func_Type)r.value(); + } + all = read_lines(); + read_func_ptr = read; } - - all = read_lines(); - read_func_ptr = read; - } } - void MLAT_Config::refresh() { - std::lock_guard guard(mtx); - std::uint16_t len{}; - if (read_func_ptr) - read_func_ptr(buf, &len); - auto list = Global::instance()->mode_acs.data_source_config.map.list(); - for (std::uint16_t i = 0; i < len; i++) { - MLAT_Data &cur = buf[i]; - std::string icao = std::string(cur.icao, 6); - - for (const auto &li : list) { - // auto air = li->get_aircraft(icao); - auto air = li->get_aircraft(icao); - if (air) { - // air->mlat = true; - // air->air_pos_track_list.push(CPR::Position{cur.lat, cur.lon}); - } + std::lock_guard guard(mtx); + std::uint16_t len{}; + if (read_func_ptr) + read_func_ptr(buf, &len); + auto list = Global::instance()->mode_acs.data_source_config.map.list(); + for (std::uint16_t i = 0; i < len; i++) { + MLAT_Data& cur = buf[i]; + std::string icao = std::string(cur.icao, 6); + for (const auto& li : list) { + // auto air = li->get_aircraft(icao); + auto air = li->get_aircraft(icao); + if (air) { + // air->mlat = true; + // air->air_pos_track_list.push(CPR::Position{cur.lat, cur.lon}); + } + } + auto& t = update_map[icao]; + if (t.d.lat != cur.lat || t.d.lon != cur.lon) { + t.d = cur; + } } - - auto &t = update_map[icao]; - if (t.d.lat != cur.lat || t.d.lon != cur.lon) { - t.d = cur; - } - } } - -void MLAT_Config::server(Global *g) { - auto &svr = g->svr; - auto &api = g->api; - svr.Post(api + "get_mlat_list", [this](HTTP_Param) { - res->setBody(warp(get_reset()).to_json_string()); - }); - - // svr.Post(api + "get_mlat_server_config", [this](HTTP_Param) { - // res->setBody(warp(to_json()).to_json_string()); - // }); - // svr.Post(api + "/set_mlat_server_config", [this, g](HTTP_Param) { - // CHECK_JSON_PARAM - // MLAT_Server_Config t; - // t.init(&o_params.value()); - // bool ok = check_ipv4(t.ip) && check_port(t.port); - // if (!ok) - // { - // server_logger->error("", {}, LOG_POS + " ip port! " + t.ip + ":" + - // std::to_string(t.port)); - // res->setBody(warp(to_json()).to_json_string()); - // return; - // } - // - // auto& s = g->mlat_server; - // s.id = t.id; - // s.port = t.port; - // s.ip = t.ip; - // - // Global::save(); - // res->setBody(warp(to_json()).to_json_string()); - // }); +void MLAT_Config::server(Global* g) { + auto& svr = g->svr; + auto& api = g->api; + svr.Post(api + "get_mlat_list", [this](HTTP_Param) { res->setBody(warp(get_reset()).to_json_string()); }); + // svr.Post(api + "get_mlat_server_config", [this](HTTP_Param) { + // res->setBody(warp(to_json()).to_json_string()); + // }); + // svr.Post(api + "/set_mlat_server_config", [this, g](HTTP_Param) { + // CHECK_JSON_PARAM + // MLAT_Server_Config t; + // t.init(&o_params.value()); + // bool ok = check_ipv4(t.ip) && check_port(t.port); + // if (!ok) + // { + // server_logger->error("", {}, LOG_POS + " ip port! " + t.ip + ":" + + // std::to_string(t.port)); + // res->setBody(warp(to_json()).to_json_string()); + // return; + // } + // + // auto& s = g->mlat_server; + // s.id = t.id; + // s.port = t.port; + // s.ip = t.ip; + // + // Global::save(); + // res->setBody(warp(to_json()).to_json_string()); + // }); } diff --git a/module/Local_Server/server/MLAT.h b/module/Local_Server/server/MLAT.h index 1bbbd71..8c52198 100644 --- a/module/Local_Server/server/MLAT.h +++ b/module/Local_Server/server/MLAT.h @@ -1,10 +1,10 @@ #ifndef MLAT_H #define MLAT_H -#include "Core/Base/JSON.h" -#include "Core/system/export.h" -#include "../global_include.h" #include #include +#include "../global_include.h" +#include "Core/Base/JSON.h" +#include "Core/system/export.h" class Global; #pragma pack(push, 8) extern "C" { @@ -53,7 +53,7 @@ public: void* lib{}; using Func_Type = void (*)(MLAT_Data* buf, std::uint16_t* len); Func_Type read_func_ptr{}; - void init(const Psc::JSON* that_json); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value); MLAT_Data buf[std::numeric_limits::max()]{}; void refresh(); Psc::JSON get_reset() { diff --git a/module/Local_Server/server/Source_Feed_Relation.cpp b/module/Local_Server/server/Source_Feed_Relation.cpp index 2ed546c..962777c 100644 --- a/module/Local_Server/server/Source_Feed_Relation.cpp +++ b/module/Local_Server/server/Source_Feed_Relation.cpp @@ -2,76 +2,69 @@ #include "Config.h" #include "Global.h" void Source_Feed_Relation_Config::set_need_refresh() { - for (const auto &li : - Global::instance()->mode_acs.data_source_config.map.list()) { - li->need_refresh_data_feed_key_list = true; - } + for (const auto& li : Global::instance()->mode_acs.data_source_config.map.list()) { + li->need_refresh_data_feed_key_list = true; + } } - -void Source_Feed_Relation_Config::server(Global *g) { - auto &svr = g->svr; - auto &api = g->api; - std::string name = "source_feed_relation"; - - svr.Post(api + "get_" + name + "_config", [this](HTTP_Param) { - res->setBody(warp(to_json()).to_json_string()); - }); - - svr.Post(api + svr.search + name, [this, g](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) - HTTP_REQUIRE_VALUE(relation, map.get(key)) - res->setBody(warp(relation->to_json()).to_json_string()); - }); - - svr.Post(api + svr.update + name, [this, g](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) - HTTP_REQUIRE_VALUE(ds, map.get(key)) - ds->from_json(¶ms); - - // 直接关闭 - g->save(); - set_need_refresh(); - }); - - svr.Post(api + svr.insert + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_PTR(data, params.get("data")) - HTTP_REQUIRE_VALUE(t, data->try_get_string("type")) - std::cout << params.to_json_string() << std::endl; - auto ds = create_source_feed_relation_from_type(t); - ds->from_json(data); - HTTP_REQUIRE_TRUE(map.insert(index, ds), "index") - // std::cout << params.to_json_string() << std::endl; - res->setBody(warp(to_json()).to_json_string()); - g->save(); - set_need_refresh(); - }); - - svr.Post(api + svr.remove + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_TRUE(map.remove(index), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - set_need_refresh(); - }); - svr.Post(api + svr.rise + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_TRUE(map.swap(index, index - 1), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - set_need_refresh(); - }); - svr.Post(api + svr.fall + name, [g, this](HTTP_Param) { - CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) - HTTP_REQUIRE_TRUE(map.swap(index, index + 1), "index") - g->save(); - res->setBody(warp(to_json()).to_json_string()); - set_need_refresh(); - }); +void Source_Feed_Relation_Config::server(Global* g) { + auto& svr = g->svr; + auto& api = g->api; + std::string name = "source_feed_relation"; + svr.Post(api + "get_" + name + "_config", [this](HTTP_Param) { res->setBody(warp(to_json()).to_json_string()); }); + svr.Post(api + svr.search + name, [this, g](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) + HTTP_REQUIRE_VALUE(relation, map.get(key)) + res->setBody(warp(relation->to_json()).to_json_string()); + }); + svr.Post(api + svr.update + name, [this, g](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Source_Feed_Relation:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(key, params.try_get_string("key")) + HTTP_REQUIRE_VALUE(ds, map.get(key)) + ds->from_json(¶ms); + // 直接关闭 + g->save(); + set_need_refresh(); + }); + svr.Post(api + svr.insert + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Source_Feed_Relation:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_PTR(data, params.get("data")) + HTTP_REQUIRE_VALUE(t, data->try_get_string("type")) + std::cout << params.to_json_string() << std::endl; + auto ds = create_source_feed_relation_from_type(t); + ds->from_json(data); + HTTP_REQUIRE_TRUE(map.insert(index, ds), "index") + // std::cout << params.to_json_string() << std::endl; + res->setBody(warp(to_json()).to_json_string()); + g->save(); + set_need_refresh(); + }); + svr.Post(api + svr.remove + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + std::cout << "Source_Feed_Relation:" << req->path() << that_json->to_json_string(); + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_TRUE(map.remove(index), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + set_need_refresh(); + }); + svr.Post(api + svr.rise + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_TRUE(map.swap(index, index - 1), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + set_need_refresh(); + }); + svr.Post(api + svr.fall + name, [g, this](HTTP_Param) { + CHECK_JSON_PARAM + HTTP_REQUIRE_VALUE(index, params.try_get_number("index")) + HTTP_REQUIRE_TRUE(map.swap(index, index + 1), "index") + g->save(); + res->setBody(warp(to_json()).to_json_string()); + set_need_refresh(); + }); } diff --git a/module/Local_Server/server/Source_Feed_Relation.h b/module/Local_Server/server/Source_Feed_Relation.h index 1e7be9d..89a07a0 100644 --- a/module/Local_Server/server/Source_Feed_Relation.h +++ b/module/Local_Server/server/Source_Feed_Relation.h @@ -1,89 +1,78 @@ #ifndef SOURCE_FEED_RELATION_H #define SOURCE_FEED_RELATION_H - +#include #include "../global_include.h" #include "Core/Serial/Serial.h" -#include - struct Source_Feed_Relation { - std::string key; - std::string type; - std::atomic enable{}; - virtual void from_json(const Psc::JSON *that_json) { - Get_J(key); - Get_J(enable); - Get_J(type); - } - - [[nodiscard]] virtual Psc::JSON to_json() const { - Psc::JSON ret = Psc::JSON::object(); - Ret_J(key) Ret_J(enable) Ret_J(type) return ret; - } - virtual ~Source_Feed_Relation() = default; + std::string key; + std::string type; + std::atomic enable{}; + virtual void from_json(const Psc::JSON* that_json) { + Get_J(key); + Get_J(enable); + Get_J(type); + } + [[nodiscard]] virtual Psc::JSON to_json() const { + Psc::JSON ret = Psc::JSON::object(); + Ret_J(key) Ret_J(enable) Ret_J(type) return ret; + } + virtual ~Source_Feed_Relation() = default; }; - struct One_to_One_Relation : Source_Feed_Relation { - std::string source_key; - std::string feed_key; - void from_json(const Psc::JSON *that_json) override { - Source_Feed_Relation::from_json(that_json); - Get_J(source_key) Get_J(feed_key) - } - [[nodiscard]] Psc::JSON to_json() const override { - Psc::JSON ret = Source_Feed_Relation::to_json(); - Ret_J(source_key) Ret_J(feed_key) return ret; - } - ~One_to_One_Relation() override = default; + std::string source_key; + std::string feed_key; + void from_json(const Psc::JSON* that_json) override { + Source_Feed_Relation::from_json(that_json); + Get_J(source_key) Get_J(feed_key) + } + [[nodiscard]] Psc::JSON to_json() const override { + Psc::JSON ret = Source_Feed_Relation::to_json(); + Ret_J(source_key) Ret_J(feed_key) return ret; + } + ~One_to_One_Relation() override = default; }; - struct First_Source_To_All_Feed_Relation : Source_Feed_Relation { - void from_json(const Psc::JSON *that_json) override { - Source_Feed_Relation::from_json(that_json); - } - [[nodiscard]] Psc::JSON to_json() const override { - Psc::JSON ret = Source_Feed_Relation::to_json(); - return ret; - } - ~First_Source_To_All_Feed_Relation() override = default; + void from_json(const Psc::JSON* that_json) override { + Source_Feed_Relation::from_json(that_json); + } + [[nodiscard]] Psc::JSON to_json() const override { + Psc::JSON ret = Source_Feed_Relation::to_json(); + return ret; + } + ~First_Source_To_All_Feed_Relation() override = default; }; - -inline std::shared_ptr -create_source_feed_relation_from_type(std::string_view t) { - std::shared_ptr ret{}; - if (t == "One_to_One_Relation") - ret = std::make_shared(); - else if (t == "First_Source_To_All_Feed_Relation") - ret = std::make_shared(); - else { - std::cout << "未知的 Source_Feed_Relation type 类型! t:[" << t << "]" - << std::endl; - throw std::invalid_argument("unknown Source_Feed_Relation type: " + std::string(t)); - } - return ret; +inline std::shared_ptr create_source_feed_relation_from_type(std::string_view t) { + std::shared_ptr ret{}; + if (t == "One_to_One_Relation") + ret = std::make_shared(); + else if (t == "First_Source_To_All_Feed_Relation") + ret = std::make_shared(); + else { + std::cout << "未知的 Source_Feed_Relation type 类型! t:[" << t << "]" << std::endl; + throw std::invalid_argument("unknown Source_Feed_Relation type: " + std::string(t)); + } + return ret; } - struct Source_Feed_Relation_Config { - void from_json(const Psc::JSON *that_json) { - auto j_list = that_json->get("list"); - for (const Psc::JSON &li : j_list->children) { - auto p = create_source_feed_relation_from_type(li.get_string("type")); - p->from_json(&li); - map.push_back(p); + void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { + auto j_list = that_json->get("list"); + for (const Psc::JSON& li : j_list->children) { + auto p = create_source_feed_relation_from_type(li.get_string("type")); + p->from_json(&li); + map.push_back(p); + } } - } - [[nodiscard]] Psc::JSON to_json() { - Psc::JSON ret = Psc::JSON::object(); - Psc::JSON j_list = Psc::JSON::array(); - for (auto &p : this->map.list()) { - j_list.append(p->to_json()); + [[nodiscard]] Psc::JSON to_json() { + Psc::JSON ret = Psc::JSON::object(); + Psc::JSON j_list = Psc::JSON::array(); + for (auto& p : this->map.list()) { + j_list.append(p->to_json()); + } + ret.append(Psc::JSON("list", j_list)); + return ret; } - ret.append(Psc::JSON("list", j_list)); - return ret; - } - Ordered_Map> map; - - static void set_need_refresh(); // 通知每一个data_source 映射关系需要更新 - void server(Global *g); + Ordered_Map> map; + static void set_need_refresh(); // 通知每一个data_source 映射关系需要更新 + void server(Global* g); }; - #endif diff --git a/module/Local_Server/server/With_Loop_Coro.h b/module/Local_Server/server/With_Loop_Coro.h index fc563c8..a9f2e9f 100644 --- a/module/Local_Server/server/With_Loop_Coro.h +++ b/module/Local_Server/server/With_Loop_Coro.h @@ -1,7 +1,6 @@ #pragma once -#include -#include #include +#include #include #include #include @@ -9,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/module/Local_Server/server/server.cpp b/module/Local_Server/server/server.cpp index ecb78e7..740bc6b 100644 --- a/module/Local_Server/server/server.cpp +++ b/module/Local_Server/server/server.cpp @@ -1,9 +1,9 @@ -#include "Global.h" -#include "Performance_Monitor.h" #include #include #include +#include "Global.h" +#include "Performance_Monitor.h" namespace { constexpr std::size_t kMaxLogRequestBodySize = 8 * 1024; void Log_Request_Body_If_Small(const drogon::HttpRequestPtr& request) { @@ -13,13 +13,12 @@ void Log_Request_Body_If_Small(const drogon::HttpRequestPtr& request) { } if (body.size() <= kMaxLogRequestBodySize) { LOG_INFO << "[request body] " - << "path=" << request->path() << ", size=" << body.size() - << ", body=" << std::string(body.data(), body.size()); + << "path=" << request->path() << ", size=" << body.size() + << ", body=" << std::string(body.data(), body.size()); } else { LOG_INFO << "[request body skipped] " - << "path=" << request->path() << ", size=" << body.size() - << ", max=" << kMaxLogRequestBodySize; + << "path=" << request->path() << ", size=" << body.size() << ", max=" << kMaxLogRequestBodySize; } } bool Is_Invalid_Http_Param(const std::exception& e) { @@ -31,21 +30,17 @@ bool Is_Safe_Version_Directory_Name(std::string_view name) { if (name.empty() || name == "." || name == "..") { return false; } - return std::ranges::all_of(name, [](unsigned char ch) { - return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; - }); + return std::ranges::all_of( + name, [](unsigned char ch) { return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; }); } bool Is_Safe_Archive_Extension(std::string_view extension) { - if (extension.empty() || extension.front() == '.' || - extension.back() == '.') { + if (extension.empty() || extension.front() == '.' || extension.back() == '.') { return false; } - return std::ranges::all_of(extension, [](unsigned char ch) { - return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; - }); + return std::ranges::all_of( + extension, [](unsigned char ch) { return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; }); } -std::string Normalize_Archive_Extension(std::string_view extension, - std::string_view fallback = "zip") { +std::string Normalize_Archive_Extension(std::string_view extension, std::string_view fallback = "zip") { auto normalized = std::string(extension); while (!normalized.empty() && normalized.front() == '.') { normalized.erase(normalized.begin()); @@ -58,8 +53,7 @@ std::string Normalize_Archive_Extension(std::string_view extension, } return normalized; } -std::optional Try_Get_String_Field(const JSON& object, - std::string_view key) { +std::optional Try_Get_String_Field(const JSON& object, std::string_view key) { const JSON* value = object.get(key); if (value == nullptr) { return std::nullopt; @@ -73,9 +67,8 @@ struct Archive_Export_Request { std::string version; Archive_Write_Options archive; }; -Archive_Export_Request -Parse_Archive_Export_Request(const drogon::HttpRequestPtr& req, - std::string_view default_version) { +Archive_Export_Request Parse_Archive_Export_Request(const drogon::HttpRequestPtr& req, + std::string_view default_version) { Archive_Export_Request result; result.version = std::move(default_version); const auto& body = req->getBody(); @@ -109,8 +102,7 @@ Parse_Archive_Export_Request(const drogon::HttpRequestPtr& req, } } else { - result.archive.extension = - Normalize_Archive_Extension(result.archive.extension); + result.archive.extension = Normalize_Archive_Extension(result.archive.extension); } return result; } @@ -118,15 +110,8 @@ const Archive_Layout_Rules& Upgrade_Zip_Layout_Rules() { static const Archive_Layout_Rules rules = [] { Archive_Layout_Rules value; value.directories = { - { - "", - {"adsb_cfg.ini", "config.json", "ecap_server", "lib9002config.json"}, - {"lib9002", "wwwroot"}, - {}, - {} - }, - {"lib9002", {"lib9002.so", "testserver"}, {"env"}, {}, {}} - }; + {"", {"adsb_cfg.ini", "config.json", "ecap_server", "lib9002config.json"}, {"lib9002", "wwwroot"}, {}, {}}, + {"lib9002", {"lib9002.so", "testserver"}, {"env"}, {}, {}}}; return value; }(); return rules; @@ -134,9 +119,7 @@ const Archive_Layout_Rules& Upgrade_Zip_Layout_Rules() { } // namespace void setupCors(); void Global::init_web_server() { - register_http_performance_monitor( - http_monitor_config.access_log, - http_monitor_config.slow_request_threshold_ms); + register_http_performance_monitor(http_monitor_config.access_log, http_monitor_config.slow_request_threshold_ms); setupCors(); static auto& web_server = web_server_config; Web_Server& svr = this->svr; @@ -146,8 +129,7 @@ void Global::init_web_server() { if (std::filesystem::exists(path)) { std::string content; httplib::detail::read_file(path, content); - auto content_type = httplib::detail::find_content_type( - path, {}, "application/octet-stream"); + auto content_type = httplib::detail::find_content_type(path, {}, "application/octet-stream"); if (path.ends_with(".glb")) { content_type = "model/gltf-binary"; } @@ -170,58 +152,51 @@ void Global::init_web_server() { }; auto add_path = [return_file](std::string_view path) { drogon::app().registerHandlerViaRegex( - std::string(path), - [return_file]( - const drogon::HttpRequestPtr& req, - std::function&& callback) { - callback(return_file(web_server.get_true_webapp() + "/index.html")); - }, - {drogon::Get}); - }; - init_tiles(); - drogon::app().registerHandlerViaRegex( - "/", - [return_file]( - const drogon::HttpRequestPtr& req, - std::function&& callback) { + std::string(path), + [return_file](const drogon::HttpRequestPtr& req, + std::function&& callback) { callback(return_file(web_server.get_true_webapp() + "/index.html")); }, {drogon::Get}); + }; + init_tiles(); + drogon::app().registerHandlerViaRegex( + "/", + [return_file](const drogon::HttpRequestPtr& req, std::function&& callback) { + callback(return_file(web_server.get_true_webapp() + "/index.html")); + }, + {drogon::Get}); add_path(R"(^/settings)"); add_path(R"(^/map)"); add_path(R"(^/map3d)"); add_path(R"(^/dsp)"); add_path(R"(^/aircraftlist)"); drogon::app().registerHandlerViaRegex( - R"(^/ui(/.*)?$)", - [return_file]( - const drogon::HttpRequestPtr& req, - std::function&& callback) { - std::cout << req->path() << std::endl; - auto res = drogon::HttpResponse::newHttpResponse(); - auto path = web_server.get_true_webapp(); - auto rp = req->path().substr(3); - if (rp.empty()) { - rp = "/"; - } - auto is_spa_path = [](std::string_view value) { - return value == "/" || value == "/map" || value == "/map3d" || - value == "/settings" || value == "/dsp" || value == "/aircraftlist"; - }; - if (is_spa_path(rp)) { - path += "/index.html"; - } - else { - path += rp; - } - callback(return_file(path)); - }); + R"(^/ui(/.*)?$)", + [return_file](const drogon::HttpRequestPtr& req, std::function&& callback) { + auto res = drogon::HttpResponse::newHttpResponse(); + auto path = web_server.get_true_webapp(); + auto rp = req->path().substr(3); + if (rp.empty()) { + rp = "/"; + } + auto is_spa_path = [](std::string_view value) { + return value == "/" || value == "/map" || value == "/map3d" || value == "/settings" || value == "/dsp" || + value == "/aircraftlist"; + }; + if (is_spa_path(rp)) { + path += "/index.html"; + } + else { + path += rp; + } + callback(return_file(path)); + }); State_Report::instance(); svr.Get(R"(/get_debug_info)", [](HTTP_Param) { JSON arr = JSON::array(); auto& sp = Global::instance()->mode_acs.data_feed_config.pool_; - arr.append(JSON::object( - {{"remain_size", sp.remain_size()}, {"free_size", sp.free_size()}})); + arr.append(JSON::object({{"remain_size", sp.remain_size()}, {"free_size", sp.free_size()}})); res->setBody(arr.to_json_string("", "\n", "")); }); mlat.server(this); @@ -232,90 +207,76 @@ void Global::init_web_server() { dsp_config.server(this); // s.w.init(); drogon::app().registerHandler( - api + "export_logs", - [](const drogon::HttpRequestPtr& req, - std::function&& cb) { - try { - auto export_request = - Parse_Archive_Export_Request(req, Global::instance()->version); - std::string name = export_request.version; - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - std::string data = archive_directory_to_memory( - version_dir / name / "logs", {}, export_request.archive); - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setBody(data); - resp->setContentTypeString("application/octet-stream"); - resp->addHeader("Content-Disposition", - "attachment; filename*=UTF-8''" + name + "_logs." + - std::string(export_request.archive.extension)); - resp->addHeader("ok", "true"); - cb(resp); - } - catch (const std::exception& e) { - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->addHeader("ok", "false"); - Psc::JSON json = - JSON::object({{"message", Psc::platform_2_utf8(e.what())}}); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(json.to_json_string()); - cb(resp); - } - }); + api + "export_logs", + [](const drogon::HttpRequestPtr& req, std::function&& cb) { + try { + auto export_request = Parse_Archive_Export_Request(req, Global::instance()->version); + std::string name = export_request.version; + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + std::string data = archive_directory_to_memory(version_dir / name / "logs", {}, export_request.archive); + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setBody(data); + resp->setContentTypeString("application/octet-stream"); + resp->addHeader("Content-Disposition", + "attachment; filename*=UTF-8''" + name + "_logs." + + std::string(export_request.archive.extension)); + resp->addHeader("ok", "true"); + cb(resp); + } + catch (const std::exception& e) { + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->addHeader("ok", "false"); + Psc::JSON json = JSON::object({{"message", Psc::platform_2_utf8(e.what())}}); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(json.to_json_string()); + cb(resp); + } + }); drogon::app().registerHandler( - api + "export_version", - [](const drogon::HttpRequestPtr& req, - std::function&& cb) { - try { - auto export_request = - Parse_Archive_Export_Request(req, Global::instance()->version); - std::string name = export_request.version; - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - std::cout << "准备压缩:" << std::endl; - std::string data = archive_directory_to_memory( - version_dir / name, - { - "logs/", "uploads/", "drogon_uploads/", - "backups/", // ghw的什么文件路径 - "stack_trace.txt", "pt.log", "ecap_server.log", "Core", "core", - name + ".zip", name + "." + std::string(export_request.archive.extension) - }, - export_request.archive); - std::cout << "压缩成功:" << data.size() << std::endl; - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setBody(data); - resp->setContentTypeString("application/octet-stream"); - resp->addHeader("Content-Disposition", - "attachment; filename*=UTF-8''" + name + "." + - std::string(export_request.archive.extension)); - resp->addHeader("ok", "true"); - cb(resp); - } - catch (const std::exception& e) { - auto message = Psc::platform_2_utf8(e.what()); - std::cout << "导出异常触发:" << message << " " << LOG_POS - << std::endl; - auto resp = drogon::HttpResponse::newHttpResponse(); - Psc::JSON json = JSON::object({{"message", message}}); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(json.to_json_string()); - resp->addHeader("ok", "false"); - cb(resp); - } - }); - drogon::app().registerHandler(api + "restart_device", [](const drogon:: - HttpRequestPtr - & req, - std::function - && cb) { + api + "export_version", + [](const drogon::HttpRequestPtr& req, std::function&& cb) { + try { + auto export_request = Parse_Archive_Export_Request(req, Global::instance()->version); + std::string name = export_request.version; + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + std::cout << "准备压缩:" << std::endl; + std::string data = + archive_directory_to_memory(version_dir / name, + {"logs/", "uploads/", "drogon_uploads/", + "backups/", // ghw的什么文件路径 + "stack_trace.txt", "pt.log", "ecap_server.log", "Core", "core", name + ".zip", + name + "." + std::string(export_request.archive.extension)}, + export_request.archive); + std::cout << "压缩成功:" << data.size() << std::endl; + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setBody(data); + resp->setContentTypeString("application/octet-stream"); + resp->addHeader("Content-Disposition", + "attachment; filename*=UTF-8''" + name + "." + + std::string(export_request.archive.extension)); + resp->addHeader("ok", "true"); + cb(resp); + } + catch (const std::exception& e) { + auto message = Psc::platform_2_utf8(e.what()); + std::cout << "导出异常触发:" << message << " " << LOG_POS << std::endl; + auto resp = drogon::HttpResponse::newHttpResponse(); + Psc::JSON json = JSON::object({{"message", message}}); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(json.to_json_string()); + resp->addHeader("ok", "false"); + cb(resp); + } + }); + drogon::app().registerHandler( + api + "restart_device", + [](const drogon::HttpRequestPtr& req, std::function&& cb) { #ifdef __linux__ std::string root_dir = Psc::get_exe_dir() + "/.."; std::string log_file = fmt::format("{}/restart_device.log", root_dir); - std::string cmd = fmt::format( - R"(systemd-run --scope --slice=system.slice sudo bash "{}/restart_device.bash" > {} 2>&1 &)", - root_dir, log_file); + std::string cmd = + fmt::format(R"(systemd-run --scope --slice=system.slice sudo bash "{}/restart_device.bash" > {} 2>&1 &)", + root_dir, log_file); std::cout << "Generated Command: " << cmd << std::endl; std::system(cmd.c_str()); #endif @@ -325,104 +286,88 @@ void Global::init_web_server() { cb(resp); }); drogon::app().registerHandler( - api + "import_version", - [](const drogon::HttpRequestPtr& req, - std::function&& cb) { - try { - // ---------- 参数校验 ---------- - auto dir = req->getHeader("dir"); - if (!Is_Safe_Version_Directory_Name(dir)) { - throw std::invalid_argument("invalid or missing header: dir"); - } - const auto& body = req->getBody(); - auto archive_layout_result = validate_archive_layout_from_memory( - body.data(), body.size(), Upgrade_Zip_Layout_Rules()); - if (!archive_layout_result) { - throw Invalid_Archive_Error(archive_layout_result.error()); - } - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - // ---------- 路径准备 ---------- - auto targetDir = version_dir / dir; - std::cout << "========dir====" << dir << std::endl; - std::cout << "========version_dir====" << version_dir << std::endl; - std::cout << "========targetDir====" << targetDir << std::endl; - std::filesystem::create_directories(targetDir); - const auto archive_extension = - Normalize_Archive_Extension(req->getHeader("archive-extension")); - auto archivePath = targetDir / (dir + "." + archive_extension); - // ---------- 写 zip ---------- - std::ofstream ofs(archivePath, std::ios::binary); - if (!ofs) { - throw std::runtime_error("open archive failed: " + - archivePath.string()); - } - ofs.write(body.data(), body.size()); - if (!ofs) { - throw std::runtime_error("write archive failed: " + - archivePath.string()); - } - ofs.close(); - if (!ofs) { - throw std::runtime_error("close archive failed: " + - archivePath.string()); - } + api + "import_version", + [](const drogon::HttpRequestPtr& req, std::function&& cb) { + try { + // ---------- 参数校验 ---------- + auto dir = req->getHeader("dir"); + if (!Is_Safe_Version_Directory_Name(dir)) { + throw std::invalid_argument("invalid or missing header: dir"); + } + const auto& body = req->getBody(); + auto archive_layout_result = + validate_archive_layout_from_memory(body.data(), body.size(), Upgrade_Zip_Layout_Rules()); + if (!archive_layout_result) { + throw Invalid_Archive_Error(archive_layout_result.error()); + } + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + // ---------- 路径准备 ---------- + auto targetDir = version_dir / dir; + std::cout << "========dir====" << dir << std::endl; + std::cout << "========version_dir====" << version_dir << std::endl; + std::cout << "========targetDir====" << targetDir << std::endl; + std::filesystem::create_directories(targetDir); + const auto archive_extension = Normalize_Archive_Extension(req->getHeader("archive-extension")); + auto archivePath = targetDir / (dir + "." + archive_extension); + // ---------- 写 zip ---------- + std::ofstream ofs(archivePath, std::ios::binary); + if (!ofs) { + throw std::runtime_error("open archive failed: " + archivePath.string()); + } + ofs.write(body.data(), body.size()); + if (!ofs) { + throw std::runtime_error("write archive failed: " + archivePath.string()); + } + ofs.close(); + if (!ofs) { + throw std::runtime_error("close archive failed: " + archivePath.string()); + } #ifdef _WIN32 - std::string root_dir = version_dir.string(); - std::string old_version = - Global::instance()->version; // Global version info - std::string new_version = dir; - std::string log_file = fmt::format( - "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); - std::string cmd = fmt::format( - R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {{ . '{}/upgrade.legacy' '{}' '{}' > '{}' 2>&1 }}" )", - root_dir, old_version, new_version, log_file); + std::string root_dir = version_dir.string(); + std::string old_version = Global::instance()->version; // Global version info + std::string new_version = dir; + std::string log_file = fmt::format("{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); + std::string cmd = fmt::format( + R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {{ . '{}/upgrade.legacy' '{}' '{}' > '{}' 2>&1 }}" )", + root_dir, old_version, new_version, log_file); #else - std::string root_dir = version_dir.string(); - std::string old_version = - Global::instance()->version; // Global version info - std::string new_version = dir; - std::string log_file = fmt::format( - "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); - std::string cmd = fmt::format( - R"(systemd-run --scope --slice=system.slice sudo bash "{}/upgrade.bash" "{}" "{}" > {} 2>&1 &)", - root_dir, old_version, new_version, log_file); + std::string root_dir = version_dir.string(); + std::string old_version = Global::instance()->version; // Global version info + std::string new_version = dir; + std::string log_file = fmt::format("{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); + std::string cmd = + fmt::format(R"(systemd-run --scope --slice=system.slice sudo bash "{}/upgrade.bash" "{}" "{}" > {} 2>&1 &)", + root_dir, old_version, new_version, log_file); #endif - std::cout << "Generated Command: " << cmd << std::endl; - std::system(cmd.c_str()); - // ---------- 成功响应 ---------- - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(R"({"ok":true})"); - cb(resp); - } - catch (const std::exception& e) { - auto resp = drogon::HttpResponse::newHttpResponse(); - const bool invalid_input = - dynamic_cast(&e) != nullptr || - dynamic_cast(&e) != nullptr; - resp->setStatusCode(invalid_input - ? drogon::k400BadRequest - : drogon::k500InternalServerError); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - auto reason = Psc::platform_2_utf8(e.what()); - std::cout << "异常" << reason << std::endl; - Psc::JSON json = JSON::object({{"ok", false}, {"error", reason}}); - resp->setBody(json.to_json_string()); - cb(resp); - } - }, - {drogon::Post}); + std::cout << "Generated Command: " << cmd << std::endl; + std::system(cmd.c_str()); + // ---------- 成功响应 ---------- + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(R"({"ok":true})"); + cb(resp); + } + catch (const std::exception& e) { + auto resp = drogon::HttpResponse::newHttpResponse(); + const bool invalid_input = dynamic_cast(&e) != nullptr || + dynamic_cast(&e) != nullptr; + resp->setStatusCode(invalid_input ? drogon::k400BadRequest : drogon::k500InternalServerError); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + auto reason = Psc::platform_2_utf8(e.what()); + std::cout << "异常" << reason << std::endl; + Psc::JSON json = JSON::object({{"ok", false}, {"error", reason}}); + resp->setBody(json.to_json_string()); + cb(resp); + } + }, + {drogon::Post}); svr.Post(api + "get_debug_log", [](HTTP_Param) { CHECK_JSON_PARAM - HTTP_REQUIRE_VALUE( - start_serial_number, - params.try_get_number("serial_number")) - auto log = - base64_encode(debug_logger_info_manager.get_info(start_serial_number)); + HTTP_REQUIRE_VALUE(start_serial_number, params.try_get_number("serial_number")) + auto log = base64_encode(debug_logger_info_manager.get_info(start_serial_number)); JSON ret = JSON::object(); ret.append({"log", log}); - ret.append( - {"serial_number", debug_logger_info_manager.get_cur_serial_number()}); + ret.append({"serial_number", debug_logger_info_manager.get_cur_serial_number()}); ret.append({"start_serial_number", start_serial_number}); res->setBody(warp(ret).to_json_string()); }); @@ -456,108 +401,98 @@ void Global::init_web_server() { res->setBody(warp(ret).to_json_string()); }); da.setDefaultHandler( - [](const drogon::HttpRequestPtr& req, - std::function&& callback) { - LOG_WARN << "[http route not found] " - << "path=" << req->path(); - auto res = drogon::HttpResponse::newHttpResponse(); - res->setStatusCode(drogon::k404NotFound); - res->setBody("not found"); - res->addHeader("Content-Type", "text/plain; charset=utf-8"); - callback(res); - }); + [](const drogon::HttpRequestPtr& req, std::function&& callback) { + LOG_WARN << "[http route not found] " + << "path=" << req->path(); + auto res = drogon::HttpResponse::newHttpResponse(); + res->setStatusCode(drogon::k404NotFound); + res->setBody("not found"); + res->addHeader("Content-Type", "text/plain; charset=utf-8"); + callback(res); + }); da.setCustomErrorHandler( - [](drogon::HttpStatusCode status, - const drogon::HttpRequestPtr& req) -> drogon::HttpResponsePtr { - LOG_WARN << "[http error] " - << "path=" << req->path() - << ", status=" << static_cast(status); - auto res = drogon::HttpResponse::newHttpResponse(); - res->setStatusCode(status); - res->setBody("http error"); - res->addHeader("Content-Type", "text/plain; charset=utf-8"); - return res; - }); - da.setExceptionHandler( - [](const std::exception& e, const drogon::HttpRequestPtr& req, - std::function&& callback) { - auto res = drogon::HttpResponse::newHttpResponse(); - if (Is_Invalid_Http_Param(e)) { - LOG_WARN << "[invalid http parameters] " - << "path=" << req->path() << ", detail=" << e.what(); - Log_Request_Body_If_Small(req); - res->setStatusCode(drogon::k400BadRequest); - res->setContentTypeCode(drogon::CT_APPLICATION_JSON); - res->setBody(R"({"code":400,"message":"invalid http parameters"})"); - } - else { - LOG_ERROR << "[handler exception] " - << "path=" << req->path() << ", what=" << e.what(); - res->setStatusCode(drogon::k500InternalServerError); - res->setContentTypeCode(drogon::CT_APPLICATION_JSON); - res->setBody(R"({"code":500,"message":"internal server error"})"); - } - callback(res); - }); + [](drogon::HttpStatusCode status, const drogon::HttpRequestPtr& req) -> drogon::HttpResponsePtr { + LOG_WARN << "[http error] " + << "path=" << req->path() << ", status=" << static_cast(status); + auto res = drogon::HttpResponse::newHttpResponse(); + res->setStatusCode(status); + res->setBody("http error"); + res->addHeader("Content-Type", "text/plain; charset=utf-8"); + return res; + }); + da.setExceptionHandler([](const std::exception& e, const drogon::HttpRequestPtr& req, + std::function&& callback) { + auto res = drogon::HttpResponse::newHttpResponse(); + if (Is_Invalid_Http_Param(e)) { + LOG_WARN << "[invalid http parameters] " + << "path=" << req->path() << ", detail=" << e.what(); + Log_Request_Body_If_Small(req); + res->setStatusCode(drogon::k400BadRequest); + res->setContentTypeCode(drogon::CT_APPLICATION_JSON); + res->setBody(R"({"code":400,"message":"invalid http parameters"})"); + } + else { + LOG_ERROR << "[handler exception] " + << "path=" << req->path() << ", what=" << e.what(); + res->setStatusCode(drogon::k500InternalServerError); + res->setContentTypeCode(drogon::CT_APPLICATION_JSON); + res->setBody(R"({"code":500,"message":"internal server error"})"); + } + callback(res); + }); da.setUploadPath(get_exe_dir() + "/drogon_uploads"); std::cout << "上传路径: " << da.getUploadPath() << std::endl; init_ok = true; } void setupCors() { // Register sync advice to handle CORS preflight (OPTIONS) requests - drogon::app().registerSyncAdvice( - [](const drogon::HttpRequestPtr& req) -> drogon::HttpResponsePtr { - if (req->method() == drogon::HttpMethod::Options) { - auto resp = drogon::HttpResponse::newHttpResponse(); - // Set Access-Control-Allow-Origin header based on the Origin - // request header - const auto& origin = req->getHeader("Origin"); - if (!origin.empty()) { - resp->addHeader("Access-Control-Allow-Origin", origin); - } - // Set Access-Control-Allow-Methods based on the requested method - const auto& requestMethod = - req->getHeader("Access-Control-Request-Method"); - if (!requestMethod.empty()) { - resp->addHeader("Access-Control-Allow-Methods", requestMethod); - } - // Allow credentials to be included in cross-origin requests - resp->addHeader("Access-Control-Allow-Credentials", "true"); - // Set allowed headers from the Access-Control-Request-Headers - // header - const auto& requestHeaders = - req->getHeader("Access-Control-Request-Headers"); - if (!requestHeaders.empty()) { - resp->addHeader("Access-Control-Allow-Headers", requestHeaders); - } - return std::move(resp); - } - return {}; - }); - // Register post-handling advice to add CORS headers to all responses - drogon::app().registerPostHandlingAdvice( - [](const drogon::HttpRequestPtr& req, - const drogon::HttpResponsePtr& resp) -> void { - // Set Access-Control-Allow-Origin based on the Origin request - // header + drogon::app().registerSyncAdvice([](const drogon::HttpRequestPtr& req) -> drogon::HttpResponsePtr { + if (req->method() == drogon::HttpMethod::Options) { + auto resp = drogon::HttpResponse::newHttpResponse(); + // Set Access-Control-Allow-Origin header based on the Origin + // request header const auto& origin = req->getHeader("Origin"); if (!origin.empty()) { resp->addHeader("Access-Control-Allow-Origin", origin); } - // Reflect the requested Access-Control-Request-Method back in the - // response - const auto& requestMethod = - req->getHeader("Access-Control-Request-Method"); + // Set Access-Control-Allow-Methods based on the requested method + const auto& requestMethod = req->getHeader("Access-Control-Request-Method"); if (!requestMethod.empty()) { resp->addHeader("Access-Control-Allow-Methods", requestMethod); } // Allow credentials to be included in cross-origin requests resp->addHeader("Access-Control-Allow-Credentials", "true"); - // Reflect the requested Access-Control-Request-Headers back - const auto& requestHeaders = - req->getHeader("Access-Control-Request-Headers"); + // Set allowed headers from the Access-Control-Request-Headers + // header + const auto& requestHeaders = req->getHeader("Access-Control-Request-Headers"); if (!requestHeaders.empty()) { resp->addHeader("Access-Control-Allow-Headers", requestHeaders); } - }); + return std::move(resp); + } + return {}; + }); + // Register post-handling advice to add CORS headers to all responses + drogon::app().registerPostHandlingAdvice( + [](const drogon::HttpRequestPtr& req, const drogon::HttpResponsePtr& resp) -> void { + // Set Access-Control-Allow-Origin based on the Origin request + // header + const auto& origin = req->getHeader("Origin"); + if (!origin.empty()) { + resp->addHeader("Access-Control-Allow-Origin", origin); + } + // Reflect the requested Access-Control-Request-Method back in the + // response + const auto& requestMethod = req->getHeader("Access-Control-Request-Method"); + if (!requestMethod.empty()) { + resp->addHeader("Access-Control-Allow-Methods", requestMethod); + } + // Allow credentials to be included in cross-origin requests + resp->addHeader("Access-Control-Allow-Credentials", "true"); + // Reflect the requested Access-Control-Request-Headers back + const auto& requestHeaders = req->getHeader("Access-Control-Request-Headers"); + if (!requestHeaders.empty()) { + resp->addHeader("Access-Control-Allow-Headers", requestHeaders); + } + }); } diff --git a/module/Local_Server/server/tiles.cpp b/module/Local_Server/server/tiles.cpp index c8c3c9a..136f7dd 100644 --- a/module/Local_Server/server/tiles.cpp +++ b/module/Local_Server/server/tiles.cpp @@ -274,23 +274,23 @@ public: if (config_.extension.empty() || config_.extension.front() != '.') { throw std::invalid_argument("invalid tile extension: " + config_.extension); } - if (config_.file_format == "directory") { + if (config_.file_format == Map_Tile_File_Format::directory) { resolver_ = std::make_unique(config_); } - else if (config_.file_format == "mbtiles") { + else if (config_.file_format == Map_Tile_File_Format::mbtiles) { for (auto& file : config_.get_true_files()) { mbtiles_files_.push_back(std::make_unique(std::move(file))); } } else { - throw std::invalid_argument("invalid tile file_format: " + config_.file_format); + throw std::invalid_argument("invalid tile file_format: " + Psc::to_string(config_.file_format)); } } asio::awaitable load(const Tile_Request& request, const Tile_Cache_Request& cache_request) const { if (request.z < config_.minimum_level || request.z > config_.maximum_level) { co_return Tile_Load_Result{Tile_Load_Status::Not_Found}; } - if (config_.file_format == "mbtiles") { + if (config_.file_format == Map_Tile_File_Format::mbtiles) { co_return co_await load_mbtiles_tile(request, cache_request); } co_return co_await load_directory_tile(request, cache_request); @@ -336,7 +336,6 @@ private: std::move(content_type), *cache_info}; } asio::awaitable load_mbtiles_tile(Tile_Request request, Tile_Cache_Request cache_request) const { - std::cout << "加载 load_mbtiles_tile" << std::endl; auto content_type = httplib::detail::find_content_type("tile" + config_.extension, {}, "application/octet-stream"); co_return co_await asio::co_spawn( @@ -520,7 +519,7 @@ void register_map_graphics_handler() { return; } try { - global->cesium_graphics_config.from_base_json(&parsed.value()); + global->cesium_graphics_config.from_base_json(&parsed.value(), false); Global::save(); } catch (const std::exception& error) { @@ -643,7 +642,7 @@ void handle_map_model_config_update(const drogon::HttpRequestPtr& req, Global* g if (!parsed.has_value()) { throw std::invalid_argument("invalid map_models"); } - global->map_model_config.from_base_json(&parsed.value()); + global->map_model_config.from_base_json(&parsed.value(), false); Global::save(); } void register_map_models_handler() { @@ -700,11 +699,15 @@ void register_map_view_handler() { } try { auto next_view = global->map_view_config; - next_view.from_base_json(&parsed.value()); + next_view.from_base_json(&parsed.value(), false); if (!global->map_resources_config.is_imagery_key(next_view.map2d.current_imagery_key) || !global->map_resources_config.is_imagery_key(next_view.map3d.current_imagery_key)) { throw std::invalid_argument("invalid current_imagery_key"); } + if (!next_view.map3d.current_terrain_key.empty() && + !global->map_resources_config.is_terrain_key(next_view.map3d.current_terrain_key)) { + throw std::invalid_argument("invalid current_terrain_key"); + } global->map_resources_config.current_imagery_key = key.value(); global->map_view_config = next_view; Global::save(); diff --git a/module/Local_Server_main.cpp b/module/Local_Server_main.cpp index abde734..9bdb33e 100644 --- a/module/Local_Server_main.cpp +++ b/module/Local_Server_main.cpp @@ -1,184 +1,170 @@ -#include +#include +#include +#include +#include +#include +#include +#include #include #include "Local_Server/Crawler/Crawler.h" #include "Local_Server/Data_Source/Data_Source.h" #include "Local_Server/State_Report/State_Report.h" #include "Local_Server/server/Global.h" -#include -#include -#include -#include -#include #include "Local_Server/server/io_coro.h" -#include // ./server ./config.json #ifdef __linux__ #include #endif struct Catch_Memory { - Catch_Memory() { - sm = (std::int64_t) get_system_memory(); - cur = (std::int64_t) get_process_memory(); - } - - std::int64_t MB = 1024 * 1024; - - bool catch_ok() { - auto old_memory = cur; - cur = (std::int64_t) get_process_memory(); - auto change_mb = (cur - old_memory) / MB; - auto cur_mb = cur / MB; - // std::cout << get_current_date_string() << " 时内存" << cur_mb << "MB " - // << " 变更" << change_mb << "MB" << std::endl; - if (cur > memory_max) { - auto rate = (double) cur / (double) sm; - std::cout << get_current_date_string() + " 抓住内存暴涨:" << cur_mb - << "MB" << " 变更" << change_mb << "MB" << std::endl; - std::cout << "\t内存占用" << rate << "%" << std::endl; - stop_program = SIGINT; + Catch_Memory() { + sm = (std::int64_t)get_system_memory(); + cur = (std::int64_t)get_process_memory(); + } + std::int64_t MB = 1024 * 1024; + bool catch_ok() { + auto old_memory = cur; + cur = (std::int64_t)get_process_memory(); + auto change_mb = (cur - old_memory) / MB; + auto cur_mb = cur / MB; + // std::cout << get_current_date_string() << " 时内存" << cur_mb << "MB " + // << " 变更" << change_mb << "MB" << std::endl; + if (cur > memory_max) { + auto rate = (double)cur / (double)sm; + std::cout << get_current_date_string() + " 抓住内存暴涨:" << cur_mb << "MB" << " 变更" << change_mb + << "MB" << std::endl; + std::cout << "\t内存占用" << rate << "%" << std::endl; + stop_program = SIGINT; #if WIN32 #else - system("top"); + system("top"); #endif - return true; - } - return false; - } + return true; + } + return false; + } #if WIN32 - std::int64_t memory_max = 1 * 1024 * 1024 * 1024; + std::int64_t memory_max = 1 * 1024 * 1024 * 1024; #else - std::int64_t memory_max = 1 * 1024 * 1024 * 1024; + std::int64_t memory_max = 1 * 1024 * 1024 * 1024; #endif - std::int64_t cur; - std::int64_t sm; + std::int64_t cur; + std::int64_t sm; }; - -int psc_main(int argc, char *argv[]) { - std::cout << "wyc_main" << std::endl; - if (argc >= 2) { - std::string config_path = argv[1]; - if (config_path.at(0) == '@') { - config_path.replace(0, 1, get_exe_dir()); - } - ::default_config_path = config_path; - } - // std::cout << get_stack_trace() << std::endl; - init_signal_config({SIGINT, SIGTERM}, +int psc_main(int argc, char* argv[]) { + std::cout << "wyc_main" << std::endl; + if (argc >= 2) { + std::string config_path = argv[1]; + if (config_path.at(0) == '@') { + config_path.replace(0, 1, get_exe_dir()); + } + ::default_config_path = config_path; + } + // std::cout << get_stack_trace() << std::endl; + init_signal_config({SIGINT, SIGTERM}, #ifdef WIN32 - {} + {} #else - { - SIGPIPE - } + {SIGPIPE} #endif - ); - auto clear = []() { - std::cout << "保存配置文件 " << LOG_POS << std::endl; - Config::save(); - std::cout << "shutdown" << std::endl; - auto i = Global::instance(); - i->svr.stop(); - i->thread_manager.stop_all_thread(); - Global::instance()->dsp_config.close_dsp_device(); - std::cout << "destroy开始" << std::endl; - Global::destroy(); - std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl; - Base_Logger_Manager::destroy(); - std::cout << " clear完成" << std::endl; - std::cout << " 正常退出" << std::endl; - }; - auto g = Global::instance(); - Psc::set_fail_fast([](std::string_view name) { - // 如果是在 Global::instance() 里面失败是不能调用这个处理函数的 - auto g = Global::instance(); - std::cout << "set_fail_fast 退出原因: 222" << name << std::endl; - std::cout << "shutdown" << LOG_POS << std::endl; - auto id = std::this_thread::get_id(); - std::cout << "id: " << id << std::endl; - Detach_Thread *dt = g->thread_manager.get_thread(id); - if (!dt) { - std::cout << VAR_STR_1((void*)dt) << std::endl; - std::terminate(); - } - std::set excluded_thread; - excluded_thread.insert(dt->name); - std::cout << dt->name << std::endl; - // std::cout << "保存配置文件 " << LOG_POS << std::endl; - // Config::save(); - g->svr.stop(); - g->thread_manager.stop_all_thread(10000, excluded_thread); - std::cout << "22222222" << std::endl; - Global::instance()->dsp_config.close_dsp_device(); - std::cout << "destroy开始" << std::endl; - Global::destroy(); - std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl; - Base_Logger_Manager::destroy(); - std::cout << " clear完成" << std::endl; - std::cout << " std::exit(75) " << name << std::endl; - std::exit(75); - std::cout << "std::exit(75) 完成:" << name << std::endl; - }); - Detach_Thread_Manager &manager = g->thread_manager; - std::cout << "[主线程:" << std::this_thread::get_id() << "]" << " \n" - << std::flush; - manager.test_and_start_thread( - "web服务器线程", [g](std::atomic &running) { - auto &c = Global::instance()->device_config; - std::string ip = "0.0.0.0"; + ); + auto clear = []() { + std::cout << "保存配置文件 " << LOG_POS << std::endl; + Config::save(); + std::cout << "shutdown" << std::endl; + auto i = Global::instance(); + i->svr.stop(); + i->thread_manager.stop_all_thread(); + Global::instance()->dsp_config.close_dsp_device(); + std::cout << "destroy开始" << std::endl; + Global::destroy(); + std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl; + Base_Logger_Manager::destroy(); + std::cout << " clear完成" << std::endl; + std::cout << " 正常退出" << std::endl; + }; + auto g = Global::instance(); + Psc::set_fail_fast([](std::string_view name) { + // 如果是在 Global::instance() 里面失败是不能调用这个处理函数的 + auto g = Global::instance(); + std::cout << "set_fail_fast 退出原因: " << name << std::endl; + std::cout << "shutdown" << LOG_POS << std::endl; + auto id = std::this_thread::get_id(); + std::cout << "id: " << id << std::endl; + Detach_Thread* dt = g->thread_manager.get_thread(id); + if (!dt) { + std::cout << VAR_STR_1((void*)dt) << std::endl; + std::terminate(); + } + std::set excluded_thread; + excluded_thread.insert(dt->name); + std::cout << dt->name << std::endl; + // std::cout << "保存配置文件 " << LOG_POS << std::endl; + // Config::save(); + g->svr.stop(); + g->thread_manager.stop_all_thread(10000, excluded_thread); + std::cout << "22222222" << std::endl; + Global::instance()->dsp_config.close_dsp_device(); + std::cout << "destroy开始" << std::endl; + Global::destroy(); + std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl; + Base_Logger_Manager::destroy(); + std::cout << " clear完成" << std::endl; + std::cout << " std::exit(75) " << name << std::endl; + std::exit(75); + std::cout << "std::exit(75) 完成:" << name << std::endl; + }); + Detach_Thread_Manager& manager = g->thread_manager; + std::cout << "[主线程:" << std::this_thread::get_id() << "]" << " \n" << std::flush; + manager.test_and_start_thread("web服务器", [g](std::atomic& running) { + auto& c = Global::instance()->device_config; + std::string ip = "0.0.0.0"; #ifdef WIN32 - ip = "127.0.0.1"; + ip = "127.0.0.1"; #endif - Net_Config *device = c.list.get("device").value(); - std::cout << "http://" + ip + ":" + std::to_string(device->port) + "\n" - << std::flush; - std::cout << "http://" + device->ip + ":" + - std::to_string(device->port) + "\n" - << std::flush; - if (!g->svr.listen("0.0.0.0", device->port)) { - if (running.load(std::memory_order_acquire)) { - std::cout << "http://" + ip + ":" + std::to_string(device->port) + - "启动失败 退出!\n" - << std::flush; - std::cout << "http://" + device->ip + ":" + - std::to_string(device->port) + "启动失败 退出!\n" - << std::flush; - std::exit(0); - } - } - }); - // manager.test_and_start_thread("io_coro 协程线程", io_coro); - static int t = Global::instance()->mode_acs.read_milliseconds; - g->dsp_config.init_env(); - bool enable = g->mlat.enable; - auto coro = Coro::instance(); - coro->start(); - // Catch_Memory cm; - while (stop_program == 0) { - for (auto &ds: g->mode_acs.data_source_config.map.list()) { - ds->delete_timeout_aircraft(); - } - if (enable) { - g->mlat.refresh(); - } + Net_Config* device = c.list.get("device").value(); + std::cout << "http://" + ip + ":" + std::to_string(device->port) + "\n" << std::flush; + std::cout << "http://" + device->ip + ":" + std::to_string(device->port) + "\n" << std::flush; + if (!g->svr.listen("0.0.0.0", device->port)) { + if (running.load(std::memory_order_acquire)) { + std::cout << "http://" + ip + ":" + std::to_string(device->port) + "启动失败 退出!\n" << std::flush; + std::cout << "http://" + device->ip + ":" + std::to_string(device->port) + "启动失败 退出!\n" + << std::flush; + std::exit(0); + } + } + }); + // manager.test_and_start_thread("io_coro 协程线程", io_coro); + static int t = Global::instance()->mode_acs.read_milliseconds; + g->dsp_config.init_env(); + bool enable = g->mlat.enable; + auto coro = Coro::instance(); + coro->start(); + // Catch_Memory cm; + while (stop_program == 0) { + for (auto& ds : g->mode_acs.data_source_config.map.list()) { + ds->delete_timeout_aircraft(); + } + if (enable) { + g->mlat.refresh(); + } #ifdef __linux__ - if (g->mode_acs.monitor_msg_live) - malloc_trim(0); + if (g->mode_acs.monitor_msg_live) + malloc_trim(0); #endif - std::this_thread::sleep_for(std::chrono::seconds(3)); - if (Global::instance()->init_ok) { - // if (cm.catch_ok()) { - // stop_program = SIGINT; - // break; - // } - } - } - coro->stop(); - if (stop_program == SIGINT || stop_program == SIGTERM) { - clear(); - } - return 0; + std::this_thread::sleep_for(std::chrono::seconds(3)); + if (Global::instance()->init_ok) { + // if (cm.catch_ok()) { + // stop_program = SIGINT; + // break; + // } + } + } + coro->stop(); + if (stop_program == SIGINT || stop_program == SIGTERM) { + clear(); + } + return 0; } - -int main(int argc, char *argv[]) { - return redict_main_with_gtest(argc, argv, psc_main); +int main(int argc, char* argv[]) { + return redict_main_with_gtest(argc, argv, psc_main); } diff --git a/module/dll_source/Dll_Global.cpp b/module/dll_source/Dll_Global.cpp index 858273e..2ca5718 100644 --- a/module/dll_source/Dll_Global.cpp +++ b/module/dll_source/Dll_Global.cpp @@ -1,222 +1,217 @@ #include "Dll_Global.h" #include "Core/Base/JSON.h" #include "Core/Base/SM_RingBuffer.h" -Dll_Global *dg = new Dll_Global(); +Dll_Global* dg = new Dll_Global(); std::string Dll_Global::get_config_path() { - return get_exe_dir() + "/" + "data_progress_config.json"; + return get_exe_dir() + "/" + "data_progress_config.json"; } void Dll_Global::init_when_exe() { - rb = new SM_RingBuffer; - rb->init("rb", 2112 * 1000); - json_func_call = new SM_RingBuffer; - json_func_call->init("json_func_call2", 1000); - mode_acs = new SM_RingBuffer; - mode_acs->init("mode_acs", 2112 * 1000); - void *lib; - { - auto r = try_load_library(Psc::get_abs_path(library_path)); - if (!r) { - Psc::fail_fast(); - } - lib = r.value(); - } - { - auto r = Psc::try_load_function(lib, "adsb_set_iq_cbk"); - if (!r) { - Psc::fail_fast(); - } - set_iq_cbk = (adsb_set_iq_cbk_t)r.value(); - } - { - auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_ddc_param"); - if (!r) { - Psc::fail_fast(); - } - set_less_30Mhz_ddc_param = (adsb_set_less_30Mhz_ddc_param_t)r.value(); - } - { - auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_fft_param"); - if (!r) { - Psc::fail_fast(); - } - set_less_30Mhz_fft_param = (adsb_set_less_30Mhz_fft_param_t)r.value(); - } - std::cout << "set_less_30Mhz_ddc_param " - << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl; - set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, 1); - std::cout << "set_less_30Mhz_fft_param " - << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl; - set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, 1); - std::cout << "set_iq_cbk " << std::endl; - set_iq_cbk( - [](void *phandle, void *pdata, uint64_t length) { - if (length != 2112) { - std::cout << LOG_POS << " IQ回调传入的长度不对!" << std::endl; - return; - } - auto dg = (Dll_Global*)phandle; - // - dg->handle_2112(pdata); - // auto sk = (UHD_Struct_KFFT *) pdata; - // std::cout << (int)sk->DataType << std::endl; - // dg->iq_memory_buffer.push(pdata, length); // length 永远等于2112 - }, - this); + rb = new SM_RingBuffer; + rb->init("rb", 2112 * 1000); + json_func_call = new SM_RingBuffer; + json_func_call->init("json_func_call2", 1000); + mode_acs = new SM_RingBuffer; + mode_acs->init("mode_acs", 2112 * 1000); + void* lib; + { + auto r = try_load_library(Psc::get_abs_path(library_path)); + if (!r) { + Psc::fail_fast(); + } + lib = r.value(); + } + { + auto r = Psc::try_load_function(lib, "adsb_set_iq_cbk"); + if (!r) { + Psc::fail_fast(); + } + set_iq_cbk = (adsb_set_iq_cbk_t)r.value(); + } + { + auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_ddc_param"); + if (!r) { + Psc::fail_fast(); + } + set_less_30Mhz_ddc_param = (adsb_set_less_30Mhz_ddc_param_t)r.value(); + } + { + auto r = Psc::try_load_function(lib, "adsb_set_less_30Mhz_fft_param"); + if (!r) { + Psc::fail_fast(); + } + set_less_30Mhz_fft_param = (adsb_set_less_30Mhz_fft_param_t)r.value(); + } + std::cout << "set_less_30Mhz_ddc_param " << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl; + set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, 1); + std::cout << "set_less_30Mhz_fft_param " << VAR_STR_3(center_freq, sample_rate, band_width) << std::endl; + set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, 1); + std::cout << "set_iq_cbk " << std::endl; + set_iq_cbk( + [](void* phandle, void* pdata, uint64_t length) { + if (length != 2112) { + std::cout << LOG_POS << " IQ回调传入的长度不对!" << std::endl; + return; + } + auto dg = (Dll_Global*)phandle; + // + dg->handle_2112(pdata); + // auto sk = (UHD_Struct_KFFT *) pdata; + // std::cout << (int)sk->DataType << std::endl; + // dg->iq_memory_buffer.push(pdata, length); // length 永远等于2112 + }, + this); } void Dll_Global::init_when_dll() { - Detach_Thread_Manager& manager = dtm; - manager.test_and_start_thread("Dll_Global", [&](std::atomic& run) { - std::mt19937 rng(std::random_device{}()); // 随机数引擎 - std::uniform_int_distribution dist(0 * 256, 70 * 256); - constexpr int size = 64 + 1024 * sizeof(uint16_t); - uint8_t buf[size]; - while (run) { - int fn = fft_point_number / 1024; - auto sk = (UHD_Struct_KFFT*)buf; - uint16_t *fft = (uint16_t*)(buf + 64); - for (int fi = 0; fi < fn; fi++) { - sk->DataType = kd_fft; - sk->Param.FFT.SubFrame = fi; - for (int i = 0; i < 1024; ++i) { - fft[i] = dist(rng); - } - give_call_back(buf, size); - } - uint64_t sleep_ms = fft_period_ms; - uint64_t num = sample_rate / sleep_ms; - uint64_t times = num / 2048; - if (times < 1) { - times = 1; - } - sk->DataType = zd_ddc; - uint16_t *iq = (uint16_t*)(buf + 64); - for (int i = 0; i < 1024; ++i) { - auto random = dist(rng); - iq[i] = random; - } - sk->UsefullLen = 2048; - for (int i = 0; i < times; ++i) { - give_call_back(buf, size); - } - std::this_thread::sleep_for(std::chrono::milliseconds(fft_period_ms)); - } - }); + Detach_Thread_Manager& manager = dtm; + manager.test_and_start_thread("Dll_Global", [&](std::atomic& run) { + std::mt19937 rng(std::random_device{}()); // 随机数引擎 + std::uniform_int_distribution dist(0 * 256, 70 * 256); + constexpr int size = 64 + 1024 * sizeof(uint16_t); + uint8_t buf[size]; + while (run) { + int fn = fft_point_number / 1024; + auto sk = (UHD_Struct_KFFT*)buf; + uint16_t* fft = (uint16_t*)(buf + 64); + for (int fi = 0; fi < fn; fi++) { + sk->DataType = kd_fft; + sk->Param.FFT.SubFrame = fi; + for (int i = 0; i < 1024; ++i) { + fft[i] = dist(rng); + } + give_call_back(buf, size); + } + uint64_t sleep_ms = fft_period_ms; + uint64_t num = sample_rate / sleep_ms; + uint64_t times = num / 2048; + if (times < 1) { + times = 1; + } + sk->DataType = zd_ddc; + uint16_t* iq = (uint16_t*)(buf + 64); + for (int i = 0; i < 1024; ++i) { + auto random = dist(rng); + iq[i] = random; + } + sk->UsefullLen = 2048; + for (int i = 0; i < times; ++i) { + give_call_back(buf, size); + } + std::this_thread::sleep_for(std::chrono::milliseconds(fft_period_ms)); + } + }); } Dll_Global::Dll_Global() { - auto config = try_parse_json_file(get_config_path()); - if (!config.has_value()) { - std::cout << "Dll_Global 配置文件加载失败!" << std::endl; - Psc::fail_fast(); - } - from_base_json(&config.value()); - psm = new std::uint8_t[65536 * 2]; + auto config = try_parse_json_file(get_config_path()); + if (!config.has_value()) { + std::cout << "Dll_Global 配置文件加载失败!" << std::endl; + Psc::fail_fast(); + } + from_base_json(&config.value(), false); + psm = new std::uint8_t[65536 * 2]; } Dll_Global::~Dll_Global() { - delete psm; + delete psm; } void adsb_close() { - std::cout << " adsb_close()" << std::endl; - Dll_Global::instance()->dtm.stop_all_thread(); + std::cout << " adsb_close()" << std::endl; + Dll_Global::instance()->dtm.stop_all_thread(); } void Dll_Global::save() { - std::ofstream config_file; - config_file.open(get_config_path()); - std::string json = to_base_json().to_json_string(); - config_file.write(json.c_str(), static_cast(json.size())); - config_file.close(); + std::ofstream config_file; + config_file.open(get_config_path()); + std::string json = to_base_json().to_json_string(); + config_file.write(json.c_str(), static_cast(json.size())); + config_file.close(); } -void Dll_Global::give_call_back(std::uint8_t *data, size_t len) { - recv_cbk(puser, data, len); - auto sk = (UHD_Struct_KFFT*)data; - if (sk->DataType == kd_fft) { - auto idx_max = fft_point_number / 1024; - auto idx = sk->Param.FFT.SubFrame; - if (idx >= idx_max) { - std::cout << "give_call_back idx 越界" << idx << " >= " << idx_max - << std::endl; - } - } +void Dll_Global::give_call_back(std::uint8_t* data, size_t len) { + recv_cbk(puser, data, len); + auto sk = (UHD_Struct_KFFT*)data; + if (sk->DataType == kd_fft) { + auto idx_max = fft_point_number / 1024; + auto idx = sk->Param.FFT.SubFrame; + if (idx >= idx_max) { + std::cout << "give_call_back idx 越界" << idx << " >= " << idx_max << std::endl; + } + } } -void Dll_Global::handle_2112_test(void *data) { - // 记录开始时间 - auto start = std::chrono::high_resolution_clock::now(); - // 调用目标函数 - handle_2112_pure(data); - // 记录结束时间 - auto end = std::chrono::high_resolution_clock::now(); - // 计算持续时间(微秒) - auto duration = - std::chrono::duration_cast(end - start); - // 输出每次调用的时间 - std::cout << "Average time per call: " << duration.count() << " microseconds" - << std::endl; +void Dll_Global::handle_2112_test(void* data) { + // 记录开始时间 + auto start = std::chrono::high_resolution_clock::now(); + // 调用目标函数 + handle_2112_pure(data); + // 记录结束时间 + auto end = std::chrono::high_resolution_clock::now(); + // 计算持续时间(微秒) + auto duration = std::chrono::duration_cast(end - start); + // 输出每次调用的时间 + std::cout << "Average time per call: " << duration.count() << " microseconds" << std::endl; } -void Dll_Global::handle_2112(void *data) { - handle_2112_pure(data); - // static Frequency_Limit fl(freq); - // if (fl.test()) { - // handle_2112_test(data); - // } else { - // handle_2112_pure(data); - // } +void Dll_Global::handle_2112(void* data) { + handle_2112_pure(data); + // static Frequency_Limit fl(freq); + // if (fl.test()) { + // handle_2112_test(data); + // } else { + // handle_2112_pure(data); + // } } -void Dll_Global::handle_2112_pure(void *data) { - auto d = (UHD_Struct_KFFT*)(data); - auto pdata = (std::uint8_t*)data + 64; - auto idx_max = fft_point_number / 1024; - auto type = d->DataType; - if (type == kd_fft) { - auto idx = d->Param.FFT.SubFrame; - if (idx >= idx_max) { - std::cout << "idx 越界" << idx << " >= " << idx_max << std::endl; - } - else { - memcpy(psm + idx * 2048, pdata, 2048); - } - } +void Dll_Global::handle_2112_pure(void* data) { + auto d = (UHD_Struct_KFFT*)(data); + auto pdata = (std::uint8_t*)data + 64; + auto idx_max = fft_point_number / 1024; + auto type = d->DataType; + if (type == kd_fft) { + auto idx = d->Param.FFT.SubFrame; + if (idx >= idx_max) { + std::cout << "idx 越界" << idx << " >= " << idx_max << std::endl; + } + else { + memcpy(psm + idx * 2048, pdata, 2048); + } + } #if WIN32 - else if (type == kd_ddc || type == zd_ddc) { - dg->rb->write((uint8_t*)data, 2112); - } - else { - Psc::fail_fast(); - } + else if (type == kd_ddc || type == zd_ddc) { + dg->rb->write((uint8_t*)data, 2112); + } + else { + Psc::fail_fast(); + } #else - else { - dg->rb->write((uint8_t*)data, 2112); - } + else { + dg->rb->write((uint8_t*)data, 2112); + } #endif } void Dll_Global::handle_json_call() { - size_t length = 0; - uint8_t json_func_data[1000]; - json_func_call->read(json_func_data, length); - std::string json((const char*)json_func_data, length); - if (!json.empty()) { - auto func_call = Psc::parse_json(json); - auto method = func_call.get_string("method"); - std::cout << func_call.to_json_string() << std::endl; - if (method == "adsb_set_less_30Mhz_ddc_param") { - center_freq = func_call.get_number("center_freq"); - sample_rate = func_call.get_number("sample_rate"); - band_width = func_call.get_number("band_width"); - auto sw = func_call.get_number("sw"); - save(); - set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, sw); - } - if (method == "adsb_set_less_30Mhz_fft_param") { - fft_win_type = (UHD_FFTWin)func_call.get_number("fft_win_type"); - fft_point_number = func_call.get_number("fft_point_number"); - fft_period_ms = func_call.get_number("fft_period_ms"); - auto sw = func_call.get_number("sw"); - save(); - set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, - sw); - } - if (method == "restart_device") { - std::cout << "关闭进程, 然后会被守护进程拉起来" << std::endl; - stop_program = true; - } - } + size_t length = 0; + uint8_t json_func_data[1000]; + json_func_call->read(json_func_data, length); + std::string json((const char*)json_func_data, length); + if (!json.empty()) { + auto func_call = Psc::parse_json(json); + auto method = func_call.get_string("method"); + std::cout << func_call.to_json_string() << std::endl; + if (method == "adsb_set_less_30Mhz_ddc_param") { + center_freq = func_call.get_number("center_freq"); + sample_rate = func_call.get_number("sample_rate"); + band_width = func_call.get_number("band_width"); + auto sw = func_call.get_number("sw"); + save(); + set_less_30Mhz_ddc_param(center_freq, sample_rate, band_width, sw); + } + if (method == "adsb_set_less_30Mhz_fft_param") { + fft_win_type = (UHD_FFTWin)func_call.get_number("fft_win_type"); + fft_point_number = func_call.get_number("fft_point_number"); + fft_period_ms = func_call.get_number("fft_period_ms"); + auto sw = func_call.get_number("sw"); + save(); + set_less_30Mhz_fft_param(fft_win_type, fft_point_number, fft_period_ms, sw); + } + if (method == "restart_device") { + std::cout << "关闭进程, 然后会被守护进程拉起来" << std::endl; + stop_program = true; + } + } +} +void set_error_cbk(error_cbk_t cbk) { } -void set_error_cbk(error_cbk_t cbk) {}