上一次实现了调用摄像头接口,并实现了每间隔五分钟执行一次;用的是while语句加上Thread.sleep(),虽然能实现定时调用的功能,但是sleep会长时间占用内存,浪费资源;后来经朋友提醒,改用了Quartz指针,去实现定时任务。
参考了相关资料,加上本地的实际情况,改进后的代码如下:
首先是引入的架包:包括log4j-1.2.16.jar、quartz-2.2.1.jar、slf4j-api-1.6.6.jar、slf4j-log4j12-1.6.6.jar 4个架包
其次先新建一个实现Job接口的类,加上本地的代码,实现了整合,如下所示:
package ClientDemo;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import ClientDemo.HCNetSDK.NET_DVR_DEVICEINFO_V30;
import ClientDemo.HCNetSDK.NET_DVR_IPPARACFG;
import ClientDemo.HCNetSDK.NET_DVR_JPEGPARA;
import ClientDemo.HCNetSDK.NET_DVR_WORKSTATE_V30;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
public class TestQuartz implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
TestQuartz tqQuartz = new TestQuartz();
try {
tqQuartz.getImages();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void getImages() throws IOException{
final TestQuartz app = new TestQuartz();
final MonitorCameraInfo cameraInfo = new MonitorCameraInfo();
cameraInfo.setCameraIp("****");
cameraInfo.setCameraPort(****);
cameraInfo.setUserName("***");
cameraInfo.setUserPwd("****");
app.getDVRConfig(cameraInfo);
app.getDVRPic(cameraInfo);
}
public void getDVRConfig(MonitorCameraInfo cameraInfo) {
HCNetSDK sdk = HCNetSDK.INSTANCE;
//判断摄像头是否开启
if (!sdk.NET_DVR_Init()) {
System.out.println("SDK初始化失败");
return;
}
NET_DVR_DEVICEINFO_V30 devinfo = new NET_DVR_DEVICEINFO_V30();// 设备信息
//登录信息
NativeLong id = sdk.NET_DVR_Login_V30(cameraInfo.getCameraIp(), (short) cameraInfo.getCameraPort(),
cameraInfo.getUserName(), cameraInfo.getUserPwd(), devinfo);
cameraInfo.setUserId(id);// 返回一个用户编号,同时将设备信息写入devinfo
if (cameraInfo.getUserId().intValue() < 0) {
System.out.println("设备注册失败");
return;
}
//DVR工作状态
NET_DVR_WORKSTATE_V30 devwork = new NET_DVR_WORKSTATE_V30();
if (!sdk.NET_DVR_GetDVRWorkState_V30(cameraInfo.getUserId(), devwork)) {
// 返回Boolean值,判断是否获取设备能力
System.out.println("返回设备状态失败");
}
IntByReference ibrBytesReturned = new IntByReference(0);// 获取IP接入配置参数
NET_DVR_IPPARACFG ipcfg = new NET_DVR_IPPARACFG();//IP接入配置结构
ipcfg.write();
Pointer lpIpParaConfig = ipcfg.getPointer();
//获取相关参数配置
sdk.NET_DVR_GetDVRConfig(cameraInfo.getUserId(), HCNetSDK.NET_DVR_GET_IPPARACFG, new NativeLong(0),
lpIpParaConfig, ipcfg.size(), ibrBytesReturned);
ipcfg.read();
System.out.print("IP地址:" + cameraInfo.getCameraIp());
System.out.println("|设备状态:" + devwork.dwDeviceStatic);// 0正常,1CPU占用率过高,2硬件错误,3未知
//System.out.println("ChanNum"+devinfo.byChanNum);
// 显示模拟通道
for (int i = 0; i < devinfo.byChanNum; i++) {
System.out.print("Camera" + i + 1);// 模拟通道号名称
System.out.print("|是否录像:" + devwork.struChanStatic[i].byRecordStatic);// 0不录像,不录像
System.out.print("|信号状态:" + devwork.struChanStatic[i].bySignalStatic);// 0正常,1信号丢失
System.out.println("|硬件状态:" + devwork.struChanStatic[i].byHardwareStatic);// 0正常,1异常
}
//注销用户
sdk.NET_DVR_Logout(cameraInfo.getUserId());//释放SDK资源
sdk.NET_DVR_Cleanup();
}
//抓拍图片
public void getDVRPic(MonitorCameraInfo cameraInfo) throws IOException {
//设置通道号,其中1正常,-1不正常
NativeLong chanLong = new NativeLong(1);
cameraInfo.setChannel(chanLong);
//System.out.println("Channel:"+chanLong);
long startTime = System.currentTimeMillis();
HCNetSDK sdk = HCNetSDK.INSTANCE;
if (!sdk.NET_DVR_Init()) {
System.out.println("SDK初始化失败");
return;
}
NET_DVR_DEVICEINFO_V30 devinfo = new NET_DVR_DEVICEINFO_V30();// 设备信息
//注册设备
NativeLong id = sdk.NET_DVR_Login_V30(cameraInfo.getCameraIp(), (short) cameraInfo.getCameraPort(),
cameraInfo.getUserName(), cameraInfo.getUserPwd(), devinfo);
cameraInfo.setUserId(id);// 返回一个用户编号,同时将设备信息写入devinfo
if (cameraInfo.getUserId().intValue() < 0) {
System.out.println("设备注册失败"+sdk.NET_DVR_GetLastError());
return;
} else {
System.out.println("id:" + cameraInfo.getUserId().intValue());
}
NET_DVR_WORKSTATE_V30 devwork = new NET_DVR_WORKSTATE_V30();
if (!sdk.NET_DVR_GetDVRWorkState_V30(cameraInfo.getUserId(), devwork)) {
// 返回Boolean值,判断是否获取设备能力
System.out.println("返回设备状态失败");
}
//System.out.println("设备注册耗时:[" + (System.currentTimeMillis() - startTime) + "]");
startTime = System.currentTimeMillis();
//图片质量
NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
// 设置图片的分辨率
jpeg.wPicSize = 2;
// 设置图片质量
jpeg.wPicQuality = 2;
IntByReference a = new IntByReference();
//设置图片大小
ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
// 创建文件目录和文件
SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
Date date = new Date();
//按照每天设置一个目录
String fileName = cameraInfo.getPath() +sd.format(date) ;
File files = new File(fileName);
if(!files.exists()){
files.mkdirs();
}
//按照日期文件夹放入图片
String fileNameString = fileName+"/"+sdf.format(date)+".jpg";
System.out.println(fileNameString);
File file = new File(fileNameString);
// 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
//需要加入通道
boolean is = sdk.NET_DVR_CaptureJPEGPicture_NEW(cameraInfo.getUserId(), cameraInfo.getChannel(), jpeg,
jpegBuffer, 1024 * 1024, a);
//System.out.println("Channel:"+cameraInfo.getChannel());
System.out.println("抓图到内存耗时:[" + (System.currentTimeMillis() - startTime) + "ms]");
// 抓图到文件
//boolean is = sdk.NET_DVR_CaptureJPEGPicture(cameraInfo.UserId,cameraInfo.Channel,jpeg, fileNameString);
if (is) {
System.out.println("抓取成功,返回长度:" + a.getValue());
} else {
System.out.println("抓取失败:"+sdk.NET_DVR_GetLastError());
}
//startTime = System.currentTimeMillis();
// 存储本地,写入内容
BufferedOutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(jpegBuffer.array(), 0, a.getValue());
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("存储本地耗时:[" + (System.currentTimeMillis() - startTime) + "ms]");
sdk.NET_DVR_Logout(cameraInfo.getUserId());
sdk.NET_DVR_Cleanup();
}
}
其次是创建任务调度,并执行,代码参考的https://www.cnblogs.com/longqingyang/p/7027897.html
如下所示:
package ClientDemo;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 创建调度任务并执行
* @author 72414
*
*/
public class MainScheduler {
@SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
MainScheduler mainScheduler = new MainScheduler();
MainScheduler.schedulerJob();
}
//创建调度器
public static Scheduler getScheduler() throws Exception{
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
return schedulerFactory.getScheduler();
}
public static void schedulerJob() throws Exception{
//创建任务
JobDetail jobDetail = JobBuilder.newJob(TestQuartz.class).withIdentity("job1", "group1").build();
//创建触发器,每5s执行一次,如果是分钟,则把withIntervalInSeconds(intervalInSeconds)改成withIntervalInMinutes(intervalInMinutes)
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group3").withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(5).repeatForever()).build();
Scheduler scheduler = getScheduler();
//将任务及其触发器放入调度器
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
之后在main方法执行就成功了。
参考的资料:https://www.cnblogs.com/longqingyang/p/7027897.html
http://blog.csdn.net/qq_26562641/article/details/51964910
在执行的时候,有可能会出现log4j的相关警告信息,只需要在src目录下新建文件名为log4j.properties,内容如下:
# Configure logging for testing: optionally with log file
log4j.rootLogger=WARN, stdout
# log4j.rootLogger=WARN, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
再执行就没有问题了。