修复问题

This commit is contained in:
2026-08-09 15:30:12 +08:00
parent 6fe0bed78e
commit 4b9dd5c199
15 changed files with 616 additions and 278 deletions
+3 -3
View File
@@ -19,7 +19,7 @@ asio::awaitable<void> Data_Feed_UDP_Server::send_coro(std::string_view data) {
co_return;
}
asio::awaitable<void> Data_Feed_UDP_Server::_open() {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
svr.set_bind_address("0.0.0.0", value.port);
svr.create();
server_logger->c_debug({}, {}, to_string() + "开启!");
@@ -60,7 +60,7 @@ void Data_feed_Config::server(Global* g) {
});
}
void BIN_Msg_Buffer::push(std::string_view msg) {
auto output_packet_size = Global::instance()->mode_acs.data_feed_config.settings.member<&Data_feed_Config_Data::packet_byte_size>().snapshot();
auto output_packet_size = Global::instance()->mode_acs.data_feed_config.settings.member<&Data_feed_Config_Data::packet_byte_size>().read([](const auto& value) { return value; });
std::lock_guard<std::mutex> 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) {
@@ -85,7 +85,7 @@ BIN_Msg_Buffer::BIN_Msg_Buffer() {
msg_list.reserve(8 * 1024);
}
Psc::JSON BIN_Msg_Buffer::state_json() {
auto output_packet_size = Global::instance()->mode_acs.data_feed_config.settings.member<&Data_feed_Config_Data::packet_byte_size>().snapshot();
auto output_packet_size = Global::instance()->mode_acs.data_feed_config.settings.member<&Data_feed_Config_Data::packet_byte_size>().read([](const auto& value) { return value; });
size_t size, cache_size, pool_capacity, pool_free_count;
{
std::lock_guard<std::mutex> g(mtx);
+22 -34
View File
@@ -44,15 +44,13 @@ public:
}
virtual Psc::JSON to_json() {
Psc::JSON ret = With_Loop_Coro::to_base_json();
ret.append(Psc::JSON("output_format", output_format.snapshot().to_base_json()));
ret.append(Psc::JSON("output_format", output_format.read([](const auto& value) { return value.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);
auto value = output_format.snapshot();
value.from_base_json(that_json->get("output_format"), not_exist_use_default_value);
output_format.write([&](auto& target) {
target = value;
output_format.write([&](auto& value) {
value.from_base_json(that_json->get("output_format"), not_exist_use_default_value);
});
}
virtual Psc::JSON get_custom_state_json() {
@@ -96,7 +94,7 @@ public:
Psc::asio_socket::TCP_Server_Coro svr;
Psc::JSON get_custom_state_json() override {
auto& state = svr.state;
auto value = specific.snapshot();
auto value = specific.read([](const auto& value) { return value; });
auto ret = value.to_base_json();
ret.key = "fixed";
auto result = VAR_JSON_1(state);
@@ -115,21 +113,19 @@ public:
}
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Feed::to_json() += specific.snapshot().to_base_json();
return Data_Feed::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
asio::awaitable<void> _close() override {
co_await svr.close_coro();
co_return;
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
svr.set_connect_user_buffer_size(value.connect_user_buffer_size);
svr.set_connect_system_buffer_size(value.connect_system_buffer_size);
svr.set_tcp_no_delay(false);
@@ -206,7 +202,7 @@ public:
co_return;
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
Psc::asio_socket::Sockaddr_In sockaddr_in;
sockaddr_in.ip = value.url;
sockaddr_in.port = value.port;
@@ -217,14 +213,12 @@ public:
}
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Feed::to_json() += specific.snapshot().to_base_json();
return Data_Feed::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
};
class Data_Feed_UDP_Server_Data {
@@ -265,14 +259,12 @@ public:
}
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Feed::to_json() += specific.snapshot().to_base_json();
return Data_Feed::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
asio::awaitable<void> _close() override {
co_await svr.close_coro();
@@ -316,14 +308,12 @@ public:
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Feed::to_json() += specific.snapshot().to_base_json();
return Data_Feed::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
asio::awaitable<void> _close() override {
std::cout << "udp client target address:" << cli.dest_address.to_string() << " closed" << std::endl;
@@ -331,7 +321,7 @@ public:
co_return;
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
cli.create();
cli.set_dest_address(value.url, value.port);
co_await cli.connect_coro();
@@ -392,10 +382,8 @@ public:
t->from_json(&it, not_exist_use_default_value);
map.push_back(t);
}
auto value = settings.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
settings.write([&](auto& target) {
target = value;
settings.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON list() const {
@@ -406,7 +394,7 @@ public:
return connect_json;
}
Psc::JSON to_json() const {
Psc::JSON ret = settings.snapshot().to_base_json();
Psc::JSON ret = settings.read([](const auto& value) { return value.to_base_json(); });
ret.append({"list", list()});
return ret;
}
@@ -53,7 +53,7 @@ Data_Source::Data_Source() {
// parse_format = std::make_shared<Input_Format>();
// 写入到配置文件是懒加载 其他保存时他跟着保存
base_station.handle_when_updated = [this](SSR::HULC_Status_Message msg) {
if (!settings.member<&Data_Source_Data::update_form_gps>().snapshot())
if (!settings.member<&Data_Source_Data::update_form_gps>().read([](const auto& value) { return value; }))
return;
settings.write([&](auto& value) {
value.lat = msg.get_latitude();
@@ -179,7 +179,7 @@ std::optional<std::string> File_Data_Source::get_raw_line(int& ret_index) {
}
std::optional<std::string> log_info = std::nullopt;
if (index == part_infos.size()) {
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
if (config.play_mode == Play_Mode::loop) {
index = 0;
}
@@ -308,7 +308,7 @@ asio::awaitable<void> File_Data_Source::_close() {
}
asio::awaitable<void> File_Data_Source::_open() {
std::lock_guard g(mtx);
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
auto path = Psc::get_abs_path(config.file_path);
namespace fs = std::filesystem;
if (!fs::exists(path)) {
@@ -360,7 +360,7 @@ void File_Data_Source::origin_data_transform_mode_data(std::string& mode_data) {
std::lock_guard g(mtx);
assert(mode_data.size() == 0);
int ret_index = 0;
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
if (config.play_mode != Play_Mode::analysis) {
std::optional<std::string> log_info = get_raw_line(ret_index);
mode_data = log_info.has_value() ? get_true_from_raw_line(this, config.data_type, ret_index, log_info.value()) : "";
@@ -419,7 +419,7 @@ 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;
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
auto buf = reinterpret_cast<char*>(buffer.data());
auto len = read_func_ptr(buf, config.buffer_size);
vs.update(len);
@@ -437,7 +437,7 @@ void Dll_Data_Source::origin_data_transform_mode_data(std::string& mode_data) {
mode_data = ret;
}
asio::awaitable<void> Shared_Memory_Data_Source::_open() {
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
sm = std::make_unique<Psc::SM_RingBuffer>();
sm->init(config.shared_memory_name, config.shared_memory_size);
co_return;
@@ -461,7 +461,7 @@ void Shared_Memory_Data_Source::origin_data_transform_mode_data(std::string& mod
if (Global::instance()->console_config.mode_s_console) {
std::cout << "read:" << data << std::endl;
}
const auto config = specific.snapshot();
const auto config = specific.read([](const auto& value) { return value; });
auto ret = get_true_from_raw_line(this, config.data_type, -1, data);
mode_data = ret;
}
+24 -35
View File
@@ -186,14 +186,12 @@ public:
return ret;
}
virtual Psc::JSON to_json() {
return With_Loop_Coro::to_base_json() += settings.snapshot().to_base_json();
return With_Loop_Coro::to_base_json() += settings.read([](const auto& value) { return value.to_base_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);
auto value = settings.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
settings.write([&](auto& target) {
target = value;
settings.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
std::string buffer;
@@ -233,7 +231,7 @@ public:
type = "TCP_Client_Data_Source";
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
Psc::asio_socket::Sockaddr_In addr;
addr.ip = value.ip;
addr.port = value.port;
@@ -247,14 +245,12 @@ public:
co_return;
}
Psc::JSON to_json() override {
return Data_Source::to_json() += specific.snapshot().to_base_json();
return Data_Source::to_json() += specific.read([](const auto& value) { return value.to_base_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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
asio::awaitable<std::string> read_coro() override {
@@ -288,7 +284,7 @@ public:
type = "Serial_Data_Source";
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
serial = std::make_unique<Psc::serial::Serial_Coro>();
serial->set_serial_name(value.port_name);
serial->set_baud_rate(value.baud_rate);
@@ -317,14 +313,12 @@ public:
co_return co_await serial->read_coro();
}
Psc::JSON to_json() override {
return Data_Source::to_json() += specific.snapshot().to_base_json();
return Data_Source::to_json() += specific.read([](const auto& value) { return value.to_base_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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
std::unique_ptr<Psc::serial::Serial_Coro> serial{};
@@ -392,21 +386,19 @@ public:
std::shared_ptr<Cache_Msg> pre_cache = nullptr;
std::deque<std::shared_ptr<Cache_Msg>> cache_list;
std::string get_true_file_path() const {
return Psc::get_abs_path(specific.member<&File_Data_Source_Data::file_path>().snapshot());
return Psc::get_abs_path(specific.member<&File_Data_Source_Data::file_path>().read([](const auto& value) { return value; }));
}
asio::awaitable<void> _close() override;
asio::awaitable<void> _open() override;
std::vector<std::string> 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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Source::to_json() += specific.snapshot().to_base_json();
return Data_Source::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
void origin_data_transform_mode_data(std::string& data) override;
void handle_mode_s(std::shared_ptr<SSR::Mode_S_Msg>& msg) override;
@@ -453,15 +445,14 @@ public:
std::vector<std::uint8_t> buffer;
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
const auto buffer_size = specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
return value.buffer_size;
});
buffer.resize(value.buffer_size);
buffer.resize(buffer_size);
}
Psc::JSON to_json() override {
return Data_Source::to_json() += specific.snapshot().to_base_json();
return Data_Source::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
void* lib{};
using Func_Type = size_t (*)(char* buf, std::size_t max_len);
@@ -474,7 +465,7 @@ public:
co_return;
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
const auto value = specific.read([](const auto& value) { return value; });
{
auto r = Psc::try_load_library(Psc::get_abs_path(value.library_path));
if (!r) {
@@ -524,14 +515,12 @@ public:
}
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
specific.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
Psc::JSON to_json() override {
return Data_Source::to_json() += specific.snapshot().to_base_json();
return Data_Source::to_json() += specific.read([](const auto& value) { return value.to_base_json(); });
}
asio::awaitable<void> _open() override;
asio::awaitable<void> _close() override;
@@ -1,5 +1,7 @@
#include "Data_Source_Handler.h"
#include <string_view>
#include <tuple>
#include <utility>
#include "Data_Source.h"
#include "Local_Server/server/Global.h"
#include "Local_Server/server/io_coro.h"
@@ -145,7 +147,7 @@ size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data)
}
};
auto f = [this, source, handle_packet](std::string& packet) {
const auto wait = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::wait_process_msg>().snapshot();
const auto wait = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::wait_process_msg>().read([](const auto& value) { return value; });
if (wait) {
handle_packet(packet);
}
@@ -168,29 +170,28 @@ void Data_Source_Handler::handle_mode_s(std::shared_ptr<SSR::Mode_S_Msg>& mode_s
mem2hex(t, true, " "), mem2hex(mode_s_msg->packet, true, " "), t, mode_s_msg->packet);
Psc::fail_fast(data);
}
const auto cfg = Global::instance()->mode_acs.settings.snapshot();
const auto source_cfg = source->settings.snapshot();
bool time_space_filter = cfg.time_space_filter;
bool speed_filter = cfg.speed_filter;
bool use_system_time = source_cfg.ignore_msg_time;
const auto mode_config = Global::instance()->mode_acs.settings.read([](const auto& value) {
return std::tuple{value.time_space_filter, value.speed_filter, value.aircraft_change_list_adsb_range_filter, value.aircraft_change_list_adsb_range_factor, value.max_speed_m_s, value.air_pos_timeout, value.surface_pos_timeout};
});
const auto source_config = source->settings.read([](const auto& value) {
return std::tuple{value.ignore_msg_time, value.base_station_has_valid_position, value.lat, value.lon, value.alt};
});
const auto [time_space_filter, speed_filter, range_filter, range_factor, max_speed_m_s, air_pos_timeout, surface_pos_timeout] = mode_config;
const auto [use_system_time, base_station_has_valid_position, lat, lon, alt] = source_config;
auto base_station_pos = source->base_station.get_pos();
if (!base_station_pos && source_cfg.base_station_has_valid_position)
base_station_pos = SSR::Position_3D{source_cfg.lat, source_cfg.lon, source_cfg.alt};
auto range_filter = cfg.aircraft_change_list_adsb_range_filter;
auto range_factor = cfg.aircraft_change_list_adsb_range_factor;
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_cfg.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_cfg.alt,
range_filter, range_factor};
if (!base_station_pos && base_station_has_valid_position)
base_station_pos = SSR::Position_3D{lat, lon, alt};
SSR::ADS_B_T::Constraint air_constraint{max_speed_m_s, air_pos_timeout, SSR::cpr_cb, time_space_filter,
speed_filter, use_system_time, base_station_pos, alt, range_filter, range_factor};
SSR::ADS_B_T::Constraint surface_constraint{max_speed_m_s, surface_pos_timeout, SSR::cpr_cb, time_space_filter,
speed_filter, use_system_time, base_station_pos, 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) {
auto derived = std::dynamic_pointer_cast<Aircraft>(base);
derived->refresh_external_database_info();
}
if (Global::instance()->mlat.settings.member<&MLAT_Config_Data::merge>().snapshot()) {
if (Global::instance()->mlat.settings.member<&MLAT_Config_Data::merge>().read([](const auto& value) { return value; })) {
auto& mh = Global::instance()->mlat_handler;
mh.push(mode_s_msg);
auto tt = mh.get_all();
@@ -288,31 +289,33 @@ void Data_Source_Handler::refresh_data_feed_key_list() {
const auto feeds = global->mode_acs.data_feed_config.map.list();
const auto relations = global->mode_acs.source_feed_relation_config.map.list();
for (const auto& relation : relations) {
const auto config = relation->settings.snapshot();
if (!config.enable || relation->type != "One_to_One_Relation")
continue;
const auto source = global->mode_acs.data_source_config.map.get(config.source_key);
const auto feed = global->mode_acs.data_feed_config.map.get(config.feed_key);
if (source.has_value() && feed.has_value() && source.value()->enabled() && feed.value()->enabled() && !assignment.contains(config.feed_key))
assignment.emplace(config.feed_key, config.source_key);
relation->settings.read([&](const auto& config) {
if (!config.enable || relation->type != "One_to_One_Relation")
return;
const auto source = global->mode_acs.data_source_config.map.get(config.source_key);
const auto feed = global->mode_acs.data_feed_config.map.get(config.feed_key);
if (source.has_value() && feed.has_value() && source.value()->enabled() && feed.value()->enabled() && !assignment.contains(config.feed_key))
assignment.emplace(config.feed_key, config.source_key);
});
}
for (const auto& relation : relations) {
const auto config = relation->settings.snapshot();
if (!config.enable || relation->type != "Name_One_To_Many_Relation")
continue;
const auto source = global->mode_acs.data_source_config.map.get(config.source_key);
if (!source.has_value() || !source.value()->enabled())
continue;
const std::string& prefix = config.feed_name.empty() ? config.source_key : config.feed_name;
for (const auto& feed : feeds) {
if (!feed->enabled() || assignment.contains(feed->key) || !feed->key.starts_with(prefix))
continue;
assignment.emplace(feed->key, config.source_key);
}
relation->settings.read([&](const auto& config) {
if (!config.enable || relation->type != "Name_One_To_Many_Relation")
return;
const auto source = global->mode_acs.data_source_config.map.get(config.source_key);
if (!source.has_value() || !source.value()->enabled())
return;
const std::string& prefix = config.feed_name.empty() ? config.source_key : config.feed_name;
for (const auto& feed : feeds) {
if (!feed->enabled() || assignment.contains(feed->key) || !feed->key.starts_with(prefix))
continue;
assignment.emplace(feed->key, config.source_key);
}
});
}
bool use_default = false;
for (const auto& relation : relations) {
if (relation->type == "First_Source_To_All_Feed_Relation" && relation->settings.member<&Source_Feed_Relation_Data::enable>().snapshot()) {
if (relation->type == "First_Source_To_All_Feed_Relation" && relation->settings.member<&Source_Feed_Relation_Data::enable>().read([](const auto& value) { return value; })) {
use_default = true;
break;
}
@@ -351,12 +354,12 @@ std::optional<std::string> convert_to_send_format(Data_Source_Handler* ds, const
auto& type = msg->type;
auto fs = dynamic_cast<File_Data_Source*>(msg->source.get());
if (fs) {
if (fs->specific.member<&File_Data_Source_Data::play_mode>().snapshot() == Play_Mode::analysis) {
if (fs->specific.member<&File_Data_Source_Data::play_mode>().read([](const auto& value) { return value; }) == Play_Mode::analysis) {
// std::cout << fs->key << " analysis i ==" << i << std::endl;
}
}
// 出口输出的条件
const auto feed_format = feed->output_format.snapshot();
const auto feed_format = feed->output_format.read([](const auto& value) { return value; });
const auto output_format = feed_format.type;
const auto use_mode_ac = feed_format.use_mode_ac;
const auto use_status = feed_format.use_status;
@@ -488,9 +491,9 @@ void Data_Source_Handler::push_to_feed(const std::shared_ptr<SSR::Msg>& msg) {
refresh_data_feed_key_list();
need_refresh_data_feed_key_list = false;
}
const auto mode_config = Global::instance()->mode_acs.settings.snapshot();
const auto other_size = mode_config.mode_other_max_num;
const auto s_size = mode_config.mode_s_max_num;
const auto [other_size, s_size] = Global::instance()->mode_acs.settings.read([](const auto& value) {
return std::pair{value.mode_other_max_num, value.mode_s_max_num};
});
std::vector<std::string> list;
for (const auto& item : cached_data_feed_key_list) {
auto& key = item.key;
+20 -18
View File
@@ -3,7 +3,7 @@
#include "../server/Global.h"
#include "../server/Performance_Monitor.h"
#include "../server/WebSocket_Manager.h"
#include <tuple>
#include <algorithm>
#include <chrono>
#include <cmath>
@@ -290,7 +290,7 @@ void register_aircraft_stream_ws() {
}
}
Aircraft::Aircraft(std::string_view icao) : Aircraft_Info(icao) {
auto size = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::max_track_point_size>().snapshot();
auto size = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::max_track_point_size>().read([](const auto& value) { return value; });
air_pos_track_list.init(size);
surface_pos_track_list.init(size);
}
@@ -332,7 +332,7 @@ void DataBase::delete_timeout_aircraft() {
std::cout << "未初始化的 timestamp " << LOG_POS << std::endl;
}
long long time = std::time(nullptr) - item->timestamp;
return time > Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::timeout_seconds>().snapshot();
return time > Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::timeout_seconds>().read([](const auto& value) { return value; });
});
}
@@ -360,16 +360,17 @@ std::vector<std::shared_ptr<SSR::Aircraft_Info>>
DataBase::get_visible_aircraft_snapshot() {
std::vector<std::shared_ptr<SSR::Aircraft_Info>> ret;
auto g = Global::instance();
auto min_position_points =
g->mode_acs.settings.member<&Mode_ACS_Config_Data::aircraft_change_list_min_position_points>().snapshot();
auto range_filter = g->mode_acs.settings.member<&Mode_ACS_Config_Data::aircraft_change_list_adsb_range_filter>().snapshot();
auto range_factor = g->mode_acs.settings.member<&Mode_ACS_Config_Data::aircraft_change_list_adsb_range_factor>().snapshot();
const auto [min_position_points, range_filter, range_factor] = g->mode_acs.settings.read([](const auto& value) {
return std::tuple{value.aircraft_change_list_min_position_points, value.aircraft_change_list_adsb_range_filter, value.aircraft_change_list_adsb_range_factor};
});
auto source = g->source(get_key());
auto base_position = base_station.get_pos();
if (source) {
const auto source_config = source->settings.snapshot();
if (!base_position && source_config.base_station_has_valid_position) {
base_position = SSR::Position_3D{source_config.lat, source_config.lon, source_config.alt};
const auto [valid_position, lat, lon, alt] = source->settings.read([](const auto& value) {
return std::tuple{value.base_station_has_valid_position, value.lat, value.lon, value.alt};
});
if (!base_position && valid_position) {
base_position = SSR::Position_3D{lat, lon, alt};
}
}
for (auto &it : aircraft_map.values()) {
@@ -541,13 +542,14 @@ void database_server(Global *g) {
if (db) {
ret = db->base_station.to_Json();
auto target_height =
g->mode_acs.settings.member<&Mode_ACS_Config_Data::adsb_theoretical_target_altitude_meters>().snapshot();
const auto source_config = db->settings.snapshot();
auto range = Base_Station::theoretical_detection_range_meters(source_config.alt,
target_height);
ret.append({"latitude", source_config.lat});
ret.append({"longitude", source_config.lon});
ret.append({"height", source_config.alt});
g->mode_acs.settings.member<&Mode_ACS_Config_Data::adsb_theoretical_target_altitude_meters>().read([](const auto& value) { return value; });
const auto [lat, lon, alt] = db->settings.read([](const auto& value) {
return std::tuple{value.lat, value.lon, value.alt};
});
auto range = Base_Station::theoretical_detection_range_meters(alt, target_height);
ret.append({"latitude", lat});
ret.append({"longitude", lon});
ret.append({"height", alt});
ret.append({"adsb_theoretical_target_altitude_meters", target_height});
ret.append({"adsb_theoretical_detection_range_meters", range});
ret.append({"理论探测范围", range});
@@ -615,7 +617,7 @@ void database_server(Global *g) {
return;
}
auto limit_msg_num = g->mode_acs.settings.member<&Mode_ACS_Config_Data::default_min_aircraft_list_num>().snapshot();
auto limit_msg_num = g->mode_acs.settings.member<&Mode_ACS_Config_Data::default_min_aircraft_list_num>().read([](const auto& value) { return value; });
auto t = params.get("limit_msg_num");
if (t) {
HTTP_REQUIRE_VALUE(requested_limit_msg_num, t->try_number_val<int>())
+279 -41
View File
@@ -6,6 +6,7 @@
#include "adminive/adapters/nlohmann_json.hpp"
#include <algorithm>
#include <charconv>
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
@@ -71,9 +72,61 @@ struct Source_Feed_Relation_Row {
std::string feed_key;
std::string feed_name;
};
struct External_Resource_Row {
std::string name;
std::string description;
std::string download_url;
std::uint64_t update_interval_seconds{};
std::int64_t last_updated_at{};
std::size_t row_count{};
std::string state;
};
struct Backend_Config_Row {
std::string section;
std::string path;
std::string value;
};
}
namespace adminive {
template <>
struct Type_Descriptor<ecap::adminive_config::External_Resource_Row> {
static auto get() {
using T = ecap::adminive_config::External_Resource_Row;
return object<T>("external_resource", "外部数据源管理",
ADMINIVE_FIELD_LABEL(T, name, "数据表"),
ADMINIVE_FIELD_LABEL(T, description, "说明"),
ADMINIVE_FIELD_LABEL(T, download_url, "在线来源"),
ADMINIVE_FIELD_LABEL(T, update_interval_seconds, "建议更新周期(秒)"),
ADMINIVE_FIELD_LABEL(T, last_updated_at, "上次更新时间"),
ADMINIVE_FIELD_LABEL(T, row_count, "行数"),
ADMINIVE_FIELD_LABEL(T, state, "状态"));
}
};
template <>
struct Type_View_Descriptor<ecap::adminive_config::External_Resource_Row> {
static Table_View table() {
using T = ecap::adminive_config::External_Resource_Row;
return table_view<T>(column<&T::name>("数据表").search(), column<&T::description>("说明"), column<&T::download_url>("在线来源"), column<&T::row_count>("行数").sort(), column<&T::last_updated_at>("上次更新时间").sort(), column<&T::update_interval_seconds>("建议更新周期(秒)"), column<&T::state>("状态")).titled("外部数据源管理");
}
};
template <>
struct Type_Descriptor<ecap::adminive_config::Backend_Config_Row> {
static auto get() {
using T = ecap::adminive_config::Backend_Config_Row;
return object<T>("backend_config", "后端完整配置",
ADMINIVE_FIELD_LABEL(T, section, "配置分区"),
ADMINIVE_FIELD_LABEL(T, path, "配置项"),
ADMINIVE_FIELD_LABEL(T, value, "当前值"));
}
};
template <>
struct Type_View_Descriptor<ecap::adminive_config::Backend_Config_Row> {
static Table_View table() {
using T = ecap::adminive_config::Backend_Config_Row;
return table_view<T>(column<&T::section>("配置分区").filter(), column<&T::path>("配置项").search(), column<&T::value>("当前值")).titled("后端完整配置(只读)");
}
};
template <>
struct Type_Descriptor<ecap::adminive_config::Data_Source_Row> {
static auto get() {
using T = ecap::adminive_config::Data_Source_Row;
@@ -274,6 +327,38 @@ adminive::Resource_Transaction<Data_feed_Config_Data> data_feed_settings_transac
};
return transaction;
}
adminive::Resource_Transaction<Map_View_Config> map_view_transaction(Global* global) {
adminive::Resource_Transaction<Map_View_Config> transaction;
transaction.prepare = [global](const Map_View_Config& value, const adminive::Request_Context&) {
if(!Map_View_Config::is_scene_mode(value.scene_mode))
throw adminive::Field_Validation_Error("scene_mode", "场景模式必须为 2d 或 3d");
global->map_resources_config.read([&](const auto& resources) {
if(!resources.is_imagery_key(value.map2d.current_imagery_key))
throw adminive::Field_Validation_Error("map2d.current_imagery_key", "影像源不存在");
if(!resources.is_terrain_key(value.map2d.current_terrain_key))
throw adminive::Field_Validation_Error("map2d.current_terrain_key", "地形源不存在");
if(!resources.is_imagery_key(value.map3d.current_imagery_key))
throw adminive::Field_Validation_Error("map3d.current_imagery_key", "影像源不存在");
if(!resources.is_terrain_key(value.map3d.current_terrain_key))
throw adminive::Field_Validation_Error("map3d.current_terrain_key", "地形源不存在");
});
};
transaction.commit = [global](const Map_View_Config& value, const adminive::Request_Context&) {
global->map_resources_config.write([&](auto& resources) {
resources.current_imagery_key = value.scene_mode == "2d" ? value.map2d.current_imagery_key : value.map3d.current_imagery_key;
});
Config::save(Config_Section::map_view, value.to_base_json());
Config::save(Config_Section::map_resources);
};
transaction.rollback = [global](const Map_View_Config& value, const adminive::Request_Context&) {
global->map_resources_config.write([&](auto& resources) {
resources.current_imagery_key = value.scene_mode == "2d" ? value.map2d.current_imagery_key : value.map3d.current_imagery_key;
});
Config::save(Config_Section::map_view, value.to_base_json());
Config::save(Config_Section::map_resources);
};
return transaction;
}
void save_data_sources(Global* global) {
auto patch = Psc::JSON::object();
patch.append({"data_source", global->mode_acs.data_source_config.to_json()});
@@ -404,32 +489,39 @@ Data_Source_Row source_row(const std::shared_ptr<Data_Source>& source) {
row.key = source->key;
row.type = source_type(source->type);
row.enable = source->enabled();
row.config = source->settings.snapshot();
source->settings.read([&](const auto& value) {
row.config = value;
});
row.state = Psc::to_string(source->state);
if(const auto source_value = dynamic_cast<TCP_Client_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.ip = value.ip;
row.port = value.port;
source_value->specific.read([&](const auto& value) {
row.ip = value.ip;
row.port = value.port;
});
} else if(const auto source_value = dynamic_cast<Serial_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.port_name = value.port_name;
row.baud_rate = value.baud_rate;
source_value->specific.read([&](const auto& value) {
row.port_name = value.port_name;
row.baud_rate = value.baud_rate;
});
} else if(const auto source_value = dynamic_cast<File_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.file_path = value.file_path;
row.data_type = value.data_type;
row.play_mode = value.play_mode;
source_value->specific.read([&](const auto& value) {
row.file_path = value.file_path;
row.data_type = value.data_type;
row.play_mode = value.play_mode;
});
} else if(const auto source_value = dynamic_cast<Dll_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.library_path = value.library_path;
row.function_name = value.function_name;
row.data_type = value.data_type;
row.buffer_size = value.buffer_size;
source_value->specific.read([&](const auto& value) {
row.library_path = value.library_path;
row.function_name = value.function_name;
row.data_type = value.data_type;
row.buffer_size = value.buffer_size;
});
} else if(const auto source_value = dynamic_cast<Shared_Memory_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.shared_memory_name = value.shared_memory_name;
row.shared_memory_size = value.shared_memory_size;
row.data_type = value.data_type;
source_value->specific.read([&](const auto& value) {
row.shared_memory_name = value.shared_memory_name;
row.shared_memory_size = value.shared_memory_size;
row.data_type = value.data_type;
});
}
return row;
}
@@ -475,24 +567,31 @@ Data_Feed_Row feed_row(const std::shared_ptr<Data_Feed>& feed) {
row.key = feed->key;
row.type = feed_type(feed->type);
row.enable = feed->enabled();
row.output_format = feed->output_format.snapshot();
row.format = row.output_format.type;
feed->output_format.read([&](const auto& value) {
row.output_format = value;
row.format = value.type;
});
row.state = Psc::to_string(feed->state);
if(const auto feed_value = dynamic_cast<Data_Feed_TCP_Server*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.port = value.port;
row.connect_user_buffer_size = value.connect_user_buffer_size;
row.connect_system_buffer_size = value.connect_system_buffer_size;
feed_value->specific.read([&](const auto& value) {
row.port = value.port;
row.connect_user_buffer_size = value.connect_user_buffer_size;
row.connect_system_buffer_size = value.connect_system_buffer_size;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_UDP_Server*>(feed.get())) {
row.port = feed_value->specific.member<&Data_Feed_UDP_Server_Data::port>().snapshot();
feed_value->specific.read([&](const auto& value) {
row.port = value.port;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_TCP_Client*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.url = value.url;
row.port = value.port;
feed_value->specific.read([&](const auto& value) {
row.url = value.url;
row.port = value.port;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_UDP_Client*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.url = value.url;
row.port = value.port;
feed_value->specific.read([&](const auto& value) {
row.url = value.url;
row.port = value.port;
});
}
return row;
}
@@ -525,13 +624,14 @@ void apply_feed_row(const std::shared_ptr<Data_Feed>& feed, const Data_Feed_Row&
}
Source_Feed_Relation_Row relation_row(const std::shared_ptr<Source_Feed_Relation>& relation) {
Source_Feed_Relation_Row row;
const auto value = relation->settings.snapshot();
row.key = relation->key;
row.type = relation_type(relation->type);
row.enable = value.enable;
row.source_key = value.source_key;
row.feed_key = value.feed_key;
row.feed_name = value.feed_name;
relation->settings.read([&](const auto& value) {
row.enable = value.enable;
row.source_key = value.source_key;
row.feed_key = value.feed_key;
row.feed_name = value.feed_name;
});
return row;
}
void apply_relation_row(const std::shared_ptr<Source_Feed_Relation>& relation, const Source_Feed_Relation_Row& row) {
@@ -570,6 +670,34 @@ std::vector<Source_Feed_Relation_Row> relation_rows(Global* global) {
rows.push_back(relation_row(relation));
return rows;
}
std::vector<External_Resource_Row> external_resource_rows(Global* global) {
std::map<std::string, External_Resource_Status> status_by_name;
for(auto status : global->external_resources_manager.external_database_status())
status_by_name.emplace(status.name, std::move(status));
const auto config = global->external_resources_manager.to_base_json();
const auto* list = config.get("list");
std::vector<External_Resource_Row> rows;
if(!list)
return rows;
rows.reserve(list->children.size());
for(const auto& item : list->children) {
External_Resources_Data value;
value.from_base_json(&item, false);
External_Resource_Row row;
row.name = value.name;
row.description = value.description;
row.download_url = value.download_url;
row.update_interval_seconds = value.update_interval_seconds;
row.last_updated_at = static_cast<std::int64_t>(value.last_updated_at);
const auto status = status_by_name.find(value.name);
if(status != status_by_name.end()) {
row.row_count = status->second.row_count;
row.state = status->second.message;
}
rows.push_back(std::move(row));
}
return rows;
}
Json source_amis_schema() {
return adminive::to_amis_table_schema<Json, Data_Source_Row>("/api/adminive/config/data_sources", adminive::describe_table_view<Data_Source_Row>());
}
@@ -579,11 +707,72 @@ Json feed_amis_schema() {
Json relation_amis_schema() {
return adminive::to_amis_table_schema<Json, Source_Feed_Relation_Row>("/api/adminive/config/source_feed_relations", adminive::describe_table_view<Source_Feed_Relation_Row>());
}
Json external_resource_amis_schema() {
auto schema = adminive::to_amis_table_schema<Json, External_Resource_Row>("/api/adminive/config/external_resources", adminive::describe_table_view<External_Resource_Row>());
auto& crud = schema["body"][0];
const std::string crud_id = "external_resource_table_crud";
crud["headerToolbar"] = Json::array({Json{{"type", "columns-toggler"}, {"draggable", true}}, "reload", Json{{"type", "button"}, {"label", "全部后端下载并导入"}, {"level", "primary"}, {"actionType", "ajax"}, {"api", Json{{"method", "post"}, {"url", "/api/refresh_external_databases"}}}, {"reload", crud_id}}});
auto& columns = crud["columns"];
if(!columns.empty())
columns.erase(columns.end() - 1);
const auto refresh_button = Json{{"type", "button"}, {"label", "后端下载并导入"}, {"level", "link"}, {"actionType", "ajax"}, {"api", Json{{"method", "post"}, {"url", "/api/refresh_external_database"}, {"data", Json{{"name", "${name}"}}}}}, {"reload", crud_id}};
const auto download_button = Json{{"type", "button"}, {"label", "前端下载"}, {"level", "link"}, {"actionType", "url"}, {"url", "${download_url}"}, {"blank", true}, {"disabledOn", "!this.download_url"}};
const auto upload_button = Json{{"type", "button"}, {"label", "离线导入"}, {"level", "link"}, {"actionType", "dialog"}, {"dialog", Json{{"title", "离线导入 ${name}"}, {"body", Json{{"type", "input-file"}, {"name", "file"}, {"label", "数据文件"}, {"accept", ".csv,.gz,.zip,.txt"}, {"receiver", Json{{"method", "post"}, {"url", "/api/upload_external_database"}, {"data", Json{{"name", "${name}"}}}}}}}}}};
const auto clear_button = Json{{"type", "button"}, {"label", "清空数据表"}, {"level", "link"}, {"className", "text-danger"}, {"actionType", "ajax"}, {"confirmText", "确定清空 ${name}"}, {"api", Json{{"method", "post"}, {"url", "/api/clear_external_database_table"}, {"data", Json{{"name", "${name}"}}}}}, {"reload", crud_id}};
columns.push_back(Json{{"type", "operation"}, {"label", "操作"}, {"buttons", Json::array({refresh_button, download_button, upload_button, clear_button})}});
return schema;
}
void append_backend_config_rows(const Json& value, const std::string& section, const std::string& path, std::vector<Backend_Config_Row>& rows) {
if(value.is_object() && !value.empty()) {
for(auto it = value.begin(); it != value.end(); ++it)
append_backend_config_rows(it.value(), section.empty() ? it.key() : section, path.empty() ? it.key() : path + "." + it.key(), rows);
return;
}
if(value.is_array() && !value.empty()) {
for(std::size_t i = 0; i < value.size(); ++i)
append_backend_config_rows(value[i], section, path + "[" + std::to_string(i) + "]", rows);
return;
}
rows.push_back({section, path, value.is_string() ? value.get<std::string>() : value.dump()});
}
std::vector<Backend_Config_Row> backend_config_rows(Global* global) {
const auto config = Json::parse(global->toJson().to_json_string());
std::vector<Backend_Config_Row> rows;
append_backend_config_rows(config, {}, {}, rows);
return rows;
}
Json backend_config_amis_schema() {
auto schema = adminive::to_amis_table_schema<Json, Backend_Config_Row>("/api/adminive/config/backend_config", adminive::describe_table_view<Backend_Config_Row>());
auto& crud = schema["body"][0];
crud["headerToolbar"] = Json::array({Json{{"type", "columns-toggler"}, {"draggable", true}}, "reload"});
auto& columns = crud["columns"];
if(!columns.empty())
columns.erase(columns.end() - 1);
return schema;
}
Json archive_operations_schema() {
const auto formats = Json::array({Json{{"label", "ZIP (.zip)"}, {"value", "zip"}, {"format", "zip"}, {"filter", ""}, {"extension", "zip"}}, Json{{"label", "TAR (.tar)"}, {"value", "tar"}, {"format", "pax"}, {"filter", ""}, {"extension", "tar"}}, Json{{"label", "TAR.GZ (.tar.gz)"}, {"value", "tar.gz"}, {"format", "pax"}, {"filter", "gzip"}, {"extension", "tar.gz"}}, Json{{"label", "TAR.XZ (.tar.xz)"}, {"value", "tar.xz"}, {"format", "pax"}, {"filter", "xz"}, {"extension", "tar.xz"}}, Json{{"label", "TAR.ZST (.tar.zst)"}, {"value", "tar.zst"}, {"format", "pax"}, {"filter", "zstd"}, {"extension", "tar.zst"}}, Json{{"label", "TAR.BZ2 (.tar.bz2)"}, {"value", "tar.bz2"}, {"format", "pax"}, {"filter", "bzip2"}, {"extension", "tar.bz2"}}, Json{{"label", "TAR.LZ4 (.tar.lz4)"}, {"value", "tar.lz4"}, {"format", "pax"}, {"filter", "lz4"}, {"extension", "tar.lz4"}}, Json{{"label", "7Z (.7z)"}, {"value", "7z"}, {"format", "7zip"}, {"filter", ""}, {"extension", "7z"}}});
return Json{{"title", "导入导出"}, {"formats", std::move(formats)}, {"exports", Json::array({Json{{"name", "版本"}, {"api", "/api/export_version"}, {"allow_version_selection", true}}, Json{{"name", "日志"}, {"api", "/api/export_logs"}, {"allow_version_selection", false}}})}, {"import_api", "/api/import_version"}, {"import_accept", ".tar.zstd,.tar.zst,.tar.gz,.tgz,.tar.xz,.txz,.tar.bz2,.tbz2,.tar.lz4,.zip,.7z,.rar,.tar,.cpio,.iso,.xar"}};
}
Json cesium_models_schema(Global* global) {
Json aircraft_types = Json::array();
global->map_model_config.read([&](const auto& config) {
for(const auto& [key, value] : config.aircraft_models) {
static_cast<void>(value);
aircraft_types.push_back(key);
}
});
return Json{{"title", "Cesium 模型设置"}, {"data_api", "/map/models"}, {"upload_accept", ".glb"}, {"aircraft_types", std::move(aircraft_types)}};
}
Json system_actions_schema() {
return Json{{"type", "panel"}, {"title", "设备操作"}, {"body", Json::array({Json{{"type", "button"}, {"label", "重启 FPGA 设备"}, {"level", "primary"}, {"actionType", "ajax"}, {"confirmText", "确定重启 FPGA 设备?"}, {"api", Json{{"method", "post"}, {"url", "/api/restart_device"}}}}})}};
}
class Adminive_Config_Resources {
public:
explicit Adminive_Config_Resources(Global* global) : global_(global),
mode_acs_resource_(global->mode_acs.settings, mode_acs_path, mode_acs_transaction()),
data_feed_settings_resource_(global->mode_acs.data_feed_config.settings, data_feed_settings_path, data_feed_settings_transaction()),
map_view_resource_(global->map_view_config, map_view_path, map_view_transaction(global)),
mlat_resource_(global->mlat.settings, mlat_path, value_section_transaction<MLAT_Config_Data>(Config_Section::mlat)),
cesium_graphics_resource_(global->cesium_graphics_config.settings, cesium_graphics_path, value_section_transaction<Cesium_Graphics_Config_Data>(Config_Section::cesium_graphics)) {
}
@@ -591,16 +780,49 @@ public:
auto& app = drogon::app();
mode_acs_resource_.bind(app);
data_feed_settings_resource_.bind(app);
map_view_resource_.bind(app);
mlat_resource_.bind(app);
cesium_graphics_resource_.bind(app);
bind_data_sources(app);
bind_data_feeds(app);
bind_relations(app);
bind_external_resources(app);
bind_backend_config(app);
app.registerHandler(manifest_path, [this](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(manifest())));
}, {drogon::Get});
}
private:
void bind_backend_config(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
app.registerHandler(backend_config_path + "/descriptor", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_descriptor_json<Json, Backend_Config_Row>())));
}, get);
app.registerHandler(backend_config_path + "/view", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_view_json<Json, Backend_Config_Row>(adminive::describe_table_view<Backend_Config_Row>()))));
}, get);
app.registerHandler(backend_config_path + "/amis", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(backend_config_amis_schema())));
}, get);
app.registerHandler(backend_config_path, [this](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(list_response<Backend_Config_Row>(backend_config_path, backend_config_rows(global_), read_collection_query(request))));
}, get);
}
void bind_external_resources(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
app.registerHandler(external_resources_path + "/descriptor", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_descriptor_json<Json, External_Resource_Row>())));
}, get);
app.registerHandler(external_resources_path + "/view", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_view_json<Json, External_Resource_Row>(adminive::describe_table_view<External_Resource_Row>()))));
}, get);
app.registerHandler(external_resources_path + "/amis", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(external_resource_amis_schema())));
}, get);
app.registerHandler(external_resources_path, [this](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(list_response<External_Resource_Row>(external_resources_path, external_resource_rows(global_), read_collection_query(request))));
}, get);
}
void bind_data_sources(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
const auto post = adminive::make_drogon_constraints(drogon::Post, {});
@@ -896,7 +1118,7 @@ private:
}, post);
}
Json manifest() const {
const auto view = adminive::composition_view("ecap_config", adminive::compose::frontend(adminive::compose::slot("mode_acs"), adminive::compose::slot("data_feed_settings"), adminive::compose::slot("data_sources"), adminive::compose::slot("data_feeds"), adminive::compose::slot("source_feed_relations"), adminive::compose::slot("mlat"), adminive::compose::slot("cesium_graphics"))).titled("ECAP 配置");
const auto view = adminive::composition_view("ecap_config", adminive::compose::frontend(adminive::compose::slot("mode_acs"), adminive::compose::slot("data_feed_settings"), adminive::compose::slot("data_sources"), adminive::compose::slot("data_feeds"), adminive::compose::slot("source_feed_relations"), adminive::compose::slot("mlat"), adminive::compose::slot("map_view"), adminive::compose::slot("cesium_graphics"), adminive::compose::slot("external_resources"), adminive::compose::slot("archive_operations"), adminive::compose::slot("cesium_models"), adminive::compose::slot("backend_config"), adminive::compose::slot("system_actions"))).titled("ECAP 配置");
const std::vector<adminive::Composition_Slot_Contract> contracts = {
{"mode_acs", "amis_schema", mode_acs_path + "/descriptor", mode_acs_path + "/view", mode_acs_path + "/data", mode_acs_path + "/amis"},
{"data_feed_settings", "amis_schema", data_feed_settings_path + "/descriptor", data_feed_settings_path + "/view", data_feed_settings_path + "/data", data_feed_settings_path + "/amis"},
@@ -904,7 +1126,13 @@ private:
{"data_feeds", "amis_schema", data_feeds_path + "/descriptor", data_feeds_path + "/view", data_feeds_path, data_feeds_path + "/amis"},
{"source_feed_relations", "amis_schema", relations_path + "/descriptor", relations_path + "/view", relations_path, relations_path + "/amis"},
{"mlat", "amis_schema", mlat_path + "/descriptor", mlat_path + "/view", mlat_path + "/data", mlat_path + "/amis"},
{"cesium_graphics", "amis_schema", cesium_graphics_path + "/descriptor", cesium_graphics_path + "/view", cesium_graphics_path + "/data", cesium_graphics_path + "/amis"}
{"map_view", "amis_schema", map_view_path + "/descriptor", map_view_path + "/view", map_view_path + "/data", map_view_path + "/amis"},
{"cesium_graphics", "amis_schema", cesium_graphics_path + "/descriptor", cesium_graphics_path + "/view", cesium_graphics_path + "/data", cesium_graphics_path + "/amis"},
{"external_resources", "amis_schema", external_resources_path + "/descriptor", external_resources_path + "/view", external_resources_path, external_resources_path + "/amis"},
{"archive_operations", "ecap_archive_operations", {}, {}, {}, {}},
{"cesium_models", "ecap_cesium_models", {}, {}, "/map/models", {}},
{"backend_config", "amis_schema", backend_config_path + "/descriptor", backend_config_path + "/view", backend_config_path, backend_config_path + "/amis"},
{"system_actions", "amis_schema", {}, {}, {}, {}}
};
const std::map<std::string, Json> schemas = {
{"mode_acs", mode_acs_resource_.amis_schema()},
@@ -913,15 +1141,24 @@ private:
{"data_feeds", feed_amis_schema()},
{"source_feed_relations", relation_amis_schema()},
{"mlat", mlat_resource_.amis_schema()},
{"cesium_graphics", cesium_graphics_resource_.amis_schema()}
{"map_view", map_view_resource_.amis_schema()},
{"cesium_graphics", cesium_graphics_resource_.amis_schema()},
{"external_resources", external_resource_amis_schema()},
{"archive_operations", archive_operations_schema()},
{"cesium_models", cesium_models_schema(global_)},
{"backend_config", backend_config_amis_schema()},
{"system_actions", system_actions_schema()}
};
return adminive::to_composition_manifest_json<Json>(view, contracts, schemas);
}
static inline const std::string mode_acs_path = "/api/adminive/config/mode_acs";
static inline const std::string data_feed_settings_path = "/api/adminive/config/data_feed_settings";
static inline const std::string map_view_path = "/api/adminive/config/map_view";
static inline const std::string data_sources_path = "/api/adminive/config/data_sources";
static inline const std::string data_feeds_path = "/api/adminive/config/data_feeds";
static inline const std::string relations_path = "/api/adminive/config/source_feed_relations";
static inline const std::string external_resources_path = "/api/adminive/config/external_resources";
static inline const std::string backend_config_path = "/api/adminive/config/backend_config";
static inline const std::string mlat_path = "/api/adminive/config/mlat";
static inline const std::string cesium_graphics_path = "/api/adminive/config/cesium_graphics";
static inline const std::string manifest_path = "/api/adminive/config/manifest";
@@ -929,6 +1166,7 @@ private:
std::mutex topology_mutex_;
adminive::Drogon_Resource<Mode_ACS_Config_Data, Json> mode_acs_resource_;
adminive::Drogon_Resource<Data_feed_Config_Data, Json> data_feed_settings_resource_;
adminive::Drogon_Resource<Map_View_Config, Json> map_view_resource_;
adminive::Drogon_Resource<MLAT_Config_Data, Json> mlat_resource_;
adminive::Drogon_Resource<Cesium_Graphics_Config_Data, Json> cesium_graphics_resource_;
};
+28 -19
View File
@@ -104,9 +104,18 @@ Psc::JSON config_section_value(Global& global, Config_Section section) {
case Config_Section::http_monitor: return global.http_monitor_config.to_base_json();
case Config_Section::mlat: return global.mlat.to_base_json();
case Config_Section::web_server: return global.web_server_config.to_base_json();
case Config_Section::map_resources: return global.map_resources_config.to_base_json();
case Config_Section::map_view: return global.map_view_config.to_base_json();
case Config_Section::map_models: return global.map_model_config.to_base_json();
case Config_Section::map_resources:
return global.map_resources_config.read([](const auto& value) {
return value.to_base_json();
});
case Config_Section::map_view:
return global.map_view_config.read([](const auto& value) {
return value.to_base_json();
});
case Config_Section::map_models:
return global.map_model_config.read([](const auto& value) {
return value.to_base_json();
});
case Config_Section::device: return global.device_config.to_base_json();
case Config_Section::mode_acs: return global.mode_acs.to_base_json();
case Config_Section::log: return global.log_config.to_base_json();
@@ -469,25 +478,25 @@ void Cesium_Graphics_Config::from_base_json(const Psc::JSON* that_json, bool not
return;
if (that_json->valueType != Psc::Object)
throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "cesium_graphics");
auto value = settings.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
value.target_frame_rate = std::clamp(value.target_frame_rate, 1u, 120u);
value.resolution_scale = std::clamp(value.resolution_scale, 0.2, 1.5);
value.msaa_samples = std::clamp(value.msaa_samples, 1u, 8u);
value.maximum_screen_space_error = std::clamp(value.maximum_screen_space_error, 1u, 16u);
value.terrain_maximum_level = std::clamp(value.terrain_maximum_level, 0u, 24u);
value.terrain_cache_tiles = std::clamp(value.terrain_cache_tiles, 16u, 2048u);
value.performance_panel_x = std::max(0.0, value.performance_panel_x);
value.performance_panel_y = std::max(0.0, value.performance_panel_y);
value.view_axes_panel_y = std::max(0.0, value.view_axes_panel_y);
value.view_axes_panel_size = std::clamp(value.view_axes_panel_size, 48.0, 240.0);
value.occlusion_sample_spacing_meters = std::clamp(value.occlusion_sample_spacing_meters, 10.0, 5000.0);
settings.write([&](auto& target) {
target = value;
settings.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
value.target_frame_rate = std::clamp(value.target_frame_rate, 1u, 120u);
value.resolution_scale = std::clamp(value.resolution_scale, 0.2, 1.5);
value.msaa_samples = std::clamp(value.msaa_samples, 1u, 8u);
value.maximum_screen_space_error = std::clamp(value.maximum_screen_space_error, 1u, 16u);
value.terrain_maximum_level = std::clamp(value.terrain_maximum_level, 0u, 24u);
value.terrain_cache_tiles = std::clamp(value.terrain_cache_tiles, 16u, 2048u);
value.performance_panel_x = std::max(0.0, value.performance_panel_x);
value.performance_panel_y = std::max(0.0, value.performance_panel_y);
value.view_axes_panel_y = std::max(0.0, value.view_axes_panel_y);
value.view_axes_panel_size = std::clamp(value.view_axes_panel_size, 48.0, 240.0);
value.occlusion_sample_spacing_meters = std::clamp(value.occlusion_sample_spacing_meters, 10.0, 5000.0);
});
}
Psc::JSON Cesium_Graphics_Config::to_base_json() const {
return settings.snapshot().to_base_json();
return settings.read([](const auto& value) {
return value.to_base_json();
});
}
Map_Model_Item_Config::Map_Model_Item_Config(std::string url) : url(std::move(url)) {
}
+87 -15
View File
@@ -122,22 +122,22 @@ struct Mode_ACS_Config {
std::cout << " ~Mode_S_Config()" << std::endl;
}
Psc::JSON to_base_json() const {
auto ret = settings.snapshot().to_base_json();
auto ret = settings.read([](const auto& value) {
return value.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()));
return ret;
}
void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
auto value = settings.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
settings.write([&](auto& target) {
target = value;
settings.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
SSR::Monitor_Mode_ACS_Message_Num = value.monitor_msg_live;
});
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);
SSR::Monitor_Mode_ACS_Message_Num = value.monitor_msg_live;
}
void server(Global* g);
};
@@ -215,6 +215,17 @@ struct Map_Resources_Config {
[[nodiscard]] bool is_imagery_key(std::string_view key) const;
[[nodiscard]] bool is_terrain_key(std::string_view key) const;
};
namespace adminive {
template <>
struct Type_Descriptor<Map_Resources_Config> {
static auto get() {
using T = Map_Resources_Config;
return object<T>("map_resources_config", "地图资源配置",
ADMINIVE_FIELD_LABEL(T, current_imagery_key, "当前影像源").read_write(),
ADMINIVE_FIELD_LABEL(T, tile_sources, "地图瓦片源").read_write());
}
};
}
struct Map_Camera_Config {
double longitude = 121.27;
double latitude = 37.41;
@@ -224,6 +235,21 @@ struct Map_Camera_Config {
double roll = 0.0;
PSC_USE_JSON
};
namespace adminive {
template <>
struct Type_Descriptor<Map_Camera_Config> {
static auto get() {
using T = Map_Camera_Config;
return object<T>("map_camera_config", "地图相机",
ADMINIVE_FIELD_LABEL(T, longitude, "经度").editable().number_input(),
ADMINIVE_FIELD_LABEL(T, latitude, "纬度").editable().number_input(),
ADMINIVE_FIELD_LABEL(T, height, "高度").editable().number_input(),
ADMINIVE_FIELD_LABEL(T, heading, "航向角").editable().number_input(),
ADMINIVE_FIELD_LABEL(T, pitch, "俯仰角").editable().number_input(),
ADMINIVE_FIELD_LABEL(T, roll, "横滚角").editable().number_input());
}
};
}
struct Map_Tile_View_Config {
std::string current_imagery_key = "imagery";
std::string current_terrain_key = "terrain";
@@ -232,6 +258,19 @@ struct Map_Tile_View_Config {
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
[[nodiscard]] Psc::JSON to_base_json() const;
};
namespace adminive {
template <>
struct Type_Descriptor<Map_Tile_View_Config> {
static auto get() {
using T = Map_Tile_View_Config;
return object<T>("map_tile_view_config", "地图瓦片视图",
ADMINIVE_FIELD_LABEL(T, current_imagery_key, "影像源").editable().text_input(),
ADMINIVE_FIELD_LABEL(T, current_terrain_key, "地形源").editable().text_input(),
ADMINIVE_FIELD_LABEL(T, tile_zoom_mode, "缩放模式").editable().select_input(),
ADMINIVE_FIELD_LABEL(T, tile_display_maximum_level, "显示最大层级").editable().number_input());
}
};
}
struct Map_View_Config {
std::string scene_mode = "3d";
Map_Tile_View_Config map2d;
@@ -242,6 +281,20 @@ struct Map_View_Config {
[[nodiscard]] Psc::JSON to_base_json() const;
[[nodiscard]] static bool is_scene_mode(std::string_view mode);
};
namespace adminive {
template <>
struct Type_Descriptor<Map_View_Config> {
static auto get() {
using T = Map_View_Config;
return object<T>("map_view_config", "地图视图配置",
ADMINIVE_FIELD_LABEL(T, scene_mode, "场景模式").editable().required().text_input(),
ADMINIVE_FIELD_LABEL(T, map2d, "2D 地图").editable(),
ADMINIVE_FIELD_LABEL(T, map3d, "3D 地图").editable(),
ADMINIVE_FIELD_LABEL(T, camera, "相机").editable(),
ADMINIVE_FIELD_LABEL(T, base_station_fly_to_height_offset_meters, "基站飞行高度偏移(米)").editable().number_input());
}
};
}
struct Cesium_Graphics_Config_Data {
bool debug_show_frames_per_second = true;
std::uint32_t target_frame_rate = 30;
@@ -356,6 +409,19 @@ struct Map_Model_Config {
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
[[nodiscard]] Psc::JSON to_base_json() const;
};
namespace adminive {
template <>
struct Type_Descriptor<Map_Model_Config> {
static auto get() {
using T = Map_Model_Config;
return object<T>("map_model_config", "Cesium 模型配置",
ADMINIVE_FIELD_LABEL(T, aircraft_model, "默认飞机模型").read_write(),
ADMINIVE_FIELD_LABEL(T, aircraft_models, "机型模型").read_write(),
ADMINIVE_FIELD_LABEL(T, base_station_model, "基站模型").read_write(),
ADMINIVE_FIELD_LABEL(T, device_model, "设备模型").read_write());
}
};
}
struct Net_Config {
std::string key{};
std::string ip{};
@@ -409,10 +475,10 @@ public:
MLAT_Config mlat;
Device_Config device_config;
Web_Server_Config web_server_config;
Map_Resources_Config map_resources_config;
Map_View_Config map_view_config;
adminive::Managed_Value<Map_Resources_Config> map_resources_config;
adminive::Managed_Value<Map_View_Config> map_view_config;
Cesium_Graphics_Config cesium_graphics_config;
Map_Model_Config map_model_config;
adminive::Managed_Value<Map_Model_Config> map_model_config;
Mode_ACS_Config mode_acs;
Log_Config log_config;
Console_Config console_config{};
@@ -425,10 +491,16 @@ public:
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);
map_resources_config.write([&](auto& value) {
value.from_base_json(that_json->get("map_resources"), not_exist_use_default_value);
});
map_view_config.write([&](auto& value) {
value.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);
map_model_config.write([&](auto& value) {
value.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);
@@ -445,9 +517,9 @@ public:
{"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()},
{"map_resources", map_resources_config.read([](const auto& value) { return value.to_base_json(); })},
{"map_view", map_view_config.read([](const auto& value) { return value.to_base_json(); })},
{"map_models", map_model_config.read([](const auto& value) { return value.to_base_json(); })},
{"device", device_config.to_base_json()},
{"mode_acs", mode_acs.to_base_json()},
//{"ais", ais.to_json()},
+7 -7
View File
@@ -1,6 +1,7 @@
#include "MLAT.h"
#include <fstream>
#include <string_view>
#include <tuple>
#include "Global.h"
time_t datetime_to_timestamp(std::string_view datetime) {
std::tm tm = {};
@@ -98,21 +99,20 @@ void read(MLAT_Data* buf, std::uint16_t* len) {
MLAT_Config::MLAT_Config() {
}
void MLAT_Config::from_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
auto value = settings.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
settings.write([&](auto& target) {
target = value;
const auto [enable, library_path, function_name] = settings.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
return std::tuple{value.enable, value.library_path, value.function_name};
});
if (value.enable) {
if (enable) {
{
auto r = Psc::try_load_library(Psc::get_abs_path(value.library_path));
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, value.function_name);
auto r = Psc::try_load_function(lib, function_name);
if (!r) {
Psc::fail_fast();
}
+3 -1
View File
@@ -62,7 +62,9 @@ public:
~MLAT_Config() = default;
MLAT_Config();
[[nodiscard]] Psc::JSON to_base_json() const {
return settings.snapshot().to_base_json();
return settings.read([](const auto& value) {
return value.to_base_json();
});
}
void* lib{};
using Func_Type = void (*)(MLAT_Data* buf, std::uint16_t* len);
@@ -3,14 +3,12 @@
#include "Global.h"
void Source_Feed_Relation::from_json(const Psc::JSON* that_json) {
Get_J(key) Get_J(type)
auto value = settings.snapshot();
value.from_base_json(that_json, true);
settings.write([&](auto& target) {
target = value;
settings.write([&](auto& value) {
value.from_base_json(that_json, true);
});
}
Psc::JSON Source_Feed_Relation::to_json() const {
auto ret = settings.snapshot().to_base_json();
auto ret = settings.read([](const auto& value) { return value.to_base_json(); });
ret.append({"key", key});
ret.append({"type", type});
return ret;
@@ -47,14 +45,14 @@ bool Source_Feed_Relation_Config::source_has_dependency(std::string_view key) co
for (const auto& relation : map.list()) {
if (relation->type == "First_Source_To_All_Feed_Relation")
continue;
if (relation->settings.member<&Source_Feed_Relation_Data::source_key>().snapshot() == key)
if (relation->settings.member<&Source_Feed_Relation_Data::source_key>().read([](const auto& value) { return value; }) == key)
return true;
}
return false;
}
bool Source_Feed_Relation_Config::feed_has_dependency(std::string_view key) const {
for (const auto& relation : map.list()) {
const auto value = relation->settings.snapshot();
const auto value = relation->settings.read([](const auto& value) { return value; });
if (relation->type == "One_to_One_Relation" && value.feed_key == key)
return true;
if (relation->type == "Name_One_To_Many_Relation") {
@@ -71,7 +69,7 @@ void Source_Feed_Relation_Config::validate(const Source_Feed_Relation& relation,
auto existing = map.get(relation.key);
if (existing.has_value() && relation.key != current_key)
throw std::invalid_argument("关系名称已存在: " + relation.key);
const auto value = relation.settings.snapshot();
const auto value = relation.settings.read([](const auto& value) { return value; });
if (relation.type == "One_to_One_Relation") {
if (!source_exists(value.source_key))
throw std::invalid_argument("数据源不存在: " + value.source_key);
@@ -80,7 +78,7 @@ void Source_Feed_Relation_Config::validate(const Source_Feed_Relation& relation,
for (const auto& item : map.list()) {
if (item->key == current_key || item->type != "One_to_One_Relation")
continue;
if (item->settings.member<&Source_Feed_Relation_Data::feed_key>().snapshot() == value.feed_key)
if (item->settings.member<&Source_Feed_Relation_Data::feed_key>().read([](const auto& value) { return value; }) == value.feed_key)
throw std::invalid_argument("数据馈送已存在一对一关系: " + value.feed_key);
}
return;
+8 -6
View File
@@ -40,7 +40,9 @@ public:
void sync_wait();
[[nodiscard]] bool running() const;
[[nodiscard]] bool enabled() const {
return config.member<&With_Loop_Coro_Config::enable>().snapshot();
return config.member<&With_Loop_Coro_Config::enable>().read([](bool value) {
return value;
});
}
void set_enabled(bool value) {
config.member<&With_Loop_Coro_Config::enable>().write([value](bool& target) {
@@ -48,17 +50,17 @@ public:
});
}
[[nodiscard]] Psc::JSON to_base_json() const {
auto ret = config.snapshot().to_base_json();
auto ret = config.read([](const auto& value) {
return value.to_base_json();
});
ret.append({"type", type});
ret.append({"key", key});
return ret;
}
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
Get_J(type) Get_J(key)
auto value = config.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
config.write([&](auto& target) {
target = value;
config.write([&](auto& value) {
value.from_base_json(that_json, not_exist_use_default_value);
});
}
asio::awaitable<void> tick();
+5 -4
View File
@@ -14,6 +14,7 @@
#include <format>
#include <sstream>
#include <thread>
#include <utility>
static std::string thread_id_str() {
std::ostringstream oss;
oss << std::this_thread::get_id();
@@ -160,9 +161,9 @@ asio::awaitable<void> Data_Feed::loop_coro() {
auto other_num = feed->msg_buffer.mode_other_msg_num.load();
const std::vector<std::string*>& all = feed->msg_buffer.get_all();
Pool_Guard pg(&pool, all);
const auto mode_config = mode_acs.settings.snapshot();
auto num = mode_config.report_data_feed_msg_mum;
auto monitor_msg_live = mode_config.monitor_msg_live;
const auto [num, monitor_msg_live] = mode_acs.settings.read([](const auto& value) {
return std::pair{value.report_data_feed_msg_mum, value.monitor_msg_live};
});
if (monitor_msg_live && num != 0 && all.size() > num && too_many_msg_limit.test()) {
std::ostringstream oss;
oss << "feed_key:" << feed->key << " ";
@@ -227,7 +228,7 @@ asio::awaitable<void> Data_Source::loop_coro() {
if (data_source_debug) {
std::cout << std::format("[4] ds:{} after read thread:{}\n", key, thread_id_str()) << std::flush;;
}
const auto wait = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::wait_process_msg>().snapshot();
const auto wait = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::wait_process_msg>().read([](const auto& value) { return value; });
if (wait) {
// 调度到别的线程
co_await resume_on(co->process_data->get_executor());
+71 -37
View File
@@ -484,19 +484,26 @@ void register_map_resources_handler() {
return;
}
auto key = parsed.value().try_get_string("current_imagery_key");
if (!key.has_value() || !global->map_resources_config.is_imagery_key(key.value())) {
const bool valid_key = key.has_value() && global->map_resources_config.read([&](const auto& config) {
return config.is_imagery_key(key.value());
});
if (!valid_key) {
response->setStatusCode(drogon::k400BadRequest);
response->setContentTypeCode(drogon::CT_TEXT_PLAIN);
response->setBody("invalid current_imagery_key");
callback(response);
return;
}
global->map_resources_config.current_imagery_key = key.value();
global->map_resources_config.write([&](auto& config) {
config.current_imagery_key = key.value();
});
Global::save(Config_Section::map_resources);
}
response->setStatusCode(drogon::k200OK);
response->setContentTypeCode(drogon::CT_APPLICATION_JSON);
response->setBody(global->map_resources_config.to_public_json().to_json_string());
response->setBody(global->map_resources_config.read([](const auto& config) {
return config.to_public_json().to_json_string();
}));
response->addHeader("Cache-Control", "no-store");
callback(response);
},
@@ -538,8 +545,12 @@ void register_map_graphics_handler() {
{drogon::Get, drogon::Post});
}
Psc::JSON make_map_view_response(Global* global) {
auto ret = global->map_view_config.to_base_json();
ret.append({"current_imagery_key", global->map_resources_config.current_imagery_key});
auto ret = global->map_view_config.read([](const auto& config) {
return config.to_base_json();
});
global->map_resources_config.read([&](const auto& config) {
ret.append({"current_imagery_key", config.current_imagery_key});
});
return ret;
}
bool is_multipart_request(const drogon::HttpRequestPtr& req) {
@@ -590,9 +601,13 @@ void save_uploaded_model_file(const drogon::HttpFile& upload, std::string_view m
if (extension != ".glb") {
throw std::invalid_argument("model file must be .glb");
}
if (model_type == "aircraft_type" &&
!global->map_model_config.aircraft_models.contains(std::string(aircraft_model_key))) {
throw std::invalid_argument("unknown aircraft_model_key");
if (model_type == "aircraft_type") {
const bool exists = global->map_model_config.read([&](const auto& config) {
return config.aircraft_models.contains(std::string(aircraft_model_key));
});
if (!exists) {
throw std::invalid_argument("unknown aircraft_model_key");
}
}
auto upload_dir = std::filesystem::path(drogon::app().getUploadPath());
std::filesystem::create_directories(upload_dir);
@@ -610,18 +625,20 @@ void save_uploaded_model_file(const drogon::HttpFile& upload, std::string_view m
std::filesystem::copy_file(temp_path, source_dir / file_name, std::filesystem::copy_options::overwrite_existing);
std::filesystem::remove(temp_path);
auto url = "/ui/model/" + file_name;
if (model_type == "aircraft") {
global->map_model_config.aircraft_model.url = url;
}
else if (model_type == "aircraft_type") {
global->map_model_config.aircraft_models[std::string(aircraft_model_key)].url = url;
}
else if (model_type == "base_station") {
global->map_model_config.base_station_model.url = url;
}
else {
global->map_model_config.device_model.url = url;
}
global->map_model_config.write([&](auto& config) {
if (model_type == "aircraft") {
config.aircraft_model.url = url;
}
else if (model_type == "aircraft_type") {
config.aircraft_models[std::string(aircraft_model_key)].url = url;
}
else if (model_type == "base_station") {
config.base_station_model.url = url;
}
else {
config.device_model.url = url;
}
});
}
void handle_map_model_upload(const drogon::HttpRequestPtr& req, Global* global) {
drogon::MultiPartParser parser;
@@ -641,7 +658,9 @@ 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(), false);
global->map_model_config.write([&](auto& config) {
config.from_base_json(&parsed.value(), false);
});
Global::save(Config_Section::map_models);
}
void register_map_models_handler() {
@@ -661,7 +680,9 @@ void register_map_models_handler() {
}
response->setStatusCode(drogon::k200OK);
response->setContentTypeCode(drogon::CT_APPLICATION_JSON);
response->setBody(global->map_model_config.to_base_json().to_json_string());
response->setBody(global->map_model_config.read([](const auto& config) {
return config.to_base_json().to_json_string();
}));
}
catch (const std::exception& error) {
response->setStatusCode(drogon::k400BadRequest);
@@ -689,7 +710,10 @@ void register_map_view_handler() {
return;
}
auto key = parsed.value().try_get_string("current_imagery_key");
if (!key.has_value() || !global->map_resources_config.is_imagery_key(key.value())) {
const bool valid_key = key.has_value() && global->map_resources_config.read([&](const auto& config) {
return config.is_imagery_key(key.value());
});
if (!valid_key) {
response->setStatusCode(drogon::k400BadRequest);
response->setContentTypeCode(drogon::CT_TEXT_PLAIN);
response->setBody("invalid current_imagery_key");
@@ -697,18 +721,26 @@ void register_map_view_handler() {
return;
}
try {
auto next_view = global->map_view_config;
auto next_view = global->map_view_config.read([](const auto& config) {
return config;
});
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->map_resources_config.read([&](const auto& config) {
if (!config.is_imagery_key(next_view.map2d.current_imagery_key) ||
!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() &&
!config.is_terrain_key(next_view.map3d.current_terrain_key)) {
throw std::invalid_argument("invalid current_terrain_key");
}
});
global->map_resources_config.write([&](auto& config) {
config.current_imagery_key = key.value();
});
global->map_view_config.write([&](auto& config) {
config = std::move(next_view);
});
Global::save(Config_Section::map_resources);
Global::save(Config_Section::map_view);
}
@@ -734,7 +766,9 @@ void Global::init_tiles() {
register_map_graphics_handler();
register_map_models_handler();
register_map_view_handler();
for (const auto& source : map_resources_config.tile_sources) {
register_tile_source_handler(source);
}
map_resources_config.read([](const auto& config) {
for (const auto& source : config.tile_sources) {
register_tile_source_handler(source);
}
});
}