How does the Android GB28181 device access module implement real-time location subscription (MobilePosition)

Technical background

Real-time location (MobilePosition) subscription and reporting is particularly important for GB28281 device access terminals, such as mobile individual soldier equipment, law enforcement recorders, smart helmets, vehicle-mounted terminals, etc. Android national standard access devices obtain real-time longitude and latitude information, and according to certain The national standard service platform dynamically displays the positioning information of the front-end equipment in real time through an electronic map, thereby achieving visual and controllable management of the front-end access equipment. For example, 4G/5G law enforcement cameras, smart helmets, smart police helmets, individual soldiers, etc.

Let’s first look at the description of MobilePosition in GB/T28181-2016:

<elementname="TargetID"type="tg:deviceIDType"/>Mobile device location data notification
<! -- Command type: Mobile device location data notification (required) -->
<elementname="CmdType"fixed="MobilePosition"/>
<! --Command serial number (required)-->
<elementname="SN" type="integer"minInclusivevalue= "1"/>
<! -- Generate notification time (required) -->
<elementname="Time" type="dateTime"/>
<! --Longitude (required)--> <elementname="Longitude"type="double"/>
<! -- Latitude (required)--> <elementname="Latitude"type="double"/>
<! --Speed, unit: km/h (optional) -->
<elementname="Speed"type="double"/>
<!--Direction, the value is the clockwise angle between the current camera direction and true north, the value range is 0°~360°, unit: (°) (optional)-->
<elementname="Direction"type="double"/>
<! --Altitude, unit: m (optional) -->
<elementname="Altitude"type="tg:deviceIDType"/>

1. Configure the device to support location subscription: The GB28181 device needs to be configured to support the location subscription function. It can be configured through the device management platform or the management interface of the device itself.

2. Obtain the SIP server address and port: During the location subscription process, you need to know the address and port information of the SIP server.

3. Send a subscription request: Use the SIP protocol to send a location subscription request. Define the requested subscription parameters in the SIP message, such as the subscribed device ID, subscription type, subscription time interval, etc.

4. Respond to the subscription request: After receiving the location subscription request, the SIP server will return a response message indicating that the subscription is successful.

5. Receive location update messages: When the device location changes, the device will send a location update message to the SIP server. The SIP server will deliver the message to the subscriber.

6. Process the location update message: After receiving the location update message, the subscriber can perform corresponding processing as needed, such as displaying the device location on the map in real time, recording the device’s whereabouts, etc.

Technical implementation

This article takes the Andorid platform GB28181 device docking module of Daniu Live SDK as an example. The basic structure of the Android national standard access terminal DevicePosition is as follows:

/*
 *DevicePosition.java
 *
 * Author: https://daniusdk.com
 *
 */
public class DevicePosition {
    private String mTime; // The time when location information is generated, the format is: 2022-03-16T10:37:21, yyyy-MM-dd'T'HH:mm:ss
    private String mLongitude; // Longitude
    private String mLatitude; //Latitude
    private String mSpeed; // Speed, unit: km/h
    private String mDirection; // Direction, the value is the clockwise angle between the current camera direction and true north, the value range is 0°~360°, unit: (°)
    private String mAltitude; // Altitude, unit: 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);
    }
}

When there is a SUBSCRIBE request requesting location update, return the request to the upper layer:

/*
 * Device location request, this is mainly used for mobile device location subscription
 * @param interval request interval, unit is milliseconds
 */
void ntsOnDevicePositionRequest(String deviceId, int interval);

Provides an external interface for updating device location information:

/*
 *Update device location information
 */
boolean updateDevicePosition(String deviceId, DevicePosition position)

The upper layer specifically handles ntsOnDevicePositionRequest:

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

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

            if (mLongitude != null & amp; & amp; mLatitude != null) {
                com.gb28181.ntsignalling.DevicePosition device_pos = new com.gb28181.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);
}

How to add a device:

private void addTestDevice() {
com.gb28181.ntsignalling.Device gb_device = new com.gb28181.ntsignalling.Device("34020000001380000037", "An Android device", Build.MANUFACTURER, Build.MODEL,
                    "Universe","Mars1","Mars", true);
        
     if (mLongitude != null & amp; & amp; mLatitude != null) {
          com.gb28181.ntsignalling.DevicePosition device_pos = new com.gb28181.ntsignalling.DevicePosition();

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

          gb_device.setSupportMobilePosition(true); // Set support for mobile location reporting
      }

      gb28181_agent_.addDevice(gb_device);
}