mirror of
https://github.com/jhbruhn/catprint-rs.git
synced 2025-03-14 18:35:49 +00:00
Merge fba7b6fc3e
into a771416288
This commit is contained in:
commit
71b5089739
6 changed files with 1320 additions and 487 deletions
1696
Cargo.lock
generated
1696
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -6,11 +6,11 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
btleplug = "0.8"
|
btleplug = "0.11"
|
||||||
uuid = "0.8"
|
uuid = "1.10"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = {version = "1.10", features = ["rt", "macros", "rt-multi-thread"] }
|
tokio = {version = "1.10", features = ["rt", "macros", "rt-multi-thread"] }
|
||||||
crc = { git = "https://github.com/mrhooray/crc-rs.git" }
|
crc = { git = "https://github.com/mrhooray/crc-rs.git" }
|
||||||
dither = "=1.3.7" # last version without nightly requirement
|
dither = "=1.3.7" # last version without nightly requirement
|
||||||
image = "0.23"
|
image = "0.25"
|
||||||
clap = "3.0.0-beta.4"
|
clap = { version = "4.5", features = ["derive"] }
|
|
@ -2,20 +2,19 @@ use btleplug::platform::Manager;
|
||||||
use catprint::*;
|
use catprint::*;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use clap::{crate_authors, crate_version, AppSettings, ArgEnum, Clap};
|
use clap::{Parser, ValueEnum};
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(version = crate_version!(), author = crate_authors!())]
|
#[command(author, version, about, long_about = None)]
|
||||||
#[clap(setting = AppSettings::ColoredHelp)]
|
|
||||||
struct Opts {
|
struct Opts {
|
||||||
/// Set the device name of your printer.
|
/// Set the device name of your printer.
|
||||||
#[clap(short, long, default_value = "GB02")]
|
#[arg(short, long, default_value = "GB02")]
|
||||||
device_name: String,
|
device_name: String,
|
||||||
#[clap(subcommand)]
|
#[command(subcommand)]
|
||||||
subcmd: SubCommand,
|
subcmd: SubCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Parser, Debug)]
|
||||||
enum SubCommand {
|
enum SubCommand {
|
||||||
/// Move the paper without printing
|
/// Move the paper without printing
|
||||||
Feed(Feed),
|
Feed(Feed),
|
||||||
|
@ -24,7 +23,7 @@ enum SubCommand {
|
||||||
Print(Print),
|
Print(Print),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Parser, Debug)]
|
||||||
struct Feed {
|
struct Feed {
|
||||||
/// Print debug info
|
/// Print debug info
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
|
@ -33,13 +32,13 @@ struct Feed {
|
||||||
length: u8,
|
length: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Parser, Debug)]
|
||||||
struct Print {
|
struct Print {
|
||||||
/// The path to the image you want to print out
|
/// The path to the image you want to print out
|
||||||
input_image: String,
|
input_image: String,
|
||||||
|
|
||||||
/// The ditherer supposed to be used. none is good for text and vector graphics
|
/// 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,
|
ditherer: Ditherers,
|
||||||
|
|
||||||
/// Rotate picture by 90 degrees
|
/// Rotate picture by 90 degrees
|
||||||
|
@ -51,7 +50,7 @@ struct Print {
|
||||||
no_compress: bool,
|
no_compress: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ArgEnum)]
|
#[derive(ValueEnum, Debug, Clone)]
|
||||||
enum Ditherers {
|
enum Ditherers {
|
||||||
None,
|
None,
|
||||||
KMean,
|
KMean,
|
||||||
|
|
|
@ -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 btleplug::platform::Manager;
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::time;
|
use tokio::time;
|
||||||
|
@ -12,7 +11,8 @@ const TX_CHARACTERISTIC_UUID: Uuid = Uuid::from_u128(0x0000ae01_0000_1000_8000_0
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
peripheral: btleplug::platform::Peripheral,
|
peripheral: btleplug::platform::Peripheral,
|
||||||
supports_compression: bool,
|
supports_compression: bool,
|
||||||
tx_buffer: VecDeque<u8>,
|
tx_buffer: Vec<u8>,
|
||||||
|
tx_characteristic: btleplug::api::Characteristic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
|
@ -26,7 +26,7 @@ impl Device {
|
||||||
for adapter in adapter_list.iter() {
|
for adapter in adapter_list.iter() {
|
||||||
println!("Starting scan...");
|
println!("Starting scan...");
|
||||||
adapter
|
adapter
|
||||||
.start_scan()
|
.start_scan(ScanFilter::default())
|
||||||
.await
|
.await
|
||||||
.expect("Can't scan BLE adapter for connected devices...");
|
.expect("Can't scan BLE adapter for connected devices...");
|
||||||
time::sleep(Duration::from_secs(2)).await;
|
time::sleep(Duration::from_secs(2)).await;
|
||||||
|
@ -41,17 +41,27 @@ impl Device {
|
||||||
if !peripheral.is_connected().await? {
|
if !peripheral.is_connected().await? {
|
||||||
peripheral.connect().await?;
|
peripheral.connect().await?;
|
||||||
}
|
}
|
||||||
let _ = peripheral.discover_characteristics().await?;
|
|
||||||
|
|
||||||
let supports_compression = match name {
|
println!("Connected to {}", name);
|
||||||
"MX10" => false,
|
println!("Discovering services...");
|
||||||
_ => true,
|
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 {
|
device_result = Ok(Device {
|
||||||
peripheral,
|
peripheral,
|
||||||
tx_buffer: VecDeque::new(),
|
tx_buffer: Vec::new(),
|
||||||
supports_compression,
|
supports_compression,
|
||||||
|
tx_characteristic: tx_characteristic.clone(),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +70,7 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Scan complete");
|
||||||
device_result
|
device_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,46 +85,25 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn flush(&mut self) -> Result<(), Box<dyn Error>> {
|
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 write_type = if chunks.len() > 1 {
|
||||||
let mut buf = Vec::with_capacity(MTU_SIZE);
|
WriteType::WithoutResponse
|
||||||
for _ in 0..MTU_SIZE {
|
} else {
|
||||||
if let Some(byte) = self.tx_buffer.pop_front() {
|
WriteType::WithResponse
|
||||||
buf.push(byte);
|
};
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this could be nicer i guess
|
for chunk in chunks {
|
||||||
}
|
self.peripheral
|
||||||
|
.write(&self.tx_characteristic, chunk, write_type)
|
||||||
self.tx(&buf).await?;
|
.await
|
||||||
|
.unwrap();
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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) {
|
pub async fn destroy(self) {
|
||||||
self.peripheral.disconnect().await.unwrap();
|
self.peripheral.disconnect().await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl Image {
|
||||||
let pixel = self.image.get((x, y)).unwrap();
|
let pixel = self.image.get((x, y)).unwrap();
|
||||||
let val = if pixel > &self.mean { 0 } else { 1 };
|
let val = if pixel > &self.mean { 0 } else { 1 };
|
||||||
if val == last_val {
|
if val == last_val {
|
||||||
counter = counter + 1
|
counter += 1
|
||||||
} else if counter > 0 {
|
} else if counter > 0 {
|
||||||
compressed.extend(rle_bytes(last_val, counter));
|
compressed.extend(rle_bytes(last_val, counter));
|
||||||
counter = 1;
|
counter = 1;
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl Command {
|
||||||
DeviceId(_) => 0xBB,
|
DeviceId(_) => 0xBB,
|
||||||
SetSpeed(_) => 0xBD,
|
SetSpeed(_) => 0xBD,
|
||||||
SetDrawingMode(_) => 0xBE,
|
SetDrawingMode(_) => 0xBE,
|
||||||
Print(true, _, _) => 0xBf, // compressed
|
Print(true, _, _) => 0xBF, // compressed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl Command {
|
||||||
|
|
||||||
let mut crc = CCITT.digest();
|
let mut crc = CCITT.digest();
|
||||||
crc.update(&payload);
|
crc.update(&payload);
|
||||||
let crc = crc.finalize() as u8;
|
let crc = crc.finalize();
|
||||||
|
|
||||||
let payload_len = payload.len();
|
let payload_len = payload.len();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue