From d7c84d60e8bddd396c205414261978ab74d41013 Mon Sep 17 00:00:00 2001 From: core Date: Mon, 19 May 2025 23:01:29 -0400 Subject: [PATCH] feat: cif work --- Cargo.lock | 1 + crates/interchange/Cargo.toml | 4 +- .../schemas/digitalRadarData.capnp | 5 +- crates/interchange/src/ar2.rs | 70 +++- .../interchange/src/digitalRadarData_capnp.rs | 326 ++---------------- crates/interchange/src/lib.rs | 2 +- crates/tiler/Cargo.toml | 2 +- crates/tiler/src/nexrad.rs | 8 +- 8 files changed, 119 insertions(+), 299 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33beb46..ccd01eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3630,6 +3630,7 @@ version = "0.1.0" dependencies = [ "capnp", "capnpc", + "nexrad-decode", "wxbox-ar2", ] diff --git a/crates/interchange/Cargo.toml b/crates/interchange/Cargo.toml index d526102..e217d36 100644 --- a/crates/interchange/Cargo.toml +++ b/crates/interchange/Cargo.toml @@ -5,11 +5,13 @@ edition = "2024" [dependencies] capnp = "0.20" + wxbox-ar2 = { path = "../ar2", optional = true } +nexrad-decode = { path = "../nexrad-decode", optional = true } [features] default = [] -ar2 = ["dep:wxbox-ar2"] +ar2 = ["dep:wxbox-ar2", "dep:nexrad-decode"] [build-dependencies] capnpc = "0.20" \ No newline at end of file diff --git a/crates/interchange/schemas/digitalRadarData.capnp b/crates/interchange/schemas/digitalRadarData.capnp index c05353f..7dfb500 100644 --- a/crates/interchange/schemas/digitalRadarData.capnp +++ b/crates/interchange/schemas/digitalRadarData.capnp @@ -19,10 +19,7 @@ struct Radial { elevationNumber @5 :UInt8; elevationDegrees @6 :Float32; - requestedProduct :union { - unavailable @7 :Void; - available @8 :MomentaryProduct; - } + requestedProduct @7 :MomentaryProduct; } enum RadialStatus { diff --git a/crates/interchange/src/ar2.rs b/crates/interchange/src/ar2.rs index 6458614..cd39599 100644 --- a/crates/interchange/src/ar2.rs +++ b/crates/interchange/src/ar2.rs @@ -1,5 +1,7 @@ -use wxbox_ar2::Scan; -pub fn serialize_scan_to_cif_message(scan: &Scan, elevation_number: u8) -> Vec { +use std::io::Cursor; +use nexrad_decode::messages::digital_radar_data::RadialStatus; +use wxbox_ar2::{MomentData, Radial, Scan}; +pub fn serialize_scan_to_cif_message(scan: &Scan, elevation_number: u8, requested_product: &str) -> Vec { let mut message = capnp::message::Builder::new_default(); let cif_message = message.init_root::(); let mut digital_radar_data = cif_message.init_digital_radar_data(); @@ -10,10 +12,72 @@ pub fn serialize_scan_to_cif_message(scan: &Scan, elevation_number: u8) -> Vec = vec![]; + for radial in &elevation.radials { + match requested_product { + "REF" if radial.reflectivity.is_some() => { + radials_we_can_use.push((&radial, &radial.reflectivity.as_ref().unwrap())); + }, + "VEL" if radial.velocity.is_some() => { + radials_we_can_use.push((&radial, &radial.velocity.as_ref().unwrap())); + }, + "SW" if radial.spectrum_width.is_some() => { + radials_we_can_use.push((&radial, &radial.spectrum_width.as_ref().unwrap())); + }, + "ZDR" if radial.differential_reflectivity.is_some() => { + radials_we_can_use.push((&radial, &radial.differential_reflectivity.as_ref().unwrap())); + }, + "PHI" if radial.differential_phase.is_some() => { + radials_we_can_use.push((&radial, &radial.differential_phase.as_ref().unwrap())); + }, + "RHO" if radial.correlation_coefficient.is_some() => { + radials_we_can_use.push((&radial, &radial.correlation_coefficient.as_ref().unwrap())); + }, + "CFP" if radial.specific_differential_phase.is_some() => { + radials_we_can_use.push((&radial, &radial.specific_differential_phase.as_ref().unwrap())); + }, + _ => {} + } + } + let mut radials = digital_radar_data.reborrow().init_radials(radials_we_can_use.len() as u32); + + for (number, (radial, data)) in radials_we_can_use.iter().enumerate() { + let mut this_radial_msg = radials.reborrow().get(number as u32); + this_radial_msg.set_collection_timestamp(radial.collection_timestamp); + this_radial_msg.set_azimuth_number(radial.azimuth_number); + this_radial_msg.set_azimuth_angle_degrees(radial.azimuth_angle_degrees); + this_radial_msg.set_azimuth_spacing_degrees(radial.azimuth_spacing_degrees); + this_radial_msg.set_elevation_number(radial.elevation_number); + this_radial_msg.set_elevation_degrees(radial.elevation_number_degrees); + + this_radial_msg.set_radial_status(match radial.radial_status { + RadialStatus::ElevationStart => crate::digitalRadarData_capnp::RadialStatus::ElevationStart, + RadialStatus::IntermediateRadialData => crate::digitalRadarData_capnp::RadialStatus::IntermediateRadialData, + RadialStatus::ElevationEnd => crate::digitalRadarData_capnp::RadialStatus::ElevationEnd, + RadialStatus::VolumeScanStart => crate::digitalRadarData_capnp::RadialStatus::VolumeScanStart, + RadialStatus::VolumeScanEnd => crate::digitalRadarData_capnp::RadialStatus::VolumeScanEnd, + RadialStatus::ElevationStartVCPFinal => crate::digitalRadarData_capnp::RadialStatus::ElevationStartVCPFinal, + }); + + let mut msg_requested_product = this_radial_msg.reborrow().init_requested_product(); + + let mut product_metadata = msg_requested_product.reborrow().init_product_metadata(); + product_metadata.set_product_name(requested_product); + + let mut momentary_product_data = msg_requested_product.reborrow().init_data(); + momentary_product_data.set_scale(data.scale); + momentary_product_data.set_offset(data.offset); + momentary_product_data.set_start_range(data.start_range); + momentary_product_data.set_sample_interval(data.sample_interval); + momentary_product_data.set_values(&*data.values).unwrap(); + } } else { digital_radar_data.reborrow().init_radials(0); // no elevation is signalled by an empty radials field } - todo!() + let mut output = Cursor::new(Vec::new()); + capnp::serialize_packed::write_message(&mut output, &message).unwrap(); + output.into_inner() } \ No newline at end of file diff --git a/crates/interchange/src/digitalRadarData_capnp.rs b/crates/interchange/src/digitalRadarData_capnp.rs index 0a4be41..06e40d8 100644 --- a/crates/interchange/src/digitalRadarData_capnp.rs +++ b/crates/interchange/src/digitalRadarData_capnp.rs @@ -364,8 +364,12 @@ pub mod radial { self.reader.get_data_field::(6) } #[inline] - pub fn get_requested_product(self) -> crate::digitalRadarData_capnp::radial::requested_product::Reader<'a> { - self.reader.into() + pub fn get_requested_product(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_requested_product(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() } } @@ -478,14 +482,20 @@ pub mod radial { self.builder.set_data_field::(6, value); } #[inline] - pub fn get_requested_product(self) -> crate::digitalRadarData_capnp::radial::requested_product::Builder<'a> { - self.builder.into() + pub fn get_requested_product(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn init_requested_product(mut self, ) -> crate::digitalRadarData_capnp::radial::requested_product::Builder<'a> { - self.builder.set_data_field::(11, 0); - self.builder.reborrow().get_pointer_field(0).clear(); - self.builder.into() + pub fn set_requested_product(&mut self, value: crate::digitalRadarData_capnp::momentary_product::Reader<'_>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_requested_product(self, ) -> crate::digitalRadarData_capnp::momentary_product::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_requested_product(&self) -> bool { + !self.builder.is_pointer_field_null(0) } } @@ -496,19 +506,19 @@ pub mod radial { } } impl Pipeline { - pub fn get_requested_product(&self) -> crate::digitalRadarData_capnp::radial::requested_product::Pipeline { - ::capnp::capability::FromTypelessPipeline::new(self._typeless.noop()) + pub fn get_requested_product(&self) -> crate::digitalRadarData_capnp::momentary_product::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 145] = [ + pub static ENCODED_NODE: [::capnp::Word; 152] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), ::capnp::word(52, 61, 253, 131, 10, 228, 32, 210), ::capnp::word(23, 0, 0, 0, 1, 0, 4, 0), ::capnp::word(138, 240, 108, 5, 28, 207, 29, 249), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(145, 0, 0, 0, 1, 2, 0, 0), + ::capnp::word(145, 0, 0, 0, 194, 1, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -571,12 +581,12 @@ pub mod radial { ::capnp::word(16, 1, 0, 0, 3, 0, 1, 0), ::capnp::word(28, 1, 0, 0, 2, 0, 1, 0), ::capnp::word(7, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(53, 153, 198, 6, 37, 147, 62, 245), + ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(25, 1, 0, 0, 138, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(28, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(40, 1, 0, 0, 2, 0, 1, 0), ::capnp::word(99, 111, 108, 108, 101, 99, 116, 105), ::capnp::word(111, 110, 84, 105, 109, 101, 115, 116), ::capnp::word(97, 109, 112, 0, 0, 0, 0, 0), @@ -647,6 +657,13 @@ pub mod radial { ::capnp::word(114, 101, 113, 117, 101, 115, 116, 101), ::capnp::word(100, 80, 114, 111, 100, 117, 99, 116), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(145, 161, 46, 18, 18, 53, 76, 181), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { @@ -657,7 +674,7 @@ pub mod radial { 4 => ::introspect(), 5 => ::introspect(), 6 => ::introspect(), - 7 => ::introspect(), + 7 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -675,273 +692,6 @@ pub mod radial { pub static MEMBERS_BY_NAME : &[u16] = &[2,1,3,0,6,5,4,7]; pub const TYPE_ID: u64 = 0xd220_e40a_83fd_3d34; } - - pub mod requested_product { - pub use self::Which::{Unavailable,Available}; - - #[derive(Copy, Clone)] - pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) - } - } - - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn has_available(&self) -> bool { - if self.reader.get_data_field::(11) != 1 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.reader.get_data_field::(11) { - 0 => { - ::core::result::Result::Ok(Unavailable( - () - )) - } - 1 => { - ::core::result::Result::Ok(Available( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - x => ::core::result::Result::Err(::capnp::NotInSchema(x)) - } - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 4, pointers: 1 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn set_unavailable(&mut self, _value: ()) { - self.builder.set_data_field::(11, 0); - } - #[inline] - pub fn set_available(&mut self, value: crate::digitalRadarData_capnp::momentary_product::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(11, 1); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_available(self, ) -> crate::digitalRadarData_capnp::momentary_product::Builder<'a> { - self.builder.set_data_field::(11, 1); - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) - } - #[inline] - pub fn has_available(&self) -> bool { - if self.builder.get_data_field::(11) != 1 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.builder.get_data_field::(11) { - 0 => { - ::core::result::Result::Ok(Unavailable( - () - )) - } - 1 => { - ::core::result::Result::Ok(Available( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - x => ::core::result::Result::Err(::capnp::NotInSchema(x)) - } - } - } - - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 52] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(53, 153, 198, 6, 37, 147, 62, 245), - ::capnp::word(30, 0, 0, 0, 1, 0, 4, 0), - ::capnp::word(52, 61, 253, 131, 10, 228, 32, 210), - ::capnp::word(1, 0, 7, 0, 1, 0, 2, 0), - ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(21, 0, 0, 0, 122, 1, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(33, 0, 0, 0, 119, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(100, 105, 103, 105, 116, 97, 108, 82), - ::capnp::word(97, 100, 97, 114, 68, 97, 116, 97), - ::capnp::word(46, 99, 97, 112, 110, 112, 58, 82), - ::capnp::word(97, 100, 105, 97, 108, 46, 114, 101), - ::capnp::word(113, 117, 101, 115, 116, 101, 100, 80), - ::capnp::word(114, 111, 100, 117, 99, 116, 0, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 255, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 0, 0, 0, 98, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 254, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 8, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(49, 0, 0, 0, 82, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(48, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(60, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(117, 110, 97, 118, 97, 105, 108, 97), - ::capnp::word(98, 108, 101, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(97, 118, 97, 105, 108, 97, 98, 108), - ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(145, 161, 46, 18, 18, 53, 76, 181), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { - 0 => <() as ::capnp::introspect::Introspect>::introspect(), - 1 => ::introspect(), - _ => panic!("invalid field index {}", index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - panic!("invalid annotation indices ({:?}, {}) ", child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1]; - pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; - pub const TYPE_ID: u64 = 0xf53e_9325_06c6_9935; - } - pub enum Which { - Unavailable(()), - Available(A0), - } - pub type WhichReader<'a,> = Which<::capnp::Result>>; - pub type WhichBuilder<'a,> = Which<::capnp::Result>>; - } } #[repr(u16)] @@ -990,7 +740,7 @@ pub static ENCODED_NODE: [::capnp::Word; 52] = [ ::capnp::word(138, 240, 108, 5, 28, 207, 29, 249), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(3, 2, 0, 0, 224, 2, 0, 0), + ::capnp::word(196, 1, 0, 0, 161, 2, 0, 0), ::capnp::word(21, 0, 0, 0, 34, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1229,7 +979,7 @@ pub mod momentary_product { ::capnp::word(138, 240, 108, 5, 28, 207, 29, 249), ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(226, 2, 0, 0, 78, 3, 0, 0), + ::capnp::word(163, 2, 0, 0, 15, 3, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1455,7 +1205,7 @@ pub mod momentary_product_meta { ::capnp::word(138, 240, 108, 5, 28, 207, 29, 249), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(80, 3, 0, 0, 137, 3, 0, 0), + ::capnp::word(17, 3, 0, 0, 74, 3, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1714,7 +1464,7 @@ pub mod momentary_product_data { ::capnp::word(138, 240, 108, 5, 28, 207, 29, 249), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(138, 3, 0, 0, 48, 4, 0, 0), + ::capnp::word(75, 3, 0, 0, 241, 3, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), diff --git a/crates/interchange/src/lib.rs b/crates/interchange/src/lib.rs index a528b02..f64c431 100644 --- a/crates/interchange/src/lib.rs +++ b/crates/interchange/src/lib.rs @@ -5,5 +5,5 @@ pub mod digitalRadarData_capnp; #[allow(non_snake_case)] pub mod tilerStatusReport_capnp; -#[cfg(feature = ar2)] +#[cfg(feature = "ar2")] pub mod ar2; \ No newline at end of file diff --git a/crates/tiler/Cargo.toml b/crates/tiler/Cargo.toml index a71a633..d0e166a 100644 --- a/crates/tiler/Cargo.toml +++ b/crates/tiler/Cargo.toml @@ -46,4 +46,4 @@ wxbox-common = { path = "../common" } chrono = "0.4" quick-xml = { version = "0.37", features = ["serialize"] } -wxbox-interchange = { path = "../interchange" } \ No newline at end of file +wxbox-interchange = { path = "../interchange", features = ["ar2"] } \ No newline at end of file diff --git a/crates/tiler/src/nexrad.rs b/crates/tiler/src/nexrad.rs index d5b0235..74b130a 100644 --- a/crates/tiler/src/nexrad.rs +++ b/crates/tiler/src/nexrad.rs @@ -24,6 +24,7 @@ use std::sync::Arc; use tracing::{debug, info_span}; use wxbox_ar2::sites::wsr88d::{SITES, Wsr88dSite}; use wxbox_ar2::{MomentValue, Radial, Scan, Sweep, parse}; +use wxbox_interchange::ar2::serialize_scan_to_cif_message; use wxbox_pal::ColorPalette; pub type NexradDataCache = Cache>; @@ -126,7 +127,12 @@ pub async fn nexrad_data_handler( state.nexrad_data_cache.get(&data_id).await.unwrap() }; - todo!() + + + Ok(( + [(header::CONTENT_TYPE, "application/wxbox-common-interchange-format")], + serialize_scan_to_cif_message(&data, sweep, &product), + )) } async fn load_nexrad_data(