Как получить уведомление от принтера о завершении физической страницы / задания
Я хотел бы иметь возможность получать уведомление от сетевого принтера, когда он физически заканчивает печать страницы (и / или всей работы). Это будет использоваться в приложении, которое я пишу, для управления печатью через Интернет, и так как пользователи получают плату за страницу, и плата не должна снижаться до того, как страница фактически завершится.
Я не уверен, что для этого нужно написать драйвер, какой-нибудь плагин или подойдет клиентское приложение. Я гибок с моей платформой, так как мой клиент еще не написан, поэтому я хотел бы услышать о любом подходящем решении в Windows или Linux, на любом языке программирования / уровне.
Я знаю, что между диспетчером очереди и принтером есть разница. Я пытаюсь выяснить, на каком уровне принтер может уведомить аппарат через IPP, когда страница или задание будут физически завершены.
В настоящее время я изучаю Java, используя пакет jspi или cups4j, чтобы получить уведомление, когда свойство IPP job-impressions-completed
изменения или, альтернативно, опрос для этого. Я использую интерфейс CUPS IPP для локального принтера. Запуск простого тестера (HelloPrint.java
прилагается ниже; или CupsTest.java
включены в cups4j), я не получил ни одного job-impressions-completed
атрибут не изменился, и при этом он не перечислял атрибут для работы, когда я проводил опрос.
Итак, вот вопросы:
- Я делаю это правильно? Если нет, то как мне это сделать?
- Поскольку это интерфейс CUPS к локальному принтеру, возможно,
job-impressions-completed
атрибут не обновляется, особенно потому, что он действует как спулер для реального принтера. Предполагая, что настоящий принтер будет уведомлять об этом атрибуте или перечислять его, будет ли это специфичным для принтера, или у любого принтера, поддерживающего IPP, этот атрибут будет доступен и обновлен?
Информация о системе: Ubuntu 11.10, CUPS 1.5.0, принтер Brother HL-2240D ( PPD доступен здесь)
Примечание: HL-2240D не тот принтер, который я буду использовать для возможного проекта (в частности, он не поддерживает IPP); Я собираюсь использовать HP HL4250DN, Samsung 3741ND или аналогичный.
Вот пример приложения с использованием javax.print
пакеты и JSPI:
HelloPrint.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import javax.print.event.*;
import de.lohndirekt.print.IppPrintService;
public class HelloPrint {
/**
* @param args
*/
public static void main(String[] args) {
// create request attributes
PrintRequestAttributeSet requestAttributeSet = new HashPrintRequestAttributeSet();
requestAttributeSet.add(MediaSizeName.ISO_A4);
requestAttributeSet.add(new Copies(1));
requestAttributeSet.add(Sides.DUPLEX);
// find an appropriate service
// using jspi (http://code.google.com/p/jspi/)
URI printerURI;
try {
printerURI = new URI("ipp://localhost:631/printers/HL2240D-local");
} catch (URISyntaxException e2) {
e2.printStackTrace();
return;
}
IppPrintService service = new IppPrintService(printerURI);
// by enumerating
// PrintService[] services = PrintServiceLookup.lookupPrintServices(
// DocFlavor.INPUT_STREAM.PDF, requestAttributeSet);
// for (PrintService service1 : services) {
// System.out.println(service1);
// }
// PrintService service = services[0];
// add listeners to service
service.addPrintServiceAttributeListener(new PrintServiceAttributeListener() {
@Override
public void attributeUpdate(PrintServiceAttributeEvent event) {
PrintServiceAttributeSet serviceAttributeSet = event
.getAttributes();
StringBuilder s = new StringBuilder();
s.append("=== PrintServiceAttributeEvent: (" + serviceAttributeSet.size() + " attributes)\n");
for (Attribute attribute : serviceAttributeSet.toArray()) {
PrintServiceAttribute printServiceAttribute = (PrintServiceAttribute) attribute;
s.append(printServiceAttribute.getCategory().getName()
+ "/" + printServiceAttribute.getName() + " = "
+ printServiceAttribute.toString() + "\n");
}
System.out.println(s.toString());
}
});
// add file (blank.pdf is a blank page exported as PDF from LibreOffice
// Writer)
FileInputStream inputStream;
try {
inputStream = new FileInputStream("blank.pdf");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
// create a new doc and job
DocAttributeSet docAttributeSet = new HashDocAttributeSet();
docAttributeSet.add(MediaSizeName.ISO_A4);
docAttributeSet.add(Sides.DUPLEX);
Doc doc = new SimpleDoc(inputStream, DocFlavor.INPUT_STREAM.PDF,
docAttributeSet);
DocPrintJob job = service.createPrintJob();
// listen to print job attribute change events
// attribute set is null, means this means to listen on all dynamic
// attributes that the job supports.
job.addPrintJobAttributeListener(new PrintJobAttributeListener() {
@Override
public void attributeUpdate(PrintJobAttributeEvent event) {
PrintJobAttributeSet jobAttributeSet = event.getAttributes();
StringBuilder s = new StringBuilder();
s.append("=== PrintJobAttributeEvent: (" + jobAttributeSet.size() + " attributes)\n");
for (Attribute attribute : jobAttributeSet.toArray()) {
PrintJobAttribute jobAttribute = (PrintJobAttribute) attribute;
s.append(jobAttribute.getCategory().getName() + "/"
+ jobAttribute.getName() + " = "
+ jobAttribute.toString() + "\n");
}
System.out.println(s.toString());
}
}, null);
// listen to print job events
job.addPrintJobListener(new PrintJobListener() {
@Override
public void printJobRequiresAttention(PrintJobEvent pje) {
System.out.println("=== PrintJobEvent: printJobRequiresAttention");
}
@Override
public void printJobNoMoreEvents(PrintJobEvent pje) {
// TODO Auto-generated method stub
System.out.println("=== PrintJobEvent: printJobNoMoreEvents");
System.out.println(pje.getPrintEventType());
System.out.println(pje.toString());
}
@Override
public void printJobFailed(PrintJobEvent pje) {
// TODO Auto-generated method stub
System.out.println("=== PrintJobEvent: printJobFailed");
System.out.println(pje.getPrintEventType());
System.out.println(pje.toString());
}
@Override
public void printJobCompleted(PrintJobEvent pje) {
// TODO Auto-generated method stub
System.out.println("=== PrintJobEvent: printJobCompleted");
System.out.println(pje.getPrintEventType());
System.out.println(pje.toString());
}
@Override
public void printJobCanceled(PrintJobEvent pje) {
// TODO Auto-generated method stub
System.out.println("=== PrintJobEvent: printJobCanceled");
System.out.println(pje.getPrintEventType());
System.out.println(pje.toString());
}
@Override
public void printDataTransferCompleted(PrintJobEvent pje) {
System.out.println("=== PrintJobEvent: printDataTransferCompleted");
System.out.println(pje.getPrintEventType());
System.out.println(pje.toString());
}
});
// print
try {
job.print(doc, requestAttributeSet);
} catch (PrintException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return;
}
// try polling
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
System.out.println("=== Polling: I'm alive and it's " + new Date());
System.out.println("Job attributes");
for (Attribute attribute : job.getAttributes().toArray()) {
System.out.println((attribute.getCategory().getName() + "/"
+ attribute.getName() + " = " + attribute.toString()));
}
System.out.println("Service attributes");
for (Attribute attribute : service.getAttributes().toArray()) {
System.out.println((attribute.getCategory().getName() + "/"
+ attribute.getName() + " = " + attribute.toString()));
}
}
}
}
1 ответ
В конце концов все зависит от прошивки принтеров. IPP указывает атрибут "задание-показ-выполнено" как необязательный. Это означает, что если принтер не может определить, какая страница была напечатана, вы не сможете ее прочитать - независимо от того, правильное ли у вас программирование или нет.
Производители обычно утверждают, что поддерживают IPP, но не очень хорошо документируют дополнительные детали, которые они могли реализовать (или нет).
Прежде чем приступить к программированию, я предлагаю прочитать все доступные задания с помощью ipptool
доступны от CUPS:
#!/usr/bin/env ipptool -tv -d job=482 ipp://192.168.2.113/ipp
{
OPERATION Get-Job-Attributes
GROUP operation-attributes-tag
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $uri
ATTR integer job-id $job
}
job-state
является обязательным атрибутом и через некоторое время должен достичь конечного состояния: completed
, aborted
или же canceled
, Это может быть достаточно, если вы можете получить количество рабочих страниц где-то еще:-)