diff --git a/etws_loader/src/lib.rs b/etws_loader/src/lib.rs index 45741bc..3b84800 100644 --- a/etws_loader/src/lib.rs +++ b/etws_loader/src/lib.rs @@ -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 where { - let mut lat_range = [0.0, 0.0]; - let mut lon_range = [0.0, 0.0]; + fn load(&self, path: RStr<'_>) -> RResult, 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 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} + ); - 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], - ); - - 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::>(), - 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::>(), - ), - fill_value: b.info.fill_value, - data_type, - } + .collect::>(), + ); + let dimension_names = convert_vec_to_rvec( + b.info + .dimension_des + .into_iter() + .map(RString::from) + .collect::>(), + ); + + 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::>(); - 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(raw: impl Iterator) -> RVec { + RVec::from(raw.collect::>()) +} + +fn convert_vec_to_rvec(raw: Vec) -> RVec { + RVec::from(raw) +} + +fn convert_nested_vec_to_rvec(raw: Vec>) -> RVec> { + RVec::from(raw.into_iter().map(RVec::from).collect::>()) +} + #[sabi_extern_fn] -pub fn new(plugin_id: PluginId) -> RResult { +pub fn new(plugin_id: PluginId) -> RResult { let this = ETWSLoader { id: plugin_id }; - ROk(Plugin_TO::from_value(this, TD_Opaque)) + ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque)) } // 测试模块 diff --git a/radar-g/src/datapool/mod.rs b/radar-g/src/datapool/mod.rs index bb48a85..6760668 100644 --- a/radar-g/src/datapool/mod.rs +++ b/radar-g/src/datapool/mod.rs @@ -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 = Arc; pub enum Data { @@ -24,12 +27,15 @@ impl DataPool { pub fn get_or_load(&self, path: impl Into) -> Result, ()> { 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(()) }) } } diff --git a/radar-g/src/plugin_system/mod.rs b/radar-g/src/plugin_system/mod.rs index e353864..a889804 100644 --- a/radar-g/src/plugin_system/mod.rs +++ b/radar-g/src/plugin_system/mod.rs @@ -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() + } } diff --git a/radarg_plugin_interface/src/lib.rs b/radarg_plugin_interface/src/lib.rs index e27869e..e9b3ad2 100644 --- a/radarg_plugin_interface/src/lib.rs +++ b/radarg_plugin_interface/src/lib.rs @@ -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), +} + +#[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), F64(RVec), @@ -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, + pub dimensions: RVec>, + pub dimension_names: RVec, + pub fill_value: f64, pub datetime: ROption, - pub site_info: ROption, - pub lat_range: ROption<[f64; 2]>, - pub lon_range: ROption<[f64; 2]>, - pub data_format: ROption, - pub other_info: ROption, + pub value_description: ROption, + pub value_name: RString, + pub maybe_probe_data_type: ROption, + 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, -} - -#[repr(C)] -#[derive(StableAbi, Clone, Debug)] -#[sabi(impl_InterfaceType(Sync, Send, Debug))] -pub struct Block { - pub data: VecResult, - pub shape: DataShape, - pub size: RVec, - pub coord_type: CoordType, - pub datetime: i64, - pub dimensions: RVec, - pub dimension_values: RVec>, - 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>, } +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; +pub trait DataLoaderPlugin: Send + Sync { + fn load(&self, path: RStr<'_>) -> RResult, Error>; fn plugin_id(&self) -> &PluginId; fn plugin_info(&self) -> PluginInfo; } @@ -151,7 +114,6 @@ pub trait Plugin: Send + Sync { /// call ::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!(); }