HPInc / jipp

A Java-compatible implementation of IPP
MIT License
153 stars 42 forks source link

Bad request sending printJob request #64

Closed 39otrebla closed 5 years ago

39otrebla commented 5 years ago

I'm trying IPP printing on Android, my printer is an Epson Workforce 3725. After successfully connecting via Wi-Fi Direct, I'm running:

final File file = new File(mContext.getFilesDir(), filename);

URI uri = URI.create("http://192.168.10.1:631/ipp/print");

IppPacket printRequest = new IppPacket(Operation.printJob, 125, AttributeGroup.groupOf(Tag.operationAttributes, printerUri.of(uri)));

IppClientTransport transport = new HttpIppClientTransport();
try {
    IppPacketData request = new IppPacketData(printRequest, new FileInputStream(file));
    IppPacketData response = transport.sendData(uri, request);

    Log.d("main", response.getPacket().prettyPrint(100, "  "));
} catch (IOException ex) {
    Log.e("main", "Error: "+ ex.toString());
}

File is PDF created with built-in Android library. I'm getting this error:

IppPacket(v=0x200, c=client-error-bad-request(1024), r=0x7d) {
      operation-attributes {
        attributes-charset = "utf-8" (charset),
        attributes-natural-language = "en" (naturalLanguage) } }

EDIT Using sample application jprint from the command line I am able to print using LAN address (http://192.168.1.22:631/ipp/print instead of http://192.168.10.1:631/ipp/print), but the POST request is printed, not the actual file. It's like I was printing using port 9100.

39otrebla commented 5 years ago

I figured out that requester name is mandatory, at least for my printer... But I'm still getting 50-60 sheets printed with incomprehensible chars written on them! I'm going to open a new issue for this.

GladeDiviney commented 5 years ago

Sounds like you need to send data using a supported document-format. The basic process:

  1. Send a Operation.getPrinterAttributes query for document-format-supported:

    IppPacket(v=0x200, c=Get-Printer-Attributes(11), r=0x1) {
    operation-attributes {
    attributes-charset = "utf-8" (charset),
    attributes-natural-language = "en-us" (naturalLanguage),
    printer-uri = ipp://192.168.1.11:631/ipp/print,
    requested-attributes = [ document-format-supported ] } }
  2. Read from the printerAttributes group in the resulting response, e.g.:

    IppPacket(v=0x200, c=successful-ok(0), r=0x1) {
    operation-attributes { ... }
    printer-attributes {
    document-format-supported = [
      application/PCLm,
      application/pdf,
      image/pwg-raster, ...]
    } }
  3. Send a job with one of the supported document-formats:

    IppPacket(v=0x200, c=Print-Job(2), r=0x2) {
    operation-attributes {
    attributes-charset = "utf-8" (charset),
    attributes-natural-language = "en-us" (naturalLanguage),
    printer-uri = ipp://192.168.1.11:631/ipp/print,
    requesting-user-name = "myself" (name),
    job-name = "mydoc.pwg" (name) },
    job-attributes {
    document-format = image/pwg-raster
    } }
    + DATA
39otrebla commented 5 years ago

@GladeDiviney I confirm my printer does not support application/pdf format. Thanks again

sebastian-schmitt commented 4 years ago

Just as a hint to others who stumbled upon this issue like me: the user name attribute has to go AFTER the target (like job-uri or printer-uri+job-id)

gladed commented 4 years ago

Yes, IPP is particular that way!

I'd love to model this restriction in Java somehow but there are many legal variants for an IPP packet, and I'm not a fan of classes with 20 constructors...