311 lines
11 KiB
Java
311 lines
11 KiB
Java
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;
|
||
}
|
||
} |