定时调用海康威视摄像头接口抓取图片

    上一次实现了调用摄像头接口,并实现了每间隔五分钟执行一次;用的是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

再执行就没有问题了。

你可能感兴趣的:(随笔)