package org.example; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import org.glassfish.tyrus.server.Server; import MvCodeReaderCtrlWrapper.*; import MvCodeReaderCtrlWrapper.MvCodeReaderCtrl.*; import MvCodeReaderCtrlWrapper.MvCodeReaderCtrlDefine.*; import MvCodeReaderCtrlWrapper.ParameterException.*; import java.net.*; import java.io.*; public class Main { static Handle hHandle = null; // 保存所有读取到的设备列表 private static ArrayList allDevices = new ArrayList<>(); // 保存正在监听的设备列表 private static ArrayList activeDevices = new ArrayList<>(); // 获取所有读取到的设备列表JSON(推送给前端) public static String getAllDevicesJson() { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("type", "allDevices"); org.json.JSONArray arr = new org.json.JSONArray(); for (MV_CODEREADER_DEVICE_INFO camInfo : allDevices) { org.json.JSONObject dev = new org.json.JSONObject(); dev.put("id", camInfo.stGigEInfo.chSerialNumber); // 序列号 dev.put("name", camInfo.stGigEInfo.chUserDefinedName != null ? camInfo.stGigEInfo.chUserDefinedName : camInfo.stGigEInfo.chModelName); dev.put("model", camInfo.stGigEInfo.chModelName); // 型号 dev.put("manufacturer", camInfo.stGigEInfo.chManufacturerName); // 制造商 dev.put("ip", getIpAddress(camInfo.stGigEInfo.nCurrentIp)); // IP地址 dev.put("version", camInfo.stGigEInfo.chDeviceVersion); // 设备版本 dev.put("isActive", isDeviceActive(camInfo)); // 是否正在监听 arr.put(dev); } obj.put("devices", arr); obj.put("totalCount", allDevices.size()); // 设备总数 obj.put("activeCount", activeDevices.size()); // 活跃设备数 return obj.toString(); } // 检查设备是否正在监听 private static boolean isDeviceActive(MV_CODEREADER_DEVICE_INFO device) { for (MV_CODEREADER_DEVICE_INFO active : activeDevices) { if (active.stGigEInfo.chSerialNumber.equals(device.stGigEInfo.chSerialNumber)) { return true; } } return false; } // 将IP整数转换为字符串格式 private static String getIpAddress(int ipInt) { return ((ipInt & 0xff000000) >> 24) + "." + ((ipInt & 0x00ff0000) >> 16) + "." + ((ipInt & 0x0000ff00) >> 8) + "." + (ipInt & 0x000000ff); } public static void saveDataToFile(byte[] dataToSave, int dataSize, String fileName) { OutputStream os = null; try { // 创建保存目录 File tempFile = new File("saveImg"); if (!tempFile.exists()) { tempFile.mkdirs(); } os = new FileOutputStream("saveImg/" + fileName); os.write(dataToSave, 0, dataSize); System.out.println("图像保存成功: " + fileName); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭文件流 try { if (os != null) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } } // 回调函数 private static void printImgCBInfo(byte[] pdata, MV_CODEREADER_IMAGE_OUT_INFO_EX2 stOutInfo) { if (null == stOutInfo) { System.out.println("stOutInfo is null"); return; } System.out.print("/**CBpstOutInfo***************************************/\n"); System.out.print(String.format("获取一帧: nEventID[%d], nChannelID[%d], nWidth[%d], nHeight[%d], nFrameNum[%d], nTriggerIndex[%d], nFrameLen[%d], " + " nCodeNumber[%d] \r\n", stOutInfo.nEventID, stOutInfo.nChannelID, stOutInfo.nWidth, stOutInfo.nHeight, stOutInfo.nFrameNum, stOutInfo.nTriggerIndex, stOutInfo.nFrameLen, stOutInfo.pstCodeListEx.nCodeNum)); System.out.print("解码状态: bIsGetCode[" + stOutInfo.bIsGetCode + "]\r\n"); System.out.print("像素类型: MvCodeReaderGvspPixelType[" + stOutInfo.enPixelType + "]\r\n"); // 打印解码信息 for (int a = 0; a < stOutInfo.pstCodeListEx.nCodeNum; a++) { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("type", "scanMessage"); // 解析码中的数据,用下划线分割,第一个为物料类型,第二个为物料id String code = stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).chCode; String[] parts = code.split("__"); if (parts.length >= 2) { String itemType = parts[0]; String itemId = parts[1]; obj.put("itemType", itemType); obj.put("itemId", itemId); } else { obj.put("rawCode", code); obj.put("error", "格式不正确"); } WsServer.broadcast(obj.toString()); System.out.print(String.format("解码信息: TheCodeID[%d], CodeString[%s], nCodeLen[%d], nAngle[%d], nBarType[%d]," + "sAlgoCost[%d], nIDRScore[%d], n1DIsGetQuality[%d]\r\n", a, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).chCode, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).nLen, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).nAngle, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).nBarType, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).sAlgoCost, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).nIDRScore, stOutInfo.pstCodeListEx.stBcrInfoEx.get(a).n1DIsGetQuality)); } } private static void PrintDeviceInfo(MV_CODEREADER_DEVICE_INFO stCamInfo) { if (stCamInfo.nTLayerType == MvCodeReaderCtrlDefine.MV_CODEREADER_GIGE_DEVICE) { System.out.print("IP地址: " + getIpAddress(stCamInfo.stGigEInfo.nCurrentIp) + "\r\n"); System.out.print(String.format("设备信息: 自定义名称:[%s], 序列号:[%s], 型号:[%s] \r\n\r\n", stCamInfo.stGigEInfo.chUserDefinedName, stCamInfo.stGigEInfo.chSerialNumber, stCamInfo.stGigEInfo.chModelName)); } } public static void main(String[] args) throws InterruptedException { System.out.print(" ***************程序开始****************** \r\n"); String strVersion = MvCodeReaderCtrl.MV_CODEREADER_GetSDKVersion(); System.out.print("SDK版本: " + strVersion + "\r\n"); // 枚举所有设备 allDevices = MvCodeReaderCtrl.MV_CODEREADER_EnumDevices(); if (allDevices == null || allDevices.isEmpty()) { System.out.print("未发现任何设备!\r\n"); } else { System.out.print("发现" + allDevices.size() + "个设备:\r\n"); for (MV_CODEREADER_DEVICE_INFO device : allDevices) { PrintDeviceInfo(device); } } ArrayList handleList = new ArrayList<>(); // 尝试打开并启动所有发现的设备 for (int i = 0; i < allDevices.size(); i++) { MV_CODEREADER_DEVICE_INFO camInfo = allDevices.get(i); System.out.print("处理设备 " + i + ": " + camInfo.stGigEInfo.chSerialNumber + "\r\n"); Handle handle = null; try { handle = MvCodeReaderCtrl.MV_CODEREADER_CreateHandle(camInfo); } catch (ParameterException e) { System.out.print("创建句柄失败: " + e.getMessage() + "\r\n"); continue; } if (handle == null) { System.out.print("创建句柄失败 for device " + i + "!\r\n"); continue; } int nRet = MvCodeReaderCtrl.MV_CODEREADER_OpenDevice(handle); if (nRet != 0) { System.out.print("打开设备失败 for device " + i + "! 错误码[" + String.format("0x%x", nRet) + "]\r\n"); continue; } nRet = MvCodeReaderCtrl.MV_CODEREADER_RegisterImageCallBackEx2(handle, new ImageCallBack() { @Override public int OnImageCallBack(byte[] pdata, MV_CODEREADER_IMAGE_OUT_INFO_EX2 stOutInfo) { printImgCBInfo(pdata, stOutInfo); return 0; } }); if (nRet != 0) { System.out.print("注册回调失败 for device " + i + "! 错误码[" + String.format("0x%x", nRet) + "]\r\n"); MvCodeReaderCtrl.MV_CODEREADER_CloseDevice(handle); continue; } nRet = MvCodeReaderCtrl.MV_CODEREADER_StartGrabbing(handle); if (nRet != 0) { System.out.print("启动抓取失败 for device " + i + "! 错误码[" + String.format("0x%x", nRet) + "]\r\n"); MvCodeReaderCtrl.MV_CODEREADER_CloseDevice(handle); continue; } // 如果所有步骤都成功,添加到活跃设备列表 handleList.add(handle); activeDevices.add(camInfo); System.out.print("设备 " + i + " 启动成功,开始监听!\r\n"); } System.out.println("所有设备处理完毕。活跃设备数量: " + activeDevices.size() + "\r\n"); // 启动WebSocket服务器,用于向前端推送设备列表和扫描结果 Server server = new Server("localhost", 9000, "/", null, WsServer.class); try { server.start(); System.out.println("WebSocket服务器已启动,端口9000"); System.out.println("按Enter键退出程序..."); System.in.read(); // 阻塞主线程直到回车 } catch (Exception e) { System.out.println("WebSocket服务器错误: " + e.getMessage()); e.printStackTrace(); } finally { // 停止所有设备 System.out.println("停止所有设备..."); for (Handle handle : handleList) { MvCodeReaderCtrl.MV_CODEREADER_StopGrabbing(handle); MvCodeReaderCtrl.MV_CODEREADER_CloseDevice(handle); } server.stop(); System.out.println("程序已退出"); } } }