package com.whdc.service.impl; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import com.whdc.alarm.NVSSDK2; import com.whdc.alarm.NetClient2; import com.whdc.entity.AlarmRecord; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.File; import java.time.LocalDateTime; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Slf4j @Service public class VehicleDetectionService { @Value("${app.image-save-path}") private String imageSavePath; @Autowired private AlarmRecordService alarmRecordService; private int m_iLogonID = -1; private int m_iConnectID = -1; private boolean isRunning = false; private ExecutorService executorService; private String[] strCarPlateColor = new String[NVSSDK2.MAX_CAR_PLATE_COLOR]; private String[] strCarColor = new String[NVSSDK2.MAX_CAR_COLOR]; // @PostConstruct public void init() { executorService = Executors.newSingleThreadExecutor(); initValueString(); createImageDirectory(); startDetection(); } @PreDestroy public void destroy() { stopDetection(); if (executorService != null) { executorService.shutdown(); } } private void initValueString() { strCarPlateColor[0] = "unknown"; strCarPlateColor[1] = "white on blue"; strCarPlateColor[2] = "black on yellow"; strCarPlateColor[3] = "Black on white"; strCarPlateColor[4] = "black and white"; strCarPlateColor[5] = "white on green"; strCarColor[0] = "white"; strCarColor[1] = "red"; strCarColor[2] = "yellow"; // ... 其他颜色定义 } private void createImageDirectory() { File dir = new File(imageSavePath); if (!dir.exists()) { if (dir.mkdirs()) { System.out.println("创建图片保存目录成功: " + imageSavePath); } else { System.err.println("创建图片保存目录失败: " + imageSavePath); } } } public void startDetection() { if (isRunning) { return; } executorService.execute(() -> { try { isRunning = true; System.out.println("开始车辆检测..."); // SDK初始化 if (sdkInit() != 0) { System.err.println("SDK初始化失败"); return; } // 设备登录(这里需要根据实际情况配置) if (logonDevice("192.168.1.100", "admin", "password", 3000) != 0) { System.err.println("设备登录失败"); return; } // 开始抓拍 startSnap(); // 保持运行 while (isRunning) { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } catch (Exception e) { System.err.println("车辆检测服务异常: " + e.getMessage()); e.printStackTrace(); } finally { stopDetection(); } }); } public void stopDetection() { isRunning = false; if (m_iConnectID != -1) { NetClient2.StopRecv(m_iConnectID); m_iConnectID = -1; } if (m_iLogonID != -1) { NetClient2.Logoff(m_iLogonID); m_iLogonID = -1; } NetClient2.Cleanup(); System.out.println("车辆检测服务已停止"); } private int sdkInit() { NVSSDK2.SDK_VERSION ver = new NVSSDK2.SDK_VERSION(); int iRet = NetClient2.GetVersion(ver); System.out.println("[SDK_VERSION]" + ver.m_cVerInfo); // 设置回调函数 iRet = NetClient2.SetNotifyFunction( new NVSSDK2.MAIN_NOTIFY() { public void MainNotify(int iLogonID, int wParam, Pointer lParam, Pointer noitfyUserData) { // 处理主通知 } }, new NVSSDK2.ALARM_NOTIFY() { public void AlarmNotify(int iLogonID, int iChannel, int iAlarmState, int iAlarmType, Pointer pUserData) { // 处理告警通知 } }, new NVSSDK2.PARACHANGE_NOTIFY() { public void ParaChangeNotify(int iLogonID, int iChannel, int paraType, Pointer para, Pointer noitfyUserData) { // 处理参数变化通知 } } ); System.out.println("SetNotifyFunction(" + iRet + ")"); iRet = NetClient2.Startup(); System.out.println("Startup(" + iRet + ")"); return iRet; } private int logonDevice(String ip, String username, String password, int port) { m_iLogonID = NetClient2.Logon("", ip, username, password, "", port); // 等待登录成功 int retryCount = 0; while (retryCount < 30) { int logonStatus = NetClient2.GetLogonStatus(m_iLogonID); if (logonStatus == NVSSDK2.LOGON_SUCCESS) { log.info("设备登录成功: {}", ip); return 0; } else if (logonStatus == NVSSDK2.LOGON_FAILED) { System.err.println("设备登录失败: " + ip); return -1; } try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return -1; } retryCount++; } System.err.println("设备登录超时: " + ip); return -1; } private int startSnap() { NVSSDK2.NetPicPara tNetPicParam = new NVSSDK2.NetPicPara(); tNetPicParam.iStructLen = tNetPicParam.size(); tNetPicParam.iChannelNo = 0; tNetPicParam.cbkPicStreamNotify = new NVSSDK2.NET_PICSTREAM_NOTIFY() { public int PicDataNotify(int ulID, int lCommand, Pointer tInfo, int iLen, Pointer lpUserData) { return handlePicData(ulID, lCommand, tInfo, iLen, lpUserData); } }; tNetPicParam.pvUser = null; IntByReference pConnectID = new IntByReference(); int iRet = NetClient2.StartRecvNetPicStream(m_iLogonID, tNetPicParam, tNetPicParam.size(), pConnectID); if (iRet < 0) { m_iConnectID = -1; System.out.println("StartRecvNetPicStream Failed!"); return -1; } else { m_iConnectID = pConnectID.getValue(); System.out.println("StartRecvNetPicStream Success! ConnectID(" + m_iConnectID + ")"); return 0; } } private int handlePicData(int ulID, int lCommand, Pointer tInfo, int iLen, Pointer lpUserData) { if (lCommand != NVSSDK2.NET_PICSTREAM_CMD_ITS) { return 0; } try { NVSSDK2.ItsPicStream tItsPicStream = new NVSSDK2.ItsPicStream(); tItsPicStream.write(); Pointer pItsBuffer = tItsPicStream.getPointer(); byte[] RecvBuffer = tInfo.getByteArray(0, iLen); int iCopySize = Math.min(tItsPicStream.size(), iLen); pItsBuffer.write(0, RecvBuffer, 0, iCopySize); tItsPicStream.read(); String strIP = new String(tItsPicStream.cCameraIP).trim(); String strPlate = new String(tItsPicStream.cPlate).trim(); // 检测到车辆,生成告警 if (!strPlate.isEmpty() && !strPlate.equals("未知")) { log.info("检测到车辆闯入: {}, IP: {}", strPlate, strIP); // 保存图片 String imageFileName = saveVehicleImage(tItsPicStream); // 创建告警记录 createAlarmRecord(tItsPicStream, imageFileName); } } catch (Exception e) { System.err.println("处理图片数据异常: " + e.getMessage()); e.printStackTrace(); } return 0; } private String saveVehicleImage(NVSSDK2.ItsPicStream tItsPicStream) { String fileName = "vehicle_" + System.currentTimeMillis() + "_" + new String(tItsPicStream.cPlate).trim() + ".jpg"; String filePath = imageSavePath + File.separator + fileName; // 这里简化图片保存逻辑,实际需要根据SDK的图片数据结构来保存 try { // 实际实现需要根据tItsPicStream中的图片数据来保存 log.info("保存车辆图片: " + filePath); return fileName; } catch (Exception e) { System.err.println("保存车辆图片失败: " + e.getMessage()); return ""; } } private void createAlarmRecord(NVSSDK2.ItsPicStream tItsPicStream, String imageFileName) { try { AlarmRecord alarm = new AlarmRecord(); alarm.setCameraIP(new String(tItsPicStream.cCameraIP).trim()); alarm.setLicensePlate(new String(tItsPicStream.cPlate).trim()); alarm.setChannelID(tItsPicStream.iChannelID); alarm.setSpeed((double) tItsPicStream.fSpeed); alarm.setAlarmType(tItsPicStream.iAlarmType); alarm.setAlarmCode(new String(tItsPicStream.cAlarmCode).trim()); alarm.setImagePath(imageFileName); alarm.setAlarmTime(LocalDateTime.now()); // 设置车辆颜色 if (tItsPicStream.iCarColor >= 0 && tItsPicStream.iCarColor < strCarColor.length) { alarm.setCarColor(strCarColor[tItsPicStream.iCarColor]); } else { alarm.setCarColor("unknown"); } // 设置车牌颜色 if (tItsPicStream.iPlateColor >= 0 && tItsPicStream.iPlateColor < strCarPlateColor.length) { alarm.setPlateColor(strCarPlateColor[tItsPicStream.iPlateColor]); } else { alarm.setPlateColor("unknown"); } // 保存到数据库 alarmRecordService.saveAlarmRecord(alarm); log.info("告警记录保存成功: {}", alarm.getLicensePlate()); } catch (Exception e) { log.error("创建告警记录失败: {}", e.getMessage()); } } public boolean isRunning() { return isRunning; } }