투케이2K

112. (ios/swift) 비콘 목록 다중 스캔 실시 - beacon list multi scan 본문

IOS

112. (ios/swift) 비콘 목록 다중 스캔 실시 - beacon list multi scan

투케이2K 2022. 2. 2. 20:12

[개발 환경 설정]

개발 툴 : XCODE

개발 언어 : SWIFT

 

[방법 설명]

 

[소스 코드]

    /*
    MARK: - [실시간 비콘 스캔 요약 설명]
    // -----------------------------------------
    [필요한 import 선언]
    import CoreLocation
    import CoreBluetooth
    */
    // -----------------------------------------
    /*
    [필요한 class delegate 선언]
    class A_Main: UIViewController, CLLocationManagerDelegate { }
    */
    // -----------------------------------------
    /*
    [실시간 비콘 스캔 시작 방법]
    self.startBeaconScanFlag = true // 비콘 스캔 시작 플래그 지정
    self.checkLocationPermission() // 위치 권한 확인 >> 비콘 스캔 시작
    */
    // -----------------------------------------
    /*
    [실시간 비콘 스캔 종료 방법]
    self.beaconScanTimerStop()
    */
    // -----------------------------------------
    /*
    [실시간 비콘 스캔 로직]
    Function [권한 확인] : checkLocationPermission
    Function [권한 체크] : locationManager [didChangeAuthorization]
    Function [스캔 시작] : beaconScanStart / beaconScanTimerStart
    Function [스캔 목록 확인] : locationManager [didRangeBeacons]
    */
    // -----------------------------------------
    
    
    
    
    
    // MARK: - [실시간 비콘 스캐닝을 위한 전역 변수 선언 부분]
    // -----------------------------------------
    var locationManager : CLLocationManager! // [위치 권한 상태 확인]
    // -----------------------------------------
    var startBeaconScanFlag = false // [비콘 스캔 시작 여부 확인 플래그]
    // -----------------------------------------
    var beaconScanCount = 1 // [비콘 스캔 진행 카운트 값]
    let beaconScanCountMax = 13 // [비콘 스캔 진행 최대값 정의]
    // -----------------------------------------
    var beaconScanTimer : Timer? // [실시간 비콘 스캔 진행 여부 확인 타이머 핸들러]
    // -----------------------------------------
    //var scanUuid = UUID(uuidString: "F7A3E806-F5BB-43F8-BA87-0783669EBEB1")! // MARK: [단일 :: 비콘 스캔 Uuid :: 필수 설정]
    let scanUuid = [UUID(uuidString: "F7A3E806-F5BB-43F8-BA87-0783669EBEB1")!,
                            UUID(uuidString: "F7A3E806-F5BB-43F8-BA87-0783669EBEB2")!] // MARK: [다중 :: 비콘 스캔 Uuid :: 필수 설정]
    // -----------------------------------------
    //var scanMajor = 1 // [비콘 스캔 Major :: 필요시 추가 설정]
    //var scanMinor = 121 // [비콘 스캔 Minor :: 필요시 추가 설정]
    // -----------------------------------------
    var scanBeaconRegion: CLBeaconRegion! // [실시간 비콘 스캔 감지 : 특정 uuid 일치값 설정]
    // -----------------------------------------
    var scanBeaconRegionConstraints: Any? = nil // [비콘 스캔 RegionConstraints]
    // -----------------------------------------
    
    
    
    
    
    // MARK: - [위치 권한 활성 상태 확인 : 비콘 스캔]
    func checkLocationPermission() {
        DispatchQueue.main.async {
            print("")
            print("===============================")
            print("[A_Main >> checkLocationPermission() :: [위치 사용 권한 요청 실시]]")
            print("===============================")
            print("")
            // -----------------------------------------
            self.locationManager = CLLocationManager.init() // [locationManager 초기화]
            self.locationManager.delegate = self // [델리게이트 넣어줌]
            self.locationManager.requestAlwaysAuthorization() // [위치 권한 설정 값을 받아옵니다]
            // -----------------------------------------
            self.locationManager.startUpdatingLocation() // [위치 업데이트 시작]
            // -----------------------------------------
        }
    }
    // MARK: [위치 서비스에 대한 권한 확인 실시]
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        print("")
        print("===============================")
        print("[A_Main >> locationManager() :: [위치 사용 권한 확인 실시]]")
        print("===============================")
        print("")
        // -----------------------------------------
        if status == .authorizedAlways {
            print("")
            print("===============================")
            print("[A_Main >> locationManager() :: [위치 사용 권한 항상 허용]]")
            print("===============================")
            print("")
            
            // [비콘 스캔 플래그 값 확인]
            if startBeaconScanFlag == true {
                print("")
                print("===============================")
                print("[A_Main >> locationManager() :: [authorizedAlways] :: [beaconScanStart]]")
                print("===============================")
                print("")
                
                // [실시간 비콘 스캔 시작]
                self.beaconScanStart()
            }
        }
        // -----------------------------------------
        if status == .authorizedWhenInUse {
            print("")
            print("===============================")
            print("[A_Main >> locationManager() :: [위치 사용 권한 앱 사용 시 허용]]")
            print("===============================")
            print("")
            
            // [비콘 스캔 플래그 값 확인]
            if startBeaconScanFlag == true {
                print("")
                print("===============================")
                print("[A_Main >> locationManager() :: [authorizedWhenInUse] :: [beaconScanStart]]")
                print("===============================")
                print("")
            
                // [실시간 비콘 스캔 시작]
                self.beaconScanStart()
            }
        }
        // -----------------------------------------
        if status == .denied {
            print("")
            print("===============================")
            print("[A_Main >> locationManager() :: [위치 사용 권한 거부]]")
            print("===============================")
            print("")
            
            // [비콘 스캔 플래그 값 확인]
            if startBeaconScanFlag == true {
                print("")
                print("===============================")
                print("[A_Main >> locationManager() :: [denied] :: [startBeaconScanFlag == false]]")
                print("===============================")
                print("")
                
                // [비콘 스캔 플래그 변경]
                self.startBeaconScanFlag = false
            }
        }
        // -----------------------------------------
        if status == .restricted || status == .notDetermined {
            print("")
            print("===============================")
            print("[A_Main >> locationManager() :: [위치 사용 권한 대기 상태]]")
            print("===============================")
            print("")
            
            // [비콘 스캔 플래그 값 확인]
            if startBeaconScanFlag == true {
                print("")
                print("===============================")
                print("[A_Main >> locationManager() :: [restricted || notDetermined] :: [startBeaconScanFlag == false]]")
                print("===============================")
                print("")
                
                // [비콘 스캔 플래그 변경]
                self.startBeaconScanFlag = false
            }
        }
        // -----------------------------------------
    }
    
    
    
    
    
    // MARK: - [실시간 비콘 스캐닝 진행]
    func beaconScanStart() {
    
        // -----------------------------------------
        // [플래그 값 초기 지정]
        self.startBeaconScanFlag = false
        // -----------------------------------------
        // [이미 비콘 스캔이 진행 중인 경우 먼저 종료 위함]
        self.beaconScanTimerStop()
        // -----------------------------------------
        // [비콘 스캔 카운트 초기화]
        self.beaconScanCount = 1
        // -----------------------------------------
        // [비콘 스캔 진행 실시]
        if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
            if CLLocationManager.isRangingAvailable() { // [비콘 스캔 기능을 이용할 수 있는 경우]
                print("")
                print("===============================")
                print("[A_Main >> beaconScanStart() :: 실시간 비콘 스캔 실시 [정상]]")
                print("설 명 :: CLLocationManager.isRangingAvailable == true]")
                print("===============================")
                print("")
                
                if #available(iOS 13, *) {
                    // -----------------------------------------
                    // MARK: [단일 지정]
                    // [사용 셋팅 : 특정 uuid 일치 값 설정]
                    //self.scanBeaconRegion = CLBeaconRegion.init(uuid: self.scanUuid, identifier: self.scanUuid.uuidString)
                    //self.scanBeaconRegionConstraints = CLBeaconIdentityConstraint(uuid: self.scanUuid)
                    
                    // [비콘 스캔 시작]
                    //self.locationManager.startMonitoring(for: self.scanBeaconRegion)
                    //self.locationManager.startRangingBeacons(satisfying: self.scanBeaconRegionConstraints as! CLBeaconIdentityConstraint)
                    // -----------------------------------------
                    // MARK: [다중 지정]
                    // [for 문 사용해서 비콘 스캔 값 추가 실시]
                    for i in stride(from: 0, through: self.scanUuid.count-1, by: 1) {
                        self.scanBeaconRegion = CLBeaconRegion.init(uuid: self.scanUuid[i], identifier: self.scanUuid[i].uuidString)
                        self.scanBeaconRegionConstraints = CLBeaconIdentityConstraint(uuid: self.scanUuid[i])
                        
                        self.locationManager.startMonitoring(for: self.scanBeaconRegion)
                        self.locationManager.startRangingBeacons(satisfying: self.scanBeaconRegionConstraints as! CLBeaconIdentityConstraint)
                    }
                    // -----------------------------------------
                }
                else {
                    // -----------------------------------------
                    // MARK: [단일 지정]
                    // [사용 셋팅 : 특정 uuid 일치 값 설정]
                    //self.scanBeaconRegion = CLBeaconRegion.init(proximityUUID: self.scanUuid, identifier: self.scanUuid.uuidString)
                    
                    // [비콘 스캔 시작]
                    //self.locationManager.startMonitoring(for: self.scanBeaconRegion)
                    //self.locationManager.startRangingBeacons(in: self.scanBeaconRegion)
                    // -----------------------------------------
                    // MARK: [다중 지정]
                    // [for 문 사용해서 비콘 스캔 값 추가 실시]
                    for i in stride(from: 0, through: self.scanUuid.count-1, by: 1) {
                        self.scanBeaconRegion = CLBeaconRegion.init(proximityUUID: self.scanUuid[i], identifier: self.scanUuid[i].uuidString)
                        
                        self.locationManager.startMonitoring(for: self.scanBeaconRegion)
                        self.locationManager.startRangingBeacons(in: self.scanBeaconRegion)
                    }
                    // -----------------------------------------
                }
                // -----------------------------------------
                // [비콘 스캔 시작 플래그 값 지정]
                self.startBeaconScanFlag = true // [비콘 스캔 시작 플래그 변경]
                self.beaconScanTimerStart() // [타이머 시작 호출]
                // -----------------------------------------
            }
            else {
                print("")
                print("===============================")
                print("[A_Main >> beaconScanStart() :: 실시간 비콘 스캔 실시 [비정상]]")
                print("설 명 :: CLLocationManager.isRangingAvailable == false]")
                print("===============================")
                print("")
                // -----------------------------------------
                // [비콘 스캔 시작 플래그 변경]
                self.startBeaconScanFlag = false
                // -----------------------------------------
            }
        }
        else {
            print("")
            print("===============================")
            print("[A_Main >> beaconScanStart() :: 실시간 비콘 스캔 실시 [비정상]]")
            print("설 명 :: CLLocationManager.isMonitoringAvailable == false]")
            print("===============================")
            print("")
            // -----------------------------------------
            // [비콘 스캔 시작 플래그 변경]
            self.startBeaconScanFlag = false
            // -----------------------------------------
        }
    }



    
    
    // MARK: - [실시간 비콘 감지 수행 부분]
    func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
        if beacons.count > 0 { // [스캔된 비콘 개수가 있는 경우 : UUID]
            
            // [for 반복문을 수행하면서 스캔한 비콘 정보 확인 실시]
            for beacon in beacons {
                // -----------------------------------------
                var SCAN_UUID = ""
                if #available(iOS 13, *) {
                    SCAN_UUID = String(beacon.uuid.uuidString) // uuid 값
                }
                else {
                    SCAN_UUID = String(beacon.proximityUUID.uuidString) // uuid 값
                }
                // -----------------------------------------
                let SCAN_MINOR : String = String(beacon.minor.description) // minor 값
                let SCAN_MAJOR : String = String(beacon.major.description) // major 값
                // -----------------------------------------
                print("")
                print("===============================")
                print("[A_Main >> didRangeBeacons() :: 실시간 비콘 스캔 세부 정보]")
                print("beacon [uuid] :: ", SCAN_UUID)
                print("beacon [minor] :: ", SCAN_MINOR)
                print("beacon [major] :: ", SCAN_MAJOR)
                print("beacon [rssi] :: ", beacon.rssi)
                print("===============================")
                print("")
                // -----------------------------------------
            }
        }
    }
    
    
    
    
    
    // MARK: - [실시간 비콘 스캐닝 종료]
    func beaconScanStop(){
        print("")
        print("===============================")
        print("[A_Main >> beaconScanStop() :: 실시간 비콘 스캔 종료]")
        print("===============================")
        print("")
        
        // -----------------------------------------
        // [비콘 변수 값 초기화 부분]
        self.beaconScanCount = 1 // 비콘 스캔 카운트 초기화
        self.startBeaconScanFlag = false // 비콘 스캔 플래그 변경
        // -----------------------------------------
        // MARK: [단일 지정]
        // [비콘 스캔 모니터링 종료]
        /*
        self.locationManager.stopMonitoring(for: self.scanBeaconRegion)
        
        // [비콘 범위 감지 종료]
        if #available(iOS 13, *) {
            self.locationManager.stopRangingBeacons(satisfying: self.scanBeaconRegionConstraints as! CLBeaconIdentityConstraint)
        }
        else {
            self.locationManager.stopRangingBeacons(in: self.scanBeaconRegion)
        }
        */
        // -----------------------------------------
        // MARK: [다중 지정]
        // [for 문 사용해서 비콘 스캔 제거 실시]
        for i in stride(from: 0, through: self.scanUuid.count-1, by: 1) {
            self.scanBeaconRegion = CLBeaconRegion.init(proximityUUID: self.scanUuid[i], identifier: self.scanUuid[i].uuidString)
            
            // [비콘 스캔 모니터링 종료]
            self.locationManager.stopMonitoring(for: self.scanBeaconRegion)
            
            // [비콘 범위 감지 종료]
            if #available(iOS 13, *) {
                self.scanBeaconRegionConstraints = CLBeaconIdentityConstraint(uuid: self.scanUuid[i])
                self.locationManager.stopRangingBeacons(satisfying: self.scanBeaconRegionConstraints as! CLBeaconIdentityConstraint)
            }
            else {
                self.locationManager.stopRangingBeacons(in: self.scanBeaconRegion)
            }
        }
        // -----------------------------------------
    }


    
    
    
    // MARK: - [비콘 스캔 실시간 반복 작업 시작 호출]
    func beaconScanTimerStart(){
        print("")
        print("===============================")
        print("[A_Main >> beaconScanTimerStart() :: 비콘 스캔 타이머 동작 [시작]]")
        print("===============================")
        print("")
        // -----------------------------------------
        // [타이머 객체 생성 실시 :: 주기 timeInterval = 1초]
        self.beaconScanTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.beaconScanTimerCallback), userInfo: nil, repeats: true)
        // -----------------------------------------
    }
    // [실시간 반복 작업 수행 부분]
    @objc func beaconScanTimerCallback() {
        print("")
        print("===============================")
        print("[A_Main >> beaconScanTimerCallback() :: 비콘 스캔 타이머 동작 [진행]]")
        print("비콘 스캔 카운트 :: \(self.beaconScanCount)")
        print("===============================")
        print("")
        
        // [처리할 로직 작성 실시]
        self.beaconScanCount += 1 // [1씩 카운트 값 증가 실시]
        if self.beaconScanCount > self.beaconScanCountMax { // [카운트 값이 max 보다 큰 경우]
            // -----------------------------------------
            self.beaconScanTimerStop() // [타이머 종료 실시]
            // -----------------------------------------
        }
    }
    // [실시간 반복 작업 정지 호출]
    func beaconScanTimerStop(){
        print("")
        print("===============================")
        print("[A_Main >> beaconScanTimerStop() :: 비콘 스캔 타이머 동작 [종료]]")
        print("===============================")
        print("")
        // [실시간 반복 작업 중지]
        if self.beaconScanTimer != nil && self.beaconScanTimer!.isValid {
            // -----------------------------------------
            self.beaconScanTimer!.invalidate() // [타이머 초기화]
            // -----------------------------------------
            self.beaconScanStop() // [비콘 스캔 종료 호출]
            // -----------------------------------------
        }
    }
 

[결과 출력]

 

 

반응형
Comments