#include "Config.h" #include "Core/Base/Check.h" #include "Core/Net_Adapter/Net_Adapter.h" #include "Global.h" #include #include #include #include #undef interface std::string default_config_path; std::string get_config_path() { // #ifdef WIN32 // get_exe_dir() // return "D:/ae/proj/projects/ECAP_Server/config/config.json"; // #endif static bool first = true; if (!default_config_path.empty()) return default_config_path; std::string ret; std::ostringstream oss; std::string file_name = "config.json"; ret = get_exe_dir() + "/" + file_name; if (first) { std::cout << oss.str() << std::endl; first = false; } return ret; } static std::vector read_string_array(const Psc::JSON* json, std::string_view key) { auto field = json->get(key); if (field == nullptr || field->valueType != Psc::Array) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } std::vector ret; ret.reserve(field->children.size()); for (const auto& child : field->children) { if (child.valueType != Psc::String) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } ret.emplace_back(child.val); } return ret; } static Psc::JSON write_string_array(std::string_view key, const std::vector& list) { auto array = Psc::JSON::array(); for (const auto& path : list) { array.append(Psc::JSON(path)); } return Psc::JSON(key, array); } static const std::pair kDefaultAircraftModelUrls[] = { {"no_category_information", "/ui/model/aircraft-no-category-information.glb"}, {"surface_emergency_vehicle", "/ui/model/aircraft-surface-emergency-vehicle.glb"}, {"surface_service_vehicle", "/ui/model/aircraft-surface-service-vehicle.glb"}, {"ground_obstruction_4", "/ui/model/aircraft-ground-obstruction-4.glb"}, {"ground_obstruction_5", "/ui/model/aircraft-ground-obstruction-5.glb"}, {"ground_obstruction_6", "/ui/model/aircraft-ground-obstruction-6.glb"}, {"ground_obstruction_7", "/ui/model/aircraft-ground-obstruction-7.glb"}, {"glider", "/ui/model/aircraft-glider.glb"}, {"lighter_than_air", "/ui/model/aircraft-lighter-than-air.glb"}, {"parachutist", "/ui/model/aircraft-parachutist.glb"}, {"ultralight_hangglider_paraglider", "/ui/model/aircraft-ultralight-hangglider-paraglider.glb"}, {"reserved_3_5", "/ui/model/aircraft-reserved-3-5.glb"}, {"unmanned_aerial_vehicle", "/ui/model/aircraft-unmanned-aerial-vehicle.glb"}, {"space_transatmospheric_vehicle", "/ui/model/aircraft-space-transatmospheric-vehicle.glb"}, {"light_aircraft", "/ui/model/aircraft-light-aircraft.glb"}, {"medium_1_aircraft", "/ui/model/aircraft-medium-1-aircraft.glb"}, {"medium_2_aircraft", "/ui/model/aircraft-medium-2-aircraft.glb"}, {"high_vortex_aircraft", "/ui/model/aircraft-high-vortex-aircraft.glb"}, {"heavy_aircraft", "/ui/model/aircraft-heavy-aircraft.glb"}, {"high_performance_aircraft", "/ui/model/aircraft-high-performance-aircraft.glb"}, {"rotorcraft", "/ui/model/aircraft-rotorcraft.glb"} }; static std::map make_default_aircraft_models() { std::map ret; for (const auto& item : kDefaultAircraftModelUrls) { ret.emplace(std::string(item.first), Map_Model_Item_Config{std::string(item.second), 50.0, -90.0, 0.0, 0.0}); } return ret; } static std::map read_optional_model_object_field(const Psc::JSON* json, std::string_view key, std::map fallback) { auto field = json->get(key); if (field == nullptr) { return fallback; } if (field->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } for (const auto& child : field->children) { if (child.valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } fallback[child.key].from_base_json(&child); } return fallback; } static Psc::JSON write_model_object(std::string_view key, const std::map& values) { auto object = Psc::JSON::object(); for (const auto& item : values) { object.append({item.first, item.second.to_base_json()}); } return Psc::JSON(key, object); } static std::string read_string_field(const Psc::JSON* json, std::string_view key) { auto field = json->get(key); if (field == nullptr || field->valueType != Psc::String) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->val; } static std::uint32_t read_uint32_field(const Psc::JSON* json, std::string_view key) { auto field = json->get(key); if (field == nullptr || field->valueType != Psc::Number) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->number_val(); } static std::string read_optional_string_field(const Psc::JSON* json, std::string_view key) { auto field = json->get(key); if (field == nullptr) { return {}; } if (field->valueType != Psc::String) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->val; } static std::string read_optional_string_field(const Psc::JSON* json, std::string_view key, std::string_view fallback) { auto field = json->get(key); if (field == nullptr) { return std::string(fallback); } if (field->valueType != Psc::String) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->val; } static bool read_optional_bool_field(const Psc::JSON* json, std::string_view key, bool fallback) { auto field = json->get(key); if (field == nullptr) { return fallback; } if (field->valueType != Psc::Bool) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->bool_val(); } static std::uint32_t read_optional_uint32_field(const Psc::JSON* json, std::string_view key, std::uint32_t fallback) { auto field = json->get(key); if (field == nullptr) { return fallback; } if (field->valueType != Psc::Number) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->number_val(); } static double read_optional_double_field(const Psc::JSON* json, std::string_view key, double fallback) { auto field = json->get(key); if (field == nullptr) { return fallback; } if (field->valueType != Psc::Number) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), std::string(key)); } return field->number_val(); } void Map_Tile_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr || that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map tile config"); } directories = read_string_array(that_json, "directories"); path_layout = read_string_field(that_json, "path_layout"); y_axis = read_string_field(that_json, "y_axis"); projection = read_string_field(that_json, "projection"); extension = read_string_field(that_json, "extension"); tile_size = read_uint32_field(that_json, "tile_size"); minimum_level = read_uint32_field(that_json, "minimum_level"); maximum_level = read_uint32_field(that_json, "maximum_level"); encoding = read_optional_string_field(that_json, "encoding"); } Psc::JSON Map_Tile_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append(write_string_array("directories", directories)); ret.append({"path_layout", path_layout}); ret.append({"y_axis", y_axis}); ret.append({"projection", projection}); ret.append({"extension", extension}); ret.append({"tile_size", tile_size}); ret.append({"minimum_level", minimum_level}); ret.append({"maximum_level", maximum_level}); if (!encoding.empty()) { ret.append({"encoding", encoding}); } return ret; } Psc::JSON Map_Tile_Config::to_public_json(std::string_view url) const { auto ret = Psc::JSON::object(); ret.append({"url", std::string(url)}); ret.append({"minimum_level", minimum_level}); ret.append({"maximum_level", maximum_level}); ret.append({"tile_size", tile_size}); ret.append({"projection", projection}); ret.append({"y_axis", y_axis}); if (!encoding.empty()) { ret.append({"encoding", encoding}); } return ret; } void Map_Resources_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr || that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_resources"); } current_imagery_key = read_optional_string_field(that_json, "current_imagery_key"); if (current_imagery_key.empty()) { current_imagery_key = "imagery"; } imagery.from_base_json(that_json->get("imagery")); google_imagery.from_base_json(that_json->get("google_imagery")); terrain.from_base_json(that_json->get("terrain")); if (!is_imagery_key(current_imagery_key)) { current_imagery_key = "imagery"; } } Psc::JSON Map_Resources_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"current_imagery_key", current_imagery_key}); ret.append({"imagery", imagery.to_base_json()}); ret.append({"google_imagery", google_imagery.to_base_json()}); ret.append({"terrain", terrain.to_base_json()}); return ret; } static Psc::JSON make_public_imagery_source(std::string_view key, std::string_view name, const Psc::JSON& resource) { auto ret = Psc::JSON::object(); ret.append({"key", std::string(key)}); ret.append({"name", std::string(name)}); ret.append({"resource", resource}); return ret; } static Psc::JSON make_osm_public_resource() { auto ret = Psc::JSON::object(); ret.append({"url", "https://tile.openstreetmap.org/{z}/{x}/{y}.png"}); ret.append({"minimum_level", 0}); ret.append({"maximum_level", 19}); ret.append({"tile_size", 256}); ret.append({"projection", "web_mercator"}); ret.append({"y_axis", "xyz"}); ret.append({"credit", "OpenStreetMap contributors"}); return ret; } Psc::JSON Map_Resources_Config::to_public_json() const { auto ret = Psc::JSON::object(); auto imagery_json = imagery.to_public_json("/map/imagery/{z}/{x}/{y}"); auto google_imagery_json = google_imagery.to_public_json("/tiles/{z}/{x}/{y}"); auto osm_json = make_osm_public_resource(); auto sources = Psc::JSON::array(); sources.append(make_public_imagery_source("imagery", "本地卫星影像", imagery_json)); sources.append(make_public_imagery_source("google_imagery", "本地Google瓦片", google_imagery_json)); sources.append(make_public_imagery_source("osm_online", "OpenStreetMap在线", osm_json)); ret.append({"current_imagery_key", current_imagery_key}); ret.append({"imagery_sources", sources}); ret.append({"imagery", imagery_json}); ret.append({"google_imagery", google_imagery_json}); ret.append({"terrain", terrain.to_public_json("/map/terrain/{z}/{x}/{y}")}); return ret; } bool Map_Resources_Config::is_imagery_key(std::string_view key) const { return key == "imagery" || key == "google_imagery" || key == "osm_online"; } void Map_Camera_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr) { return; } if (that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map camera"); } longitude = read_optional_double_field(that_json, "longitude", longitude); latitude = read_optional_double_field(that_json, "latitude", latitude); height = read_optional_double_field(that_json, "height", height); heading = read_optional_double_field(that_json, "heading", heading); pitch = read_optional_double_field(that_json, "pitch", pitch); roll = read_optional_double_field(that_json, "roll", roll); } Psc::JSON Map_Camera_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"longitude", longitude}); ret.append({"latitude", latitude}); ret.append({"height", height}); ret.append({"heading", heading}); ret.append({"pitch", pitch}); ret.append({"roll", roll}); return ret; } bool Map_View_Config::is_scene_mode(std::string_view mode) { return mode == "2d" || mode == "2.5d" || mode == "3d"; } bool Map_Tile_View_Config::is_tile_zoom_mode(std::string_view mode) { return mode == "native" || mode == "upscale" || mode == "both"; } void Map_Tile_View_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr) { return; } if (that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_tile_view"); } current_imagery_key = read_optional_string_field(that_json, "current_imagery_key", current_imagery_key); auto next_tile_zoom_mode = read_optional_string_field(that_json, "tile_zoom_mode", tile_zoom_mode); if (!is_tile_zoom_mode(next_tile_zoom_mode)) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "tile_zoom_mode"); } tile_zoom_mode = next_tile_zoom_mode; tile_display_maximum_level = std::clamp(read_optional_uint32_field(that_json, "tile_display_maximum_level", tile_display_maximum_level), 0u, 24u); } Psc::JSON Map_Tile_View_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"current_imagery_key", current_imagery_key}); ret.append({"tile_zoom_mode", tile_zoom_mode}); ret.append({"tile_display_maximum_level", tile_display_maximum_level}); return ret; } void Map_View_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr) { return; } if (that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_view"); } auto next_scene_mode = read_optional_string_field(that_json, "scene_mode", scene_mode); if (!is_scene_mode(next_scene_mode)) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "scene_mode"); } scene_mode = next_scene_mode; map2d.from_base_json(that_json->get("map2d")); map3d.from_base_json(that_json->get("map3d")); camera.from_base_json(that_json->get("camera")); base_station_fly_to_height_offset_meters = std::max(100.0, read_optional_double_field(that_json, "baseStationFlyToHeightOffsetMeters", base_station_fly_to_height_offset_meters)); } Psc::JSON Map_View_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"scene_mode", scene_mode}); ret.append({"map2d", map2d.to_base_json()}); ret.append({"map3d", map3d.to_base_json()}); ret.append({"camera", camera.to_base_json()}); ret.append({"baseStationFlyToHeightOffsetMeters", base_station_fly_to_height_offset_meters}); return ret; } void Cesium_Graphics_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr) { return; } if (that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "cesium_graphics"); } debug_show_frames_per_second = read_optional_bool_field(that_json, "debug_show_frames_per_second", debug_show_frames_per_second); target_frame_rate = std::clamp(read_optional_uint32_field(that_json, "target_frame_rate", target_frame_rate), 1u, 120u); use_browser_recommended_resolution = read_optional_bool_field(that_json, "use_browser_recommended_resolution", use_browser_recommended_resolution); resolution_scale = std::clamp(read_optional_double_field(that_json, "resolution_scale", resolution_scale), 0.2, 1.5); msaa_samples = std::clamp(read_optional_uint32_field(that_json, "msaa_samples", msaa_samples), 1u, 8u); fxaa = read_optional_bool_field(that_json, "fxaa", fxaa); shadows = read_optional_bool_field(that_json, "shadows", shadows); enable_lighting = read_optional_bool_field(that_json, "enable_lighting", enable_lighting); solar_lighting = read_optional_bool_field(that_json, "solar_lighting", solar_lighting); solar_light_intensity = read_optional_double_field(that_json, "solar_light_intensity", solar_light_intensity); maximum_screen_space_error = std::clamp(read_optional_uint32_field(that_json, "maximum_screen_space_error", maximum_screen_space_error), 1u, 16u); terrain_enabled_in_3d = read_optional_bool_field(that_json, "terrain_enabled_in_3d", terrain_enabled_in_3d); terrain_exaggeration = read_optional_double_field(that_json, "terrain_exaggeration", terrain_exaggeration); terrain_limit_maximum_level = read_optional_bool_field(that_json, "terrain_limit_maximum_level", terrain_limit_maximum_level); terrain_maximum_level = std::clamp(read_optional_uint32_field(that_json, "terrain_maximum_level", terrain_maximum_level), 0u, 24u); terrain_cache_tiles = std::clamp(read_optional_uint32_field(that_json, "terrain_cache_tiles", terrain_cache_tiles), 16u, 2048u); terrain_occlusion_enabled = read_optional_bool_field(that_json, "terrain_occlusion_enabled", terrain_occlusion_enabled); surface_navigation_reference_visible = read_optional_bool_field(that_json, "surface_navigation_reference_visible", surface_navigation_reference_visible); view_axes_visible = read_optional_bool_field(that_json, "view_axes_visible", view_axes_visible); performance_panel_x = std::max(0.0, read_optional_double_field(that_json, "performance_panel_x", performance_panel_x)); performance_panel_y = std::max(0.0, read_optional_double_field(that_json, "performance_panel_y", performance_panel_y)); view_axes_panel_x = read_optional_double_field(that_json, "view_axes_panel_x", view_axes_panel_x); view_axes_panel_y = std::max(0.0, read_optional_double_field(that_json, "view_axes_panel_y", view_axes_panel_y)); view_axes_panel_size = std::clamp(read_optional_double_field(that_json, "view_axes_panel_size", view_axes_panel_size), 48.0, 240.0); occlusion_sample_spacing_meters = std::clamp(read_optional_double_field(that_json, "occlusion_sample_spacing_meters", occlusion_sample_spacing_meters), 10.0, 5000.0); occlusion_clearance_margin_meters = read_optional_double_field(that_json, "occlusion_clearance_margin_meters", occlusion_clearance_margin_meters); } Psc::JSON Cesium_Graphics_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"debug_show_frames_per_second", debug_show_frames_per_second}); ret.append({"target_frame_rate", target_frame_rate}); ret.append({"use_browser_recommended_resolution", use_browser_recommended_resolution}); ret.append({"resolution_scale", resolution_scale}); ret.append({"msaa_samples", msaa_samples}); ret.append({"fxaa", fxaa}); ret.append({"shadows", shadows}); ret.append({"enable_lighting", enable_lighting}); ret.append({"solar_lighting", solar_lighting}); ret.append({"solar_light_intensity", solar_light_intensity}); ret.append({"maximum_screen_space_error", maximum_screen_space_error}); ret.append({"terrain_enabled_in_3d", terrain_enabled_in_3d}); ret.append({"terrain_exaggeration", terrain_exaggeration}); ret.append({"terrain_limit_maximum_level", terrain_limit_maximum_level}); ret.append({"terrain_maximum_level", terrain_maximum_level}); ret.append({"terrain_cache_tiles", terrain_cache_tiles}); ret.append({"terrain_occlusion_enabled", terrain_occlusion_enabled}); ret.append({"surface_navigation_reference_visible", surface_navigation_reference_visible}); ret.append({"view_axes_visible", view_axes_visible}); ret.append({"performance_panel_x", performance_panel_x}); ret.append({"performance_panel_y", performance_panel_y}); if (view_axes_panel_x >= 0.0) { ret.append({"view_axes_panel_x", view_axes_panel_x}); } ret.append({"view_axes_panel_y", view_axes_panel_y}); ret.append({"view_axes_panel_size", view_axes_panel_size}); ret.append({"occlusion_sample_spacing_meters", occlusion_sample_spacing_meters}); ret.append({"occlusion_clearance_margin_meters", occlusion_clearance_margin_meters}); return ret; } Map_Model_Item_Config::Map_Model_Item_Config(std::string url) : url(std::move(url)) {} Map_Model_Item_Config::Map_Model_Item_Config(std::string url, double built_in_size, double heading, double pitch, double roll) : url(std::move(url)), built_in_size(built_in_size), heading_offset_degrees(heading), pitch_offset_degrees(pitch), roll_offset_degrees(roll) {} void Map_Model_Item_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr || that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_model_item"); } url = read_optional_string_field(that_json, "url", url); built_in_size = read_optional_double_field(that_json, "built_in_size", built_in_size); heading_offset_degrees = read_optional_double_field(that_json, "heading_offset_degrees", heading_offset_degrees); pitch_offset_degrees = read_optional_double_field(that_json, "pitch_offset_degrees", pitch_offset_degrees); roll_offset_degrees = read_optional_double_field(that_json, "roll_offset_degrees", roll_offset_degrees); } Psc::JSON Map_Model_Item_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"url", url}); ret.append({"built_in_size", built_in_size}); ret.append({"heading_offset_degrees", heading_offset_degrees}); ret.append({"pitch_offset_degrees", pitch_offset_degrees}); ret.append({"roll_offset_degrees", roll_offset_degrees}); return ret; } Map_Model_Config::Map_Model_Config() : aircraft_models(make_default_aircraft_models()) {} void Map_Model_Config::from_base_json(const Psc::JSON* that_json) { if (that_json == nullptr) { return; } if (that_json->valueType != Psc::Object) { throw Psc::json_assign_error(std::make_error_code(std::errc::invalid_argument), "map_models"); } aircraft_model.from_base_json(that_json->get("aircraft_model")); aircraft_models = read_optional_model_object_field(that_json, "aircraft_models", make_default_aircraft_models()); base_station_model.from_base_json(that_json->get("base_station_model")); device_model.from_base_json(that_json->get("device_model")); } Psc::JSON Map_Model_Config::to_base_json() const { auto ret = Psc::JSON::object(); ret.append({"aircraft_model", aircraft_model.to_base_json()}); ret.append(write_model_object("aircraft_models", aircraft_models)); ret.append({"base_station_model", base_station_model.to_base_json()}); ret.append({"device_model", device_model.to_base_json()}); return ret; } void Mode_ACS_Config::server(Global *g) { auto &svr = g->svr; auto &api = g->api; data_source_config.server(g); data_feed_config.server(g); source_feed_relation_config.server(g); svr.Post(api + "get_mode_s_basic_config", [this](HTTP_Param) { CHECK_JSON_PARAM res->setBody(warp(to_base_json()).to_json_string()); }); svr.Post(api + "set_mode_s_basic_config", [this](HTTP_Param) { CHECK_JSON_PARAM auto &j = o_params.value(); init_base_json(&j); if (auto min_points = j.try_get_number("aircraft_change_list_min_position_points")) { aircraft_change_list_min_position_points = min_points.value(); } if (auto range_filter = j.try_get_bool("aircraft_change_list_adsb_range_filter")) { aircraft_change_list_adsb_range_filter = range_filter.value(); } if (auto range_factor = j.try_get_number("aircraft_change_list_adsb_range_factor")) { aircraft_change_list_adsb_range_factor = range_factor.value(); } if (auto target_altitude = j.try_get_number("adsb_theoretical_target_altitude_meters")) { adsb_theoretical_target_altitude_meters = target_altitude.value(); } Global::save(); res->setBody(warp(to_base_json()).to_json_string()); }); } void Device_Config::server(Global *g) { auto &svr = g->svr; auto &api = g->api; svr.Post(api + "get_device_config", [this](HTTP_Param) { res->setBody(warp(to_base_json()).to_json_string()); }); svr.Post(api + "get_net_adapter_list", [this](HTTP_Param) { JSON ret = JSON::object(); auto arr = JSON::array(); for (auto &it: Psc::get_net_adapter_info_map()) { arr.append(it.second.to_Json()); } ret.append({"list", arr}); res->setBody(warp(ret).to_json_string()); }); svr.Post(api + "set_device_config", [this](HTTP_Param) { CHECK_JSON_PARAM JSON old_device_config; { old_device_config = to_base_json(); } HTTP_REQUIRE_PTR(net, params.get("net")) Net_Config device, wifi; bool has_device = false; bool has_wifi = false; for (const auto &it: net->children) { HTTP_REQUIRE_VALUE(net_key, it.try_get_string("key")) if (net_key == "device") { device.from_base_json(&it); has_device = true; } if (net_key == "wifi") { wifi.from_base_json(&it); has_wifi = true; } } HTTP_REQUIRE_TRUE(has_device && has_wifi, "net") bool it1 = check_ip_netmask_gateway(device.ip, device.netmask, device.gateway); bool it2 = check_ip_netmask_gateway(wifi.ip, wifi.netmask, wifi.gateway); bool p1 = check_port(device.port); bool p2 = check_port(wifi.port); if (!it1 || !it2 || !p1 || !p2) { server_logger->error("", {}, LOG_POS + " ip port! " + device.ip + ":" + std::to_string(device.port)); res->setBody(warp(old_device_config).to_json_string()); return; } #if WIN32 bool use = false; #else bool use = true; #endif { auto &w = *this; *w.list.get("device").value() = device; *w.list.get("wifi").value() = wifi; } Global::save(); if (use) { std::string interface; { std::string path = get_exe_dir() + "/interface"; std::ifstream ifs(path); if (!ifs.is_open()) { server_logger->error("", {}, LOG_POS + " 无法打开文件! " + path); res->setBody(warp(old_device_config).to_json_string()); return; } std::stringstream buffer; buffer << ifs.rdbuf(); interface = buffer.str(); } static auto set = [](std::string &interface, std::string_view token, std::string_view value) { std::string var_name = "${" + std::string(token) + "}"; auto size = var_name.size(); size_t pos = interface.find(var_name); while (pos != std::string::npos) { interface.replace(pos, size, value); pos = interface.find(var_name); } }; set(interface, "ip", device.ip); set(interface, "gateway", device.gateway); set(interface, "netmask", device.netmask); set(interface, "wifi_ip", wifi.ip); set(interface, "wifi_gateway", wifi.gateway); set(interface, "wifi_netmask", wifi.netmask); std::cout << interface << std::endl; std::string path = "/etc/network/interfaces"; std::ofstream outfile(path); if (!outfile.is_open()) { server_logger->error("", {}, LOG_POS + " 无法打开文件!" + path); res->setBody(warp(old_device_config).to_json_string()); return; } outfile << interface; outfile.close(); std::string bash_path = get_exe_dir() + "/restart_net_service.sh"; if (!std::filesystem::exists(bash_path)) { server_logger->error("", {}, LOG_POS + " !" + bash_path); res->setBody(warp(old_device_config).to_json_string()); return; } int result = system(bash_path.c_str()); if (result != 0) { server_logger->error("", {}, LOG_POS + " 脚本执行失败!" + bash_path); res->setBody(warp(old_device_config).to_json_string()); return; } } res->setBody(warp(params).to_json_string()); }); } void Config::save() { std::ofstream config_file; config_file.open(get_config_path()); std::string json = Global::instance()->toJson().to_json_string(); config_file.write(json.c_str(), static_cast(json.size())); config_file.close(); }