수색…


소개

블루투스 저에너지 장치에 데이터를 읽고 쓸 수 있습니다.

비고

몇 가지 중요한 사항

  • 기능이 필요하지 않습니다.
  • Little Endian 형식의 iPhone 저장 바이트이므로 블루투스 액세서리가 Little Endian을 사용하는지 확인하십시오. 예:
    • 인텔 CPU는 일반적으로 리틀 엔디안을 사용합니다.
    • ARM 아키텍처는 빅 엔디안이되었을 때 버전 3 이전에는 리틀 엔디안이었습니다.
  • 단일 또는 일괄 작업 후 연결이 끊어 지므로 계속하기 전에 다시 연결해야합니다.

SERVICE UUID를 검색하십시오.

func SearchBLE(){
    cb_manager.scanForPeripherals(withServices:[service_uuid], options: nil)
    StopSearchBLE()
}

문서없이 SERVICE UUID를 찾는 방법

func centralManager(_ central: CBCentralManager, didConnect peripheral:             
CBPeripheral) {
        peripheral.delegate = self
        peripheral.discoverServices(nil)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    for service in peripheral.services! {
        print("Service: \(service)\n error: \(error)")
    }
}
  • discoverServices (nil) - NIL은 모든 서비스가 반환된다는 것을 의미하며 좋은 옵션은 아닙니다 (READ 비고 3)
  • SERVICE UUID가 코드를 실행하고 콘솔에서 찾을 수 없다면 여기에 이미지 설명을 입력하십시오.
  • 배터리, 장치 정보 (펌웨어) 및 FFF0의 세 가지 서비스가 있습니다.
  • 이 uuid 서비스는 표준이 아니며, 표준 목록이 여기에서 찾을 수 있습니다.
  • 이 경우 FFF0은 SERVICE UUID입니다.

데이터를 UInt16으로 변환하고 반대

이 확장을 클래스에 추가하십시오.

protocol DataConvertible {
    init?(data: Data)
    var data: Data { get }
}

extension DataConvertible {

    init?(data: Data) {
        guard data.count == MemoryLayout<Self>.size else { return nil }
        self = data.withUnsafeBytes { $0.pointee }
    }

    var data: Data {
        var value = self
        return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }
}
extension UInt16 : DataConvertible {
    init?(data: Data) {
        guard data.count == MemoryLayout<UInt16>.size else { return nil }
        self = data.withUnsafeBytes { $0.pointee }
    }
    var data: Data {
        var value = CFSwapInt16HostToBig(self)
        return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }
}

모든 Bluetooth Low Energy (BLE)의 이름 표시

  • 이 예제에서는 단일 BLE 장치를 사용할 수있는 제어 된 방이 있습니다.
  • 클래스가 CBCentralManagerDelegate를 확장해야합니다.
  • 메소드 구현 : centralManagerDidUpdateState (_ central : CBCentralManager).
  • 글로벌 대기열을 사용하여 장치를 검색하는 동안 화면이 멈추지 않도록하십시오.
  • CBCentralManager를 인스턴스화하고 콜백 centralManagerDidUpdateState 응답을 기다립니다.
class BLEController: CBCentralManagerDelegate{

var cb_manager: CBCentralManager!
var bles : [CBPeripheral] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        cb_manager = CBCentralManager(delegate: self, queue: DispatchQueue.global())
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        print("UPDATE STATE - \(central)")
    }
}

centralManagerDidUpdateState에 대한 콜백은 CoreBluetooth가 준비되었음을 나타내므로 이제 BLE을 검색 할 수 있습니다. 준비가되었을 때 모든 BLE 장치를 검색하려면 centralManagerDidUpdateState 코드를 업데이트하십시오.

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    print("UPDATE STATE - \(central)")
    SearchBLE()
}

func SearchBLE(){
    cb_manager.scanForPeripherals(withServices: nil, options: nil)
    StopSearchBLE()
}

func StopSearchBLE() {
    let when = DispatchTime.now() + 5 // change 5 to desired number of seconds
    DispatchQueue.main.asyncAfter(deadline: when) {
        self.cb_manager.stopScan()
    }
}
  • BLE 장치에 대한 SearchBLE () 검색 및 5 초 후 검색 중지
  • cb_manager.scanForPeripherals (withServices : nil, options : nil)는 범위에있는 모든 BLE를 찾습니다.
  • StopSearchBLE ()은 5 초 후에 검색을 중지합니다.
  • 각 BLE은 callback func centralManager (_ 중앙 : CBCentralManager, 주변 장치 검색 : CBPeripheral, advertisingData : [문자열 : 모두], rssi RSSI : NSNumber)
func centralManager(_ central: CBCentralManager, didDiscover peripheral:                                                             
    CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    guard let name = peripheral.name else {
        return
    }
    print(name)
    bles.append(peripheral)
}

주요 가치 연결 및 읽기

  • 나는 IBEACON 프로토콜을 사용하는 하나의 미니 신호로 통제 된 방에있다.
  • BLEController는 CBPeripheralDelegate를 확장해야합니다.
  • 검색이 중지 된 후 첫 번째 BLE을 사용하여 연결합니다.
  • StopSearchBLE () 메서드 수정
class BLEController: CBCentralManagerDelegate, CBPeripheralDelegate{
//...
    func StopSearchMiniewBeacon() {
        let when = DispatchTime.now() + 5 // change 2 to desired number of seconds
        DispatchQueue.main.asyncAfter(deadline: when) {
            self.cb_manager.stopScan()
            self.cb_manager.connect(bles.first)
        }
    }
/...
}
  • BLE 장치의 문서화에서 SERVICE UUID와 MAUOR UUID CHARACTERISTIC
var service_uuid =  CBUUID(string: "0000fff0-0000-1000-8000-00805f9b34fb")
var major_uuid =  CBUUID(string: "0000fff2-0000-1000-8000-00805f9b34fb")
func centralManager(_ central: CBCentralManager, didConnect peripheral:             
CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices([service_uuid])
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    print("Service: \(service)\n error: \(error)")
    peripheral.discoverCharacteristics([major_uuid], for: (peripheral.services?[0])!)
}
  • 위의 코드와 같이 'service_uuid'및 'major_uuid'변수를 만듭니다. '-0000-1000-8000-00805f9b34fb'는 표준의 일부입니다. 'fff0'은 나의 SERVICE UUID이고, 'fff2'는 나의 주요 UUID 특성이고 '0000'은 4 바이트 uuid 1º 블록을 채우는 데 필요합니다.
  • discoverCharacteristics ([major_uuid], for : (peripheral.services?[0))!)는 내 장치 서버에서 주요 특성을 얻을 것이며 NIL은 현재 값으로 사용됩니다.
  • (peripheral.services?[0])! - peripheral_discoverServices ([service_uuid])를 수행하면 0 beacuse가 단일 값을 반환합니다.
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    for characteristic in service.characteristics! {
        print("Characteristic: \(characteristic)\n error: \(error)")
        if(characteristic.uuid.uuidString == "FFF2"){
            peripheral.readValue(for: characteristic)
        }
    }
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
}
  • 특성 값은 호출 후에 만 ​​읽을 수 있습니다. peripheral.readValue (for : characteristic)
  • readValue는 데이터 유형에 값이있는 func 주변 장치 (_ 주변 장치 : CBPeripheral, didUpdateValue 특성 : CBCharacteristic, 오류 : 오류?)를 발생시킵니다.

주요 가치 쓰기

  • 서비스와 특성을 발견해야합니다.
  • 이 특성을 덮어 쓰기 전에 특성 값을 읽을 필요가 없습니다.
  • 이 예제의 경우 읽기 값 후에 계속됩니다. func 주변 장치 수정 (_ 주변 장치 : CBPeripheral, didUpdateValue 특성 : CBCharacteristic, 오류 : 오류?)
  • new_major 및 reset_characteristic 변수를 추가하십시오.
var reset_characteristic : CBCharacteristic!
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    for characteristic in service.characteristics! {
        print("Characteristic: \(characteristic)\n error: \(error)")
        if(characteristic.uuid.uuidString == "FFF2"){
            peripheral.readValue(for: characteristic)
        }
        if(characteristic.uuid.uuidString == "FFFF"){
            reset_characteristic = characteristic
        }
    }
}
let new_major : UInt16 = 100
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
    peripheral.writeValue(new_major.data, for: characteristic, type: CBCharacteristicWriteType.withResponse)
}
  • deafult에 의한 iPhone은 Little Endian 형식으로 바이트를 보내고 받지만 내 장치 MINEW 마녀 칩셋 NRF51822에는 ARM 아키텍처가 있으며 Big Endian 형식의 바이트가 필요하므로이를 교환해야합니다.
  • BLE 장치 설명서에는 각 특성에 어떤 유형의 입력 및 출력이 있는지, 위와 같이 읽을 수 있는지 (CBCharacteristicWriteType.withResponse) 여부가 표시됩니다.
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic write: \(characteristic)\n error: \(error)")
    if(characteristic.uuid.uuidString == "FFF2"){
            print("Resetting")
            peripheral.writeValue("minew123".data(using: String.Encoding.utf8)!, for: reset_characteristic, type: CBCharacteristicWriteType.withResponse)
        }
    if(characteristic.uuid.uuidString == "FFFF"){
        print("Reboot finish")
        cb_manager.cancelPeripheralConnection(peripheral)
    }
}
  • 서버 정보를 업데이트하려면 프로그래밍 방식으로 다시 부팅하거나 데이터를 저장 한 다음 수동으로 껐다 켜야합니다.
  • FFFF는이 장치에서 수행하는 특성입니다.
  • 'minew123'은이 경우 재부팅 및 정보 저장을위한 기본 암호입니다.
  • 앱을 실행하고 오류가 있는지 콘솔에서 볼 수 있지만 아무 것도 없길 바라지 만 새로운 가치는 아직 보지 못합니다.
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
    //peripheral.writeValue(new_major.data, for: characteristic, type: CBCharacteristicWriteType.withResponse)

}

  • 마지막 단계는 메소드 didUpdateValueFor의 마지막 행에 주석을 달고 앱을 재실행하는 것입니다. 이제는 새 값을 적용 할 것입니다.


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow