531 lines
27 KiB
C++
531 lines
27 KiB
C++
#ifndef CONFIG_H_H
|
||
#define CONFIG_H_H
|
||
#include <array>
|
||
#include <fstream>
|
||
#include <map>
|
||
#include <vector>
|
||
#include "../DSP/export.h"
|
||
#include "../Data_Feed/export.h"
|
||
#include "../Data_Source/export.h"
|
||
#include "MLAT.h"
|
||
#include "Psc_Cpp_Core/spdlog/export.h"
|
||
#include "adminive/json.hpp"
|
||
#include "adminive/managed.hpp"
|
||
inline bool delete_log = false;
|
||
extern std::string default_config_directory;
|
||
#define ECAP_CONFIG_SECTION_LIST(X) \
|
||
X(version) \
|
||
X(dsp) \
|
||
X(drogon) \
|
||
X(http_monitor) \
|
||
X(mlat) \
|
||
X(web_server) \
|
||
X(map_resources) \
|
||
X(map_view) \
|
||
X(map_models) \
|
||
X(mode_acs) \
|
||
X(log) \
|
||
X(console) \
|
||
X(external_database) \
|
||
X(cesium_graphics)
|
||
enum class Config_Section {
|
||
#define ECAP_CONFIG_SECTION_ENUM(name) name,
|
||
ECAP_CONFIG_SECTION_LIST(ECAP_CONFIG_SECTION_ENUM)
|
||
#undef ECAP_CONFIG_SECTION_ENUM
|
||
count
|
||
};
|
||
inline constexpr std::array config_section_names = {
|
||
#define ECAP_CONFIG_SECTION_NAME(name) std::string_view{#name},
|
||
ECAP_CONFIG_SECTION_LIST(ECAP_CONFIG_SECTION_NAME)
|
||
#undef ECAP_CONFIG_SECTION_NAME
|
||
};
|
||
#undef ECAP_CONFIG_SECTION_LIST
|
||
static_assert(config_section_names.size() == static_cast<std::size_t>(Config_Section::count));
|
||
inline constexpr std::string_view config_section_name(Config_Section section) {
|
||
return config_section_names[static_cast<std::size_t>(section)];
|
||
}
|
||
struct Log_Config {
|
||
~Log_Config() {
|
||
if (delete_log)
|
||
std::cout << "~Log_Config()" << std::endl;
|
||
}
|
||
enum class Open_Mode { Append, Delete, Rename };
|
||
Open_Mode open_mode = Open_Mode::Rename;
|
||
std::uint16_t piece_num{};
|
||
std::uint16_t size_MB{};
|
||
PSC_USE_JSON
|
||
};
|
||
struct Console_Config {
|
||
~Console_Config() {
|
||
if (delete_log)
|
||
std::cout << "~Console_Config()" << std::endl;
|
||
}
|
||
bool record_playback;
|
||
bool mode_s_console;
|
||
PSC_USE_JSON
|
||
};
|
||
struct Http_Monitor_Config {
|
||
bool access_log = true;
|
||
std::size_t slow_request_threshold_ms = 1000;
|
||
std::size_t slow_scope_threshold_ms = 100;
|
||
PSC_USE_JSON
|
||
};
|
||
struct Mode_ACS_Config_Data {
|
||
std::size_t timeout_seconds{};
|
||
SSR::CPR::D max_speed_m_s{};
|
||
SSR::CPR::D air_pos_timeout = 8;
|
||
SSR::CPR::D surface_pos_timeout = 32;
|
||
bool wait_process_msg{};
|
||
bool time_space_filter{};
|
||
bool speed_filter{};
|
||
std::size_t max_track_point_size{};
|
||
std::size_t mode_s_max_num{};
|
||
std::size_t mode_other_max_num{};
|
||
std::size_t report_data_feed_msg_mum{};
|
||
std::size_t default_min_aircraft_list_num{};
|
||
std::size_t aircraft_change_list_min_position_points = 2;
|
||
bool aircraft_change_list_adsb_range_filter = true;
|
||
double aircraft_change_list_adsb_range_factor = 1.2;
|
||
double adsb_theoretical_target_altitude_meters = 10000.0;
|
||
bool monitor_msg_live{};
|
||
PSC_USE_JSON
|
||
};
|
||
struct Data_Topology_Node_Position {
|
||
double x{};
|
||
double y{};
|
||
};
|
||
struct Data_Topology_View_Config {
|
||
bool initialized{};
|
||
std::uint32_t layout_revision{};
|
||
double zoom = 1.0;
|
||
double pan_x{};
|
||
double pan_y{};
|
||
std::map<std::string, Data_Topology_Node_Position> node_positions;
|
||
void from_json(const Psc::JSON* that_json);
|
||
[[nodiscard]] Psc::JSON to_json() const;
|
||
};
|
||
namespace adminive {
|
||
template <>
|
||
struct Type_Descriptor<Data_Topology_Node_Position> {
|
||
static auto get() {
|
||
using T = Data_Topology_Node_Position;
|
||
return object<T>("data_topology_node_position", "拓扑节点位置",
|
||
ADMINIVE_FIELD_LABEL(T, x, "X"),
|
||
ADMINIVE_FIELD_LABEL(T, y, "Y"));
|
||
}
|
||
};
|
||
template <>
|
||
struct Type_Descriptor<Data_Topology_View_Config> {
|
||
static auto get() {
|
||
using T = Data_Topology_View_Config;
|
||
return object<T>("data_topology_view", "数据拓扑视图",
|
||
ADMINIVE_FIELD_LABEL(T, initialized, "已初始化"),
|
||
ADMINIVE_FIELD_LABEL(T, layout_revision, "布局版本"),
|
||
ADMINIVE_FIELD_LABEL(T, zoom, "缩放"),
|
||
ADMINIVE_FIELD_LABEL(T, pan_x, "平移 X"),
|
||
ADMINIVE_FIELD_LABEL(T, pan_y, "平移 Y"),
|
||
ADMINIVE_FIELD_LABEL(T, node_positions, "节点位置"));
|
||
}
|
||
};
|
||
template <>
|
||
struct Type_Descriptor<Mode_ACS_Config_Data> {
|
||
static auto get() {
|
||
using T = Mode_ACS_Config_Data;
|
||
return object<T>("mode_acs_config", "Mode ACS 基础配置",
|
||
ADMINIVE_FIELD_LABEL(T, timeout_seconds, "目标超时时间(秒)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, max_speed_m_s, "飞机最大速度(m/s)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, air_pos_timeout, "空中 CPR 超时(秒)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, surface_pos_timeout, "地面 CPR 超时(秒)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, wait_process_msg, "等待处理消息").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, time_space_filter, "时空过滤").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, speed_filter, "速度过滤").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, max_track_point_size, "最大航迹点数量").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, mode_s_max_num, "Mode S 最大数量").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, mode_other_max_num, "其他 Mode 最大数量").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, report_data_feed_msg_mum, "数据馈送消息上报数量").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, default_min_aircraft_list_num, "默认最小飞机列表数量").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, aircraft_change_list_min_position_points, "飞机变化列表最少位置点").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, aircraft_change_list_adsb_range_filter, "基站理论范围过滤").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, aircraft_change_list_adsb_range_factor, "范围过滤系数").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, adsb_theoretical_target_altitude_meters, "理论目标高度(米)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, monitor_msg_live, "监控 Mode ACS 消息").editable().boolean_input());
|
||
}
|
||
};
|
||
}
|
||
struct Mode_ACS_Config {
|
||
adminive::Managed_Value<Mode_ACS_Config_Data> settings;
|
||
Data_feed_Config data_feed_config;
|
||
Data_Source_Config data_source_config;
|
||
adminive::Managed_Value<Data_Topology_View_Config> data_topology_view;
|
||
std::size_t Report_Data_Feed_Message_Num{};
|
||
Mode_ACS_Config() = default;
|
||
~Mode_ACS_Config() {
|
||
if (delete_log)
|
||
std::cout << " ~Mode_S_Config()" << std::endl;
|
||
}
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
void from_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
void server(Global* g);
|
||
};
|
||
struct Web_Server_Config {
|
||
[[nodiscard]] std::string get_true_webapp() const {
|
||
return Psc::get_abs_path(webapp);
|
||
}
|
||
std::string webapp;
|
||
std::uint16_t listen_port = 9081;
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
};
|
||
enum class Map_Tile_File_Format { directory, mbtiles, online };
|
||
enum class Map_Tile_Y_Axis { xyz, tms };
|
||
enum class Map_Tile_Projection { web_mercator };
|
||
enum class Map_Tile_Type { imagery, terrain };
|
||
enum class Map_Tile_Request_Method { GET };
|
||
enum class Map_Tile_Zoom_Mode { native, upscale, both };
|
||
struct Map_Tile_Config_Data {
|
||
Map_Tile_File_Format file_format = Map_Tile_File_Format::directory;
|
||
std::string path_layout;
|
||
Map_Tile_Y_Axis y_axis = Map_Tile_Y_Axis::xyz;
|
||
Map_Tile_Projection projection = Map_Tile_Projection::web_mercator;
|
||
std::string extension;
|
||
std::uint32_t tile_size{};
|
||
std::uint32_t minimum_level{};
|
||
std::uint32_t maximum_level{};
|
||
PSC_USE_JSON
|
||
};
|
||
struct Map_Tile_Config : Map_Tile_Config_Data {
|
||
std::vector<std::string> directories;
|
||
std::vector<std::string> files;
|
||
std::string encoding;
|
||
[[nodiscard]] std::vector<std::string> get_true_directories() const {
|
||
std::vector<std::string> ret;
|
||
ret.reserve(directories.size());
|
||
for (const auto& path : directories) {
|
||
ret.emplace_back(Psc::get_abs_path(path));
|
||
}
|
||
return ret;
|
||
}
|
||
[[nodiscard]] std::vector<std::string> get_true_files() const {
|
||
std::vector<std::string> ret;
|
||
ret.reserve(files.size());
|
||
for (const auto& path : files) {
|
||
ret.emplace_back(Psc::get_abs_path(path));
|
||
}
|
||
return ret;
|
||
}
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
[[nodiscard]] Psc::JSON to_public_json(std::string_view url) const;
|
||
};
|
||
struct Map_Tile_Source_Config_Data {
|
||
std::string key;
|
||
std::string name;
|
||
Map_Tile_Type tile_type = Map_Tile_Type::imagery;
|
||
Map_Tile_Request_Method request_method = Map_Tile_Request_Method::GET;
|
||
PSC_USE_JSON
|
||
};
|
||
struct Map_Tile_Source_Config : Map_Tile_Source_Config_Data {
|
||
std::string url;
|
||
Map_Tile_Config resource;
|
||
[[nodiscard]] bool local() const {
|
||
return resource.file_format != Map_Tile_File_Format::online;
|
||
}
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
[[nodiscard]] Psc::JSON to_public_json(std::string_view local_url) const;
|
||
};
|
||
struct Map_Resources_Config {
|
||
std::string current_imagery_key = "imagery";
|
||
std::vector<Map_Tile_Source_Config> tile_sources;
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
[[nodiscard]] Psc::JSON to_public_json() const;
|
||
[[nodiscard]] bool is_imagery_key(std::string_view key) const;
|
||
[[nodiscard]] bool is_terrain_key(std::string_view key) const;
|
||
};
|
||
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;
|
||
double height = 300000.0;
|
||
double heading = 0.0;
|
||
double pitch = -90.0;
|
||
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";
|
||
Map_Tile_Zoom_Mode tile_zoom_mode = Map_Tile_Zoom_Mode::native;
|
||
std::uint32_t tile_display_maximum_level = 19;
|
||
void from_base_json(const Psc::JSON* that_json, 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;
|
||
Map_Tile_View_Config map3d;
|
||
Map_Camera_Config camera;
|
||
double base_station_fly_to_height_offset_meters = 8000.0;
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[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;
|
||
bool use_browser_recommended_resolution = true;
|
||
double resolution_scale = 0.7;
|
||
std::uint32_t msaa_samples = 1;
|
||
bool fxaa = false;
|
||
bool shadows = false;
|
||
bool enable_lighting = false;
|
||
bool solar_lighting = false;
|
||
double solar_light_intensity = 1.5;
|
||
std::uint32_t maximum_screen_space_error = 4;
|
||
bool terrain_enabled_in_3d = false;
|
||
double terrain_exaggeration = 1.0;
|
||
bool terrain_limit_maximum_level = true;
|
||
std::uint32_t terrain_maximum_level = 15;
|
||
std::uint32_t terrain_cache_tiles = 128;
|
||
bool terrain_occlusion_enabled = false;
|
||
bool surface_navigation_reference_visible = false;
|
||
bool view_axes_visible = false;
|
||
double performance_panel_x = 12.0;
|
||
double performance_panel_y = 92.0;
|
||
double view_axes_panel_x = -1.0;
|
||
double view_axes_panel_y = 76.0;
|
||
double view_axes_panel_size = 84.0;
|
||
double occlusion_sample_spacing_meters = 250.0;
|
||
double occlusion_clearance_margin_meters = 10.0;
|
||
PSC_USE_JSON
|
||
};
|
||
namespace adminive {
|
||
template <>
|
||
struct Type_Descriptor<Cesium_Graphics_Config_Data> {
|
||
static auto get() {
|
||
using T = Cesium_Graphics_Config_Data;
|
||
auto descriptor = object<T>("cesium_graphics_config", "Cesium 图形配置",
|
||
ADMINIVE_FIELD_LABEL(T, debug_show_frames_per_second, "显示帧率").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, target_frame_rate, "目标帧率").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, use_browser_recommended_resolution, "使用浏览器推荐分辨率").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, resolution_scale, "分辨率缩放").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, msaa_samples, "MSAA 采样数").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, fxaa, "启用 FXAA").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, shadows, "启用阴影").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, enable_lighting, "启用光照").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, solar_lighting, "启用太阳光照").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, solar_light_intensity, "太阳光强度").editable().required().number_input().visible_on("${$self.solar_lighting}"),
|
||
ADMINIVE_FIELD_LABEL(T, maximum_screen_space_error, "最大屏幕空间误差").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_enabled_in_3d, "3D 启用地形").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_exaggeration, "地形夸张系数").editable().required().number_input().visible_on("${$self.terrain_enabled_in_3d}"),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_limit_maximum_level, "限制地形最大层级").editable().boolean_input().visible_on("${$self.terrain_enabled_in_3d}"),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_maximum_level, "地形最大层级").editable().required().number_input().visible_on("${$self.terrain_enabled_in_3d && $self.terrain_limit_maximum_level}"),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_cache_tiles, "地形缓存瓦片数").editable().required().number_input().visible_on("${$self.terrain_enabled_in_3d}"),
|
||
ADMINIVE_FIELD_LABEL(T, terrain_occlusion_enabled, "启用地形遮挡").editable().boolean_input().visible_on("${$self.terrain_enabled_in_3d}"),
|
||
ADMINIVE_FIELD_LABEL(T, surface_navigation_reference_visible, "显示地表导航参考").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, view_axes_visible, "显示视图坐标轴").editable().boolean_input(),
|
||
ADMINIVE_FIELD_LABEL(T, performance_panel_x, "性能面板 X").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, performance_panel_y, "性能面板 Y").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, view_axes_panel_x, "坐标轴面板 X").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, view_axes_panel_y, "坐标轴面板 Y").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, view_axes_panel_size, "坐标轴面板尺寸").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, occlusion_sample_spacing_meters, "遮挡采样间距(米)").editable().required().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, occlusion_clearance_margin_meters, "遮挡净空余量(米)").editable().required().number_input());
|
||
return descriptor.validator([](const T& value, Validation_Context& validation) {
|
||
if (value.target_frame_rate < 1 || value.target_frame_rate > 120)
|
||
validation.error("target_frame_rate", "必须在 1 到 120 之间");
|
||
if (value.resolution_scale < 0.2 || value.resolution_scale > 1.5)
|
||
validation.error("resolution_scale", "必须在 0.2 到 1.5 之间");
|
||
if (value.msaa_samples < 1 || value.msaa_samples > 8)
|
||
validation.error("msaa_samples", "必须在 1 到 8 之间");
|
||
if (value.maximum_screen_space_error < 1 || value.maximum_screen_space_error > 16)
|
||
validation.error("maximum_screen_space_error", "必须在 1 到 16 之间");
|
||
if (value.terrain_maximum_level > 24)
|
||
validation.error("terrain_maximum_level", "不能大于 24");
|
||
if (value.terrain_cache_tiles < 16 || value.terrain_cache_tiles > 2048)
|
||
validation.error("terrain_cache_tiles", "必须在 16 到 2048 之间");
|
||
if (value.performance_panel_x < 0)
|
||
validation.error("performance_panel_x", "不能小于 0");
|
||
if (value.performance_panel_y < 0)
|
||
validation.error("performance_panel_y", "不能小于 0");
|
||
if (value.view_axes_panel_y < 0)
|
||
validation.error("view_axes_panel_y", "不能小于 0");
|
||
if (value.view_axes_panel_size < 48 || value.view_axes_panel_size > 240)
|
||
validation.error("view_axes_panel_size", "必须在 48 到 240 之间");
|
||
if (value.occlusion_sample_spacing_meters < 10 || value.occlusion_sample_spacing_meters > 5000)
|
||
validation.error("occlusion_sample_spacing_meters", "必须在 10 到 5000 之间");
|
||
});
|
||
}
|
||
};
|
||
}
|
||
struct Cesium_Graphics_Config {
|
||
adminive::Managed_Value<Cesium_Graphics_Config_Data> settings;
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
};
|
||
struct Map_Model_Item_Config {
|
||
std::string url;
|
||
double built_in_size = 50.0;
|
||
double heading_offset_degrees = 0.0;
|
||
double pitch_offset_degrees = 0.0;
|
||
double roll_offset_degrees = 0.0;
|
||
Map_Model_Item_Config() = default;
|
||
explicit Map_Model_Item_Config(std::string url);
|
||
Map_Model_Item_Config(std::string url, double built_in_size, double heading, double pitch, double roll);
|
||
void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value);
|
||
[[nodiscard]] Psc::JSON to_base_json() const;
|
||
};
|
||
namespace adminive {
|
||
template <>
|
||
struct Type_Descriptor<Map_Model_Item_Config> {
|
||
static auto get() {
|
||
using T = Map_Model_Item_Config;
|
||
return object<T>("map_model_item_config", "Cesium 模型",
|
||
ADMINIVE_FIELD_LABEL(T, url, "模型地址"),
|
||
ADMINIVE_FIELD_LABEL(T, built_in_size, "模型原始尺寸").editable().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, heading_offset_degrees, "航向偏移(度)").editable().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, pitch_offset_degrees, "俯仰偏移(度)").editable().number_input(),
|
||
ADMINIVE_FIELD_LABEL(T, roll_offset_degrees, "横滚偏移(度)").editable().number_input());
|
||
}
|
||
};
|
||
}
|
||
struct Map_Model_Config {
|
||
Map_Model_Item_Config aircraft_model{"/ui/model/aircraft.glb", 50.0, -90.0, 0.0, 0.0};
|
||
std::map<std::string, Map_Model_Item_Config> aircraft_models;
|
||
Map_Model_Item_Config base_station_model{"/ui/model/base-station.glb", 16.635522, 0.0, 0.0, 0.0};
|
||
Map_Model_Item_Config device_model{"/ui/model/device.glb", 80.0, 0.0, 0.0, 0.0};
|
||
Map_Model_Config();
|
||
void from_base_json(const Psc::JSON* that_json, 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());
|
||
}
|
||
};
|
||
}
|
||
class Config {
|
||
public:
|
||
Config() = default;
|
||
DELETE_COPY(Config)
|
||
MLAT_Config mlat;
|
||
Web_Server_Config web_server_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;
|
||
adminive::Managed_Value<Map_Model_Config> map_model_config;
|
||
Mode_ACS_Config mode_acs;
|
||
Log_Config log_config;
|
||
Console_Config console_config{};
|
||
DSP_Config dsp_config;
|
||
Psc::JSON drogon_config;
|
||
Http_Monitor_Config http_monitor_config;
|
||
std::string version;
|
||
External_Resources_Manager external_resources_manager;
|
||
static Psc::JSON load();
|
||
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.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.write([&](auto& value) {
|
||
value.from_base_json(that_json->get("map_models"), not_exist_use_default_value);
|
||
});
|
||
mode_acs.from_json(that_json->get("mode_acs"), not_exist_use_default_value);
|
||
console_config.from_base_json(that_json->get("console"), not_exist_use_default_value);
|
||
dsp_config.from_json(that_json->get("dsp"), not_exist_use_default_value);
|
||
drogon_config = *that_json->get("drogon");
|
||
http_monitor_config.from_base_json(that_json->get("http_monitor"), not_exist_use_default_value);
|
||
external_resources_manager.from_json(that_json->get("external_database"), not_exist_use_default_value);
|
||
}
|
||
Psc::JSON toJson() {
|
||
auto ret = Psc::JSON::object({
|
||
{"version", version},
|
||
{"dsp", dsp_config.to_base_json()},
|
||
{"drogon", drogon_config},
|
||
{"http_monitor", http_monitor_config.to_base_json()},
|
||
{"mlat", mlat.to_base_json()},
|
||
{"web_server", web_server_config.to_base_json()},
|
||
{"map_resources", map_resources_config.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(); })},
|
||
{"mode_acs", mode_acs.to_base_json()},
|
||
{"log", log_config.to_base_json()},
|
||
{"console", console_config.to_base_json()},
|
||
{"external_database", external_resources_manager.to_base_json()},
|
||
{"cesium_graphics", cesium_graphics_config.to_base_json()},
|
||
});
|
||
return ret;
|
||
}
|
||
static void save();
|
||
static void save(Config_Section section);
|
||
static void save(Config_Section section, const Psc::JSON& value);
|
||
static void merge(Config_Section section, const Psc::JSON& value);
|
||
};
|
||
#endif
|