PrinterMonitor

Struct PrinterMonitor 

Source
pub struct PrinterMonitor { /* private fields */ }
Expand description

Printer monitoring and querying functionality

PrinterMonitor is cheaply cloneable (uses Arc internally) and can be shared across tasks without creating multiple backend connections.

Implementations§

Source§

impl PrinterMonitor

Source

pub async fn new() -> Result<Self>

Creates a new PrinterMonitor instance with the appropriate platform backend.

This function automatically selects and initializes the correct backend for the current platform (WMI for Windows, CUPS for Linux).

§Returns
  • Result<Self> - A new PrinterMonitor instance or an error if initialization fails
§Errors
  • PrinterError::PlatformNotSupported - If the current platform is not supported
  • PrinterError::WmiError - If WMI initialization fails on Windows
  • PrinterError::CupsError - If CUPS initialization fails on Linux
§Example
use printer_event_handler::PrinterMonitor;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
}
Source

pub async fn list_printers(&self) -> Result<Vec<Printer>>

Retrieves a list of all printers available on the system.

This method queries the platform-specific printer service to get information about all installed and available printers.

§Returns
  • Result<Vec<Printer>> - A vector of all printers found on the system
§Errors
  • PrinterError::WmiError - If the WMI query fails on Windows
  • PrinterError::CupsError - If the CUPS query fails on Linux
  • PrinterError::IoError - If there are system I/O issues
§Example
use printer_event_handler::PrinterMonitor;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let printers = monitor.list_printers().await.unwrap();
     
    for printer in printers {
        println!("{}: {}", printer.name(), printer.status_description());
    }
}
Source

pub async fn find_printer(&self, name: &str) -> Result<Option<Printer>>

Searches for a specific printer by name using case-insensitive matching.

This method searches through all available printers to find one with a name that matches the provided string (case-insensitive).

§Arguments
  • name - The name of the printer to search for
§Returns
  • Result<Option<Printer>> - The found printer or None if not found
§Errors
  • PrinterError::WmiError - If the WMI query fails on Windows
  • PrinterError::CupsError - If the CUPS query fails on Linux
  • PrinterError::IoError - If there are system I/O issues
§Example
use printer_event_handler::PrinterMonitor;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
     
    if let Some(printer) = monitor.find_printer("HP LaserJet").await.unwrap() {
        println!("Found printer: {}", printer.name());
    }
}
Source

pub async fn monitor_printer<F>( &self, printer_name: &str, interval_ms: u64, cancel_token: Option<CancellationToken>, callback: F, ) -> Result<()>
where F: FnMut(&Printer, Option<&Printer>) + Send,

Continuously monitors a specific printer for status changes.

This function runs indefinitely, polling the specified printer every interval_ms milliseconds and calling the provided callback function whenever the printer’s status changes. The callback receives both the current printer state and the previous state (if any).

§Arguments
  • printer_name - The name of the printer to monitor
  • interval_ms - Polling interval in milliseconds
  • callback - Function called when printer status changes, receives (current, previous)
§Returns
  • Result<()> - Never returns Ok normally (runs indefinitely), only Err on failure
§Errors
  • PrinterError::PrinterNotFound - If the specified printer is not found initially
  • PrinterError::WmiError - If WMI queries fail on Windows
  • PrinterError::CupsError - If CUPS queries fail on Linux
  • PrinterError::IoError - If there are system I/O issues
§Behavior
  • If the printer disappears during monitoring, the callback is called with a synthetic “unknown” status to indicate the printer is no longer available
  • The first check always triggers the callback to provide the initial status
  • Subsequent calls only trigger the callback if the status actually changes
§Example
use printer_event_handler::PrinterMonitor;
use tokio_util::sync::CancellationToken;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let cancel_token = CancellationToken::new();

    monitor.monitor_printer("HP LaserJet", 30000, Some(cancel_token.clone()), |current, previous| {
        if let Some(prev) = previous {
            if prev != current {
                println!("Status changed: {} -> {}",
                    prev.status_description(),
                    current.status_description());
            }
        } else {
            println!("Initial status: {}", current.status_description());
        }
    }).await.unwrap();
}
Source

pub async fn printer_summary(&self) -> Result<HashMap<String, PrinterSummary>>

Retrieves a comprehensive summary of all printers and their current states.

This method provides a convenient way to get an overview of all printers in a structured format, useful for status dashboards or reports.

§Returns
  • Result<HashMap<String, PrinterSummary>> - Map of printer names to their summaries
§Errors
  • PrinterError::WmiError - If the WMI query fails on Windows
  • PrinterError::CupsError - If the CUPS query fails on Linux
  • PrinterError::IoError - If there are system I/O issues
§Example
use printer_event_handler::PrinterMonitor;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let summary = monitor.printer_summary().await.unwrap();
     
    for (name, info) in summary {
        println!("{}: {} ({})", name, info.status,
            if info.has_error { "ERROR" } else { "OK" });
    }
}
Source

pub async fn monitor_printer_changes<F>( &self, printer_name: &str, interval_ms: u64, cancel_token: Option<CancellationToken>, callback: F, ) -> Result<()>
where F: FnMut(&PrinterChanges) + Send,

Monitors a printer with detailed property change detection.

This enhanced monitoring method provides detailed information about exactly which properties changed between checks, enabling fine-grained monitoring and alerting.

§Arguments
  • printer_name - The name of the printer to monitor
  • interval_ms - Polling interval in milliseconds
  • cancel_token - Optional cancellation token for graceful shutdown
  • callback - Function called when properties change, receives PrinterChanges
§Returns
  • Result<()> - Returns Ok when cancelled, or Err on failure
§Behavior
  • The callback is NOT called on the initial state capture
  • Only actual property changes trigger the callback
  • Changes are always non-empty when the callback is invoked
  • The initial state is captured silently for comparison with future states
  • Monitoring stops gracefully when the cancellation token is cancelled
§Example
use printer_event_handler::PrinterMonitor;
use tokio_util::sync::CancellationToken;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let cancel_token = CancellationToken::new();

    // Clone the token for the monitoring task
    let token_clone = cancel_token.clone();
    let handle = tokio::spawn(async move {
        monitor.monitor_printer_changes("HP LaserJet", 30000, Some(token_clone), |changes| {
            println!("Detected {} changes:", changes.change_count());
            for change in &changes.changes {
                println!("  - {}", change.description());
            }
        }).await
    });

    // Later: cancel monitoring
    cancel_token.cancel();
    handle.await.unwrap().unwrap();
}
Source

pub async fn monitor_property<F>( &self, printer_name: &str, property: MonitorableProperty, interval_ms: u64, cancel_token: Option<CancellationToken>, callback: F, ) -> Result<()>
where F: FnMut(&PropertyChange) + Send,

Monitors a specific property of a printer for changes.

This method allows monitoring just a single property, useful for alerting on specific conditions like offline status or error state changes.

§Arguments
  • printer_name - The name of the printer to monitor
  • property - The specific property to watch using MonitorableProperty enum
  • interval_ms - Polling interval in milliseconds
  • cancel_token - Optional cancellation token for graceful shutdown
  • callback - Function called when the property changes
§Example
use printer_event_handler::{PrinterMonitor, MonitorableProperty};
use tokio_util::sync::CancellationToken;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let cancel_token = CancellationToken::new();

    monitor.monitor_property(
        "HP LaserJet",
        MonitorableProperty::IsOffline,
        60000,
        Some(cancel_token.clone()),
        |change| {
            println!("Offline status changed: {}", change.description());
        }
    ).await.unwrap();
}
Source

pub async fn monitor_multiple_printers<F>( &self, printer_names: Vec<String>, interval_ms: u64, cancel_token: Option<CancellationToken>, callback: F, ) -> Result<()>
where F: Fn(&PrinterChanges) + Send + Sync + 'static,

Monitors multiple printers concurrently and reports changes for any of them.

This method allows monitoring several printers simultaneously, with a single callback that receives changes from any of the monitored printers.

§Arguments
  • printer_names - List of printer names to monitor
  • interval_ms - Polling interval in milliseconds
  • cancel_token - Optional cancellation token for graceful shutdown
  • callback - Function called when any printer changes (NOT called on initial state)
§Returns
  • Result<()> - Returns Ok when cancelled or all tasks complete, or Err on failure
§Behavior
  • The callback is NOT called on the initial state capture for each printer
  • Only actual property changes trigger the callback
  • Each printer is monitored in a separate task for true concurrent monitoring
  • Callbacks are called outside of internal locks to prevent contention with slow callbacks
  • The monitor is cloned (cheaply via Arc) for each task, sharing the same backend connection
  • Monitoring stops gracefully when the cancellation token is cancelled
§Example
use printer_event_handler::PrinterMonitor;
use tokio_util::sync::CancellationToken;

#[tokio::main]
async fn main() {
    let monitor = PrinterMonitor::new().await.unwrap();
    let printers = vec!["HP LaserJet".to_string(), "Canon Printer".to_string()];
    let cancel_token = CancellationToken::new();

    let token_clone = cancel_token.clone();
    let handle = tokio::spawn(async move {
        monitor.monitor_multiple_printers(printers, 30000, Some(token_clone), |changes| {
            println!("Printer '{}' changed: {}", changes.printer_name, changes.summary());
        }).await
    });

    // Later: cancel monitoring
    cancel_token.cancel();
    handle.await.unwrap().unwrap();
}

Trait Implementations§

Source§

impl Clone for PrinterMonitor

Source§

fn clone(&self) -> PrinterMonitor

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.