swift 百度地图加载与百度地图电子围栏加载

3 篇文章 0 订阅
1 篇文章 0 订阅

最近在写百度地图电子围栏加载,研究源码,也花了一些时间。

1、百度电子围栏整体思路

    1)用户创造实体,赋予监控权限

    2)对该实体创造电子围栏,有服务端和本地端两种方式,先创造实体,上传到的服务器中。在对实体创造电子围栏,服务器端的有多边形,圆形,本地端的只有圆形围栏。

    3)查询对于该实体的电子围栏操作,从代理返回值中在地图上画出围栏。

    4)检测实体运动轨迹,若超出范围,则报警。(创建实体,允许获得用户轨迹,百度后台返回的代理)

一、工程配置

    按照官网提示的即可,swift要加桥接而已。

二、

0、调用百度地图服务之前,都需要设置ak mcode信息,否则调用不到

let sop: BTKServiceOption = BTKServiceOption(ak: "ksqN5xi5s2Kpc6jlqW6Km5zk524pDhmy", mcode: "www.arvin.com.baiduMap", serviceID: 200447, keepAlive: false)
        BTKAction.sharedInstance().initInfo(sop) 

ak 是在百度地图申请的,mcode是工程的Bundle id。

1、添加百度地图,因为我们用鹰眼围栏是需要在地图上画出图形来的。

 _mapView = BMKMapView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))

        self.view.addSubview(_mapView!)

按照百度地图官网或者其demo即可。

2、添加百度地图的第一步是首先需要创建实体,并给实体创建电子围栏,上传给百度地图服务器

    //设置地理围栏
    func creatMapFrence() {
        //创建entity实体 entityDesc 字母数字下划线
        let request: BTKAddEntityRequest = BTKAddEntityRequest(entityName: "entityA", entityDesc: "ThissaentityA", columnKey: nil, serviceID: 00000, tag: 1)
        BTKEntityAction.sharedInstance().addEntity(with: request, delegate: self)
         //创建一个名称为“server_circle_fence” 的服务端圆形地理围栏,圆心坐标为东经116.3134度、北纬40.0478度,围栏半径为50米。它的监控对象为“entityA”,且当entityA这个终端实体的定位精度大于50米的轨迹点不参与此围栏的计算。
        //圆心40.055573298959558)Optional(116.30384089417596
        let center: CLLocationCoordinate2D = CLLocationCoordinate2D.init(latitude: 40.055573298959558, longitude: 116.30384089417596)
        //构造将要创建的新的围栏对象
        let fence: BTKServerCircleFence = BTKServerCircleFence(center: center, radius: 450.0, coordType: .COORDTYPE_BD09LL, denoiseAccuracy: 50, fenceName: "firstFenceName", monitoredObject: "entityA")
        //构建请求对象
        let circleRequest: BTKCreateServerFenceRequest = BTKCreateServerFenceRequest.init(serverCircleFence: fence, serviceID: 00000, tag: 1)
        //发起请求
        BTKFenceAction.sharedInstance().createServerFence(with: circleRequest, delegate: self)
      
    }

完成之后,我们需要调用创建实体是否成功的代理,判断是否创建成功

 //创建地理围栏返回代理
    func onCreateServerFence(_ response: Data!) {
        guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Any] else {//转化失败就返回
            return
        }
        print("创建地理围栏\(array)")
    }

2、搜索我们可以在鹰眼代理BTKFenceDelegate 中查询我们所创建的实体

//查询围栏
    func qureyMapFernce() {
        //构建请求对象
        let request = BTKQueryServerFenceRequest(monitoredObject: "entityA", fenceIDs: nil, outputCoordType: .COORDTYPE_BD09LL, serviceID: 000000, tag: 1)
        //发送查询请求
        BTKFenceAction.sharedInstance().queryServerFence(with: request, delegate: self)
        
    }

查询地理围栏并且在地图上画出地理围栏

    func onQueryServerFence(_ response: Data!) {
        guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Any] else {//转化失败就返回
            return
        }
        print("查询地理围栏\(array)")
        let size: NSInteger = array["size"] as! NSInteger
        //在地图上展示这些围栏
        //获取size 在地理位置信息
        //使用Annotation代表圆形围栏的圆心
        let centerAnnotations: NSMutableArray = NSMutableArray(capacity: size)
        //使用填充圆行围栏的覆盖物
        let radiusOverlays: NSMutableArray = NSMutableArray(capacity: size)
        //存储所有围栏的圆心位置,是为了确定地图的显示范围
        let coordinates: NSMutableArray = NSMutableArray(capacity: size)
        let dicFence: [[String: Any]] = array["fences"] as! [[String : Any]]
        
        for fence in dicFence {
            //筛选circle的圆
            let circle: String = fence["shape"] as! String
            if circle == "circle" {
                //解析数据 经纬度
                let fenceCenter: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: fence["latitude"] as! CLLocationDegrees, longitude: fence["longitude"] as! CLLocationDegrees)
                
                let fenceRadius: Double = fence["radius"] as! Double
                let fenceName: String = fence["fence_name"] as! String
                let denoiseAccuracy: NSInteger = fence["denoise"] as! NSInteger
                let monitoredObject: String = fence["monitored_person"] as! String
                
                //存贮圆心位置 /*略有问题*/
//                let coordinateValue: NSValue = NSValue.init(bytes: &fenceCenter, objCType: "CLLocationCoordinate2D")
                
                coordinates.add(fenceCenter)
                
                //构造Annotaion
                let annotation: BMKPointAnnotation = BMKPointAnnotation()
                annotation.coordinate = fenceCenter
                annotation.title = "预设名称\(fenceName)"
                annotation.subtitle = "半径:\(fenceRadius),去噪精度 \(denoiseAccuracy)"
                centerAnnotations.add(annotation)  //圆心数组
                
                //围栏的覆盖范围
                let coverageArea: BMKCircle = BMKCircle()
                coverageArea.coordinate = fenceCenter
                coverageArea.radius = fenceRadius
                
                radiusOverlays.add(coverageArea)
                
                
//                let annoationKey: NSValue = NSValue.value(annotation, withObjCType: <#UnsafePointer<Int8>#>)
                let annoationKey: NSValue = NSValue.init(nonretainedObject: annotation)  //转换NSDate
                
                //存储标注到围栏的映射
                let fenceObject: BTKServerCircleFence = BTKServerCircleFence(center: fenceCenter, radius: fenceRadius, coordType: .COORDTYPE_BD09LL, denoiseAccuracy: UInt(denoiseAccuracy), fenceName: fenceName, monitoredObject: monitoredObject)
                annotationMapToFenceObject.setObject(fenceObject, forKey: annoationKey)
                
                //存储标注到围栏ID的映射
                let fenceID: NSNumber = fence["fence_id"] as! NSNumber
                annotationMapToFenceID.setObject(fenceID, forKey: annoationKey)

            } else {
                
            }
        }
//        weak let weakSelf = self
        //在地图上展示围栏 //主队列 异步
        DispatchQueue.main.async {
            //清空原有的标注和覆盖物
            self._mapView?.removeOverlays(self._mapView?.overlays)
            self._mapView?.removeAnnotations(self._mapView?.annotations)
            //添加新的标注物和覆盖物
            self._mapView?.addAnnotations(centerAnnotations as! [Any])
            self._mapView?.addOverlays(radiusOverlays as! [Any])
            //设置地图的显示范围
            self.mapViewFitForCoordinates(points: coordinates)
        }
        
    }
//设置地图的显示范围
    func mapViewFitForCoordinates(points: NSArray) {
        var minLat: Double = 90.0
        var maxLat: Double = -90.0
        var minLon: Double = 180.0
        var maxLon: Double = -180.0
        for i in 0..<points.count {
            let coord: CLLocationCoordinate2D = points[i] as! CLLocationCoordinate2D
            minLat = fmin(minLat, coord.latitude)
            maxLat = fmax(maxLat, coord.latitude)
            minLon = fmin(minLon, coord.longitude)
            maxLon = fmax(maxLon, coord.longitude)
        }
        
        let center: CLLocationCoordinate2D = CLLocationCoordinate2DMake((minLat + maxLat) * 0.5, (minLon + maxLon) * 0.5)
        //设置经纬度范围
        let span = BMKCoordinateSpan(latitudeDelta: (maxLat - minLat) + 0.06, longitudeDelta: (maxLon - minLon) + 0.06)
        
        var region = BMKCoordinateRegion()
        region.center = center
        region.span = span
        
        self._mapView?.setRegion(region, animated: true)
    }
    
    
    //围栏的画图,需要实现这个代理,否则画不出来
    func mapView(_ mapView: BMKMapView!, viewFor overlay: BMKOverlay!) -> BMKOverlayView! {
        //判断是圆形
        if overlay is BMKCircle {
            let circleView = BMKCircleView.init(overlay: overlay)
            circleView?.fillColor = UIColor.init(red: 0, green: 0, blue: 1, alpha: 0.3)
            circleView?.strokeColor = UIColor.init(red: 0, green: 0, blue: 1, alpha: 0)
            return circleView
        } else {
            return nil
        }
        
        
        
    }

删除地理围栏

//删除围栏
    func deleteMapFrence() {
        //请求构造对象
        let request: BTKDeleteServerFenceRequest = BTKDeleteServerFenceRequest(monitoredObject: "entityA", fenceIDs: nil, serviceID: 200447, tag: 22)
        //发起删除请求
        BTKFenceAction.sharedInstance().deleteServerFence(with: request, delegate: self)
    }

删除地理围栏代理

 //删除围栏
    func onDeleteServerFence(_ response: Data!) {
        guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Any] else {//转化失败就返回
            return
        }
        print("删除地理围栏\(array)")
    }

更新地理围栏

//更新围栏
    func updateMapFrence() {
        //新的圆心
        let center: CLLocationCoordinate2D = CLLocationCoordinate2DMake(40.1578, 116.2234)
        //新的圆形围栏
        let fence: BTKServerCircleFence = BTKServerCircleFence(center: center, radius: 60, coordType: .COORDTYPE_BD09LL, denoiseAccuracy: 60, fenceName: "server_fence_60", monitoredObject: "entityB")
        //构建请求对象
        let request: BTKUpdateServerFenceRequest = BTKUpdateServerFenceRequest(serverCircleFence: fence, fenceID: 138, serviceID: 200447, tag: 1)
        //发起更新请求
        BTKFenceAction.sharedInstance().updateServerFence(with: request, delegate: self)

    }

实时查询

    //实时状态查询
    func querServerFenceStatus() {
        //实时状态查询
        //鹰眼iOS SDK支持查询指定监控对象的状态,监控对象即某个终端实体(,,),监控对象是指其相对其上的地理围栏的位置关系,是在圆形或
        //多边形围栏的内部还是外部,是否偏离了线性围栏等。
        let request: BTKQueryServerFenceStatusRequest = BTKQueryServerFenceStatusRequest(monitoredObject: "entityA", fenceIDs: nil, serviceID: 200447, tag: 25)
        //发起查询请求
        BTKFenceAction.sharedInstance().queryServerFenceStatus(with: request, delegate: self)
        
//        以下代码片段表示,假设“entityA”这个终端实体在东经120.44度,北纬40.11度的话,该终端实体和其上的fenceID为17、23、29的这几个服务端地理围栏的位置关系,只有这几个地理围栏的监控对象是“entityA”这个终端实体时才有意义,如果不知道有哪些地理围栏在监控“entityA”这个终端实体,则fenceIDs属性传入nil即可。
        let customLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(40.11, 120.44)
        //地理围栏ID列表
//        NSArray *fenceIDs = ["",""]
        //构建请求对象
        let requestB: BTKQueryServerFenceStatusByCustomLocationRequest = BTKQueryServerFenceStatusByCustomLocationRequest(monitoredObject: "entityA", customLocation: customLocation, coordType: .COORDTYPE_BD09LL, fenceIDs: nil, serviceID: 200447, tag: 28)
        //发起查询请求
        BTKFenceAction.sharedInstance().queryServerFenceStatusByCustomLocation(with: requestB, delegate: self)
        
    }

若是获取报警信息,我们应用的是BTKTraceDelegate的代理

//报警推送
    //当服务器围栏被触发之后,会通过长链接将报警信息推送给SDK,SDK会通过BTKActionDelete SDK会通过 BTKActionDelegate 协议的 -(void)onGetPushMessage:(BTKPushMessage *)message; 方法将报警信息推送给开发者。因此服务端围栏的报警推送要求网络畅通。当接收报警的手机断网或网络状态不好时,会导致报警推送失败,鹰眼服务端将在后续的10分钟之内每隔15s推送一次,直至收到成功响应。若10分钟之后仍未成功,将不再推送,但报警记录将存储在鹰眼服务端。为避免因此造成报警漏接收,开发者可定期使用历史报警查询接口同步报警信息。
    /*BTKTraceDelegate*/ //需要定义实体检测其轨迹
    func onGet(_ message: BTKPushMessage!) {
        //获得推送消息
        if (message.type != 0x03 && message.type != 0x04) {
            return;
        }
        let content: BTKPushMessageFenceAlarmContent = message.content as! BTKPushMessageFenceAlarmContent
        var fenceName: String = "「" + content.fenceName + "」"
        let monitoredObject = "「" + content.monitoredObject + "」"
        var action = ""
        if content.actionType == .FENCE_MONITORED_OBJECT_ACTION_TYPE_ENTER {
            action = "进入"
        } else {
            action = "离开"
        }
        let fenceType = ""
        if message.type == 0x03 {
            fenceName = "服务器围栏"
        } else {
            fenceName = "客户端围栏"
        }
        
        //通过触发报警的轨迹点,解析出触发报警的时间
        let currentPoint: BTKFenceAlarmLocationPoint = content.currentPoint
        let dataFormatter: DateFormatter = DateFormatter()
        dataFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let alarmDate: Date = Date(timeIntervalSince1970: TimeInterval(currentPoint.loctime))
        let alarmDateStr: String = dataFormatter.string(from: alarmDate)
        
        let puchMessage: String = "终端" + monitoredObject + "在" + alarmDateStr + action + fenceType + fenceName
        //
        print("推送消息\(puchMessage)")
        
        let deviceType: String = UIDevice.current.systemVersion
        let deviceTypeDouble: Double = Double(deviceType)!
        
        if deviceTypeDouble >= 10.0 {
            // 发送本地通知UNNotificationRequest
            let notificationContent: UNMutableNotificationContent = UNMutableNotificationContent()
            notificationContent.title = "报警" + fenceType
            notificationContent.body = puchMessage
            notificationContent.sound = UNNotificationSound.default()
            let notificationTrigger: UNTimeIntervalNotificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
            let idd = "YYPushMessageNotificationIdentifier" + puchMessage
            
            let request: UNNotificationRequest = UNNotificationRequest(identifier: idd, content: notificationContent, trigger: notificationTrigger)
            UNUserNotificationCenter.current().add(request) { (error) in
                let errorMessage: NSError = error! as NSError
                if errorMessage.description == "" {
                    print("地理围栏报警发送失败" + error.debugDescription)
                } else {
                    print("消息发送成功")
                    UIApplication.shared.applicationIconBadgeNumber += 1
                }
            }
            
            
            
        } else {
            
            
        }
        
        
    }

希望能帮到你们。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值