diff options
| author | Corey Schuhen <[email protected]> | 2024-03-24 15:13:55 +1000 |
|---|---|---|
| committer | Corey Schuhen <[email protected]> | 2024-03-28 09:32:13 +1000 |
| commit | 2217b802781b5f2188b4da659aca47f9d89ee032 (patch) | |
| tree | 3054378ec4087372858312e74091f9a16ce26efd /examples | |
| parent | f5daa50a7baceb44f2aad44bf6ce055bccb08433 (diff) | |
CAN: Unify API's between BXCAN and FDCAN. Use Envelope for all read methods instead of a tuple sometimes.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/stm32f1/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/can.rs | 102 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 29 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/can.rs | 12 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/can.rs | 12 |
5 files changed, 121 insertions, 35 deletions
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index df5d32f70..4f282f326 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -23,6 +23,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } | |||
| 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 24 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 25 | nb = "1.0.0" | 25 | nb = "1.0.0" |
| 26 | static_cell = "2.0.0" | ||
| 26 | 27 | ||
| 27 | [profile.dev] | 28 | [profile.dev] |
| 28 | opt-level = "s" | 29 | opt-level = "s" |
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs index ac337e8a0..90cb9e46b 100644 --- a/examples/stm32f1/src/bin/can.rs +++ b/examples/stm32f1/src/bin/can.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::can::{ | 6 | use embassy_stm32::can::{ |
| 7 | filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, | 7 | filter, Can, Envelope, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, |
| 8 | TxInterruptHandler, | 8 | TxInterruptHandler, |
| 9 | }; | 9 | }; |
| 10 | use embassy_stm32::peripherals::CAN; | 10 | use embassy_stm32::peripherals::CAN; |
| 11 | use embassy_stm32::{bind_interrupts, Config}; | 11 | use embassy_stm32::{bind_interrupts, Config}; |
| 12 | use static_cell::StaticCell; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 14 | ||
| 14 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| @@ -21,6 +22,27 @@ bind_interrupts!(struct Irqs { | |||
| 21 | // This example is configured to work with real CAN transceivers on B8/B9. | 22 | // This example is configured to work with real CAN transceivers on B8/B9. |
| 22 | // See other examples for loopback. | 23 | // See other examples for loopback. |
| 23 | 24 | ||
| 25 | fn handle_frame(env: Envelope, read_mode: &str) { | ||
| 26 | match env.frame.id() { | ||
| 27 | Id::Extended(id) => { | ||
| 28 | defmt::println!( | ||
| 29 | "{} Extended Frame id={:x} {:02x}", | ||
| 30 | read_mode, | ||
| 31 | id.as_raw(), | ||
| 32 | env.frame.data() | ||
| 33 | ); | ||
| 34 | } | ||
| 35 | Id::Standard(id) => { | ||
| 36 | defmt::println!( | ||
| 37 | "{} Standard Frame id={:x} {:02x}", | ||
| 38 | read_mode, | ||
| 39 | id.as_raw(), | ||
| 40 | env.frame.data() | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 24 | #[embassy_executor::main] | 46 | #[embassy_executor::main] |
| 25 | async fn main(_spawner: Spawner) { | 47 | async fn main(_spawner: Spawner) { |
| 26 | let p = embassy_stm32::init(Config::default()); | 48 | let p = embassy_stm32::init(Config::default()); |
| @@ -28,6 +50,9 @@ async fn main(_spawner: Spawner) { | |||
| 28 | // Set alternate pin mapping to B8/B9 | 50 | // Set alternate pin mapping to B8/B9 |
| 29 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); | 51 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); |
| 30 | 52 | ||
| 53 | static RX_BUF: StaticCell<embassy_stm32::can::RxBuf<10>> = StaticCell::new(); | ||
| 54 | static TX_BUF: StaticCell<embassy_stm32::can::TxBuf<10>> = StaticCell::new(); | ||
| 55 | |||
| 31 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); | 56 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); |
| 32 | 57 | ||
| 33 | can.as_mut() | 58 | can.as_mut() |
| @@ -43,21 +68,72 @@ async fn main(_spawner: Spawner) { | |||
| 43 | can.set_bitrate(250_000); | 68 | can.set_bitrate(250_000); |
| 44 | 69 | ||
| 45 | can.enable().await; | 70 | can.enable().await; |
| 46 | |||
| 47 | let mut i: u8 = 0; | 71 | let mut i: u8 = 0; |
| 72 | |||
| 73 | /* | ||
| 74 | // Example for using buffered Tx and Rx without needing to | ||
| 75 | // split first as is done below. | ||
| 76 | let mut can = can.buffered( | ||
| 77 | TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new()), | ||
| 78 | RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 79 | loop { | ||
| 80 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 81 | can.write(&tx_frame).await; | ||
| 82 | |||
| 83 | match can.read().await { | ||
| 84 | Ok((frame, ts)) => { | ||
| 85 | handle_frame(Envelope { ts, frame }, "Buf"); | ||
| 86 | } | ||
| 87 | Err(err) => { | ||
| 88 | defmt::println!("Error {}", err); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | i += 1; | ||
| 92 | } | ||
| 93 | |||
| 94 | */ | ||
| 95 | let (mut tx, mut rx) = can.split(); | ||
| 96 | |||
| 97 | // This example shows using the wait_not_empty API before try read | ||
| 98 | while i < 3 { | ||
| 99 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 100 | tx.write(&tx_frame).await; | ||
| 101 | |||
| 102 | rx.wait_not_empty().await; | ||
| 103 | let env = rx.try_read().unwrap(); | ||
| 104 | handle_frame(env, "Wait"); | ||
| 105 | i += 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | // This example shows using the full async non-buffered API | ||
| 109 | while i < 6 { | ||
| 110 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 111 | tx.write(&tx_frame).await; | ||
| 112 | |||
| 113 | match rx.read().await { | ||
| 114 | Ok(env) => { | ||
| 115 | handle_frame(env, "NoBuf"); | ||
| 116 | } | ||
| 117 | Err(err) => { | ||
| 118 | defmt::println!("Error {}", err); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | i += 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | // This example shows using buffered RX and TX. User passes in desired buffer (size) | ||
| 125 | // It's possible this way to have just RX or TX buffered. | ||
| 126 | let mut rx = rx.buffered(RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 127 | let mut tx = tx.buffered(TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new())); | ||
| 128 | |||
| 48 | loop { | 129 | loop { |
| 49 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | 130 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); |
| 50 | can.write(&tx_frame).await; | 131 | tx.write(&tx_frame).await; |
| 51 | 132 | ||
| 52 | match can.read().await { | 133 | match rx.read().await { |
| 53 | Ok(env) => match env.frame.id() { | 134 | Ok(envelope) => { |
| 54 | Id::Extended(id) => { | 135 | handle_frame(envelope, "Buf"); |
| 55 | defmt::println!("Extended Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | 136 | } |
| 56 | } | ||
| 57 | Id::Standard(id) => { | ||
| 58 | defmt::println!("Standard Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | ||
| 59 | } | ||
| 60 | }, | ||
| 61 | Err(err) => { | 137 | Err(err) => { |
| 62 | defmt::println!("Error {}", err); | 138 | defmt::println!("Error {}", err); |
| 63 | } | 139 | } |
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 4373a89a8..2ed632a93 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { | |||
| 36 | } | 36 | } |
| 37 | let peripherals = embassy_stm32::init(config); | 37 | let peripherals = embassy_stm32::init(config); |
| 38 | 38 | ||
| 39 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 39 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 40 | 40 | ||
| 41 | can.set_extended_filter( | 41 | can.set_extended_filter( |
| 42 | can::filter::ExtendedFilterSlot::_0, | 42 | can::filter::ExtendedFilterSlot::_0, |
| @@ -56,21 +56,22 @@ async fn main(_spawner: Spawner) { | |||
| 56 | info!("Configured"); | 56 | info!("Configured"); |
| 57 | 57 | ||
| 58 | let mut can = can.start(match use_fd { | 58 | let mut can = can.start(match use_fd { |
| 59 | true => can::FdcanOperatingMode::InternalLoopbackMode, | 59 | true => can::OperatingMode::InternalLoopbackMode, |
| 60 | false => can::FdcanOperatingMode::NormalOperationMode, | 60 | false => can::OperatingMode::NormalOperationMode, |
| 61 | }); | 61 | }); |
| 62 | 62 | ||
| 63 | let mut i = 0; | 63 | let mut i = 0; |
| 64 | let mut last_read_ts = embassy_time::Instant::now(); | 64 | let mut last_read_ts = embassy_time::Instant::now(); |
| 65 | 65 | ||
| 66 | loop { | 66 | loop { |
| 67 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 67 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 68 | info!("Writing frame"); | 68 | info!("Writing frame"); |
| 69 | 69 | ||
| 70 | _ = can.write(&frame).await; | 70 | _ = can.write(&frame).await; |
| 71 | 71 | ||
| 72 | match can.read().await { | 72 | match can.read().await { |
| 73 | Ok((rx_frame, ts)) => { | 73 | Ok(envelope) => { |
| 74 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 74 | let delta = (ts - last_read_ts).as_millis(); | 75 | let delta = (ts - last_read_ts).as_millis(); |
| 75 | last_read_ts = ts; | 76 | last_read_ts = ts; |
| 76 | info!( | 77 | info!( |
| @@ -105,7 +106,8 @@ async fn main(_spawner: Spawner) { | |||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | match can.read_fd().await { | 108 | match can.read_fd().await { |
| 108 | Ok((rx_frame, ts)) => { | 109 | Ok(envelope) => { |
| 110 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 109 | let delta = (ts - last_read_ts).as_millis(); | 111 | let delta = (ts - last_read_ts).as_millis(); |
| 110 | last_read_ts = ts; | 112 | last_read_ts = ts; |
| 111 | info!( | 113 | info!( |
| @@ -129,12 +131,13 @@ async fn main(_spawner: Spawner) { | |||
| 129 | let (mut tx, mut rx) = can.split(); | 131 | let (mut tx, mut rx) = can.split(); |
| 130 | // With split | 132 | // With split |
| 131 | loop { | 133 | loop { |
| 132 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 134 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 133 | info!("Writing frame"); | 135 | info!("Writing frame"); |
| 134 | _ = tx.write(&frame).await; | 136 | _ = tx.write(&frame).await; |
| 135 | 137 | ||
| 136 | match rx.read().await { | 138 | match rx.read().await { |
| 137 | Ok((rx_frame, ts)) => { | 139 | Ok(envelope) => { |
| 140 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 138 | let delta = (ts - last_read_ts).as_millis(); | 141 | let delta = (ts - last_read_ts).as_millis(); |
| 139 | last_read_ts = ts; | 142 | last_read_ts = ts; |
| 140 | info!( | 143 | info!( |
| @@ -156,7 +159,7 @@ async fn main(_spawner: Spawner) { | |||
| 156 | } | 159 | } |
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | let can = can::Fdcan::join(tx, rx); | 162 | let can = can::Can::join(tx, rx); |
| 160 | 163 | ||
| 161 | info!("\n\n\nBuffered\n"); | 164 | info!("\n\n\nBuffered\n"); |
| 162 | if use_fd { | 165 | if use_fd { |
| @@ -173,7 +176,8 @@ async fn main(_spawner: Spawner) { | |||
| 173 | _ = can.write(frame).await; | 176 | _ = can.write(frame).await; |
| 174 | 177 | ||
| 175 | match can.read().await { | 178 | match can.read().await { |
| 176 | Ok((rx_frame, ts)) => { | 179 | Ok(envelope) => { |
| 180 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 177 | let delta = (ts - last_read_ts).as_millis(); | 181 | let delta = (ts - last_read_ts).as_millis(); |
| 178 | last_read_ts = ts; | 182 | last_read_ts = ts; |
| 179 | info!( | 183 | info!( |
| @@ -198,7 +202,7 @@ async fn main(_spawner: Spawner) { | |||
| 198 | RX_BUF.init(can::RxBuf::<10>::new()), | 202 | RX_BUF.init(can::RxBuf::<10>::new()), |
| 199 | ); | 203 | ); |
| 200 | loop { | 204 | loop { |
| 201 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 205 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 202 | info!("Writing frame"); | 206 | info!("Writing frame"); |
| 203 | 207 | ||
| 204 | // You can use any of these approaches to send. The writer makes it | 208 | // You can use any of these approaches to send. The writer makes it |
| @@ -208,7 +212,8 @@ async fn main(_spawner: Spawner) { | |||
| 208 | can.writer().write(frame).await; | 212 | can.writer().write(frame).await; |
| 209 | 213 | ||
| 210 | match can.read().await { | 214 | match can.read().await { |
| 211 | Ok((rx_frame, ts)) => { | 215 | Ok(envelope) => { |
| 216 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 212 | let delta = (ts - last_read_ts).as_millis(); | 217 | let delta = (ts - last_read_ts).as_millis(); |
| 213 | last_read_ts = ts; | 218 | last_read_ts = ts; |
| 214 | info!( | 219 | info!( |
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 643df27f9..dd625c90a 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs | |||
| @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | 24 | ||
| 25 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 26 | 26 | ||
| 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 28 | 28 | ||
| 29 | // 250k bps | 29 | // 250k bps |
| 30 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| @@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) { | |||
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | 38 | let mut last_read_ts = embassy_time::Instant::now(); |
| 39 | 39 | ||
| 40 | loop { | 40 | loop { |
| 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 41 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 42 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 43 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 44 | 44 | ||
| 45 | match can.read().await { | 45 | match can.read().await { |
| 46 | Ok((rx_frame, ts)) => { | 46 | Ok(envelope) => { |
| 47 | let (rx_frame, ts) = envelope.parts(); | ||
| 47 | let delta = (ts - last_read_ts).as_millis(); | 48 | let delta = (ts - last_read_ts).as_millis(); |
| 48 | last_read_ts = ts; | 49 | last_read_ts = ts; |
| 49 | info!( | 50 | info!( |
| @@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) { | |||
| 69 | let (mut tx, mut rx) = can.split(); | 70 | let (mut tx, mut rx) = can.split(); |
| 70 | // With split | 71 | // With split |
| 71 | loop { | 72 | loop { |
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 73 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 73 | info!("Writing frame"); | 74 | info!("Writing frame"); |
| 74 | _ = tx.write(&frame).await; | 75 | _ = tx.write(&frame).await; |
| 75 | 76 | ||
| 76 | match rx.read().await { | 77 | match rx.read().await { |
| 77 | Ok((rx_frame, ts)) => { | 78 | Ok(envelope) => { |
| 79 | let (rx_frame, ts) = envelope.parts(); | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | 80 | let delta = (ts - last_read_ts).as_millis(); |
| 79 | last_read_ts = ts; | 81 | last_read_ts = ts; |
| 80 | info!( | 82 | info!( |
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 13a6a5051..22cb27481 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs | |||
| @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | 24 | ||
| 25 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 26 | 26 | ||
| 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 28 | 28 | ||
| 29 | // 250k bps | 29 | // 250k bps |
| 30 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| @@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) { | |||
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | 38 | let mut last_read_ts = embassy_time::Instant::now(); |
| 39 | 39 | ||
| 40 | loop { | 40 | loop { |
| 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 41 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 42 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 43 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 44 | 44 | ||
| 45 | match can.read().await { | 45 | match can.read().await { |
| 46 | Ok((rx_frame, ts)) => { | 46 | Ok(envelope) => { |
| 47 | let (rx_frame, ts) = envelope.parts(); | ||
| 47 | let delta = (ts - last_read_ts).as_millis(); | 48 | let delta = (ts - last_read_ts).as_millis(); |
| 48 | last_read_ts = ts; | 49 | last_read_ts = ts; |
| 49 | info!( | 50 | info!( |
| @@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) { | |||
| 69 | let (mut tx, mut rx) = can.split(); | 70 | let (mut tx, mut rx) = can.split(); |
| 70 | // With split | 71 | // With split |
| 71 | loop { | 72 | loop { |
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 73 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 73 | info!("Writing frame"); | 74 | info!("Writing frame"); |
| 74 | _ = tx.write(&frame).await; | 75 | _ = tx.write(&frame).await; |
| 75 | 76 | ||
| 76 | match rx.read().await { | 77 | match rx.read().await { |
| 77 | Ok((rx_frame, ts)) => { | 78 | Ok(envelope) => { |
| 79 | let (rx_frame, ts) = envelope.parts(); | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | 80 | let delta = (ts - last_read_ts).as_millis(); |
| 79 | last_read_ts = ts; | 81 | last_read_ts = ts; |
| 80 | info!( | 82 | info!( |
