1use std::io::{self, Write};
2use std::time::Duration;
3
4use catprinter::ble::{connect, scan};
5
6#[tokio::main]
11async fn main() -> Result<(), Box<dyn std::error::Error>> {
12 println!("Scanning for CatPrinter-compatible BLE devices for 3 seconds...");
13 let devices = scan(Duration::from_secs(3)).await?;
14 if devices.is_empty() {
15 println!(
16 "No devices found. Make sure your Bluetooth adapter is up and the printer is powered on and advertising."
17 );
18 return Ok(());
19 }
20
21 println!("Found devices:");
22 for (i, d) in devices.iter().enumerate() {
23 println!(" {}) id={} name={:?}", i + 1, d.id, d.name);
24 }
25
26 let mut input = String::new();
28 loop {
29 print!("Select device number to connect to (1-{}): ", devices.len());
30 io::stdout().flush()?;
31 input.clear();
32 io::stdin().read_line(&mut input)?;
33 if let Ok(n) = input.trim().parse::<usize>() {
34 if n >= 1 && n <= devices.len() {
35 let chosen = &devices[n - 1];
36 println!(
37 "Connecting to device id={} name={:?} ...",
38 chosen.id, chosen.name
39 );
40 match connect(&chosen.id, Duration::from_secs(10)).await {
41 Ok(printer) => {
42 println!("Connected successfully.");
43 run_interactive_session(printer).await?;
44 return Ok(());
45 }
46 Err(e) => {
47 eprintln!("Failed to connect: {}", e);
48 print!("Try another device? (y/N): ");
50 io::stdout().flush()?;
51 input.clear();
52 io::stdin().read_line(&mut input)?;
53 if input.trim().to_lowercase() != "y" {
54 return Ok(());
55 } else {
56 for (i, d) in devices.iter().enumerate() {
58 println!(" {}) id={} name={:?}", i + 1, d.id, d.name);
59 }
60 }
61 }
62 }
63 break;
64 }
65 }
66 println!("Invalid selection.");
67 }
68
69 Ok(())
70}
71
72async fn run_interactive_session(
75 printer: catprinter::ble::CatPrinterAsync,
76) -> Result<(), Box<dyn std::error::Error>> {
77 println!("Querying printer status...");
79 match printer.get_status(Duration::from_secs(10)).await {
80 Ok(s) => {
81 println!(
82 "Status -> battery: {:?}, temperature: {:?}, state: {:?}",
83 s.battery_percent, s.temperature, s.state
84 );
85 }
86 Err(e) => {
87 eprintln!("Failed to get status: {}", e);
88 }
89 }
90 let mut mode = String::new();
91 print!("Choose print mode: 1 for text, 2 for image: ");
93 io::stdout().flush()?;
94 io::stdin().read_line(&mut mode)?;
95
96 if mode.trim() == "1" {
97 let mut main = String::new();
99 let mut author = String::new();
100 print!("Enter the main text to print: ");
102 io::stdout().flush()?;
103 io::stdin().read_line(&mut main)?;
104 print!("Enter the author name: ");
105 io::stdout().flush()?;
106 io::stdin().read_line(&mut author)?;
107 let main = main.trim();
108 let author = author.trim();
109
110 if main.is_empty() {
111 println!("No text entered, aborting.");
112 return Ok(());
113 }
114
115 println!("Sending print job (text)...");
117 match printer.print_text(main, author).await {
118 Ok(()) => println!("Print job completed (printer reported AA/complete)."),
119 Err(e) => eprintln!("Print job failed: {}", e),
120 }
121 } else if mode.trim() == "2" {
122 let mut img_path = String::new();
123 print!("Enter the path to the image: ");
125 io::stdout().flush()?;
126 io::stdin().read_line(&mut img_path)?;
127 let img_path = img_path.trim();
128
129 if img_path.is_empty() {
130 println!("No image path entered, aborting.");
131 return Ok(());
132 }
133
134 let mut dithering_mode = String::new();
136 print!("Choose dithering mode: 1=Threshold, 2=Floyd-Steinberg, 3=Atkinson, 4=Halftone: ");
137 io::stdout().flush()?;
138 io::stdin().read_line(&mut dithering_mode)?;
139 let dithering = match dithering_mode.trim() {
140 "2" => catprinter::dithering::ImageDithering::FloydSteinberg,
141 "3" => catprinter::dithering::ImageDithering::Atkinson,
142 "4" => catprinter::dithering::ImageDithering::Halftone,
143 _ => catprinter::dithering::ImageDithering::Threshold,
144 };
145
146 println!("Sending print job (image)...");
148 match printer.print_image_from_path(img_path, dithering).await {
149 Ok(()) => println!("Print job completed (printer reported AA/complete)."),
150 Err(e) => eprintln!("Print job failed: {}", e),
151 }
152 } else {
153 println!("Invalid selection.");
154 }
155
156 Ok(())
157}