2012-04-10 92 views
3

我希望能够在物理完成打印页面(和/或整个作业)时从网络打印机获得通知。这将用于我正在通过网络进行打印管理的应用程序,并且由于用户每页都收取费用,并且在页面实际完成之前不应停止收费。如何在物理页面/作业完成时从打印机获取通知

我不确定这是否需要编写驱动程序,某种插件或者客户端应用程序能否完成。我对我的平台很灵活,因为我的客户端还没有写入,所以我想在任何编程语言/级别的Windows或Linux中听到任何合适的解决方案。

我知道假脱机程序和打印机之间是有区别的。我试图检查打印机在哪个级别通过IPP通知机器何时完成页面或作业。

我正在调查Java,使用jspicups4j程序包获取IPP属性job-impressions-completed更改时的通知,或者轮询它。我正在使用本地打印机的CUPS IPP接口。运行一个简单的测试程序(HelloPrint.java附在下面;或包含在cups4j中),我没有收到任何job-impressions-completed属性更改,也没有列出我在投票时作业的属性。

所以这里的问题:

  • 要这么做吗?如果不是,那我该怎么做呢?
  • 由于这是CUPS接口到本地打印机,它可能是job-impressions-completed属性没有被更新,特别是因为它充当真正的打印机假脱机程序。假设真实打印机通知或列出此属性,这是打印机特定的还是必须任何支持IPP的打印机都可以使用此属性并进行更新?

系统信息:Ubuntu的11.10,CUPS 1.5.0,打印机是兄弟HL-2240D(PPD available here

注:HL-2240D是我将使用为最终项目打印机(具体而言,它不支持IPP);我打算使用HP HL4250DN或三星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())); 
      } 
     } 
    } 

} 
+0

嗯,我认为“我如何监控物理打印作业进度”是一个合适的问题。我考虑了你的意见,希望这个问题的版本更清晰(甚至可能会得到回答!) – Yuval 2012-04-12 15:01:13

+0

您的修改后的问题非常适合。感谢(大量)编辑;它现在好多了。 :) – 2012-04-12 15:45:03

+0

嗨Yuval,你能找到你的问题的答案? 我有同样的要求,并且找不到解决方案。 – 2012-08-27 23:20:17

回答

2

在这一切都取决于打印机固件结束。 IPP将属性作业印象完成指定为可选。这意味着如果打印机无法确定哪个页面已经打印完毕,您将无法读取它 - 无论您的编程是否正确。

制造商通常声称支持IPP,但没有很好地记录他们可能实施(或不实施)的可选部件。

之前做任何编程,我建议使用ipptool从CUPS读取所有可用的作业attrbutes:

#!/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是一个强制属性,一段时间后应达到最终状态:completedabortedcanceled。这可能是足够好的,如果你可以得到其他地方的工作页数:-)

+0

谢谢你。你有没有参考它在哪里说'job-impressions-completed'是可选的? – Yuval 2015-05-18 10:05:42

+0

[RFC 2911,Section 4.3](https://tools.ietf.org/html/rfc2911)职位描述特征: “如果[属性]没有被指定为REQUIRED,那么它是可选的” – 2015-10-02 10:22:16

相关问题