use cpdb_rs::CpdbClient;
use cpdb_rs::events::DiscoveryEvent;
use futures_util::StreamExt;
#[tokio::main]
async fn main() -> cpdb_rs::Result<()> {
let client = CpdbClient::new().await?;
println!("Connected to {} backend(s).\n", client.backend_count());
let printers = client.get_all_printers().await?;
println!("=== All Printers ({} found) ===", printers.len());
for p in &printers {
println!(
" {} [{}] - {} (state={}, accepting={})",
p.name, p.id, p.make_model, p.state, p.accepting_jobs
);
}
match client.get_default_printer("CUPS").await {
Ok(default) => {
let display = if default.is_empty() || default == "[Invalid UTF-8]" || default == "NA" {
"Not Set"
} else {
&default
};
println!("\nDefault CUPS printer: {display}");
}
Err(_) => println!("\nDefault CUPS printer: Not Set"),
}
if let Some(p) = printers.iter().find(|p| p.is_ready()) {
println!("\n=== Details for '{}' ===", p.name);
match client.get_printer_details(&p.id, &p.backend).await {
Ok((options, media)) => {
println!(
"Option Groups ({} total): {:?}",
options.groups().len(),
options.groups()
);
println!("Options ({} total):", options.len());
for opt in options.iter().take(8) {
println!(
" {}: default='{}', choices=[{}]",
opt.name,
opt.default_value,
opt.supported_values.join(", ")
);
}
println!("Media ({} total):", media.len());
for m in media.iter().take(5) {
println!(
" {}: {}×{} mm, {} margin(s)",
m.name,
m.width as f64 / 100.0,
m.length as f64 / 100.0,
m.margins.len()
);
}
}
Err(e) => eprintln!(" Failed to get details: {e}"),
}
} else {
println!("\nNo ready printers to query details for.");
}
println!("\n=== Listening for live discovery events ===");
println!(
"(Try: sudo lpadmin -p TestPrinter -E -v ipp://localhost/printers/test -m everywhere)"
);
println!("(Press Ctrl+C to stop)\n");
let keep_alive_client = client.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(15));
loop {
interval.tick().await;
keep_alive_client.keep_alive_all().await;
}
});
let mut stream = client.discovery_stream().await?;
while let Some(event) = stream.next().await {
match &event {
DiscoveryEvent::PrinterAdded(snap) => {
println!(
"+ ADDED: {} [{}] backend={}",
snap.name, snap.id, snap.backend
);
}
DiscoveryEvent::PrinterRemoved { id, backend } => {
println!("- REMOVED: id={id}, backend={backend}");
}
DiscoveryEvent::PrinterStateChanged { id, state, .. } => {
println!("~ STATE: id={id}, state={state}");
match state {
cpdb_rs::types::PrinterState::Stopped => {
println!(" -> Status: Printer is stopped.");
}
cpdb_rs::types::PrinterState::Idle => {
println!(" -> Status: Printer is idle and ready.");
}
cpdb_rs::types::PrinterState::Processing => {
println!(" -> Status: Printer is processing a job.");
}
cpdb_rs::types::PrinterState::Unknown(raw) => {
println!(" -> Status: Printer is in an unknown state: {raw}");
}
}
}
_ => {}
}
}
Ok(())
}