ipp-client-kotlin
A client implementation of the ipp protocol written in kotlin. RFCs 8010, 8011, 3995 and 3996
Usage
You may use ippfind
or other ZeroConf tools for discovery.
The CupsClient supports printer lookup by queue name.
Repository ipp-samples contains a kotlin example 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"),
media("iso_a4_210x297mm"),
copies(2),
numberUp(2),
pageRanges(2..3, 8..10),
printerResolution(300),
finishings(Punch, Staple),
IppPrintQuality.High,
IppColorMode.Monochrome,
IppSides.TwoSidedLongEdge,
IppMedia.Collection(source = "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()
// 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()
Printer Capabilities
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
IppRequest for IppResponse
exchangeval 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"])
CupsClient
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")
}
Print jpeg to 2" label printer
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)
)
)
Logging
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.consoleWriterEnabled = false
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("/ipp-client-logging.conf")
Slf4jAdapter.configure()
Source packages
Package
de.gmuth.ipp.core
contains the usual
encoding
and
decoding
operations. RFC 8010 is fully supported.
E.g. decode a cups spool file:
IppRequest().read(File("/var/spool/cups/c01579")).logDetails()
Package
de.gmuth.ipp.client
contains the
IppClient
which requires a
Http.Client
that implements HTTP:
e.g. HttpURLConnectionClient
or JavaHttpClient
Build
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.
Artifacts
Configure Gradle for use with Github Packages. Use this github package of the project as maven repo. You can access the repo with any github account. If you prefer to download a zip look for Release assets.
repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/gmuth/ipp-client-kotlin")
credentials {
// configure gpr.user and gpr.token in ~/.gradle/gradle.properties
// gpr.user=yourname
// gpr.token=yourtoken
username = project.findProperty("gpr.user") as String?
password = project.findProperty("gpr.token") as String?
}
}
}
Add dependency:
implementation("de.gmuth.ipp:ipp-client-kotlin:2.2")
or implementation("de.gmuth.ipp:ipp-client-kotlin:2.3-SNAPSHOT")