// // BluetoothManager+Function.swift // HDFwear // // Created by daifengyi on 2023/6/27. // import SwiftDate extension BluetoothManager { // 通用应答 func response(frameNumber: [UInt8], messageId: [UInt8], success: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getResponseCmd(frameNumber: frameNumber, messageId: messageId, success: success) // self.setCmdClosure = completion sendData(data) } // 查询设备信息 // 0x01 设备ID // 0x02 设备名称 // 0x03 设备mac地址 // 0x04 MCU版本号 // 0x05 电量 // 例如[0x02, 0x03]表示查询设备名称和设备mac地址 func queryDeviceInfo(queryItems: [UInt8], completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getQueryDeviceInfoCmd(queryItems: queryItems) self.setCmdClosure = completion sendData(data) } // 设置时间 func newSetTime(completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getTimeCmd() self.setCmdClosure = completion sendData(data) } // 设置时间格式 func newSetTimeFormat(format: TimeFormat, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getTimeFormatCmd(format: format) self.setCmdClosure = completion sendData(data) } // 设置温度单位 func newSetTemperatureUnit(unit: TemperatureUnit, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getTemperatureUnitCmd(unit: unit) self.setCmdClosure = completion sendData(data) } // 设置公英制 func newSetDistanceUnit(unit: DistanceUnit, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getDistanceUnitCmd(unit: unit) self.setCmdClosure = completion sendData(data) } // 设置抬腕唤醒 // bool 0表示关闭,1表示打开 func newSetWristSense(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getWristSenseCmd(bool) self.setCmdClosure = completion sendData(data) } // 设置触摸唤醒 // bool 0表示关闭,1表示打开 func newSetTouchSense(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getTouchSenseCmd(bool) self.setCmdClosure = completion sendData(data) } // 设置低电提醒 // bool 0表示关闭,1表示打开 func newSetLowPowerRemind(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getLowPowerRemind(bool) self.setCmdClosure = completion sendData(data) } // 设置语言 // lan 0表示中文,1表示英语 func newSetLanguage(lan: UInt8, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getLanguageCmd(lan) self.setCmdClosure = completion sendData(data) } // 设置恢复出厂设置 func newSetRestore(completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getRestoreCmd() self.setCmdClosure = completion sendData(data) } // 设置心率过高提醒 // maxHr 0表示关闭提醒 其他值表示最大值 func newSetHeartRateHighRemind(maxHr: UInt8, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getHeartRateHighRemindCmd(maxHr) self.setCmdClosure = completion sendData(data) } // 设置心率过低提醒 // minHr 0表示关闭提醒 其他值表示最小值 func newSetHeartRateLowRemind(minHr: UInt8, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getHeartRateLowRemindCmd(minHr) self.setCmdClosure = completion sendData(data) } // 设置查找手表 // bool 0表示关闭 1表示打开 func newSetFindWatch(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getFindWatchCmd(bool) self.setCmdClosure = completion sendData(data) } // 设置压力自动检测 // bool 0表示关闭 1表示打开 func newSetPressureAutoDetect(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getPressureAutoDetectCmd(bool) self.setCmdClosure = completion sendData(data) } // 设置血压自动检测 // bool 0表示关闭 1表示打开 func newSetBloodOxygenAutoDetect(bool: Bool, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getBloodOxygenAutoDetectCmd(bool) self.setCmdClosure = completion sendData(data) } // 设置用户信息 // user 使用UserInfoModel数据类型,该接口只支持身高、体重、性别的设置,对应是weight、height、gender func newSetUserInfo(_ user: UserInfoModel, completion: ((_ error: Int?) -> ())? = nil) { let data = BleMessage.shared.getUserInfoCmd(user) self.setCmdClosure = completion sendData(data) } // 设置勿扰模式 // remind 使用RemindModel数据类型,该接口使用到了isOn,startDate,endDate这三个字段 func newSetNotDisturb(remind: RemindModel, completion: @escaping(_ error: Int?) -> ()) { let data = BleMessage.shared.getNotDisturbCmd(remind) self.setCmdClosure = completion sendData(data) } // 设置天气 // func newSetWeather(weather: NewWeatherModel, completion: @escaping(_ error: Int?) -> ()) { let data = BleMessage.shared.getNewWeatherCmd(weather) self.setCmdClosure = completion sendData(data) } // 设置北斗联系人 // func newSetBeiDouContact(contacts: [NewBeiDouContactModel], completion: @escaping(_ error: Int?) -> ()) { let data = BleMessage.shared.getNewBeiDouContactCmd(contacts) self.setCmdClosure = completion sendData(data) } // 设置北斗快捷回复 // func newSetBeiDouQuickAnswer(answers: [String], completion: @escaping(_ error: Int?) -> ()) { let data = BleMessage.shared.getNewBeiDouQuickAnswerCmd(answers) self.setCmdClosure = completion sendData(data) } //MARK: - 同步健康数据 // 拉取睡眠数据 func getSleepHistoryData( closure: SleepClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.sleep) newStartSyncHealthData(closure: closure, data: data, synType: .sleep) } // 拉取血氧数据 func getBloodOxygenHistoryData( closure: BloodOxygenClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.bloodOxygen) newStartSyncHealthData(closure: closure, data: data, synType: .bloodOxygen) } // 拉取心跳数据 func getHeartRateHistoryData( closure: HeartRateClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.heartRate) newStartSyncHealthData(closure: closure, data: data, synType: .heartRate) } // 拉取计步数据 func getStepHistoryData( closure: StepClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.step) newStartSyncHealthData(closure: closure, data: data, synType: .step) } // 拉取训练数据 func getTrainHistoryData( closure: TrainClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.train) newStartSyncHealthData(closure: closure, data: data, synType: .train) } // 拉取压力数据 func getPressureHistoryData( closure: PressureClosure? = nil) { let data = BleMessage.shared.getSyncCmd(.pressure) newStartSyncHealthData(closure: closure, data: data, synType: .pressure) } // 同步数据 func newStartSyncHealthData(closure: Any?, data: Data, synType: SyncType) { if !isSync { GCDTimer.shared.scheduledDispatchTimerNotNow(WithTimerName: "SyncInterval", timeInterval: 0.1, queue: .main, repeats: false) { self.clearClosures(closure: closure) self.startSyncTimer() self.isNextSync = false self.isSync = true self.isSyncType = synType self.sendData(data) } } else { switch closure { case is BloodPressureClosure: if bloodPressureClosure == nil { bloodPressureClosure = closure as? BloodPressureClosure bloodPressureClosure?([], -1002) bloodPressureClosure = nil } case is HeartRateClosure: if heartRateClosure == nil { heartRateClosure = closure as? HeartRateClosure heartRateClosure?([], -1002) heartRateClosure = nil } case is BloodOxygenClosure: if bloodOxygenClosure == nil { bloodOxygenClosure = closure as? BloodOxygenClosure bloodOxygenClosure?([], -1002) bloodOxygenClosure = nil } case is SleepClosure: if sleepClosure == nil { sleepClosure = closure as? SleepClosure sleepClosure?([], -1002) sleepClosure = nil } case is StepClosure: if stepClosure == nil { stepClosure = closure as? StepClosure stepClosure?([], -1002) stepClosure = nil } case is TrainClosure: if trainClosure == nil { trainClosure = closure as? TrainClosure trainClosure?(nil, -1002) trainClosure = nil } case is PressureClosure: if pressureClosure == nil { pressureClosure = closure as? PressureClosure pressureClosure?([], -1002) pressureClosure = nil } case is MettClosure: if mettClosure == nil { mettClosure = closure as? MettClosure mettClosure?([], -1002) mettClosure = nil } default: break } } } //MARK: - 发送数据 func sendData(_ data: Data) { if peripheral == nil { print("peripheral == nil") return } var serverUUID: String = "" var writeUUID: String = "" switch platform { case ._828: serverUUID = BLEConfig.ServerUUID writeUUID = BLEConfig.WriteUUID default: break } if let services = peripheral?.services { for service in services { // if service.uuid.uuidString == serverUUID { if serverUUID.contains(service.uuid.uuidString) { if service.characteristics == nil { return } for char in service.characteristics! { // if char.uuid.uuidString == writeUUID { if writeUUID.contains(char.uuid.uuidString) { if platform == ._828 { if data.count <= 20 { print("发送: \([UInt8](data))") peripheral?.writeValue(data, for: char, type: .withoutResponse) } else { print("发送 拼: \([UInt8](data))") let n = data.count/20 + (data.count%20 == 0 ? 0 : 1) for i in 0.. 12 else { return } let msgId = Int(UInt16(bytes[4]) << 8 | UInt16(bytes[5])) switch msgId { case 0x8001: parseDefaultResponseData(bytes) case 0x8002:// 设备信息查询应答 print("设备信息查询应答") let content = parseContentFromBytes(bytes) parseDeviceInfoData(content) case 0x8009:// 实时步数、卡路里、距离自动上报 print("实时步数、卡路里、距离自动上报") let content = parseContentFromBytes(bytes) parseStepCalorieDistanceData(content) case 0x8010:// 电量变化自动上报 print("电量变化自动上报") Battery = Int(bytes[10]) for delegate in syncDelegateList { delegate.didReceiveBattery(value: Battery) } case 0x8014:// 电话挂断 print("电话挂断") if bytes[10] == 0x02 { for delegate in syncDelegateList { delegate.didReceiveCallOff() } } case 0x8015:// 找手机 print("找手机") let ring = Int(bytes[10]) for delegate in syncDelegateList { delegate.didReceiveFindPhoneCommand(value: ring) } case 0x8016:// 历史心率数据上报 print("历史心率数据上报") let content = parseContentFromBytes(bytes) parseHeartRateData(content) case 0x8017:// 历史血氧数据上报 print("历史血氧数据上报") let content = parseContentFromBytes(bytes) parseBlooodOxygenData(content) case 0x8018:// 历史体温数据上报 print("历史体温数据上报") let content = parseContentFromBytes(bytes) parseTemperaturData(content) case 0x8019:// 睡眠数据上报 print("睡眠数据上报") let content = parseContentFromBytes(bytes) parseSleepData(content) case 0x8020:// 历史压力数据上报 print("历史压力数据上报") let content = parseContentFromBytes(bytes) parsePressureData(content) case 0x8021:// 分时段计步数据上报 print("分时段计步数据上报") let content = parseContentFromBytes(bytes) parseStepData(content) case 0x8022:// 遥控拍照 print("遥控拍照") let stauts = bytes[10] for delegate in syncDelegateList { delegate.didReceiveCameraCommand(status: stauts) } default: break } // switch cmd { // case .set, .find, .device, .remind, .firmware: // parseSetData(SetCmd(rawValue: bytes[10]), data: data) // case .sync: // let valueBytes = Array(bytes[13.. [UInt8] { let contentLength = Int(bytes[9]) // 获取内容长度 guard bytes.count >= 10 + contentLength else { return [] // 如果字节数组长度不足以包含内容,返回空数组 } let content = Array(bytes[10..<(10 + contentLength)]) // 获取内容部分 return content } // 通用返回数据 private func parseDefaultResponseData(_ bytes: [UInt8]) { guard bytes.count == 17, bytes[9] == 5 else { return } let newcmd = NewCmd(rawValue: bytes[13]) switch newcmd { case .setTime, .setTimeFormat, .setTemperatureUnit, .setDistanceUnit, .setWristSense, .setTouchSense, .setLowPowerRemind, .setLanguage: if setCmdClosure != nil { let success = bytes[14] == 0 if success { setCmdClosure?(nil) }else { setCmdClosure?((Int)(bytes[14])) } setCmdClosure = nil } case .none: break default: break } } // 设备信息数据 private func parseDeviceInfoData (_ content:[UInt8]) { guard content.count > 0 else { print("无有效的信息") return } let totalInfoCount = Int(content[0]) var currentIndex = 1 // 检查总信息数是否大于0 guard totalInfoCount > 0 else { print("无有效的信息") return } for _ in 0.. 0 else { print("无有效的信息") heartRateClosure?([], nil) return } let hrArray = HeartRateModel.toHeartRateArray(content) HeartRateModel.addArray(hrArray)// 加入数据库 heartRateClosure?(hrArray, nil) } // 血氧数据 func parseBlooodOxygenData (_ content: [UInt8]) { guard content.count > 0 else { print("无有效的信息") bloodOxygenClosure?([], nil) return } let array = BloodOxygenModel.toBloodOxygenArray(content) BloodOxygenModel.addArray(array)// 加入数据库 bloodOxygenClosure?(array, nil) } // 体温数据 func parseTemperaturData (_ content: [UInt8]) { guard content.count > 0 else { print("无有效的信息") return } let array = TemperatureModel.toTemperatureArray(content) TemperatureModel.addArray(array)// 加入数据库 } // 压力数据 func parsePressureData (_ content: [UInt8]) { guard content.count > 0 else { print("无有效的信息") pressureClosure?([], nil) return } let array = PressureModel.toPressureArray(content) PressureModel.addArray(array)// 加入数据库 pressureClosure?(array, nil) } // 计步数据 func parseStepData (_ content: [UInt8]) { guard content.count > 0 else { print("无有效的信息") stepClosure?([], nil) return } let array = StepModel.toStepArray(content) StepModel.addArray(array)// 加入数据库 stepClosure?(array, nil) } // 睡眠数据 func parseSleepData (_ content: [UInt8]) { guard content.count > 0 else { print("无有效的信息") sleepClosure?([], nil) return } let array = SleepModel.toSleepArray(content) SleepModel.addArray(array)// 加入数据库 sleepClosure?(array, nil) } // 实时步数,卡路里,距离数据 func parseStepCalorieDistanceData (_ content: [UInt8]) { guard content.count == 16 else { print("无有效的信息") stepClosure?([], nil) return } let step = StepModel.toStepModel(content) step.realTimeAdd()// 加入数据库 for delegate in syncDelegateList { delegate.didReceiveStep() } stepClosure?([step], nil) } }