4

Вопрос по driver – Как получить уведомление от принтера о завершении физической страницы / задания

Я хотел бы иметь возможность получать уведомление от сетевого принтера, когда он физически заканчивает печать страницы (и / или всей работы). Это будет использоваться в приложении, которое я пишу, для управления печатью через Интернет, и так как пользователи получают плату за страницу, и плата не должна снижаться до фактического завершения страницы.

Я не уверен, что для этого нужно написать драйвер, какой-нибудь плагин или подойдет клиентское приложение. Я гибок с моей платформой, так как мой клиент еще не написан, поэтому я хотел бы услышать о любом подходящем решении в Windows или Linux, на любом языке программирования / уровне.

Мне известно, что между диспетчером очереди и принтером существует различие. Я пытаюсь выяснить, на каком уровне принтер может уведомлять аппарат через IPP о физическом завершении страницы или задания.

Я сейчас изучаю Java, используя либоjspi или жеcups4j пакет для получения уведомления, когда свойство IPPjob-impressions-completed  изменения или, альтернативно, опрос для этого. Я использую интерфейс CUPS IPP для локального принтера. Запуск простого тестера (HelloPrint.java прилагается ниже; илиCupsTest.java включены в cups4j), я не получил ни одногоjob-impressions-completed атрибут не изменился, и при этом он не перечислял атрибут для задания, когда я проводил опрос

Итак, вот вопросы:

  • Am doing this right? If not, then how should I do it?
  • Since this is a CUPS interface to a local printer, it might be that the job-impressions-completed attribute isn't being updated, specifically since it acts as a spooler for the real printer. Assuming that the real printer will notify about or list this attribute, Would this be printer-specific or must any IPP-supporting printer have this attribute available and updated?

Системная информация: Ubuntu 11.10, CUPS 1.5.0, принтер Brother HL-2240D (PPD доступен здесь)

Примечание: HL-2240D являетсяnot принтер, который я буду использовать для возможного проекта (в частности, он не поддерживает 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()));
            }
        }
    }

}

Привет Юваль, не могли бы вы найти ответ на свой вопрос? У меня точно такое же требование, и я пока не могу найти решение.

Aug 27, 2012, 11:20 PMот

Я сейчас вернусь к этому проекту. Я только что получил доступ к карте Kyocera KM-3530 с принтером (надеюсь, я правильно понял модель) и проверим, как с ней работать. Это волонтерский проект, и пройдет около месяца, прежде чем я успею обойти его, но я буду поддерживать связь и обновлять проблему.

Aug 29, 2012, 10:05 PMот

Ваш пересмотренный вопрос идеально подходит. Спасибо за (существенное) редактирование; это & APOS; s<i>much</i> теперь лучше. :)

Apr 12, 2012, 3:45 PMот

Ну, я думаю "как я могу отслеживать ход выполнения задания на печать"? это подходящий вопрос. Я учел ваши комментарии, и, надеюсь, эта версия вопроса будет более ясной (и, возможно, даже может быть дан ответ!)

Apr 12, 2012, 3:01 PMот

1ответ

2

В конце концов все зависит от прошивки принтеров.IPP specifies the attribute job-impressions-completed as optional, Это означает, что если принтер не может сказать, какая страница была напечатана, вы не сможете ее прочитать - независимо от того, правильное ли у вас программирование или нет.

Производители обычно утверждают, что поддерживают 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, Это может быть достаточно, если вы можете получить количество рабочих страниц где-то еще :-)

RelatedQuestions