安卓GB28181云台控制和预置位查询

8 篇文章 0 订阅
7 篇文章 0 订阅

     多数安卓手机摄像头是支持调焦距的, GB28181标准定义了云台操作,  只要安卓端实现云台XML指令解析, 实时视频回看时远程控制安卓摄像头焦距调整是一个很实用的功能。 

    GB28181云台控制属于设备控制的一部分,使用SIP Message方法实现,走无应答命令流程。和云台相关的还有预置位查询,要走有应答命令流程。

     云台控制和其他设备控制的XML定义差不多, 下面是一个具体的实例:

<?xml version="1.0" encoding="GB2312"?>
    <Control>
      <CmdType>DeviceControl</CmdType>
      <SN>32211</SN>
      <DeviceID>31010000011380000013</DeviceID>
      <PTZCmd>A50F0100000000B5</PTZCmd>
    </Control>

      XML中最关键的是PTZCmd元素, PTZCmd在GB28181-2016中有详细定义,总共8个字节,定义格式如下:

字节字节1字节2字节3字节4字节5字节6字节7字节8
含义A5H组合码1地址指令数据1数据2组合码2校验码

    8个字节中,最重要的字节4(指令码), 定义了云台各种操作类型。字节5, 6, 7主要用来传递指令相关参数。

    字节1是首字节,固定为A5H。

    针对PTZ, 字节4的第7和第6位都是0, 第5和第4位用来镜头调焦距, 第3和第2位是云台垂直方向控制, 第1和第0位是云台水平方向控制。解析时需要注意的是镜头焦距调整指令, 云台垂直上下指令、云台水平左右指令三者可以组合, 可能一条控制消息要执行三种类型的云台控制, 实际实现中要处理好。

    实际云台操作中,会先发一个云台控制SIP Message, 紧接着再发一个云台停止指令SIP Message,云台停止指令中字节4的每一位都为0。

    更详细定义请参考28181-2016文档A.3,指令解析实现还是比较容易的。

    预置位查询属于网络设备信息查询的一部分,也使用SIP Message方法实现, 和云台控制不同的是,需要有响应消息, 下面给出一个查询和响应的具体XML实例:

<?xml version="1.0" encoding="GB2312"?>
    <Query>
      <CmdType>PresetQuery</CmdType>
      <SN>7733</SN>
      <DeviceID>31010000011380000021</DeviceID>
    </Query>
<?xml version="1.0" encoding="GB2312"?>
    <Response>
    <CmdType>PresetQuery</CmdType>
    <SN>7733</SN>
    <DeviceID>31010000011380000021</DeviceID>
    <PresetList Num="2">
    <Item>
    <PresetID>1</PresetID>
    <PresetName>安卓预置位1</PresetName>
    </Item>
    <Item>
    <PresetID>2</PresetID>
    <PresetName>安卓预置位2</PresetName>
    </Item>
    </PresetList>
    </Response>

      定义接口和Demo代码:

// Github: https://github.com/daniulive/SmarterStreaming
// Copyright (C) 1130758427@qq.com

package com.gb.ntsignalling;

public interface GBSIPAgentDeviceControlListener {

    /*
     * 收到远程启动控制命令
     */
    void ntsOnDeviceControlTeleBootCommand(String deviceId, String teleBootValue);

    /*
    * 云台控制
     */
    void ntsOnDeviceControlPTZCmd(String deviceId, String typeValue);
}


package com.gb.ntsignalling;

public interface GBSIPAgentQueryCommandListener {

    /*
     * 设备预置位查询
     */
    void ntsOnDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId);
}


package com.gb.ntsignalling;

public interface GBSIPAgent {

  void addDeviceControlListener(GBSIPAgentDeviceControlListener deviceControlListener);

  void addQueryCommandListener(GBSIPAgentQueryCommandListener queryCommandListener);

  /*
  预置位查询应答
  */
  boolean respondDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId, java.util.List<PresetItem> presetList);
}


public class MyAndroidG8181DemoImpl implements GBSIPAgentDeviceControlListener,
        GBSIPAgentQueryCommandListener {

    @Override
    public void ntsOnDeviceControlPTZCmd(String deviceId, String typeValue) {
        handler_.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "ntsOnDeviceControlPTZCmd device_id:" + device_id_ + " PTZType:" + ptz_type_);

                if (null == ptz_type_)
                    return;

                ptz_type_ = ptz_type_.trim();
                if (ptz_type_.length() != 16)
                    return;

                int instruction = hexStringToInt(ptz_type_.substring(6, 8));
                int combination_code2 = hexStringToInt(ptz_type_.substring(12, 14));

                if ((instruction & 0xc0) == 0 ) {
                    if ((instruction & 0x20) != 0) {
                        // Zoom Out
                        int zoom_speed = (combination_code2 >> 4) & 0xf;

                        Log.i(TAG, "ntsOnDeviceControlPTZCmd device_id:" + device_id_ + " PTZType:" + ptz_type_ + " Zoom Out, speed:" +zoom_speed);

                        cameraZoom(true, zoom_speed);
                    }
                    else if ((instruction & 0x10) != 0) {
                        // Zoom In
                        int zoom_speed = (combination_code2 >> 4) & 0xf;

                        Log.i(TAG, "ntsOnDeviceControlPTZCmd device_id:" + device_id_ + " PTZType:" + ptz_type_ + " Zoom In, speed:" +zoom_speed);

                        cameraZoom(false, zoom_speed);
                    }
                }
            }

            int hexStringToInt(String hex) {
                if (null == hex)
                    return 0;

                try
                {
                    int v = Integer.parseInt(hex, 16);
                    return v;
                }catch (Exception e) {
                    return  0;
                }
            }

            private String device_id_;
            private String ptz_type_;

            public Runnable set(String device_id, String ptz_type) {
                this.device_id_ = device_id;
                this.ptz_type_ = ptz_type;
                return this;
            }

        }.set(deviceId, typeValue),0);
    }

    @Override
    public void ntsOnDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId) {
        handler_.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "ntsOnDevicePresetQueryCommand from_user_name:" + from_user_name_ + ", sn:" + sn_ + ", device_id:" + device_id_);

                List<com.gb.ntsignalling.PresetItem> preset_list = new LinkedList<>();

                preset_list.add(new com.gb.ntsignalling.PresetItem("1", "安卓预置位1"));
                preset_list.add(new com.gb.ntsignalling.PresetItem("2", "安卓预置位2"));

                if (gb28181_agent_ != null )
                    gb28181_agent_.respondDevicePresetQueryCommand(this.from_user_name_, this.from_user_name_at_domain_, this.sn_, this.device_id_, preset_list);
            }

            private String from_user_name_;
            private String from_user_name_at_domain_;
            private String sn_;
            private String device_id_;

            public Runnable set(String from_user_name, String from_user_name_at_domain,String sn, String device_id) {
                this.from_user_name_ = from_user_name;
                this.from_user_name_at_domain_ = from_user_name_at_domain;
                this.sn_ = sn;
                this.device_id_ = device_id;
                return this;
            }

        }.set(fromUserName, fromUserNameAtDomain, sn, deviceId),0);
    }

}

     上面的代码我只实现了对焦距控制的指令解析,如果想处理其他云台指令,解析代码类似,不难实现,测试安卓机前后摄像头都支持焦距调节,实际测下来,效果还可以。更多问题可以联系qq: 1130758427

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
  1、支持国标GB28181平台、国标GB28181 IPC和国标GB28181 NVR设备同时接入 (支持GB28181-2011版本和GB28181-2016版本)     2、支持国标GB28181设备注册和注销,对所有设备进行管理,获取资源 对资源列表进行管理     3、支持国标GB28181的目录订阅,对接收的订阅通知进行处理     4、支持国标GB28181实时视频请求(支持UDP、TCP主动(tcpactive)、TCP被动(tcppassive))     5、支持国标GB28181 PTZ控制     6、支持国标GB28181 录像查询     7、支持国标GB28181 历史视频点播 (支持UDP、TCP主动(tcpactive)、TCP被动(tcppassive))     8、支持国标GB28181 历史视频下载 (支持UDP、TCP主动(tcpactive)、TCP被动(tcppassive))     9、支持对接收的国标实时视频码流和历史视频码流进行管理     10、支持将国标的PS码流转换成ES码流     11、支持丢包打印和断流打印     13、支持RTSP服务和RTSP会话管理     14、支持RTSP客户端 UDP传输和TCP传输     15、支持国标GB28181设备5000路左右的接入管理,支持国标请求视频在100路左右     16、支持国标28181设备和通道写入mysql数据库      17、支持设备的云台PTZ控制控制类型:上"up",下"down",左"left",右"right",左上"leftup",左下"leftdown",右上"rightup",右下"rightdown",镜头近"zoomin",镜头远"zoomout", 焦距远"focusfar",焦距近"focusnear", 设置预置"setpos",调预置"callpos"     18、支持历史视频的查询和历史视频的点播控制     19、支持对国标设备的控制,"record":录像开启和停止-通道id "guard":布放和撤防-报警通道id "reboot":设备重启-设备id "keyfame":强制关键帧-通道id     20、支持对实时视频的图片截图,通过http直接访问图片    21、支持rtmp和hls会话一直保留    22、支持报警消息(设备上线、下线和设备端报警)通过httpclient方式主动通知    23、支持公网和局域网同时存在    24、支持httpserver,接口支持http+json    25、支持设备上线、下线和设备报警通过httpclient通知到指定的httpserver   26、支持http+json设置平台信息  27、支持http+json获取资源组、资源等信息  29、支持国标28181级联上级

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值