### Custom Synchronous and Asynchronous I/O Traits (Rust) Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Demonstrates implementing custom synchronous (`WatchdogIo`) and asynchronous (`WatchdogIoAsync`) traits for heartbeat communication. These traits allow for integration with various communication methods beyond UDP and GPIO, such as serial ports or custom network protocols. The implementations involve defining `get` and `clear` methods to handle edge detection and buffer clearing. ```rust use heartbeat_watchdog::{io::WatchdogIo, io::WatchdogIoAsync, Edge, Result, Error}; use std::time::Duration; // Synchronous custom I/O struct MyCustomIo { timeout: Duration, } impl WatchdogIo for MyCustomIo { fn get(&self, expected: Edge) -> Result { // Wait for and return the expected edge // Return Error::Timeout if edge not received in time // Example: Read from serial port, TCP socket, etc. let received_edge = Edge::Rising; // Your implementation if received_edge == expected { Ok(received_edge) } else { Err(Error::Timeout) } } fn clear(&self) -> Result<()> { // Clear any buffered data (e.g., flush socket buffer) Ok(()) } } // Asynchronous custom I/O struct MyAsyncCustomIo { timeout: Duration, } impl WatchdogIoAsync for MyAsyncCustomIo { async fn get(&self, expected: Edge) -> Result { // Async implementation - poll or wait for edge let received_edge = Edge::Falling; Ok(received_edge) } async fn clear(&self) -> Result<()> { Ok(()) } } ``` -------------------------------- ### Configure Watchdog - Rust Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Builds a watchdog configuration with customizable heartbeat intervals, timeout/window ranges, warmup periods, and minimum valid beats. Supports basic and advanced configurations. ```rust use heartbeat_watchdog::{Range, WatchdogConfig}; use std::time::Duration; // Basic configuration with 100ms heartbeat interval let config = WatchdogConfig::new(Duration::from_millis(100)); // Advanced configuration with time window validation let config = WatchdogConfig::new(Duration::from_millis(100)) .with_range(Range::Window(Duration::from_millis(10))) // +/- 10ms window .with_warmup(Duration::from_secs(2)) // 2s warmup after fault .with_min_beats(5); // 5 valid beats before OK // Access configuration values let interval = config.interval(); // Duration let io_timeout = config.io_timeout(); // Duration for I/O operations let warmup = config.warmup(); // Duration let min_beats = config.min_beats(); // u32 ``` -------------------------------- ### Run Synchronous Watchdog - Rust Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Initializes and runs a synchronous watchdog using UDP for I/O. It monitors heartbeat signals, emits state change events, and runs in a blocking loop. Requires the 'std' feature. ```rust use heartbeat_watchdog::{ io::udp::UdpIo, Range, State, StateEvent, Watchdog, WatchdogConfig, }; use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // Configure watchdog with 100ms interval and 10ms window tolerance let watchdog_config = WatchdogConfig::new(Duration::from_millis(100)) .with_range(Range::Window(Duration::from_millis(10))); // Create UDP I/O bound to local address let watchdog_io = UdpIo::create("127.0.0.1:9999", watchdog_config.io_timeout())?; // Create watchdog instance let watchdog = Watchdog::new(watchdog_config, watchdog_io); // Get state receiver for monitoring state changes let state_rx = watchdog.state_rx(); // Spawn thread to handle state events thread::spawn(move || { for event in state_rx { match event { StateEvent::Ok => println!("Watchdog OK"), StateEvent::Fault(kind) => println!("Fault: {:?}", kind), } } }); // Run watchdog in separate thread (blocking) thread::spawn(move || { watchdog.run().unwrap(); }); // Check current state anytime // let current_state: State = watchdog.state(); Ok(()) } ``` -------------------------------- ### Run Asynchronous Watchdog - Rust Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Sets up and runs an asynchronous watchdog compatible with async runtimes like Tokio or Embassy. It requires a custom async I/O implementation and supports async state event handling. ```rust use heartbeat_watchdog::{ io::WatchdogIoAsync, Range, WatchdogAsync, WatchdogConfig, }; use std::time::Duration; // Custom async I/O implementation struct MyAsyncIo { /* ... */ } impl WatchdogIoAsync for MyAsyncIo { async fn get(&self, expected: heartbeat_watchdog::Edge) -> heartbeat_watchdog::Result { // Poll for expected edge, return Timeout error if not found todo!() } async fn clear(&self) -> heartbeat_watchdog::Result<()> { // Clear any buffered data Ok(()) } } async fn run_async_watchdog() -> heartbeat_watchdog::Result<()> { let config = WatchdogConfig::new(Duration::from_millis(100)) .with_range(Range::Window(Duration::from_millis(10))); let io = MyAsyncIo { /* ... */ }; let watchdog = WatchdogAsync::new(config, io); // Get async state receiver (std feature) #[cfg(feature = "std")] let state_rx = watchdog.state_rx(); // Run watchdog (blocks until error) watchdog.run().await } ``` -------------------------------- ### Bare-Metal Async Watchdog with Embassy (Rust) Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Implements a custom GPIO watchdog I/O for STM32 microcontrollers using the Embassy framework for bare-metal, no_std environments. It requires the 'embassy' feature and specific configuration for GPIO pins and watchdog timeouts. ```rust #![no_std] #![no_main] use embassy_executor::Spawner; use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; use embassy_time::{Duration, Instant, Timer}; use heartbeat_watchdog::{ io::WatchdogIoAsync, Edge, EmbassyStateChannel, Error, Range, Result, StateEvent, WatchdogAsync, WatchdogConfig, }; use static_cell::StaticCell; // Custom GPIO watchdog I/O for STM32 struct GpioWatchIo { input: Input<'static>, timeout: Duration, } impl WatchdogIoAsync for GpioWatchIo { async fn get(&self, expected: Edge) -> Result { let now = Instant::now(); loop { if now.elapsed() > self.timeout { return Err(Error::Timeout); } let edge: Edge = bool::from(self.input.get_level()).into(); if edge == expected { return Ok(edge); } Timer::after(Duration::from_micros(100)).await; } } async fn clear(&self) -> Result<()> { Ok(()) } } #[embassy_executor::task] async fn run_watchdog(watchdog: WatchdogAsync) { watchdog.run().await.unwrap(); } static WATCHDOG_CHANNEL: StaticCell = StaticCell::new(); #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); let mut fault_led = Output::new(p.PB13, Level::High, Speed::Low); let w_input = Input::new(p.PB14, Pull::Down); let config = WatchdogConfig::new(Duration::from_millis(10).into()) .with_range(Range::Window(Duration::from_millis(1).into())) .with_warmup(Duration::from_secs(2).into()) .with_min_beats(200); let io = GpioWatchIo { input: w_input, timeout: config.io_timeout().try_into().unwrap(), }; let channel = WATCHDOG_CHANNEL.init(EmbassyStateChannel::new()); let mut watchdog = WatchdogAsync::new(config, io); watchdog.set_state_tx(channel.sender()); spawner.spawn(run_watchdog(watchdog)).unwrap(); loop { if let Ok(event) = channel.try_receive() { match event { StateEvent::Fault(kind) => fault_led.set_high(), StateEvent::Ok => fault_led.set_low(), } } Timer::after_millis(1).await; } } ``` -------------------------------- ### UDP Heartbeat and Watchdog Communication (Rust) Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Implements a UDP-based heartbeat client and watchdog I/O for inter-process or inter-machine monitoring. It requires the `heartbeat_watchdog` crate and standard Rust libraries for threading and time. The client sends heartbeats, and the watchdog monitors for these signals, reporting state changes. ```rust use heartbeat_watchdog::{ io::udp::{UdpHeart, UdpIo}, Heart, Range, StateEvent, Watchdog, WatchdogConfig, }; use rtsc::time::interval; use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // Create heartbeat client that sends to watchdog let heart = UdpHeart::create("127.0.0.1:9999")?; // Configure and create watchdog let watchdog_config = WatchdogConfig::new(Duration::from_millis(100)) .with_range(Range::Window(Duration::from_millis(10))); let watchdog_io = UdpIo::create("127.0.0.1:9999", watchdog_config.io_timeout())?; let watchdog = Watchdog::new(watchdog_config, watchdog_io); // Monitor state changes let state_rx = watchdog.state_rx(); thread::spawn(move || { for e in state_rx { println!("{:?}", e); } }); // Run watchdog thread::spawn(move || { watchdog.run().unwrap(); }); // Send heartbeats at regular intervals for _ in interval(Duration::from_millis(100)) { heart.beat()?; // Alternates between rising (+) and falling (.) edges } Ok(()) } ``` -------------------------------- ### Custom Synchronous and Asynchronous Heartbeat Client Traits (Rust) Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Provides implementations for custom synchronous (`Heart`) and asynchronous (`HeartAsync`) heartbeat client traits. These traits enable the creation of heartbeat clients using various communication transports like sockets, GPIO, or serial interfaces. The `beat` and `beat_async` methods are responsible for toggling the heartbeat state and sending the corresponding signal. ```rust use heartbeat_watchdog::{Heart, HeartAsync, Result}; use portable_atomic::{AtomicBool, Ordering}; struct MyHeart { next: AtomicBool, // Your transport (socket, GPIO, serial, etc.) } impl Heart for MyHeart { fn beat(&self) -> Result<()> { // Toggle and send edge let is_rising = self.next.fetch_xor(true, Ordering::Relaxed); // Send '+' for rising, '.' for falling let edge_byte = if is_rising { b'+' } else { b'.' }; // Your send implementation here Ok(()) } } impl HeartAsync for MyHeart { async fn beat_async(&self) -> Result<()> { // Async version of beat() let is_rising = self.next.fetch_xor(true, Ordering::Relaxed); // Async send implementation Ok(()) } } ``` -------------------------------- ### GPIO Heartbeat and Watchdog Communication (Rust) Source: https://context7.com/roboplc/heartbeat-watchdog/llms.txt Implements a GPIO-based heartbeat client and watchdog for embedded systems. This requires the `gpio` feature of the `heartbeat_watchdog` crate. The code configures specific GPIO pins for sending heartbeats and monitoring them, with configurable polling intervals. ```rust use heartbeat_watchdog::{ io::gpio::{Gpio, GpioConfig, GpioHeart}, Heart, Range, StateEvent, Watchdog, WatchdogConfig, }; use rtsc::time::interval; use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // Create GPIO heartbeat client (output pin) let heart = GpioHeart::create("/dev/gpiochip0", 17)?; // Configure watchdog let watchdog_config = WatchdogConfig::new(Duration::from_millis(100)) .with_range(Range::Window(Duration::from_millis(10))); // Create GPIO watchdog I/O (input pin with 2ms polling interval) let gpio_config = GpioConfig::new("/dev/gpiochip0", 27, Duration::from_millis(2)); let watchdog_io = Gpio::create(&gpio_config, watchdog_config.io_timeout())?; let watchdog = Watchdog::new(watchdog_config, watchdog_io); // Monitor state changes let state_rx = watchdog.state_rx(); thread::spawn(move || { for e in state_rx { println!("{:?}", e); } }); // Run watchdog thread::spawn(move || { watchdog.run().unwrap(); }); // Send GPIO heartbeats for _ in interval(Duration::from_millis(100)) { heart.beat()?; } Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.