海康安防平台SDK抓图示例

上次写了利用javacv从rtsp流抓图的过程,这次简单记录一下利用海康SDK从安防平台抓图的过程。

1. SDK

首先,在海康官网找到并下载OpenAPI安全认证库(JAVA):
海康开放平台
在这里插入图片描述
在我们的项目中,我把下载后得到的artemis-http-client-1.1.12.RELEASE-sources.jar中的源代码解压到工程目录中,以便后面根据实际需求修改某些参数。如果不想直接用源码,也可以在pom.xml中添加SDK引用:

<dependency>
	<groupId>com.hikvision.ga</groupId>
	<artifactId>artemis-http-client</artifactId>
	<version>1.1.12.RELEASE</version>
</dependency>

需要说明的是,源码里有一个地方可能是需要修改的 —— 我们抓图或者是调用海康接口,肯定要用到ArtemisHttpUtil这个类,它对认证信息和请求信息进行了封装,其中的请求部分封装成了Request的实例,如:

Request request = new Request(Method.GET, httpSchema + artemisConfig.getHost(),
                path.get(httpSchema), artemisConfig.getAppKey(), artemisConfig.getAppSecret(), Constants.DEFAULT_TIMEOUT);

然后,这个Request的实例通过层层调用,最终来到了HttpUtil,以其中的httpPost方法为例,我们看一下具体实现:

public static Response httpPost(String host, String path, int connectTimeout, Map<String, String> headers, Map<String, String> querys, Map<String, String> bodys, List<String> signHeaderPrefixList, String appKey, String appSecret)
            throws Exception {
    if (headers == null) {
        headers = new HashMap<String, String>();
    }

    headers.put(HttpHeader.HTTP_HEADER_CONTENT_TYPE, ContentType.CONTENT_TYPE_FORM);

    headers = initialBasicHeader(HttpMethod.POST, path, headers, querys, bodys, signHeaderPrefixList, appKey, appSecret);

    CloseableHttpClient httpClient = wrapClient(host);

    HttpPost post = new HttpPost(initUrl(host, path, querys));
    for (Map.Entry<String, String> e : headers.entrySet()) {
        post.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue()));
    }

    UrlEncodedFormEntity formEntity = buildFormEntity(bodys);
    if (formEntity != null) {
        post.setEntity(formEntity);
    }
    return convert(httpClient.execute(post));
}

这里有一个不起眼但是又很关键的问题,传进来的connectTimeout参数没用。在一切状况都非常好的情况下,所有一切都部署在同一网段的时候,everything is ok。但是如果通过外网访问,或者海康服务器在A城市,你的应用在B城市通过广域网访问,这时候网络原因可能造成你无法正确通过HTTP取得正确的结果。
这里简单写一下设置超时的方式:

RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectTimeout)
                .build();
post.setConfig(requestConfig);

抓图

实际上在海康开放平台上,对各种接口的描述已经写得非常清楚了,网上各种教程和资料也非常多。这里简单归纳总结一下,再放上一段代码给大家参考:

抓图流程

(1) 取得访问身份信息,可以找海康平台管理员分配appKey和appSecret;
(2) 取得要抓图的设备编码;
(3) 构造ArtemisConfig对新,设置海康服务器IP、端口、appKey和appSecret;
(4) 调用抓图接口;
(5) 按照开放平台的描述,解析返回结果,正常情况下会取到一个图片的picUrl;
(6) 从picUrl下载图片。

示例代码

public class ArtemisPost {
	/**
     * API网关的后端服务上下文为:/artemis
     */
    private static final String ARTEMIS_PATH = "/artemis";

	private static final String MANUAL_CAPTURE = "/api/video/v1/manualCapture";

	private String ip = "";

    private String port = "";

    private String appKey = "";
    
    private String appSecret = "";
	
	private String cameraIndexCode = "";

	public void callManualCapture() {
        ArtemisConfig config = new ArtemisConfig();
        config.setHost(ip + ":" + port);
        config.setAppKey(appKey);
        config.setAppSecret(appSecret);
        final String getCamsApi = ARTEMIS_PATH + MANUAL_CAPTURE;

        Map<String, String> paramMap = new HashMap<>();		// post请求参数
        paramMap.put("cameraIndexCode", cameraIndexCode);
        String body = JSON.toJSON(paramMap).toString();

        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put("https://", getCamsApi);
            }
        };

        try {
            String result = ArtemisHttpUtil.doPostStringArtemis(config, path, body, null, null, "application/json", null);
            if (!StringUtils.isEmpty(result)) {
            	// 在返回结果里,通过code判断操作是否成功
            	// 操作成功时,取data,再取picUrl
                Map resultObj = JSON.parseObject(result, Map.class);
                if (resultObj != null && "0".equals(resultObj.get("code").toString())) {
                    Map<String, String> resultData = (Map<String, String>) resultObj.get("data");
                    String picUrl = resultData.get("picUrl");
					
					// 代码略有删减,这里将服务器返回的图片转成了base64使用
                    String imgBase64 = downloadPic(picUrl);	
                }
            }
        } catch (ConnectTimeoutException e) {
            log.error("Connect to {} failed: connect timed out", ip);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return captureResult;
    }

	public String downloadPic(String picUrl) throws IOException {
        HTTPSTrustManager.retrieveResponseFromServer(picUrl);
        URL url = new URL(picUrl);

        byte[] buf = new byte[4096];
        HttpsURLConnection conn = null;
        InputStream inStream = null;
        ByteArrayOutputStream outStream = null;
        String imgBase64 = null;
        try {
            //构造连接
            conn = (HttpsURLConnection) url.openConnection();
            //这个网站要模拟浏览器才行
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko");
            //打开连接
            conn.connect();
            //打开这个网站的输入流
            inStream = conn.getInputStream();
            //用这个做中转站 ,把图片数据都放在了这里,再调用toByteArray()即可获得数据的byte数组
            outStream = new ByteArrayOutputStream();
            int len = 0;
            //读取图片数据
            while ((len = inStream.read(buf)) != -1) {
                outStream.write(buf, 0, len);
            }
            outStream.flush();

            // 图片转为base64
            imgBase64 = Base64Utils.imageToBase64ByLocalByte(outStream.toByteArray());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (inStream != null) {
                inStream.close();
            }
            if (outStream != null) {
                outStream.close();
            }
        }
        return imgBase64;
    }
}

服务器返回的图片是以https开头的,所以下载图片之前需要搞一下认证。这东西是在网上找的,直接代码贴出来:

import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
 
public class HTTPSTrustManager implements X509TrustManager {
    static HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
            System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                    + session.getPeerHost());
            return true;
        }
    };
 
    public final static String retrieveResponseFromServer(final String url) {
        HttpURLConnection connection = null;
 
        try {
            URL validationUrl = new URL(url);
            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
 
            connection = (HttpURLConnection) validationUrl.openConnection();
            final BufferedReader in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
 
            String line;
            final StringBuffer stringBuffer = new StringBuffer(255);
 
            synchronized (stringBuffer) {
                while ((line = in.readLine()) != null) {
                    stringBuffer.append(line);
                    stringBuffer.append("\n");
                }
                return stringBuffer.toString();
            }
 
        } catch (final IOException e) {
            System.out.println(e.getMessage());
            return null;
        } catch (final Exception e1){
            System.out.println(e1.getMessage());
            return null;
        }finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
 
    public static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext
                .getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc
                .getSocketFactory());
    }
 
    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
 
    }
 
    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
 
    }
 
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
 
    static class miTM implements TrustManager,
            X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
 
        public boolean isServerTrusted(
                X509Certificate[] certs) {
            return true;
        }
 
        public boolean isClientTrusted(
                X509Certificate[] certs) {
            return true;
        }
 
        public void checkServerTrusted(
                X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
 
        public void checkClientTrusted(
                X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }
}
以下是一个使用海康CVR(Centralized Video Recording)SDK的简单编程示例,用于录制视频: ```cpp #include <stdio.h> #include <Windows.h> #include <ctime> #include <iostream> #include "CVRSDK.h" // 回调函数,用于接收录像文件的实时状态 void __stdcall RecordStatusCallback(DWORD dwHandle, DWORD dwRecordStatus, PVOID pUserData) { switch (dwRecordStatus) { case CVR_RECORD_STATUS_START: std::cout << "录像开始" << std::endl; break; case CVR_RECORD_STATUS_STOP: std::cout << "录像停止" << std::endl; break; case CVR_RECORD_STATUS_FAILED: std::cout << "录像失败" << std::endl; break; default: break; } } int main() { // 初始化CVRSDK if (!CVRSDK_Init()) { std::cout << "CVRSDK初始化失败" << std::endl; return -1; } // 创建CVR句柄 DWORD dwHandle = CVRSDK_CreateHandle(); if (dwHandle == 0) { std::cout << "创建CVR句柄失败" << std::endl; return -1; } // 设置回调函数 CVRSDK_SetRecordStatusCallback(dwHandle, RecordStatusCallback, NULL); // 设置录像文件保存路径 std::string filePath = "D:\\Recordings\\"; if (!CVRSDK_SetRecordPath(dwHandle, filePath.c_str())) { std::cout << "设置录像文件保存路径失败" << std::endl; return -1; } // 设置录像文件名 std::time_t t = std::time(nullptr); char fileName[MAX_PATH]; std::strftime(fileName, sizeof(fileName), "%Y%m%d%H%M%S", std::localtime(&t)); if (!CVRSDK_SetRecordFileName(dwHandle, fileName)) { std::cout << "设置录像文件名失败" << std::endl; return -1; } // 开始录像 if (!CVRSDK_StartRecord(dwHandle)) { std::cout << "开始录像失败" << std::endl; return -1; } // 录制一段时间(例如10秒) Sleep(10000); // 停止录像 if (!CVRSDK_StopRecord(dwHandle)) { std::cout << "停止录像失败" << std::endl; return -1; } // 释放CVR句柄 CVRSDK_ReleaseHandle(dwHandle); // 释放CVRSDK CVRSDK_Cleanup(); return 0; } ``` 请注意,此示例仅用于演示目的,并未包含完整的错误处理和其他功能。在实际使用中,你可能需要根据自己的需求进行修改和完善。另外,确保在编译和运行代码之前已经正确安装和配置了海康CVR SDK,并将相关的库文件和头文件路径添加到项目设置中。在实际应用中,你还需要根据海康CVR SDK的文档和示例代码来使用其提供的其他功能和接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值