2012-04-10 36 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

相關問題