|
|
@@ -0,0 +1,195 @@
|
|
|
+package com.mes.print.monitor;
|
|
|
+
|
|
|
+import org.snmp4j.CommunityTarget;
|
|
|
+import org.snmp4j.PDU;
|
|
|
+import org.snmp4j.Snmp;
|
|
|
+import org.snmp4j.event.ResponseEvent;
|
|
|
+import org.snmp4j.mp.SnmpConstants;
|
|
|
+import org.snmp4j.smi.Address;
|
|
|
+import org.snmp4j.smi.GenericAddress;
|
|
|
+import org.snmp4j.smi.OID;
|
|
|
+import org.snmp4j.smi.OctetString;
|
|
|
+import org.snmp4j.smi.VariableBinding;
|
|
|
+import org.snmp4j.transport.DefaultUdpTransportMapping;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.ScheduledExecutorService;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 打印机 SNMP 监控器
|
|
|
+ * 通过 SNMP 协议监控 HP 打印机的物理打印完成状态
|
|
|
+ */
|
|
|
+public class PrinterMonitor {
|
|
|
+
|
|
|
+ // SNMP OID 定义
|
|
|
+ private static final String OID_PRINTER_LIFE_COUNT = "1.3.6.1.2.1.43.10.2.1.4.1.1"; // 总打印页数
|
|
|
+ private static final String OID_PRINTER_STATUS = "1.3.6.1.2.1.25.3.5.1.1.1"; // 打印机状态
|
|
|
+
|
|
|
+ private final String printerIp;
|
|
|
+ private final String community; // SNMP 团体名(默认 public)
|
|
|
+ private final int port;
|
|
|
+
|
|
|
+ private Snmp snmp;
|
|
|
+ private CommunityTarget target;
|
|
|
+ private ScheduledExecutorService scheduler;
|
|
|
+
|
|
|
+ public PrinterMonitor(String printerIp) {
|
|
|
+ this(printerIp, "public", 161);
|
|
|
+ }
|
|
|
+
|
|
|
+ public PrinterMonitor(String printerIp, String community, int port) {
|
|
|
+ this.printerIp = printerIp;
|
|
|
+ this.community = community;
|
|
|
+ this.port = port;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化 SNMP 连接
|
|
|
+ */
|
|
|
+ public void init() throws IOException {
|
|
|
+ DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
|
|
|
+ snmp = new Snmp(transport);
|
|
|
+ transport.listen();
|
|
|
+
|
|
|
+ Address targetAddress = GenericAddress.parse("udp:" + printerIp + "/" + port);
|
|
|
+ target = new CommunityTarget();
|
|
|
+ target.setCommunity(new OctetString(community));
|
|
|
+ target.setAddress(targetAddress);
|
|
|
+ target.setRetries(2);
|
|
|
+ target.setTimeout(1500);
|
|
|
+ target.setVersion(SnmpConstants.version2c);
|
|
|
+
|
|
|
+ scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
|
|
|
+ Thread t = new Thread(r, "PrinterMonitor-" + printerIp);
|
|
|
+ t.setDaemon(true);
|
|
|
+ return t;
|
|
|
+ });
|
|
|
+
|
|
|
+ System.out.println("[PrinterMonitor] 已连接到打印机:" + printerIp);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭监控
|
|
|
+ */
|
|
|
+ public void close() {
|
|
|
+ if (scheduler != null) {
|
|
|
+ scheduler.shutdownNow();
|
|
|
+ }
|
|
|
+ if (snmp != null) {
|
|
|
+ try {
|
|
|
+ snmp.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询打印机总页数计数器
|
|
|
+ */
|
|
|
+ public Long getPageCount() {
|
|
|
+ try {
|
|
|
+ PDU pdu = new PDU();
|
|
|
+ pdu.add(new VariableBinding(new OID(OID_PRINTER_LIFE_COUNT)));
|
|
|
+ pdu.setType(PDU.GET);
|
|
|
+
|
|
|
+ ResponseEvent event = snmp.send(pdu, target);
|
|
|
+ if (event != null && event.getResponse() != null) {
|
|
|
+ PDU response = event.getResponse();
|
|
|
+ if (response.getErrorStatus() == PDU.noError) {
|
|
|
+ VariableBinding vb = response.get(0);
|
|
|
+ return vb.getVariable().toLong();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("[PrinterMonitor] 查询页数失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询打印机状态
|
|
|
+ * @return 1=其他, 3=空闲, 4=打印中, 5=预热
|
|
|
+ */
|
|
|
+ public Integer getPrinterStatus() {
|
|
|
+ try {
|
|
|
+ PDU pdu = new PDU();
|
|
|
+ pdu.add(new VariableBinding(new OID(OID_PRINTER_STATUS)));
|
|
|
+ pdu.setType(PDU.GET);
|
|
|
+
|
|
|
+ ResponseEvent event = snmp.send(pdu, target);
|
|
|
+ if (event != null && event.getResponse() != null) {
|
|
|
+ PDU response = event.getResponse();
|
|
|
+ if (response.getErrorStatus() == PDU.noError) {
|
|
|
+ VariableBinding vb = response.get(0);
|
|
|
+ return vb.getVariable().toInt();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("[PrinterMonitor] 查询状态失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 监控打印完成(通过页数计数器变化检测)
|
|
|
+ *
|
|
|
+ * @param expectedPages 预期增加的页数(通常是 1)
|
|
|
+ * @param callback 完成回调
|
|
|
+ * @param timeoutSeconds 超时时间(秒)
|
|
|
+ */
|
|
|
+ public void waitForPrintComplete(int expectedPages, Runnable callback, int timeoutSeconds) {
|
|
|
+ Long baseCount = getPageCount();
|
|
|
+ if (baseCount == null) {
|
|
|
+ System.err.println("[PrinterMonitor] 无法获取初始页数,跳过监控");
|
|
|
+ callback.run();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println("[PrinterMonitor] 开始监控,当前页数=" + baseCount + ",预期增加=" + expectedPages);
|
|
|
+
|
|
|
+ final long startTime = System.currentTimeMillis();
|
|
|
+ final long targetCount = baseCount + expectedPages;
|
|
|
+
|
|
|
+ scheduler.scheduleAtFixedRate(() -> {
|
|
|
+ try {
|
|
|
+ // 检查超时
|
|
|
+ if (System.currentTimeMillis() - startTime > timeoutSeconds * 1000L) {
|
|
|
+ System.err.println("[PrinterMonitor] 监控超时(" + timeoutSeconds + "秒),停止监控");
|
|
|
+ scheduler.shutdown();
|
|
|
+ callback.run();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询当前页数
|
|
|
+ Long currentCount = getPageCount();
|
|
|
+ if (currentCount == null) {
|
|
|
+ return; // 查询失败,下次重试
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println("[PrinterMonitor] 当前页数=" + currentCount + ",目标=" + targetCount);
|
|
|
+
|
|
|
+ // 页数达到预期,打印完成
|
|
|
+ if (currentCount >= targetCount) {
|
|
|
+ System.out.println("[PrinterMonitor] 打印完成检测到!页数从 " + baseCount + " → " + currentCount);
|
|
|
+ scheduler.shutdown();
|
|
|
+ callback.run();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("[PrinterMonitor] 监控异常: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }, 0, 2, TimeUnit.SECONDS); // 每 2 秒查询一次
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试 SNMP 连接
|
|
|
+ */
|
|
|
+ public boolean testConnection() {
|
|
|
+ Long count = getPageCount();
|
|
|
+ Integer status = getPrinterStatus();
|
|
|
+ System.out.println("[PrinterMonitor] 测试连接 - 页数=" + count + ", 状态=" + status);
|
|
|
+ return count != null || status != null;
|
|
|
+ }
|
|
|
+}
|