Jak uzyskać powiadomienie od drukarki, gdy fizyczna strona / zadanie jest zakończone

Chciałbym móc otrzymywać powiadomienia z drukarki sieciowej, gdy fizycznie zakończy drukowanie strony (i / lub całego zadania). Będzie to używane w aplikacji, którą piszę do zarządzania drukowaniem przez Internet, a ponieważ użytkownicy są obciążani za stronę, a opłata nie powinna spadać, zanim strona rzeczywiście się zakończy.

Nie jestem pewien, czy wymaga to napisania sterownika, jakiegoś rodzaju wtyczki lub czy aplikacja kliencka będzie działać. Jestem elastyczny z moją platformą, ponieważ mój klient nie jest jeszcze napisany, więc chciałbym usłyszeć o każdym odpowiednim rozwiązaniu w systemie Windows lub Linux, w dowolnym języku / poziomie programowania.

Wiem, że istnieje różnica między buforowaniem a drukarką. Próbuję sprawdzić, na jakim poziomie drukarka może powiadomić maszynę za pośrednictwem protokołu IPP, gdy strona lub zadanie zostaną fizycznie ukończone.

Obecnie zajmuję się Java, korzystając z obujspi lubcups4j pakiet, aby uzyskać powiadomienie, gdy właściwość IPPjob-impressions-completed zmiany lub alternatywnie sonduj je. Używam interfejsu CUPS IPP do lokalnej drukarki. Uruchamianie prostego testera (HelloPrint.java dołączony poniżej; alboCupsTest.java zawarte w cups4j), nie otrzymałem żadnychjob-impressions-completed Zmienia się atrybut, ani nie wyszczególnił atrybutu dla zadania, gdy odpytałem.

Oto pytania:

Czy robię to dobrze? Jeśli nie, to jak mam to zrobić?Ponieważ jest to interfejs CUPS do drukarki lokalnej, może to być interfejsjob-impressions-completed atrybut nie jest aktualizowany, ponieważ działa jako bufor dla rzeczywistej drukarki. Zakładając, że prawdziwa drukarkabędzie powiadomienie o tym atrybucie lub wyświetlenie tego atrybutu, czy byłoby to specyficzne dla drukarki lubmusi każda drukarka obsługująca IPP ma ten atrybut dostępny i zaktualizowany?

Informacje o systemie: Ubuntu 11.10, CUPS 1.5.0, drukarka to Brother HL-2240D (PPD dostępne tutaj)

Uwaga: HL-2240D tonie drukarka, której będę używać do ewentualnego projektu (w szczególności nie obsługuje IPP); Zamierzam użyć HP HL4250DN lub Samsung 3741ND lub podobnego.

Oto przykładowa aplikacja korzystająca zjavax.print pakiety i jspi:

HelloPrint.java

<code>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()));
            }
        }
    }

}
</code>

questionAnswers(1)

yourAnswerToTheQuestion