A client implementation of the ipp protocol for java and kotlin. RFCs 8010, 8011, 3995 and 3996
You may use ippfind
or other ZeroConf tools for printer discovery.
The CupsClient supports printer lookup by queue name.
Repository ipp-samples contains examples how to use jmDNS.
IppPrinter and IppJob
// initialize printer connection and show printer attributes
val ippPrinter = IppPrinter(URI.create("ipp://colorjet.local/ipp/printer"))
ippPrinter.attributes.logDetails()
// marker levels
ippPrinter.markers.forEach { println(it) }
println("black: ${ippPrinter.marker(BLACK).levelPercent()} %")
// print file
val file = File("A4-ten-pages.pdf")
val job = ippPrinter.printJob(
file,
jobName(file.name),
jobPriority(30),
documentFormat("application/pdf"),
copies(2),
numberUp(2),
pageRanges(2..3, 8..10),
printerResolution(300),
finishings(Punch, Staple),
IppPrintQuality.High,
IppColorMode.Monochrome,
IppSides.TwoSidedLongEdge,
media("iso_a4_210x297mm"),
mediaColSource("tray-1"),
notifyEvents = listOf("job-state-changed", "job-stopped", "job-completed") // CUPS
)
job.logDetails()
job.subscription?.processEvents { println(it) }
// print remote file, make printer pull document from remote server
val remoteFile = URI.create("http://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
ippPrinter.printUri(remoteFile)
// create job and send document
val job = ippPrinter.createJob(jobName(file.name))
job.sendDocument(FileInputStream(file))
job.waitForTermination()
// manage jobs
ippPrinter.getJobs().forEach { println(it) }
ippPrinter.getJobs(IppWhichJobs.Completed)
val job = ippPrinter.getJob(4)
job.hold()
job.release()
job.cancel()
job.cupsGetDocuments() // CUPS only
// print operator
ippPrinter.pause()
ippPrinter.resume()
ippPrinter.sound() // identify printer
// subscribe and log events (e.g. from CUPS) for 1 minute
ippPrinter.createPrinterSubscription(60)
.processEvents()
IppPrinter
checks, if attribute values are supported by looking into '...-supported'
printer attributes.
documentFormat("application/pdf")
WARN: according to printer attributes value 'application/pdf' is not supported.
document-format-supported (1setOf mimeMediaType) = application/PCL,application/postscript
exchange IppRequest for IppResponse
val uri = URI.create("ipp://colorjet.local/ipp/printer")
val file = File("A4-blank.pdf")
val ippClient = IppClient()
val request = IppRequest(IppOperation.PrintJob, uri).apply {
// constructor adds 'attributes-charset', 'attributes-natural-language' and 'printer-uri'
operationGroup.attribute("document-format", IppTag.MimeMediaType, "application/pdf")
documentInputStream = FileInputStream(file)
}
val response = ippClient.exchange(request)
println(response.jobGroup["job-id"])
Use the CupsClient
to connect to a CUPS server.
If you want to access a cups queue you can construct an IppPrinter
from it's uri.
// connect to default ipp://localhost:631
val cupsClient = CupsClient()
// credentials (e.g. for remote connections)
cupsClient.basicAuth("admin", "secret")
// list all queues
cupsClient.getPrinters().forEach {
println("${it.name} -> ${it.printerUri}")
}
// list all completed jobs for queue
cupsClient.getPrinter("ColorJet_HP")
.getJobs(IppWhichJobs.Completed)
.forEach { println(it) }
// default printer
val defaultPrinter = cupsClient.getDefault()
// check capability
if(defaultPrinter.hasCapability(Capability.CanPrintInColor)) {
println("${defaultPrinter.name} can print in color")
}
// get canceled jobs and save documents
cupsClient.getJobsAndSaveDocuments(IppWhichJobs.Canceled)
val printer = IppPrinter(URI.create("ipp://192.168.2.64"))
val width = 2540 * 2 // hundreds of mm
val jpegFile = File("label.jpg")
val image = javax.imageio.ImageIO.read(jpegFile)
printer.printJob(
jpegFile, documentFormat("image/jpeg"),
IppMedia.Collection(
size = IppMedia.Size(width, width * image.height / image.width),
margins = IppMedia.Margins(0)
)
)
Log levels can be changed globally or individually.
The defaultLogLevel
must be changed before any constructor of a logger is called.
Logging.defaultLogLevel = Logging.LogLevel.ERROR
IppInputStream.log.logLevel = Logging.LogLevel.DEBUG
IppOutputStream.log.logLevel = Logging.LogLevel.TRACE
A simple stdout console writer is enabled by default and can be disabled.
Logging.disable()
You can configure the library to use Java Util Logging or Slf4j. Then the log levels must be configured according to the underlaying implementation (e.g. logback or Slf4j-Android).
JulAdapter.configure()
Slf4jAdapter.configure()
To build the jar make sure you have JDK 11 installed.
The default tasks build the jar in build/libs
.
./gradlew
To install the artifact to your local maven repository run
./gradlew publishToMavenLocal
This software has no dependencies to
javax.print,
CUPS or
ipptool.
Operation has mostly been tested for target jvm
. Android is supported since v1.6.
A Java Version 11 Runtime is only required if you want to use the Java 11 HttpClient.
The build produces the jar, sources and javadoc artifacts. They are available at maven central repository.
- group: gmuth.de
- artifact: ipp-client
- version: 2.4
Add dependency:
implementation("de.gmuth:ipp-client:2.4")
IPP is based on the exchange of binary messages via HTTP. For reading and writing binary data DataInputStream and DataOutputStream are used.
For the transport layer I've created a HTTP interface. By default implementation HttpURLConnectionClient is used which in turn uses javas HttpURLConnection.
Only java runtimes (including Android) provide implementations of these classes. The java standard libraries also provide support for SSL/TLS.
Package
de.gmuth.ipp.core
contains the usual
encoding
and
decoding
operations. RFC 8010 is fully supported.
Package
de.gmuth.ipp.client
contains the
IppClient
which requires a
Http.Client
that implements HTTP:
e.g. HttpURLConnectionClient
or JavaHttpClient