From: liangzhenying <867174124@qq.com> Date: Fri, 7 Mar 2025 07:27:18 +0000 (+0800) Subject: 改了文件传协议,改为边录边传 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=b4be43f07b5b4120db72dc363395b55b3f2cf7fd;p=mirrors%2FIOTBluetooth-iOS.git 改了文件传协议,改为边录边传 --- diff --git "a/Doc/\346\234\200\346\226\260/\350\223\235\347\211\231\346\211\213\350\241\250AI\345\215\217\350\256\256.docx" "b/Doc/\346\234\200\346\226\260/\350\223\235\347\211\231\346\211\213\350\241\250AI\345\215\217\350\256\256.docx" new file mode 100644 index 0000000..311db31 Binary files /dev/null and "b/Doc/\346\234\200\346\226\260/\350\223\235\347\211\231\346\211\213\350\241\250AI\345\215\217\350\256\256.docx" differ diff --git a/IOTBluetooth/IOTBluetooth/Example/Datas.swift b/IOTBluetooth/IOTBluetooth/Example/Datas.swift index 10563ad..37d4590 100644 --- a/IOTBluetooth/IOTBluetooth/Example/Datas.swift +++ b/IOTBluetooth/IOTBluetooth/Example/Datas.swift @@ -114,6 +114,7 @@ let datas: [(ability: IBAbility, label: String, parameters: [IBParameter])] = [ (.fetchFiles, "获取指定类型所有文件", [.file(.mp3)]), (.sendWeather, "发送天气数据", [.weather(IBWeather())]), + (.sendChatGptKey, "发送ChatGpt key", [.text("")]), ] class Config{ diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate b/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate index f6204ab..e7e7e0b 100644 Binary files a/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate and b/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 5008c74..94d7cbd 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -20,5 +20,21 @@ landmarkType = "3"> + + + + diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAbility.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAbility.swift index c96c932..faa7a5a 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAbility.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAbility.swift @@ -539,6 +539,10 @@ public extension IBAbility { /// 发送Ai回应内容 /// - Parameter aiResponse: see ``IBAiResponse`` internal static let aiResponse = IBAbility.long.id(0x1f).parser(IBGeneralParser.self).checker(IBAiReponseChecker.self) + + /// APP发送ChatGPT Key给手表 + /// - Parameter text:String + static let sendChatGptKey = IBAbility.long.id(0x23).parser(IBGeneralParser.self).checker(IBTextChecker.self) } extension IBAbility { diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAiManager.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAiManager.swift index cc113fc..6e3b371 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAiManager.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBAiManager.swift @@ -41,6 +41,7 @@ public class IBAiManager{ var responseId = "" var reply = "" + var recordData = Data() var isLogin:Bool{ return MixSdk.shared.auth.authorized @@ -52,7 +53,23 @@ public class IBAiManager{ setupChatCallBack() } - func aiValid(_ data:Data){ + + /// 检查chatGPT key是否有效 + /// - Parameters: + /// - key: key + /// - completeHandler: 结果回调 + public func checkChatptValid(_ key:String ,completeHandler: @escaping MSChatGptCheckKeyCallBack){ + guard let key = chatGptKey else{ + Logger.log("请先设置chatGPT key") + completeHandler(false,nil) + return + } + MixSdk.shared.chatGpt.isValidKey(key, completeHandler: completeHandler) + } + + + + func checkAiValid(_ data:Data){ let result = IBGeneralParser.dataPacket(data) let platform = chatModeMap[result.int] ?? .doubao let key = platform == .chatGPT ? chatGptKey : nil @@ -80,43 +97,17 @@ public class IBAiManager{ } } } - - public func checkChatptValid(_ key:String ,completeHandler: @escaping MSChatGptCheckKeyCallBack){ - guard let key = chatGptKey else{ - Logger.log("请先设置chatGPT key") - completeHandler(false,nil) - return - } - MixSdk.shared.chatGpt.isValidKey(key, completeHandler: completeHandler) - } - func sendAiState(isValid:Bool,gptKey:String?){ - let model = IBAiValid() - model.isValid = isValid - model.key = gptKey - IBSender() - .ability(IBAbility.aiValid) - .parameters([.aiValid(model)]) - .response { result in - - } - } //取消当前思考 func cancelThinkAction(){ MixSdk.shared.chat.reset() cancelThink?() } - func aiRequest(_ data:Data){ + func startRecord(_ data:Data){ + recordData = Data() + Logger.log("开始录音:") let result = IBGeneralParser.dataPacket(data) let code = result.int - IBSender() - .ability(IBAbility.aiReady) - .parameters([.value(1)]) - .response {[weak self] result in - self?.fectchAiAudio() - } - - let platform = chatModeMap[code] ?? .doubao Logger.log("使用模型:",platform.title) useMode?(platform) @@ -129,29 +120,43 @@ public class IBAiManager{ MixSdk.shared.setPlatform(platform,key: nil) } } - func fectchAiAudio(){ + func stopRecord(_ data:Data){ + Logger.log("结束录音:") + receiveFullData(sbcData: recordData) + } + func receiveRecordData(data:Data){ + recordData.append(data) + } +} +extension IBAiManager{ + + func sendAiState(isValid:Bool,gptKey:String?){ + let model = IBAiValid() + model.isValid = isValid + model.key = gptKey IBSender() - .ability(IBAbility.fetchAiAudio) - .parameters([]) - .response {[weak self] result in - guard let self = self else {return} - responseId = "\(Date().timeIntervalSince1970)" - if result.isSuccess,let data = result.value as? Data{ - receiveAiData(sbcData: data) - } - else{ - Logger.log(result) - let model = IBAiResponse(responseId) - model.type = 0 - model.state = "end" - model.content = "录音解析错误" - sendRelpy(model: model) - } + .ability(IBAbility.aiValid) + .parameters([.aiValid(model)]) + .response { result in + } } + + func saveRecordData(data:Data){ + Logger.log("文件大小 \(data.count)") + let filePath = NSHomeDirectory() + "/Documents/\(Date().format(.long2)).sbc" + let url = URL(fileURLWithPath: filePath) + do { + try data.write(to: url) + print("保存路径 \(filePath)") + } catch let error { + print("\(error)") + } + } } extension IBAiManager{ - func receiveAiData(sbcData:Data){ + private func receiveFullData(sbcData:Data){ + saveRecordData(data: sbcData) let pcmData = MSAudioConvert.sbcTopcm(sbcData) if pcmData.count == 0{ Logger.log("sbc2pcm失败") @@ -192,7 +197,7 @@ extension IBAiManager{ } } - func sendToChatGpt(content text:String){ + private func sendToChatGpt(content text:String){ reply = "" MixSdk.shared.chatGpt.send(content: text) {[weak self] response, error in guard let self = self else {return} @@ -225,7 +230,7 @@ extension IBAiManager{ } - func setupChatCallBack(){ + private func setupChatCallBack(){ let chat = MixSdk.shared.chat chat.callBack = {[weak self] model in guard let self = self else {return} @@ -251,11 +256,9 @@ extension IBAiManager{ sendRelpy(model: data) } } - - } - func sendRelpy(model:IBAiResponse){ + private func sendRelpy(model:IBAiResponse){ self.aiResponse?(model) IBSender() .ability(IBAbility.aiResponse) @@ -266,7 +269,7 @@ extension IBAiManager{ } } -extension IBAiManager{ + extension IBAiManager{ func login(){ let mac = IBBluetooth.shared.currentConnected.macAddress.split(separator: ":").joined().uppercased() login(deviceId:mac ) { token, error in @@ -277,7 +280,7 @@ extension IBAiManager{ /// - Parameters: /// - deviceId: 设备ID /// - completeHandler: 结果回调 - func login(deviceId:String,completeHandler: @escaping MSLoginCallBack){ + private func login(deviceId:String,completeHandler: @escaping MSLoginCallBack){ if productId.isEmpty || productKey.isEmpty { Logger.log("请先设置productId和productKey!") return @@ -291,7 +294,7 @@ extension IBAiManager{ } } - func startLogin(deviceId:String,password:String,completeHandler: @escaping MSLoginCallBack) { + private func startLogin(deviceId:String,password:String,completeHandler: @escaping MSLoginCallBack) { MixSdk.shared.auth.login(productKey:productKey,deviceId: deviceId, password: password){[weak self] token,error in if let err = error{ if case .reponseError(let code,_) = err,code == 50021{ @@ -305,7 +308,7 @@ extension IBAiManager{ } } - func startRegister(deviceId:String,completeHandler: @escaping MSRegisterCallBack){ + private func startRegister(deviceId:String,completeHandler: @escaping MSRegisterCallBack){ MixSdk.shared.auth.register(productId: productId, productKey: productKey, deviceId: deviceId){[weak self] password,error in if let pwd = password{ UserDefaults.standard.setValue(password, forKey: deviceId) diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBChecker.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBChecker.swift index 1c8b58b..749dd88 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBChecker.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBChecker.swift @@ -63,6 +63,16 @@ struct IBValueChecker: IBChecker { return [value.byte] } } +struct IBTextChecker: IBChecker { + static func check(_ parameters: [IBParameter]) -> [UInt8] { + guard case let .text(value) = parameters[.text] else { fatalError("缺少参数: value") } + Logger.log(value) + if let value = value.data(using: .utf8),!value.isEmpty { + return value.bytes + } + return [] + } +} struct IBHeartRateHighChecker: IBChecker { static func check(_ parameters: [IBParameter]) -> [UInt8] { diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBNotify.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBNotify.swift index 9f54dcd..2bc7b7a 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBNotify.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBNotify.swift @@ -202,14 +202,14 @@ extension IBNotify { } //手表询问APP AI模型是否可用 if(data.bytes[1] == 0x05 && data.bytes[2] == 0x06){ - IBAiManager.shared.aiValid(data) + IBAiManager.shared.checkAiValid(data) return true } //AI录音已准备好 - if(data.bytes[1] == 0x05 && data.bytes[2] == 0x05){ - IBAiManager.shared.aiRequest(data) - return true - } +// if(data.bytes[1] == 0x05 && data.bytes[2] == 0x05){ +// IBAiManager.shared.aiRequest(data) +// return true +// } //AI取消当前思考 if(data.bytes[1] == 0x05 && data.bytes[2] == 0x07){ IBAiManager.shared.cancelThinkAction() diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBParameter.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBParameter.swift index 87a20f4..bada05a 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBParameter.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBParameter.swift @@ -13,6 +13,7 @@ enum IBKey: String { case motionMode = "motionMode" case language = "language" case value = "value" + case text = "text" case file = "file" case targetStep = "targetStep" case sleep = "sleep" @@ -58,6 +59,8 @@ public enum IBParameter { case language(IBLanguage) /// 通用值设置 case value(Int) + /// 通用值设置 + case text(String) /// 文件 case file(IBFile) /// 训练目标 @@ -126,6 +129,7 @@ public enum IBParameter { case .motionMode(_): return .motionMode case .language(_): return .language case .value(_): return .value + case .text(_): return .text case .file(_): return .file case .targetStep(_): return .targetStep case .sleep(_): return .sleep diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBReceiveManager.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBReceiveManager.swift index da68032..e419482 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBReceiveManager.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBReceiveManager.swift @@ -25,7 +25,23 @@ class IBReceiveManager { guard let data = characteristic.value else { return } if data.count == 2 && data.int == 0 { - // Logger.log("收到0000指令异常") + //Logger.log("收到0000指令异常") + return + } + + if characteristic.uuid.uuidString == recordCharacteristicUUID { + //手表发送录音开始 + if(data.bytes[1] == 0x08 && data.bytes[2] == 0x01){ + IBAiManager.shared.startRecord(data) + } + //手表发送录音结束 + else if(data.bytes[1] == 0x08 && data.bytes[2] == 0x02){ + IBAiManager.shared.stopRecord(data) + } + else{ + //音频数据 + IBAiManager.shared.receiveRecordData(data: data) + } return } diff --git a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBluetooth.swift b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBluetooth.swift index d6dfa2e..343d7e1 100644 --- a/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBluetooth.swift +++ b/IOTBluetooth/IOTBluetooth/IOTBluetooth/IBluetooth.swift @@ -47,6 +47,8 @@ let writeBigCharacteristicUUID: String = "2AE4" /// Write 特征值(发送文件OAT、MP3等) let writeFileCharacteristicUUID: String = "2AE6" let writeFileResponseUUID: String = "2AE7" +/// 录音uuid +let recordCharacteristicUUID: String = "2AE8" class IBBluetooth: NSObject { static let shared = IBBluetooth() @@ -69,6 +71,8 @@ class IBBluetooth: NSObject { private var writeBigCharacteristic: CBCharacteristic! /// 2AE0 private var writeFileCharacteristic: CBCharacteristic! + /// 2AE8 + private var recordCharacteristic: CBCharacteristic! /// 中央管理类,管理蓝牙的扫描连接 var centralManager: CBCentralManager! @@ -287,6 +291,12 @@ extension IBBluetooth: CBPeripheralDelegate { peripheral.setNotifyValue(true, for: $0) return } + if $0.uuid.uuidString == recordCharacteristicUUID { + recordCharacteristic = $0 + peripheral.setNotifyValue(true, for: $0) + return + } + } } func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { @@ -297,7 +307,13 @@ extension IBBluetooth: CBPeripheralDelegate { Logger.log(error) } if let data = characteristic.value { - Logger.log( "[receive] \(characteristic.uuid.uuidString) " + data.joined(" ")) +// Logger.log( "[receive] \(characteristic.uuid.uuidString) " + data.joined("")) + if data.count > 100 { + Logger.log( "[receive] \(characteristic.uuid.uuidString) " + "\(data.count)") + } + else{ + Logger.log( "[receive] \(characteristic.uuid.uuidString) " + data.joined("")) + } } receiveManager.receice(characteristic: characteristic) }