init
parent
a4ef78b806
commit
3e56420861
55
pom.xml
55
pom.xml
|
|
@ -14,11 +14,17 @@
|
|||
<groupId>com.whdc</groupId>
|
||||
<artifactId>tiandy-service</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>视频</description>
|
||||
<modules>
|
||||
<module>ruoyi</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
|
@ -43,6 +49,10 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
|
|
@ -178,16 +188,11 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 使用spring-boot-maven-plugin打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.whdc.TiandyApplication</mainClass>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
@ -195,7 +200,43 @@
|
|||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>com.whdc.TiandyApplication</mainClass>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<!-- <build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <!– 使用spring-boot-maven-plugin打包 –>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <mainClass>com.whdc.TiandyApplication</mainClass>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>repackage</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!-- </build>-->
|
||||
</project>
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
package com.whdc.alarm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.whdc.alarm.NVSSDK2;
|
||||
import com.whdc.alarm.NetClient2;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
|
||||
|
||||
public class ItsSnap {
|
||||
|
||||
int m_iLogonID = -1;
|
||||
int m_iConnectID = -1;
|
||||
|
||||
String[] strCarPlateColor = new String[NVSSDK2.MAX_CAR_PLATE_COLOR];
|
||||
String[] strCarColor = new String[NVSSDK2.MAX_CAR_COLOR];
|
||||
|
||||
int iCount = 0;
|
||||
|
||||
NVSSDK2.MAIN_NOTIFY cbkMain = new NVSSDK2.MAIN_NOTIFY()
|
||||
{
|
||||
public void MainNotify(int iLogonID, int wParam, Pointer lParam,
|
||||
Pointer noitfyUserData) {
|
||||
|
||||
int iMsgType = wParam & 0xFFFF;
|
||||
switch (iMsgType) {
|
||||
case NVSSDK2.WCM_LOGON_NOTIFY:
|
||||
{
|
||||
try
|
||||
{
|
||||
int iLogonStatus = NetClient2.GetLogonStatus(iLogonID);
|
||||
NVSSDK2.ENCODERINFO tDevInfo = new NVSSDK2.ENCODERINFO();
|
||||
NetClient2.GetDevInfo(iLogonID, tDevInfo);
|
||||
|
||||
String strIP = new String(tDevInfo.m_cEncoder).trim();
|
||||
String strID = new String(tDevInfo.m_cFactoryID).trim();
|
||||
LogonNotify(strIP, strID, iLogonID, iLogonStatus);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void LogonNotify(String strIP, String strID, int iLogonID,
|
||||
int iLogonState) {
|
||||
String strMsg = new String();
|
||||
m_iLogonID = -1;
|
||||
switch (iLogonState) {
|
||||
case NVSSDK2.LOGON_SUCCESS: {
|
||||
m_iLogonID = iLogonID;
|
||||
strMsg = "LOGON_SUCCESS";
|
||||
break;
|
||||
}
|
||||
case NVSSDK2.LOGON_FAILED: {
|
||||
strMsg = "LOGON_FAILED";
|
||||
break;
|
||||
}
|
||||
case NVSSDK2.LOGON_TIMEOUT: {
|
||||
strMsg = "LOGON_TIMEOUT";
|
||||
break;
|
||||
}
|
||||
case NVSSDK2.LOGON_RETRY: {
|
||||
strMsg = "LOGON_RETRY";
|
||||
break;
|
||||
}
|
||||
case NVSSDK2.LOGON_ING: {
|
||||
strMsg = "LOGON_ING";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
System.out.println("[WCM_LOGON_NOTIFY][" + iLogonState + "] IP("
|
||||
+ strIP + "),ID(" + strID + "),LogonID(" + iLogonID + ")");
|
||||
}
|
||||
}
|
||||
System.out.println("[WCM_LOGON_NOTIFY][" + strMsg + "] IP(" + strIP
|
||||
+ "),ID(" + strID + "),LogonID(" + iLogonID + ")");
|
||||
}
|
||||
|
||||
NVSSDK2.ALARM_NOTIFY cbkAlarm = new NVSSDK2.ALARM_NOTIFY(){
|
||||
public void AlarmNotify(int _iLogonID, int _iChannel,
|
||||
int _iAlarmState, int _iAlarmType, Pointer _pUserData) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
NVSSDK2.PARACHANGE_NOTIFY cbkParaChange = new NVSSDK2.PARACHANGE_NOTIFY(){
|
||||
public void ParaChangeNotify(int iLogonID, int iChannel, int paraType,
|
||||
Pointer para, Pointer noitfyUserData) {
|
||||
}
|
||||
};
|
||||
NVSSDK2.RECVDATA_NOTIFY cbkRecvData = new NVSSDK2.RECVDATA_NOTIFY(){
|
||||
public void RecvDataNotify(int _ulID, Pointer data, int len, int _iFlag,
|
||||
Pointer _lpUserData) {
|
||||
System.out.println("[RECVDATA_NOTIFY] ConnID(" + _ulID + "),DataLen("
|
||||
+ len + ")");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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(cbkMain, cbkAlarm, cbkParaChange);
|
||||
System.out.println("SetNotifyFunction(" + iRet + ")");
|
||||
|
||||
iRet = NetClient2.Startup();
|
||||
System.out.println("Startup(" + iRet + ")");
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
public int LogonDevice()
|
||||
{
|
||||
Scanner scanIn = new Scanner(System.in);
|
||||
System.out.print("IP:" );
|
||||
String strIP = scanIn.next();
|
||||
System.out.print("UserName:" );
|
||||
String strUserName = scanIn.next();
|
||||
System.out.print("Password:" );
|
||||
String strPasswd = scanIn.next();
|
||||
System.out.print("Port:" );
|
||||
int iPort = 3000;
|
||||
|
||||
System.out.println("Logon" + strIP + ":" + 3000 + "-" +strUserName + "-" + strPasswd);
|
||||
while(true){
|
||||
m_iLogonID = NetClient2.Logon("", strIP, strUserName, strPasswd, "",iPort);
|
||||
int iLogonStatus = NetClient2.GetLogonStatus(m_iLogonID);
|
||||
if(iLogonStatus == NVSSDK2.LOGON_SUCCESS){
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.currentThread();
|
||||
Thread.sleep(1000);
|
||||
} catch(InterruptedException e) {
|
||||
System.err.println("Interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
public boolean createDir(String destDirName) {
|
||||
File dir = new File(destDirName);
|
||||
if (dir.exists()) {// Check if a directory exists
|
||||
System.out.println("Failed to create directory, target directory already exists!");
|
||||
return false;
|
||||
}
|
||||
if (!destDirName.endsWith(File.separator)) {// Whether it ends with "/"
|
||||
destDirName = destDirName + File.separator;
|
||||
}
|
||||
if (dir.mkdirs()) {//Create target directory
|
||||
System.out.println("Create directory successfully!" + destDirName);
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("Failed to create directory!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int SavePic(String FileName, Pointer pic, int len)
|
||||
{
|
||||
FileOutputStream fop = null;
|
||||
File file;
|
||||
|
||||
try {
|
||||
|
||||
|
||||
file = new File(FileName);
|
||||
fop = new FileOutputStream(file);
|
||||
|
||||
// if file doesnt exists, then create it
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
|
||||
// get the content in bytes
|
||||
byte[] contentInBytes = pic.getByteArray(0, len);
|
||||
|
||||
fop.write(contentInBytes);
|
||||
fop.flush();
|
||||
fop.close();
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (fop != null) {
|
||||
fop.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
NVSSDK2.NET_PICSTREAM_NOTIFY cbkPicData = new NVSSDK2.NET_PICSTREAM_NOTIFY(){
|
||||
public int PicDataNotify(int _ulID, int _lCommand, Pointer _tInfo, int _iLen,
|
||||
Pointer _lpUserData){
|
||||
|
||||
if(_lCommand != NVSSDK2.NET_PICSTREAM_CMD_ITS){
|
||||
System.out.println("PicDataNotify other Snap type " + _lCommand) ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
String strOutput = "PicDataNotify Snap Pic "+strIP+
|
||||
" iChannelID: " + tItsPicStream.iChannelID+
|
||||
" count:"+ tItsPicStream.iPicCount +
|
||||
" cPlate:" + strPlate;
|
||||
if(tItsPicStream.iCarColor >= 0 && tItsPicStream.iCarColor < NVSSDK2.MAX_CAR_COLOR) {
|
||||
strOutput += " Car Color:" + strCarColor[tItsPicStream.iCarColor];
|
||||
} else {
|
||||
strOutput += " Car Color:" + "unknown ";
|
||||
}
|
||||
|
||||
if(tItsPicStream.iPlateColor >= 0 && tItsPicStream.iPlateColor < NVSSDK2.MAX_CAR_PLATE_COLOR) {
|
||||
strOutput += " Plate Color:" + strCarPlateColor[tItsPicStream.iPlateColor];
|
||||
} else {
|
||||
strOutput += " Plate Color:" + "unknown ";
|
||||
}
|
||||
|
||||
System.out.println(strOutput) ;
|
||||
|
||||
if(tItsPicStream.iPicCount <= 0){
|
||||
System.out.println("error count " + tItsPicStream.iPicCount) ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
NVSSDK2.PicData[] tPicData = (NVSSDK2.PicData[])new NVSSDK2.PicData().toArray(8);
|
||||
for(int i = 0; i < tItsPicStream.iPicCount && i < 8; i++){
|
||||
tPicData[i].write();
|
||||
Pointer pPicBuffer = tPicData[i].getPointer();
|
||||
Pointer pData = tItsPicStream.tPicData[i];
|
||||
byte[] bBuffer = pData.getByteArray(0, tItsPicStream.iSize);
|
||||
int iPicSize = Math.min(tPicData[i].size(), tItsPicStream.iSize);
|
||||
pPicBuffer.write(0, bBuffer, 0, iPicSize);
|
||||
tPicData[i].read();
|
||||
}
|
||||
|
||||
int uiYear = tPicData[0].tPicTime.uiYear;
|
||||
int uiMonth = tPicData[0].tPicTime.uiMonth;
|
||||
int uiDay = tPicData[0].tPicTime.uiDay;
|
||||
int uiWeek = tPicData[0].tPicTime.uiWeek;
|
||||
int uiHour = tPicData[0].tPicTime.uiHour;
|
||||
int uiMinute = tPicData[0].tPicTime.uiMinute;
|
||||
int uiSecondsr = tPicData[0].tPicTime.uiSecondsr;
|
||||
int uiMilliseconds = tPicData[0].tPicTime.uiMilliseconds;
|
||||
|
||||
String strFileName = new String();
|
||||
strFileName +="ITS" + uiYear + "-"+ uiMonth + "-"+ uiDay + "-"+ uiWeek + "-"+ uiHour + "-"+ uiMinute+ "-"+ uiSecondsr + "-"+ uiMilliseconds;
|
||||
for(int i = 0; i < tItsPicStream.iPicCount && i < 8; i++){
|
||||
if(iCount > 2000)
|
||||
{
|
||||
System.out.println("save picture over 20000!") ;
|
||||
}
|
||||
SavePic("PIC/" + strFileName + "pic" + iCount + ".jpg", tPicData[i].pcPicData, tPicData[i].iDataLen);
|
||||
iCount++;
|
||||
}
|
||||
|
||||
NVSSDK2.PicData tPlatData = (NVSSDK2.PicData)new NVSSDK2.PicData();
|
||||
if(tItsPicStream.iPlatCount > 0) {
|
||||
tPlatData.write();
|
||||
Pointer pPicBuffer = tPlatData.getPointer();
|
||||
Pointer pData = tItsPicStream.tPlatData;
|
||||
byte[] bBuffer = pData.getByteArray(0, tItsPicStream.iSize);
|
||||
int iPicSize = Math.min(tPlatData.size(), tItsPicStream.iSize);
|
||||
pPicBuffer.write(0, bBuffer, 0, iPicSize);
|
||||
tPlatData.read();
|
||||
|
||||
SavePic("PIC/" + strFileName + "plat" + "CP" + ".jpg", tPlatData.pcPicData, tPlatData.iDataLen);
|
||||
}
|
||||
|
||||
NVSSDK2.PicData[] tFaceData = (NVSSDK2.PicData[])new NVSSDK2.PicData().toArray(3);
|
||||
for(int i = 0; i < tItsPicStream.iFaceCount && i < 8; i++){
|
||||
tFaceData[i].write();
|
||||
Pointer pPicBuffer = tFaceData[i].getPointer();
|
||||
Pointer pData = tItsPicStream.tPicData[i];
|
||||
byte[] bBuffer = pData.getByteArray(0, tItsPicStream.iSize);
|
||||
int iPicSize = Math.min(tFaceData[i].size(), tItsPicStream.iSize);
|
||||
pPicBuffer.write(0, bBuffer, 0, iPicSize);
|
||||
tFaceData[i].read();
|
||||
|
||||
SavePic("PIC/" + strFileName + "plat" + "RL" + + i + ".jpg", tFaceData[i].pcPicData, tFaceData[i].iDataLen);
|
||||
}
|
||||
|
||||
String strlog = "PicDataNotify Snap Pic" + "Pic" + tItsPicStream.iPicCount + "Plat" + tItsPicStream.iPlatCount + " Face" + tItsPicStream.iFaceCount;
|
||||
System.out.println(strlog) ;
|
||||
|
||||
String strBWPlateData = new String();
|
||||
if (tItsPicStream.pcBWPlateData != Pointer.NULL && tItsPicStream.iBWPlatePicLen > 0)
|
||||
{
|
||||
strBWPlateData = tItsPicStream.pcBWPlateData.getString(tItsPicStream.iBWPlatePicLen);
|
||||
}
|
||||
System.out.println("iPreset:" + tItsPicStream.iPreset + ",iArea:" + tItsPicStream.iArea + ",sOriginalImgWidth:" + tItsPicStream.sOriginalImgWidth
|
||||
+ ",pcBWPlateData:" + strBWPlateData + ",iRealImgWidth:" + tItsPicStream.iRealImgWidth + ",iRealImgHeight:" + tItsPicStream.iRealImgHeight
|
||||
+ ",iTargetType:" + tItsPicStream.iTargetType + ",iNewTargetType:" + tItsPicStream.iNewTargetType);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public int StartSnap()
|
||||
{
|
||||
NVSSDK2.NetPicPara tNetPicParam = new NVSSDK2.NetPicPara();
|
||||
tNetPicParam.iStructLen = tNetPicParam.size();
|
||||
tNetPicParam.iChannelNo = 0;
|
||||
tNetPicParam.cbkPicStreamNotify = cbkPicData; //Capture callback function
|
||||
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!");
|
||||
} else {
|
||||
m_iConnectID = pConnectID.getValue();
|
||||
System.out.println("StartRecvNetPicStream Success! ConnectID(" + m_iConnectID + ")");
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public int 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" ;
|
||||
strCarColor[3] = "yellow" ;
|
||||
strCarColor[4] = "blue" ;
|
||||
strCarColor[5] = "green" ;
|
||||
strCarColor[6] = "green" ;
|
||||
strCarColor[7] = "purple" ;
|
||||
strCarColor[8] = "pink" ;
|
||||
strCarColor[9] = "black" ;
|
||||
strCarColor[10] = "red" ;
|
||||
strCarColor[11] = "yellow" ;
|
||||
strCarColor[12] = "yellow" ;
|
||||
strCarColor[13] = "grey" ;
|
||||
strCarColor[14] = "yellow" ;
|
||||
strCarColor[15] = "blue" ;
|
||||
strCarColor[16] = "blue" ;
|
||||
strCarColor[17] = "green" ;
|
||||
strCarColor[18] = "green" ;
|
||||
strCarColor[19] = "white" ;
|
||||
strCarColor[20] = "green" ;
|
||||
strCarColor[21] = "cyan" ;
|
||||
strCarColor[22] = "yellow" ;
|
||||
strCarColor[23] = "red" ;
|
||||
strCarColor[24] = "blue" ;
|
||||
strCarColor[25] = "blue" ;
|
||||
strCarColor[26] = "grey" ;
|
||||
strCarColor[27] = "purple" ;
|
||||
strCarColor[28] = "purple" ;
|
||||
strCarColor[29] = "brown" ;
|
||||
strCarColor[30] = "brown" ;
|
||||
strCarColor[31] = "brown" ;
|
||||
return 0;
|
||||
};
|
||||
|
||||
public static void main(String args[])
|
||||
{
|
||||
ItsSnap tItsSnap = new ItsSnap();
|
||||
tItsSnap.createDir("PIC");//Create snapshot directory
|
||||
tItsSnap.InitValueString();
|
||||
tItsSnap.SDKInit(); //Initialize SDK
|
||||
tItsSnap.LogonDevice();//Log in to the device
|
||||
tItsSnap.StartSnap();//Connect image stream channel
|
||||
|
||||
while(true){
|
||||
try {
|
||||
Thread.currentThread();
|
||||
Thread.sleep(1000);
|
||||
} catch(InterruptedException e) {
|
||||
System.err.println("Interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,405 @@
|
|||
package com.whdc.alarm;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.Structure.ByValue;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
|
||||
import com.sun.jna.Callback;
|
||||
|
||||
public interface NVSSDK2 extends Library {
|
||||
|
||||
public static final int WM_USER = 0x0400; //
|
||||
|
||||
public static final int WM_MAIN_MESSAGE = WM_USER + 1001; // system information
|
||||
public static final int WM_PARACHG = WM_USER + 1002; // parameter change message
|
||||
public static final int WM_ALARM = WM_USER + 1003; // alarm message
|
||||
public static final int WCM_ERR_ORDER = 2;
|
||||
public static final int WCM_ERR_DATANET = 3;
|
||||
public static final int WCM_LOGON_NOTIFY = 7;
|
||||
public static final int WCM_VIDEO_HEAD = 8;
|
||||
public static final int WCM_VIDEO_DISCONNECT = 9;
|
||||
public static final int WCM_RECORD_ERR = 13;
|
||||
public static final int WCM_QUERYFILE_FINISHED = 18;
|
||||
public static final int WCM_DWONLOAD_FINISHED = 19;
|
||||
public static final int WCM_DWONLOAD_FAULT = 20;
|
||||
public static final int WCM_DOWNLOAD_INTERRUPT = 29;
|
||||
|
||||
public static final int LOGON_SUCCESS = 0;
|
||||
public static final int LOGON_ING = 1;
|
||||
public static final int LOGON_RETRY = 2;
|
||||
public static final int LOGON_DSMING = 3;
|
||||
public static final int LOGON_FAILED = 4;
|
||||
public static final int LOGON_TIMEOUT = 5;
|
||||
public static final int NOT_LOGON = 6;
|
||||
public static final int LOGON_DSMFAILED = 7;
|
||||
public static final int LOGON_DSMTIMEOUT = 8;
|
||||
public static final int PLAYER_PLAYING = 0x02;
|
||||
public static final int USER_ERROR = 0x10000000;
|
||||
|
||||
public static final int MOVE_UP = 1;
|
||||
public static final int MOVE_UP_STOP = 2;
|
||||
public static final int MOVE_DOWN = 3;
|
||||
public static final int MOVE_DOWN_STOP = 4;
|
||||
public static final int MOVE_LEFT = 5;
|
||||
public static final int MOVE_LEFT_STOP = 6;
|
||||
public static final int MOVE_RIGHT = 7;
|
||||
public static final int MOVE_RIGHT_STOP = 8;
|
||||
public static final int MOVE_UP_LEFT = 9;
|
||||
public static final int MOVE_UP_LEFT_STOP = 10;
|
||||
public static final int MOVE_UP_RIGHT = 11;
|
||||
public static final int MOVE_UP_RIGHT_STOP = 12;
|
||||
public static final int MOVE_DOWN_LEFT = 13;
|
||||
public static final int MOVE_DOWN_LEFT_STOP = 14;
|
||||
public static final int MOVE_DOWN_RIGHT = 15;
|
||||
public static final int MOVE_DOWN_RIGHT_STOP = 16;
|
||||
|
||||
public static final int HOR_AUTO = 21;
|
||||
public static final int HOR_AUTO_STOP = 22;
|
||||
|
||||
public static final int ZOOM_BIG = 31;
|
||||
public static final int ZOOM_BIG_STOP = 32;
|
||||
public static final int ZOOM_SMALL = 33;
|
||||
public static final int ZOOM_SMALL_STOP = 34;
|
||||
public static final int FOCUS_FAR = 35;
|
||||
public static final int FOCUS_FAR_STOP = 36;
|
||||
public static final int FOCUS_NEAR = 37;
|
||||
public static final int FOCUS_NEAR_STOP = 38;
|
||||
public static final int IRIS_OPEN = 39;
|
||||
public static final int IRIS_OPEN_STOP = 40;
|
||||
public static final int IRIS_CLOSE = 41;
|
||||
public static final int IRIS_CLOSE_STOP = 42;
|
||||
public static final int LIGHT_ON = 43;
|
||||
public static final int LIGHT_OFF = 44;
|
||||
public static final int POWER_ON = 45;
|
||||
public static final int POWER_OFF = 46;
|
||||
public static final int RAIN_ON = 47;
|
||||
public static final int RAIN_OFF = 48;
|
||||
|
||||
public static final int MOVE = 60;
|
||||
public static final int MOVE_STOP = 61;
|
||||
public static final int CALL_VIEW = 62;
|
||||
public static final int SET_VIEW = 63;
|
||||
|
||||
public static final int ALARM_VDO_MOTION = 0;
|
||||
public static final int ALARM_VDO_REC = 1;
|
||||
public static final int ALARM_VDO_LOST = 2;
|
||||
public static final int ALARM_VDO_INPORT = 3;
|
||||
public static final int ALARM_VDO_OUTPORT = 4;
|
||||
public static final int ALARM_VDO_COVER = 5;
|
||||
public static final int ALARM_VCA_INFO = 6; // Intelligent analysis of alarm information
|
||||
|
||||
public static final int T_AUDIO8 = 0;
|
||||
public static final int T_YUV420 = 1;
|
||||
public static final int T_YUV422 = 2;
|
||||
|
||||
public static final int NET_PICSTREAM_CMD_VCA = 1; //Callback VCA image stream information
|
||||
public static final int NET_PICSTREAM_CMD_ITS = 2; //Callback ITS image stream information
|
||||
public static final int NET_PICSTREAM_CMD_FACE = 3; //Callback face image stream information
|
||||
public static final int NET_PICSTREAM_CMD_NORMALSNAP = 4; //Callback normal snap image stream information
|
||||
|
||||
public static final int MAX_CAR_COLOR = 32;
|
||||
public static final int MAX_CAR_PLATE_COLOR = 6;
|
||||
|
||||
public static final int LEN_32 = 32;
|
||||
public static final int LEN_64 = 64;
|
||||
public static final int LEN_16 = 16;
|
||||
public static final int LEN_8 = 8;
|
||||
public static final int LEN_36 = 36;
|
||||
public static final int LEN_128 = 128;
|
||||
|
||||
public static class RECT_S extends Structure implements ByValue {
|
||||
public short sLeft;
|
||||
public short sRight;
|
||||
public short sTop;
|
||||
public short sBottom;
|
||||
}
|
||||
|
||||
public static class STRCT_BRAND extends Structure
|
||||
{
|
||||
public int uiBrandType; //Vehicle Brands
|
||||
public int uiSubBrand; //Vehicle sub-brand
|
||||
public int uiSubBrandYearStart;//Vehicle brand year model example: 2010-2013 or 2010
|
||||
public int uiSubBrandYearEnd;
|
||||
RECT stRectLogo; //Car logo coordinate rectangle
|
||||
public int uiConfid; //Confidence
|
||||
}
|
||||
|
||||
public static class RECT extends Structure implements ByValue {
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
}
|
||||
|
||||
public static class SDK_VERSION extends Structure {
|
||||
public short m_ulMajorVersion;
|
||||
public short m_ulMinorVersion;
|
||||
public short m_ulBuilder;
|
||||
public String m_cVerInfo;
|
||||
}
|
||||
|
||||
public static class CLIENTINFO extends Structure {
|
||||
public CLIENTINFO() {
|
||||
allocateMemory();
|
||||
}
|
||||
public int m_iServerID;
|
||||
public int m_iChannelNo;
|
||||
public byte[] m_cNetFile = new byte[255];
|
||||
public byte[] m_cRemoteIP = new byte[16];
|
||||
public int m_iNetMode;
|
||||
public int m_iTimeout;
|
||||
public int m_iTTL;
|
||||
public int m_iBufferCount;
|
||||
public int m_iDelayNum;
|
||||
public int m_iDelayTime;
|
||||
public int m_iStreamNO;
|
||||
public int m_iFlag;
|
||||
public int m_iPosition;
|
||||
public int m_iSpeed;
|
||||
}
|
||||
|
||||
|
||||
public static class ENCODERINFO extends Structure {
|
||||
public byte[] m_cHostName = new byte[32];
|
||||
public byte[] m_cEncoder = new byte[16];
|
||||
public int m_iRecvMode;
|
||||
public byte[] m_cProxy = new byte[16];
|
||||
public byte[] m_cFactoryID = new byte[32]; //ProductID
|
||||
public int m_iPort;//NVS port
|
||||
public int m_nvsType; //NVS type(NVS_T or NVS_S or DVR ...eg)
|
||||
public int m_iChanNum;
|
||||
public int m_iLogonState;
|
||||
public int m_iServerType;
|
||||
}
|
||||
|
||||
public static class PicTime extends Structure {
|
||||
|
||||
public int uiYear;
|
||||
public int uiMonth;
|
||||
public int uiDay;
|
||||
public int uiWeek;
|
||||
public int uiHour;
|
||||
public int uiMinute;
|
||||
public int uiSecondsr;
|
||||
public int uiMilliseconds;
|
||||
}
|
||||
|
||||
public static class PicData extends Structure {
|
||||
|
||||
public PicTime tPicTime;
|
||||
public int iDataLen;
|
||||
public Pointer pcPicData;
|
||||
}
|
||||
|
||||
public static class VcaPicStream extends Structure {
|
||||
|
||||
public int iStructLen;
|
||||
public int iWidth;
|
||||
public int iHeight;
|
||||
public int iChannelID;
|
||||
public int iEventType;
|
||||
public int iRuleID;
|
||||
public int iTargetID;
|
||||
public int iTargetType;
|
||||
public int iTargetSpeed;
|
||||
public int iTargetDirection;
|
||||
public RECT tTargetPosition;
|
||||
public int iPresetNo;
|
||||
public byte[] m_cRemoteIP = new byte[16];
|
||||
public int iPicCount;
|
||||
public PicData[] tPicData = new PicData[3];
|
||||
}
|
||||
|
||||
|
||||
public static class ItsPicStream extends Structure {
|
||||
|
||||
public int iStructLen; //Structure length
|
||||
public int iChannelID; //Lane number
|
||||
public byte[] cPlate = new byte[32]; //License plate
|
||||
public int iPlateColor; //License plate color
|
||||
public int iPlateType; //License plate type
|
||||
public int iCarColor; //the color of car
|
||||
public RECT tPlateRange; //License plate range
|
||||
public int iCharNum; //The number of characters in the license plate
|
||||
public int[] iCharConfid = new int[12]; //Each character confidence, up to 12 characters
|
||||
public int iPlateConfid; //The entire license plate confidence
|
||||
public int iRecrdoNum; //Identify picture serial number
|
||||
public float fSpeed; //Vehicle speed
|
||||
public int iVehicleDirection; //Direction of the vehicle
|
||||
public int iAlarmType; //Alarm type
|
||||
public byte[] cCameraIP = new byte[16]; //Camera IP
|
||||
public int iRedBeginTime; //Red light start time in seconds
|
||||
public int iRedEndTime; //Red light end time in seconds
|
||||
public int iPicCount; //Record the number of images included
|
||||
public int iSize;
|
||||
public Pointer[] tPicData = new Pointer[8];
|
||||
public int iPlatCount;
|
||||
public Pointer tPlatData;
|
||||
public int iFaceCount;
|
||||
public Pointer[] tFaceData= new Pointer[3];
|
||||
|
||||
public int iPreset; //(The Ball ) preset position number
|
||||
public int iArea; //(The Ball )Area number
|
||||
public byte[] cFileName = new byte[LEN_32]; //Video file name
|
||||
public int iCarSerialNum; //No. of parked vehicle
|
||||
public int iPictureNum; //No. of pictures of vehicles in violation of parking regulations
|
||||
public int iPicType; //Invalid field, no actual meaning
|
||||
public int iPlatePicLen; //Data length of small license plate
|
||||
public int iFacePicNum; //Number of small face pictures
|
||||
public byte[] cChannelName = new byte[LEN_64]; //Lane name
|
||||
public byte[] cChannelDirection = new byte[LEN_64]; //Lane direction
|
||||
public byte[] cCrossingID = new byte[LEN_64]; //Intersection number
|
||||
public byte[] cCrossingName = new byte[LEN_64]; //Intersection name
|
||||
public int iCarRegionNum; //Vehicle contour number, which determines which image tcarregion is based on, starting from 0, where 0 represents the first one.
|
||||
public RECT tCarRegion; //Vehicle contour coordinates, icarregionnum determines which image tcarregion is based on. Icarregionnum starts from 0, where 0 represents the first image.
|
||||
public int iTargetType; //Target type machine is not human ,Car model ( It is not recommended to use this field ,Suggested use iNewTargetType)
|
||||
public int[] iFacePicLen = new int[3]; //Face small graph length
|
||||
public int iRecordAttr; //Record attribute 0- General record ,1- Take the first record before and after ,2- Second records before and after capture
|
||||
public int iLinkageChannelNo; //Lane numbers for associated cameras ,Use before and after snapping
|
||||
public int iLinkageNo; //Linkage number, greater than 0 random number, the same camera linkage number before and after the same capture record, valid before and after pure video capture, others are - 1
|
||||
public byte[] cLinkageCameraIP = new byte[LEN_16]; //Linkage camera IP,Use before and after snapping
|
||||
public int iVehicleBrand; /*Auto Logos ,0:Unknown ;1:Public ;2:Audi ;3:Toyota ;4:Honda ;5:Benz ;6:Chevrolet ;7:Chery ;8:Buick ;9:The Great Wall ;10:modern ;11:NISSAN ;12:Ford ;
|
||||
13:BMW ;14:Citroen ;15:kIa ;16:Suzuki ;17:Mazda ;18:BYD ;20:Beautiful ;21:Changan ;22:LEXUS ;23:The ZH people ;24:SKODA ;25:A hippocampus ;26:Charade ;
|
||||
27:Wuling ;28:East wind ;29:Hafei ;30:FAW ;31:Bao Jun ;32:The Emperor ;33:The name of the name ;34:Southeast ;35:An crown ;36:Golden cup ;37:Mitsubishi ;38:Roewe ;
|
||||
39:Auspicious ;40:English ;41:global hawk ;42:Hafei Saibao ;43:Changfeng ;44:Wei Wang ;45:Beijing ;46:New Kay ;47:Gio ;48:Maserati ;49:rover ;50:Austen ;51:Ma's ;
|
||||
52:dodge ;54:General Pontiac ;55:Jaguar ;56:Ozzy's dawn ;57:alpha ;58:Lamborghini ;59:Bugatti ;60:Lincoln ;61:Ferrari ;62:Changhe ;63:Fiat ;64:Fukuda ;65:Eulogize ;
|
||||
66:Lotus flower ;67:Huapu ;68:red flag ;69:Riich ;70:Pentium ;71:Wei Lin ;72:Zhongtai ;73:Lifan ;74:Beijing jeep ;75:ZTE ;76:karry ;77:Land Rover ;78:Maybach ;
|
||||
79:Renault ;80:Opel ;81:Wild horse ;82:Jeep ;83:Iveco ;84:Infiniti ;85:Subaru ;86:Aston Martin ;87:An Kai ;88:Porsche ;89:Bentley ;90:Fudi ;91:Fujian ;92:Jim ;93:View ;
|
||||
94:Wide steam ;95:Shuanglong ;96:Hagrid ;97:Hummer ;98:Huatai ;99:Yellow Sea ;100:Kowloon ;101:Idea ;102:SMART;103:Land wind ;104:Na Ji Jie ;105:Oley ;106:Kai Chen ;
|
||||
107:Haversian ;108:HOWO ;109:The crowd ;110:golden dragon ;111:Golden brigades ;112:Yangtze and Huai rivers ;113:Jiangling ;114:Cadillac ;115:Cheetah ;116:Mini ;117:Shaanxi steam ;
|
||||
118:Shaolin Temple ;119:Volvo ;120:Isuzu ;121:Leap forward ;122:Yutong ;123:Zhong Tong ;124:Jinling ;125:Shen wo ;126:Yangzi River ;127:Tang Jun Ou Ling ;128:North Run ;129:Red Crag ;
|
||||
130:Rolls-Royce ;131:Tesla ;132:Teng potential ;133:Field ;134:English ;135:West Yat ;136:Star ;137:Daewoo ;138:Alex ;139:Kaye ;140:chase ;141:Shi Ming ;142:Kama. */
|
||||
public RECT_S tFaceRegion; //Face coordinates
|
||||
public int iAlgIllgalType; //Algorithm detecting illegal types ,bit0 No seat belt ,bit1 Phone
|
||||
public int iAlarmCode; //Illegal code,Old field, no longer maintained, please use cAlarmCode.
|
||||
public short sMergePicNum; //Picture synthesis information ,Photo synthesis number
|
||||
public short sMergeType; //Bit synthesis
|
||||
public short sMergePercent; //Synthesis ratio
|
||||
public short sMergeOSDSize; //Synthetic black edge height
|
||||
public short sMergeOSDType; //Synthetic black edge position ,0- Overlay in picture 1- Overlay in black box under picture 2- Overlay in black box on picture
|
||||
public short sSingleOSDSize; //Single black edge height
|
||||
public short sSingleOSDType; //Single black edge position ,0- Overlay in picture 1- Overlay in black box under picture 2- Overlay in black box on picture
|
||||
public short sOriginalImgWidth; //Source image width
|
||||
public short sOriginalImgHeight; //Source image height
|
||||
public RECT_S tVehicleRegion; //Vehicle logo coordinates, this field is valid only when supporting and opening the vehicle logo recognition function, indicating the coordinates of the vehicle logo, the image serial number based on iRecrdoNum determines, otherwise the field is invalid.
|
||||
public RECT_S tCopilotRegion; //Face coordinates of copilot
|
||||
public byte[] cCaptureTimeEx2 = new byte[5*LEN_8]; //Capture time of each picture: year, month, day, week, hour, minute, second and millisecond.
|
||||
public int[] iCaptureLenEx2 = new int[5]; //The length of each picture.
|
||||
public byte[] cUserDefChannelID = new byte[LEN_64]; //Lane customization number
|
||||
public short sBodyOfCarLeight; //Body length (cm)
|
||||
public byte[] cSecurityCode = new byte[LEN_8*LEN_36]; //Image security code
|
||||
public int iSpeedPercent; //Percentage of overspeed
|
||||
public byte[] cLinkPanoramaCapUUID = new byte[LEN_128]; //Linkage panoramic camera snapping linkage UID
|
||||
public int iRedBeginTimeMS; //Red light start time ( Millisecond )
|
||||
public int iRedEndTimeMS; //Red End ( Millisecond )
|
||||
public int iIPDCapType; //Violation of stop the illegal record capture type ,0 automatic ,1 Manual
|
||||
public byte[] cAlarmCode = new byte[LEN_16]; //Illegal code compatibility letter
|
||||
public int[] iCarFeatures = new int[2]; /*Vehicle characteristic attributes, such as hazardous chemicals vehicle, tissue box, etc., by bit, 64 bit is supported. Bit0: do not wear safety belt, Bit1: make a phone call, bit2: main driver's sunshade, bit3: copilot's sunshade,
|
||||
bit4: dangerous chemicals vehicle, bit5: yellow label vehicle, bit6: hanging, bit7: tissue box, bit8: annual inspection label, bit9: high beam lamp, bit10: abnormal license plate, bit11: window standing person.*/
|
||||
public STRCT_BRAND stBrandInfo; //Vehicle label information
|
||||
public int iMainDriverSex; //Driving sex ,0:Unknown ;1:Male ;2:Female sex.
|
||||
public int iCopilpt; //Co driving sex ,0:Unknown ;1:Male ;2:Female sex.
|
||||
public int iNewTargetType; /*Vehicle type ,0:Unknown model ;1:Hatchback car ;2:Sedan ;3:Coupe ;4:Small car ;5:Mini car ;6:MPV;7:SUV;8:Large bus ;9:Medium-sized passenger car ;10:Van ;11:Mini van ;12:Big truck ;13:Medium truck ;14:Fuel tank car ;15:crane ;
|
||||
16:Part of the car ;17:Van ;18:Pickup ;19:Micro card ;20:dogcart ;21:Tricycle ;22:pedestrian ;23:License plate deviation ;24:License plate detection ;25:Head of a car ;26:Tail of a car ;27:Automative lighting ;28:SUV/ MPV;29:trailer;
|
||||
100: bicycle; 101: electric vehicle; 102: motorcycle.*/
|
||||
public int iRealImgWidth; //image width ( Containing synthetic pictures )
|
||||
public int iRealImgHeight; //Image height ( Containing synthetic pictures )
|
||||
public int iBWPlatePicLen; //The data length of small license plate picture after two-value
|
||||
public Pointer pcBWPlateData; //Small license plate picture data after two-value
|
||||
|
||||
}
|
||||
|
||||
public static class PICSTREAM_INFO extends Structure {
|
||||
|
||||
public byte[] RecvBuffer = new byte[200*1024];//400 here should not be less than the maximum alarm message length
|
||||
}
|
||||
|
||||
|
||||
public static interface MAIN_NOTIFY extends Callback {
|
||||
void MainNotify(int _iLogonID, int _iwParam, Pointer _ilParam,
|
||||
Pointer _pUserData);
|
||||
}
|
||||
|
||||
public static interface ALARM_NOTIFY extends Callback {
|
||||
void AlarmNotify(int _iLogonID, int _iChannel,
|
||||
int _iAlarmState, int _iAlarmType, Pointer _pUserData);
|
||||
}
|
||||
|
||||
public static interface PARACHANGE_NOTIFY extends Callback {
|
||||
void ParaChangeNotify(int _iLogonID, int _iChannel, int _iParaType,
|
||||
Pointer _strPara, Pointer _pUserData);
|
||||
}
|
||||
|
||||
public static interface COMRECV_NOTIFY extends Callback {
|
||||
void ComRecvNotify(int _iLogonID, Pointer _pData, int _iLen,
|
||||
int _iComNo, Pointer _pUserData);
|
||||
}
|
||||
|
||||
public static interface PROXY_NOTIFY extends Callback {
|
||||
void ProxyNotify(int _iLogonID, int _iCmdKey, Pointer _pData,
|
||||
int _iLen, Pointer _pUserData);
|
||||
}
|
||||
|
||||
public static interface RECVDATA_NOTIFY extends StdCallCallback {
|
||||
void RecvDataNotify(int _ulID, Pointer _ucData, int _iLen, int _iFlag,
|
||||
Pointer _lpUserData);
|
||||
}
|
||||
|
||||
public static interface NET_PICSTREAM_NOTIFY extends StdCallCallback {
|
||||
int PicDataNotify(int _ulID, int _lCommand, Pointer _tInfo, int _iLen,
|
||||
Pointer _lpUserData);
|
||||
}
|
||||
|
||||
public static class NetPicPara extends Structure {
|
||||
public int iStructLen; //Structure length
|
||||
public int iChannelNo;
|
||||
public NET_PICSTREAM_NOTIFY cbkPicStreamNotify;
|
||||
public Pointer pvUser;
|
||||
}
|
||||
|
||||
public static class PointerSize extends Structure {
|
||||
public Pointer pPointer;
|
||||
}
|
||||
|
||||
|
||||
int NetClient_GetVersion(SDK_VERSION _ver);
|
||||
|
||||
int NetClient_SetNotifyFunction_V4(MAIN_NOTIFY _cbkMainNotify,
|
||||
ALARM_NOTIFY _cbkAlarmNotify,
|
||||
PARACHANGE_NOTIFY _cbkParaChangeNotify,
|
||||
COMRECV_NOTIFY _cbkComRecv,
|
||||
PROXY_NOTIFY _cbkProxyNotify);
|
||||
|
||||
int NetClient_SetPort(int _iServerPort, int _iClientPort);
|
||||
|
||||
int NetClient_Startup_V4(int _iServerPort, int _iClientPort, int _iWnd);
|
||||
|
||||
int NetClient_Cleanup();
|
||||
|
||||
int NetClient_Logon(String _cProxy, String _cIP, String _cUserName,
|
||||
String _cPassword, String _pcProID, int _iPort);
|
||||
|
||||
int NetClient_Logoff(int _iLogonID);
|
||||
|
||||
int NetClient_StartRecvEx(IntByReference _ulConID, CLIENTINFO _cltInfo,
|
||||
RECVDATA_NOTIFY _cbkDataNotify, Pointer _pUserData);
|
||||
|
||||
int NetClient_StartRecvNetPicStream(int _iLogonID, NetPicPara _ptPara, int _iBufLen, IntByReference _puiRecvID);
|
||||
|
||||
int NetClient_StopRecv(int _ulConID);
|
||||
|
||||
int NetClient_StartCaptureData(int _ulConID);
|
||||
|
||||
int NetClient_StartPlay(int _ulConID, int _hWnd, RECT _rcShow, int _iDecflag);
|
||||
|
||||
int NetClient_StopPlay(int _ulConID);
|
||||
|
||||
int NetClient_StartCaptureFile(int _ulConID, String _cFileName,
|
||||
int _iRecFileType);
|
||||
|
||||
int NetClient_StopCaptureFile(int _ulConID);
|
||||
int NetClient_GetLogonStatus(int _iLogonID);
|
||||
int NetClient_GetDevInfo(int _iLogonID,ENCODERINFO _pEncoderInfo);
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.whdc.alarm;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import com.whdc.playback.NVSSDK;
|
||||
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
|
||||
public class NetClient2 {
|
||||
|
||||
private static NVSSDK2 nvssdk = (NVSSDK2)(System.getProperty("os.name").toLowerCase().startsWith("win")?Native.loadLibrary("NVSSDK.dll",NVSSDK.class):Native.loadLibrary("libnvssdk.so", NVSSDK.class));
|
||||
|
||||
public static int GetVersion(NVSSDK2.SDK_VERSION _ver) {
|
||||
return nvssdk.NetClient_GetVersion(_ver);
|
||||
}
|
||||
|
||||
public static int SetNotifyFunction(NVSSDK2.MAIN_NOTIFY _cbkMainNotify,
|
||||
NVSSDK2.ALARM_NOTIFY _cbkAlarmNotify, NVSSDK2.PARACHANGE_NOTIFY _cbkParaChangeNotify) {
|
||||
return nvssdk.NetClient_SetNotifyFunction_V4(_cbkMainNotify, _cbkAlarmNotify, _cbkParaChangeNotify, null, null);
|
||||
}
|
||||
|
||||
public static int SetPort(int _iServerPort, int _iClientPort) {
|
||||
return nvssdk
|
||||
.NetClient_SetPort(_iServerPort, _iClientPort);
|
||||
}
|
||||
|
||||
public static int Startup() {
|
||||
return nvssdk.NetClient_Startup_V4(0, 0, 0);
|
||||
}
|
||||
|
||||
public static int Cleanup() {
|
||||
return nvssdk.NetClient_Cleanup();
|
||||
}
|
||||
|
||||
public static int Logon(String _cProxy, String _cIP, String _cUserName,
|
||||
String _cPassword, String _pcProID, int _iPort) {
|
||||
return nvssdk.NetClient_Logon(_cProxy, _cIP, _cUserName,
|
||||
_cPassword, _pcProID, _iPort);
|
||||
}
|
||||
|
||||
public static int Logoff(int _iLogonID) {
|
||||
return nvssdk.NetClient_Logoff(_iLogonID);
|
||||
}
|
||||
|
||||
public static int StartRecv(IntByReference _ulConID, NVSSDK2.CLIENTINFO _cltInfo,
|
||||
NVSSDK2.RECVDATA_NOTIFY _cbkDataNotify) {
|
||||
return nvssdk.NetClient_StartRecvEx(_ulConID, _cltInfo,
|
||||
_cbkDataNotify, Pointer.NULL);
|
||||
}
|
||||
|
||||
public static int StopRecv(int _ulConID) {
|
||||
return nvssdk.NetClient_StopRecv(_ulConID);
|
||||
}
|
||||
|
||||
public static int StartCaptureData(int _ulConID) {
|
||||
return nvssdk.NetClient_StartCaptureData(_ulConID);
|
||||
}
|
||||
|
||||
public static int StartPlay(int _ulConID, Component _hWnd, int _iDecflag) {
|
||||
int hWnd = (int) Native.getComponentID(_hWnd);
|
||||
NVSSDK2.RECT rcShow = new NVSSDK2.RECT();
|
||||
return nvssdk.NetClient_StartPlay(_ulConID, hWnd, rcShow,
|
||||
_iDecflag);
|
||||
}
|
||||
|
||||
public static int StopPlay(int _ulConID) {
|
||||
return nvssdk.NetClient_StopPlay(_ulConID);
|
||||
}
|
||||
|
||||
public static int StartCaptureFile(int _ulConID, String _cFileName,
|
||||
int _iRecFileType) {
|
||||
return nvssdk.NetClient_StartCaptureFile(_ulConID,
|
||||
_cFileName, _iRecFileType);
|
||||
}
|
||||
|
||||
public static int StopCaptureFile(int _ulConID) {
|
||||
return nvssdk.NetClient_StopCaptureFile(_ulConID);
|
||||
}
|
||||
|
||||
public static int StartRecvNetPicStream(int _iLogonID, NVSSDK2.NetPicPara _ptPara, int _iBufLen, IntByReference _puiRecvID) {
|
||||
return nvssdk.NetClient_StartRecvNetPicStream(_iLogonID, _ptPara, _iBufLen, _puiRecvID);
|
||||
}
|
||||
|
||||
public static int GetLogonStatus(int _iLogonID) {
|
||||
return nvssdk.NetClient_GetLogonStatus(_iLogonID);
|
||||
}
|
||||
|
||||
public static int GetDevInfo(int _iLogonID , NVSSDK2.ENCODERINFO _pEncoderInfo) {
|
||||
return nvssdk.NetClient_GetDevInfo(_iLogonID, _pEncoderInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.whdc.service.impl.AlarmRecordService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/alarms")
|
||||
public class AlarmRecordController {
|
||||
|
||||
@Autowired
|
||||
private AlarmRecordService alarmRecordService;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.whdc.dto.ApiResponse;
|
||||
import com.whdc.dto.PlaybackRequest;
|
||||
import com.whdc.service.impl.PlaybackService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/playback")
|
||||
public class PlaybackController {
|
||||
|
||||
@Autowired
|
||||
private PlaybackService playbackService;
|
||||
|
||||
@PostMapping("/start")
|
||||
public ApiResponse<Map<String, Object>> startPlayback(@RequestBody PlaybackRequest request) {
|
||||
try {
|
||||
Map<String, Object> result = playbackService.startPlayback(request);
|
||||
return ApiResponse.success("回放启动成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("回放启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/stop/{playbackId}")
|
||||
public ApiResponse<Boolean> stopPlayback(@PathVariable String playbackId) {
|
||||
try {
|
||||
boolean result = playbackService.stopPlayback(playbackId);
|
||||
return ApiResponse.success("回放停止成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("回放停止失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/status/{playbackId}")
|
||||
public ApiResponse<Map<String, Object>> getPlaybackStatus(@PathVariable String playbackId) {
|
||||
try {
|
||||
Map<String, Object> status = playbackService.getPlaybackStatus(playbackId);
|
||||
return ApiResponse.success("获取回放状态成功", status);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("获取回放状态失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.whdc.service.impl.VehicleDetectionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/detection")
|
||||
public class VehicleDetectionController {
|
||||
|
||||
@Autowired
|
||||
private VehicleDetectionService vehicleDetectionService;
|
||||
|
||||
@PostMapping("/start")
|
||||
public ResponseEntity<String> startDetection() {
|
||||
vehicleDetectionService.startDetection();
|
||||
return ResponseEntity.ok("车辆检测已启动");
|
||||
}
|
||||
|
||||
@PostMapping("/stop")
|
||||
public ResponseEntity<String> stopDetection() {
|
||||
vehicleDetectionService.stopDetection();
|
||||
return ResponseEntity.ok("车辆检测已停止");
|
||||
}
|
||||
|
||||
@GetMapping("/status")
|
||||
public ResponseEntity<Boolean> getDetectionStatus() {
|
||||
boolean isRunning = vehicleDetectionService.isRunning();
|
||||
return ResponseEntity.ok(isRunning);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.whdc.callback.RawFrameCallback;
|
||||
import com.whdc.dto.*;
|
||||
import com.whdc.dto.ApiResponse;
|
||||
import com.whdc.dto.PTZControlRequest;
|
||||
import com.whdc.dto.StartStreamRequest;
|
||||
import com.whdc.service.impl.VideoStreamService;
|
||||
import com.whdc.service.impl.VideoSurveillanceService;
|
||||
import com.whdc.video.NVSSDK1;
|
||||
|
|
@ -35,7 +37,7 @@ public class VideoController {
|
|||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<String> login(@RequestBody LoginRequest request) {
|
||||
public ApiResponse<String> login(@RequestBody com.whdc.dto.LoginRequest request) {
|
||||
try {
|
||||
boolean success = videoService.login(
|
||||
request.getIp(),
|
||||
|
|
@ -75,7 +77,7 @@ public class VideoController {
|
|||
// 设置原始流回调
|
||||
videoService.setRawFrameCallback(currentConnectId, new RawFrameCallback() {
|
||||
@Override
|
||||
public void onRawFrameReceived(int connectId, byte[] data, RawFrameInfo frameInfo) {
|
||||
public void onRawFrameReceived(int connectId, byte[] data, com.whdc.dto.RawFrameInfo frameInfo) {
|
||||
// 只处理视频帧
|
||||
if (frameInfo.getFrameType() == NVSSDK1.VI_FRAME ||
|
||||
frameInfo.getFrameType() == NVSSDK1.VP_FRAME) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.whdc.dto.ApiResponse;
|
||||
import com.whdc.dto.LoginRequest;
|
||||
import com.whdc.dto.StartStreamRequest;
|
||||
import com.whdc.service.impl.VideoPlayService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/video/play")
|
||||
public class VideoPlayController {
|
||||
|
||||
@Autowired
|
||||
private VideoPlayService videoPlayService;
|
||||
|
||||
@PostMapping("/init")
|
||||
public ApiResponse<Boolean> initSDK() {
|
||||
try {
|
||||
boolean result = videoPlayService.initSDK();
|
||||
return ApiResponse.success("SDK初始化成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("SDK初始化失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<Integer> login(@RequestBody LoginRequest request) {
|
||||
try {
|
||||
int logonId = videoPlayService.login(
|
||||
request.getIp(),
|
||||
request.getPort(),
|
||||
request.getUsername(),
|
||||
request.getPassword()
|
||||
);
|
||||
return ApiResponse.success("登录成功", logonId);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("登录失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/stream/start")
|
||||
public ApiResponse<String> startPlay(@RequestBody StartStreamRequest request) {
|
||||
try {
|
||||
String streamId = videoPlayService.startStream(
|
||||
request.getM_iServerID(),
|
||||
request.getChannelNo(),
|
||||
request.getStreamType(),
|
||||
request.getNetMode()
|
||||
);
|
||||
return ApiResponse.success("视频流启动成功", streamId);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("启动视频流失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/stream/stop/{streamId}")
|
||||
public ApiResponse<Boolean> stopstream(@PathVariable String streamId) {
|
||||
try {
|
||||
boolean result = videoPlayService.stopStream(streamId);
|
||||
return ApiResponse.success("视频流停止成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("停止视频流失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/logout/{logonId}")
|
||||
public ApiResponse<Boolean> logout(@PathVariable int logonId) {
|
||||
try {
|
||||
boolean result = videoPlayService.logout(logonId);
|
||||
return ApiResponse.success("登出成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("登出失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/cleanup")
|
||||
public ApiResponse<Boolean> cleanup() {
|
||||
try {
|
||||
boolean result = videoPlayService.cleanup();
|
||||
return ApiResponse.success("SDK清理成功", result);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error("SDK清理失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.whdc.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PlaybackRequest {
|
||||
private String deviceIp;
|
||||
private Integer devicePort;
|
||||
private String username;
|
||||
private String password;
|
||||
private Integer channelNo;
|
||||
private Date startTime;
|
||||
private Date endTime;
|
||||
private Integer streamType = 0; // 0-主码流, 1-子码流
|
||||
private Integer speed = 1; // 播放速度 1,2,4,8,16,32
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.whdc.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("alarm_records")
|
||||
public class AlarmRecord {
|
||||
|
||||
@TableId(value="id", type= IdType.AUTO)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@TableField(value = "camera_ip")
|
||||
private String cameraIP;
|
||||
|
||||
@TableField(value = "camera_name")
|
||||
private String cameraName;
|
||||
|
||||
@TableField(value = "license_plate")
|
||||
private String licensePlate;
|
||||
|
||||
@TableField(value = "car_color")
|
||||
private String carColor;
|
||||
|
||||
@TableField(value = "plate_color")
|
||||
private String plateColor;
|
||||
|
||||
@TableField(value = "channel_id")
|
||||
private Integer channelID;
|
||||
|
||||
@TableField(value = "alarm_time")
|
||||
private LocalDateTime alarmTime;
|
||||
|
||||
@TableField(value = "speed")
|
||||
private Double speed;
|
||||
|
||||
@TableField(value = "alarm_type")
|
||||
private Integer alarmType;
|
||||
|
||||
@TableField(value = "alarm_code")
|
||||
private String alarmCode;
|
||||
|
||||
@TableField(value = "image_path")
|
||||
private String imagePath;
|
||||
|
||||
@TableField(value = "create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.whdc.entity;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("camera_config")
|
||||
public class CameraConfig {
|
||||
|
||||
@TableId(value="id", type= IdType.AUTO)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@TableField(value = "camera_name")
|
||||
private String cameraName;
|
||||
|
||||
@TableField(value = "camera_ip")
|
||||
private String cameraIP;
|
||||
|
||||
@TableField(value = "username")
|
||||
private String username;
|
||||
|
||||
@TableField(value = "password")
|
||||
private String password;
|
||||
|
||||
@TableField(value = "port")
|
||||
private Integer port = 3000;
|
||||
|
||||
@TableField(value = "channel_no")
|
||||
private Integer channelNo = 0;
|
||||
|
||||
@TableField(value = "enabled")
|
||||
private Integer enabled = 1;
|
||||
|
||||
@TableField(value = "description")
|
||||
private String description;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.entity.AlarmRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface AlarmRecordMapper extends BaseMapper<AlarmRecord> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.entity.CameraConfig;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CameraConfigMapper extends BaseMapper<CameraConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
package com.whdc.service;
|
||||
|
||||
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 com.whdc.entity.CameraConfig;
|
||||
import com.whdc.service.impl.AlarmRecordService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class CameraDetectionSession {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CameraDetectionSession.class);
|
||||
|
||||
private final CameraConfig cameraConfig;
|
||||
private final AlarmRecordService alarmRecordService;
|
||||
private final String imageSavePath;
|
||||
|
||||
private int logonID = -1;
|
||||
private int connectID = -1;
|
||||
private final AtomicBoolean isRunning = new AtomicBoolean(false);
|
||||
private Thread detectionThread;
|
||||
|
||||
private final String[] strCarPlateColor;
|
||||
private final String[] strCarColor;
|
||||
|
||||
public CameraDetectionSession(CameraConfig cameraConfig,
|
||||
AlarmRecordService alarmRecordService,
|
||||
String imageSavePath,
|
||||
String[] strCarPlateColor,
|
||||
String[] strCarColor) {
|
||||
this.cameraConfig = cameraConfig;
|
||||
this.alarmRecordService = alarmRecordService;
|
||||
this.imageSavePath = imageSavePath;
|
||||
this.strCarPlateColor = strCarPlateColor;
|
||||
this.strCarColor = strCarColor;
|
||||
}
|
||||
|
||||
public void startDetection() {
|
||||
if (isRunning.get()) {
|
||||
logger.warn("摄像头 {} 的检测已经在运行", cameraConfig.getCameraIP());
|
||||
return;
|
||||
}
|
||||
|
||||
detectionThread = new Thread(this::runDetection, "CameraDetection-" + cameraConfig.getCameraIP());
|
||||
detectionThread.start();
|
||||
}
|
||||
|
||||
public void stopDetection() {
|
||||
if (!isRunning.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
isRunning.set(false);
|
||||
|
||||
// 停止SDK连接
|
||||
if (connectID != -1) {
|
||||
NetClient2.StopRecv(connectID);
|
||||
connectID = -1;
|
||||
}
|
||||
if (logonID != -1) {
|
||||
NetClient2.Logoff(logonID);
|
||||
logonID = -1;
|
||||
}
|
||||
|
||||
// 等待线程结束
|
||||
if (detectionThread != null && detectionThread.isAlive()) {
|
||||
try {
|
||||
detectionThread.join(5000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("摄像头 {} 的检测已停止", cameraConfig.getCameraIP());
|
||||
}
|
||||
|
||||
private void runDetection() {
|
||||
try {
|
||||
isRunning.set(true);
|
||||
logger.info("开始摄像头 {} 的车辆检测", cameraConfig.getCameraIP());
|
||||
|
||||
// 设备登录
|
||||
if (logonDevice() != 0) {
|
||||
logger.error("摄像头 {} 登录失败", cameraConfig.getCameraIP());
|
||||
return;
|
||||
}
|
||||
|
||||
// 开始抓拍
|
||||
if (startSnap() != 0) {
|
||||
logger.error("摄像头 {} 开始抓拍失败", cameraConfig.getCameraIP());
|
||||
return;
|
||||
}
|
||||
|
||||
// 保持运行
|
||||
while (isRunning.get()) {
|
||||
try {
|
||||
// 检查登录状态
|
||||
if (logonID != -1) {
|
||||
int logonStatus = NetClient2.GetLogonStatus(logonID);
|
||||
if (logonStatus != NVSSDK2.LOGON_SUCCESS) {
|
||||
logger.warn("摄像头 {} 连接断开,尝试重新登录", cameraConfig.getCameraIP());
|
||||
reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(5000); // 5秒检查一次
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("摄像头 {} 检测异常: {}", cameraConfig.getCameraIP(), e.getMessage(), e);
|
||||
} finally {
|
||||
stopDetection();
|
||||
}
|
||||
}
|
||||
|
||||
private int logonDevice() {
|
||||
logonID = NetClient2.Logon("",
|
||||
cameraConfig.getCameraIP(),
|
||||
cameraConfig.getUsername(),
|
||||
cameraConfig.getPassword(),
|
||||
"",
|
||||
cameraConfig.getPort());
|
||||
|
||||
// 等待登录成功
|
||||
int retryCount = 0;
|
||||
while (retryCount < 30 && isRunning.get()) {
|
||||
int logonStatus = NetClient2.GetLogonStatus(logonID);
|
||||
if (logonStatus == NVSSDK2.LOGON_SUCCESS) {
|
||||
logger.info("摄像头 {} 登录成功", cameraConfig.getCameraIP());
|
||||
return 0;
|
||||
} else if (logonStatus == NVSSDK2.LOGON_FAILED) {
|
||||
logger.error("摄像头 {} 登录失败", cameraConfig.getCameraIP());
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return -1;
|
||||
}
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
logger.error("摄像头 {} 登录超时", cameraConfig.getCameraIP());
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void reconnect() {
|
||||
stopDetection();
|
||||
try {
|
||||
Thread.sleep(3000); // 等待3秒后重连
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRunning.get()) {
|
||||
logger.info("尝试重新连接摄像头 {}", cameraConfig.getCameraIP());
|
||||
startDetection();
|
||||
}
|
||||
}
|
||||
|
||||
private int startSnap() {
|
||||
NVSSDK2.NetPicPara netPicParam = new NVSSDK2.NetPicPara();
|
||||
netPicParam.iStructLen = netPicParam.size();
|
||||
netPicParam.iChannelNo = cameraConfig.getChannelNo();
|
||||
netPicParam.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);
|
||||
}
|
||||
};
|
||||
netPicParam.pvUser = null;
|
||||
|
||||
IntByReference pConnectID = new IntByReference();
|
||||
int iRet = NetClient2.StartRecvNetPicStream(logonID, netPicParam, netPicParam.size(), pConnectID);
|
||||
if (iRet < 0) {
|
||||
connectID = -1;
|
||||
logger.error("摄像头 {} 开始抓拍失败", cameraConfig.getCameraIP());
|
||||
return -1;
|
||||
} else {
|
||||
connectID = pConnectID.getValue();
|
||||
logger.info("摄像头 {} 开始抓拍成功, ConnectID: {}", cameraConfig.getCameraIP(), connectID);
|
||||
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 itsPicStream = new NVSSDK2.ItsPicStream();
|
||||
itsPicStream.write();
|
||||
Pointer pItsBuffer = itsPicStream.getPointer();
|
||||
byte[] recvBuffer = tInfo.getByteArray(0, iLen);
|
||||
int copySize = Math.min(itsPicStream.size(), iLen);
|
||||
pItsBuffer.write(0, recvBuffer, 0, copySize);
|
||||
itsPicStream.read();
|
||||
|
||||
String licensePlate = new String(itsPicStream.cPlate).trim();
|
||||
|
||||
// 检测到车辆,生成告警
|
||||
if (!licensePlate.isEmpty() && !licensePlate.equals("未知")) {
|
||||
logger.info("摄像头 {} 检测到车辆: {}", cameraConfig.getCameraIP(), licensePlate);
|
||||
|
||||
// 创建告警记录
|
||||
createAlarmRecord(itsPicStream);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("摄像头 {} 处理图片数据异常: {}", cameraConfig.getCameraIP(), e.getMessage(), e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void createAlarmRecord(NVSSDK2.ItsPicStream itsPicStream) {
|
||||
try {
|
||||
AlarmRecord alarm = new AlarmRecord();
|
||||
alarm.setCameraIP(cameraConfig.getCameraIP());
|
||||
alarm.setCameraName(cameraConfig.getCameraName());
|
||||
alarm.setLicensePlate(new String(itsPicStream.cPlate).trim());
|
||||
alarm.setChannelID(itsPicStream.iChannelID);
|
||||
alarm.setSpeed((double) itsPicStream.fSpeed);
|
||||
alarm.setAlarmType(itsPicStream.iAlarmType);
|
||||
alarm.setAlarmCode(new String(itsPicStream.cAlarmCode).trim());
|
||||
alarm.setAlarmTime(LocalDateTime.now());
|
||||
|
||||
// 设置车辆颜色
|
||||
if (itsPicStream.iCarColor >= 0 && itsPicStream.iCarColor < strCarColor.length) {
|
||||
alarm.setCarColor(strCarColor[itsPicStream.iCarColor]);
|
||||
} else {
|
||||
alarm.setCarColor("unknown");
|
||||
}
|
||||
|
||||
// 设置车牌颜色
|
||||
if (itsPicStream.iPlateColor >= 0 && itsPicStream.iPlateColor < strCarPlateColor.length) {
|
||||
alarm.setPlateColor(strCarPlateColor[itsPicStream.iPlateColor]);
|
||||
} else {
|
||||
alarm.setPlateColor("unknown");
|
||||
}
|
||||
|
||||
// 保存到数据库
|
||||
alarmRecordService.saveAlarmRecord(alarm);
|
||||
logger.info("摄像头 {} 告警记录保存成功: {}", cameraConfig.getCameraIP(), alarm.getLicensePlate());
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("摄像头 {} 创建告警记录失败: {}", cameraConfig.getCameraIP(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning.get();
|
||||
}
|
||||
|
||||
public CameraConfig getCameraConfig() {
|
||||
return cameraConfig;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
if (!isRunning.get()) {
|
||||
return "STOPPED";
|
||||
}
|
||||
if (logonID == -1) {
|
||||
return "CONNECTING";
|
||||
}
|
||||
int logonStatus = NetClient2.GetLogonStatus(logonID);
|
||||
switch (logonStatus) {
|
||||
case NVSSDK2.LOGON_SUCCESS:
|
||||
return "RUNNING";
|
||||
case NVSSDK2.LOGON_ING:
|
||||
return "CONNECTING";
|
||||
case NVSSDK2.LOGON_FAILED:
|
||||
return "FAILED";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.whdc.entity.AlarmRecord;
|
||||
import com.whdc.mapper.AlarmRecordMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class AlarmRecordService extends ServiceImpl<AlarmRecordMapper, AlarmRecord>
|
||||
{
|
||||
|
||||
public boolean saveAlarmRecord(AlarmRecord record) {
|
||||
return this.baseMapper.insert(record) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.whdc.entity.CameraConfig;
|
||||
import com.whdc.mapper.CameraConfigMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CameraConfigService extends ServiceImpl<CameraConfigMapper, CameraConfig> {
|
||||
|
||||
|
||||
|
||||
public List<CameraConfig> getEnabledCameras() {
|
||||
LambdaQueryWrapper<CameraConfig> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(CameraConfig::getEnabled, 1);
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.whdc.alarm.NVSSDK2;
|
||||
import com.whdc.alarm.NetClient2;
|
||||
import com.whdc.entity.CameraConfig;
|
||||
import com.whdc.service.CameraDetectionSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class MultiCameraDetectionService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MultiCameraDetectionService.class);
|
||||
|
||||
@Value("${app.image-save-path}")
|
||||
private String imageSavePath;
|
||||
|
||||
@Autowired
|
||||
private CameraConfigService cameraConfigService;
|
||||
|
||||
@Autowired
|
||||
private AlarmRecordService alarmRecordService;
|
||||
|
||||
private final Map<Long, CameraDetectionSession> cameraSessions = new ConcurrentHashMap<>();
|
||||
private final Map<String, String[]> colorMappings = new ConcurrentHashMap<>();
|
||||
private ScheduledExecutorService scheduler;
|
||||
private boolean isServiceRunning = false;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initColorMappings();
|
||||
startService();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
stopService();
|
||||
}
|
||||
|
||||
private void initColorMappings() {
|
||||
// 车牌颜色映射
|
||||
String[] strCarPlateColor = new String[NVSSDK2.MAX_CAR_PLATE_COLOR];
|
||||
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";
|
||||
|
||||
// 车辆颜色映射
|
||||
String[] strCarColor = new String[NVSSDK2.MAX_CAR_COLOR];
|
||||
strCarColor[0] = "white";
|
||||
strCarColor[1] = "red";
|
||||
strCarColor[2] = "yellow";
|
||||
strCarColor[3] = "gray";
|
||||
strCarColor[4] = "black";
|
||||
strCarColor[5] = "blue";
|
||||
strCarColor[6] = "green";
|
||||
// ... 其他颜色
|
||||
|
||||
colorMappings.put("plateColor", strCarPlateColor);
|
||||
colorMappings.put("carColor", strCarColor);
|
||||
|
||||
// SDK初始化(只需要一次)
|
||||
sdkInit();
|
||||
}
|
||||
|
||||
private void sdkInit() {
|
||||
NVSSDK2.SDK_VERSION ver = new NVSSDK2.SDK_VERSION();
|
||||
int iRet = NetClient2.GetVersion(ver);
|
||||
logger.info("SDK版本: {}", 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) {
|
||||
// 处理参数变化通知
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
logger.info("SDK通知函数设置: {}", iRet);
|
||||
|
||||
iRet = NetClient2.Startup();
|
||||
logger.info("SDK启动: {}", iRet);
|
||||
}
|
||||
|
||||
public void startService() {
|
||||
if (isServiceRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
isServiceRunning = true;
|
||||
scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
// 每30秒检查一次摄像头状态和配置
|
||||
scheduler.scheduleAtFixedRate(this::checkCameras, 0, 30, TimeUnit.SECONDS);
|
||||
|
||||
logger.info("多摄像头检测服务已启动");
|
||||
}
|
||||
|
||||
public void stopService() {
|
||||
isServiceRunning = false;
|
||||
|
||||
if (scheduler != null) {
|
||||
scheduler.shutdown();
|
||||
try {
|
||||
if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// 停止所有摄像头检测
|
||||
cameraSessions.values().forEach(CameraDetectionSession::stopDetection);
|
||||
cameraSessions.clear();
|
||||
|
||||
NetClient2.Cleanup();
|
||||
logger.info("多摄像头检测服务已停止");
|
||||
}
|
||||
|
||||
private void checkCameras() {
|
||||
if (!isServiceRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<CameraConfig> enabledCameras = cameraConfigService.getEnabledCameras();
|
||||
|
||||
// 启动新摄像头
|
||||
for (CameraConfig camera : enabledCameras) {
|
||||
if (!cameraSessions.containsKey(camera.getId())) {
|
||||
startCameraDetection(camera);
|
||||
}
|
||||
}
|
||||
|
||||
// 停止已禁用的摄像头
|
||||
cameraSessions.entrySet().removeIf(entry -> {
|
||||
Long cameraId = entry.getKey();
|
||||
CameraDetectionSession session = entry.getValue();
|
||||
|
||||
boolean shouldRemove = enabledCameras.stream()
|
||||
.noneMatch(camera -> camera.getId().equals(cameraId));
|
||||
|
||||
if (shouldRemove) {
|
||||
session.stopDetection();
|
||||
logger.info("摄像头 {} 检测已停止(配置已禁用)", session.getCameraConfig().getCameraIP());
|
||||
}
|
||||
|
||||
return shouldRemove;
|
||||
});
|
||||
|
||||
// 检查摄像头连接状态
|
||||
cameraSessions.forEach((id, session) -> {
|
||||
String status = session.getStatus();
|
||||
if ("FAILED".equals(status) || "STOPPED".equals(status)) {
|
||||
logger.warn("摄像头 {} 检测异常,状态: {}",
|
||||
session.getCameraConfig().getCameraIP(), status);
|
||||
// 自动重启
|
||||
session.stopDetection();
|
||||
session.startDetection();
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("检查摄像头状态异常: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startCameraDetection(CameraConfig cameraConfig) {
|
||||
if (cameraSessions.containsKey(cameraConfig.getId())) {
|
||||
logger.warn("摄像头 {} 的检测已经在运行", cameraConfig.getCameraIP());
|
||||
return;
|
||||
}
|
||||
|
||||
CameraDetectionSession session = new CameraDetectionSession(
|
||||
cameraConfig,
|
||||
alarmRecordService,
|
||||
imageSavePath,
|
||||
colorMappings.get("plateColor"),
|
||||
colorMappings.get("carColor")
|
||||
);
|
||||
|
||||
cameraSessions.put(cameraConfig.getId(), session);
|
||||
session.startDetection();
|
||||
|
||||
logger.info("启动摄像头 {} 的车辆检测", cameraConfig.getCameraIP());
|
||||
}
|
||||
|
||||
public void stopCameraDetection(Long cameraId) {
|
||||
CameraDetectionSession session = cameraSessions.get(cameraId);
|
||||
if (session != null) {
|
||||
session.stopDetection();
|
||||
cameraSessions.remove(cameraId);
|
||||
logger.info("停止摄像头 {} 的车辆检测", session.getCameraConfig().getCameraIP());
|
||||
}
|
||||
}
|
||||
|
||||
public void restartCameraDetection(Long cameraId) {
|
||||
stopCameraDetection(cameraId);
|
||||
|
||||
CameraConfig cameraConfig = cameraConfigService.getById(cameraId);
|
||||
if (cameraConfig != null && cameraConfig.getEnabled() == 1) {
|
||||
startCameraDetection(cameraConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Long, String> getCameraStatus() {
|
||||
Map<Long, String> statusMap = new ConcurrentHashMap<>();
|
||||
cameraSessions.forEach((id, session) -> {
|
||||
statusMap.put(id, session.getStatus());
|
||||
});
|
||||
return statusMap;
|
||||
}
|
||||
|
||||
public boolean isServiceRunning() {
|
||||
return isServiceRunning;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.whdc.playback.NVSSDK;
|
||||
import com.whdc.playback.NetClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.whdc.dto.PlaybackRequest;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Service
|
||||
public class PlaybackService {
|
||||
|
||||
private Map<String, PlaybackSession> playbackSessions = new ConcurrentHashMap<>();
|
||||
|
||||
private static class PlaybackSession {
|
||||
String playbackId;
|
||||
int logonId;
|
||||
int connectId;
|
||||
String status; // "playing", "paused", "stopped", "error"
|
||||
Date startTime;
|
||||
PlaybackRequest request;
|
||||
|
||||
PlaybackSession(String playbackId, int logonId, PlaybackRequest request) {
|
||||
this.playbackId = playbackId;
|
||||
this.logonId = logonId;
|
||||
this.request = request;
|
||||
this.startTime = new Date();
|
||||
this.status = "playing";
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> startPlayback(PlaybackRequest request) {
|
||||
try {
|
||||
// 1. 登录设备
|
||||
int logonId = loginDevice(request);
|
||||
|
||||
// 2. 启动回放
|
||||
String playbackId = generatePlaybackId();
|
||||
int connectId = startPlaybackStream(logonId, request);
|
||||
|
||||
// 3. 创建回放会话
|
||||
PlaybackSession session = new PlaybackSession(playbackId, logonId, request);
|
||||
session.connectId = connectId;
|
||||
playbackSessions.put(playbackId, session);
|
||||
|
||||
// 4. 返回结果
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("playbackId", playbackId);
|
||||
result.put("logonId", logonId);
|
||||
result.put("connectId", connectId);
|
||||
result.put("status", "playing");
|
||||
result.put("startTime", new Date());
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("启动回放失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean stopPlayback(String playbackId) {
|
||||
PlaybackSession session = playbackSessions.get(playbackId);
|
||||
if (session == null) {
|
||||
throw new RuntimeException("回放会话不存在: " + playbackId);
|
||||
}
|
||||
|
||||
try {
|
||||
// 停止下载
|
||||
NetClient.NetFileStopDownloadFile(session.connectId);
|
||||
|
||||
// 登出设备
|
||||
NetClient.Logoff(session.logonId);
|
||||
|
||||
// 更新状态
|
||||
session.status = "stopped";
|
||||
playbackSessions.remove(playbackId);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("停止回放失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> getPlaybackStatus(String playbackId) {
|
||||
PlaybackSession session = playbackSessions.get(playbackId);
|
||||
if (session == null) {
|
||||
throw new RuntimeException("回放会话不存在: " + playbackId);
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取下载进度
|
||||
IntByReference progress = new IntByReference();
|
||||
IntByReference downloadSize = new IntByReference();
|
||||
NetClient.NetFileGetDownloadPos(session.connectId, progress, downloadSize);
|
||||
|
||||
Map<String, Object> status = new HashMap<>();
|
||||
status.put("playbackId", playbackId);
|
||||
status.put("status", session.status);
|
||||
status.put("progress", progress.getValue());
|
||||
status.put("downloadSize", downloadSize.getValue());
|
||||
status.put("startTime", session.startTime);
|
||||
status.put("currentTime", new Date());
|
||||
|
||||
return status;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取回放状态失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private int loginDevice(PlaybackRequest request) {
|
||||
int logonId = NetClient.Logon("", request.getDeviceIp(),
|
||||
request.getUsername(), request.getPassword(),
|
||||
"", request.getDevicePort());
|
||||
|
||||
if (logonId < 0) {
|
||||
throw new RuntimeException("设备登录失败,错误码: " + logonId);
|
||||
}
|
||||
|
||||
// 等待登录成功
|
||||
int retryCount = 0;
|
||||
while (retryCount < 10) {
|
||||
int status = NetClient.GetLogonStatus(logonId);
|
||||
if (status == NVSSDK.LOGON_SUCCESS) {
|
||||
return logonId;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
retryCount++;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("登录等待被中断");
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("设备登录超时");
|
||||
}
|
||||
|
||||
private int startPlaybackStream(int logonId, PlaybackRequest request) {
|
||||
try {
|
||||
NVSSDK.DOWNLOAD_TIMESPAN downloadTimespan = new NVSSDK.DOWNLOAD_TIMESPAN();
|
||||
downloadTimespan.m_iSize = downloadTimespan.size();
|
||||
|
||||
// 设置本地文件名
|
||||
String localFileName = "playback_" + System.currentTimeMillis() + ".sdv";
|
||||
downloadTimespan.m_cLocalFilename = localFileName.getBytes();
|
||||
|
||||
downloadTimespan.m_iChannelNO = request.getChannelNo();
|
||||
downloadTimespan.m_iStreamNo = request.getStreamType();
|
||||
downloadTimespan.m_iSaveFileType = 0; // SDV格式
|
||||
|
||||
// 设置时间范围
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(request.getStartTime());
|
||||
downloadTimespan.m_tTimeBegin.iYear = (short) cal.get(Calendar.YEAR);
|
||||
downloadTimespan.m_tTimeBegin.iMonth = (short) (cal.get(Calendar.MONTH) + 1);
|
||||
downloadTimespan.m_tTimeBegin.iDay = (short) cal.get(Calendar.DAY_OF_MONTH);
|
||||
downloadTimespan.m_tTimeBegin.iHour = (short) cal.get(Calendar.HOUR_OF_DAY);
|
||||
downloadTimespan.m_tTimeBegin.iMinute = (short) cal.get(Calendar.MINUTE);
|
||||
downloadTimespan.m_tTimeBegin.iSecond = (short) cal.get(Calendar.SECOND);
|
||||
|
||||
cal.setTime(request.getEndTime());
|
||||
downloadTimespan.m_tTimeEnd.iYear = (short) cal.get(Calendar.YEAR);
|
||||
downloadTimespan.m_tTimeEnd.iMonth = (short) (cal.get(Calendar.MONTH) + 1);
|
||||
downloadTimespan.m_tTimeEnd.iDay = (short) cal.get(Calendar.DAY_OF_MONTH);
|
||||
downloadTimespan.m_tTimeEnd.iHour = (short) cal.get(Calendar.HOUR_OF_DAY);
|
||||
downloadTimespan.m_tTimeEnd.iMinute = (short) cal.get(Calendar.MINUTE);
|
||||
downloadTimespan.m_tTimeEnd.iSecond = (short) cal.get(Calendar.SECOND);
|
||||
|
||||
downloadTimespan.m_iPosition = -1; // 不使用定位
|
||||
downloadTimespan.m_iSpeed = request.getSpeed();
|
||||
downloadTimespan.m_iReqMode = 1; // 帧模式
|
||||
downloadTimespan.write();
|
||||
|
||||
IntByReference connectId = new IntByReference();
|
||||
int result = NetClient.NetFileDownload(connectId, logonId,
|
||||
NVSSDK.DOWNLOAD_CMD_TIMESPAN,
|
||||
downloadTimespan.getPointer(),
|
||||
downloadTimespan.size());
|
||||
|
||||
if (result == 0) {
|
||||
return connectId.getValue();
|
||||
} else {
|
||||
throw new RuntimeException("启动回放流失败,错误码: " + result);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("启动回放流异常: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String generatePlaybackId() {
|
||||
return "playback_" + System.currentTimeMillis() + "_" +
|
||||
Math.abs((int)(Math.random() * 10000));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.whdc.video.NVSSDK1;
|
||||
import com.whdc.video.NetClient1;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class VideoPlayService {
|
||||
|
||||
private boolean sdkInitialized = false;
|
||||
private Map<String, StreamSession> activeSessions = new ConcurrentHashMap<>();
|
||||
private Map<Integer, StreamSession> logonSessions = new ConcurrentHashMap<>();
|
||||
|
||||
public static interface FrameCallback {
|
||||
void onFrame(byte[] frameData);
|
||||
}
|
||||
|
||||
private static class StreamSession {
|
||||
String streamId;
|
||||
int logonId;
|
||||
int connectId;
|
||||
FrameCallback frameCallback;
|
||||
|
||||
StreamSession(String streamId) {
|
||||
this.streamId = streamId;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean initSDK() {
|
||||
try {
|
||||
if (sdkInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取SDK版本
|
||||
NVSSDK1.SDK_VERSION ver = new NVSSDK1.SDK_VERSION();
|
||||
int iRet = NetClient1.GetVersion(ver);
|
||||
log.info("[SDK_VERSION] {}", ver.m_cVerInfo);
|
||||
|
||||
// 设置通知回调
|
||||
iRet = NetClient1.SetNotifyFunction(null, null, null);
|
||||
log.info("SetNotifyFunction({})", iRet);
|
||||
|
||||
// 启动SDK
|
||||
iRet = NetClient1.Startup();
|
||||
log.info("Startup({})", iRet);
|
||||
|
||||
sdkInitialized = (iRet == NVSSDK1.RET_SUCCESS);
|
||||
return sdkInitialized;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("SDK初始化异常: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int login(String ip, int port, String username, String password) {
|
||||
try {
|
||||
if (!sdkInitialized) {
|
||||
throw new IllegalStateException("SDK未初始化");
|
||||
}
|
||||
|
||||
NVSSDK1.LogonPara logonPara = new NVSSDK1.LogonPara();
|
||||
logonPara.iSize = logonPara.size();
|
||||
logonPara.cNvsIP = ip.getBytes();
|
||||
logonPara.iNvsPort = port;
|
||||
logonPara.cUserName = username.getBytes();
|
||||
logonPara.cUserPwd = password.getBytes();
|
||||
logonPara.write();
|
||||
|
||||
int logonId = NetClient1.Logon_V4(NVSSDK1.SERVER_NORMAL, logonPara.getPointer(), logonPara.size());
|
||||
|
||||
if (logonId < 0) {
|
||||
throw new RuntimeException("登录失败, 错误码: " + logonId);
|
||||
}
|
||||
|
||||
log.info("登录成功, LogonID: {}", logonId);
|
||||
return logonId;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("登录异常: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String startStream(int logonId, int channelNo, int streamType, int netMode) {
|
||||
try {
|
||||
// 创建流会话
|
||||
String streamId = generateStreamId();
|
||||
StreamSession session = new StreamSession(streamId);
|
||||
session.logonId = logonId;
|
||||
|
||||
// 启动视频流接收
|
||||
NVSSDK1.CLIENTINFO clientInfo = new NVSSDK1.CLIENTINFO();
|
||||
clientInfo.m_iChannelNo = channelNo;
|
||||
clientInfo.m_iNetMode = netMode;
|
||||
clientInfo.m_iStreamNO = streamType;
|
||||
clientInfo.m_iServerID = logonId;
|
||||
clientInfo.m_iBufferCount = 20;
|
||||
clientInfo.write();
|
||||
|
||||
IntByReference piConnectID = new IntByReference();
|
||||
|
||||
// 设置数据回调
|
||||
NVSSDK1.NVSDATA_NOTIFY dataCallback = new NVSSDK1.NVSDATA_NOTIFY() {
|
||||
public void NvsDataNotify(int _uiID, Pointer _pucData, int _iLen, Pointer _iUser) {
|
||||
// 处理原始数据
|
||||
byte[] frameData = _pucData.getByteArray(0, _iLen);
|
||||
if (session.frameCallback != null) {
|
||||
session.frameCallback.onFrame(frameData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int iRet = NetClient1.StartRecv_V4(piConnectID, clientInfo, dataCallback, null);
|
||||
if (iRet < 0) {
|
||||
throw new RuntimeException("启动视频流接收失败, 错误码: " + iRet);
|
||||
}
|
||||
|
||||
int connectId = piConnectID.getValue();
|
||||
session.connectId = connectId;
|
||||
|
||||
// 开始捕获数据
|
||||
NetClient1.StartCaptureData(connectId);
|
||||
|
||||
// 设置原始帧回调
|
||||
NVSSDK1.RAWFRAME_NOTIFY rawFrameCallback = new NVSSDK1.RAWFRAME_NOTIFY() {
|
||||
public void rawFrameNotify(int _uiID, Pointer _pcData, int _iLen,
|
||||
NVSSDK1.RAWFRAME_INFO _ptRawFrameInfo, Pointer _pvUsrData) {
|
||||
// 只处理视频帧
|
||||
if (_ptRawFrameInfo.nType == NVSSDK1.VI_FRAME ||
|
||||
_ptRawFrameInfo.nType == NVSSDK1.VP_FRAME) {
|
||||
byte[] frameData = _pcData.getByteArray(0, _iLen);
|
||||
if (session.frameCallback != null) {
|
||||
session.frameCallback.onFrame(frameData);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NetClient1.SetRawFrameCallBack(connectId, rawFrameCallback, null);
|
||||
NetClient1.StartPlay(connectId, null, 0);
|
||||
|
||||
// 保存会话
|
||||
activeSessions.put(streamId, session);
|
||||
logonSessions.put(logonId, session);
|
||||
|
||||
log.info("视频流启动成功, StreamID: {}, ConnectID: {}", streamId, connectId);
|
||||
return streamId;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("启动视频流异常: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrameCallback(String streamId, FrameCallback callback) {
|
||||
StreamSession session = activeSessions.get(streamId);
|
||||
if (session != null) {
|
||||
session.frameCallback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean stopStream(String streamId) {
|
||||
try {
|
||||
StreamSession session = activeSessions.remove(streamId);
|
||||
if (session != null) {
|
||||
logonSessions.remove(session.logonId);
|
||||
|
||||
// 停止播放
|
||||
NetClient1.StopPlay(session.connectId);
|
||||
// 停止数据捕获
|
||||
NetClient1.StopCaptureData(session.connectId);
|
||||
// 停止接收
|
||||
NetClient1.StopRecv(session.connectId);
|
||||
|
||||
System.out.println("视频流停止成功, StreamID: " + streamId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("停止视频流异常: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean logout(int logonId) {
|
||||
try {
|
||||
StreamSession session = logonSessions.get(logonId);
|
||||
if (session != null) {
|
||||
stopStream(session.streamId);
|
||||
}
|
||||
|
||||
int iRet = NetClient1.Logoff(logonId);
|
||||
boolean success = (iRet == NVSSDK1.RET_SUCCESS);
|
||||
|
||||
if (success) {
|
||||
System.out.println("登出成功, LogonID: " + logonId);
|
||||
} else {
|
||||
System.err.println("登出失败, LogonID: " + logonId + ", 错误码: " + iRet);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("登出异常: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean cleanup() {
|
||||
try {
|
||||
// 停止所有活跃会话
|
||||
for (String streamId : activeSessions.keySet()) {
|
||||
stopStream(streamId);
|
||||
}
|
||||
activeSessions.clear();
|
||||
logonSessions.clear();
|
||||
|
||||
// 清理SDK
|
||||
int iRet = NetClient1.Cleanup();
|
||||
boolean success = (iRet == NVSSDK1.RET_SUCCESS);
|
||||
|
||||
if (success) {
|
||||
sdkInitialized = false;
|
||||
log.info("SDK清理成功");
|
||||
} else {
|
||||
log.error("SDK清理失败, 错误码: " + iRet);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("SDK清理异常: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String generateStreamId() {
|
||||
return "stream_" + System.currentTimeMillis() + "_" + Math.abs((int)(Math.random() * 10000));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package com.whdc.websocket;
|
||||
|
||||
import com.whdc.service.impl.VideoPlayService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.*;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@ServerEndpoint("/ws/video/{streamId}")
|
||||
public class VideoStreamWebSocket {
|
||||
|
||||
private static VideoPlayService videoStreamService;
|
||||
|
||||
private static Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
public void setVideoStreamService(VideoPlayService videoStreamService) {
|
||||
VideoStreamWebSocket.videoStreamService = videoStreamService;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("streamId") String streamId) {
|
||||
sessions.put(streamId, (WebSocketSession) session);
|
||||
System.out.println("WebSocket连接建立: " + streamId);
|
||||
|
||||
// 设置帧数据回调
|
||||
videoStreamService.setFrameCallback(streamId, (frameData) -> {
|
||||
try {
|
||||
WebSocketSession wsSession = sessions.get(streamId);
|
||||
if (wsSession != null && wsSession.isOpen()) {
|
||||
// 发送二进制帧数据
|
||||
wsSession.sendMessage(new BinaryMessage(frameData));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("发送视频帧数据失败: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(@PathParam("streamId") String streamId) {
|
||||
sessions.remove(streamId);
|
||||
System.out.println("WebSocket连接关闭: " + streamId);
|
||||
|
||||
// 停止视频流
|
||||
videoStreamService.stopStream(streamId);
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(@PathParam("streamId") String streamId, Throwable error) {
|
||||
System.err.println("WebSocket错误: " + streamId + ", " + error.getMessage());
|
||||
sessions.remove(streamId);
|
||||
videoStreamService.stopStream(streamId);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, @PathParam("streamId") String streamId) {
|
||||
// 处理客户端消息(如控制指令)
|
||||
System.out.println("收到消息: " + message + " from " + streamId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.whdc.websocket;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocket
|
||||
public class WebSocketConfig implements WebSocketConfigurer {
|
||||
|
||||
@Override
|
||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||
registry.addHandler((WebSocketHandler) new VideoStreamWebSocket(), "/ws/video/*")
|
||||
.setAllowedOrigins("*")
|
||||
.addInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
server:
|
||||
port: 12117
|
||||
port: 12118
|
||||
|
||||
spring:
|
||||
#数据库配置
|
||||
|
|
@ -26,10 +26,3 @@ logging:
|
|||
config: classpath:logback-spring.xml
|
||||
mybatis:
|
||||
mapper-locations: classpath:mapper/*.xml
|
||||
|
||||
mqtt:
|
||||
broker: tcp://120.24.5.249:3189
|
||||
clientId: mqttx_c4d1c22b
|
||||
|
||||
enableMqttListening: true
|
||||
offlineThreshold: 24
|
||||
Loading…
Reference in New Issue