package com.netsdk.demo.intelligentTraffic;
|
|
import java.io.File;
|
import java.io.UnsupportedEncodingException;
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import com.netsdk.demo.util.Testable;
|
import com.netsdk.lib.NativeString;
|
import com.netsdk.lib.NetSDKLib;
|
import com.netsdk.lib.NetSDKLib.LLong;
|
import com.netsdk.lib.NetSDKLib.SdkStructure;
|
import com.netsdk.lib.ToolKits;
|
import com.netsdk.lib.structure.NET_MEDIA_QUERY_TRAFFICCAR_PARAM_EX;
|
import com.sun.jna.Memory;
|
import com.sun.jna.Pointer;
|
import com.sun.jna.ptr.IntByReference;
|
|
import static com.netsdk.lib.NetSDKLib.*;
|
|
/**
|
* 适用于 ITSE 智能交通设备
|
* 查询并下载抓拍图片及录像
|
*
|
* @author 29779
|
*/
|
public class TrafficMediaFile implements Testable {
|
static NetSDKLib netsdkApi = NetSDKLib.NETSDK_INSTANCE;
|
|
/**
|
* 设备信息
|
*/
|
private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
|
|
/**
|
* 登录句柄
|
*/
|
private LLong loginHandle = new LLong(0);
|
private String username = "admin";
|
private String password = "admin123";
|
private String address = "172.12.5.200";
|
private int port = 37777;
|
|
/**
|
* 返回错误码, 具体值参照 NetSDKLib.java NET_NOERROR
|
*/
|
public static void printLastError(String msg) {
|
System.err.printf("[ ERROR ] %s, Error Code [%s]\n", msg, ToolKits.getErrorCode());
|
}
|
|
public static void printMessage(String msg) {
|
System.out.println("[ INFO ] >> " + msg);
|
}
|
|
/**
|
* 获取文件数量
|
*
|
* @param findHandle 查询句柄
|
* @return 失败返回 -1 成功返回 实际数量
|
*/
|
public int getTotalFiles(LLong findHandle) {
|
IntByReference nCount = new IntByReference(0);
|
boolean bRet = netsdkApi.CLIENT_GetTotalFileCount(findHandle, nCount, null, 3000);
|
if (!bRet) {
|
printLastError("GetTotalFileCount failed!");
|
return -1;
|
}
|
|
System.out.println("The Total File: " + nCount.getValue());
|
|
return nCount.getValue();
|
}
|
|
/**
|
* 交通违章事件转化
|
*
|
* @param eventType 违章码
|
* @return 转成字符串
|
*/
|
public static String eventToString(int eventType) {
|
switch (eventType) {
|
case NetSDKLib.EVENT_IVS_TRAFFIC_TOLLGATE:
|
return "卡口"; // 交通违章-卡口事件----新规则
|
case NetSDKLib.EVENT_IVS_TRAFFICJUNCTION:
|
return "路口"; // 交通路口事件
|
case NetSDKLib.EVENT_IVS_TRAFFIC_RUNREDLIGHT:
|
return "闯红灯"; // 交通违章-闯红灯事件
|
case NetSDKLib.EVENT_IVS_TRAFFIC_OVERLINE:
|
return "压车道"; // 交通违章-压车道线事件
|
case NetSDKLib.EVENT_IVS_TRAFFIC_RETROGRADE:
|
return "逆行"; // 交通违章-逆行事件
|
case NetSDKLib.EVENT_IVS_TRAFFIC_OVERSPEED:
|
return "超速"; // 交通违章-超速
|
case NetSDKLib.EVENT_IVS_TRAFFIC_UNDERSPEED:
|
return "低速"; // 交通违章-低速
|
case NetSDKLib.EVENT_IVS_TRAFFIC_PARKING:
|
return "违章停车"; // 交通违章-违章停车
|
case NetSDKLib.EVENT_IVS_TRAFFIC_WRONGROUTE:
|
return "不按车道行驶"; // 交通违章-不按车道行驶
|
case NetSDKLib.EVENT_IVS_TRAFFIC_CROSSLANE:
|
return "违章变道"; // 交通违章-违章变道
|
case NetSDKLib.EVENT_IVS_TRAFFIC_OVERYELLOWLINE:
|
return "压黄线"; // 交通违章-压黄线
|
case NetSDKLib.EVENT_IVS_TRAFFIC_YELLOWPLATEINLANE:
|
return "黄牌车占道"; // 交通违章-黄牌车占道事件
|
case NetSDKLib.EVENT_IVS_TRAFFIC_PEDESTRAINPRIORITY:
|
return "斑马线行人优先"; // 交通违章-斑马线行人优先事件
|
default:
|
return null;
|
}
|
}
|
|
private static ConcurrentHashMap<Long, Boolean> imageDownloadStatus = new ConcurrentHashMap<>();
|
|
/**
|
* 下载进度
|
*/
|
public static class Download implements NetSDKLib.fDownLoadPosCallBack {
|
private static Download _instance = new Download();
|
private static String _lock = "DownLoadPos";
|
|
private Download() {
|
}
|
|
public static Download getInstance() {
|
return _instance;
|
}
|
|
public void invoke(LLong lPlayHandle, int dwTotalSize,
|
int dwDownLoadSize, Pointer dwUser) {
|
if (-1 == dwDownLoadSize) {
|
try {
|
imageDownloadStatus.put(lPlayHandle.longValue(), true);
|
printMessage("Progress: Download OK");
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
} else {
|
imageDownloadStatus.put(lPlayHandle.longValue(), false);
|
}
|
}
|
|
/**
|
* 下载交通图片
|
*
|
* @param hLogin
|
* @param info
|
* @param fileName
|
* @return 失败返回 false 成功放回 true
|
*/
|
public boolean downloadImage(LLong hLogin, NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO info, String fileName) throws InterruptedException {
|
int fileType = NetSDKLib.EM_FILE_QUERY_TYPE.NET_FILE_QUERY_TRAFFICCAR;
|
return downloadMediaFile(hLogin, fileType, info, fileName);
|
}
|
|
/**
|
* 根据下载的图片文件信息下载图片文件
|
* (注意下载图片时,应该在一张图片下载完成后,再开始下载下一张图片)
|
*
|
* @param emType 文件查询条件
|
* @param info 文件信息
|
* @param fileName 保存的文件名
|
* @return -1 error
|
* @see emType EM_FILE_QUERY_TYPE
|
*/
|
public boolean downloadMediaFile(LLong hLogin, int emType, SdkStructure info, String fileName) throws InterruptedException {
|
if (hLogin.longValue() == 0) {
|
printLastError("Please Login First");
|
return false;
|
}
|
|
info.write();
|
LLong hDownload = netsdkApi.CLIENT_DownloadMediaFile(hLogin, emType,
|
info.getPointer(), fileName, _instance, null, null);
|
info.read();
|
|
if (hDownload.longValue() == 0) {
|
printLastError("Download " + fileName + "Failed");
|
return false;
|
}
|
|
int count = 100; // 最多循环100次, 即10s
|
while ((!imageDownloadStatus.containsKey(hDownload.longValue()) || !imageDownloadStatus.get(hDownload.longValue()))
|
&& count > 0) {
|
Thread.sleep(100);
|
count--;
|
}
|
imageDownloadStatus.remove(hDownload.longValue());
|
|
printMessage("Download " + fileName + " Success");
|
netsdkApi.CLIENT_StopDownloadMediaFile(hDownload);
|
|
return true;
|
}
|
}
|
|
|
public void findMediaFile() throws InterruptedException {
|
if (loginHandle.longValue() == 0) {
|
System.err.println("Please Login First");
|
return;
|
}
|
|
final int queryType = NetSDKLib.EM_FILE_QUERY_TYPE.NET_FILE_QUERY_TRAFFICCAR;
|
NetSDKLib.MEDIA_QUERY_TRAFFICCAR_PARAM condition = new NetSDKLib.MEDIA_QUERY_TRAFFICCAR_PARAM();
|
|
condition.nChannelID = -1; // 通道号 -1代表所有通道
|
condition.nMediaType = 1; // 文件类型 0:任意类型, 1:jpg图片, 2:dav文件
|
condition.byFileFlag = 0; // 设置 文件标志, 0xFF-使用nFileFlagEx, 0-表示所有录像, 1-定时文件, 2-手动文件, 3-事件文件, 4-重要文件, 5-合成文件
|
condition.byRandomAccess = 1; // 设置 是否需要在查询过程中随意跳转,0-不需要,1-需要
|
condition.byLane = -1; // 查询相应车道信息 -1代表所有车道
|
condition.nDirection = -1; // 查询车开往的方向 -1代表所有方向
|
|
condition.StartTime.setTime(2020, 12, 21, 21, 0, 0); // 设置 开始时间
|
condition.EndTime.setTime(2020, 12, 21, 21, 30, 0); // 设置 结束时间
|
|
condition.nEventTypeNum = 2; // 设置需要查询的违章事件类型个数
|
// IntByReference nEventType = new IntByReference(EVENT_IVS_ALL); // 全部
|
int[] eventTypes = new int[condition.nEventTypeNum];
|
eventTypes[0] = EVENT_IVS_TRAFFICJUNCTION;
|
eventTypes[1] = EVENT_IVS_TRAFFIC_PARKINGSPACE_MANUALSNAP;
|
Pointer pEventTypes = new Memory(Integer.SIZE * condition.nEventTypeNum);
|
pEventTypes.write(0, eventTypes, 0, condition.nEventTypeNum);
|
condition.pEventTypes = pEventTypes;
|
|
// 设置查询类型 获取查询句柄
|
condition.write();
|
LLong findHandle = netsdkApi.CLIENT_FindFileEx(loginHandle, queryType, condition.getPointer(), null, 3000);
|
condition.read();
|
if (findHandle.longValue() == 0) {
|
printLastError("Failed to Find File");
|
return;
|
}
|
|
// 获取违章总数
|
int totalCount = getTotalFiles(findHandle);
|
int queryCount = Math.min(10, totalCount); //每次获取的违章数量
|
NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO[] mediaFileInfos = new NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO[queryCount];
|
for (int i = 0; i < mediaFileInfos.length; ++i) {
|
mediaFileInfos[i] = new NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO();
|
}
|
|
final int memorySize = mediaFileInfos[0].size() * queryCount;
|
Pointer mediaFileMemory = new Memory(memorySize);
|
mediaFileMemory.clear(memorySize);
|
|
//循环查询
|
int nCurCount = 0;
|
do {
|
// 查询
|
ToolKits.SetStructArrToPointerData(mediaFileInfos, mediaFileMemory);
|
int nRet = netsdkApi.CLIENT_FindNextFileEx(findHandle, queryCount, mediaFileMemory, memorySize, null, 3000);
|
ToolKits.GetPointerDataToStructArr(mediaFileMemory, mediaFileInfos);
|
if (nRet < 0) {
|
printLastError("FindNextFileEx failed!");
|
break;
|
}
|
|
//更多信息输出,可以查看结构体MEDIAFILE_TRAFFICCAR_INFO_EX中的MEDIAFILE_TRAFFICCAR_INFO
|
for (int j = 0; j < nRet; j++) {
|
++nCurCount;
|
|
NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO info = mediaFileInfos[j];
|
printMessage("-------------------------" + nCurCount + "---------------------------");
|
printMessage("通道号: " + info.ch);
|
printMessage("违章类型: " + eventToString(info.nEvents[0]));
|
printMessage("车道号: " + info.byLane);
|
String plateNumber = "";
|
try {
|
plateNumber = new String(info.szPlateNumber, "GBK").trim();
|
} catch (UnsupportedEncodingException e) {
|
e.printStackTrace();
|
}
|
plateNumber = plateNumber.isEmpty() ? "无牌车" : plateNumber;
|
printMessage("车牌号码: " + plateNumber);
|
printMessage("车牌颜色: " + new String(info.szPlateColor).trim());
|
printMessage("车牌类型: " + new String(info.szPlateType).trim());
|
printMessage("车身颜色: " + new String(info.szVehicleColor).trim());
|
printMessage("抓拍时间: " + info.stSnapTime.toStringTime());
|
printMessage("事件组ID: " + info.nGroupID);
|
printMessage("该组ID抓怕张数: " + info.byCountInGroup);
|
printMessage("该组ID抓怕索引: " + info.byIndexInGroup);
|
printMessage("图片地址: " + new String(info.szFilePath));
|
printMessage("包含事件数: " + info.nEventsNum);
|
printMessage("事件枚举: " + String.format("0x%08x", info.nEvents[0]));
|
|
|
// 下载当前图片
|
String fileName = String.format("Image_Channel_%d_%s_%d.jpg", info.ch, info.stSnapTime.toString(), info.nGroupID);
|
if (!Download.getInstance().downloadImage(loginHandle, info, fileName)) {
|
totalCount = 0;
|
break;
|
}
|
}
|
} while ((totalCount -= queryCount) > 0);
|
|
netsdkApi.CLIENT_FindCloseEx(findHandle);
|
}
|
|
public void findMediaFileEx_TrafficCar() throws InterruptedException {
|
if (loginHandle.longValue() == 0) {
|
System.err.println("Please Login First");
|
return;
|
}
|
|
final int queryType = NetSDKLib.EM_FILE_QUERY_TYPE.NET_FILE_QUERY_TRAFFICCAR_EX;
|
MEDIA_QUERY_TRAFFICCAR_PARAM_EX condition = new MEDIA_QUERY_TRAFFICCAR_PARAM_EX();
|
|
condition.stuParam.nChannelID = 0; // 通道号 -1代表所有通道
|
condition.stuParam.nMediaType = 1; // 文件类型 0:任意类型, 1:jpg图片, 2:dav文件
|
condition.stuParam.byFileFlag = 0; // 设置 文件标志, 0xFF-使用nFileFlagEx, 0-表示所有录像, 1-定时文件, 2-手动文件, 3-事件文件, 4-重要文件, 5-合成文件
|
condition.stuParam.byRandomAccess = 0; // 设置 是否需要在查询过程中随意跳转,0-不需要,1-需要
|
condition.stuParam.byLane = -1; // 查询相应车道信息 -1代表所有车道
|
condition.stuParam.nDirection = -1; // 查询车开往的方向 -1代表所有方向
|
|
condition.stuParam.StartTime.setTime(2022, 8, 30, 0, 0, 0); // 设置 开始时间
|
condition.stuParam.EndTime.setTime(2022, 9, 6, 10, 0, 0); // 设置 结束时间
|
|
condition.stuParam.nEventTypeNum = 6; // 设置需要查询的违章事件类型个数
|
// IntByReference nEventType = new IntByReference(EVENT_IVS_ALL); // 全部
|
int[] eventTypes = new int[condition.stuParam.nEventTypeNum];
|
eventTypes[0] = EVENT_IVS_TRAFFICJUNCTION;
|
eventTypes[1] = EVENT_IVS_CROSSLINEDETECTION;
|
eventTypes[2] = EVENT_IVS_CROSSREGIONDETECTION;
|
eventTypes[3] = EVENT_IVS_RIOTERDETECTION;
|
eventTypes[4] = EVENT_IVS_PARKINGDETECTION;
|
eventTypes[5] = EVENT_IVS_WANDERDETECTION;
|
Pointer pEventTypes = new Memory(Integer.SIZE * condition.stuParam.nEventTypeNum);
|
pEventTypes.write(0, eventTypes, 0, condition.stuParam.nEventTypeNum);
|
condition.stuParam.pEventTypes = pEventTypes;
|
//拓展查询参数设置
|
// NET_MEDIA_QUERY_TRAFFICCAR_PARAM_EX paramEx = new NET_MEDIA_QUERY_TRAFFICCAR_PARAM_EX();
|
// System.arraycopy("CN".getBytes(),0,paramEx.szCountry,0,"CN".getBytes().length);
|
// //设置使用UTC查询(为1时StartTime、EndTime失效)
|
// paramEx.bOnlySupportRealUTC = 1;
|
// paramEx.stuStartTimeRealUTC.setTime(2022,9,1,0,0,0);
|
// paramEx.stuEndTimeRealUTC.setTime(2022,9,8,0,0,0);
|
// condition.stuParam.pstuTrafficCarParamEx = new Memory(paramEx.size()); // 申请内存
|
// condition.stuParam.pstuTrafficCarParamEx.clear(paramEx.size());
|
// ToolKits.SetStructDataToPointer(paramEx, condition.stuParam.pstuTrafficCarParamEx,0);
|
// 设置查询类型 获取查询句柄
|
condition.write();
|
LLong findHandle = netsdkApi.CLIENT_FindFileEx(loginHandle, queryType, condition.getPointer(), null, 3000);
|
condition.read();
|
if (findHandle.longValue() == 0) {
|
printLastError("Failed to Find File");
|
return;
|
}
|
|
// 获取违章总数
|
int totalCount = getTotalFiles(findHandle);
|
int queryCount = Math.min(10, totalCount); //每次获取的违章数量
|
NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO_EX[] mediaFileInfos = new NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO_EX[queryCount];
|
for (int i = 0; i < mediaFileInfos.length; ++i) {
|
mediaFileInfos[i] = new NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO_EX();
|
}
|
|
final int memorySize = mediaFileInfos[0].size() * queryCount;
|
Pointer mediaFileMemory = new Memory(memorySize);
|
mediaFileMemory.clear(memorySize);
|
|
//循环查询
|
int nCurCount = 0;
|
do {
|
// 查询
|
ToolKits.SetStructArrToPointerData(mediaFileInfos, mediaFileMemory);
|
int nRet = netsdkApi.CLIENT_FindNextFileEx(findHandle, queryCount, mediaFileMemory, memorySize, null, 3000);
|
ToolKits.GetPointerDataToStructArr(mediaFileMemory, mediaFileInfos);
|
if (nRet < 0) {
|
printLastError("FindNextFileEx failed!");
|
break;
|
}
|
|
//更多信息输出,可以查看结构体MEDIAFILE_TRAFFICCAR_INFO_EX中的MEDIAFILE_TRAFFICCAR_INFO
|
for (int j = 0; j < nRet; j++) {
|
++nCurCount;
|
|
NetSDKLib.MEDIAFILE_TRAFFICCAR_INFO_EX info = mediaFileInfos[j];
|
printMessage("-------------------------" + nCurCount + "---------------------------");
|
printMessage("通道号: " + info.stuInfo.ch);
|
printMessage("违章类型: " + eventToString(info.stuInfo.nEvents[0]));
|
printMessage("车道号: " + info.stuInfo.byLane);
|
String plateNumber = "";
|
try {
|
plateNumber = new String(info.stuInfo.szPlateNumber, "GBK").trim();
|
} catch (UnsupportedEncodingException e) {
|
e.printStackTrace();
|
}
|
plateNumber = plateNumber.isEmpty() ? "无牌车" : plateNumber;
|
printMessage("车牌号码: " + plateNumber);
|
printMessage("车牌颜色: " + new String(info.stuInfo.szPlateColor).trim());
|
printMessage("车牌类型: " + new String(info.stuInfo.szPlateType).trim());
|
printMessage("车身颜色: " + new String(info.stuInfo.szVehicleColor).trim());
|
printMessage("抓拍时间: " + info.stuInfo.stSnapTime.toStringTime());
|
printMessage("事件组ID: " + info.stuInfo.nGroupID);
|
printMessage("该组ID抓拍张数: " + info.stuInfo.byCountInGroup);
|
printMessage("该组ID抓拍索引: " + info.stuInfo.byIndexInGroup);
|
printMessage("图片地址: " + new String(info.stuInfo.szFilePath));
|
printMessage("包含事件数: " + info.stuInfo.nEventsNum);
|
for(int i = 0; i < info.stuInfo.nEventsNum; i ++){
|
printMessage("事件枚举["+i+"]: " + String.format("0x%08x", info.stuInfo.nEvents[i]));
|
}
|
printMessage("是否真实UTC: " + info.bRealUTC);
|
printMessage("UTC开始时间: " + info.stuStartTimeRealUTC.toStringTime());
|
printMessage("UTC结束时间: " + info.stuEndTimeRealUTC.toStringTime());
|
|
|
// 下载当前图片
|
String fileName = String.format("Image_Channel_%d_%s_%d.jpg", info.stuInfo.ch, info.stuInfo.stSnapTime.toString(), info.stuInfo.nGroupID);
|
if (!Download.getInstance().downloadImage(loginHandle, info.stuInfo, fileName)) {
|
totalCount = 0;
|
break;
|
}
|
}
|
} while ((totalCount -= queryCount) > 0);
|
|
netsdkApi.CLIENT_FindCloseEx(findHandle);
|
}
|
|
@Override
|
public void initTest() {
|
// 初始化SDK
|
netsdkApi.CLIENT_Init(null, null);
|
|
//打开日志,可选
|
NetSDKLib.LOG_SET_PRINT_INFO logInfo = new NetSDKLib.LOG_SET_PRINT_INFO();
|
File path = new File(".");
|
String logPath = path.getAbsoluteFile().getParent() + TrafficMediaFile.class.getName().toLowerCase() + ".log";
|
|
logInfo.bSetFilePath = 1;
|
System.arraycopy(logPath.getBytes(), 0, logInfo.szLogFilePath, 0, logPath.getBytes().length);
|
|
logInfo.bSetPrintStrategy = 1;
|
logInfo.nPrintStrategy = 0;
|
boolean bLogopen = netsdkApi.CLIENT_LogOpen(logInfo);
|
if (!bLogopen) {
|
System.err.println("Failed to open NetSDK log");
|
}
|
|
int nSpecCap = NetSDKLib.EM_LOGIN_SPAC_CAP_TYPE.EM_LOGIN_SPEC_CAP_TCP; // TCP 方式登录
|
final IntByReference error = new IntByReference();
|
loginHandle = netsdkApi.CLIENT_LoginEx2(address, (short) port, username,
|
password, nSpecCap, null, deviceInfo, error);
|
if (loginHandle.longValue() == 0) {
|
System.err.printf("Login Device [%s:%d] Failed ! Last Error[%x]\n", address, port, netsdkApi.CLIENT_GetLastError());
|
}
|
|
System.out.printf("Login Device [%s:%d] Success. \n", address, port);
|
}
|
|
@Override
|
public void runTest() throws InterruptedException {
|
findMediaFileEx_TrafficCar();
|
}
|
|
@Override
|
public void endTest() {
|
if (loginHandle.longValue() != 0) {
|
netsdkApi.CLIENT_Logout(loginHandle);
|
System.out.println("Logout Device " + address);
|
}
|
|
netsdkApi.CLIENT_Cleanup();
|
}
|
|
public static void main(String[] args) throws InterruptedException {
|
|
TrafficMediaFile demo = new TrafficMediaFile();
|
|
demo.initTest();
|
|
demo.runTest();
|
|
demo.endTest();
|
}
|
}
|