This commit is contained in:
Tsuki 2024-08-25 15:58:17 +08:00
parent 58947b9aa1
commit 2aecd72b8a
4 changed files with 163 additions and 242 deletions

View File

@ -14,11 +14,35 @@ use abi_stable::{
},
};
use parser::{Record, ValueResult};
use radarg_plugin_interface::{
CoordType, Error, Loc3, MetaData, Plugin, PluginId, PluginMod, PluginMod_Ref, PluginResult,
PluginResultType, PluginType, Plugin_TO,
DataLoaderPlugin, DataLoaderPlugin_TO, Error, GridDataInfo, LoadedData, PluginId, PluginMod,
PluginMod_Ref, ProbeDataType, RadarGridData, VecResult,
};
macro_rules! data_rvec {
($data:ident, $({$parsed_vec:tt => $abi_stable_rvec:tt}),+) => {
match $data {
$(
ValueResult::$parsed_vec(data) => VecResult::$abi_stable_rvec(RVec::from(data)),
)+
}
};
}
macro_rules! data_type {
($datetype:ident, $({ $($name:literal)|+ => $type:tt }),+) => {
match $datetype {
$(
$($name)|+ => ProbeDataType::$type,
)+
_ => ProbeDataType::Unknown
}
};
}
#[export_root_module]
fn instantiate_root_module() -> PluginMod_Ref {
PluginMod { new }.leak_into_prefix()
@ -28,182 +52,90 @@ struct ETWSLoader {
id: PluginId,
}
fn calculate_coverage(lat_deg: f64, lon_deg: f64, radius_km: f64) -> (f64, f64, f64, f64) {
let center = Point::new(lon_deg, lat_deg);
// 计算四个方向(北、南、东、西)的点
let north = center.haversine_destination(0.0, radius_km);
let south = center.haversine_destination(180.0, radius_km);
let east = center.haversine_destination(90.0, radius_km);
let west = center.haversine_destination(270.0, radius_km);
let min_lat = south.y();
let max_lat = north.y();
let min_lon = west.x();
let max_lon = east.x();
(min_lat, max_lat, min_lon, max_lon)
}
impl Plugin for ETWSLoader {
impl DataLoaderPlugin for ETWSLoader {
fn plugin_id(&self) -> &PluginId {
&self.id
}
fn load(&self, path: RStr<'_>) -> RResult<PluginResult, Error> where {
let mut lat_range = [0.0, 0.0];
let mut lon_range = [0.0, 0.0];
fn load(&self, path: RStr<'_>) -> RResult<RVec<LoadedData>, Error> where {
if let Ok(record) = Record::parse_from_path(path.to_string()) {
let result_blocks = record
let result = record
.blocks
.into_iter()
.map(|b| {
let (dimension_len, data) = match b.data {
ValueResult::I16(data) => (
data.len(),
radarg_plugin_interface::VecResult::I16(RVec::from(data)),
),
ValueResult::F32(data) => (
data.len(),
radarg_plugin_interface::VecResult::F32(RVec::from(data)),
),
ValueResult::F64(data) => (
data.len(),
radarg_plugin_interface::VecResult::F64(RVec::from(data)),
),
ValueResult::I32(data) => (
data.len(),
radarg_plugin_interface::VecResult::I32(RVec::from(data)),
),
ValueResult::U32(data) => (
data.len(),
radarg_plugin_interface::VecResult::U32(RVec::from(data)),
),
ValueResult::I64(data) => (
data.len(),
radarg_plugin_interface::VecResult::I64(RVec::from(data)),
),
ValueResult::U64(data) => (
data.len(),
radarg_plugin_interface::VecResult::U64(RVec::from(data)),
),
ValueResult::I8(data) => (
data.len(),
radarg_plugin_interface::VecResult::I8(RVec::from(data)),
),
ValueResult::U8(data) => (
data.len(),
radarg_plugin_interface::VecResult::U8(RVec::from(data)),
),
};
let dimension_des = b.info.dimension_des;
let c = if dimension_des.contains(&format!("lat")) {
let len = b.info.dimension_values.len();
let lon = b.info.dimension_values.get(len - 1).unwrap();
let lat = b.info.dimension_values.get(len - 2).unwrap();
lon_range = [lon[0], lon[lon.len() - 1]];
lat_range = [lat[0], lat[lat.len() - 1]];
CoordType::Cartesian
} else if dimension_des.contains(&format!("ele"))
|| dimension_des.contains(&format!("el"))
|| dimension_des.contains(&format!("elevation"))
{
let (min_lat, max_lat, min_lon, max_lon) = calculate_coverage(
b.info.radar_lat.unwrap(),
b.info.radar_lon.unwrap(),
b.info.dimension_end[2],
let data = b.data;
let converted_data = data_rvec!(
data,
{I16 => I16},
{F32 => F32},
{F64 => F64},
{I32 => I32},
{U32 => U32},
{I64 => I64},
{U64 => U64},
{I8 => I8},
{U8 => U8}
);
lon_range = [min_lon, max_lon];
lat_range = [min_lat, max_lat];
CoordType::Polar(
Loc3 {
x: b.info.radar_lon.unwrap(),
y: b.info.radar_lat.unwrap(),
z: b.info.radar_alt.unwrap(),
},
b.info.dimension_end[2],
)
} else {
CoordType::Other
};
let shape = match b.info.dimension_size.len() {
1 => radarg_plugin_interface::DataShape::Vector,
2 => {
// let lat = b.info.dimension_values.get(0).unwrap();
// let lon = b.info.dimension_values.get(1).unwrap();
// lat_range = [lat[0], lat[lat.len() - 1]];
// lon_range = [lon[0], lon[lon.len() - 1]];
radarg_plugin_interface::DataShape::Matrix
}
_ => {
// let lat = b.info.dimension_values.get(1).unwrap();
// let lon = b.info.dimension_values.get(2).unwrap();
// lat_range = [lat[0], lat[lat.len() - 1]];
// lon_range = [lon[0], lon[lon.len() - 1]];
radarg_plugin_interface::DataShape::Cube
}
};
let data_type = match b.info.value_name.as_str() {
"ET" => PluginResultType::ET,
"VIL" => PluginResultType::VIL,
"EB" => PluginResultType::EB,
"DBZ" => PluginResultType::DBZ,
"CR" => PluginResultType::DBZ,
"R" => PluginResultType::R,
"V" => PluginResultType::V,
"ZDR" => PluginResultType::ZDR,
"PHIDP" => PluginResultType::PHIDP,
"KDP" => PluginResultType::KDP,
"CC" => PluginResultType::CC,
"HCA" => PluginResultType::HCA,
"QPE" => PluginResultType::QPE,
"QPF" => PluginResultType::QPF,
"FR" => PluginResultType::DBZ,
_ => PluginResultType::Unknown,
};
radarg_plugin_interface::Block {
data: data,
shape,
size: RVec::from(b.info.dimension_size)
let dimension_values = convert_nested_vec_to_rvec(b.info.dimension_values);
let dimension_size = convert_vec_to_rvec(
b.info
.dimension_size
.into_iter()
.map(|p| p as usize)
.collect::<RVec<_>>(),
datetime: record.filetime.timestamp(),
dimensions: RVec::from(vec![RString::from("time")]),
coord_type: c,
dimension_values: RVec::from(
b.info
.dimension_values
.into_iter()
.map(|p| RVec::from(p))
.collect::<Vec<_>>(),
),
fill_value: b.info.fill_value,
data_type,
}
);
let dimension_names = convert_vec_to_rvec(
b.info
.dimension_des
.into_iter()
.map(RString::from)
.collect::<Vec<_>>(),
);
let fill_value = b.info.fill_value;
let value_name = RString::from(b.info.value_name);
let value_description = RString::from(b.info.value_des);
let datetime = record.filetime.timestamp();
let value_key = value_name.as_str();
let data_type = data_type!(
value_key,
{ "ET" => ET },
{ "DBZ" | "CR" | "FR" | "R" => DBZ},
{ "VIL" => VIL},
{ "EB" => EB},
{ "V" => V},
{ "ZDR" => ZDR},
{ "PHIDP" => PHIDP},
{ "KDP" => KDP},
{ "CC" =>CC},
{ "HCA" => HCA},
{ "QPE" => QPE},
{ "QPF" => QPF}
);
let grid_info = GridDataInfo {
shape: dimension_size,
dimensions: dimension_values,
dimension_names,
fill_value,
datetime: RSome(datetime),
value_description: RSome(value_description),
maybe_probe_data_type: RSome(data_type),
value_name,
dimension_description: "Wrong".into(),
};
LoadedData::RadarGridData(RadarGridData {
data: converted_data,
info: grid_info,
})
})
.collect::<RVec<_>>();
let meta = MetaData {
datetime: RSome(record.filetime.timestamp()),
site_info: RNone,
lon_range: RSome(lon_range),
lat_range: RSome(lat_range),
data_format: RSome("Eastone Washon Radar".into()),
other_info: RNone,
};
ROk(PluginResult {
datetime: RString::from(record.filetime.format("%Y%m%d%H%M").to_string()),
blocks: result_blocks,
meta,
})
ROk(result)
} else {
RErr(Error::UnsupportedFormat)
}
@ -211,6 +143,7 @@ impl Plugin for ETWSLoader {
fn plugin_info(&self) -> radarg_plugin_interface::PluginInfo where {
radarg_plugin_interface::PluginInfo {
plugin_type: "DataLoader".into(),
name: "ETWS_Loader".into(),
version: "0.1.0".into(),
author: "Tsuki".into(),
@ -220,10 +153,22 @@ impl Plugin for ETWSLoader {
}
}
fn convert_iter_to_rvec<T>(raw: impl Iterator<Item = T>) -> RVec<T> {
RVec::from(raw.collect::<Vec<_>>())
}
fn convert_vec_to_rvec<T>(raw: Vec<T>) -> RVec<T> {
RVec::from(raw)
}
fn convert_nested_vec_to_rvec<T>(raw: Vec<Vec<T>>) -> RVec<RVec<T>> {
RVec::from(raw.into_iter().map(RVec::from).collect::<Vec<_>>())
}
#[sabi_extern_fn]
pub fn new(plugin_id: PluginId) -> RResult<PluginType, Error> {
pub fn new(plugin_id: PluginId) -> RResult<dyn DataLoaderPlugin, Error> {
let this = ETWSLoader { id: plugin_id };
ROk(Plugin_TO::from_value(this, TD_Opaque))
ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque))
}
// 测试模块

View File

@ -2,9 +2,12 @@ pub mod data;
use data::GridData;
use quick_cache::sync::Cache;
use radarg_plugin_interface::Plugin;
use std::path::PathBuf;
use std::sync::Arc;
use crate::PLUGIN_MANAGER;
pub type Value<T> = Arc<T>;
pub enum Data {
@ -24,12 +27,15 @@ impl DataPool {
pub fn get_or_load(&self, path: impl Into<PathBuf>) -> Result<Value<Data>, ()> {
self.pool.get_or_insert_async(&path.into(), async {
let path = path.into();
let data = match path.extension().and_then(|ext| ext.to_str()) {
Some("grid") => Data::GridData(GridData::load(&path).await.unwrap()),
_ => panic!("Unsupported file type"),
};
Ok(Arc::new(data))
// let path = path.into();
for data_loader in PLUGIN_MANAGER.data_loader_plugin().iter() {
let path: PathBuf = path.into();
if let Ok(data) = data_loader.load(path.as_os_str().to_str().unwrap().into()) {
return Ok(Arc::new(Data::GridData(GridData::new(data))));
}
}
Err(())
})
}
}

View File

@ -93,4 +93,12 @@ impl PluginManager {
.find(|(id, _)| id.named == name)
.map(|(_, p)| p)
}
pub fn data_loader_plugin(&self) -> Vec<&Plugin_TO<'static, RBox<()>>> {
self.registered_plugins
.iter()
.filter(|p| p.1.plugin_info().plugin_type == "DataLoader")
.map(|p| p.1)
.collect()
}
}

View File

@ -12,38 +12,30 @@ pub use self::error::Error;
/// The identifier for a plugin.
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq, StableAbi, Hash)]
#[sabi(impl_InterfaceType(Sync, Send, Debug, Debug, Hash))]
pub struct PluginId {
pub named: RCowStr<'static>,
/// The number of the instance of this Plugin.
pub instance: u64,
}
// Plugin Can be loaded from a file path
#[repr(C)]
#[derive(Debug, Clone, StableAbi, Copy)]
#[sabi(impl_InterfaceType(Sync, Send, Debug, Debug))]
pub struct Loc3 {
pub x: f64,
pub y: f64,
pub z: f64,
#[derive(Clone, Debug, StableAbi)]
pub enum LoadedData {
RadarGridData(RadarGridData),
JsonData,
PlainText(RString),
Binary(RVec<u8>),
}
#[repr(C)]
#[derive(StableAbi, Clone, Debug)]
pub struct RadarGridData {
pub data: VecResult,
pub info: GridDataInfo,
}
pub type Range = f64;
#[repr(C)]
#[derive(StableAbi, Clone, Debug, Copy)]
#[sabi(impl_InterfaceType(Sync, Send, Debug, Debug))]
pub enum CoordType {
Polar(Loc3, Range),
Cartesian,
Other,
}
pub type PluginType = Plugin_TO<'static, RBox<()>>;
#[repr(C)]
#[derive(StableAbi, Clone, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub enum VecResult {
I64(RVec<i64>),
F64(RVec<f64>),
@ -58,29 +50,22 @@ pub enum VecResult {
}
#[repr(C)]
#[derive(StableAbi, Clone, Copy, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub enum DataShape {
Vector,
Matrix,
Cube,
}
#[repr(C)]
#[derive(Debug, StableAbi, Clone)]
pub struct MetaData {
#[derive(StableAbi, Clone, Debug)]
pub struct GridDataInfo {
pub shape: RVec<usize>,
pub dimensions: RVec<RVec<f64>>,
pub dimension_names: RVec<RString>,
pub fill_value: f64,
pub datetime: ROption<i64>,
pub site_info: ROption<RString>,
pub lat_range: ROption<[f64; 2]>,
pub lon_range: ROption<[f64; 2]>,
pub data_format: ROption<RString>,
pub other_info: ROption<RString>,
pub value_description: ROption<RString>,
pub value_name: RString,
pub maybe_probe_data_type: ROption<ProbeDataType>,
pub dimension_description: RString,
}
#[repr(C)]
#[derive(StableAbi, Clone, Copy, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub enum PluginResultType {
pub enum ProbeDataType {
// Single
R,
V,
@ -102,34 +87,11 @@ pub enum PluginResultType {
Unknown,
}
#[repr(C)]
#[derive(StableAbi, Clone, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub struct PluginResult {
pub datetime: RString,
pub meta: MetaData,
pub blocks: RVec<Block>,
}
#[repr(C)]
#[derive(StableAbi, Clone, Debug)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub struct Block {
pub data: VecResult,
pub shape: DataShape,
pub size: RVec<usize>,
pub coord_type: CoordType,
pub datetime: i64,
pub dimensions: RVec<RString>,
pub dimension_values: RVec<RVec<f64>>,
pub fill_value: f64,
pub data_type: PluginResultType,
}
#[repr(C)]
#[derive(Debug, StableAbi)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub struct PluginInfo {
pub plugin_type: RStr<'static>,
pub name: RStr<'static>,
pub version: RStr<'static>,
pub author: RStr<'static>,
@ -137,10 +99,11 @@ pub struct PluginInfo {
pub url: ROption<RStr<'static>>,
}
pub type PluginType = DataLoaderPlugin_TO<'static, RBox<()>>;
#[sabi_trait]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
pub trait Plugin: Send + Sync {
fn load(&self, path: RStr<'_>) -> RResult<PluginResult, Error>;
pub trait DataLoaderPlugin: Send + Sync {
fn load(&self, path: RStr<'_>) -> RResult<RVec<LoadedData>, Error>;
fn plugin_id(&self) -> &PluginId;
fn plugin_info(&self) -> PluginInfo;
}
@ -151,7 +114,6 @@ pub trait Plugin: Send + Sync {
/// call <PluginMod as RootModule>::load_from_directory(some_directory_path)
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
#[sabi(kind(Prefix(prefix_ref = PluginMod_Ref)))]
#[sabi(missing_field(panic))]
pub struct PluginMod {
@ -173,7 +135,7 @@ pub struct PluginMod {
impl RootModule for PluginMod_Ref {
declare_root_module_statics! {PluginMod_Ref}
const BASE_NAME: &'static str = "plugin";
const NAME: &'static str = "plugin";
const BASE_NAME: &'static str = "data_loader_plugin";
const NAME: &'static str = "data_loader_plugin";
const VERSION_STRINGS: VersionStrings = package_version_strings!();
}