更新cpr统计,以及解码时间间隔,速度检测跳过配置

This commit is contained in:
2026-07-15 12:27:43 +08:00
parent 406417071d
commit f8277ac511
6 changed files with 432 additions and 516 deletions
+13 -44
View File
@@ -69,22 +69,18 @@ struct CPR_Data {
} }
} even_msg, odd_msg; } even_msg, odd_msg;
time_t last_parse_pos_time = 0; time_t last_parse_pos_time = 0;
std::function<std::optional<CPR::Position>( std::function<std::optional<CPR::Position>(std::string_view, std::string_view, time_t, time_t)> global_parse = nullptr;
std::string_view, std::string_view, time_t, time_t)> std::function<std::optional<CPR::Position>(std::string_view, double lat, double lon, time_t, time_t)> locale_parse = nullptr;
global_parse = nullptr;
std::function<std::optional<CPR::Position>(std::string_view, double lat, double lon, time_t, time_t)>
locale_parse = nullptr;
std::function<std::string(double, double, CPR::Frame)> encode = nullptr; std::function<std::string(double, double, CPR::Frame)> encode = nullptr;
std::optional<CPR::Position> pos; std::optional<CPR::Position> pos;
std::optional<CPR::Position> cache_ok_pos;
CPR::Frame cpr_format = CPR::Frame::Even; CPR::Frame cpr_format = CPR::Frame::Even;
void set_pos(std::optional<CPR::Position> new_pos, time_t cur_time) { };
pos = new_pos; struct Constraint {
if (new_pos != std::nullopt) { CPR::D max_speed_m_s;
cache_ok_pos = new_pos; CPR::D max_time_s;
} SSR::CPR_CB cb;
last_parse_pos_time = cur_time; bool time_space_filter;
} bool speed_filter;
}; };
template <typename That> template <typename That>
struct CPR_MSG : CPR_Data { struct CPR_MSG : CPR_Data {
@@ -92,16 +88,7 @@ struct CPR_MSG : CPR_Data {
PROP_T_FUN(RET<double>, lon, std::nullopt) PROP_T_FUN(RET<double>, lon, std::nullopt)
PROP_T_FUN(RET<double>, lat, std::nullopt) PROP_T_FUN(RET<double>, lat, std::nullopt)
PROP_T_FUN(CPR::Frame, cpr_format, CPR::Frame::Even); PROP_T_FUN(CPR::Frame, cpr_format, CPR::Frame::Even);
std::string current_state() { std::string current_state(P_S msg);
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();
}
Psc::JSON current_state_json() { Psc::JSON current_state_json() {
Psc::JSON ret = Psc::JSON::object(); Psc::JSON ret = Psc::JSON::object();
ret.append({"pos", (pos.has_value() ? pos->to_string() : "null")}); 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()}); ret.append({"even_msg", even_msg.to_json()});
return ret; return ret;
} }
std::string get_cpr_log(std::string_view type, std::string_view icao, RET<Pos_Ret> global_parse_message(P_S msg, double time_s, P_S other_msg, double other_time_s, Constraint constraint);
std::string_view msg_hex, CPR::Frame f, RET<Pos_Ret> local_parse_message(CPR::Position old_pos, P_S msg, double time_s, Constraint constraint);
std::string_view before_state, std::string_view after_state) { RET<Pos_Ret> parse_message(P_S msg, double time_s, Constraint constraint);
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<Pos_Ret> parse_message(const std::shared_ptr<Mode_S_Msg>& msg,
double time_s, CPR::D max_speed_m_s,
CPR::D max_time_s, const SSR::CPR_CB& cb);
virtual void parse(std::string& msg_bin) { virtual void parse(std::string& msg_bin) {
get_bin<53, 1, CPR::Frame>(msg_bin, cpr_format); get_bin<53, 1, CPR::Frame>(msg_bin, cpr_format);
} }
+5 -20
View File
@@ -100,16 +100,7 @@ bool check_new_prase_pos(ADS_B_T::CPR_Data& t, std::optional<CPR::Position>& tp,
return true; return true;
} }
constexpr double s_ns = 1000000000.0; constexpr double s_ns = 1000000000.0;
// cpr回调 bool parse_absb_17(SSR::Data_Source_Interface* src, SSR::P_S mode_s_msg, JSON& msg_json, std::optional<CPR::Position> base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint) {
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<CPR::Position> base_station_pos,
CPR::D max_speed_m_s, CPR::Time air_pos_time_out,
CPR::Time surface_pos_time_out) {
std::shared_ptr<Aircraft_Info> a = src->get_aircraft(mode_s_msg->icao); std::shared_ptr<Aircraft_Info> a = src->get_aircraft(mode_s_msg->icao);
if (!a) { if (!a) {
a = src->create_aircraft(mode_s_msg->icao); 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) Parse_no_json(t, BDS06_surface_position)
info.refresh_pos(true); info.refresh_pos(true);
t.base_station_pos = base_station_pos; t.base_station_pos = base_station_pos;
auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), air_constraint);
max_speed_m_s, surface_pos_time_out, cpr_cb);
if (tp.has_value()) { if (tp.has_value()) {
auto t2 = t.odd_msg; auto t2 = t.odd_msg;
Position_Info p(tp.value(), info.altitude_meter().value_or(0)); 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) Parse(t2, BDS05_airborne_Position_v2)
} }
using namespace std::chrono; 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, auto tp = t.parse_message(mode_s_msg, mode_s_msg->time().abs_sec(), surface_constraint);
cpr_cb);
if (tp.has_value()) { if (tp.has_value()) {
auto alt = t.get_alt_meter(); auto alt = t.get_alt_meter();
Position_Info p(tp.value(), alt); Position_Info p(tp.value(), alt);
@@ -306,10 +295,7 @@ bool parse_Message_commb(SSR::Data_Source_Interface* src,
} }
return true; return true;
} }
bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional<CPR::Position> base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint) {
std::optional<CPR::Position> base_station_pos,
CPR::D max_speed_m_s, CPR::Time air_pos_time_out,
CPR::Time surface_pos_time_out) {
auto& msg_hex = mode_s_msg->msg_hex; auto& msg_hex = mode_s_msg->msg_hex;
auto& msg = mode_s_msg->msg_bin; auto& msg = mode_s_msg->msg_bin;
auto& df = mode_s_msg->df; 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); "parse_absb_17 crc_error", {}, nullptr, mode_s_msg);
return false; return false;
} }
ok = parse_absb_17(src, mode_s_msg, msg_json, base_station_pos, ok = parse_absb_17(src, mode_s_msg, msg_json, base_station_pos, air_constraint, surface_constraint);
max_speed_m_s, air_pos_time_out, surface_pos_time_out);
} }
else if (df == Downlink_Format::Comm_B_Altitude_Reply_20 || else if (df == Downlink_Format::Comm_B_Altitude_Reply_20 ||
df == Downlink_Format::Comm_B_Identity_Reply_21) { df == Downlink_Format::Comm_B_Identity_Reply_21) {
+290 -311
View File
@@ -7,317 +7,296 @@
#include <functional> #include <functional>
#include <variant> #include <variant>
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
// 硬件接收来的 二进制消息族 // 硬件接收来的 二进制消息族
namespace SSR { namespace SSR {
class Data_Source_Interface; class Data_Source_Interface;
extern bool Monitor_Mode_ACS_Message_Num;
extern bool Monitor_Mode_ACS_Message_Num; class Msg {
public:
class Msg { enum T : unsigned char {
public: AC = 0x31, // 49
enum T : unsigned char { S7 = 0x32, // 50
AC = 0x31, // 49 S14 = 0x33, // 51
S7 = 0x32, // 50 Radarcape_status = 0x34, // 52
S14 = 0x33, // 51 HULC_Status = 0x48, // 72
Radarcape_status = 0x34, // 52 UNKNOWN = 0xFF
HULC_Status = 0x48, // 72 };
UNKNOWN = 0xFF enum Len {
}; AC_len = 9 + 2,
S7_len = 9 + 7,
enum Len { S14_len = 9 + 14,
AC_len = 9 + 2, Radarcape_status_len = 2 + 3,
S7_len = 9 + 7, HULC_len = 28,
S14_len = 9 + 14, };
Radarcape_status_len = 2 + 3, std::shared_ptr<Data_Source_Interface> source{};
HULC_len = 28, T type = UNKNOWN;
}; std::string packet; // 收到的原始消息
explicit Msg(const std::shared_ptr<Data_Source_Interface>& source, std::string_view packet);
std::shared_ptr<Data_Source_Interface> source{}; virtual Psc::JSON to_Json() {
T type = UNKNOWN; Psc::JSON ret = Psc::JSON::object();
std::string packet; // 收到的原始消息 ret.append({"type", Psc::to_string((T)(type))});
explicit Msg(const std::shared_ptr<Data_Source_Interface> &source, std::string_view packet); return ret;
}
virtual Psc::JSON to_Json() { virtual ~Msg();
Psc::JSON ret = Psc::JSON::object(); virtual std::string to_string() {
ret.append({"type", Psc::to_string((T) (type))}); return VAR_STR_2(type, packet);
return ret; }
} };
struct Play_Back_Time_Point {
virtual ~Msg(); static constexpr std::uint64_t SECS_PER_DAY = 86400ULL;
static constexpr std::uint64_t NANOSECS_PER_SEC = 1000000000ULL;
virtual std::string to_string() { std::uint64_t day_num{};
return VAR_STR_2(type, packet); std::uint64_t day_sec{};
} std::uint64_t nanosec{};
}; struct HMS {
std::uint32_t hour{};
struct Play_Back_Time_Point { std::uint32_t minute{};
std::uint64_t day_num{}; std::uint32_t second{};
std::uint64_t day_sec{}; // 0..86399 std::string to_string() const {
struct HMS { std::ostringstream oss;
std::uint32_t hour; oss << std::setfill('0')
std::uint32_t minute; << std::setw(2) << hour << ':'
std::uint32_t second; << std::setw(2) << minute << ':'
<< std::setw(2) << second;
std::string to_string() const { return oss.str();
std::ostringstream oss; }
oss << std::setw(2) << std::setfill('0') << hour << ':' << std::setw(2) };
<< std::setfill('0') << minute << ':' << std::setw(2) HMS hms() const noexcept {
<< std::setfill('0') << second; HMS result{};
return oss.str(); result.hour = static_cast<std::uint32_t>(day_sec / 3600);
} result.minute = static_cast<std::uint32_t>((day_sec % 3600) / 60);
}; result.second = static_cast<std::uint32_t>(day_sec % 60);
return result;
HMS hms() noexcept { }
HMS hms{}; std::string to_string() const {
hms.hour = static_cast<std::uint32_t>(day_sec / 3600); std::ostringstream oss;
day_sec %= 3600; oss << "Play_Back_Time_Point[" << day_num << ',' << hms().to_string()
hms.minute = static_cast<std::uint32_t>(day_sec / 60); << '.' << std::setfill('0') << std::setw(9) << nanosec << ']';
hms.second = static_cast<std::uint32_t>(day_sec % 60); return oss.str();
return hms; }
} void normalize() noexcept {
std::uint64_t sec_carry = nanosec / NANOSECS_PER_SEC;
std::string to_string() { nanosec %= NANOSECS_PER_SEC;
return "Play_Back_Time_Point[" + Psc::to_string(day_num) + "," + day_num += day_sec / SECS_PER_DAY;
hms().to_string() + "]"; day_sec %= SECS_PER_DAY;
} day_num += sec_carry / SECS_PER_DAY;
sec_carry %= SECS_PER_DAY;
static constexpr std::uint64_t SECS_PER_DAY = 86400ULL; day_sec += sec_carry;
// 归一化:保证 day_sec < 86400 if (day_sec >= SECS_PER_DAY) {
void normalize() noexcept { ++day_num;
if (day_sec >= SECS_PER_DAY) { 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 (day_num != other.day_num) {
return day_num < other.day_num;
bool operator<(const Play_Back_Time_Point &other) const noexcept { }
if (other == *this) return false; if (day_sec != other.day_sec) {
if (day_num != other.day_num) return day_num < other.day_num; return 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 { bool operator==(const Play_Back_Time_Point& other) const noexcept {
return day_num == other.day_num && day_sec == other.day_sec; return day_num == other.day_num &&
} day_sec == other.day_sec &&
nanosec == other.nanosec;
bool operator>(const Play_Back_Time_Point &other) const noexcept { }
if (other == *this) return false; bool operator>(const Play_Back_Time_Point& other) const noexcept {
return other < *this; return other < *this;
} }
bool operator<=(const Play_Back_Time_Point& other) const noexcept {
std::uint64_t abs_sec() const noexcept { return !(other < *this);
return day_num * SECS_PER_DAY + day_sec; }
} bool operator>=(const Play_Back_Time_Point& other) const noexcept {
return !(*this < other);
void add_sec(std::uint64_t sec) noexcept { }
day_sec += sec; double abs_sec() const noexcept {
normalize(); return static_cast<double>(day_num) * static_cast<double>(SECS_PER_DAY) +
} static_cast<double>(day_sec) +
}; static_cast<double>(nanosec) / static_cast<double>(NANOSECS_PER_SEC);
}
class Mode_Msg : public Msg { void add_sec(std::uint64_t sec) noexcept {
public: day_num += sec / SECS_PER_DAY;
std::uint64_t day_num = 0; // 自己维护的字段 day_sec += sec % SECS_PER_DAY;
MLAT_timestamp mlat_timestamp; if (day_sec >= SECS_PER_DAY) {
std::string msg_hex; ++day_num;
std::string msg_bin; day_sec -= SECS_PER_DAY;
char signal_level{}; }
}
explicit Mode_Msg(const std::shared_ptr<Data_Source_Interface> &source, void add_nanosec(std::uint64_t value) noexcept {
std::string_view packet); add_sec(value / NANOSECS_PER_SEC);
nanosec += value % NANOSECS_PER_SEC;
Psc::JSON to_Json() override { if (nanosec >= NANOSECS_PER_SEC) {
Psc::JSON ret = Msg::to_Json(); ++day_sec;
Ret_J(msg_hex) nanosec -= NANOSECS_PER_SEC;
Ret_J(signal_level) if (day_sec >= SECS_PER_DAY) {
ret.append({"mlat_timestamp", mlat_timestamp.to_string()}); ++day_num;
Ret_J(day_num) day_sec -= SECS_PER_DAY;
return ret; }
} }
}
~Mode_Msg() override; };
class Mode_Msg : public Msg {
Play_Back_Time_Point time() { public:
return {day_num, mlat_timestamp.daysec}; std::uint64_t day_num = 0; // 自己维护的字段
} MLAT_timestamp mlat_timestamp;
std::string msg_hex;
std::string to_string() override { std::string msg_bin;
auto &time = mlat_timestamp; char signal_level{};
return VAR_STR_3(signal_level, time, msg_hex); explicit Mode_Msg(const std::shared_ptr<Data_Source_Interface>& source,
} std::string_view packet);
}; Psc::JSON to_Json() override {
Psc::JSON ret = Msg::to_Json();
class Mode_AC_Msg : public Mode_Msg { Ret_J(msg_hex)
public: Ret_J(signal_level)
explicit Mode_AC_Msg(const std::shared_ptr<Data_Source_Interface> &source, ret.append({"mlat_timestamp", mlat_timestamp.to_string()});
std::string_view packet); Ret_J(day_num)
return ret;
~Mode_AC_Msg() override; }
}; ~Mode_Msg() override;
Play_Back_Time_Point time() {
// 1 + 1 + 6 + 1 + 2/7/14 return {day_num, mlat_timestamp.daysec, mlat_timestamp.nanosec};
// 1a + type time_stamp signal_level data }
// 用于数据发送 std::string to_string() override {
class Mode_S_Msg : public Mode_Msg { auto& time = mlat_timestamp;
public: return VAR_STR_3(signal_level, time, msg_hex);
Downlink_Format df = Downlink_Format::Unknown; }
std::string icao; };
class Mode_AC_Msg : public Mode_Msg {
Psc::JSON to_Json() override { public:
Psc::JSON ret = Mode_Msg::to_Json(); explicit Mode_AC_Msg(const std::shared_ptr<Data_Source_Interface>& source,
ret.append({"df", Psc::to_string(df)}); std::string_view packet);
ret.append({"icao", icao}); ~Mode_AC_Msg() override;
return ret; };
} // 1 + 1 + 6 + 1 + 2/7/14
// 1a + type time_stamp signal_level data
// 1a 31 19 b2dd1c7af671 3220 // 用于数据发送
explicit Mode_S_Msg(const std::shared_ptr<Data_Source_Interface> &source, class Mode_S_Msg : public Mode_Msg {
std::string_view packet); public:
Downlink_Format df = Downlink_Format::Unknown;
~Mode_S_Msg() override; std::string icao;
Psc::JSON to_Json() override {
std::string to_string() override { Psc::JSON ret = Mode_Msg::to_Json();
auto &time = mlat_timestamp; ret.append({"df", Psc::to_string(df)});
return VAR_STR_5(df, icao, signal_level, time, msg_hex); ret.append({"icao", icao});
} return ret;
}; }
// 1a 31 19 b2dd1c7af671 3220
class NoneCopyLock { explicit Mode_S_Msg(const std::shared_ptr<Data_Source_Interface>& source,
public: std::string_view packet);
std::mutex mtx; // 互斥量,不能被复制 ~Mode_S_Msg() override;
NoneCopyLock() = default; std::string to_string() override {
auto& time = mlat_timestamp;
NoneCopyLock(const NoneCopyLock &other) = delete; return VAR_STR_5(df, icao, signal_level, time, msg_hex);
}
NoneCopyLock &operator=(const NoneCopyLock &other) { };
return *this; class NoneCopyLock {
} public:
}; std::mutex mtx; // 互斥量,不能被复制
NoneCopyLock() = default;
struct Position_3D : CPR::Position { NoneCopyLock(const NoneCopyLock& other) = delete;
CPR::D alt; NoneCopyLock& operator=(const NoneCopyLock& other) {
return *this;
Position_3D(CPR::D lat, CPR::D lon, CPR::D alt) : CPR::Position(lat, lon), alt(alt) { }
} };
}; 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; class Pos_Ret {
std::shared_ptr<Mode_S_Msg> that; public:
using Extra = std::variant<std::shared_ptr<Mode_S_Msg>, CPR::Position>; CPR::Position pos;
Extra extra; std::shared_ptr<Mode_S_Msg> that;
using Extra = std::variant<std::shared_ptr<Mode_S_Msg>, CPR::Position>;
Pos_Ret(CPR::Position p, std::shared_ptr<Mode_S_Msg> t, Extra extra;
std::shared_ptr<Mode_S_Msg> o) : pos(p), that(std::move(t)), extra(std::move(o)) { Pos_Ret(CPR::Position p, std::shared_ptr<Mode_S_Msg> t,
} std::shared_ptr<Mode_S_Msg> o) : pos(p), that(std::move(t)), extra(std::move(o)) {}
Pos_Ret(CPR::Position p, std::shared_ptr<Mode_S_Msg> t, CPR::Position old) : pos(p), that(std::move(t)),
Pos_Ret(CPR::Position p, std::shared_ptr<Mode_S_Msg> t, CPR::Position old) : pos(p), that(std::move(t)), extra(old) {}
extra(old) { };
} // 展示出最详细的信息
}; struct Position_Info : Position_3D {
std::int64_t sys_day_ns{};
// 展示出最详细的信息 std::uint64_t utc{};
struct Position_Info : Position_3D { std::uint64_t odd_even_diff_ns{};
std::int64_t sys_day_ns{}; Position_Info() : Position_3D(0.0, 0.0, 0.0) {}
std::uint64_t utc{}; Pos_Ret::Extra extra;
std::uint64_t odd_even_diff_ns{}; std::shared_ptr<Mode_S_Msg> that;
Position_Info(const Pos_Ret& r, CPR::D alt) : Position_3D(r.pos.lat, r.pos.lon, alt), that(r.that),
Position_Info() : Position_3D(0.0, 0.0, 0.0) { extra(r.extra) {
} using namespace std::chrono;
utc = static_cast<std::uint64_t>(
Pos_Ret::Extra extra; duration_cast<seconds>(system_clock::now().time_since_epoch()).count());
std::shared_ptr<Mode_S_Msg> that; }
Psc::JSON to_json() {
Position_Info(const Pos_Ret &r, CPR::D alt) : Position_3D(r.pos.lat, r.pos.lon, alt), that(r.that), Psc::JSON ret = Psc::JSON::object();
extra(r.extra) { Ret_J(lat)
using namespace std::chrono; Ret_J(lon)
utc = static_cast<std::uint64_t>( Ret_J(alt)
duration_cast<seconds>(system_clock::now().time_since_epoch()).count()); Ret_J(utc)
} Ret_J(that->mlat_timestamp)
Ret_J(that->msg_hex)
Psc::JSON to_json() { Ret_J(that->signal_level)
Psc::JSON ret = Psc::JSON::object(); if (auto p = std::get_if<
Ret_J(lat) std::shared_ptr<Mode_S_Msg>>(
Ret_J(lon) &extra)) {
Ret_J(alt) std::shared_ptr<Mode_S_Msg> other = *p;
Ret_J(utc) Ret_J(other->mlat_timestamp)
Ret_J(that->mlat_timestamp) Ret_J(other->msg_hex)
Ret_J(that->msg_hex) Ret_J(other->signal_level)
Ret_J(that->signal_level) return ret;
if (auto p = std::get_if< }
std::shared_ptr<Mode_S_Msg> >( if (auto p = std::get_if<CPR::Position>(&extra)) {
&extra)) { CPR::Position old = *p;
std::shared_ptr<Mode_S_Msg> other = *p; Ret_J(old)
Ret_J(other->mlat_timestamp) return ret;
Ret_J(other->msg_hex) }
Ret_J(other->signal_level) return ret;
return ret; }
} };
if (auto p = std::get_if<CPR::Position>(&extra)) { struct POS_List {
CPR::Position old = *p; NoneCopyLock mtx;
Ret_J(old) size_t max_size;
return ret; POS_List() {}
} void reset() {
return ret; std::lock_guard g(mtx.mtx);
} seq = 0;
}; head = 0;
count = 0;
struct POS_List { }
NoneCopyLock mtx; void init(size_t _max_size) {
size_t max_size; this->max_size = _max_size;
buf.resize(_max_size);
POS_List() { }
} size_t size() {
std::lock_guard g(mtx.mtx);
void reset() { return count;
std::lock_guard g(mtx.mtx); }
seq = 0; bool empty() {
head = 0; std::lock_guard g(mtx.mtx);
count = 0; return count == 0;
} }
std::optional<Position_Info> last() {
void init(size_t _max_size) { std::lock_guard g(mtx.mtx);
this->max_size = _max_size; if (count == 0) return std::nullopt;
buf.resize(_max_size); std::size_t idx = (head + max_size - 1) % max_size;
} return buf[idx];
}
size_t size() { void push(Position_Info new_position) {
std::lock_guard g(mtx.mtx); std::lock_guard g(mtx.mtx);
return count; buf[head] = std::move(new_position);
} head = (head + 1) % max_size;
if (count < max_size) ++count;
bool empty() { ++seq;
std::lock_guard g(mtx.mtx); }
return count == 0; Psc::JSON get_last_array_json(std::uint64_t last_seq);
} std::string to_string();
protected:
std::optional<Position_Info> last() { std::uint64_t seq = 0;
std::lock_guard g(mtx.mtx); std::uint64_t head = 0;
if (count == 0) return std::nullopt; std::uint64_t count = 0;
std::size_t idx = (head + max_size - 1) % max_size; std::vector<Position_Info> buf;
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<Position_Info> buf;
};
} // namespace SSR } // namespace SSR
+1 -1
View File
@@ -42,7 +42,7 @@ public:
virtual std::shared_ptr<Aircraft_Info> get_aircraft(std::string_view icao) = 0; virtual std::shared_ptr<Aircraft_Info> get_aircraft(std::string_view icao) = 0;
virtual std::shared_ptr<Aircraft_Info> create_aircraft(std::string_view icao) = 0; virtual std::shared_ptr<Aircraft_Info> create_aircraft(std::string_view icao) = 0;
}; };
bool parse_mode_s_bin(Data_Source_Interface* src, P_S mode_s_msg, std::optional<CPR::Position> 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<CPR::Position> base_station_pos, SSR::ADS_B_T::Constraint air_constraint, SSR::ADS_B_T::Constraint surface_constraint);
} }
#include "export.hpp" #include "export.hpp"
#endif #endif
+99 -121
View File
@@ -19,137 +19,115 @@ void init_that(Aircraft_Info& info, std::string_view field_name, T& t,
field_name, {}, &t, msg); 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 { namespace ADS_B_T {
// cpr回调
template <typename That> template <typename That>
RET<Pos_Ret> CPR_MSG<That>::parse_message(const std::shared_ptr<Mode_S_Msg>& msg, double time_s, CPR::D max_speed_m_s, CPR::D max_time_s, const SSR::CPR_CB& cb) { RET<Pos_Ret> CPR_MSG<That>::local_parse_message(CPR::Position old_pos, P_S msg, double time_s, Constraint constraint) {
const std::string& msg_bin = msg->msg_bin; constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Base, current_state(msg), msg);
std::string msg_hex = bin2hex(msg_bin); auto diff_time = std::abs(time_s - last_parse_pos_time);
std::string icao = msg_hex.substr(2, 6); if (constraint.time_space_filter && diff_time > constraint.max_time_s) {
Info *that, *other; constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Time_Space_Too_Long, current_state(msg), msg);
auto f = get_cpr_format(); return std::nullopt;
auto before_state = current_state();
if (f == CPR::Frame::Even) {
// std::cout << "even\n";
that = &even_msg;
other = &odd_msg;
} }
else { auto new_pos = locale_parse(msg->msg_bin, old_pos.lat, old_pos.lon, time_s, last_parse_pos_time);
// std::cout << "odd\n"; if (!new_pos.has_value()) {
that = &odd_msg; constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Inter_Error, current_state(msg), msg);
other = &even_msg; return std::nullopt;
} }
that->msg = msg; auto distance_m = CPR::haversine(old_pos, new_pos.value());
that->time = time_s; auto used_time_s = time_s - last_parse_pos_time;
Log_Type log_type({}, {{"ICAO", icao}, {"Frame_type", Psc::to_string(f)}}); auto max_distance = used_time_s * constraint.max_speed_m_s;
std::optional<CPR::Position>& old_pos = pos; 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 <typename That>
std::string CPR_MSG<That>::current_state(P_S msg) {
auto src = msg->source; auto src = msg->source;
if (old_pos.has_value()) { return std::format(
auto diff_time = std::abs(that->time - last_parse_pos_time); "{{\n"
if (diff_time < max_time_s) { " data_source:{}"
auto new_pos = locale_parse(that->msg->msg_bin, old_pos->lat, old_pos->lon, that->time, last_parse_pos_time); " cpr_format:{}"
bool locale_parse_ok = new_pos.has_value(); " msg_hex:{}"
if (locale_parse_ok) { " pos:{}\n"
auto distance_m = CPR::haversine(old_pos.value(), new_pos.value()); " odd_msg: {}\n"
auto used_time_s = time_s - last_parse_pos_time; " even_msg: {}\n"
auto max_distance = used_time_s * max_speed_m_s; " last_parse_pos_time: {}\n"
if (distance_m < max_distance) { "}}\n",
set_pos(new_pos, time_s); src->get_key(),
cb(SSR::CPR_Error_Type::Normal, msg->msg_hex, Psc::to_string(get_cpr_format()),
get_cpr_log("本地位置解码", icao, msg_hex, f, before_state, pos.has_value() ? pos->to_string() : "null",
current_state()), odd_msg.to_string(),
msg); even_msg.to_string(),
// 解码成功返回 Psc::to_string(last_parse_pos_time)
if (!new_pos.has_value()) { );
return std::nullopt; }
} template <typename That>
set_pos(new_pos, time_s); RET<Pos_Ret> CPR_MSG<That>::global_parse_message(P_S msg, double time_s, P_S other_msg, double other_time_s, Constraint constraint) {
return Pos_Ret(new_pos.value(), that->msg, old_pos.value()); 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);
else { 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);
cb(SSR::CPR_Error_Type::Local_Speed_Error, return std::nullopt;
get_cpr_log("本地位置解码速度异常舍弃, 尝试全局解码", icao, }
msg_hex, f, before_state, current_state()) + RET<CPR::Position> new_pos = global_parse(msg->msg_bin, other_msg->msg_bin, time_s, other_time_s);
" " + if (!new_pos.has_value()) {
VAR_STR_4(distance_m, max_distance, used_time_s, constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Inter_Error, current_state(msg), msg);
max_speed_m_s), return std::nullopt;
msg); }
} if (constraint.speed_filter && pos.has_value()) {
} auto distance_m = CPR::haversine(pos.value(), new_pos.value());
else { auto used_time_s = time_s - other_time_s;
cb(SSR::CPR_Error_Type::Unknow_Error, auto max_distance = used_time_s * constraint.max_speed_m_s;
get_cpr_log("未知错误", icao, msg_hex, f, before_state, if (distance_m > max_distance) {
current_state()), auto var = VAR_STR_6(distance_m, time_s, last_parse_pos_time, used_time_s, constraint.max_speed_m_s, max_distance);
msg); constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Speed_Error, "全局解码 速度异常:" + var + current_state(msg), msg);
} return std::nullopt;
}
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);
} }
} }
// 本地解码失败走到这里 尝试全局解码 constraint.cb(SSR::CPR_Type::Global_pos_parse, SSR::CPR_Ret_Type::Parse_OK, current_state(msg), msg);
if (other->msg) { return Pos_Ret(new_pos.value(), msg, other_msg);
auto diff_time = std::abs(that->time - other->time); }
if (diff_time < max_time_s) { template <typename That>
RET<CPR::Position> new_pos = global_parse( RET<Pos_Ret> CPR_MSG<That>::parse_message(P_S msg, double time_s, Constraint constraint) {
that->msg->msg_bin, other->msg->msg_bin, that->time, other->time); auto f = get_cpr_format();
if (new_pos.has_value()) { Info* that = f == CPR::Frame::Even ? &even_msg : &odd_msg;
if (old_pos.has_value()) { Info* other = f == CPR::Frame::Even ? &odd_msg : &even_msg;
auto distance = CPR::haversine(old_pos.value(), new_pos.value()); if (!pos.has_value()) {
auto used_time_s = time_s - other->time; constraint.cb(SSR::CPR_Type::Local_pos_parse, SSR::CPR_Ret_Type::Lack_Old_Pos, "缺旧位置" + current_state(msg), msg);
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);
}
} }
else { else {
// 消息不足 放弃解码 RET<Pos_Ret> ret = local_parse_message(pos.value(), msg, time_s, constraint);
cb(SSR::CPR_Error_Type::Msg_Lack, if (ret.has_value()) {
get_cpr_log(" 消息不足 放弃解码", icao, msg_hex, f, before_state, that->msg = msg;
current_state()), that->time = time_s;
msg); 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<Pos_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; last_parse_pos_time = 0;
pos = std::nullopt; pos = std::nullopt;
other->reset(); other->reset();
+24 -19
View File
@@ -4,25 +4,30 @@
#include <string> #include <string>
namespace SSR { namespace SSR {
enum class Parse_Call_Back_Type { enum class Parse_Call_Back_Type {
Normal_Block, Normal_Block,
CRC_Error, CRC_Error,
Length_Error, Length_Error,
Unknown_DF, Unknown_DF,
Cannot_Choose_BDS, Cannot_Choose_BDS,
More_than_one_BDS, More_than_one_BDS,
ICAO_Error, ICAO_Error,
Unknown_tc Unknown_tc
}; };
enum class CPR_Error_Type { enum class CPR_Type {
Normal, Local_pos_parse,
Msg_Lack, Global_pos_parse
Local_Speed_Error, };
Global_Speed_Error, enum class CPR_Ret_Type {
Local_Time_Space_Too_Long, // 百分比情况
Global_Time_Space_Too_Long, Speed_Error,
Unknow_Error, Parse_OK,
Inter_Error,
Time_Space_Too_Long,
// 正常情况
Lack_Other_Msg, // 缺乏条件,不参与计数
Lack_Old_Pos, // 缺乏条件,不参与计数
Base // 总计数
}; };
using P_S = const std::shared_ptr<Mode_S_Msg>&; using P_S = const std::shared_ptr<Mode_S_Msg>&;
using CPR_CB = using CPR_CB = std::function<void(CPR_Type cet, CPR_Ret_Type err_type, std::string_view log, P_S msg)>;
std::function<void(CPR_Error_Type cet, std::string_view log, P_S msg)>; }
}