Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注

技术背景

我们在做GB28181设备接入端的时候,其中有个功能,不难但非常重要:那就是GB28181实时位置的订阅(mobileposition subscribe)和上报(notify)。

特别是执法记录仪、智能安全帽、车载终端等场景下,现场人员的实时位置是国标平台侧非常关注的。国标平台侧通过周期性的获取GB28181设备接入端的经纬度信息,并在电子地图显示,需要看现场的情况,点开图标,进行音视频回传和语音广播语音对讲等操作,现场人员的总体概况一目了然。

规范解读

其他不表,我们先看看GB/T28181-2016规范中,关于订阅通知流程:

Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注_第1张图片

基本流程和注解如下:

  1. 国标服务平台向Android平台GB28181设备接入终端发送SUBSCRIBE消息体,并携带Expire头域指定订阅过期时间;
  2. Android平台GB28181设备接入终端收到SUBSCRIBE后,200 OK响应;
  3. Android平台GB28181设备接入终端发送 NOTIFY 消息相关的位置信息,并使用Event头域描述订阅事件,国标GB28181的移动设备位置订阅这个值是"presence"
  4. 国标服务平台收到 Android平台GB28181设备接入终端NOTIFY消息后,200 OK响应;
  5. NOTIFY...200 OK...NOTIFY...200 OK...etc..
  6. 国标服务平台在订阅过期之前,向Android国标接入终端发送刷新订阅 SUBSCRIBE 消息,消息头域中使用 Event头域描述订阅事件,消息体中携带订阅的详细参数,使用 Expire头域指定订阅过期时间;
  7. Android平台GB28181设备接入终端收到订阅消息后,向国标服务平台发送200 OK响应;
  8. NOTIFY...200 OK...NOTIFY...200 OK........
  9. 如国标服务平台需要取消订阅,可以向Android平台GB28181设备接入终端发送取消订阅SUBSCRIBE消息,消息头域中使用Event头域描述订阅事件,消息体中携带订阅的详细参数,Expire头域值为0;
  10. Android国标接入终端收到订阅消息后,向国标服务平台发送200 OK响应,取消向国标服务平台发送实时位置通知消息,取消订阅成功的话,也会发一个最终的NOTIFY给国标服务端;
  11. 这里需要注意的是:Android平台GB28181设备接入终端收到SUBSCRIBE请求后,会检查SUBSCRIBE请求中"Expires"值的大小,当且仅当这个值大于0且小于1小时,并且小于Notifier配置的最小值时,Notifier可能会返回一个"423 Interval too  small"错误,并包含一个""Min-Expires" 头域;
  12. Android国标接入端发送的NOTIFY请求超时的话,应该移除这个订阅;
  13. NOTIFY request必须包含"Subscription-State"头,有三个可选的值:"active", "pending", "terminated". 当值是"active"或"pending"时,应该也包含一个”expires“参数,显示订阅剩余时间。

GB/T28181-2016针对MobilePosition描述

移动设备位置数据通知




 
 
  
  
 
 



技术实现

Android平台GB28181设备接入端,启动GB28181后,调用InitGB28181Agent()的时候,添加设备:

Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注_第2张图片

 相关代码如下:

   /*
    * Camera2Activity.java
    * Author: daniusdk.com
    */ 
   private boolean initGB28181Agent() {
        if ( gb28181_agent_ != null )
            return  true;

        getLocation(context_);

        String local_ip_addr = IPAddrUtils.getIpAddress(context_);
        Log.i(TAG, "initGB28181Agent local ip addr: " + local_ip_addr);

        if ( local_ip_addr == null || local_ip_addr.isEmpty() ) {
            Log.e(TAG, "initGB28181Agent local ip is empty");
            return  false;
        }

        gb28181_agent_ = GBSIPAgentFactory.getInstance().create();
        if ( gb28181_agent_ == null ) {
            Log.e(TAG, "initGB28181Agent create agent failed");
            return false;
        }

        gb28181_agent_.addListener(this);
        gb28181_agent_.addPlayListener(this);
		
        gb28181_agent_.addTalkListener(this);
        gb28181_agent_.addAudioBroadcastListener(this);
        gb28181_agent_.addDeviceControlListener(this);
        gb28181_agent_.addQueryCommandListener(this);

        // 必填信息
        gb28181_agent_.setLocalAddress(local_ip_addr);
        gb28181_agent_.setServerParameter(gb28181_sip_server_addr_, gb28181_sip_server_port_, gb28181_sip_server_id_, gb28181_sip_domain_);
        gb28181_agent_.setUserInfo(gb28181_sip_username_, gb28181_sip_password_);

        // 可选参数
        gb28181_agent_.setUserAgent(gb28181_sip_user_agent_filed_);
        gb28181_agent_.setTransportProtocol(gb28181_sip_trans_protocol_==0?"UDP":"TCP");

        // GB28181配置
        gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);

        com.gb.ntsignalling.Device gb_device = new com.gb.ntsignalling.Device("34020000001310000001", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
                    "宇宙","火星1","火星", true);

        if (mLongitude != null && mLatitude != null) {
            com.gb.ntsignalling.DevicePosition device_pos = new com.gb.ntsignalling.DevicePosition();

            device_pos.setTime(mLocationTime);
            device_pos.setLongitude(mLongitude);
            device_pos.setLatitude(mLatitude);
            gb_device.setPosition(device_pos);

            gb_device.setSupportMobilePosition(true); // 设置支持移动位置上报
        }

        gb28181_agent_.addDevice(gb_device);


        if (!gb28181_agent_.createSipStack()) {
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.createSipStack failed.");
            return  false;
        }

        boolean is_bind_local_port_ok = false;

        // 最多尝试5000个端口
        int try_end_port = gb28181_sip_local_port_base_ + 5000;
        try_end_port = try_end_port > 65536 ?65536: try_end_port;

        for (int i = gb28181_sip_local_port_base_; i < try_end_port; ++i) {
            if (gb28181_agent_.bindLocalPort(i)) {
                is_bind_local_port_ok = true;
                break;
            }
        }

        if (!is_bind_local_port_ok) {
            gb28181_agent_.releaseSipStack();
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.bindLocalPort failed.");
            return  false;
        }

        if (!gb28181_agent_.initialize()) {
            gb28181_agent_.unBindLocalPort();
            gb28181_agent_.releaseSipStack();
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.initialize failed.");
            return  false;
        }

        return true;
    }

Android平台GB28181设备接入端DevicePosition设计如下:

/*
 * DevicePosition.java
 * Author: daniusdk.com
 */
public class DevicePosition {
    private String mTime; // 产生位置信息的时间,格式如:2022-03-16T10:37:21, yyyy-MM-dd'T'HH:mm:ss
    private String mLongitude; // 经度
    private String mLatitude; //纬度
    private String mSpeed; // 速度,单位:km/h
    private String mDirection; // 方向,取值为当前摄像头方向与正北方的顺时针夹角,取值范围0°~360°,单位:(°)
    private String mAltitude; // 海拔高度,单位:m
 
    public String getTime() {
        return mTime;
    }
 
    public void setTime(String time) {
        this.mTime = time;
    }
 
    public String getLongitude() {
        return mLongitude;
    }
 
    public void setLongitude(double longitude) {
        this.mLongitude = String.valueOf(longitude);
    }
 
    public void setLongitude(String longitude) { this.mLongitude =longitude; }
 
    public String getLatitude() {
        return mLatitude;
    }
 
    public void setLatitude(double latitude) {
        this.mLatitude = String.valueOf(latitude);
    }
 
    public void setLatitude(String latitude) { this.mLatitude = latitude;}
 
    public String getSpeed() {
        return mSpeed;
    }
 
    public void setSpeed(double speed) {
        this.mSpeed = String.valueOf(speed);
    }
 
    public String getDirection() {
        return mDirection;
    }
 
    public void setDirection(double direction) {
        this.mDirection = String.valueOf(direction);
    }
 
    public String getAltitude() {
        return mAltitude;
    }
 
    public void setAltitude(double altitude) {
        this.mAltitude = String.valueOf(altitude);
    }
}

当有SUBSCRIBE request请求位置更新,上层处理如下:

    @Override
    public void ntsOnDevicePositionRequest(String deviceId, int interval) {
        handler_.postDelayed(new Runnable() {
            @Override
            public void run() {
                getLocation(context_);

                Log.v(TAG, "ntsOnDevicePositionRequest, deviceId:" + this.device_id_ + ", Longitude:" + mLongitude
                        + ", Latitude:" + mLatitude + ", Time:" + mLocationTime);


                if (mLongitude != null && mLatitude != null) {
                    com.gb.ntsignalling.DevicePosition device_pos = new com.gb.ntsignalling.DevicePosition();

                    device_pos.setTime(mLocationTime);
                    device_pos.setLongitude(mLongitude);
                    device_pos.setLatitude(mLatitude);

                    if (gb28181_agent_ != null ) {
                        gb28181_agent_.updateDevicePosition(device_id_, device_pos);
                    }
                }
            }

            private String device_id_;
            private int interval_;

            public Runnable set(String device_id, int interval) {
                this.device_id_ = device_id;
                this.interval_ = interval;
                return this;
            }

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

总结

国标平台侧获取到Android平台GB28181设备接入端的实时位置信息后,可以非常方便的根据实时经纬度信息,把前端设备位置标注到地图服务上。Android平台获取实时经纬度并无难度,这里不再赘述。

 

你可能感兴趣的:(GB28181接入,流媒体,GB28181,GB28181经纬度,MobilePosition,GB28181,GPS,GB28181实时位置)