iOS
CoreBluetooth로 비컨 구성
수색…
소개
블루투스 저에너지 장치에 데이터를 읽고 쓸 수 있습니다.
비고
몇 가지 중요한 사항
- 기능이 필요하지 않습니다.
- 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