SwiftUI IOS BLE 相关

1. 中心设备

import Foundation
import CoreBluetooth

struct Const {
    static let SERVICE_UUID = CBUUID(string: "6B5C4A86-CFB7-4031-98EB-09DF5E2543F0")
    static let WRITE_CHARACTERISTIC_UUID = CBUUID(string: "4551ABAE-CE14-4F9E-B31A-E61FC372E480")
    static let NOTIFY_CHARACTERISTIC_UUID = CBUUID(string: "DFB13451-1740-4F8A-B0F0-7C20D79E8BDF")
}

class MyCentral: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    
    let centralManager = CBCentralManager()
    // peripheral
    var candidates: [CBPeripheral] = []
    var peripheral: CBPeripheral?
    var service: CBService?
    var writeCharacteristic: CBCharacteristic?
    var notifyCharacteristic: CBCharacteristic?
    // The local name of a peripheral.
    @Published var candidateNames: [String] = []
    @Published var notifiedMessage = "未受信"
    var randomPerSecond = 0
    var timer : Timer! = nil
    var receivedMessageArray: String = ""
    var iPhoneCentralMessageArray: String = ""
    
    var sendData = [
        "heartRate": "80",
        "bloodPressure": "80",
        "bodyTemperature": "36.6",
        "respiratoryRate": "70",
    ]
    
    override init() {
        super.init()
        centralManager.delegate = self
    }
    
    // スキャン開始
    func startScan() {
        print("start scan")
        candidateNames.removeAll()
        candidates.removeAll()
        if !centralManager.isScanning {
            centralManager.scanForPeripherals(withServices: [Const.SERVICE_UUID], options: nil)
        }
    }
    
    // スキャン停止
    func stopScan() {
        print("stop scan")
        if centralManager.isScanning {
            centralManager.stopScan()
        }
    }
    
    // Centralの状態が変化したとき
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOff:
            print("BLE PoweredOff")
            break
        case .poweredOn:
            print("BLE poweredOn")
            break
        case .resetting:
            print("BLE resetting")
            break
        case .unauthorized:
            print("BLE unauthorized")
            break
        case .unknown:
            print("BLE unknown")
            break
        case .unsupported:
            print("BLE unsupported")
            break
        @unknown default:
            print("BLE illegalstate \(central.state)")
        }
    }
    
    // ペリフェラルと接続
    func connect(index: Int) {
        print("BLE start connect")
        self.peripheral = candidates[index]
        centralManager.connect(self.peripheral!, options: nil)
    }
    
    // データ書き込み
    func write() { 
        let data = try! JSONSerialization.data(withJSONObject: sendData, options: [])
        print("data:",data)
        
        self.peripheral?.writeValue(data, for: (self.service?.characteristics?.first)!, type: .withoutResponse)  
    }
    
    // Peripheralを見つけたとき
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        
        let name = peripheral.name
        let localName = advertisementData[CBAdvertisementDataLocalNameKey] as? String
        print("BLE discovered \(String(describing: name)) LocalName=\(String(describing: localName))")
        if localName != nil && localName == "sample" {
            // The local name of a peripheral.
            candidateNames.append(localName!)
            // peripheral
            candidates.append(peripheral)
        }
    }
    
    // 接続したとき
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("BLE connected")
        peripheral.delegate = self
        peripheral.discoverServices([Const.SERVICE_UUID])
    }
    
    // 接続に失敗したとき
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("BLE connect failed")
    }
    
    // Serviceを見つけたとき
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        print("BLE discovered services")
        service = peripheral.services?.first
        peripheral.discoverCharacteristics([Const.WRITE_CHARACTERISTIC_UUID, Const.NOTIFY_CHARACTERISTIC_UUID], for: service!)
    }
    
    // Characteristicを見つけたとき
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        print("BLE discovered characteristics")
        
        for characteristic in service.characteristics! {
            if characteristic.uuid == Const.WRITE_CHARACTERISTIC_UUID {
                writeCharacteristic = characteristic
            } else if characteristic.uuid == Const.NOTIFY_CHARACTERISTIC_UUID {
                // 通知の受け取りを開始する
                notifyCharacteristic = characteristic
                peripheral.setNotifyValue(true, for: notifyCharacteristic!)
            }
        }
    }
    
    // 通知を受け取ったとき
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        print("BLE updated characteristis: \(characteristic)")
        
        let data = characteristic.value!
        print("data:",data)
        
        let json = try! JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String, String>
        print("json:",json)
        
        notifiedMessage = "\(json)"
        
        createCSV(from: json)
    }
    
    // CSVファイル生成
    func createCSV(from recArray:Dictionary<String, String>) {
        var csvString = "\("Type"),\("Number")\n\n"
        for dct in recArray {
            csvString = csvString.appending("\(String(describing: dct.key)) ,\(String(describing: dct.value))\n")
        }
        
        let dateFormat = DateFormatter()
        dateFormat.dateFormat = "yyyyMMddHHmmss"
        let now = Date()
        print(dateFormat.string(from: now))
        
        let fileManager = FileManager.default
        do {
            let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
            let fileURL = path.appendingPathComponent("\(dateFormat.string(from: now))_HealthData.csv")
            try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
        } catch {
            print("error creating file")
        }
     }
}

2. 外围设备

import Foundation
import CoreBluetooth
import SwiftUI

struct Const {
    static let SERVICE_UUID = CBUUID(string: "6B5C4A86-CFB7-4031-98EB-09DF5E2543F0")
    static let WRITE_CHARACTERISTIC_UUID = CBUUID(string: "4551ABAE-CE14-4F9E-B31A-E61FC372E480")
    static let NOTIFY_CHARACTERISTIC_UUID = CBUUID(string: "DFB13451-1740-4F8A-B0F0-7C20D79E8BDF")
}

class MyPeripheral: NSObject, ObservableObject, CBPeripheralManagerDelegate {
    let peripheralManager = CBPeripheralManager()
    var service: CBMutableService?
    var writeCharacteristic: CBMutableCharacteristic?
    var notifyCharacteristic: CBMutableCharacteristic?
    
    @Published var wroteMessage = ""
    
    var count: UInt32 = 0
    
    override init() {
        super.init()
        peripheralManager.delegate = self
    }
    
    var sendData = [
        "heartRate": "80",
        "bloodPressure": "80",
        "bodyTemperature": "36.6",
        "respiratoryRate": "70",
    ]
    
    // アドバタイズ開始ボタンが押されたとき
    func startRegistAndAdvertise() {
        print("[BLE] start Regist and Advertise")
        // まずはレジストから
        regist()
    }
    
    // アドバタイズ停止ボタンが押されたとき
    func stopAdvertise() {
        print("[BLE] stop Advertise")
        peripheralManager.stopAdvertising()
    }
    
    // 通知
    func notify() {
        print("[BLE] notify")

        let data = try! JSONSerialization.data(withJSONObject: sendData, options: [])
        print("data:",data)

        peripheralManager.updateValue(data, for: notifyCharacteristic!, onSubscribedCentrals: nil)
        
    }
    
    // レジスト
    func regist() {
        print("[BLE] start regist")
        
        // create service
        let service = CBMutableService(type: Const.SERVICE_UUID, primary: true)
        
        // create characteristic
        let writeCharacteristic = CBMutableCharacteristic(type: Const.WRITE_CHARACTERISTIC_UUID, properties: [.read, .writeWithoutResponse], value: nil, permissions: [.readable, .writeable])
        let notifyCharacteristic = CBMutableCharacteristic(type: Const.NOTIFY_CHARACTERISTIC_UUID, properties: [.read, .notify], value: nil, permissions: [.readable, .writeable])
        service.characteristics = [writeCharacteristic, notifyCharacteristic]
        
        // regist
        peripheralManager.add(service)
    }
    
    // PeripheralManagerの状態が変わったとき
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        switch peripheral.state {
        case .poweredOff:
            print("[BLE]  PoweredOff")
            break
        case .poweredOn:
            print("[BLE]  poweredOn")
            break
        case .resetting:
            print("[BLE]  resetting")
            break
        case .unauthorized:
            print("[BLE]  unauthorized")
            break
        case .unknown:
            print("[BLE]  unknown")
            break
        case .unsupported:
            print("[BLE]  unsupported")
            break
        @unknown default:
            print("[BLE]  illegalstate \(peripheral.state)")
        }
    }
    
    // レジストが終わったとき
    func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
        print("[BLE] didAdd error=\(String(describing: error))")
        
        // Service と Characteristicを持っておく
        self.service = service as? CBMutableService
        for characteristic in service.characteristics! {
            if characteristic.uuid == Const.NOTIFY_CHARACTERISTIC_UUID {
                notifyCharacteristic = characteristic as? CBMutableCharacteristic
            } else if characteristic.uuid == Const.WRITE_CHARACTERISTIC_UUID {
                writeCharacteristic = characteristic as? CBMutableCharacteristic
            }
        }
        
        // アドバタイズを開始
        let advertisementData = [CBAdvertisementDataServiceUUIDsKey: [service.uuid], CBAdvertisementDataLocalNameKey: "sample"] as [String : Any]
        peripheralManager.startAdvertising(advertisementData)
    }
    
    // アドバタイズが開始されたとき
    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        print("[BLE] peripheralManagerDidStartAdvertising error=\(String(describing: error))")
    }
    
    // Centralからの購読を受信したとき
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
        print("[BLE] didSubscribeTo")
    }
    
    // Centralからの書き込みを受信したとき
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        print("[BLE] didReceiveWrite")
        
//        for oneRequest in requests {
//            print("oneRequest:",oneRequest)
//            guard let requestValue = oneRequest.value,
//                  let stringFromData = String(data: requestValue, encoding: .utf8) else {
//                continue
//            }
//            print("Received write request:",stringFromData)
//            wroteMessage = "\(stringFromData)"
//        }
        
        for oneRequest in requests {
            print("oneRequest:",oneRequest)
            let requestValue = oneRequest.value
            let dic = try! JSONSerialization.jsonObject(with: requestValue!, options: []) as! Dictionary<String, String>
            print("Received write request:",dic)
            wroteMessage = "\(dic)"
            
            createCSV(from: dic)
        }
        
    }
    
    // CSVファイル生成
    func createCSV(from recArray:Dictionary<String, String>) {
        var csvString = "\("Type"),\("Number")\n\n"
        for dct in recArray {
            csvString = csvString.appending("\(String(describing: dct.key)) ,\(String(describing: dct.value))\n")
        }
        
        let dateFormat = DateFormatter()
        dateFormat.dateFormat = "yyyyMMddHHmmss"
        let now = Date()
        print(dateFormat.string(from: now))
        
        let fileManager = FileManager.default
        do {
            let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
            let fileURL = path.appendingPathComponent("\(dateFormat.string(from: now))_HealthData.csv")
            try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
        } catch {
            print("error creating file")
        }
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值