Restructure printer code

This commit is contained in:
Joscha 2024-03-08 11:50:25 +01:00
parent dc6265f837
commit ce2f986983
5 changed files with 149 additions and 96 deletions

View file

@ -1,7 +0,0 @@
pub enum Command {
Stop,
Test,
Rip,
Text(String),
ChatMessage { username: String, content: String },
}

View file

@ -0,0 +1,104 @@
use tokio::sync::mpsc;
use crate::printer::Printer;
pub enum Command {
Stop,
Rip,
Test,
Text(String),
ChatMessage { username: String, content: String },
}
pub struct Drawer {
rx: mpsc::Receiver<Command>,
printer: Printer,
}
impl Drawer {
pub fn new(rx: mpsc::Receiver<Command>, printer: Printer) -> Self {
Self { rx, printer }
}
pub fn run(&mut self) -> anyhow::Result<()> {
while let Some(command) = self.rx.blocking_recv() {
if matches!(command, Command::Stop) {
break;
};
self.on_command(command)?;
}
Ok(())
}
fn on_command(&mut self, command: Command) -> anyhow::Result<()> {
match command {
Command::Stop => {} // Already handled one level above
Command::Rip => self.printer.rip()?,
Command::Test => todo!(),
Command::Text(_) => todo!(),
Command::ChatMessage { username, content } => todo!(),
}
Ok(())
}
// fn on_test(&mut self) -> anyhow::Result<()> {
// self.printer.init()?;
// let x = 48; // bytes
// let y = 48; // dots
// let m = 0;
// let x_l = x as u8;
// let x_h = (x >> 8) as u8;
// let y_l = y as u8;
// let y_h = (y >> 8) as u8;
// let mut command = vec![0x1D, b'v', b'0', m, x_l, x_h, y_l, y_h];
// for _y in 0..y {
// for _x in 0..x {
// // command.push((x + y) as u8);
// command.push(0b0000_0011);
// }
// }
// self.printer.custom(&command)?;
// self.printer.print()?;
// Ok(())
// }
// fn on_rip(&mut self) -> anyhow::Result<()> {
// self.printer.init()?.feeds(6)?.print()?;
// Ok(())
// }
// fn on_text(&mut self, text: String) -> anyhow::Result<()> {
// let text = util::sanitize(&text);
// self.printer.init()?.write(&text)?.print()?;
// Ok(())
// }
// fn on_chat_message(&mut self, username: String, content: String) -> anyhow::Result<()> {
// let username = util::sanitize(&username);
// let content = util::sanitize(&content);
// let username = username
// .chars()
// .map(|c| if c.is_ascii_whitespace() { '_' } else { c })
// .take(16)
// .collect::<String>();
// let content = content.chars().take(300).collect::<String>();
// self.printer
// .init()?
// .reverse(true)?
// .write(&username)?
// .reverse(false)?
// .write(" ")?
// .writeln(&content)?
// .print()?;
// Ok(())
// }
}

View file

@ -1,4 +1,4 @@
mod command;
mod drawer;
mod printer;
mod server;
mod util;
@ -6,26 +6,39 @@ mod util;
use std::path::PathBuf;
use clap::Parser;
use drawer::Drawer;
use printer::Printer;
use tokio::{runtime::Runtime, sync::mpsc};
#[derive(Parser)]
struct Args {
path: PathBuf,
/// Address the web server will listen at.
addr: String,
/// Path to the printer's USB device file.
///
/// Usually, this is located at `/dev/usb/lp0` or a similar location.
#[arg(long, short)]
printer: Option<PathBuf>,
/// Export an image of whatever is printed here.
#[arg(long, short)]
export: Option<PathBuf>,
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
let (tx, rx) = mpsc::channel(3);
let mut printer = Printer::new(rx, &args.path)?;
let printer = Printer::new(args.printer, args.export)?;
let mut drawer = Drawer::new(rx, printer);
let runtime = Runtime::new()?;
runtime.spawn(server::run(tx, args.addr));
println!("Running");
printer.run()?;
drawer.run()?;
Ok(())
}

View file

@ -1,103 +1,46 @@
use std::path::Path;
use std::path::{Path, PathBuf};
use escpos::{
driver::FileDriver,
printer::Printer as EPrinter,
utils::{PageCode, Protocol},
};
use tokio::sync::mpsc;
use crate::{command::Command, util};
pub struct Printer {
rx: mpsc::Receiver<Command>,
printer: EPrinter<FileDriver>,
printer: Option<EPrinter<FileDriver>>,
export_path: Option<PathBuf>,
}
impl Printer {
pub fn new(rx: mpsc::Receiver<Command>, path: &Path) -> anyhow::Result<Self> {
let driver = FileDriver::open(path)?;
/// Experimentation has determined that the printer uses PC437 and the page
/// code can't be changed.
///
/// https://en.wikipedia.org/wiki/Code_page_437
/// https://www.epson-biz.com/modules/ref_charcode_en/index.php?content_id=10
const PAGE_CODE: PageCode = PageCode::PC437;
// Experimentation has determined that the printer uses PC437 and the
// page code can't be changed.
// https://en.wikipedia.org/wiki/Code_page_437
// https://www.epson-biz.com/modules/ref_charcode_en/index.php?content_id=10
let printer = EPrinter::new(driver, Protocol::default(), Some(PageCode::PC437));
pub fn new(
printer_path: Option<PathBuf>,
export_path: Option<PathBuf>,
) -> anyhow::Result<Self> {
let printer = if let Some(path) = printer_path {
let driver = FileDriver::open(&path)?;
let printer = EPrinter::new(driver, Protocol::default(), Some(Self::PAGE_CODE));
Some(printer)
} else {
None
};
Ok(Self { rx, printer })
Ok(Self {
printer,
export_path,
})
}
pub fn run(&mut self) -> anyhow::Result<()> {
while let Some(command) = self.rx.blocking_recv() {
match command {
Command::Stop => break,
Command::Test => self.on_test()?,
Command::Rip => self.on_rip()?,
Command::Text(text) => self.on_text(text)?,
Command::ChatMessage { username, content } => {
self.on_chat_message(username, content)?
}
}
pub fn rip(&mut self) -> anyhow::Result<()> {
if let Some(printer) = &mut self.printer {
printer.init()?.feeds(4)?.print()?;
}
Ok(())
}
fn on_test(&mut self) -> anyhow::Result<()> {
self.printer.init()?;
let x = 48; // bytes
let y = 48; // dots
let m = 0;
let x_l = x as u8;
let x_h = (x >> 8) as u8;
let y_l = y as u8;
let y_h = (y >> 8) as u8;
let mut command = vec![0x1D, b'v', b'0', m, x_l, x_h, y_l, y_h];
for _y in 0..y {
for _x in 0..x {
// command.push((x + y) as u8);
command.push(0b0000_0011);
}
}
self.printer.custom(&command)?;
self.printer.print()?;
Ok(())
}
fn on_rip(&mut self) -> anyhow::Result<()> {
self.printer.init()?.feeds(6)?.print()?;
Ok(())
}
fn on_text(&mut self, text: String) -> anyhow::Result<()> {
let text = util::sanitize(&text);
self.printer.init()?.write(&text)?.print()?;
Ok(())
}
fn on_chat_message(&mut self, username: String, content: String) -> anyhow::Result<()> {
let username = util::sanitize(&username);
let content = util::sanitize(&content);
let username = username
.chars()
.map(|c| if c.is_ascii_whitespace() { '_' } else { c })
.take(16)
.collect::<String>();
let content = content.chars().take(300).collect::<String>();
self.printer
.init()?
.reverse(true)?
.write(&username)?
.reverse(false)?
.write(" ")?
.writeln(&content)?
.print()?;
Ok(())
}

View file

@ -2,7 +2,7 @@ use axum::{extract::State, routing::post, Form, Router};
use serde::Deserialize;
use tokio::{net::TcpListener, sync::mpsc};
use crate::command::Command;
use crate::drawer::Command;
#[derive(Clone)]
struct Server {