diff --git a/SSR/ADS_B/ADS_B.hpp b/SSR/ADS_B/ADS_B.hpp index 7fbcc3f..48b9c0f 100644 --- a/SSR/ADS_B/ADS_B.hpp +++ b/SSR/ADS_B/ADS_B.hpp @@ -84,6 +84,7 @@ struct Constraint { double base_station_height_meters = 0.0; bool radio_range_filter = false; double radio_range_factor = 1.2; + bool report_routine_details = true; mutable bool fail_clear_pos = false; // 如果启用那么解码位置失败,将会清空状态 }; template diff --git a/SSR/Aircraft_Info.cpp b/SSR/Aircraft_Info.cpp index d27a556..30c2adf 100644 --- a/SSR/Aircraft_Info.cpp +++ b/SSR/Aircraft_Info.cpp @@ -15,7 +15,8 @@ using namespace Psc; std::lock_guard mtx_##Field(info.Field.mtx.mtx); \ init_that(info, #Field, info.Field, mode_s_msg); \ auto& t = info.Field.value.value(); \ - msg_json.append_list(t.toJson().children); + if (collect_json) \ + msg_json.append_list(t.toJson().children); #define checkLength(len) \ if (msg_hex.size() != len) { \ parse_call_back(Parse_Call_Back_Type::Length_Error, nullptr, to_string(df), {}, nullptr, mode_s_msg); \ @@ -84,7 +85,7 @@ void set_logger(BaseLogger* logger) { delete mode_s_logger; mode_s_logger = logger; } -bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& msg_json, +bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& msg_json, bool collect_json, std::optional base_station_pos, const SSR::ADS_B_T::Constraint& air_constraint, const SSR::ADS_B_T::Constraint& surface_constraint) { std::shared_ptr a = src->get_aircraft(mode_s_msg->icao); @@ -111,13 +112,16 @@ bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& m Position_Info p(tp.value(), info.altitude_meter().value_or(0)); list.push(p); info.mlat = false; - parse_pos_call_back(&info, mode_s_msg, true); - msg_json.append_list(t.toJson().children); + if (parse_pos_call_back) + parse_pos_call_back(&info, mode_s_msg, true); + if (collect_json) + msg_json.append_list(t.toJson().children); } else if (constraint.fail_clear_pos) { list.reset(); } - msg_json.append(Psc::JSON("地表位置消息", get_current_time_as_string())); + if (collect_json) + msg_json.append(Psc::JSON("地表位置消息", get_current_time_as_string())); } else if ((tc >= 9 && tc <= 18) || (tc >= 20 && tc <= 22)) { Parse_no_json(t, BDS05_airborne_position) info.refresh_pos(true); @@ -137,13 +141,16 @@ bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& m Position_Info p(tp.value(), alt); list.push(p); info.mlat = false; - parse_pos_call_back(&info, mode_s_msg, false); - msg_json.append_list(t.toJson().children); + if (parse_pos_call_back) + parse_pos_call_back(&info, mode_s_msg, false); + if (collect_json) + msg_json.append_list(t.toJson().children); } else if (constraint.fail_clear_pos) { list.reset(); } - msg_json.append(Psc::JSON("空中位置消息", get_current_time_as_string())); + if (collect_json) + msg_json.append(Psc::JSON("空中位置消息", get_current_time_as_string())); } else if (tc == 19) { // 速度 @@ -207,7 +214,8 @@ bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& m } return true; } -bool parse_Message_commb(SSR::Data_Source_Interface* src, std::string_view BDS, SSR::P_S mode_s_msg, JSON& msg_json) { +bool parse_Message_commb(SSR::Data_Source_Interface* src, std::string_view BDS, SSR::P_S mode_s_msg, JSON& msg_json, + bool collect_json) { std::string& msg = mode_s_msg->msg_bin; Downlink_Format& df = mode_s_msg->df; bool new_create; @@ -233,7 +241,8 @@ bool parse_Message_commb(SSR::Data_Source_Interface* src, std::string_view BDS, } else if (BDS == "30") { Parse(t, BDS30) ACAS_SubType st = t.parse_sum(msg); - msg_json.append({"ACAS_SubType st", to_string(st)}); + if (collect_json) + msg_json.append({"ACAS_SubType st", to_string(st)}); switch (st) { case ACAS_SubType::NO_RA: break; @@ -246,7 +255,8 @@ bool parse_Message_commb(SSR::Data_Source_Interface* src, std::string_view BDS, } } Threat_Type_Indicator ti = t.get_threat_Type_Indicator(); - msg_json.append({"Threat_Type_Indicator", to_string(ti)}); + if (collect_json) + msg_json.append({"Threat_Type_Indicator", to_string(ti)}); switch (ti) { case Threat_Type_Indicator::No_Identity_Data: break; @@ -283,6 +293,7 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional< auto& df = mode_s_msg->df; auto& icao = mode_s_msg->icao; JSON msg_json = JSON::object(); + const bool collect_json = static_cast(parse_ok_json); bool ok = true; if (df == Downlink_Format::Extended_Squitter_17) { checkLength(28) if (!with_PI::check_crc(msg, icao)) { @@ -291,7 +302,8 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional< mode_s_msg); return false; } - ok = parse_absb_17(src, mode_s_msg, msg_json, base_station_pos, air_constraint, surface_constraint); + ok = parse_absb_17(src, mode_s_msg, msg_json, collect_json, base_station_pos, air_constraint, + surface_constraint); } else if (df == Downlink_Format::Comm_B_Altitude_Reply_20 || df == Downlink_Format::Comm_B_Identity_Reply_21) { checkLength(28) if (!src->get_aircraft(icao)) { @@ -301,7 +313,8 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional< } std::vector bds_list = infer2(msg, true); if (bds_list.empty()) { - msg_json.append({"bds", "bds_empty"}); + if (collect_json) + msg_json.append({"bds", "bds_empty"}); std::string bds_list_str; for (auto& bds : bds_list) { bds_list_str += "_" + bds; @@ -322,12 +335,13 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional< } std::string BDS = bds_list[0]; if (!with_AP::check_crc(msg, icao, BDS)) { - msg_json.append({"crc", "invalid crc"}); + if (collect_json) + msg_json.append({"crc", "invalid crc"}); if (parse_call_back) parse_call_back(Parse_Call_Back_Type::CRC_Error, nullptr, "commb_crc", {}, nullptr, mode_s_msg); return false; } - ok = parse_Message_commb(src, BDS, mode_s_msg, msg_json); + ok = parse_Message_commb(src, BDS, mode_s_msg, msg_json, collect_json); } else if (df == Downlink_Format::Surveillance_Altitude_Reply_4 || df == Downlink_Format::Surveillance_Identity_Reply_5) { @@ -421,35 +435,16 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional< if (a) { ++a->times; } - parse_ok_json(a.get(), mode_s_msg, msg_json); + if (parse_ok_json) + parse_ok_json(a.get(), mode_s_msg, std::move(msg_json)); return ok; } bool Monitor_Mode_ACS_Message_Num = false; -struct Frequency_State { - std::atomic_int64_t cur_num{}; -}; Msg::Msg(const std::shared_ptr& source, std::string_view packet) : source(source), packet(packet) { type = static_cast(packet[1]); - static Frequency_Limit_Multi_T fl; - auto t = source->get_key() + "_" + Psc::to_string(type); - auto state = fl.get_state(t); - if (state->cur_num > 100) { - if (fl.test_ex(t)) { - std::cerr << t << " 构造 Msg msg_num " << ++state->cur_num << std::endl; - } - } -} -Msg::~Msg() { - auto t = source->get_key() + "_" + Psc::to_string(type); - static Frequency_Limit_Multi_T fl; - auto state = fl.get_state(t); - if (state->cur_num > 100) { - if (fl.test_ex(t)) { - std::cerr << t << " 析构 Msg msg_num " << --state->cur_num << std::endl; - } - } } +Msg::~Msg() = default; struct Live_Report { explicit Live_Report(std::string_view name) : name(name) { } @@ -489,12 +484,19 @@ Live_Report plane("plane"); // 1 + 1 + 6 + 1 + 2/7/14 // 1a + type time_stamp signal_level data Mode_Msg::Mode_Msg(const std::shared_ptr& source, std::string_view packet) : - Msg(source, packet) { - mlat_timestamp = MLAT_timestamp(packet.substr(2, 6)); + Msg(source, packet), mlat_timestamp(packet.substr(2, 6)) { signal_level = packet[8]; - std::string memory(packet.substr(9)); - msg_hex = mem2hex(memory); - msg_bin = hex2bin(msg_hex); + const auto memory = packet.substr(9); + constexpr char hex[] = "0123456789ABCDEF"; + msg_hex.resize(memory.size() * 2); + msg_bin.resize(memory.size() * 8); + for (std::size_t index = 0; index < memory.size(); ++index) { + const auto byte = static_cast(memory[index]); + msg_hex[index * 2] = hex[byte >> 4]; + msg_hex[index * 2 + 1] = hex[byte & 0x0f]; + for (std::size_t bit = 0; bit < 8; ++bit) + msg_bin[index * 8 + bit] = byte & (0x80 >> bit) ? '1' : '0'; + } if (mlat_timestamp.daysec == 0 && mlat_timestamp.nanosec == 0) { std::time_t tp = std::time(nullptr); mlat_timestamp.daysec = tp % (3600 * 24); @@ -537,7 +539,7 @@ Mode_S_Msg::Mode_S_Msg(const std::shared_ptr& source, std Psc::fail_fast(); } } - df = decode_df(hex2bin(msg_hex.substr(0, 2))); + df = decode_df(msg_bin); icao = SSR::decode_icao(msg_bin); if (Monitor_Mode_ACS_Message_Num) { s_mode.add(); diff --git a/SSR/CPR/CPR.cpp b/SSR/CPR/CPR.cpp index be443d9..3f54133 100644 --- a/SSR/CPR/CPR.cpp +++ b/SSR/CPR/CPR.cpp @@ -228,9 +228,6 @@ std::optional airborne_position(std::string_view msg0, std::string_vie auto poses = CPR::global_decode(YZ0, YZ1, XZ0, XZ1, 17, 360.0); if (!poses.has_value()) return std::nullopt; auto [pos0, pos1] = poses.value(); - std::string info = pos0.to_string() + " @@@@ " + pos1.to_string(); - // std::cout << info << std::endl; - mode_s_logger->debug("CPR_global_decode", {}, info); return (t0 > t1) ? pos0 : pos1; } std::optional airborne_position_with_ref(std::string_view msg_bin, double lat_ref, double lon_ref, Time t, Time t_ref) { diff --git a/SSR/Msg.h b/SSR/Msg.h index 090993b..6bd5094 100644 --- a/SSR/Msg.h +++ b/SSR/Msg.h @@ -227,13 +227,13 @@ struct POS_List { POS_List() = default; void reset() { std::lock_guard g(mtx.mtx); + buf.clear(); seq = 0; head = 0; count = 0; } void init(size_t _max_size) { this->max_size = _max_size; - buf.resize(_max_size); } size_t size() { std::lock_guard g(mtx.mtx); @@ -257,10 +257,19 @@ struct POS_List { std::optional> last_two(); void push(Position_Info new_position) { std::lock_guard g(mtx.mtx); + if (count < max_size) { + if (buf.size() == buf.capacity()) { + auto capacity = std::max(1, buf.capacity() * 2); + buf.reserve(std::min(max_size, capacity)); + } + buf.push_back(std::move(new_position)); + ++count; + head = count % max_size; + ++seq; + return; + } buf[head] = std::move(new_position); head = (head + 1) % max_size; - if (count < max_size) - ++count; ++seq; } Psc::JSON get_last_array_json(std::uint64_t last_seq); diff --git a/SSR/convert/DataOutputFormats.cpp b/SSR/convert/DataOutputFormats.cpp index 2016174..29e2a99 100644 --- a/SSR/convert/DataOutputFormats.cpp +++ b/SSR/convert/DataOutputFormats.cpp @@ -23,12 +23,12 @@ MLAT_timestamp::MLAT_timestamp() { } MLAT_timestamp::MLAT_timestamp(std::string_view memory_6) : memory(memory_6) { assert(memory_6.size() == 6); - auto msg_bin = hex2bin(mem2hex(memory)); - daysec = std::bitset<18>(msg_bin.substr(0, 18)).to_ulong(); - nanosec = std::bitset<30>(msg_bin.substr(18, 30)).to_ulong(); + std::uint64_t value = 0; + for (const unsigned char byte : memory_6) + value = value << 8 | byte; + daysec = static_cast(value >> 30); + nanosec = static_cast(value & ((std::uint64_t{1} << 30) - 1)); parse_hhmmss(); - PSC_ASSERT(memory_6 == bin2mem(to_bin_string()), - "MLAT_timestamp,内存转换错误!"); } MLAT_timestamp::MLAT_timestamp(std::uint32_t daysec, std::uint32_t nanosec) : daysec(daysec), nanosec(nanosec) { parse_hhmmss(); diff --git a/SSR/export.hpp b/SSR/export.hpp index bb6a5a9..138d1cf 100644 --- a/SSR/export.hpp +++ b/SSR/export.hpp @@ -74,13 +74,21 @@ template bool in_radio_range(const ADS_B_T::Constraint& constraint, CPR_MSG& cpr, const CPR::Position& position) { return in_radio_range(constraint, position, target_height_meters(cpr)); } +template +void report_routine_cpr_event(const ADS_B_T::Constraint& constraint, CPR_MSG& cpr, CPR_Type type, + CPR_Ret_Type result, P_S msg) { + if (constraint.report_routine_details) + constraint.cb(type, result, cpr.current_state(msg), msg); + else + constraint.cb(type, result, {}, msg); +} // cpr回调 template RET CPR_MSG::local_parse_message(CPR::Position old_pos, P_S msg, double time_s, Constraint constraint) { Psc::JSON info = Psc::JSON::object(); auto type = SSR::CPR_Type::Local_pos_parse; info.append({"type", Psc::to_string(type)}); - constraint.cb(type, SSR::CPR_Ret_Type::Base, current_state(msg), msg); + report_routine_cpr_event(constraint, *this, type, SSR::CPR_Ret_Type::Base, msg); auto diff_time = std::abs(time_s - last_parse_pos_time); if (!constraint.use_system_time) { if (constraint.time_space_filter && diff_time > constraint.max_time_s) { @@ -135,7 +143,7 @@ RET CPR_MSG::local_parse_message(CPR::Position old_pos, P_S msg, "本地解码 超出基站理论探测范围" + current_state(msg), msg); return std::nullopt; } - constraint.cb(type, SSR::CPR_Ret_Type::Parse_OK, current_state(msg), msg); + report_routine_cpr_event(constraint, *this, type, SSR::CPR_Ret_Type::Parse_OK, msg); return Pos_Ret(new_pos.value(), info); } template @@ -144,7 +152,7 @@ RET CPR_MSG::global_parse_message(P_S msg, double time_s, P_S oth Psc::JSON info = Psc::JSON::object(); auto type = SSR::CPR_Type::Global_pos_parse; info.append({"type", Psc::to_string(type)}); - constraint.cb(type, SSR::CPR_Ret_Type::Base, current_state(msg), msg); + report_routine_cpr_event(constraint, *this, type, SSR::CPR_Ret_Type::Base, msg); auto diff_time = std::abs(time_s - other_time_s); if (!constraint.use_system_time) { if (constraint.time_space_filter && diff_time > constraint.max_time_s) { @@ -201,7 +209,7 @@ RET CPR_MSG::global_parse_message(P_S msg, double time_s, P_S oth "全局解码 超出基站理论探测范围" + current_state(msg), msg); return std::nullopt; } - constraint.cb(type, SSR::CPR_Ret_Type::Parse_OK, current_state(msg), msg); + report_routine_cpr_event(constraint, *this, type, SSR::CPR_Ret_Type::Parse_OK, msg); return Pos_Ret(new_pos.value(), info); } template @@ -216,8 +224,8 @@ RET CPR_MSG::parse_message(P_S msg, Constraint constraint) { Info* that = f == CPR::Frame::Even ? &even_msg : &odd_msg; Info* other = f == CPR::Frame::Even ? &odd_msg : &even_msg; if (!last_parse_pos.has_value()) { - constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Lack_Old_Pos, "缺旧位置" + current_state(msg), - msg); + report_routine_cpr_event(constraint, *this, SSR::CPR_Type::Local_pos_parse, + SSR::CPR_Ret_Type::Lack_Old_Pos, msg); // 不返回下面接着走 } else { @@ -233,8 +241,8 @@ RET CPR_MSG::parse_message(P_S msg, Constraint constraint) { if (other->msg == nullptr) { that->msg = msg; that->time = time_s; - constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Lack_Other_Msg, - "缺另一条消息" + current_state(msg), msg); + report_routine_cpr_event(constraint, *this, SSR::CPR_Type::Global_pos_parse, + SSR::CPR_Ret_Type::Lack_Other_Msg, msg); return std::nullopt; } RET ret = global_parse_message(msg, time_s, other->msg, other->time, constraint);