上篇文章介绍利用百度鹰眼sdk对运动轨迹做纠偏、去噪、绑路处理。本篇将介绍鹰眼sdk的另一个功能——围栏,围栏的主要功能:将根据轨迹点判断手机终端是否进出围栏,并实时推送报警。应用场景:如进入目的地提醒、监控对象离开指定活动范围出发警报等等。
一 围栏简介
围栏类型
圆形围栏:进出圆形范围则推送报警
多边形围栏:进出多边形围栏则推送报警
线型围栏:偏离或回到设定路线则推送报警
行政区围栏:传入行政区名称,创建以行政区边界为界的围栏,进出报警
除围栏形状的区分,还分为:
(1)客户端围栏:围栏的创建、计算和报警均在本地鹰眼SDK完成,无需联网即可完成围栏运算,注:目前客户端围栏只支持圆形围栏
(2)服务端围栏:围栏的创建、计算和报警的发起都在服务端完成,依赖于轨迹点上传至服务端才能进行围栏进算。
创建圆形围栏和多边形围栏在地图上显示的效果如下
二 创建围栏api详解
1.流程图
2.初始化客户端采集轨迹数据
请先申请apikey和serviceId,具体工程配置请见篇头百度地图(四)文章中描述
//以下都是伪代码
/**
* 初始化鹰眼sdk客户端,
*/
LBSTraceClient mClient = mClient = new LBSTraceClient(mContext);
//初始化鹰眼服务端,serviceId:服务端唯一id,entityName:监控的对象,可以是手机设备唯一标识
Trace mTrace = new Trace(serviceId, entityName);
mClient.startTrace(trackApp.mTrace, traceListener);//开始服务
trackApp.mClient.startGather(traceListener);//开启采集
//轨迹服务监听器
private OnTraceListener traceListener = new OnTraceListener() {
/**
* 推送消息回调接口
* @param messageType 状态码
* 0x01:配置下发,0x02:语音消息,0x03:服务端围栏报警消息,0x04:本地围栏报警消息
*/
@Override
public void onPushCallback(byte messageType, PushMessage pushMessage) {
if (messageType < 0x03 || messageType > 0x04) {
return;
}
/**
* 获取报警推送消息
*/
FenceAlarmPushInfo alarmPushInfo = pushMessage.getFenceAlarmPushInfo();
alarmPushInfo.getFenceId();//获取围栏id
alarmPushInfo.getMonitoredPerson();//获取监控对象标识
alarmPushInfo.getFenceName();//获取围栏名称
alarmPushInfo.getPrePoint();//获取上一个点经度信息
AlarmPoint alarmPoin = alarmPushInfo.getCurrentPoint();//获取报警点经纬度等信息
alarmPoin.getCreateTime();//获取此位置上传到服务端时间
alarmPoin.getLocTime();//获取定位产生的原始时间
if(alarmPushInfo.getMonitoredAction() == MonitoredAction.enter){//动作类型
//进入围栏
}else if(alarmPushInfo.getMonitoredAction() == MonitoredAction.exit){
//离开围栏
}
}
//......这里省略此接口的其他方法
};
更多轨迹采集api详解请阅读篇头百度地图(四)文章
3.创建围栏
/**
* 创建客户端圆形围栏,注:目前客户端围栏只支持圆形围栏
* tag - 这次请求的唯一标识
* serviceId -轨迹服务ID
* fenceName - 围栏名称
* entityName- 监控对象唯一标识,如果是手机,请用手机的唯一id
* center - 围栏圆心
* radius - 围栏半径
* denoise - 围栏去噪精度,gps定位和网络定位都存在精度误差,会造成围栏误报警;
如设置denoise=30,则定位精度大于30米的轨迹点都不会参与围栏计算。
平均精度参考:GPS定位精度均值为15米,WIFI定位精度均值为40米,基站定位精度均值为300米。
* coordType - 坐标类型
*/
CreateFenceRequest request = CreateFenceRequest.buildLocalCircleRequest(tag, serviceId, fenceName,
entityName, circleCenter, radius, denoise, CoordType.bd09ll);
/**
* 创建服务端圆形围栏
* 参数与客户端圆形围栏一样
*/
request = CreateFenceRequest.buildServerCircleRequest(tag, serviceId, fenceName,
entityName, circleCenter, radius, denoise, CoordType.bd09ll);
/**
* 创建服务端多边形围栏
* vertexes - 顶点坐标集合,List<com.baidu.trace.model.LatLng>
* 顶点可设置地图点击监听获取,mBaiduMap.setOnMapClickListener
*/
request = CreateFenceRequest.buildServerPolygonRequest(tag,serviceId, fenceName,
entityName, vertexes, denoise, CoordType.bd09ll);
/**
* 创建服务端线形围栏
* vertexes - 顶点坐标集合,List<com.baidu.trace.model.LatLng>
* offset - 偏离路线的垂直距离,偏离大于offset 报警
*/
request = CreateFenceRequest.buildServerPolylineRequest(tag,serviceId, fenceName,
entityName, vertexes, offset, denoise, CoordType.bd09ll);
/**
* 创建服务端行政区围栏
* district:行政区名称,注意写全,如北京市西城区
*/
request = CreateFenceRequest.buildServerDistrictRequest(tag,serviceId, fenceName, entityName,
district, denoise);
//发起创建围栏请求
mClient.createFence(request, fenceListener);
4.围栏操作的监听器
OnFenceListener fenceListener = new OnFenceListener() {
@Override
public void onCreateFenceCallback(CreateFenceResponse response) {
//创建围栏响应结果,能获取围栏的一些信息
if(StatusCodes.SUCCESS != response.getStatus()){
return;
}
response.getTag();//请求标识
response.getDistrict();//获取行政区名称
response.getFenceId();//创建的围栏id
response.getFenceShape();//围栏形状
response.getFenceType();//围栏类型(本地围栏、服务端围栏)
//...方法不一一列举了,比较简单
}
@Override
public void onUpdateFenceCallback(UpdateFenceResponse response) {
//更新围栏响应结果
//...
}
@Override
public void onDeleteFenceCallback(DeleteFenceResponse response) {
//删除围栏响应结果
response.getFenceIds();//获取删除的围栏id
//...
}
@Override
public void onFenceListCallback(FenceListResponse response) {
//获取围栏列表响应结果
response.getSize();//围栏个数
List<FenceInfo> fenceInfos = response.getFenceInfos();//获取围栏信息列表
for (FenceInfo fenceInfo : fenceInfos) {
switch (fenceInfo.getFenceShape()) {//判断围栏形状
case circle://圆形
CircleFence circleFence = fenceInfo.getCircleFence();
circleFence.getFenceId();
circleFence.getCenter();
circleFence.getRadius();
circleFence.getDenoise();//去噪精度
circleFence.getMonitoredPerson();//监控设备的唯一标识
//...获取圆心和半径就可以在地图上画圆形图层
break;
case polygon://多边形
PolygonFence polygonFence = fenceInfo.getPolygonFence();
//获取多边形顶点集合
List<com.baidu.trace.model.LatLng> polygonVertexes = polygonFence.getVertexes();
//...获取顶点坐标可以在地图上画多边形图层
break;
case polyline://线形
PolylineFence polylineFence = fenceInfo.getPolylineFence();
//获取线形顶点集合
List<com.baidu.trace.model.LatLng> polylineVertexes = polylineFence.getVertexes();
//...
break;
case district:
DistrictFence districtFence = fenceInfo.getDistrictFence();
districtFence.getDistrict();//获取行政区名称
//...注:行政区围栏并能像多边形一样返回定点集合,行政区范围很大,点很多...,
//如果想获取行政区的边界点坐标结合,请使用baidumapapi_search_v4_3_1.jar中DistrictSearch类
break;
}
}
}
@Override
public void onMonitoredStatusCallback(MonitoredStatusResponse response) {
//查询监控对象状态响应结果
List<MonitoredStatusInfo> monitoredStatusInfos = response.getMonitoredStatusInfos();
for (MonitoredStatusInfo monitoredStatusInfo : monitoredStatusInfos){
monitoredStatusInfo.getFenceId();
MonitoredStatus status = monitoredStatusInfo.getMonitoredStatus();//获取状态
switch (status){
case in:
//监控的设备在围栏内
break;
case out:
//监控的设备在围栏外
break;
case unknown:
//监控的设备状态未知
break;
}
}
}
@Override
public void onMonitoredStatusByLocationCallback(MonitoredStatusByLocationResponse response){
//查询监控对象在指定位置的状态响应结果,api同onMonitoredStatusCallback
}
@Override
public void onHistoryAlarmCallback(HistoryAlarmResponse response) {
//查询围栏历史报警信息响应结果
//获取报警信息列表,FenceAlarmInfo继承FenceAlarmPushInfo
List<FenceAlarmInfo> fenceAlarmInfos = response.getFenceAlarmInfos();
}
};
创建围栏成功后,服务端时刻计算最新采集的轨迹点与围栏的地理关系,一旦进出围栏报警信息会通过OnTraceListener.onPushCallback方法回到给客户端,你可以在这里进行自己的业务了。
判断轨迹点进入围栏、离开围栏,推送报警效果如下
如果你没有在地图上画图层的需求,完全不必像图a、图b那样,只需要创建围栏,开启采集数据,等待报警信息的回调就可以了。
三 围栏查询、删除等api详解
以下api方法中的参数详见3中描述,基本一样;围栏监听器同用一个fenceListener,参见4中描述。
5.更新围栏
/**
* 以更新服务端圆形围栏为例,其他围栏同理
* fenceId:围栏id
* 更新围栏传入新的参数即可,如圆形围栏传入新的半径和圆心坐标
*/
UpdateFenceRequest updateRequest = UpdateFenceRequest.buildServerCircleRequest(tag, serviceId, fenceId,
fenceName, entityName, center, radius, denoise, coordType);
//发起更新围栏请求
mClient.updateFence(updateRequest , fenceListener);
6.删除围栏
/**
* 以删除服务端围栏为例
* deleteFenceIds:要删除的服务端围栏编号列表,List<Long>
*/
DeleteFenceRequest deleteRequest = DeleteFenceRequest.buildServerRequest(tag,serviceId, entityName, deleteFenceIds);
//发起删除围栏请求
mClient.deleteFence(deleteRequest , fenceListener);
7.查询围栏列表
/**
* 以查询服务端围栏为例
* fenceIds:服务端围栏编号列表,List<Long>,如传入null,表示查询所有围栏
*/
FenceListRequest request = FenceListRequest.buildServerRequest(tag,serviceId, entityName, fenceIds,CoordType.bd09ll);
//发起查询围栏请求
mClient.queryFenceList(request, fenceListener);
8.查询指定监控对象状态
/**
* 查询监控对象是否在围栏内,以查询服务端为例
* fenceIds:服务端围栏编号列表,List<Long>
* entityName:监控对象标识
*/
MonitoredStatusRequest request = MonitoredStatusRequest.buildServerRequest(tag, serviceId,entityName, fenceIds);
//发起查询请求
mClient.queryMonitoredStatus(request, fenceListener);
9.查询指定监控对象在指定位置的状态
/**
* 查询监控对象在指定位置是否在围栏内,以查询服务端为例
* latLng:位置点
*/
MonitoredStatusByLocationRequest request = MonitoredStatusByLocationRequest .buildServerRequest(tag, serviceId,
entityName, fenceIds, latLng, coordType);
//发起查询请求
mClient.queryMonitoredStatusByLocation(request, fenceListener);
10.查询围栏历史报警信息
/**
* 以查询服务端为例
* startTime:开始时间
* endTime:结束时间
*/
HistoryAlarmRequest request = HistoryAlarmRequest.buildServerRequest(tag, serviceId, startTime,
endTime, entityName, fenceIds, coordType)
//发起查询请求
mClient.queryFenceHistoryAlarmInfo(request, fenceListener);
好啦,到此,百度鹰眼sdk围栏部分就讲完了。
如果各位看官觉得文章不错,别忘了点个喜欢。
源码下载地址 https://github.com/zhuhaoHappig/BaiduMapFence
作者:zhh_happig
链接:http://www.jianshu.com/p/db11ae2bad4f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。