Files
ECAP_Server/module/Local_Server/Aircraft/aircraftlist_json.h
T
2026-08-09 16:05:16 +08:00

340 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "../Data_Source/Database.h"
// https://wiki.jetvision.de/wiki/Radarcape:Software_Features#Aircraft_List_JSON_Service
struct Aircraft_List_JSON_Service_O {
size_t times; //自定义添加出现的次数 用于显示的优先级
time_t uti{}; // Time of last message: Seconds since UNIX epoch
std::uint32_t ns{}; // Time of last message: Nanoseconds since Second epoch
std::uint32_t day_second{}; // Time of last message: Nanoseconds since Second epoch
std::string hex; // ICAO Mode-S or c, in Hex format
RET<std::string> fli; // Flight Identification
RET<std::string> ava; // Flight data: available flight data sources
std::string src; // Flight data: Source
std::string cla; // Subclass of ADS-B data
RET<double> lat; // Flight data: Latitude (-90 to 90º)
RET<double> lon; // Flight data: Longitude (-180 to 180º)
RET<double> alt; // Flight data: Barometric uncalibrated altitude (ft)
RET<double> spd; // Flight data: Ground Speed (kt)
RET<double> trk; // Flight data: True track (0-360º)
RET<double> vrt; // Flight data: Vertical Rate (ft/min)
std::string gda; // Airborne/Ground
std::string cat; // Aircraft category
RET<std::string> org; // Origin DB 起点机场
RET<std::string> dst; // Destination DB 目标机场
RET<std::string> opr; // Operator DB
RET<std::string> typ; // Type DB
RET<std::string> reg; // Registration DB
RET<std::string> squ; // Mode-A (Squawk)
RET<std::string> cou; // Country
RET<double> dis; // Distance (km or NM depending on configuration)
RET<size_t> tru; // Trust count Number of Mode-S frames successfully decoded from this A/C. Statistically it's possible that for a very low count the A/C does not actually exist
int dbm{}; // Approximate signal level in dBm;
RET<time_t> lla; // int Age of last Position (s)
RET<int> tmp; // Temperature (ºC)
RET<int> wsp ; // Wind Speed (kt)
RET<double> wdi; // Wind from Direction (0-360º)
RET<int> mop; // ADS-B MOPS version;
RET<std::string> spi; // SPI (Squawk ident);
RET<bool> alr; // Alert status
RET<double> ias; // IAS
RET<double> tas; // TAS
RET<double> hdgm; // Magnetic Heading
RET<std::string> hdgt; // True Heading
RET<std::string> qnhs; // Selected QNH
RET<std::string> alts; // Selected QNH
RET<double> hdgs; // Selected Heading
RET<double> altg; // GNSS elipsoidal altitude (ft)
RET<std::string> pic; // Asterix PIC
RET<std::string> tcm; // ACAS/TCAS status
RET<std::string> ape; // Autopilot engaged
RET<int> sil; // ADS-B SIL
RET<std::string> sda; // ADS-B SDA
RET<int> nacp; // ADS-B SDA
RET<int> pest; // Number of position estimations per second
RET<size_t> nocl; // Number of sensors providing data aircraft
RET<std::string> tq; // Time quality of this entry
static Psc::JSON view_model() {
auto columns = Psc::JSON::array();
const auto add_column = [&columns](const char* key, const char* label, const char* type,
const char* default_sort_order = nullptr) {
auto column = Psc::JSON::object();
column.append({"key", key});
column.append({"label", label});
column.append({"type", type});
if (default_sort_order != nullptr) {
column.append({"defaultSortOrder", default_sort_order});
}
columns.append(std::move(column));
};
add_column("index", "序号", "index");
auto time_column = Psc::JSON::object();
time_column.append({"key", "time"});
time_column.append({"label", "时间"});
time_column.append({"type", "timestamp"});
time_column.append({"secondsKey", "uti"});
time_column.append({"nanosecondsKey", "ns"});
columns.append(std::move(time_column));
add_column("times", "<mode_s>消息数", "number");
add_column("hex", "识别码<ICAO>", "text");
add_column("fli", "航班编号", "text");
add_column("ava", "数据来源标识", "text");
add_column("src", "首选数据源", "text");
add_column("cla", "ADS-B数据子类", "text");
add_column("lat", "纬度", "number");
add_column("lon", "经度", "number", "descend");
add_column("alt", "高度(米)", "number");
add_column("spd", "地速(节)", "number");
add_column("trk", "航向(真)", "number");
add_column("vrt", "垂直速度(<ft/min>", "number");
add_column("gda", "空中/地面状态", "text");
add_column("cat", "机型分类", "text");
add_column("org", "起飞机场", "text");
add_column("dst", "目的机场", "text");
add_column("opr", "航空公司", "text");
add_column("typ", "机型", "text");
add_column("reg", "注册号", "text");
add_column("squ", "应答机编码", "text");
add_column("cou", "国家", "text");
add_column("dis", "接收器距离", "number");
add_column("tru", "信任值", "number");
add_column("dbm", "信号强度(<dBm>", "number");
add_column("lla", "位置数据延迟(秒)", "number");
add_column("tmp", "温度(℃)", "number");
add_column("wsp", "风速(节)", "number");
add_column("wdi", "风向(°)", "number");
add_column("mop", "ADS-B协议版本", "number");
add_column("spi", "识别应答(<SPI>", "text");
add_column("alr", "告警状态", "boolean");
add_column("ias", "指示空速(<IAS>", "number");
add_column("tas", "真空速(<TAS>", "number");
add_column("hdgm", "磁航向", "number");
add_column("hdgt", "真航向", "text");
add_column("qnhs", "气压设定(<QNH>", "text");
add_column("alts", "选择高度", "text");
add_column("hdgs", "选择航向", "number");
add_column("altg", "GNSS椭球高度(英尺)", "number");
add_column("pic", "<Asterix PIC>", "text");
add_column("tcm", "防撞系统状态", "text");
add_column("ape", "自动驾驶启用", "text");
add_column("sil", "系统完整性等级(<SIL>", "number");
add_column("sda", "系统设计保证(<SDA>", "text");
add_column("nacp", "位置精度(<NACp>", "number");
add_column("pest", "位置估算次数每秒", "number");
add_column("nocl", "提供数据的接收机数", "number");
add_column("tq", "时间质量", "text");
auto model = Psc::JSON::object();
model.append({"columns", std::move(columns)});
return model;
}
Psc::JSON toJson() {
auto ret = Psc::JSON::object();
ADD_Json(times);
ADD_Json(uti);
ADD_Json(ns);
ADD_Json(day_second);
ADD_Json(hex);
ADD_Json_RET(fli);
ADD_Json_RET(ava);
ADD_Json(src);
ADD_Json(cla);
ADD_Json_RET(lat);
ADD_Json_RET(lon);
ADD_Json_RET(alt);
ADD_Json_RET(spd);
ADD_Json_RET(trk);
ADD_Json_RET(vrt);
ADD_Json(gda);
ADD_Json(cat);
ADD_Json_RET(org);
ADD_Json_RET(dst);
ADD_Json_RET(opr);
ADD_Json_RET(typ);
ADD_Json_RET(reg);
ADD_Json_RET(squ);
ADD_Json_RET(cou);
ADD_Json_RET(dis);
ADD_Json(tru);
ADD_Json(dbm);
ADD_Json_RET(lla);
ADD_Json_RET(tmp);
ADD_Json_RET(wsp);
ADD_Json_RET(wdi);
ADD_Json_RET(mop);
ADD_Json_RET(spi);
ADD_Json_RET(alr);
ADD_Json_RET(ias);
ADD_Json_RET(tas);
ADD_Json_RET(hdgm);
ADD_Json_RET(hdgt);
ADD_Json_RET(qnhs);
ADD_Json_RET(alts);
ADD_Json_RET(hdgs);
ADD_Json_RET(altg);
ADD_Json_RET(pic);
ADD_Json_RET(tcm);
ADD_Json_RET(ape);
ADD_Json_RET(sil);
ADD_Json_RET(sda);
ADD_Json_RET(nacp);
ADD_Json_RET(pest);
ADD_Json_RET(nocl);
ADD_Json_RET(tq);
return ret;
}
// https://wiki.jetvision.de/wiki/Radarcape:Software_Features#Aircraft_List_JSON_Service
static Aircraft_List_JSON_Service_O to_That(DataBase* db, Aircraft* info) {
Aircraft_List_JSON_Service_O ret;
// 航线查询结果保存在 Aircraft 中,仅在首次加载或 callsign 变化时重新读取数据库。
ret.times = info->times;
ret.uti = info->timestamp;
ret.ns = info->mlat_timestamp.nanosec;
ret.day_second = info->mlat_timestamp.daysec;
ret.hex = info->icao; // TODO not c
// fli Flight Identification Mode-S From ADS-B or BDS2,0 as specified on ICAO Annex 10, Volume IV, Table 3-9; "?" when A/C reports loss of interface
ret.fli = info->bds20_call_sign();
// ava ava Flight data: available flight data sources One letter per available flight data sources. A=ADSB, M=Jetvision MLAT, F=FlightAware MLAT, O=OGN, L=FLARM
// ret.ava
ret.ava = "暂不支持";
// ret.src
ret.src = "暂不支持";
// ret.cla
ret.cla = "暂不支持";
RET<SSR::CPR::Position> pos = info->air_pos_track_list.last();
if(pos.has_value()) {
ret.lat = pos.value().lat;
ret.lon = pos.value().lon;
}
ret.alt = info->altitude_meter();
ret.spd = info->speed();
ret.trk = info->air_magnetic_heading();
ret.vrt = info->vertical_rate();
// 飞机在地面还是空中 G for on ground, A for airborne (if TIS-B then lowercase g or a)
ret.gda = info->is_on_ground() ? "G" : "A";
auto vt = info->vortex_type();
if (vt.has_value()) {
ret.cat = Vortex_Type_to_radarcape_code(vt.value());
}
// =============== 来自DB 航班数据库 ================
auto route_info = info->external_database_row("vrs_routes");
if (!route_info) {
route_info = info->external_database_row("adsblol_vrs_standing_data_routes");
}
if (!route_info) {
route_info = info->external_database_row("vradarserver_standing_data_routes");
}
if (route_info) {
const auto airport_codes = route_info->get("AirportCodes");
if (airport_codes && !airport_codes->empty()) {
const auto first_separator = airport_codes->find('-');
const auto last_separator = airport_codes->rfind('-');
ret.org = airport_codes->substr(0, first_separator);
ret.dst = last_separator == std::string::npos
? *airport_codes
: airport_codes->substr(last_separator + 1);
}
}
//ret.opr
const auto opensky_info =
info->external_database_row("opensky_aircraft_database");
if (opensky_info) {
ret.opr = opensky_info->get("operator");
}
//ret.typ
if (opensky_info) {
ret.typ = opensky_info->get("typecode");
}
//ret.reg
if (opensky_info) {
ret.reg = opensky_info->get("registration");
}
// ===============================
// squ Mode-A (Squawk) Mode-S While this is a Mode-A code,
// it can only be correlated in Mode-S targets. Mode-A or Mode-A/C targets are not
// displayed in decoded formats since they cannot be correlated with a <hex> value
ret.squ = info->squawk();
// cou Country <hex> Country according to Mode-S allocation block if decodable, mostly unusable/invalid for FLARM A/C
//ret.cou
const auto faa_info = info->external_database_row("faa_aircraft_registry");
if (faa_info) {
ret.cou = faa_info->get("country");
}
// dis Distance (km or NM depending on configuration) To the Receiver GNSS location
auto p = db->base_station.get_pos();
if (p.has_value() && pos.has_value()) {
ret.dis = SSR::CPR::haversine(pos.value(), p.value());
}
ret.tru = info->times;
ret.dbm = info->signal_level;
//ret.lla
ret.lla = std::time(nullptr) - info->timestamp;
//ret.tmp
ret.tmp = info->temperature();
//ret.wsp
ret.wsp = info->wind_speed();
//ret.wdi
ret.wdi = info->wind_direction();
ret.mop = info->ADS_B_Ver();
//ret.spi
ret.spi = info->squawk();
//ret.alr
ret.alr = info->alart();
auto air_speed = info->get_airspeed();
if (air_speed.has_value()) {
auto& t = air_speed.value();
auto type = t.get_airspeed_type();
if (type == SSR::Airspeed_type::Indicated_airspeed_IAS) {
ret.ias = air_speed.value().get_speed();
}
if (type == SSR::Airspeed_type::True_airspeed_TAS) {
ret.tas= air_speed.value().get_speed();
}
ret.hdgm = air_speed.value().get_magnetic_heading();
ret.hdgt = "暂不支持";
}
//ret.qnhs Selected QNH
ret.qnhs = "暂不支持";
//ret.alts Selected Altitude
ret.alts = "暂不支持";
//ret.hdgs Selected Heading
ret.hdgs = info->select_heading();
auto it = info->get_speed_base();
if (it.has_value()) {
auto i = it.value();
i.get_GNSS_barometric_altitudes_difference();
auto diff = i.get_GNSS_barometric_altitudes_difference();
if (diff.has_value() && ret.alt.has_value()) {
ret.altg = diff.value() + ret.alt.value();
}
}
//ret.pic
ret.pic = "暂不支持";
//ret.tcm
ret.tcm = "暂不支持";
// ape Autopilot engaged 2 Mode-S
//ret.ape
ret.ape = "暂不支持";
ret.sil = info->SIL();
//ret.sda
ret.sda = "暂不支持";
ret.nacp = info->NACp();
// pest Number of position estimations per second MLAT
ret.pest = info->get_pest();
// nocl Number of sensors providing data aircraft MLAT
ret.nocl = 1;
// tq Time quality of this entry Sensor 0: GNSS 1: Sensor NTP 2: Server NTP
//ret.tq
ret.tq = "暂不支持";
return ret;
}
};