This commit is contained in:
Kezi 2024-08-21 09:31:43 +02:00 committed by GitHub
commit 71b5089739
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1320 additions and 487 deletions

1696
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,11 +6,11 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
btleplug = "0.8"
uuid = "0.8"
btleplug = "0.11"
uuid = "1.10"
futures = "0.3"
tokio = {version = "1.10", features = ["rt", "macros", "rt-multi-thread"] }
crc = { git = "https://github.com/mrhooray/crc-rs.git" }
dither = "=1.3.7" # last version without nightly requirement
image = "0.23"
clap = "3.0.0-beta.4"
image = "0.25"
clap = { version = "4.5", features = ["derive"] }

View file

@ -2,20 +2,19 @@ use btleplug::platform::Manager;
use catprint::*;
use std::error::Error;
use clap::{crate_authors, crate_version, AppSettings, ArgEnum, Clap};
use clap::{Parser, ValueEnum};
#[derive(Clap)]
#[clap(version = crate_version!(), author = crate_authors!())]
#[clap(setting = AppSettings::ColoredHelp)]
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Opts {
/// Set the device name of your printer.
#[clap(short, long, default_value = "GB02")]
#[arg(short, long, default_value = "GB02")]
device_name: String,
#[clap(subcommand)]
#[command(subcommand)]
subcmd: SubCommand,
}
#[derive(Clap)]
#[derive(Parser, Debug)]
enum SubCommand {
/// Move the paper without printing
Feed(Feed),
@ -24,7 +23,7 @@ enum SubCommand {
Print(Print),
}
#[derive(Clap)]
#[derive(Parser, Debug)]
struct Feed {
/// Print debug info
#[clap(short, long)]
@ -33,13 +32,13 @@ struct Feed {
length: u8,
}
#[derive(Clap)]
#[derive(Parser, Debug)]
struct Print {
/// The path to the image you want to print out
input_image: String,
/// The ditherer supposed to be used. none is good for text and vector graphics
#[clap(arg_enum, short, long, default_value = "k-mean")]
#[clap(value_enum, short, long, default_value = "k-mean")]
ditherer: Ditherers,
/// Rotate picture by 90 degrees
@ -51,7 +50,7 @@ struct Print {
no_compress: bool,
}
#[derive(ArgEnum)]
#[derive(ValueEnum, Debug, Clone)]
enum Ditherers {
None,
KMean,

View file

@ -1,6 +1,5 @@
use btleplug::api::{Central, Manager as _, Peripheral};
use btleplug::api::{Central, Manager as _, Peripheral, ScanFilter, WriteType};
use btleplug::platform::Manager;
use std::collections::VecDeque;
use std::error::Error;
use std::time::Duration;
use tokio::time;
@ -12,7 +11,8 @@ const TX_CHARACTERISTIC_UUID: Uuid = Uuid::from_u128(0x0000ae01_0000_1000_8000_0
pub struct Device {
peripheral: btleplug::platform::Peripheral,
supports_compression: bool,
tx_buffer: VecDeque<u8>,
tx_buffer: Vec<u8>,
tx_characteristic: btleplug::api::Characteristic,
}
impl Device {
@ -26,7 +26,7 @@ impl Device {
for adapter in adapter_list.iter() {
println!("Starting scan...");
adapter
.start_scan()
.start_scan(ScanFilter::default())
.await
.expect("Can't scan BLE adapter for connected devices...");
time::sleep(Duration::from_secs(2)).await;
@ -41,17 +41,27 @@ impl Device {
if !peripheral.is_connected().await? {
peripheral.connect().await?;
}
let _ = peripheral.discover_characteristics().await?;
let supports_compression = match name {
"MX10" => false,
_ => true,
};
println!("Connected to {}", name);
println!("Discovering services...");
peripheral.discover_services().await?;
let supports_compression = name != "MX10";
let characteristics = peripheral.characteristics();
println!("Found {} characteristics", characteristics.len());
let tx_characteristic = characteristics
.iter()
.find(|c| c.uuid == TX_CHARACTERISTIC_UUID)
.expect("Could not find TX characteristic");
device_result = Ok(Device {
peripheral,
tx_buffer: VecDeque::new(),
tx_buffer: Vec::new(),
supports_compression,
tx_characteristic: tx_characteristic.clone(),
});
break;
}
@ -60,6 +70,7 @@ impl Device {
}
}
println!("Scan complete");
device_result
}
@ -74,46 +85,25 @@ impl Device {
}
pub async fn flush(&mut self) -> Result<(), Box<dyn Error>> {
const MTU_SIZE: usize = 20;
let chunks = self.tx_buffer.chunks(20);
while !self.tx_buffer.is_empty() {
let mut buf = Vec::with_capacity(MTU_SIZE);
for _ in 0..MTU_SIZE {
if let Some(byte) = self.tx_buffer.pop_front() {
buf.push(byte);
} else {
break;
}
let write_type = if chunks.len() > 1 {
WriteType::WithoutResponse
} else {
WriteType::WithResponse
};
// this could be nicer i guess
}
self.tx(&buf).await?;
for chunk in chunks {
self.peripheral
.write(&self.tx_characteristic, chunk, write_type)
.await
.unwrap();
std::thread::sleep(std::time::Duration::from_millis(10));
}
Ok(())
}
async fn tx(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>> {
let characteristics = self.peripheral.characteristics();
let tx_characteristic = characteristics
.iter()
.filter(|c| c.uuid == TX_CHARACTERISTIC_UUID)
.next()
.unwrap();
self.peripheral
.write(
&tx_characteristic,
data,
btleplug::api::WriteType::WithoutResponse,
)
.await?;
Ok(())
}
pub async fn destroy(self) {
self.peripheral.disconnect().await.unwrap();
}

View file

@ -93,7 +93,7 @@ impl Image {
let pixel = self.image.get((x, y)).unwrap();
let val = if pixel > &self.mean { 0 } else { 1 };
if val == last_val {
counter = counter + 1
counter += 1
} else if counter > 0 {
compressed.extend(rle_bytes(last_val, counter));
counter = 1;

View file

@ -72,7 +72,7 @@ impl Command {
DeviceId(_) => 0xBB,
SetSpeed(_) => 0xBD,
SetDrawingMode(_) => 0xBE,
Print(true, _, _) => 0xBf, // compressed
Print(true, _, _) => 0xBF, // compressed
}
}
@ -107,7 +107,7 @@ impl Command {
let mut crc = CCITT.digest();
crc.update(&payload);
let crc = crc.finalize() as u8;
let crc = crc.finalize();
let payload_len = payload.len();