diff --git a/SSR/ADS_B/ADS_B.hpp b/SSR/ADS_B/ADS_B.hpp index ae80675..5c85aa6 100644 --- a/SSR/ADS_B/ADS_B.hpp +++ b/SSR/ADS_B/ADS_B.hpp @@ -69,22 +69,18 @@ struct CPR_Data { } } even_msg, odd_msg; time_t last_parse_pos_time = 0; - std::function( - std::string_view, std::string_view, time_t, time_t)> - global_parse = nullptr; - std::function(std::string_view, double lat, double lon, time_t, time_t)> - locale_parse = nullptr; + std::function(std::string_view, std::string_view, time_t, time_t)> global_parse = nullptr; + std::function(std::string_view, double lat, double lon, time_t, time_t)> locale_parse = nullptr; std::function encode = nullptr; std::optional pos; - std::optional cache_ok_pos; CPR::Frame cpr_format = CPR::Frame::Even; - void set_pos(std::optional new_pos, time_t cur_time) { - pos = new_pos; - if (new_pos != std::nullopt) { - cache_ok_pos = new_pos; - } - last_parse_pos_time = cur_time; - } +}; +struct Constraint { + CPR::D max_speed_m_s; + CPR::D max_time_s; + SSR::CPR_CB cb; + bool time_space_filter; + bool speed_filter; }; template struct CPR_MSG : CPR_Data { @@ -92,16 +88,7 @@ struct CPR_MSG : CPR_Data { PROP_T_FUN(RET, lon, std::nullopt) PROP_T_FUN(RET, lat, std::nullopt) PROP_T_FUN(CPR::Frame, cpr_format, CPR::Frame::Even); - std::string current_state() { - std::ostringstream oss; - oss << "{" << std::endl; - oss << "\tpos:" << (pos.has_value() ? pos->to_string() : "null") - << std::endl; - oss << "\todd_msg: " + odd_msg.to_string() << std::endl; - oss << "\teven_msg: " + even_msg.to_string() << std::endl; - oss << "}" << std::endl; - return oss.str(); - } + std::string current_state(P_S msg); Psc::JSON current_state_json() { Psc::JSON ret = Psc::JSON::object(); ret.append({"pos", (pos.has_value() ? pos->to_string() : "null")}); @@ -109,27 +96,9 @@ struct CPR_MSG : CPR_Data { ret.append({"even_msg", even_msg.to_json()}); return ret; } - std::string get_cpr_log(std::string_view type, std::string_view icao, - std::string_view msg_hex, CPR::Frame f, - std::string_view before_state, std::string_view after_state) { - return std::format( - "\n" - "【开始】:===============[{0}][{1}]======================\n" - "当前收到的消息 msg: {2} frame:{3} \n" - "先前的状态:\n{4}现在的状态:\n{5}\n" - "【结束】:===============[{0}][{1}]======================\n", - type, - icao, - msg_hex, - Psc::to_string(f), - before_state, - current_state() - ); - } - // 虽然消息已经存在当天的秒数 - RET parse_message(const std::shared_ptr& msg, - double time_s, CPR::D max_speed_m_s, - CPR::D max_time_s, const SSR::CPR_CB& cb); + RET global_parse_message(P_S msg, double time_s, P_S other_msg, double other_time_s, Constraint constraint); + RET local_parse_message(CPR::Position old_pos, P_S msg, double time_s, Constraint constraint); + RET parse_message(P_S msg, double time_s, Constraint constraint); virtual void parse(std::string& msg_bin) { get_bin<53, 1, CPR::Frame>(msg_bin, cpr_format); } diff --git a/SSR/Aircraft_Info.cpp b/SSR/Aircraft_Info.cpp index 674c743..8eef9b6 100644 --- a/SSR/Aircraft_Info.cpp +++ b/SSR/Aircraft_Info.cpp @@ -100,16 +100,7 @@ bool check_new_prase_pos(ADS_B_T::CPR_Data& t, std::optional& tp, return true; } constexpr double s_ns = 1000000000.0; -// cpr回调 -CPR_CB cpr_cb = [](CPR_Error_Type t, std::string_view log, P_S msg) { - if (mode_s_logger) mode_s_logger->debug("CPR/" + to_string(t), {}, log); - -}; -bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, - JSON& msg_json, - std::optional base_station_pos, - CPR::D max_speed_m_s, CPR::Time air_pos_time_out, - CPR::Time surface_pos_time_out) { +bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& msg_json, std::optional base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint) { std::shared_ptr a = src->get_aircraft(mode_s_msg->icao); if (!a) { a = src->create_aircraft(mode_s_msg->icao); @@ -127,8 +118,7 @@ bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, Parse_no_json(t, BDS06_surface_position) info.refresh_pos(true); t.base_station_pos = base_station_pos; - auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), - max_speed_m_s, surface_pos_time_out, cpr_cb); + auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), air_constraint); if (tp.has_value()) { auto t2 = t.odd_msg; Position_Info p(tp.value(), info.altitude_meter().value_or(0)); @@ -149,8 +139,7 @@ bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, Parse(t2, BDS05_airborne_Position_v2) } using namespace std::chrono; - auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), max_speed_m_s, air_pos_time_out, - cpr_cb); + auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), surface_constraint); if (tp.has_value()) { auto alt = t.get_alt_meter(); Position_Info p(tp.value(), alt); @@ -306,10 +295,7 @@ bool parse_Message_commb(SSR::Data_Source_Interface* src, } return true; } -bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, - std::optional base_station_pos, - CPR::D max_speed_m_s, CPR::Time air_pos_time_out, - CPR::Time surface_pos_time_out) { +bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint) { auto& msg_hex = mode_s_msg->msg_hex; auto& msg = mode_s_msg->msg_bin; auto& df = mode_s_msg->df; @@ -324,8 +310,7 @@ bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, "parse_absb_17 crc_error", {}, nullptr, mode_s_msg); return false; } - ok = parse_absb_17(src, mode_s_msg, msg_json, base_station_pos, - max_speed_m_s, air_pos_time_out, surface_pos_time_out); + ok = parse_absb_17(src, mode_s_msg, msg_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) { diff --git a/SSR/Msg.h b/SSR/Msg.h index 057860e..79219ab 100644 --- a/SSR/Msg.h +++ b/SSR/Msg.h @@ -7,317 +7,296 @@ #include #include #define STRINGIFY(x) #x - // 硬件接收来的 二进制消息族 namespace SSR { - class Data_Source_Interface; - - extern bool Monitor_Mode_ACS_Message_Num; - - class Msg { - public: - enum T : unsigned char { - AC = 0x31, // 49 - S7 = 0x32, // 50 - S14 = 0x33, // 51 - Radarcape_status = 0x34, // 52 - HULC_Status = 0x48, // 72 - UNKNOWN = 0xFF - }; - - enum Len { - AC_len = 9 + 2, - S7_len = 9 + 7, - S14_len = 9 + 14, - Radarcape_status_len = 2 + 3, - HULC_len = 28, - }; - - std::shared_ptr source{}; - T type = UNKNOWN; - std::string packet; // 收到的原始消息 - explicit Msg(const std::shared_ptr &source, std::string_view packet); - - virtual Psc::JSON to_Json() { - Psc::JSON ret = Psc::JSON::object(); - ret.append({"type", Psc::to_string((T) (type))}); - return ret; - } - - virtual ~Msg(); - - virtual std::string to_string() { - return VAR_STR_2(type, packet); - } - }; - - struct Play_Back_Time_Point { - std::uint64_t day_num{}; - std::uint64_t day_sec{}; // 0..86399 - struct HMS { - std::uint32_t hour; - std::uint32_t minute; - std::uint32_t second; - - std::string to_string() const { - std::ostringstream oss; - oss << std::setw(2) << std::setfill('0') << hour << ':' << std::setw(2) - << std::setfill('0') << minute << ':' << std::setw(2) - << std::setfill('0') << second; - return oss.str(); - } - }; - - HMS hms() noexcept { - HMS hms{}; - hms.hour = static_cast(day_sec / 3600); - day_sec %= 3600; - hms.minute = static_cast(day_sec / 60); - hms.second = static_cast(day_sec % 60); - return hms; - } - - std::string to_string() { - return "Play_Back_Time_Point[" + Psc::to_string(day_num) + "," + - hms().to_string() + "]"; - } - - static constexpr std::uint64_t SECS_PER_DAY = 86400ULL; - // 归一化:保证 day_sec < 86400 - void normalize() noexcept { - if (day_sec >= SECS_PER_DAY) { - day_num += day_sec / SECS_PER_DAY; - day_sec %= SECS_PER_DAY; - } - } - - bool operator<(const Play_Back_Time_Point &other) const noexcept { - if (other == *this) return false; - if (day_num != other.day_num) return day_num < other.day_num; - return day_sec < other.day_sec; - } - - bool operator==(const Play_Back_Time_Point &other) const noexcept { - return day_num == other.day_num && day_sec == other.day_sec; - } - - bool operator>(const Play_Back_Time_Point &other) const noexcept { - if (other == *this) return false; - return other < *this; - } - - std::uint64_t abs_sec() const noexcept { - return day_num * SECS_PER_DAY + day_sec; - } - - void add_sec(std::uint64_t sec) noexcept { - day_sec += sec; - normalize(); - } - }; - - class Mode_Msg : public Msg { - public: - std::uint64_t day_num = 0; // 自己维护的字段 - MLAT_timestamp mlat_timestamp; - std::string msg_hex; - std::string msg_bin; - char signal_level{}; - - explicit Mode_Msg(const std::shared_ptr &source, - std::string_view packet); - - Psc::JSON to_Json() override { - Psc::JSON ret = Msg::to_Json(); - Ret_J(msg_hex) - Ret_J(signal_level) - ret.append({"mlat_timestamp", mlat_timestamp.to_string()}); - Ret_J(day_num) - return ret; - } - - ~Mode_Msg() override; - - Play_Back_Time_Point time() { - return {day_num, mlat_timestamp.daysec}; - } - - std::string to_string() override { - auto &time = mlat_timestamp; - return VAR_STR_3(signal_level, time, msg_hex); - } - }; - - class Mode_AC_Msg : public Mode_Msg { - public: - explicit Mode_AC_Msg(const std::shared_ptr &source, - std::string_view packet); - - ~Mode_AC_Msg() override; - }; - - // 1 + 1 + 6 + 1 + 2/7/14 - // 1a + type time_stamp signal_level data - // 用于数据发送 - class Mode_S_Msg : public Mode_Msg { - public: - Downlink_Format df = Downlink_Format::Unknown; - std::string icao; - - Psc::JSON to_Json() override { - Psc::JSON ret = Mode_Msg::to_Json(); - ret.append({"df", Psc::to_string(df)}); - ret.append({"icao", icao}); - return ret; - } - - // 1a 31 19 b2dd1c7af671 3220 - explicit Mode_S_Msg(const std::shared_ptr &source, - std::string_view packet); - - ~Mode_S_Msg() override; - - std::string to_string() override { - auto &time = mlat_timestamp; - return VAR_STR_5(df, icao, signal_level, time, msg_hex); - } - }; - - class NoneCopyLock { - public: - std::mutex mtx; // 互斥量,不能被复制 - NoneCopyLock() = default; - - NoneCopyLock(const NoneCopyLock &other) = delete; - - NoneCopyLock &operator=(const NoneCopyLock &other) { - return *this; - } - }; - - struct Position_3D : CPR::Position { - CPR::D alt; - - Position_3D(CPR::D lat, CPR::D lon, CPR::D alt) : CPR::Position(lat, lon), alt(alt) { - } - }; - - // 这个返回值的意义在于 解码失败后 返回值能反应出是 位置解码失败 - // 还是奇偶报文解码位置失败 - class Pos_Ret { - public: - CPR::Position pos; - std::shared_ptr that; - using Extra = std::variant, CPR::Position>; - Extra extra; - - Pos_Ret(CPR::Position p, std::shared_ptr t, - std::shared_ptr o) : pos(p), that(std::move(t)), extra(std::move(o)) { - } - - Pos_Ret(CPR::Position p, std::shared_ptr t, CPR::Position old) : pos(p), that(std::move(t)), - extra(old) { - } - }; - - // 展示出最详细的信息 - struct Position_Info : Position_3D { - std::int64_t sys_day_ns{}; - std::uint64_t utc{}; - std::uint64_t odd_even_diff_ns{}; - - Position_Info() : Position_3D(0.0, 0.0, 0.0) { - } - - Pos_Ret::Extra extra; - std::shared_ptr that; - - Position_Info(const Pos_Ret &r, CPR::D alt) : Position_3D(r.pos.lat, r.pos.lon, alt), that(r.that), - extra(r.extra) { - using namespace std::chrono; - utc = static_cast( - duration_cast(system_clock::now().time_since_epoch()).count()); - } - - Psc::JSON to_json() { - Psc::JSON ret = Psc::JSON::object(); - Ret_J(lat) - Ret_J(lon) - Ret_J(alt) - Ret_J(utc) - Ret_J(that->mlat_timestamp) - Ret_J(that->msg_hex) - Ret_J(that->signal_level) - if (auto p = std::get_if< - std::shared_ptr >( - &extra)) { - std::shared_ptr other = *p; - Ret_J(other->mlat_timestamp) - Ret_J(other->msg_hex) - Ret_J(other->signal_level) - return ret; - } - if (auto p = std::get_if(&extra)) { - CPR::Position old = *p; - Ret_J(old) - return ret; - } - return ret; - } - }; - - struct POS_List { - NoneCopyLock mtx; - size_t max_size; - - POS_List() { - } - - void reset() { - std::lock_guard g(mtx.mtx); - 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); - return count; - } - - bool empty() { - std::lock_guard g(mtx.mtx); - return count == 0; - } - - std::optional last() { - std::lock_guard g(mtx.mtx); - if (count == 0) return std::nullopt; - std::size_t idx = (head + max_size - 1) % max_size; - return buf[idx]; - } - - void push(Position_Info new_position) { - std::lock_guard g(mtx.mtx); - 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); - - std::string to_string(); - - protected: - std::uint64_t seq = 0; - std::uint64_t head = 0; - std::uint64_t count = 0; - std::vector buf; - }; +class Data_Source_Interface; +extern bool Monitor_Mode_ACS_Message_Num; +class Msg { +public: + enum T : unsigned char { + AC = 0x31, // 49 + S7 = 0x32, // 50 + S14 = 0x33, // 51 + Radarcape_status = 0x34, // 52 + HULC_Status = 0x48, // 72 + UNKNOWN = 0xFF + }; + enum Len { + AC_len = 9 + 2, + S7_len = 9 + 7, + S14_len = 9 + 14, + Radarcape_status_len = 2 + 3, + HULC_len = 28, + }; + std::shared_ptr source{}; + T type = UNKNOWN; + std::string packet; // 收到的原始消息 + explicit Msg(const std::shared_ptr& source, std::string_view packet); + virtual Psc::JSON to_Json() { + Psc::JSON ret = Psc::JSON::object(); + ret.append({"type", Psc::to_string((T)(type))}); + return ret; + } + virtual ~Msg(); + virtual std::string to_string() { + return VAR_STR_2(type, packet); + } +}; +struct Play_Back_Time_Point { + static constexpr std::uint64_t SECS_PER_DAY = 86400ULL; + static constexpr std::uint64_t NANOSECS_PER_SEC = 1000000000ULL; + std::uint64_t day_num{}; + std::uint64_t day_sec{}; + std::uint64_t nanosec{}; + struct HMS { + std::uint32_t hour{}; + std::uint32_t minute{}; + std::uint32_t second{}; + std::string to_string() const { + std::ostringstream oss; + oss << std::setfill('0') + << std::setw(2) << hour << ':' + << std::setw(2) << minute << ':' + << std::setw(2) << second; + return oss.str(); + } + }; + HMS hms() const noexcept { + HMS result{}; + result.hour = static_cast(day_sec / 3600); + result.minute = static_cast((day_sec % 3600) / 60); + result.second = static_cast(day_sec % 60); + return result; + } + std::string to_string() const { + std::ostringstream oss; + oss << "Play_Back_Time_Point[" << day_num << ',' << hms().to_string() + << '.' << std::setfill('0') << std::setw(9) << nanosec << ']'; + return oss.str(); + } + void normalize() noexcept { + std::uint64_t sec_carry = nanosec / NANOSECS_PER_SEC; + nanosec %= NANOSECS_PER_SEC; + day_num += day_sec / SECS_PER_DAY; + day_sec %= SECS_PER_DAY; + day_num += sec_carry / SECS_PER_DAY; + sec_carry %= SECS_PER_DAY; + day_sec += sec_carry; + if (day_sec >= SECS_PER_DAY) { + ++day_num; + day_sec -= SECS_PER_DAY; + } + } + bool operator<(const Play_Back_Time_Point& other) const noexcept { + if (day_num != other.day_num) { + return day_num < other.day_num; + } + if (day_sec != other.day_sec) { + return day_sec < other.day_sec; + } + return nanosec < other.nanosec; + } + bool operator==(const Play_Back_Time_Point& other) const noexcept { + return day_num == other.day_num && + day_sec == other.day_sec && + nanosec == other.nanosec; + } + bool operator>(const Play_Back_Time_Point& other) const noexcept { + return other < *this; + } + bool operator<=(const Play_Back_Time_Point& other) const noexcept { + return !(other < *this); + } + bool operator>=(const Play_Back_Time_Point& other) const noexcept { + return !(*this < other); + } + double abs_sec() const noexcept { + return static_cast(day_num) * static_cast(SECS_PER_DAY) + + static_cast(day_sec) + + static_cast(nanosec) / static_cast(NANOSECS_PER_SEC); + } + void add_sec(std::uint64_t sec) noexcept { + day_num += sec / SECS_PER_DAY; + day_sec += sec % SECS_PER_DAY; + if (day_sec >= SECS_PER_DAY) { + ++day_num; + day_sec -= SECS_PER_DAY; + } + } + void add_nanosec(std::uint64_t value) noexcept { + add_sec(value / NANOSECS_PER_SEC); + nanosec += value % NANOSECS_PER_SEC; + if (nanosec >= NANOSECS_PER_SEC) { + ++day_sec; + nanosec -= NANOSECS_PER_SEC; + if (day_sec >= SECS_PER_DAY) { + ++day_num; + day_sec -= SECS_PER_DAY; + } + } + } +}; +class Mode_Msg : public Msg { +public: + std::uint64_t day_num = 0; // 自己维护的字段 + MLAT_timestamp mlat_timestamp; + std::string msg_hex; + std::string msg_bin; + char signal_level{}; + explicit Mode_Msg(const std::shared_ptr& source, + std::string_view packet); + Psc::JSON to_Json() override { + Psc::JSON ret = Msg::to_Json(); + Ret_J(msg_hex) + Ret_J(signal_level) + ret.append({"mlat_timestamp", mlat_timestamp.to_string()}); + Ret_J(day_num) + return ret; + } + ~Mode_Msg() override; + Play_Back_Time_Point time() { + return {day_num, mlat_timestamp.daysec, mlat_timestamp.nanosec}; + } + std::string to_string() override { + auto& time = mlat_timestamp; + return VAR_STR_3(signal_level, time, msg_hex); + } +}; +class Mode_AC_Msg : public Mode_Msg { +public: + explicit Mode_AC_Msg(const std::shared_ptr& source, + std::string_view packet); + ~Mode_AC_Msg() override; +}; +// 1 + 1 + 6 + 1 + 2/7/14 +// 1a + type time_stamp signal_level data +// 用于数据发送 +class Mode_S_Msg : public Mode_Msg { +public: + Downlink_Format df = Downlink_Format::Unknown; + std::string icao; + Psc::JSON to_Json() override { + Psc::JSON ret = Mode_Msg::to_Json(); + ret.append({"df", Psc::to_string(df)}); + ret.append({"icao", icao}); + return ret; + } + // 1a 31 19 b2dd1c7af671 3220 + explicit Mode_S_Msg(const std::shared_ptr& source, + std::string_view packet); + ~Mode_S_Msg() override; + std::string to_string() override { + auto& time = mlat_timestamp; + return VAR_STR_5(df, icao, signal_level, time, msg_hex); + } +}; +class NoneCopyLock { +public: + std::mutex mtx; // 互斥量,不能被复制 + NoneCopyLock() = default; + NoneCopyLock(const NoneCopyLock& other) = delete; + NoneCopyLock& operator=(const NoneCopyLock& other) { + return *this; + } +}; +struct Position_3D : CPR::Position { + CPR::D alt; + Position_3D(CPR::D lat, CPR::D lon, CPR::D alt) : CPR::Position(lat, lon), alt(alt) {} +}; +// 这个返回值的意义在于 解码失败后 返回值能反应出是 位置解码失败 +// 还是奇偶报文解码位置失败 +class Pos_Ret { +public: + CPR::Position pos; + std::shared_ptr that; + using Extra = std::variant, CPR::Position>; + Extra extra; + Pos_Ret(CPR::Position p, std::shared_ptr t, + std::shared_ptr o) : pos(p), that(std::move(t)), extra(std::move(o)) {} + Pos_Ret(CPR::Position p, std::shared_ptr t, CPR::Position old) : pos(p), that(std::move(t)), + extra(old) {} +}; +// 展示出最详细的信息 +struct Position_Info : Position_3D { + std::int64_t sys_day_ns{}; + std::uint64_t utc{}; + std::uint64_t odd_even_diff_ns{}; + Position_Info() : Position_3D(0.0, 0.0, 0.0) {} + Pos_Ret::Extra extra; + std::shared_ptr that; + Position_Info(const Pos_Ret& r, CPR::D alt) : Position_3D(r.pos.lat, r.pos.lon, alt), that(r.that), + extra(r.extra) { + using namespace std::chrono; + utc = static_cast( + duration_cast(system_clock::now().time_since_epoch()).count()); + } + Psc::JSON to_json() { + Psc::JSON ret = Psc::JSON::object(); + Ret_J(lat) + Ret_J(lon) + Ret_J(alt) + Ret_J(utc) + Ret_J(that->mlat_timestamp) + Ret_J(that->msg_hex) + Ret_J(that->signal_level) + if (auto p = std::get_if< + std::shared_ptr>( + &extra)) { + std::shared_ptr other = *p; + Ret_J(other->mlat_timestamp) + Ret_J(other->msg_hex) + Ret_J(other->signal_level) + return ret; + } + if (auto p = std::get_if(&extra)) { + CPR::Position old = *p; + Ret_J(old) + return ret; + } + return ret; + } +}; +struct POS_List { + NoneCopyLock mtx; + size_t max_size; + POS_List() {} + void reset() { + std::lock_guard g(mtx.mtx); + 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); + return count; + } + bool empty() { + std::lock_guard g(mtx.mtx); + return count == 0; + } + std::optional last() { + std::lock_guard g(mtx.mtx); + if (count == 0) return std::nullopt; + std::size_t idx = (head + max_size - 1) % max_size; + return buf[idx]; + } + void push(Position_Info new_position) { + std::lock_guard g(mtx.mtx); + 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); + std::string to_string(); +protected: + std::uint64_t seq = 0; + std::uint64_t head = 0; + std::uint64_t count = 0; + std::vector buf; +}; } // namespace SSR diff --git a/SSR/export.h b/SSR/export.h index 6c30297..342a900 100644 --- a/SSR/export.h +++ b/SSR/export.h @@ -42,7 +42,7 @@ public: virtual std::shared_ptr get_aircraft(std::string_view icao) = 0; virtual std::shared_ptr create_aircraft(std::string_view icao) = 0; }; -bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional base_station_pos, CPR::D max_speed_m_s, CPR::D air_pos_time_out, CPR::D surface_pos_time_out); +bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint); } #include "export.hpp" #endif diff --git a/SSR/export.hpp b/SSR/export.hpp index 0f3747c..8843bc1 100644 --- a/SSR/export.hpp +++ b/SSR/export.hpp @@ -19,137 +19,115 @@ void init_that(Aircraft_Info& info, std::string_view field_name, T& t, field_name, {}, &t, msg); } } +inline CPR_CB cpr_cb = [](CPR_Type t, CPR_Ret_Type err_type, std::string_view log, P_S msg) { + if (mode_s_logger) mode_s_logger->debug("CPR/" + Psc::to_string(t) + "/" + Psc::to_string(err_type), {}, log); +}; namespace ADS_B_T { +// cpr回调 template -RET CPR_MSG::parse_message(const std::shared_ptr& msg, double time_s, CPR::D max_speed_m_s, CPR::D max_time_s, const SSR::CPR_CB& cb) { - const std::string& msg_bin = msg->msg_bin; - std::string msg_hex = bin2hex(msg_bin); - std::string icao = msg_hex.substr(2, 6); - Info *that, *other; - auto f = get_cpr_format(); - auto before_state = current_state(); - if (f == CPR::Frame::Even) { - // std::cout << "even\n"; - that = &even_msg; - other = &odd_msg; +RET CPR_MSG::local_parse_message(CPR::Position old_pos, P_S msg, double time_s, Constraint constraint) { + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Base, current_state(msg), msg); + auto diff_time = std::abs(time_s - last_parse_pos_time); + if (constraint.time_space_filter && diff_time > constraint.max_time_s) { + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Time_Space_Too_Long, current_state(msg), msg); + return std::nullopt; } - else { - // std::cout << "odd\n"; - that = &odd_msg; - other = &even_msg; + auto new_pos = locale_parse(msg->msg_bin, old_pos.lat, old_pos.lon, time_s, last_parse_pos_time); + if (!new_pos.has_value()) { + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Inter_Error, current_state(msg), msg); + return std::nullopt; } - that->msg = msg; - that->time = time_s; - Log_Type log_type({}, {{"ICAO", icao}, {"Frame_type", Psc::to_string(f)}}); - std::optional& old_pos = pos; + auto distance_m = CPR::haversine(old_pos, new_pos.value()); + auto used_time_s = time_s - last_parse_pos_time; + auto max_distance = used_time_s * constraint.max_speed_m_s; + if (constraint.speed_filter && distance_m > max_distance) { + auto var = VAR_STR_6(distance_m, time_s, last_parse_pos_time, used_time_s, constraint.max_speed_m_s, max_distance); + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Speed_Error, "本地解码 速度异常:" + var + current_state(msg), msg); + return std::nullopt; + } + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Parse_OK, current_state(msg), msg); + return Pos_Ret(new_pos.value(), msg, old_pos); +} +template +std::string CPR_MSG::current_state(P_S msg) { auto src = msg->source; - if (old_pos.has_value()) { - auto diff_time = std::abs(that->time - last_parse_pos_time); - if (diff_time < max_time_s) { - auto new_pos = locale_parse(that->msg->msg_bin, old_pos->lat, old_pos->lon, that->time, last_parse_pos_time); - bool locale_parse_ok = new_pos.has_value(); - if (locale_parse_ok) { - auto distance_m = CPR::haversine(old_pos.value(), new_pos.value()); - auto used_time_s = time_s - last_parse_pos_time; - auto max_distance = used_time_s * max_speed_m_s; - if (distance_m < max_distance) { - set_pos(new_pos, time_s); - cb(SSR::CPR_Error_Type::Normal, - get_cpr_log("本地位置解码", icao, msg_hex, f, before_state, - current_state()), - msg); - // 解码成功返回 - if (!new_pos.has_value()) { - return std::nullopt; - } - set_pos(new_pos, time_s); - return Pos_Ret(new_pos.value(), that->msg, old_pos.value()); - } - else { - // 尝试全局解码 - cb(SSR::CPR_Error_Type::Local_Speed_Error, - get_cpr_log("本地位置解码速度异常舍弃, 尝试全局解码", icao, - msg_hex, f, before_state, current_state()) + - " " + - VAR_STR_4(distance_m, max_distance, used_time_s, - max_speed_m_s), - msg); - } - } - else { - cb(SSR::CPR_Error_Type::Unknow_Error, - get_cpr_log("未知错误", icao, msg_hex, f, before_state, - current_state()), - msg); - } - } - else { - cb(SSR::CPR_Error_Type::Local_Time_Space_Too_Long, - get_cpr_log("本地位置解码时间异常, 尝试全局解码 超时:" + VAR_STR_2(diff_time, max_time_s), icao, msg_hex, f, - before_state, current_state()), - msg); + return std::format( + "{{\n" + " data_source:{}" + " cpr_format:{}" + " msg_hex:{}" + " pos:{}\n" + " odd_msg: {}\n" + " even_msg: {}\n" + " last_parse_pos_time: {}\n" + "}}\n", + src->get_key(), + msg->msg_hex, Psc::to_string(get_cpr_format()), + pos.has_value() ? pos->to_string() : "null", + odd_msg.to_string(), + even_msg.to_string(), + Psc::to_string(last_parse_pos_time) + ); +} +template +RET CPR_MSG::global_parse_message(P_S msg, double time_s, P_S other_msg, double other_time_s, Constraint constraint) { + constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Base, current_state(msg), msg); + auto diff_time = std::abs(time_s - other_time_s); + if (constraint.time_space_filter && diff_time > constraint.max_time_s) { + constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Time_Space_Too_Long, current_state(msg), msg); + return std::nullopt; + } + RET new_pos = global_parse(msg->msg_bin, other_msg->msg_bin, time_s, other_time_s); + if (!new_pos.has_value()) { + constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Inter_Error, current_state(msg), msg); + return std::nullopt; + } + if (constraint.speed_filter && pos.has_value()) { + auto distance_m = CPR::haversine(pos.value(), new_pos.value()); + auto used_time_s = time_s - other_time_s; + auto max_distance = used_time_s * constraint.max_speed_m_s; + if (distance_m > max_distance) { + auto var = VAR_STR_6(distance_m, time_s, last_parse_pos_time, used_time_s, constraint.max_speed_m_s, max_distance); + constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Speed_Error, "全局解码 速度异常:" + var + current_state(msg), msg); + return std::nullopt; } } - // 本地解码失败走到这里 尝试全局解码 - if (other->msg) { - auto diff_time = std::abs(that->time - other->time); - if (diff_time < max_time_s) { - RET new_pos = global_parse( - that->msg->msg_bin, other->msg->msg_bin, that->time, other->time); - if (new_pos.has_value()) { - if (old_pos.has_value()) { - auto distance = CPR::haversine(old_pos.value(), new_pos.value()); - auto used_time_s = time_s - other->time; - auto max_distance = used_time_s * max_speed_m_s; - if (distance < max_distance) { - cb(SSR::CPR_Error_Type::Normal, - get_cpr_log("全局位置解码", icao, msg_hex, f, before_state, - current_state()), - msg); - last_parse_pos_time = time_s; - set_pos(new_pos, time_s); - return Pos_Ret(new_pos.value(), that->msg, other->msg); - } - else { - // 视为失败 - cb(SSR::CPR_Error_Type::Global_Speed_Error, - get_cpr_log("全局位置解码速度异常,直接舍弃", icao, msg_hex, f, - before_state, current_state()) + - " " + - VAR_STR_4(distance, max_distance, used_time_s, - max_speed_m_s), - msg); - } - } - else { - // 第一次全局解码的位置,直接视为成功 - set_pos(new_pos, time_s); - return Pos_Ret(new_pos.value(), that->msg, other->msg); - } - } - else { - cb(SSR::CPR_Error_Type::Unknow_Error, - get_cpr_log("未知错误", icao, msg_hex, f, before_state, - current_state()) + - " ", - msg); - } - } - else { - cb(SSR::CPR_Error_Type::Global_Time_Space_Too_Long, - get_cpr_log("本地位置解码时间异常, 尝试全局解码 超时:" + VAR_STR_2(diff_time, max_time_s), icao, msg_hex, f, - before_state, current_state()), - msg); - } + constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Parse_OK, current_state(msg), msg); + return Pos_Ret(new_pos.value(), msg, other_msg); +} +template +RET CPR_MSG::parse_message(P_S msg, double time_s, Constraint constraint) { + auto f = get_cpr_format(); + Info* that = f == CPR::Frame::Even ? &even_msg : &odd_msg; + Info* other = f == CPR::Frame::Even ? &odd_msg : &even_msg; + if (!pos.has_value()) { + constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Lack_Old_Pos, "缺旧位置" + current_state(msg), msg); } else { - // 消息不足 放弃解码 - cb(SSR::CPR_Error_Type::Msg_Lack, - get_cpr_log(" 消息不足 放弃解码", icao, msg_hex, f, before_state, - current_state()), - msg); + RET ret = local_parse_message(pos.value(), msg, time_s, constraint); + if (ret.has_value()) { + that->msg = msg; + that->time = time_s; + pos = ret.value().pos; + last_parse_pos_time = time_s; + return ret; + } + } + 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); + } + else { + RET ret = global_parse_message(msg, time_s, other->msg, other->time, constraint); + if (ret.has_value()) { + that->msg = msg; + that->time = time_s; + pos = ret.value().pos; + last_parse_pos_time = time_s; + return ret; + } } - // 两种解码尝试都失败 尝试这里 last_parse_pos_time = 0; pos = std::nullopt; other->reset(); diff --git a/SSR/export_type.h b/SSR/export_type.h index e64cfa9..a475dfa 100644 --- a/SSR/export_type.h +++ b/SSR/export_type.h @@ -4,25 +4,30 @@ #include namespace SSR { enum class Parse_Call_Back_Type { - Normal_Block, - CRC_Error, - Length_Error, - Unknown_DF, - Cannot_Choose_BDS, - More_than_one_BDS, - ICAO_Error, - Unknown_tc + Normal_Block, + CRC_Error, + Length_Error, + Unknown_DF, + Cannot_Choose_BDS, + More_than_one_BDS, + ICAO_Error, + Unknown_tc }; -enum class CPR_Error_Type { - Normal, - Msg_Lack, - Local_Speed_Error, - Global_Speed_Error, - Local_Time_Space_Too_Long, - Global_Time_Space_Too_Long, - Unknow_Error, +enum class CPR_Type { + Local_pos_parse, + Global_pos_parse +}; +enum class CPR_Ret_Type { + // 百分比情况 + Speed_Error, + Parse_OK, + Inter_Error, + Time_Space_Too_Long, + // 正常情况 + Lack_Other_Msg, // 缺乏条件,不参与计数 + Lack_Old_Pos, // 缺乏条件,不参与计数 + Base // 总计数 }; using P_S = const std::shared_ptr&; -using CPR_CB = -std::function; -} \ No newline at end of file +using CPR_CB = std::function; +}