sync
This commit is contained in:
parent
58947b9aa1
commit
2aecd72b8a
@ -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))
|
||||
}
|
||||
|
||||
// 测试模块
|
||||
|
||||
@ -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(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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!();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user