michaelrsweet / lprint

A Label Printer Application
https://www.msweet.org/lprint
Apache License 2.0
219 stars 29 forks source link

Interaction with cups #103

Closed andreaskem closed 7 months ago

andreaskem commented 11 months ago

Hi. I am currently trying to migrate an old UNIX printing mechanism for labels to cups. Given that label printer support is deprecated in cups, I wanted to build on what seems to be the recommended, "new" way via lprint.

My use case is pretty simple. An existing service generates ZPL/EPL files and they are supposed to be printed on one of several label printers. From what I thought I understood, this seemed to be very simple with lprint.

I started to experiment on Debian bullseye (cups package 2.3.3op2-3+deb11u2) and used lprint version 1.2 and pappl version 1.3.2, both of which I compiled myself. Later I tried the same steps on Arch Linux (lprint 1.2, pappl 1.3.2, cups 2.4.6).

The lprint side of things seems to work fine. First of all, I started the lprint service via systemctl start lprint. Then I added the (network) printer

sudo lprint add -d lpne3 -v socket://lpnzeb2 -m epl2_2inch-203dpi-dt -o label-mode-configured=peel-off

At this point, I can submit a print job and the printer produces a label that seems to match the EPL file

lprint submit -d lpne3 label.epl

My understanding was that cups would auto-discover the lprint printer and add its own corresponding print queue. However, for some reason, this does not seem to happen reliably. Even some time after the printer was added in lprint, cups does not seem to notice. However, if I restart the lprint service, cups quickly adds its own printer queue automatically. At this point, I would like to submit the print job via cups:

lp -d lpne3 label.epl

This seems to get rejected:

lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 7] HTTP_STATE_POST https://localhost:8000/ipp/print/lpne3 HTTP/1.1 ()
lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 7] Continue
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request: IPP/2.0 request-id=2
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request: operation-attributes-tag
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   attributes-charset charset utf-8
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   attributes-natural-language naturalLanguage en-us
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   printer-uri uri ipps://localhost:8000/ipp/print/lpne3
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   requesting-user-name nameWithoutLanguage andreas
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   job-name nameWithoutLanguage tt.epl
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   document-format mimeMediaType image/urf
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request: job-attributes-tag
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   media-col collection {media-size={x-dimension=10160 y-dimension=15240} media-bo>
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   output-bin keyword face-up
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   print-color-mode keyword monochrome
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   print-quality enum 0
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   sides keyword one-sided
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job request:   multiple-document-handling keyword separate-documents-collated-copies
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] IPP/2.0 Validate-Job (CUPS/2.4.2 (Linux 6.1.0-9-amd64; x86_64) IPP/2.0)
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job "document-format"='image/urf'
lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job client-error-attributes-or-values-not-supported (Unsupported print-quality enum value.)
lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 7] OK application/ipp 154
lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 8] Accepted connection from 'localhost'.
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response: IPP/2.0 request-id=2, status-code=client-error-attributes-or-values-not-supported
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response: operation-attributes-tag
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response:   attributes-charset charset utf-8
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response:   attributes-natural-language naturalLanguage en-us
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response:   status-message textWithoutLanguage Unsupported print-quality enum value.
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response: unsupported-attributes-tag
lprint[58807]: D [2023-07-25T14:09:55.674Z] [Client 7] Validate-Job response:   print-quality enum 0
lprint[58807]: I [2023-07-25T14:09:55.674Z] [Client 7] Closing connection from 'localhost'.

Then I added -o print-quality=5 to the command. The printer seems to print several empty labels at that point.

lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request: IPP/2.0 request-id=3
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request: operation-attributes-tag
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   attributes-charset charset utf-8
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   attributes-natural-language naturalLanguage en-us
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   printer-uri uri ipps://localhost:8000/ipp/print/lpne3
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   requesting-user-name nameWithoutLanguage andreas
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   job-name nameWithoutLanguage tt.epl
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request: job-attributes-tag
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   media-col collection {media-size={x-dimension=10160 y-dimension=15240} media-b>
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   output-bin keyword face-up
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   print-color-mode keyword monochrome
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   print-quality enum normal
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   sides keyword one-sided
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] Create-Job request:   multiple-document-handling keyword separate-documents-collated-copies
lprint[1117141]: D [2023-07-25T09:15:40.339Z] [Client 29] IPP/2.0 Create-Job (CUPS/2.4.2 (Linux 6.1.0-9-amd64; x86_64) IPP/2.0)
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Client 29] Create-Job successful-ok
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Client 29] OK application/ipp 237
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response: IPP/2.0 request-id=3, status-code=successful-ok
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response: operation-attributes-tag
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   attributes-charset charset utf-8
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   attributes-natural-language naturalLanguage en-us
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response: job-attributes-tag
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   job-id integer 5
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   job-uri uri ipps://localhost:8000/ipp/print/lpne3/5
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   job-state enum pending-held
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   job-state-message textWithoutLanguage Job created.
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Create-Job response:   job-state-reasons keyword job-data-insufficient
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Client 29] HTTP_STATE_POST https://localhost:8000/ipp/print/lpne3 HTTP/1.1 ()
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Client 29] Continue
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request: IPP/2.0 request-id=4
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request: operation-attributes-tag
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   attributes-charset charset utf-8
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   attributes-natural-language naturalLanguage en-us
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   printer-uri uri ipps://localhost:8000/ipp/print/lpne3
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   job-id integer 5
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   requesting-user-name nameWithoutLanguage andreas
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   last-document boolean true
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   document-format mimeMediaType image/urf
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document request:   compression keyword gzip
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] IPP/2.0 Send-Document (CUPS/2.4.2 (Linux 6.1.0-9-amd64; x86_64) IPP/2.0)
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document "compression"='gzip'
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Client 29] Receiving job file with 'gzip' compression.
lprint[1117141]: D [2023-07-25T09:15:40.340Z] [Client 29] Send-Document "document-format"='image/urf'
lprint[1117141]: I [2023-07-25T09:15:40.340Z] [Job 5] Starting print job.

Apparently, cups tries to convert the input to some other format and does not pass through the plain text EPL file. I tried adding -o document-format='application/vnd.eltron-epl', but cups rejects the mime type:

lp: Unsupported document-format "application/vnd.eltron-epl".

My next attempt was to add the printer queue to cups manually, explicitly adding -m everywhere:

sudo lpadmin -m everywhere -p lpne3 -v ipps://localhost:8000/ipp/print/lpne3

But afterward, I still could no get labels to print properly. At some point, the contents of the EPL file were printed as text on several labels.

At this point, I am thoroughly confused. I thought I would let lprint do what it is supposed to do and it all seemed very simple at first, but I cannot get it to work. What am I doing wrong? Are things even supposed to work how I expected them to work?

During testing, I noticed that the lprint service does not seem to remember the pause state of printers. The lprint pause -d lpne3 command works but after a reboot or service restart, the printer was no longer paused. From what I could tell, the pause state is not persisted in /etc/lprint.conf ?

andreaskem commented 11 months ago

Okay, I figured something out. The ppd file is auto-generated by cups as soon as it figures out that it needs to create a queue (see below). It seems to match the output of driverless ipps://localhost:8000/ipp/print/lpne3, so I assume it was created by lprint. I noticed that there are 3 cupsFilter2 lines and the first one is for image/urf. Judging from the log files, cups always seems to convert to urf for some reason, so I decided to add a line before the urf line.

*cupsFilter2: "application/octet-stream application/octet-stream 0 -"

At that point, I could successfully submit a print job and the label was created correctly. This is not reproducible, something else must have happened.

lp -d lpne3 -o document-format=application/octet-stream lbl.scratch.2005762.140044833156352-12.lpne1

This does not appear quite as seemless as I expected it to be, so I assume I am missing something.

*PPD-Adobe: "4.3"
*FormatVersion: "4.3"
*FileVersion: "1.28.17"
*LanguageVersion: English
*LanguageEncoding: ISOLatin1
*PSVersion: "(3010.000) 0"
*LanguageLevel: "3"
*FileSystem: False
*PCFileName: "drvless.ppd"
*Manufacturer: "Zebra"
*ModelName: "Zebra EPL Page Mode 2-inch/203dpi/Direct-Thermal"
*Product: "(Zebra EPL Page Mode 2-inch/203dpi/Direct-Thermal)"
*NickName: "Zebra EPL Page Mode 2-inch/203dpi/Direct-Thermal, driverless, cups-filters 1.28.17"
*ShortNickName: "Zebra EPL Page Mode 2-inch/203dpi/Direct-Thermal"
*DefaultOutputOrder: Normal
*ColorDevice: False
*cupsVersion: 2.4
*cupsSNMPSupplies: False
*cupsLanguages: "en"
*APSupplies: "http://localhost:8000/lpne3/"
*cupsFilter2: "image/urf image/urf 0 -"
*cupsFilter2: "image/jpeg image/jpeg 0 -"
*cupsFilter2: "image/png image/png 0 -"
*cupsManualCopies: True
*OpenUI *PageSize/Media Size: PickOne
*OrderDependency: 10 AnySetup *PageSize
*DefaultPageSize: 4x6
*PageSize 1.25x0.25: "<</PageSize[90 18]>>setpagedevice"
*PageSize 1.25x2.25: "<</PageSize[90 162]>>setpagedevice"
*PageSize 1.5x0.25: "<</PageSize[108 18]>>setpagedevice"
*PageSize 1.5x0.5: "<</PageSize[108 36]>>setpagedevice"
*PageSize 1.5x1: "<</PageSize[108 72]>>setpagedevice"
*PageSize 1.5x2: "<</PageSize[108 144]>>setpagedevice"
*PageSize 2.25x0.5: "<</PageSize[162 36]>>setpagedevice"
*PageSize 2.25x1.25: "<</PageSize[162 90]>>setpagedevice"
*PageSize 2.25x3.125: "<</PageSize[162 224.985826771654]>>setpagedevice"
*PageSize 2.25x4: "<</PageSize[162 288]>>setpagedevice"
*PageSize 2.25x5.5: "<</PageSize[162 396]>>setpagedevice"
*PageSize 2.38x5.5: "<</PageSize[171.354330708661 396]>>setpagedevice"
*PageSize 2.5x1: "<</PageSize[180 72]>>setpagedevice"
*PageSize 2.5x2: "<</PageSize[180 144]>>setpagedevice"
*PageSize 2.75x1.25: "<</PageSize[198 90]>>setpagedevice"
*PageSize 2.9x1: "<</PageSize[208.8 72]>>setpagedevice"
*PageSize 2x0.37: "<</PageSize[144 26.617322834646]>>setpagedevice"
*PageSize 2x0.5: "<</PageSize[144 36]>>setpagedevice"
*PageSize 2x1: "<</PageSize[144 72]>>setpagedevice"
*PageSize 2x1.25: "<</PageSize[144 90]>>setpagedevice"
*PageSize 2x2: "<</PageSize[144 144]>>setpagedevice"
*PageSize 2x3: "<</PageSize[144 216]>>setpagedevice"
*PageSize 2x4: "<</PageSize[144 288]>>setpagedevice"
*PageSize 2x5.5: "<</PageSize[144 396]>>setpagedevice"
*PageSize 3.25x2: "<</PageSize[234 144]>>setpagedevice"
*PageSize 3.25x5: "<</PageSize[234 360]>>setpagedevice"
*PageSize 3.25x5.5: "<</PageSize[234 396]>>setpagedevice"
*PageSize 3.25x5.83: "<</PageSize[234 419.754330708661]>>setpagedevice"
*PageSize 3.25x7.83: "<</PageSize[234 563.754330708661]>>setpagedevice"
*PageSize 3.5x1: "<</PageSize[252 72]>>setpagedevice"
*PageSize 3x1: "<</PageSize[216 72]>>setpagedevice"
*PageSize 3x1.25: "<</PageSize[216 90]>>setpagedevice"
*PageSize 3x2: "<</PageSize[216 144]>>setpagedevice"
*PageSize 3x3: "<</PageSize[216 216]>>setpagedevice"
*PageSize 3x5/3 x 5″: "<</PageSize[216 360]>>setpagedevice"
*PageSize 4x1: "<</PageSize[288 72]>>setpagedevice"
*PageSize 4x13: "<</PageSize[288 936]>>setpagedevice"
*PageSize 4x2: "<</PageSize[288 144]>>setpagedevice"
*PageSize 4x3: "<</PageSize[288 216]>>setpagedevice"
*PageSize 4x4: "<</PageSize[288 288]>>setpagedevice"
*PageSize 4x5: "<</PageSize[288 360]>>setpagedevice"
*PageSize 4x6/4 x 6″: "<</PageSize[288 432]>>setpagedevice"
*PageSize 4x6.5/Envelope Chinese #1: "<</PageSize[288 468]>>setpagedevice"
*PageSize 50.8x9.39mm: "<</PageSize[144 26.617322834646]>>setpagedevice"
*PageSize 57.15x79.37mm: "<</PageSize[162 224.985826771654]>>setpagedevice"
*PageSize 60.45x139.7mm: "<</PageSize[171.354330708661 396]>>setpagedevice"
*PageSize 73.66x25.4mm: "<</PageSize[208.8 72]>>setpagedevice"
*PageSize 82.55x148.08mm: "<</PageSize[234 419.754330708661]>>setpagedevice"
*PageSize 82.55x198.88mm: "<</PageSize[234 563.754330708661]>>setpagedevice"
*PageSize EnvPRC1/Envelope Chinese #1: "<</PageSize[289.133858267717 467.716535433071]>>setpagedevice"
*CloseUI: *PageSize
*OpenUI *PageRegion/Media Size: PickOne
*OrderDependency: 10 AnySetup *PageRegion
*DefaultPageRegion: 4x6
*PageRegion 1.25x0.25: "<</PageSize[90 18]>>setpagedevice"
*PageRegion 1.25x2.25: "<</PageSize[90 162]>>setpagedevice"
*PageRegion 1.5x0.25: "<</PageSize[108 18]>>setpagedevice"
*PageRegion 1.5x0.5: "<</PageSize[108 36]>>setpagedevice"
*PageRegion 1.5x1: "<</PageSize[108 72]>>setpagedevice"
*PageRegion 1.5x2: "<</PageSize[108 144]>>setpagedevice"
*PageRegion 2.25x0.5: "<</PageSize[162 36]>>setpagedevice"
*PageRegion 2.25x1.25: "<</PageSize[162 90]>>setpagedevice"
*PageRegion 2.25x3.125: "<</PageSize[162 224.985826771654]>>setpagedevice"
*PageRegion 2.25x4: "<</PageSize[162 288]>>setpagedevice"
*PageRegion 2.25x5.5: "<</PageSize[162 396]>>setpagedevice"
*PageRegion 2.38x5.5: "<</PageSize[171.354330708661 396]>>setpagedevice"
*PageRegion 2.5x1: "<</PageSize[180 72]>>setpagedevice"
*PageRegion 2.5x2: "<</PageSize[180 144]>>setpagedevice"
*PageRegion 2.75x1.25: "<</PageSize[198 90]>>setpagedevice"
*PageRegion 2.9x1: "<</PageSize[208.8 72]>>setpagedevice"
*PageRegion 2x0.37: "<</PageSize[144 26.617322834646]>>setpagedevice"
*PageRegion 2x0.5: "<</PageSize[144 36]>>setpagedevice"
*PageRegion 2x1: "<</PageSize[144 72]>>setpagedevice"
*PageRegion 2x1.25: "<</PageSize[144 90]>>setpagedevice"
*PageRegion 2x2: "<</PageSize[144 144]>>setpagedevice"
*PageRegion 2x3: "<</PageSize[144 216]>>setpagedevice"
*PageRegion 2x4: "<</PageSize[144 288]>>setpagedevice"
*PageRegion 2x5.5: "<</PageSize[144 396]>>setpagedevice"
*PageRegion 3.25x2: "<</PageSize[234 144]>>setpagedevice"
*PageRegion 3.25x5: "<</PageSize[234 360]>>setpagedevice"
*PageRegion 3.25x5.5: "<</PageSize[234 396]>>setpagedevice"
*PageRegion 3.25x5.83: "<</PageSize[234 419.754330708661]>>setpagedevice"
*PageRegion 3.25x7.83: "<</PageSize[234 563.754330708661]>>setpagedevice"
*PageRegion 3.5x1: "<</PageSize[252 72]>>setpagedevice"
*PageRegion 3x1: "<</PageSize[216 72]>>setpagedevice"
*PageRegion 3x1.25: "<</PageSize[216 90]>>setpagedevice"
*PageRegion 3x2: "<</PageSize[216 144]>>setpagedevice"
*PageRegion 3x3: "<</PageSize[216 216]>>setpagedevice"
*PageRegion 3x5/3 x 5″: "<</PageSize[216 360]>>setpagedevice"
*PageRegion 4x1: "<</PageSize[288 72]>>setpagedevice"
*PageRegion 4x13: "<</PageSize[288 936]>>setpagedevice"
*PageRegion 4x2: "<</PageSize[288 144]>>setpagedevice"
*PageRegion 4x3: "<</PageSize[288 216]>>setpagedevice"
*PageRegion 4x4: "<</PageSize[288 288]>>setpagedevice"
*PageRegion 4x5: "<</PageSize[288 360]>>setpagedevice"
*PageRegion 4x6/4 x 6″: "<</PageSize[288 432]>>setpagedevice"
*PageRegion 4x6.5/Envelope Chinese #1: "<</PageSize[288 468]>>setpagedevice"
*PageRegion 50.8x9.39mm: "<</PageSize[144 26.617322834646]>>setpagedevice"
*PageRegion 57.15x79.37mm: "<</PageSize[162 224.985826771654]>>setpagedevice"
*PageRegion 60.45x139.7mm: "<</PageSize[171.354330708661 396]>>setpagedevice"
*PageRegion 73.66x25.4mm: "<</PageSize[208.8 72]>>setpagedevice"
*PageRegion 82.55x148.08mm: "<</PageSize[234 419.754330708661]>>setpagedevice"
*PageRegion 82.55x198.88mm: "<</PageSize[234 563.754330708661]>>setpagedevice"
*PageRegion EnvPRC1/Envelope Chinese #1: "<</PageSize[289.133858267717 467.716535433071]>>setpagedevice"
*CloseUI: *PageRegion
*DefaultImageableArea: 4x6
*DefaultPaperDimension: 4x6
*ImageableArea 1.25x0.25: "0.028346456693 0.028346456693 89.971653543307 17.971653543307"
*PaperDimension 1.25x0.25: "90 18"
*ImageableArea 1.25x2.25: "0.028346456693 0.028346456693 89.971653543307 161.971653543307"
*PaperDimension 1.25x2.25: "90 162"
*ImageableArea 1.5x0.25: "0.028346456693 0.028346456693 107.971653543307 17.971653543307"
*PaperDimension 1.5x0.25: "108 18"
*ImageableArea 1.5x0.5: "0.028346456693 0.028346456693 107.971653543307 35.971653543307"
*PaperDimension 1.5x0.5: "108 36"
*ImageableArea 1.5x1: "0.028346456693 0.028346456693 107.971653543307 71.971653543307"
*PaperDimension 1.5x1: "108 72"
*ImageableArea 1.5x2: "0.028346456693 0.028346456693 107.971653543307 143.971653543307"
*PaperDimension 1.5x2: "108 144"
*ImageableArea 2.25x0.5: "0.028346456693 0.028346456693 161.971653543307 35.971653543307"
*PaperDimension 2.25x0.5: "162 36"
*ImageableArea 2.25x1.25: "0.028346456693 0.028346456693 161.971653543307 89.971653543307"
*PaperDimension 2.25x1.25: "162 90"
*ImageableArea 2.25x3.125: "0.028346456693 0.028346456693 161.971653543307 224.957480314961"
*PaperDimension 2.25x3.125: "162 224.985826771654"
*ImageableArea 2.25x4: "0.028346456693 0.028346456693 161.971653543307 287.971653543307"
*PaperDimension 2.25x4: "162 288"
*ImageableArea 2.25x5.5: "0.028346456693 0.028346456693 161.971653543307 395.971653543307"
*PaperDimension 2.25x5.5: "162 396"
*ImageableArea 2.38x5.5: "0.028346456693 0.028346456693 171.325984251968 395.971653543307"
*PaperDimension 2.38x5.5: "171.354330708661 396"
*ImageableArea 2.5x1: "0.028346456693 0.028346456693 179.971653543307 71.971653543307"
*PaperDimension 2.5x1: "180 72"
*ImageableArea 2.5x2: "0.028346456693 0.028346456693 179.971653543307 143.971653543307"
*PaperDimension 2.5x2: "180 144"
*ImageableArea 2.75x1.25: "0.028346456693 0.028346456693 197.971653543307 89.971653543307"
*PaperDimension 2.75x1.25: "198 90"
*ImageableArea 2.9x1: "0.028346456693 0.028346456693 208.771653543307 71.971653543307"
*PaperDimension 2.9x1: "208.8 72"
*ImageableArea 2x0.37: "0.028346456693 0.028346456693 143.971653543307 26.588976377953"
*PaperDimension 2x0.37: "144 26.617322834646"
*ImageableArea 2x0.5: "0.028346456693 0.028346456693 143.971653543307 35.971653543307"
*PaperDimension 2x0.5: "144 36"
*ImageableArea 2x1: "0.028346456693 0.028346456693 143.971653543307 71.971653543307"
*PaperDimension 2x1: "144 72"
*ImageableArea 2x1.25: "0.028346456693 0.028346456693 143.971653543307 89.971653543307"
*PaperDimension 2x1.25: "144 90"
*ImageableArea 2x2: "0.028346456693 0.028346456693 143.971653543307 143.971653543307"
*PaperDimension 2x2: "144 144"
*ImageableArea 2x3: "0.028346456693 0.028346456693 143.971653543307 215.971653543307"
*PaperDimension 2x3: "144 216"
*ImageableArea 2x4: "0.028346456693 0.028346456693 143.971653543307 287.971653543307"
*PaperDimension 2x4: "144 288"
*ImageableArea 2x5.5: "0.028346456693 0.028346456693 143.971653543307 395.971653543307"
*PaperDimension 2x5.5: "144 396"
*ImageableArea 3.25x2: "0.028346456693 0.028346456693 233.971653543307 143.971653543307"
*PaperDimension 3.25x2: "234 144"
*ImageableArea 3.25x5: "0.028346456693 0.028346456693 233.971653543307 359.971653543307"
*PaperDimension 3.25x5: "234 360"
*ImageableArea 3.25x5.5: "0.028346456693 0.028346456693 233.971653543307 395.971653543307"
*PaperDimension 3.25x5.5: "234 396"
*ImageableArea 3.25x5.83: "0.028346456693 0.028346456693 233.971653543307 419.725984251968"
*PaperDimension 3.25x5.83: "234 419.754330708661"
*ImageableArea 3.25x7.83: "0.028346456693 0.028346456693 233.971653543307 563.725984251968"
*PaperDimension 3.25x7.83: "234 563.754330708661"
*ImageableArea 3.5x1: "0.028346456693 0.028346456693 251.971653543307 71.971653543307"
*PaperDimension 3.5x1: "252 72"
*ImageableArea 3x1: "0.028346456693 0.028346456693 215.971653543307 71.971653543307"
*PaperDimension 3x1: "216 72"
*ImageableArea 3x1.25: "0.028346456693 0.028346456693 215.971653543307 89.971653543307"
*PaperDimension 3x1.25: "216 90"
*ImageableArea 3x2: "0.028346456693 0.028346456693 215.971653543307 143.971653543307"
*PaperDimension 3x2: "216 144"
*ImageableArea 3x3: "0.028346456693 0.028346456693 215.971653543307 215.971653543307"
*PaperDimension 3x3: "216 216"
*ImageableArea 3x5: "0.028346456693 0.028346456693 215.971653543307 359.971653543307"
*PaperDimension 3x5: "216 360"
*ImageableArea 4x1: "0.028346456693 0.028346456693 287.971653543307 71.971653543307"
*PaperDimension 4x1: "288 72"
*ImageableArea 4x13: "0.028346456693 0.028346456693 287.971653543307 935.971653543307"
*PaperDimension 4x13: "288 936"
*ImageableArea 4x2: "0.028346456693 0.028346456693 287.971653543307 143.971653543307"
*PaperDimension 4x2: "288 144"
*ImageableArea 4x3: "0.028346456693 0.028346456693 287.971653543307 215.971653543307"
*PaperDimension 4x3: "288 216"
*ImageableArea 4x4: "0.028346456693 0.028346456693 287.971653543307 287.971653543307"
*PaperDimension 4x4: "288 288"
*ImageableArea 4x5: "0.028346456693 0.028346456693 287.971653543307 359.971653543307"
*PaperDimension 4x5: "288 360"
*ImageableArea 4x6: "0.028346456693 0.028346456693 287.971653543307 431.971653543307"
*PaperDimension 4x6: "288 432"
*ImageableArea 4x6.5: "0.028346456693 0.028346456693 287.971653543307 467.971653543307"
*PaperDimension 4x6.5: "288 468"
*ImageableArea 50.8x9.39mm: "0.028346456693 0.028346456693 143.971653543307 26.588976377953"
*PaperDimension 50.8x9.39mm: "144 26.617322834646"
*ImageableArea 57.15x79.37mm: "0.028346456693 0.028346456693 161.971653543307 224.957480314961"
*PaperDimension 57.15x79.37mm: "162 224.985826771654"
*ImageableArea 60.45x139.7mm: "0.028346456693 0.028346456693 171.325984251968 395.971653543307"
*PaperDimension 60.45x139.7mm: "171.354330708661 396"
*ImageableArea 73.66x25.4mm: "0.028346456693 0.028346456693 208.771653543307 71.971653543307"
*PaperDimension 73.66x25.4mm: "208.8 72"
*ImageableArea 82.55x148.08mm: "0.028346456693 0.028346456693 233.971653543307 419.725984251968"
*PaperDimension 82.55x148.08mm: "234 419.754330708661"
*ImageableArea 82.55x198.88mm: "0.028346456693 0.028346456693 233.971653543307 563.725984251968"
*PaperDimension 82.55x198.88mm: "234 563.754330708661"
*ImageableArea EnvPRC1: "0.028346456693 0.028346456693 289.105511811024 467.688188976378"
*PaperDimension EnvPRC1: "289.133858267717 467.716535433071"
*HWMargins: "0.028346456693 0.028346456693 0.028346456693 0.028346456693"
*ParamCustomPageSize Width: 1 points 54 288
*ParamCustomPageSize Height: 2 points 18 7200
*ParamCustomPageSize WidthOffset: 3 points 0 0
*ParamCustomPageSize HeightOffset: 4 points 0 0
*ParamCustomPageSize Orientation: 5 int 0 3
*CustomPageSize True: "pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice"
*OpenUI *InputSlot/Media Source: PickOne
*OrderDependency: 10 AnySetup *InputSlot
*DefaultInputSlot: MainRoll
*InputSlot MainRoll/Main Roll: "<</MediaPosition 9>>setpagedevice"
*InputSlot Auto/Automatic: "<</MediaPosition 0>>setpagedevice"
*CloseUI: *InputSlot
*OpenUI *MediaType/Media Type: PickOne
*OrderDependency: 10 AnySetup *MediaType
*DefaultMediaType: Labels
*MediaType Continuous/Continuous: "<</MediaType(Continuous)>>setpagedevice"
*MediaType Labels/Labels: "<</MediaType(Labels)>>setpagedevice"
*MediaType LabelsContinuous: "<</MediaType(LabelsContinuous)>>setpagedevice"
*CloseUI: *MediaType
*% ColorModel from urf-supported
*OpenUI *ColorModel/Print Color Mode: PickOne
*OrderDependency: 10 AnySetup *ColorModel
*ColorModel Gray/Monochrome: "<</cupsColorSpace 18/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice"
*ColorModel DeviceGray/Device Gray: "<</cupsColorSpace 0/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice"
*DefaultColorModel: Gray
*CloseUI: *ColorModel
*OpenUI *OutputBin/Output Tray: PickOne
*OrderDependency: 10 AnySetup *OutputBin
*DefaultOutputBin: FaceUp
*OutputBin FaceUp/Face Up: ""
*PageStackOrder FaceUp: Normal
*CloseUI: *OutputBin
*DefaultResolution: 203dpi
*OpenUI *cupsPrintQuality/Print Quality: PickOne
*OrderDependency: 10 AnySetup *cupsPrintQuality
*DefaultcupsPrintQuality: Normal
*cupsPrintQuality Draft/Draft: "<</HWResolution[203 203]>>setpagedevice"
*cupsPrintQuality Normal/Normal: "<</HWResolution[203 203]>>setpagedevice"
*cupsPrintQuality High/High: "<</HWResolution[203 203]>>setpagedevice"
*CloseUI: *cupsPrintQuality
*OpenUI *print-content-optimize/Print Optimization: PickOne
*OrderDependency: 10 AnySetup *print-content-optimize
*Defaultprint-content-optimize: auto
*print-content-optimize auto/Automatic: ""
*print-content-optimize graphic/Graphics: ""
*print-content-optimize photo/Photo: ""
*print-content-optimize text-and-graphic/Text and Graphics: ""
*print-content-optimize text/Text: ""
*CloseUI: *print-content-optimize
*OpenUI *print-scaling/Print Scaling: PickOne
*OrderDependency: 10 AnySetup *print-scaling
*Defaultprint-scaling: auto
*print-scaling auto/Automatic: ""
*print-scaling auto-fit/Auto-fit: ""
*print-scaling fill/Fill: ""
*print-scaling fit/Fit: ""
*print-scaling none/None: ""
*CloseUI: *print-scaling
*cupsFilter2: "application/vnd.cups-pdf application/pdf 0 -"
andreaskem commented 10 months ago

As a test, I tried adding

application/vnd.eltron-epl epl string(0, "\nN\n")

to mime.types but CUPS still refused to accept -o document-format='application/vnd.eltron-epl'. CUPS sent raster data, when omitting the format

lp -d lpne3 lbl.scratch.epl
Aug 28 08:22:41 lap-ake lprint[2306]: I [2023-08-28T06:22:41.134Z] [Job 5] Starting print job.
Aug 28 08:22:41 lap-ake lprint[2306]: I [2023-08-28T06:22:41.135Z] [Job 5] Page 1 raster data is 812x1218x8 (sGray)

resulting in a label with the text content of the file.

As an aside:

Continuing my streak of misfortune, I wanted to try ippeveprinter, hitting an assertion in the process

$ sudo ippeveprinter -D socket://lpnzeb2 ippeve
Ignored Avahi state 101.
Listening on port 8001.
ippeveprinter: entrygroup.c:421: avahi_entry_group_add_service_strlst: Assertion `group' failed.
Aborted
michaelrsweet commented 10 months ago

Sorry for the delay in responding over the summer months... Some feedback:

  1. The "driverless" PPD generator currently doesn't handle printer-specific formats. This needs to be reported to the cups-filters project.
  2. Raw printing of EPL files is somewhat limited - as long as your file starts with a blank line followed by a line with an "N", it will be detected as an EPL file.
  3. If you are printing on the same system as lprint, it might be easier to just "cut out the middleman" and print using the lprint command instead of setting up a CUPS queue. That was one of the original purposes of lprint since label printing often has some different needs from "regular" printing...
  4. Please report the printer stopped state issue to the PAPPL project, as that is where the state is saved and restored.
  5. Issues in ippeveprinter should be reported to the CUPS and/or libcups projects.
andreaskem commented 10 months ago

Thank you for your answer.

  1. So cups-filters would have to learn to handle special "application/vnd.* MIME types if the printer supports them?
  2. lprint itself can print them just fine but cups seems to insist on converting them before sending them to lprint.
  3. Is it possible to use the cups library/APIs to talk to lprint? As far as I understand, I should be able to talk to lprint directly, since everything is IPP, but I hit some snags trying to do so. See below.
  4. Thank you, I will do so.
  5. I might do so, but this is less of a priority, to be honest.
andreaskem commented 10 months ago

I tried to use python-cups to talk to lprint directly. The following seems to work perfectly, giving me a list of the label printers configured on the system:

cups.setServer('/run/lprint.sock')
c = cups.Connection ()

dests = c.getPrinters()
for d in dests:
    print(d)

But c.getDevices() does not work:

    dests = c.getDevices()
            ^^^^^^^^^^^^^^
cups.IPPError: (1024, 'client-error-bad-request')
[Client 41] CUPS-Get-Devices request: IPP/2.0 request-id=2
[Client 41] CUPS-Get-Devices request: operation-attributes-tag
[Client 41] CUPS-Get-Devices request:   attributes-charset charset utf-8
[Client 41] CUPS-Get-Devices request:   attributes-natural-language naturalLanguage en-us
[Client 41] CUPS-Get-Devices client-error-bad-request (Missing required attributes.)
[Client 41] OK application/ipp 122
[Client 41] CUPS-Get-Devices response: IPP/2.0 request-id=2, status-code=client-error-bad-request
[Client 41] CUPS-Get-Devices response: operation-attributes-tag
[Client 41] CUPS-Get-Devices response:   attributes-charset charset utf-8
[Client 41] CUPS-Get-Devices response:   attributes-natural-language naturalLanguage en-us
[Client 41] CUPS-Get-Devices response:   status-message textWithoutLanguage Missing required attributes.
[Client 41] Closing connection from 'localhost'.

But, as far as I can tell, only "Natural Language and Character Set" are required parameters and they seem to be supplied with the request. I do not seem to be able to use the printer name for most things, so I would like to get at the printer-uri somehow. A simple printFile fails if I just supply the printer name:

    print(c.printFile('lpne3',
          ^^^^^^^^^^^^^^^^^^^^
cups.IPPError: (1030, 'printer-uri ipp://localhost:631/printers/lpne3 not found.')

edit:

At this point, I am not sure if I am obtuse or python-cups is being annoying. Both printFile and createJob take a printer name as their first argument and python-cups seems to guess the printer-uri from that. However, its guesses seem wrong

cups.setServer('localhost')
cups.setPort(8000)
c = cups.Connection ()
print(c.printFile('lpne3',...
    print(c.printFile('lpne3',
          ^^^^^^^^^^^^^^^^^^^^
cups.IPPError: (1030, 'printer-uri ipp://localhost:8000/printers/lpne3 not found.')
michaelrsweet commented 10 months ago

Thank you for your answer.

  1. So cups-filters would have to learn to handle special "application/vnd.* MIME types if the printer supports them?

Yes, it just needs to add cupsFilter lines with the passthrough (-) filter for the other MIME media types.

  1. lprint itself can print them just fine but cups seems to insist on converting them before sending them to lprint.

Right, because CUPS doesn't know about these formats.

  1. Is it possible to use the cups library/APIs to talk to lprint? As far as I understand, I should be able to talk to lprint directly, since everything is IPP, but I hit some snags trying to do so. See below.

Yes.

michaelrsweet commented 10 months ago

WRT the Python CUPS library, it is highly optimized for talking to CUPS (thus the name) so the convenience methods are really only good for talking to CUPS. Some specific issues:

  1. lprint doesn't use the old CUPS "ipp://HOSTNAME/printers/PRINTERNAME" URI format that the Python print method is using, it uses the modern IPP "ipp://HOSTNAME/ipp/print/PRINTERNAME" format instead.
  2. lprint doesn't support the CUPS-Get-Devices operation that the Python getDevices method is using.

There is also a Python IPP library that can be used to submit IPP requests to lprint from Python, and of course you can use the standard C API provided with CUPS.

michaelrsweet commented 10 months ago

Oh, and of course you can always just run the lprint executable to print a file... :)

andreaskem commented 10 months ago

Maybe I should elaborate a bit:

The system I am working on is a pretty large software package that generates both "normal" files to print (PCL/PS/PDF) and EPL/ZPL for labels. Depending on our customer, this is handled by dozens of printers and can result in tens of thousands of printed pages and hundreds or even thousands of labels a day.

Different software modules generate labels or "regular" print files and all of them dump into a single "backend". In essence, the "backend" gets a printer name and a filename and that is it. The end result is little more than a call like lp -d <printer> <filename>. The printing process cares neither about the printer type nor about the file type and the printers are configured in the OS and Do the Right Thing with what they are given.

I assumed that the migration to CUPS would be trivial and that I could basically just configure the "regular" printers in CUPS and label printers in lprint, and fire off lp -d <printer> <filename>. CUPS would identify the file, query the printer (or printer application) for supported document types and pass through or convert as required.

From what I gather, it is not that simple, at least currently. I need to decide whether to talk to lprint directly or to cups based on either the file type or the printer type. Piping the file type or printer type through our codebase would be a complex task. My options are to identify the file as EPL/ZPL (e.g., starting with \nN\n), or to ask lprint whether it knows the printer, and use lprint directly in either case. Otherwise I need to send the file to CUPS. Now I need to decide whether to shell out (e.g. system/popen a shell script) or to use a library.

Maybe I can nag enough people to make everything as seemless and non-hacky as I would like it to be ;). I just hope that the legacy printer support will be less of an issue for me.

michaelrsweet commented 10 months ago

So one of the issues with generating and sending printer-ready data through CUPS is that you are basically bypassing a large part of CUPS in the process. CUPS is designed to take common, well-defined file formats and convert them (as needed) for the printer. In 2023, that means providing PDF files for printing which get converted to the printer's native format, sometimes in multiple steps (e.g. PDF to raster, raster to EPL/ZPL). So-called "raw" printing is poorly supported to begin with...

Assuming that you have all of the right MIME media types (and auto-typing rules) on your CUPS system, that the PPD file has the corresponding passthrough cupsFilter line in it, and that your files always match the rules on both the CUPS and lprint sides, then it should "just work". But it is a lot more work and very fragile compared to using PDF.