Reputation: 9776
I have a device/appliance that you cannot install drivers for. I would like to add the ability to support network/IPP/AirPrint printers by having the user add the IP Addresses.
Since I am not printing through windows (which would use the IPP), how do I use IPP myself? Is there a c# client (or any windows library) out there that allows you to interact with IPP printers with the IPP protocol?
Upvotes: 12
Views: 29422
Reputation: 1124
There are a few IPP client implementations and IPP libraries available for different programming languages (java/php/python/c#). A practical solution could be to use the ipptool
available at https://openprinting.github.io/cups/. Create an ipp-command-file called printjob.ipp
:
{
OPERATION Print-Job
GROUP operation-attributes-tag
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $uri
FILE $filename
}
Now you should be able to print a PDF file using these options:
ipptool -tv -f mydoc.pdf ipp://192.168.2.207 printjob.ipp
Make sure the printer (or print server) supports the document format you send. I assume you're familiar with how to execute an external command in your application.
Even though the ipptool
is provided by CUPS it works perfect with any IPP printer. Check RFC 3510 or your printers documentation for the appropriate printer-uri-scheme or use ippfind
.
Experienced developers should be able to implement the print job operation in their preferred programming language and ecosystem. I have implemented the use case from above in kotlin with 100 lines of code: https://github.com/gmuth/ipp-printjob-kotlin. A Java Version is also available at https://github.com/gmuth/ipp-printjob-java
Update 2025:
This is a minimal implementation in C# returning the IPP response status code.
public static int PrintJob(Uri uri, FileInfo file)
{
WebRequest webRequest = WebRequest.Create(uri);
webRequest.Method = "POST";
webRequest.ContentType = "application/ipp";
var binaryWriter = new BinaryWriter(webRequest.GetRequestStream());
binaryWriter.Write(new byte[] { 1, 1, 0, 2, 0, 1, 0, 1, 1 });
WriteAttribute(0x47, "attributes-charset", "us-ascii");
WriteAttribute(0x48, "attributes-natural-language", "en");
WriteAttribute(0x45, "printer-uri", uri.ToString());
binaryWriter.Write((byte)3);
file.OpenRead().CopyTo(binaryWriter.BaseStream);
var binaryReader = new BinaryReader(webRequest.GetResponse().GetResponseStream());
binaryReader.ReadInt16();
return binaryReader.ReadByte() << 8 | binaryReader.ReadByte();
void WriteAttribute(byte tag, string name, string value)
{
binaryWriter.Write(new byte[] { tag, 0, (byte)name.Length });
binaryWriter.Write(Encoding.ASCII.GetBytes(name));
binaryWriter.Write(new byte[] { 0, (byte)value.Length });
binaryWriter.Write(Encoding.ASCII.GetBytes(value));
}
}
Upvotes: 10
Reputation: 90213
Meanwhile the IPP Sample Software (which includes ipptool
mentioned above) is a separate project on Github. It is now under the auspices of the Printer Working Group (PWG), the body which standardized IPP (Internet Printing Protocol).
While the software currently still is in beta, is already very functional. It ships two main command line tools:
ippserver
. Start it (with the appropriate options) and you will have a fully-fledged IPP server instance on your network, serving as virtual IPP printer (or an IPP server hosting multiple virtual IPP queues) which you can use to test any (or your self-written) IPP client software against.
ipptool
. This is an IPP client program which can send any combination of IPP requests to any IPP instance on the network (CUPS server, ippserver
, IPP-capable printer hardware) and validate its responses. The software ships with a few prepared text files containing example IPP requests, all with a .test
suffix for their filenames.
For your purpose, you could run these commands:
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print get-printer-attributes.test
.
This command will query any IPP printer about its supported IPP attributes.
This should include an item telling about its supposed IPP versions support.
For example reporting as ipp-versions-supported (1setOf keyword) = 1.0,1.1,2.0
.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-1.1.test
.
This command will run a complete validation suite against the printer to test for its real-world IPP-1.1 compliance.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-2.0.test
.
This command will run a complete validation suite against the printer to test for its real-world IPP-2.0 compliance.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-2.0.test
.
This command will run a complete validation suite against the printer to test for its real-world IPP-2.0 compliance.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-2.1.test
.
This command will run a complete validation suite against the printer to test for its real-world IPP-2.2 compliance.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-2.2.test
.
This command will run a complete validation suite against the printer to test for its real-world IPP-2.2 compliance.
ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-everywhere.test
.
This command will run a complete IPP Everywhere (which is the latest IPP Standard) validation suite against the printer to test for its real-world IPP Everywhere compliance.
To make this type of testing easy for you guys, I created a ready-made executable AppImage from the IPP Sample software that should be able to directly run (no "installation" needed!) on all x86_64 Linux distros.
You can use it on (almost) any Linux system without having CUPS or ippsample installed!
The AppImage has embedded all the major executable command line tools of the IPP Sample Software project. These exacutables will run as 'sub-commands' of the AppImage. See further down for examples.
Download:
wget https://github.com/KurtPfeifle/ippsample/releases/download/continuous/ippsample-x86_64.AppImage
Make AppImage executable (and optionally rename it to ippsample
):
chmod a+x ippsample-x86_64.AppImage
mv ippsample-x86_64.AppImage ippsample
Have a look at its built-in help screen:
./ippsample --ai-usage
Run it:
./ippsample ipptool -t -v ipp://xxx.xxx.xxx.xxx/ipp/print ipp-2.0.test
Find all IPP-capable printers nearby:
./ippsample ippfind
will yield s.th. like:
ipp://HPA0B3CCF051B9.local:631/ipp/printer
ipp://lenjessie2.local:8444/ipp/print
ipp://mbp14.papercut-ipv4.local:631/printers/OJ6500
ipp://mbp14.papercut-ipv4.local:631/printers/libreoffice-pin-code-drucker
Pick one printer, print a job:
./ippsample ipptool \
-tv \
-f ./printjob.pdf \
ipp://HPA0B3CCF051B9.local:631/ipp/printer \
print-job.test
Here is an (older) ASCIinema ascii-cast acting as an illustration of what I wrote about and how to use the IPP Sample Software (and its AppImage):
Upvotes: 4