This commit is contained in:
2026-07-24 18:09:37 +08:00
parent 908c8b5a36
commit 8370ff9e79
13 changed files with 1028 additions and 158 deletions
+151 -19
View File
@@ -12,6 +12,7 @@
#include <thread>
#include <vector>
#include <iostream>
#include <optional>
#include "Core/Base/JSON.h"
#include "Core/Base/ThreadManager.h"
#include "Core/Base/global_include.h"
@@ -21,6 +22,21 @@
#include "Core/Base/SM_RingBuffer.h"
#include "Dll_Global.h"
#include <string_view>
#ifndef ECAP_ADSB_PLAYBACK_SPEED_RATE
#define ECAP_ADSB_PLAYBACK_SPEED_RATE 20.0
#endif
#ifndef ECAP_ADSB_PLAYBACK_LOOP
#define ECAP_ADSB_PLAYBACK_LOOP 1
#endif
#ifndef ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME
#define ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME 1
#endif
#ifndef ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES
#define ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES 512
#endif
#ifndef ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC
#define ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC 0.02
#endif
std::vector<std::string> ddd = {
"1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41",
"1A 33 1A 1A F1 D9 13 EA E7 11 8D 78 1D 40 58 BF 41 E2 45 49 09 7B C8 24",
@@ -48,33 +64,64 @@ std::string get_absb() {
}
class TextLineReader {
public:
struct Playback_Line {
std::string text;
double virtual_second{};
};
explicit TextLineReader(std::string_view file_path) {
load(file_path);
}
// 每调用一次,返回一行
// 返回 true 表示成功取到一行
// 返回 false 表示已经没有更多行
bool get(std::string& ret_line) {
if (index_ >= lines_.size()) {
return false;
std::size_t read(char* buf, std::size_t len) {
if (lines_.empty() || len == 0) {
return 0;
}
ret_line = lines_[index_];
++index_;
return true;
std::string ret;
std::size_t count = 0;
while (count < ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES) {
if (index_ >= lines_.size()) {
if (ECAP_ADSB_PLAYBACK_LOOP) {
reset();
}
else {
break;
}
}
if (!line_ready(lines_[index_])) {
break;
}
const auto& line = lines_[index_].text;
auto next_size = ret.size() + line.size() + 1;
if (!ret.empty() && next_size > len) {
break;
}
ret += line;
ret += '\n';
++index_;
++count;
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
break;
}
}
auto copy_size = ret.size();
if (copy_size > len) {
copy_size = len;
}
std::memcpy(buf, ret.data(), copy_size);
return copy_size;
}
// 重新从第一行开始读
void reset() {
index_ = 0;
true_start_time_ = clock::now();
start_virtual_second_ = lines_.empty() ? 0 : lines_.front().virtual_second;
}
// 总行数
std::size_t size() const {
return lines_.size();
}
// 是否已经读完
bool empty() const {
return lines_.empty();
}
private:
using clock = std::chrono::steady_clock;
void load(std::string_view file_path) {
std::ifstream file{std::string(file_path)};
// std::cout << "抛出异常" << std::endl;
@@ -86,21 +133,106 @@ private:
throw std::runtime_error(err);
}
std::string line;
std::optional<double> last_day_second;
std::uint64_t day_offset = 0;
std::size_t fallback_index = 0;
while (std::getline(file, line)) {
lines_.push_back(line);
auto day_second = parse_day_second(line);
if (!day_second.has_value()) {
day_second = fallback_index * ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC;
}
if (last_day_second.has_value() && day_second.value() + 3600.0 < last_day_second.value()) {
++day_offset;
}
lines_.push_back({line, day_offset * 86400.0 + day_second.value()});
last_day_second = day_second;
++fallback_index;
}
index_ = 0;
reset();
}
bool line_ready(const Playback_Line& line) const {
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
return true;
}
return line.virtual_second <= current_virtual_second();
}
double current_virtual_second() const {
auto elapsed = std::chrono::duration<double>(clock::now() - true_start_time_).count();
return start_virtual_second_ + elapsed * ECAP_ADSB_PLAYBACK_SPEED_RATE;
}
static std::optional<double> parse_day_second(std::string_view line) {
auto bytes = parse_hex_bytes(line);
if (!bytes.has_value()) {
return std::nullopt;
}
auto packet = unescape_packet(bytes.value());
if (packet.size() < 8 || packet[0] != 0x1a) {
return std::nullopt;
}
std::uint64_t raw = 0;
for (std::size_t i = 2; i < 8; ++i) {
raw = (raw << 8) | packet[i];
}
auto daysec = static_cast<std::uint32_t>((raw >> 30) & 0x3ffff);
auto nanosec = static_cast<std::uint32_t>(raw & 0x3fffffff);
return daysec + nanosec / 1000000000.0;
}
static std::optional<std::vector<std::uint8_t>> parse_hex_bytes(std::string_view line) {
std::vector<std::uint8_t> ret;
int high = -1;
for (char ch : line) {
int value = hex_value(ch);
if (value < 0) {
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
continue;
}
return std::nullopt;
}
if (high < 0) {
high = value;
}
else {
ret.push_back(static_cast<std::uint8_t>((high << 4) | value));
high = -1;
}
}
if (high >= 0) {
return std::nullopt;
}
return ret;
}
static int hex_value(char ch) {
if (ch >= '0' && ch <= '9') {
return ch - '0';
}
if (ch >= 'a' && ch <= 'f') {
return ch - 'a' + 10;
}
if (ch >= 'A' && ch <= 'F') {
return ch - 'A' + 10;
}
return -1;
}
static std::vector<std::uint8_t> unescape_packet(const std::vector<std::uint8_t>& bytes) {
std::vector<std::uint8_t> ret;
ret.reserve(bytes.size());
for (std::size_t i = 0; i < bytes.size(); ++i) {
ret.push_back(bytes[i]);
if (bytes[i] == 0x1a && i + 1 < bytes.size() && bytes[i + 1] == 0x1a) {
++i;
}
}
return ret;
}
private:
std::vector<std::string> lines_;
std::vector<Playback_Line> lines_;
std::size_t index_ = 0;
clock::time_point true_start_time_{clock::now()};
double start_virtual_second_ = 0;
};
std::size_t adsb_read(char* buf, std::size_t len) {
static TextLineReader reader(get_exe_dir() + "/ADS-B_195_0205.txt");
std::string line;
reader.get(line);
auto l = line.size();
std::memcpy(buf, line.c_str(), l);
auto l = reader.read(buf, len);
/*static Frequency_Limit fl;
if (fl.test()) {
std::cout << "adsb_read" << VAR_STR_2(l, len) << std::endl;