初步修改

This commit is contained in:
2026-08-09 14:13:35 +08:00
parent 1e1e77e41a
commit 6fe0bed78e
26 changed files with 2007 additions and 681 deletions
+30 -81
View File
@@ -53,11 +53,13 @@ Data_Source::Data_Source() {
// parse_format = std::make_shared<Input_Format>();
// 写入到配置文件是懒加载 其他保存时他跟着保存
base_station.handle_when_updated = [this](SSR::HULC_Status_Message msg) {
if (this->update_form_gps) {
lat = msg.get_latitude();
lon = msg.get_longitude();
alt = msg.Alt;
}
if (!settings.member<&Data_Source_Data::update_form_gps>().snapshot())
return;
settings.write([&](auto& value) {
value.lat = msg.get_latitude();
value.lon = msg.get_longitude();
value.alt = msg.Alt;
});
};
}
std::string Data_Source::thread_key() const {
@@ -177,14 +179,15 @@ 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()) {
if (play_mode == Play_Mode::loop) {
const auto config = specific.snapshot();
if (config.play_mode == Play_Mode::loop) {
index = 0;
}
else {
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::this_thread::get_id() << "] " << config.file_path + " 全部加载成功!\n"
<< std::flush;
std::cout << oss.str() << std::flush;
have_report_play_back_all_success = true;
@@ -305,13 +308,14 @@ asio::awaitable<void> File_Data_Source::_close() {
}
asio::awaitable<void> File_Data_Source::_open() {
std::lock_guard g(mtx);
auto path = get_true_file_path();
const auto config = specific.snapshot();
auto path = Psc::get_abs_path(config.file_path);
namespace fs = std::filesystem;
if (!fs::exists(path)) {
state = "文件不存在";
co_return;
}
if (data_type == File_Data_Type::BIN) {
if (config.data_type == File_Data_Type::BIN) {
part_infos = readBinaryFileAsString(path, 1000);
}
else {
@@ -356,9 +360,10 @@ 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;
if (play_mode != Play_Mode::analysis) {
const auto config = specific.snapshot();
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, data_type, ret_index, log_info.value()) : "";
mode_data = log_info.has_value() ? get_true_from_raw_line(this, config.data_type, ret_index, log_info.value()) : "";
}
else {
int num = 0;
@@ -367,7 +372,7 @@ void File_Data_Source::origin_data_transform_mode_data(std::string& mode_data) {
while (log_info.has_value()) {
num++;
auto data = log_info.value();
auto cur = get_true_from_raw_line(this, data_type, ret_index, data);
auto cur = get_true_from_raw_line(this, config.data_type, ret_index, data);
ret += cur;
// 一定要在这个位置,否则会导致遗漏报文
if (num == 1000) {
@@ -414,8 +419,9 @@ 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();
auto buf = reinterpret_cast<char*>(buffer.data());
auto len = read_func_ptr(buf, buffer_size);
auto len = read_func_ptr(buf, config.buffer_size);
vs.update(len);
std::string data(buf, len);
if (data.empty()) {
@@ -424,15 +430,16 @@ void Dll_Data_Source::origin_data_transform_mode_data(std::string& mode_data) {
// std::cout << "Dll_Data_Source::read cost: " << cost << " us\n";
return;
}
auto ret = get_true_from_raw_line(this, data_type, -1, data);
auto ret = get_true_from_raw_line(this, config.data_type, -1, data);
auto end = std::chrono::steady_clock::now();
auto cost = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
// std::cout << "Dll_Data_Source::read cost: " << cost << " us\n";
mode_data = ret;
}
asio::awaitable<void> Shared_Memory_Data_Source::_open() {
const auto config = specific.snapshot();
sm = std::make_unique<Psc::SM_RingBuffer>();
sm->init(shared_memory_name, shared_memory_size);
sm->init(config.shared_memory_name, config.shared_memory_size);
co_return;
}
asio::awaitable<void> Shared_Memory_Data_Source::_close() {
@@ -454,87 +461,29 @@ 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;
}
auto ret = get_true_from_raw_line(this, data_type, -1, data);
const auto config = specific.snapshot();
auto ret = get_true_from_raw_line(this, config.data_type, -1, data);
mode_data = ret;
}
void Data_Source_Config::server(Global* g) {
auto& svr = g->svr;
auto& api = g->api;
std::string name = "data_source";
// 返回所有 JSON 数据的 API
svr.Post(api + "get_data_source_connect", [this](HTTP_Param) {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(key, params.try_get_string("key"))
auto t = map.get(key);
auto value = map.get(key);
JSON ret{nullptr};
if (t.has_value()) {
ret = t.value()->get_all_connect_feed();
}
if (value.has_value())
ret = value.value()->get_all_connect_feed();
res->setBody(warp(ret).to_json_string());
});
svr.Post(api + "get_data_source_state", [this](HTTP_Param) {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(key, params.try_get_string("key"))
auto t = map.get(key);
auto value = map.get(key);
JSON ret{nullptr};
if (t.has_value()) {
ret = t.value()->get_state();
}
if (value.has_value())
ret = value.value()->get_state();
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 + 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(&params, 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<int>("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<Data_Source> ds = create_data_source_from_type(t);
ds->from_json(data, true);
HTTP_REQUIRE_VALUE(enable, data->try_get_bool("enable"))
(void)enable;
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<int>("index"))
HTTP_REQUIRE_VALUE(ds, map.try_get(index))
ds->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<int>("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<int>("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();
});
}
+189 -62
View File
@@ -56,9 +56,9 @@ protected:
};
class Data_Source_Map_Display_Data {
public:
Psc::Copyable_Atomic<bool> base_station_show = true;
Psc::Copyable_Atomic<bool> aircraft_show = true;
Psc::Copyable_Atomic<bool> constant_screen_size = true;
bool base_station_show = true;
bool aircraft_show = true;
bool constant_screen_size = true;
std::string color = "#1677ff";
std::string track_point_color = "#ffff00";
std::string base_station_color = "#1677ff";
@@ -67,9 +67,9 @@ public:
std::uint32_t track_point_pixel_size = 8;
double aircraft_scale = 1.0;
double base_station_scale = 1.0;
Psc::Copyable_Atomic<bool> show_icao = true;
Psc::Copyable_Atomic<bool> show_call_sign = false;
Psc::Copyable_Atomic<bool> show_fly_status = false;
bool show_icao = true;
bool show_call_sign = false;
bool show_fly_status = false;
PSC_USE_JSON
};
class Data_Source_Map_Display_Config {
@@ -83,23 +83,22 @@ public:
return ret;
}
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
if (that_json == nullptr || that_json->valueType != Psc::Object) {
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"), not_exist_use_default_value);
map3d.from_base_json(that_json->get("map3d"), not_exist_use_default_value);
}
};
class Data_Source_Data {
public:
Psc::Copyable_Atomic<bool> base_station_has_valid_position{};
bool base_station_has_valid_position{};
Data_Source_Map_Display_Config map_display;
double lat{};
double lon{};
double alt{};
Psc::Copyable_Atomic<bool> ignore_msg_time = false; // 忽略消息时间戳 如果启用 解码位置将不在判断消息自带时间戳
Psc::Copyable_Atomic<bool> update_form_gps{};
Psc::Copyable_Atomic<bool> keep_mode = true;
bool ignore_msg_time = false;
bool update_form_gps{};
bool 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()});
@@ -111,10 +110,56 @@ public:
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<Data_Source>,
public Data_Source_Handler,
public Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<Data_Source_Map_Display_Data> {
static auto get() {
using T = Data_Source_Map_Display_Data;
return object<T>("data_source_map_display", "地图显示",
ADMINIVE_FIELD_LABEL(T, base_station_show, "显示基站").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, aircraft_show, "显示飞机").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, constant_screen_size, "固定屏幕尺寸").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, color, "颜色").creatable().editable().color_input(),
ADMINIVE_FIELD_LABEL(T, track_point_color, "航迹点颜色").creatable().editable().color_input(),
ADMINIVE_FIELD_LABEL(T, base_station_color, "基站颜色").creatable().editable().color_input(),
ADMINIVE_FIELD_LABEL(T, aircraft_pixel_size, "飞机像素尺寸").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, base_station_pixel_size, "基站像素尺寸").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, track_point_pixel_size, "航迹点像素尺寸").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, aircraft_scale, "飞机缩放").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, base_station_scale, "基站缩放").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, show_icao, "显示 ICAO").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, show_call_sign, "显示呼号").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, show_fly_status, "显示飞行状态").creatable().editable().boolean_input());
}
};
template <>
struct Type_Descriptor<Data_Source_Map_Display_Config> {
static auto get() {
using T = Data_Source_Map_Display_Config;
return object<T>("data_source_map_display_config", "地图显示配置",
ADMINIVE_FIELD_LABEL(T, map2d, "2D 地图").creatable().editable(),
ADMINIVE_FIELD_LABEL(T, map3d, "3D 地图").creatable().editable());
}
};
template <>
struct Type_Descriptor<Data_Source_Data> {
static auto get() {
using T = Data_Source_Data;
return object<T>("data_source_config", "数据源公共配置",
ADMINIVE_FIELD_LABEL(T, base_station_has_valid_position, "基站位置有效").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, map_display, "地图显示").creatable().editable(),
ADMINIVE_FIELD_LABEL(T, lat, "纬度").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, lon, "经度").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, alt, "高度").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, ignore_msg_time, "忽略消息时间戳").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, update_form_gps, "从 GPS 更新位置").creatable().editable().boolean_input(),
ADMINIVE_FIELD_LABEL(T, keep_mode, "保留模式").creatable().editable().boolean_input());
}
};
}
class Data_Source : public std::enable_shared_from_this<Data_Source>, public Data_Source_Handler {
public:
adminive::Managed_Value<Data_Source_Data> settings;
std::shared_ptr<Data_Source> that();
virtual asio::awaitable<std::string> read_coro() {
co_return "";
@@ -122,7 +167,7 @@ public:
bool registered() const;
virtual Psc::JSON get_custom_state_json() = 0;
Psc::JSON get_state();
std::string last_char; // 用于处理奇数字节
std::string last_char;
Data_Source();
asio::awaitable<void> loop_coro() final;
std::shared_ptr<SSR::Mode_Msg> last_prase_msg = nullptr;
@@ -141,11 +186,15 @@ public:
return ret;
}
virtual Psc::JSON to_json() {
return With_Loop_Coro::to_base_json() += Data_Source_Data::to_base_json();
return With_Loop_Coro::to_base_json() += settings.snapshot().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);
Data_Source_Data::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;
});
}
std::string buffer;
std::atomic_bool ask_sleep = false;
@@ -156,8 +205,20 @@ public:
std::uint16_t port{};
PSC_USE_JSON
};
class TCP_Client_Data_Source : public Data_Source, public TCP_Client_Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<TCP_Client_Data_Source_Data> {
static auto get() {
using T = TCP_Client_Data_Source_Data;
return object<T>("tcp_client_data_source", "TCP 客户端配置",
ADMINIVE_FIELD_LABEL(T, ip, "IP 地址").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, port, "端口").creatable().editable().number_input());
}
};
}
class TCP_Client_Data_Source : public Data_Source {
public:
adminive::Managed_Value<TCP_Client_Data_Source_Data> specific;
asio::awaitable<void> handle_in_loop_coro() override {
co_await cli.tick_coro();
co_return;
@@ -172,9 +233,10 @@ public:
type = "TCP_Client_Data_Source";
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
Psc::asio_socket::Sockaddr_In addr;
addr.ip = ip;
addr.port = port;
addr.ip = value.ip;
addr.port = value.port;
cli.set_dest_address(addr);
cli.create();
co_await cli.connect_coro();
@@ -185,11 +247,15 @@ public:
co_return;
}
Psc::JSON to_json() override {
return Data_Source::to_json() += TCP_Client_Data_Source_Data::to_base_json();
return Data_Source::to_json() += specific.snapshot().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);
TCP_Client_Data_Source_Data::from_base_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;
});
}
asio::awaitable<std::string> read_coro() override {
co_return co_await cli.read_coro();
@@ -201,31 +267,38 @@ public:
Baud_Rate_Type baud_rate{};
PSC_USE_JSON
};
class Serial_Data_Source : public Data_Source, public Serial_Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<Serial_Data_Source_Data> {
static auto get() {
using T = Serial_Data_Source_Data;
return object<T>("serial_data_source", "串口数据源配置",
ADMINIVE_FIELD_LABEL(T, port_name, "串口名称").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, baud_rate, "波特率").creatable().editable().select_input());
}
};
}
class Serial_Data_Source : public Data_Source {
public:
adminive::Managed_Value<Serial_Data_Source_Data> specific;
Psc::JSON get_custom_state_json() override {
return Psc::JSON::object();
}
Serial_Data_Source() {
this->type = "Serial_Data_Source";
type = "Serial_Data_Source";
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
serial = std::make_unique<Psc::serial::Serial_Coro>();
serial->set_serial_name(port_name);
serial->set_baud_rate(baud_rate);
serial->set_serial_name(value.port_name);
serial->set_baud_rate(value.baud_rate);
serial->set_parity(Psc::serial::Parity::NoParity);
serial->set_data_bits(Psc::serial::DataBits::Data8);
serial->set_stop_bits(Psc::serial::StopBits::OneStop);
serial->set_flow_control(Psc::serial::FlowControl::HardwareControl);
serial->set_buffer_byte_size(10 * 1024);
bool ok = serial->open();
if (!ok) {
std::cerr << "createSerial " + port_name + ":" + std::to_string(baud_rate) + " 打开串口失败!\n";
}
else {
// std::cerr << "createSerial " + serial_name + ":" +
// std::to_string(baud_rate) + " 打开串口成功!\n";
}
if (!serial->open())
std::cerr << "createSerial " + value.port_name + ":" + std::to_string(value.baud_rate) + " 打开串口失败!\n";
co_return;
}
asio::awaitable<void> _close() override {
@@ -234,29 +307,30 @@ public:
co_return;
}
asio::awaitable<void> handle_in_loop_coro() override {
if (serial) {
if (serial)
co_await serial->tick_coro();
}
co_return;
}
asio::awaitable<std::string> read_coro() override {
if (!serial) {
if (!serial)
co_return "";
}
co_return co_await serial->read_coro();
}
Psc::JSON to_json() override {
return Data_Source::to_json() += Serial_Data_Source_Data::to_base_json();
return Data_Source::to_json() += specific.snapshot().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);
Serial_Data_Source_Data::from_base_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;
});
}
std::unique_ptr<Psc::serial::Serial_Coro> serial{};
~Serial_Data_Source() override {
if (serial) {
if (serial)
serial->close();
}
}
};
enum class File_Data_Type {
@@ -278,8 +352,21 @@ public:
Play_Mode play_mode = Play_Mode::one;
PSC_USE_JSON
};
class File_Data_Source : public Data_Source, public File_Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<File_Data_Source_Data> {
static auto get() {
using T = File_Data_Source_Data;
return object<T>("file_data_source", "文件数据源配置",
ADMINIVE_FIELD_LABEL(T, file_path, "文件路径").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, data_type, "数据格式").creatable().editable().select_input(),
ADMINIVE_FIELD_LABEL(T, play_mode, "播放模式").creatable().editable().select_input());
}
};
}
class File_Data_Source : public Data_Source {
public:
adminive::Managed_Value<File_Data_Source_Data> specific;
bool have_report_play_back_all_success = false;
std::string state = "null";
Psc::JSON get_custom_state_json() override {
@@ -288,7 +375,7 @@ public:
return VAR_JSON_5(cur_virtual_time, playback_speed_rate, state, index, part_infos.size());
}
File_Data_Source() {
this->type = "File_Data_Source";
type = "File_Data_Source";
}
~File_Data_Source() override = default;
void before_handle_msg(std::shared_ptr<SSR::Mode_Msg>& msg) override;
@@ -305,17 +392,21 @@ 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(file_path);
return Psc::get_abs_path(specific.member<&File_Data_Source_Data::file_path>().snapshot());
}
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);
File_Data_Source_Data::from_base_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;
});
}
Psc::JSON to_json() override {
return Data_Source::to_json() += File_Data_Source_Data::to_base_json();
return Data_Source::to_json() += specific.snapshot().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;
@@ -333,8 +424,22 @@ public:
std::size_t buffer_size{};
PSC_USE_JSON
};
class Dll_Data_Source : public Data_Source, public Dll_Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<Dll_Data_Source_Data> {
static auto get() {
using T = Dll_Data_Source_Data;
return object<T>("dll_data_source", "DLL 数据源配置",
ADMINIVE_FIELD_LABEL(T, library_path, "库路径").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, function_name, "函数名").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, data_type, "数据格式").creatable().editable().select_input(),
ADMINIVE_FIELD_LABEL(T, buffer_size, "读取缓冲区大小").creatable().editable().number_input());
}
};
}
class Dll_Data_Source : public Data_Source {
public:
adminive::Managed_Value<Dll_Data_Source_Data> specific;
Psc::JSON get_custom_state_json() override {
auto ret = VAR_JSON_1(state);
ret.append({"read_vaild_len", vs.to_string()});
@@ -342,21 +447,24 @@ public:
}
Psc::Value_Statistics vs;
Dll_Data_Source() {
this->type = "Dll_Data_Source";
type = "Dll_Data_Source";
}
~Dll_Data_Source() override = default;
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);
Dll_Data_Source_Data::from_base_json(that_json, not_exist_use_default_value);
buffer.resize(buffer_size);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
});
buffer.resize(value.buffer_size);
}
Psc::JSON to_json() override {
return Data_Source::to_json() += Dll_Data_Source_Data::to_base_json();
return Data_Source::to_json() += specific.snapshot().to_base_json();
}
void* lib{};
using Func_Type = size_t (*)(char* buf, std::size_t max_len);
// using Func_Type = std::uint16_t (*)(char *buf, std::uint16_t max_len);
Func_Type read_func_ptr{};
using Call_Back = void (*)(char* buf, std::size_t len);
using set_Call_back = void (*)(Call_Back);
@@ -366,8 +474,9 @@ public:
co_return;
}
asio::awaitable<void> _open() override {
const auto value = specific.snapshot();
{
auto r = Psc::try_load_library(Psc::get_abs_path(library_path));
auto r = Psc::try_load_library(Psc::get_abs_path(value.library_path));
if (!r) {
state = r.error().message();
co_return;
@@ -375,10 +484,10 @@ public:
lib = r.value();
}
{
auto r = Psc::try_load_function(lib, function_name);
auto r = Psc::try_load_function(lib, value.function_name);
if (!r) {
state = r.error().message();
std::cout << LOG_POS << " [" << function_name << "] 函数指针加载失败!" << std::endl;
std::cout << LOG_POS << " [" << value.function_name << "] 函数指针加载失败!" << std::endl;
co_return;
}
read_func_ptr = (Func_Type)r.value();
@@ -395,17 +504,34 @@ public:
File_Data_Type data_type = File_Data_Type::BIN_Blank_Text;
PSC_USE_JSON
};
class Shared_Memory_Data_Source : public Data_Source, public Shared_Memory_Data_Source_Data {
namespace adminive {
template <>
struct Type_Descriptor<Shared_Memory_Data_Source_Data> {
static auto get() {
using T = Shared_Memory_Data_Source_Data;
return object<T>("shared_memory_data_source", "共享内存数据源配置",
ADMINIVE_FIELD_LABEL(T, shared_memory_name, "共享内存名称").creatable().editable().text_input(),
ADMINIVE_FIELD_LABEL(T, shared_memory_size, "共享内存大小").creatable().editable().number_input(),
ADMINIVE_FIELD_LABEL(T, data_type, "数据格式").creatable().editable().select_input());
}
};
}
class Shared_Memory_Data_Source : public Data_Source {
public:
adminive::Managed_Value<Shared_Memory_Data_Source_Data> specific;
Psc::JSON get_custom_state_json() override {
return Psc::JSON::object();
}
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);
auto value = specific.snapshot();
value.from_base_json(that_json, not_exist_use_default_value);
specific.write([&](auto& target) {
target = value;
});
}
Psc::JSON to_json() override {
return Data_Source::to_json() += Shared_Memory_Data_Source_Data::to_base_json();
return Data_Source::to_json() += specific.snapshot().to_base_json();
}
asio::awaitable<void> _open() override;
asio::awaitable<void> _close() override;
@@ -429,6 +555,7 @@ inline std::shared_ptr<Data_Source> create_data_source_from_type(std::string_vie
std::cout << "未知 Data_Source type类型!" << std::endl;
throw std::invalid_argument("unknown Data_Source type: " + std::string(t));
}
ret->type = std::string(t);
return ret;
}
struct Data_Source_Config {
@@ -441,14 +568,14 @@ struct Data_Source_Config {
map.push_back(ds);
}
}
Psc::JSON list() {
Psc::JSON list() const {
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 to_json() const {
Psc::JSON ret = Psc::JSON::object();
ret.append({"list", list()});
return ret;
@@ -145,7 +145,7 @@ size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data)
}
};
auto f = [this, source, handle_packet](std::string& packet) {
auto& wait = Global::instance()->mode_acs.wait_process_msg;
const auto wait = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::wait_process_msg>().snapshot();
if (wait) {
handle_packet(packet);
}
@@ -168,29 +168,29 @@ 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);
}
auto& cfg = Global::instance()->mode_acs;
bool time_space_filter = cfg.time_space_filter.load();
bool speed_filter = cfg.speed_filter.load();
bool use_system_time = source->ignore_msg_time.load();
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;
auto base_station_pos = source->base_station.get_pos();
if (!base_station_pos && source->base_station_has_valid_position.load()) {
base_station_pos = SSR::Position_3D{source->lat, source->lon, source->alt};
}
auto range_filter = cfg.aircraft_change_list_adsb_range_filter.load();
auto range_factor = cfg.aircraft_change_list_adsb_range_factor.load();
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};
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};
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.merge) {
if (Global::instance()->mlat.settings.member<&MLAT_Config_Data::merge>().snapshot()) {
auto& mh = Global::instance()->mlat_handler;
mh.push(mode_s_msg);
auto tt = mh.get_all();
@@ -216,10 +216,13 @@ void Data_Source_Handler::handle_mode_s(std::shared_ptr<SSR::Mode_S_Msg>& mode_s
if (o_pos.has_value() && o_alt.has_value()) {
have_pos = true;
auto pos = o_pos.value();
source->alt = o_alt.value();
const auto altitude = o_alt.value();
source->settings.member<&Data_Source_Data::alt>().write([altitude](double& value) {
value = altitude;
});
double x, y, z;
SSR::CPR::WGS84_LBH_to_XYZ(pos.lon, pos.lat, source->alt, x, y, z);
oss << "\tpos[" << pos.lon << "," << pos.lat << "," << source->alt << "]" << std::endl;
SSR::CPR::WGS84_LBH_to_XYZ(pos.lon, pos.lat, altitude, x, y, z);
oss << "\tpos[" << pos.lon << "," << pos.lat << "," << altitude << "]" << std::endl;
oss << "\tXYZ[" << x << "," << y << "," << z << "]" << std::endl;
}
}
@@ -279,90 +282,85 @@ void Data_Source_Handler::handle_HULC(std::string_view packet) {
}
}
void Data_Source_Handler::refresh_data_feed_key_list() {
// std::cout << key << " refresh_data_feed_key_list" << std::endl;
std::vector<std::string> tmp;
for (auto& relation : Global::instance()->mode_acs.source_feed_relation_config.map.list()) {
if (!relation->enable)
auto* global = Global::instance();
std::map<std::string, std::string> assignment;
const auto sources = global->mode_acs.data_source_config.map.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;
if (relation->type == "One_to_One_Relation") {
auto t = dynamic_cast<One_to_One_Relation*>(relation.get());
// std::cout << VAR_STR_2(t->source_key, this->key) << "
// refresh_data_feed_key_list" << std::endl;
if (t->source_key == this->key) {
tmp.push_back(t->feed_key);
}
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);
}
else if (relation->type == "First_Source_To_All_Feed_Relation") {
auto t = dynamic_cast<First_Source_To_All_Feed_Relation*>(relation.get());
std::shared_ptr<Data_Source> first = nullptr;
for (const auto& ds : Global::instance()->mode_acs.data_source_config.map.list()) {
if (ds->enable) {
first = ds;
break;
}
}
if (first->key == key) {
for (const auto& df : Global::instance()->mode_acs.data_feed_config.map.list()) {
if (df->enable) {
tmp.push_back(df->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()) {
use_default = true;
break;
}
std::sort(tmp.begin(), tmp.end());
// 去重
auto last = std::unique(tmp.begin(), tmp.end());
tmp.erase(last, tmp.end());
{
std::vector<Cached_Source_Info> tmp_info;
// 创建 tmp_info 向量,将 tmp 的内容转化为 Cached_Source_Info 对象
for (const auto& key : tmp) {
tmp_info.push_back({key});
}
{
// 进入临界区,锁住 mutex,确保线程安全
std::lock_guard<std::mutex> lock(cdf_mtx);
// 1. 删除 tmp 中没有的 cached_data_feed_key_list 元素
auto it = cached_data_feed_key_list.begin();
while (it != cached_data_feed_key_list.end()) {
if (std::find_if(tmp_info.begin(), tmp_info.end(), [&](const Cached_Source_Info& info) {
return info.key == it->key;
}) == tmp_info.end()) {
// 如果当前元素在 tmp 中找不到,删除它
it = cached_data_feed_key_list.erase(it);
}
else {
++it;
}
}
// 2. 创建 tmp 中有但 cached_data_feed_key_list 没有的元素
for (const auto& tmp_item : tmp_info) {
auto found = std::find_if(
cached_data_feed_key_list.begin(), cached_data_feed_key_list.end(),
[&](const Cached_Source_Info& cached_item) { return cached_item.key == tmp_item.key; });
if (found == cached_data_feed_key_list.end()) {
// 如果 tmp_item 不在 cached_data_feed_key_list 中,添加它
cached_data_feed_key_list.push_back(tmp_item);
}
}
}
if (use_default) {
auto first = std::find_if(sources.begin(), sources.end(), [](const auto& source) {
return source->enabled();
});
if (first != sources.end()) {
for (const auto& feed : feeds) {
if (feed->enabled() && !assignment.contains(feed->key))
assignment.emplace(feed->key, (*first)->key);
}
}
}
std::vector<Cached_Source_Info> next;
for (const auto& [feed_key, source_key] : assignment) {
if (source_key == key)
next.push_back({feed_key});
}
std::lock_guard<std::mutex> lock(cdf_mtx);
for (auto& item : next) {
auto old = std::find_if(cached_data_feed_key_list.begin(), cached_data_feed_key_list.end(), [&](const Cached_Source_Info& value) {
return value.key == item.key;
});
if (old != cached_data_feed_key_list.end()) {
item.mode_s_cache_num = old->mode_s_cache_num;
item.mode_other_cache_num = old->mode_other_cache_num;
}
}
cached_data_feed_key_list = std::move(next);
}
std::optional<std::string> convert_to_send_format(Data_Source_Handler* ds, const std::shared_ptr<Data_Feed>& feed,
const std::shared_ptr<SSR::Msg>& msg) {
auto& type = msg->type;
auto fs = dynamic_cast<File_Data_Source*>(msg->source.get());
if (fs) {
if (fs->play_mode == Play_Mode::analysis) {
if (fs->specific.member<&File_Data_Source_Data::play_mode>().snapshot() == Play_Mode::analysis) {
// std::cout << fs->key << " analysis i ==" << i << std::endl;
}
}
// 出口输出的条件
auto& output_format = feed->output_format.type;
auto& use_mode_ac = feed->output_format.use_mode_ac;
auto& use_status = feed->output_format.use_status;
auto& mode_s_output_type = feed->output_format.mode_s_output_type;
const auto feed_format = feed->output_format.snapshot();
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;
const auto mode_s_output_type = feed_format.mode_s_output_type;
// 计算出是否输出消息
std::optional<std::string> send_msg = std::nullopt;
if (type == SSR::Msg::HULC_Status) {
@@ -416,7 +414,7 @@ std::optional<std::string> convert_to_send_format(Data_Source_Handler* ds, const
auto aircraft = ds->get_aircraft(s_msg->icao);
if (output_format == Output_Data_Format::SBS) {
bool sbs_out_put = false;
if (feed->output_format.sbs_only_pos) {
if (feed_format.sbs_only_pos) {
auto s = ds->get_aircraft(s_msg->icao);
if (s) {
auto pos = s->pos();
@@ -490,8 +488,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;
}
auto& other_size = Global::instance()->mode_acs.mode_other_max_num;
auto& s_size = Global::instance()->mode_acs.mode_other_max_num;
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;
std::vector<std::string> list;
for (const auto& item : cached_data_feed_key_list) {
auto& key = item.key;
@@ -501,7 +500,7 @@ void Data_Source_Handler::push_to_feed(const std::shared_ptr<SSR::Msg>& msg) {
break;
}
std::shared_ptr<Data_Feed>& feed = opt_feed.value();
if (!feed->enable)
if (!feed->enabled())
continue;
if (msg->type == SSR::Mode_Msg::T::S7 || msg->type == SSR::Mode_Msg::T::S14) {
// static Frequency_Limit fl;
+17 -15
View File
@@ -160,7 +160,7 @@ Psc::JSON aircraft_stream_source_update_json(
auto tracks = Psc::JSON::array();
ret.append({"key", data_source_key});
auto source = Global::instance()->source(data_source_key);
if (source == nullptr || !source->enable) {
if (source == nullptr || !source->enabled()) {
ret.append({"change_list", Psc::JSON::array()});
ret.append({"removed_icaos", Psc::JSON::array()});
ret.append({"tracks", tracks});
@@ -290,7 +290,7 @@ void register_aircraft_stream_ws() {
}
}
Aircraft::Aircraft(std::string_view icao) : Aircraft_Info(icao) {
auto size = Global::instance()->mode_acs.max_track_point_size.load();
auto size = Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::max_track_point_size>().snapshot();
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.timeout_seconds;
return time > Global::instance()->mode_acs.settings.member<&Mode_ACS_Config_Data::timeout_seconds>().snapshot();
});
}
@@ -361,14 +361,15 @@ 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.aircraft_change_list_min_position_points.load();
auto range_filter = g->mode_acs.aircraft_change_list_adsb_range_filter.load();
auto range_factor = g->mode_acs.aircraft_change_list_adsb_range_factor.load();
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();
auto source = g->source(get_key());
auto base_position = base_station.get_pos();
if (source) {
if (!base_position && source->base_station_has_valid_position.load()) {
base_position = SSR::Position_3D{source->lat, source->lon, source->alt};
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};
}
}
for (auto &it : aircraft_map.values()) {
@@ -540,12 +541,13 @@ void database_server(Global *g) {
if (db) {
ret = db->base_station.to_Json();
auto target_height =
g->mode_acs.adsb_theoretical_target_altitude_meters.load();
auto range = Base_Station::theoretical_detection_range_meters(db->alt,
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", db->lat});
ret.append({"longitude", db->lon});
ret.append({"height", db->alt});
ret.append({"latitude", source_config.lat});
ret.append({"longitude", source_config.lon});
ret.append({"height", source_config.alt});
ret.append({"adsb_theoretical_target_altitude_meters", target_height});
ret.append({"adsb_theoretical_detection_range_meters", range});
ret.append({"理论探测范围", range});
@@ -588,7 +590,7 @@ void database_server(Global *g) {
std::shared_ptr<Data_Source> ts = nullptr;
auto ret = JSON::array();
for (const auto &li : list) {
if (li->enable) {
if (li->enabled()) {
ret = li->get_aircraftlist();
break;
}
@@ -613,7 +615,7 @@ void database_server(Global *g) {
return;
}
auto limit_msg_num = g->mode_acs.default_min_aircraft_list_num.load();
auto limit_msg_num = g->mode_acs.settings.member<&Mode_ACS_Config_Data::default_min_aircraft_list_num>().snapshot();
auto t = params.get("limit_msg_num");
if (t) {
HTTP_REQUIRE_VALUE(requested_limit_msg_num, t->try_number_val<int>())