Giter Site home page Giter Site logo

rust-ptouch's People

Contributors

aschmitz avatar baudetromain avatar dependabot[bot] avatar ryankurte avatar tcbennun avatar vivienm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rust-ptouch's Issues

Improve QR code character input function

Thank you for sharing such a useful tool!
I'm looking forward to Bluetooth support, but there is one more feature I would like.
Please add the function to write line breaks, catalog format, or both in QR codes.

It would be nice to be able to insert newline characters in the CODE string, or read an external template file for this requirement.

catalog formats knowlage
https://github.com/zxing/zxing/wiki/Barcode-Contents

external template file example
https://github.com/leplusorg/docker-qrcode

best regards.

Support overscan

It appears the tape margins are purely a software concept, and they're super conservative. It would be neat to support software overscan so (if you're feeling dangerous) you can write to more of the tape area.

Cannot get status of PTouch e550w

Hello,
First of all, thank you for this repository. I've been struggling with a few different library to make some Brother printers to print properly, and this one worked quite well.

However, I got stuck for quite some time before I finally managed to print something, and that's why I'm opening an issue here.
It may be a bug, or it may be that the printer I used is broken/misconfigured. I don't really know.
I'm gonna describe my toolchain and the problem I got, and I'm also gonna explain the workaround I made to finally be able to print, in case some people get the same bug than me.

TL;DR

I have a brother pt-e550w printer, and I'm trying to use this program to print things with it, but I get a timeout when the program tries to read the answer of a status request sent to the printer.

Since both the problem and the workaround are complex, this issue is very long. I'm sorry about that, but I guess it is better if I give all the details.

Toolchain used

I am working on windows, and I am using WSL2 for almost all my toolchains. I want to be able to plug my pt-e550w to my computer and print something. The command for that would be: cargo run -- --log-level debug --device pt-e550w print qr-text "hello" "hello friend".
However, WSL2 does not have natively access to the USB devices plugged to the computer. If I use the lsusb command while the printer is plugged in, I get the following result:

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Fortunately, there exist a piece of software to forward the USB traffic from windows to WSL over a local network interface (some kind of USB over IP). I found it here: https://devblogs.microsoft.com/commandline/connecting-usb-devices-to-wsl/
I installed the required tools, and listed the devices on windows with the usbipd wsl list command in a windows terminal. Here's the result:

> usbipd wsl list
BUSID  VID:PID    DEVICE                                                        STATE
2-3    04f9:2060  USB Printing Support                                          Not attached
2-4    1bcf:0005  USB Input Device                                              Not attached
2-8    13d3:56ba  Integrated Camera, Integrated IR Camera                       Not attached
2-9    06cb:00bd  Synaptics UWP WBDI                                            Not attached
2-10   8087:0aaa  Intel(R) Wireless Bluetooth(R)                                Not attached

Then, using the usbipd wsl attach --busid 2-3 command in the windows console, I can make the printer visible in wsl:

 > usbipd wsl attach --busid 2-3
usbipd: info: Using default distribution 'Ubuntu'.

Then, in wsl console:

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 04f9:2060 Brother Industries, Ltd PT-E550W
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Until then, everything's fine. I should be able to print now.

The bug

When trying the cargo run -- --log-level debug --device pt-e550w print qr-text "hello" "hello friend" command, I got this result:

$ cargo run -- --log-level debug --device pt-e550w print qr-text "hello" "hello friend"
warning: unused borrow that must be used
   --> src/commands.rs:138:9
    |
138 |         &buff[7..11].copy_from_slice(&raster_bytes);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the borrow produces a value
    |
    = note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
    |
138 |         let _ = &buff[7..11].copy_from_slice(&raster_bytes);
    |         +++++++

warning: `ptouch` (lib) generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 1.90s
     Running `target/debug/ptouch-util --log-level debug --device pt-e550w print qr-text hello 'hello friend'`
09:41:54 [DEBUG] (1) ptouch_util: Connecting to PTouch device: Options { device: PtE550W, index: 0, no_reset: false, usb_no_claim: false, usb_no_detach: false }
09:41:54 [DEBUG] (1) ptouch: Found matching devices: [(Bus 001 Device 003: ID 04f9:2060, DeviceDescriptor { bLength: 18, bDescriptorType: 1, bcdUSB: 272, bDeviceClass: 0, bDeviceSubClass: 0, bDeviceProtocol: 0, bMaxPacketSize: 64, idVendor: 1273, idProduct: 8288, bcdDevice: 256, iManufacturer: 1, iProduct: 2, iSerialNumber: 3, bNumConfigurations: 1 })]
09:41:54 [DEBUG] (1) ptouch: Error opening device
Error: Error connecting to PTouch: Usb(Access)

Looks like I need root privileges to access the USB device. Ok, let's adapt the command then: sudo target/debug/ptouch-util --log-level debug --device pt-e550w print qr-text "hello" "hello friend":

$ sudo target/debug/ptouch-util --log-level debug --device pt-e550w print qr-text "hello" "hello friend"
09:43:23 [DEBUG] (1) ptouch_util: Connecting to PTouch device: Options { device: PtE550W, index: 0, no_reset: false, usb_no_claim: false, usb_no_detach: false }
09:43:23 [DEBUG] (1) ptouch: Found matching devices: [(Bus 001 Device 003: ID 04f9:2060, DeviceDescriptor { bLength: 18, bDescriptorType: 1, bcdUSB: 272, bDeviceClass: 0, bDeviceSubClass: 0, bDeviceProtocol: 0, bMaxPacketSize: 64, idVendor: 1273, idProduct: 8288, bcdDevice: 256, iManufacturer: 1, iProduct: 2, iSerialNumber: 3, bNumConfigurations: 1 })]
09:43:23 [DEBUG] (1) ptouch: Checking for active kernel driver
09:43:23 [DEBUG] (1) ptouch: Kernel driver inactive
09:43:23 [DEBUG] (1) ptouch: Claiming interface
09:43:23 [DEBUG] (1) ptouch: WRITE: [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]
09:43:23 [DEBUG] (1) ptouch: WRITE: [1b, 40]
09:43:23 [DEBUG] (1) ptouch_util: Connected! fetching status...
09:43:23 [DEBUG] (1) ptouch: WRITE: [1b, 69, 53]
Error: Operation timeout

This is where the bug happens: the program found the printer, sent data to it, then sent a status request, but when trying to fetch the response, a timeout happened.
Going into the code, I found out the exact error happened in the status method of lib.rs, line 332:

pub fn status(&mut self) -> Result<Status, Error> {
    // Issue status request
    self.status_req()?;

    // Read status response
    let d = self.read(self.timeout)?;

    // Convert to status object
    let s = Status::from(d);

    debug!("Status: {:02x?}", s);

    Ok(s)
}

The status_req method just writes the status request hex code in the USB connection:

fn status_req(&mut self) -> Result<(), Error> {
    self.write(&[0x1b, 0x69, 0x53], self.timeout)
}

This method does not fail, but the call to self.read does. The read method tries to read as much bytes as the length of the buffer (32 bytes in our case), and if the number of read bytes is not 32, it returns Err(Error::Timeout).

fn read(&mut self, timeout: Duration) -> Result<[u8; 32], Error> {
    let mut buff = [0u8; 32];

    // Execute read
    let n = self.handle.read_bulk(self.stat_ep, &mut buff, timeout)?;

    if n != 32 {
        return Err(Error::Timeout)
    }

    // TODO: parse out status?

    Ok(buff)
}

That's exactly what is happening. Since the call to read is placed before a ? operator, the error will be propagated, and later the program will see the status fetching was unsuccessfull, and therefore stop itself.

Thoughts about this behaviour

I really don't know why isn't the printer responding via USB. I've checked the printer's documentation to see if there's any way to enable or disable the USB responses, but I didn't find anything. I haven't found any similar issue reported on the internet.

One of the possibility is that the USB over IP software to bind the USB ports to WSL doesn't allow read and write, but I've asked a friend who used it by the past and he said he hasn't been experiencing any issue with it.
With this in mind, I tried running a Ubuntu 22.04 virtual machine in VMware to run the program, since the USB mapping from windows to a virtual machine is reliable (at least I never had problems with it).
Sadly, the result was exactly the same.

At some point, I got the idea of running the program directly on windows instead of WSL. I installed all the rust toolchain on windows via rustup, and compiled and run the program again, with the same command: cargo run -- --log-level debug --device pt-e550w print qr-text "hello" "hello friend". I got another error this time:

> cargo run -- --log-level debug --device pt-e550w print qr-text "hello" "hello friend"
warning: unused borrow that must be used
   --> src\commands.rs:138:9
    |
138 |         &buff[7..11].copy_from_slice(&raster_bytes);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the borrow produces a value
    |
    = note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
    |
138 |         let _ = &buff[7..11].copy_from_slice(&raster_bytes);
    |         +++++++

warning: `ptouch` (lib) generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target\debug\ptouch-util.exe --log-level debug --device pt-e550w print qr-text hello "hello friend"`
12:03:21 [DEBUG] (1) ptouch_util: Connecting to PTouch device: Options { device: PtE550W, index: 0, no_reset: false, usb_no_claim: false, usb_no_detach: false }
12:03:21 [DEBUG] (1) ptouch: Found matching devices: [(Bus 002 Device 011: ID 04f9:2060, DeviceDescriptor { bLength: 18, bDescriptorType: 1, bcdUSB: 272, bDeviceClass: 0, bDeviceSubClass: 0, bDeviceProtocol: 0, bMaxPacketSize: 64, idVendor: 1273, idProduct: 8288, bcdDevice: 256, iManufacturer: 1, iProduct: 2, iSerialNumber: 3, bNumConfigurations: 1 })]
12:03:21 [DEBUG] (1) ptouch: Error opening device
Error: Error connecting to PTouch: Usb(NotSupported)

Running it in a console with admin privileges led to the same message.
After diving inside the code again, I found the origin of the error: the util.rs file, at line 128, tries to call the new function of the PTouch struct. The new function will call the call_with_context function of lib.rs, which will, at line 188, try to start a connection with the device by calling the open method on it. In case of error, a debug message will be printed, and the function will return the error returned by open:

let mut handle = match device.open() {
    Ok(v) => v,
    Err(e) => {
        debug!("Error opening device");
        return Err(e.into());
    }
};

The open method can return a rusb::error, and among those errors is rusb::error::NotSupported, which means "Operation not supported or unimplemented on this platform.", according to the documentation.
But the device is an instance of the rusb::Device struct from the rusb crate, so if the error comes from this crate, it is beyond the scope of this repository.
But still, it seems that this ptouch driver does not work on windows. I'm running windows 11 by the way.

Workaround

I needed to get the printing to work.
What I then did is that I created an alternative method to get_status, which I called get_status_mocked. The goal was to build an instance of the Status struct ith the printer informations and to return it. The needed informations about the status can be found in the pt-e550w manual, section 4. Printing command details, Status command.
image
My function was like this:

pub fn status_mock(&mut self) -> Result<Status, Error> {
    Ok(Status {
        model: 0x66,
        error1: Error1::empty(),
        error2: Error2::empty(),
        media_width: 12,
        media_kind: MediaKind::LaminatedTape,
        status_type: DeviceStatus::Completed,
        phase: Phase::Editing,
        tape_colour: TapeColour::White,
        text_colour: TextColour::Black
    })
}

Warning: if you try to do the same workaround, you might need to change some fields, depending on your printer (the model, the tape colour, the media width, etc).
I then edited the line 133 of util.rs to call status_mock instead of status:

let status = pt.status_mock()?;

After this change, I tried to cargo build again, and to run the program again with sudo target/debug/ptouch-util --log-level debug --device pt-e550w print qr-text "hello" "hello friend": the printer printed the expected qr code and text ! (I'm not giving the output because it is very long since all the data sent to the printer are logged).

Conclusion

With the workaround, the printing function now works. However, if someone gets stuck on the same problem than me in the future, this issue should contain enough information to help them.

In the end, maybe what I'm experimenting is not a problem with this program, but with rusb ; if that's the case, then I'm sorry, but I still wanted to report it.

That's actually the first GitHub issue on an open source project I've ever written, If some information are missing, please tell me.

Incorrect width for 3 different tape types

Hi,

While trying to add a new feature (the switch to bypass the status request you suggested here), I noticed something that looks like a bug: in the device.rs file, in method width, you return a width based on the model of self ; but the width for 3 of them seems to miss a digit:

Tze12mm => 2,
Tze18mm => 8,
Tze24mm => 4,

That probably should be 12, 18 and 24, right ?
Fortunately, it looks like this method is not used anywhere. It is still good that you implemented it, because it turns out I needed it for the feature I'm adding.

Anyway, I am fixing this in the pull request I'm gonna open for the new feature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.