java 使用onvif协议 PTZ 登录认证,获取摄像头位置, 控制摄像头转动,digest认证,拍照截图

 

1. 介绍

        前面公司做摄像头相关的项目,一开始使用的海康威视提供的相关接口来控制摄像头转动,获取位置等,后面发现由于大华的很多摄像头使用该接口却行不通,后面所以就转用通用的 onvif 协议来做相关的操作。

在网上找了很多篇文章,几乎都是c语言写的,java来做的很少,后面经过自己慢慢的摸索,终于自己用java写了一套比较完整的代码来使用onvif协议控制摄像头转动,获取摄像头位置,及登录授权获取token等接口。

onvif 协议只要摸入门,其实其他请求其接口还是很简单的, 有些人喜欢去下载wsdl文件来生成一个java代码架构,这种方式我也试过,虽然能生成出来,但是其中的代码太多,比如一个PTZ操作就是几十个java文件,

不方便查阅,使用起来困难。我比较推荐使用 (ONVIF Device Test Tool) 这款软件来连接摄像头,让后做相关的控制,它会给你呈现出你发送某个接口的xml文件是什么内容,以及返回的xml文件。拿到xml文件后你就

可以写一个http请求,通过发送xml流的方式来请求摄像头服务就可以了,这样来说,整个过程就相当简单了。

 

2. 项目结构

      

      这点我先给大家介绍一下我们onvif一个项目结构。主要有两个类,一个 OnvifDeviceInvoker,这个类主要是读取相关的xml,发送http请求, 包含:获取云台位置参数,控制摄像头转动,获取token三个接口。

      OnvifUtil: 主要包含用户密码加密,读取xml文件,发送xml流post请求, onvif值 与 osd值相互转化的工具类。 这点我介绍一为什么要做这个转化,因为我们转动摄像的角度通常用0°~360°来记录,而onvif值

      却是通常用-1到+1来记录,不同的值标识不通的角度。而且大华和海康威视还对应的不一样。 onvif值 对应 osd值 如图所示:     

GetProfiles.xml:       请求获取token的xml文件

GetStatus.xml:         请求获取摄像头位置的xml文件

 AbsoluteMove.xml:  请求转动摄像头的xml文件

GetSnapshotUri.xml:请求抓取图片的xml文件。特别说一下: 请求这个xml流之后会返回一个xml文件,

                                    获取里面的图片地址,然后再次请求这个地址,这个地址是需要经过digest认证,

                                    所以在请求后第一次会返回 一个401状态码,获取heder参数 WWW-Authenticate,

                                   用于digest 认证。示例如下:

请求示例:

生成digest加密后的认证字符串方法

拍照暂时不介绍了,具体代码,下面有完整的贴出!

      

        

 

3. 代码展示

       CameraBrandEnum 标注品牌的枚举类,主要用于不同品牌的 ONVIF与OSD转化转化的区别

public enum CameraBrandEnum {

    DH("大华", "DH"),

    HKWS("海康威视", "HKWS");

    private String name;

    private String value;


    CameraBrandEnum(String name, String value) {
        this.name = name;
        this.value = value;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public String getValue() {
        return value;
    }
}

   AbsoluteMoveReq, Digest,GetStatusResp,DigestAuthenticateDto:参数实体相关类

@Data
public class AbsoluteMoveReq {

    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "摄像头云台垂直位置 y")
    private int tiltPos;

    @ApiModelProperty(value = "摄像头云台水平位置 x")
    private int panPos;

    @ApiModelProperty(value = "摄像头云台倍数参数")
    private int zoomPos;

}
@Data
public class Digest {

    /** 加密后的密码 */
    private String password;

    /** 随机字符串 */
    private String nonce;

    /** 时间 2010-09-16T07:50:45Z */
    private String date;

    /** 用户 */
    private String username;

}
@Data
public class GetStatusResp {


    @ApiModelProperty(value = "摄像头云台垂直位置 y")
    private int tiltPos;

    @ApiModelProperty(value = "摄像头云台水平位置 x")
    private int panPos;

    @ApiModelProperty(value = "摄像头云台倍数参数")
    private int zoomPos;

}
/**
 * Digest 认证实体 
 */
@Data
public class DigestAuthenticateDto {

    private String nonce;

    private String qop;

    private String realm;
}

 

OnvifUtil: 工具类
package com.zdkj.iot.shared.onvif.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.zdkj.iot.commons.exception.IOTException;
import com.zdkj.iot.shared.onvif.dto.Digest;
import com.zdkj.iot.shared.onvif.dto.DigestAuthenticateDto;
import com.zdkj.iot.shared.onvif.enums.CameraBrandEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class OnvifUtil {

    /**
     *  获取加密的用户密码
     * @param psw 原密码
     * @return 加密的密码
     */
    public static Digest getEncryptionPassword(String username, String psw) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'",
                Locale.getDefault());
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            throw new IOTException("创建SHA-1加密方法失败");
        }
        // nonce需要用Base64解码一次
        String nonce= getNonce();
        String date = df.format(new Date());
        byte[] b1 = Base64.decode(nonce.getBytes());
        // 生成字符字节流
        byte[] b2 =  date.getBytes(); // "2018-01-10T11:00:00Z";
        byte[] b3 = psw.getBytes();
        // 根据我们传得值的长度生成流的长度
        // 利用sha-1加密字符
        md.update(b1, 0, b1.length);
        md.update(b2, 0, b2.length);
        md.update(b3, 0, b3.length);

        Digest digest = new Digest();
        digest.setNonce(nonce);
        digest.setDate(date);
        digest.setUsername(username);
        digest.setPassword(Base64.encode(md.digest()).trim());

        // 生成最终的加密字符串
        return digest;
    }

    /**
     *  替换授权相关的字符串
     */
    public static String strRepelce(Digest dig
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用Java实现ONVIFPTZ控制,可以按照以下步骤进行: 1. 首先,需要通过Java的网络编程技术连接到ONVIF设备。可以使用Java的Socket类库来建立网络连接。为此,需要知道ONVIF设备的IP地址和端口号。 2. 通过建立的网络连接,可以发送SOAP消息来实现PTZ控制ONVIF协议是基于SOAP的,使用SOAP消息来与设备进行通信。SOAP消息包含了控制云台的指令,比如移动、变焦、调亮度等。 3. 需要熟悉ONVIF协议中与PTZ相关的消息格式和内容。ONVIF协议定义了一系列用于设备管理和控制的消息结构。可以通过查阅ONVIF协议的文档来了解如何构建PTZ控制相关的消息。 4. 解析设备返回的响应消息,根据响应结果判断控制是否成功。设备会返回一个SOAP响应消息,其中包含了对控制指令的处理结果。可以使用Java的XML解析库来解析返回的SOAP响应消息。 5. 根据需要编写Java代码来完成PTZ控制的具体功能。可以通过构建合适的SOAP消息发送给设备,实现云台的移动、变焦、调光等操作。 6. 进行测试和调试,确保PTZ控制功能正常工作。可以通过编写简单的Java应用程序来测试PTZ控制功能,模拟用户对云台的操作。 需要注意的是,使用Java实现ONVIFPTZ控制需要熟悉ONVIF协议的相关内容,并了解SOAP消息的构成和解析过程。此外,还需要有一定的网络编程经验和Java编程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值