joy sdk封装
authorliangzhenying <867174124@qq.com>
Sat, 6 Dec 2025 08:27:38 +0000 (16:27 +0800)
committerliangzhenying <867174124@qq.com>
Sat, 6 Dec 2025 08:27:38 +0000 (16:27 +0800)
16 files changed:
ShenYin/ShenYin/JoySdk/AiSupportLanguage.swift [moved from ShenYin/ShenYin/lan/AiSupportLanguage.swift with 84% similarity]
ShenYin/ShenYin/JoySdk/JoyChat.swift
ShenYin/ShenYin/JoySdk/JoyDevice.swift
ShenYin/ShenYin/JoySdk/JoySdkManager.swift
ShenYin/ShenYin/Launch/BleManager.swift
ShenYin/ShenYin/Ota/OtaManager.swift
ShenYin/ShenYin/Ota/update.ufw [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/Chat/ChatHeaderView.swift
ShenYin/ShenYin/UI/Home/Chat/ChatNavigationBarItem.swift [moved from ShenYin/ShenYin/UI/Home/Chat/NavigationBarItem.swift with 96% similarity]
ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift
ShenYin/ShenYin/UI/Home/Scan/BleScanVC.swift
ShenYin/ShenYin/UI/Home/Scan/DeviceVM.swift
ShenYin/ShenYin/UI/Mode/CustomEqVC.swift
ShenYin/ShenYin/UI/Mode/FindVC.swift
ShenYin/ShenYin/UI/Mode/ModeEffectsView.swift
ShenYin/ShenYin/UI/Mode/ModeVC.swift

similarity index 84%
rename from ShenYin/ShenYin/lan/AiSupportLanguage.swift
rename to ShenYin/ShenYin/JoySdk/AiSupportLanguage.swift
index 2b4024d..9a55953 100644 (file)
@@ -24,17 +24,10 @@ enum AiSupportLanguage:String{
     case thai = "thai"
     case Arabic = "Arabic"
     case Vietnam = "Vietnam"
-    
-    /// 现场录音,通话录音,同传听译
-//    static var record:[AiSupportLanguage]{
-//        return [.chinse,.english,.japanese,.korean]
-//    }
+
     static var chinse2english:[AiSupportLanguage]{
         return [.chinse,.english]
     }
-//    static var dialog:[AiSupportLanguage]{
-//        return [.chinse,.english,.japanese]
-//    }
     static var translate:[AiSupportLanguage]{
         return [.chinse,.english,.japanese,.korean,.french,.spanish,.portuguese,.indonesian,.russian,.malay,German,Filipino,thai,Arabic,Vietnam]
     }
@@ -106,12 +99,6 @@ enum AiSupportLanguage:String{
             return kJoyGemAILocalizationVI
         }
     }
-    
 }
-//现场录音 中,英,日,韩
-//通话录音 中,英,日,韩
-//双耳互译 中英
-//同传听译 中,英,日,韩
-//面对面翻译 中,英,日
-//文本翻译 中、英、日、韩、法、西班牙、葡萄牙、印度尼西亚、俄文、马来文
+
 
index 5ada8b4..83664a6 100644 (file)
@@ -10,9 +10,6 @@ import JoyGemAI
 import SVProgressHUD
 import UIKit
 
-import UIKit
-import JoyGemAI
-
 class JoyChat:NSObject{
     var isTtsPlaying = false
     var dataList:[ChatCellModel] = []
index 1cd4054..02c4978 100644 (file)
 //
 import JoyGemAI
 
-class JoyDevice{
+enum ModeEffectsType:Int{
+    case normal
+    case fashion
+    case classic
+    case rock
+    case jazz
+    case custom
+    
+    var title:String{
+        switch self {
+        case .normal:
+            return "正常".l10n
+        case .fashion:
+            return "流行".l10n
+        case .classic:
+            return "经典".l10n
+        case .rock:
+            return "摇滚".l10n
+        case .jazz:
+            return "爵士".l10n
+        case .custom:
+            return "自定义".l10n
+        }
+    }
+    var img:String{
+        switch self {
+        case .normal:
+            return "mode_normal"
+        case .fashion:
+            return "mode_fashion"
+        case .classic:
+            return "mode_classic"
+        case .rock:
+            return "mode_rock"
+        case .jazz:
+            return "mode_jazz"
+        case .custom:
+            return "mode_custom"
+        }
+    }
+    var value:JoyGemEQMode{
+        switch self {
+        case .normal:
+            return .normal
+        case .fashion:
+            return .pop
+        case .classic:
+            return .classic
+        case .rock:
+            return .rock
+        case .jazz:
+            return .jazz
+        case .custom:
+            return .custom
+        }
+    }
     
-    static func findHeadphone(_ mode:JoyGemFindHeadphoneMode){
-        JoyGemAIManager.shared().device.findHeadphone(mode) { err in
+    static var all:[ModeEffectsType]{
+        return [.normal,.fashion,.classic,.rock,.jazz,.custom]
+    }
+}
+
+enum FindType:Int{
+    case left
+    case right
+    case all
+    case cancel
+    var value:JoyGemFindHeadphoneMode{
+        switch self {
+        case .left:
+            return .left
+        case .right:
+            return .right
+        case .cancel:
+            return .cancel
+        case .all:
+            return .all
+        }
+    }
+}
+
+class JoyDevice{
+    static func findHeadphone(_ mode:FindType){
+        JoyGemAIManager.shared().device.findHeadphone(mode.value) { err in
             Logger.debug("findHeadphone:\(err)");
         }
     }
+    static func getEQMode(finished:@escaping (ModeEffectsType?)->Void){
+        JoyGemAIManager.shared().device.getEQMode { mode in
+            let type = ModeEffectsType.all.first(where: {$0.value == mode}) ?? .normal
+            finished(type)
+        } error: { err in
+            Logger.debug("getEQMode:\(err)");
+            finished(nil)
+        }
+    }
+    static func setEQMode(_ type:ModeEffectsType){
+        JoyGemAIManager.shared().device.setEQMode(type.value) { err in
+            Logger.debug("setEQMode:\(err)");
+        }
+    }
+    
     
+    static func getCustomEQ(finished:@escaping ([NSNumber]?)->Void){
+        JoyGemAIManager.shared().device.getCustomEQ { eq in
+            Logger.debug("getCustomEQ:\(eq)");
+            finished(eq.bands)
+        } error: { err in
+            Logger.debug("getCustomEQ:\(err)");
+            finished(nil)
+        }
+    }
+    static func resetCustomEQ(){
+        JoyGemAIManager.shared().device.resetCustomEQ { err in
+            Logger.debug("resetCustomEQ:\(err)");
+        }
+    }
+    static func setCustomEQ(index:Int,value:Int){
+        JoyGemAIManager.shared().device.setCustomEQ(UInt(index), withGain: value) { err in
+            debugPrint("setCustomEQ:\(err)");
+        }
+    }
 }
index 15c2b45..94cf34e 100644 (file)
@@ -13,11 +13,37 @@ class JoySdkManager:NSObject{
     var record:JoyRecord!
     var callRecord:JoyCallRecord!
     var chat:JoyChat!
+    
+    static var serviceUUID:String{
+        return kJoyGemAIServiceUUID
+    }
+    static var notifyUUID:String{
+        return kJoyGemAICharacteristicNotifyUUID
+    }
+
 }
 extension JoySdkManager {
     func setupSdk(){
         //MARK: 初始化SDK
         JoyGemAIManager.shared().initSdk()
+        JoyGemAIManager.shared().delegate = self;
+        JoyGemAIManager.shared().dataSource = self;
+        setupLog()
+
+        record = JoyRecord()
+        callRecord = JoyCallRecord()
+        chat = JoyChat()
+        
+        let options: AVAudioSession.CategoryOptions = [.allowBluetooth]
+        do {
+            try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
+            try AVAudioSession.sharedInstance().setActive(true)
+        } catch {
+            Logger.debug(error)
+        }
+    }
+    
+    func setupLog(){
         //MARK: 配置日志类型
         //JoyGemAIManager.shared().setLogMode(JoyGemLogMode.all)
         JoyGemAIManager.shared().setLogMode(JoyGemLogMode.close)
@@ -62,16 +88,40 @@ extension JoySdkManager {
         } else {
             Logger.debug("无法找到应用支持目录")
         }
-        
         //MARK: 配置缓存路径
         let tempPath = NSTemporaryDirectory();
         JoyGemAIManager.shared().setCacheDirectory(tempPath)
         JoyGemAIManager.shared().setTWSAutoSync(true)
-        
-        record = JoyRecord()
-        callRecord = JoyCallRecord()
-        chat = JoyChat()
-        
+    }
+    
+    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
+        let success = JoyGemAIManager.shared().configService(service) { chars in
+            for char in chars {
+                Logger.debug(char)
+                peripheral.setNotifyValue(true, for: char)
+            }
+        }
+        if (!success) {
+            Logger.debug("初始化失败!")
+        }
+    }
+    func bleConnected(){
+        JoyGemAIManager.shared().bleConnected()
+    }
+    func receiveValue(_ characteristic:CBCharacteristic){
+        JoyGemAIManager.shared().receiveValue(characteristic)
+    }
+}
+
+
+extension JoySdkManager : JoyGemAIManagerDelegate {
+    func joyGemAuthFailedCallback() {
+        Logger.debug("鉴权失败")
+        YLprogressHUD.showAutoHiden("鉴权失败")
+    }
+    func joyGemAuthSuccessCallback() {
+        Logger.debug("鉴权成功")
+        PcmSound.sharedInstance().setup(16000, withchannels: 1)
         let options: AVAudioSession.CategoryOptions = [.allowBluetooth]
         do {
             try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
@@ -79,7 +129,92 @@ extension JoySdkManager {
         } catch {
             Logger.debug(error)
         }
+        
+        DeviceCache.saveLastConnected(mac: BleManager.shared.connectPeripheral!.mac)
+        DeviceCache.shared.add(BleManager.shared.connectPeripheral!.device.identifier.uuidString, mac: BleManager.shared.connectPeripheral!.mac)
+        BleManager.shared.isConnetd = true
+        BleManager.shared.didConnectDeviceCallback?(BleManager.shared.connectPeripheral!)
+        NotificationManager.post(type: .deviceValidChange, objtect: nil)
+        DeviceVM.updateOtaVersion()
+    }
+    
+    func joyGemAction(_ action: JoyGemActionMode) {
+        Logger.debug(action)
+        if !CacheManager.shared.user.isLogin{
+            return
+        }
+        switch action {
+        case .cancel:
+            Logger.debug("请求关闭录音功能/通知关闭了对话")
+            if let topVC = App.shared.topVC(), let vc = topVC as? FieldRecordingVC {
+                vc.stopRecord()
+            }
+            if let topVC = App.shared.topVC(), let vc = topVC as? CallingRecordVC {
+                vc.stopRecord()
+            }
+            if let topVC = App.shared.topVC(), let vc = topVC as? StereoCallVC {
+                vc.stopRecord()
+            }
+            JoySdkManager.shared.record.recordStop()
+        case .recordLive:
+            Logger.debug("请求开启现场录音")
+            if let vc = App.shared.topVC() as? FieldRecordingVC {
+                vc.startRecord()
+            }
+            else{
+                App.shared.goToPage(FieldRecordingVC(autoStart: true))
+                JoySdkManager.shared.record.recordStart()
+            }
+        case .recordCall:
+            Logger.debug("请求开启通话录音")
+            if JoySdkManager.shared.callRecord.supportStereo{
+                if let vc = App.shared.topVC() as? StereoCallVC {
+                    vc.startRecord()
+                }else{
+                    App.shared.goToPage(CallingRecordVC(autoStart: true))
+                    JoySdkManager.shared.callRecord.callRecordStart()
+                }
+            }
+            else{
+                if let vc = App.shared.topVC() as? CallingRecordVC {
+                    vc.startRecord()
+                }else{
+                    App.shared.goToPage(CallingRecordVC(autoStart: true))
+                    JoySdkManager.shared.callRecord.callRecordStart()
+                }
+            }
+            
+        case .si:
+            Logger.debug( "请求开启同传听译")
+        case .chat:
+            Logger.debug("通知开启AI对话")
+            if !App.shared.topVC().isKind(of: ChatVC.self) {
+                App.shared.goToPage(ChatVC())
+            }
+        @unknown default:
+            break
+        }
+    }
+}
+extension JoySdkManager : JoyGemAIManagerDataSource {
+    func joyGemSend(_ data: Data, with characteristic: CBCharacteristic) {
+        //        print("发送",data.map { String($0) }.joined(separator: ""))
+        BleManager.shared.joySdkSend(data, with: characteristic)
     }
 }
 
 
+extension JoySdkManager{
+   static func getMac(_ dict:[String:Any])->String?{
+        if let advMsd = dict[CBAdvertisementDataManufacturerDataKey] as? Data {
+            if (advMsd.count >= 13) {
+                let mac = advMsd[7...12];
+                return mac.map { String($0, radix: 16).padLeft(toLength: 2, withPad: "0") }.joined(separator: ":").uppercased()
+            } else {
+                return nil
+            }
+        } else {
+            return nil
+        }
+    }
+}
index 493adf9..ab82dd9 100644 (file)
@@ -7,7 +7,6 @@
 
 import UIKit
 import CoreBluetooth
-import JoyGemAI
 import AVFAudio
 
 class DCPeripheral{
@@ -22,26 +21,17 @@ class DCPeripheral{
 class BleManager: NSObject {
     var discoverDeviceCallback: (([DCPeripheral]) -> Void)?
     var didConnectDeviceCallback: ((DCPeripheral) -> Void)?
-    var disConnectDeviceCallback: ((DCPeripheral) -> Void)?
     var conetedFailureCallback: ((DCPeripheral) -> Void)?
     
     private var centralManager: CBCentralManager!
     var devices: [DCPeripheral] = []
     var connectPeripheral: DCPeripheral?
-    var otaCharacteristic:CBCharacteristic?
+    static let shared = BleManager()
+    var isConnetd:Bool = false
     
     private override init() {
         super.init()
         centralManager = CBCentralManager(delegate: self, queue: nil)
-        setupJoySdk()
-    }
-    
-    static let shared = BleManager()
-    var isConnetd:Bool = false
-    
-    func setupJoySdk(){
-        JoyGemAIManager.shared().delegate = self;
-        JoyGemAIManager.shared().dataSource = self;
     }
 }
 extension BleManager:CBCentralManagerDelegate{
@@ -81,7 +71,7 @@ extension BleManager:CBCentralManagerDelegate{
 //        if peripheral.identifier.uuidString != "DB209A55-DD0E-5031-29FA-40D734C34971" {
 //            return
 //        }
-        let mac = getMac(advertisementData) ?? ""
+        let mac = JoySdkManager.getMac(advertisementData) ?? ""
         devices.append(DCPeripheral(device: peripheral,mac: mac))
         Logger.debug(peripheral)
         discoverDeviceCallback?(devices)
@@ -92,44 +82,23 @@ extension BleManager:CBCentralManagerDelegate{
         Logger.debug("蓝牙已连接 \(peripheral)")
 
         peripheral.delegate = self
-        peripheral.discoverServices([CBUUID(string: kJoyGemAIServiceUUID),CBUUID(string: "AE00")]);
-        
-//        DeviceCache.saveLastConnected(mac: connectPeripheral!.mac)
-//        DeviceCache.shared.add(connectPeripheral!.device.identifier.uuidString, mac: connectPeripheral!.mac)
-//        self.isConnetd = true
-//        didConnectDeviceCallback?(connectPeripheral!)
-//        NotificationManager.post(type: .deviceValidChange, objtect: nil)
-//        DeviceVM.updateOtaVersion()
+        peripheral.discoverServices([CBUUID(string: JoySdkManager.serviceUUID),CBUUID(string: OtaMananger.otaServiceUUId)]);
     }
     func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
         Logger.debug("peripheral: %@ failed to connect", peripheral)
         conetedFailureCallback?(connectPeripheral!)
     }
     func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
-        Logger.debug("蓝牙已断开 \(connectPeripheral)")
+        Logger.debug("蓝牙已断开 \(peripheral)")
         self.isConnetd = false
         NotificationManager.post(type: .deviceValidChange, objtect: nil)
-        disConnectDeviceCallback?(connectPeripheral!)
         OtaMananger.shared.otaManager.centralManager(central, didDisconnectPeripheral: peripheral, error: error)
         checkConectState()
     }
-    func getMac(_ dict:[String:Any])->String?{
-        if let advMsd = dict[CBAdvertisementDataManufacturerDataKey] as? Data {
-            if (advMsd.count >= 13) {
-                let mac = advMsd[7...12];
-                return mac.map { String($0, radix: 16).padLeft(toLength: 2, withPad: "0") }.joined(separator: ":").uppercased()
-            } else {
-                return nil
-            }
-        } else {
-            return nil
-        }
-    }
 }
 
 extension BleManager: CBPeripheralDelegate {
     func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
-        
         Logger.debug("发现服务成功")
         for service in peripheral.services! {
             Logger.debug("peripheral service: %@", service)
@@ -139,49 +108,38 @@ extension BleManager: CBPeripheralDelegate {
     }
     
     func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
-        if (service.uuid.uuidString == kJoyGemAIServiceUUID) {
-            let success = JoyGemAIManager.shared().configService(service) { chars in
-                for char in chars {
-                    Logger.debug(char)
-                    peripheral.setNotifyValue(true, for: char)
-                }
-            }
-            if (!success) {
-                Logger.debug("初始化失败!")
-            }
+        if (service.uuid.uuidString == JoySdkManager.serviceUUID) {
+            JoySdkManager.shared.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: error)
         }
-        else if service.uuid.uuidString == "AE00",let list = service.characteristics{
+        else if service.uuid.uuidString == OtaMananger.otaServiceUUId{
             OtaMananger.shared.otaManager.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: error)
-                
         }
     }
     
     func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?) {
-        if (characteristic.isNotifying == true && characteristic.service?.uuid.uuidString == kJoyGemAIServiceUUID && characteristic.uuid.uuidString == kJoyGemAICharacteristicNotifyUUID) {
-            //MARK: 使能成功时需要
+        if (characteristic.isNotifying == true && characteristic.service?.uuid.uuidString == JoySdkManager.serviceUUID && characteristic.uuid.uuidString == JoySdkManager.notifyUUID) {
             Logger.debug("特征使能成功")
-            JoyGemAIManager.shared().bleConnected()
+            JoySdkManager.shared.bleConnected()
         }
-        if characteristic.uuid.uuidString == "AE02" || characteristic.uuid.uuidString == "AE01"{
+        if OtaMananger.isOtadata(characteristic){
             OtaMananger.shared.otaManager.peripheral(peripheral, didUpdateNotificationStateFor: characteristic, error: error)
         }
     }
     
     func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
 //        Logger.debug("收到数据 ===uUId ",characteristic.uuid)
-        if characteristic.uuid.uuidString == "AE02" || characteristic.uuid.uuidString == "AE01"{
-            if let data = characteristic.value,error == nil {
+        if OtaMananger.isOtadata(characteristic){
+            if let _ = characteristic.value,error == nil {
                 OtaMananger.shared.otaManager.peripheral(peripheral, didUpdateValueFor: characteristic)
             }
             else{
-                Logger.debug("收到数据 ===\(characteristic.uuid)","无数据")
+                Logger.debug("ota 收到数据 ===\(characteristic.uuid)","无数据")
             }
         }
         else {
             //MARK: 需要配置传入数据
-            JoyGemAIManager.shared().receiveValue(characteristic)
+            JoySdkManager.shared.receiveValue(characteristic)
         }
-
     }
     
     func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
@@ -194,8 +152,6 @@ extension BleManager: CBPeripheralDelegate {
 }
 
 extension BleManager{
-    
-    // MARK: - Public Methods
     func startScanDevice() {
 //        centralManager.stopScan()
         Logger.debug("扫描中...")
@@ -208,10 +164,9 @@ extension BleManager{
 //                devices.append(DCPeripheral(device: item,mac: mac))
 //            }
 //        }
-        centralManager.scanForPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)],options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
+        centralManager.scanForPeripherals(withServices: [CBUUID(string: JoySdkManager.serviceUUID)],options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
         discoverDeviceCallback?(devices)
     }
-
     
     func stopScanDevice() {
         centralManager.stopScan()
@@ -237,100 +192,14 @@ extension BleManager{
     }
 }
 
-
-extension BleManager : JoyGemAIManagerDelegate {
-    func joyGemAuthFailedCallback() {
-        Logger.debug("鉴权失败")
-        YLprogressHUD.showAutoHiden("鉴权失败")
-    }
-    
-    func joyGemAuthSuccessCallback() {
-        Logger.debug("鉴权成功")
-        PcmSound.sharedInstance().setup(16000, withchannels: 1)
-        let options: AVAudioSession.CategoryOptions = [.allowBluetooth]
-        do {
-            try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
-            try AVAudioSession.sharedInstance().setActive(true)
-        } catch {
-            Logger.debug(error)
-        }
-        
-        DeviceCache.saveLastConnected(mac: connectPeripheral!.mac)
-        DeviceCache.shared.add(connectPeripheral!.device.identifier.uuidString, mac: connectPeripheral!.mac)
-        self.isConnetd = true
-        didConnectDeviceCallback?(connectPeripheral!)
-        NotificationManager.post(type: .deviceValidChange, objtect: nil)
-        DeviceVM.updateOtaVersion()
-    }
-    
-    func joyGemAction(_ action: JoyGemActionMode) {
-        Logger.debug(action)
-        if !CacheManager.shared.user.isLogin{
-            return
-        }
-        switch action {
-        case .cancel:
-            Logger.debug("请求关闭录音功能/通知关闭了对话")
-            if let topVC = App.shared.topVC(), let vc = topVC as? FieldRecordingVC {
-                vc.stopRecord()
-            }
-            if let topVC = App.shared.topVC(), let vc = topVC as? CallingRecordVC {
-                vc.stopRecord()
-            }
-            if let topVC = App.shared.topVC(), let vc = topVC as? StereoCallVC {
-                vc.stopRecord()
-            }
-            JoySdkManager.shared.record.recordStop()
-        case .recordLive:
-            Logger.debug("请求开启现场录音")
-            if let vc = App.shared.topVC() as? FieldRecordingVC {
-                vc.startRecord()
-            }
-            else{
-                App.shared.goToPage(FieldRecordingVC(autoStart: true))
-                JoySdkManager.shared.record.recordStart()
-            }
-        case .recordCall:
-                Logger.debug("请求开启通话录音")
-            if JoySdkManager.shared.callRecord.supportStereo{
-                if let vc = App.shared.topVC() as? StereoCallVC {
-                    vc.startRecord()
-                }else{
-                    App.shared.goToPage(CallingRecordVC(autoStart: true))
-                    JoySdkManager.shared.callRecord.callRecordStart()
-                }
-            }
-            else{
-                if let vc = App.shared.topVC() as? CallingRecordVC {
-                    vc.startRecord()
-                }else{
-                    App.shared.goToPage(CallingRecordVC(autoStart: true))
-                    JoySdkManager.shared.callRecord.callRecordStart()
-                }
-            }
-
-        case .si:
-                Logger.debug( "请求开启同传听译")
-        case .chat:
-            Logger.debug("通知开启AI对话")
-            if !App.shared.topVC().isKind(of: ChatVC.self) {
-                App.shared.goToPage(ChatVC())
-            }
-        @unknown default:
-            break
-        }
-    }
-}
-extension BleManager : JoyGemAIManagerDataSource {
-    func joyGemSend(_ data: Data, with characteristic: CBCharacteristic) {
-//        print("发送",data.map { String($0) }.joined(separator: ""))
+extension BleManager{
+    func joySdkSend(_ data: Data, with characteristic: CBCharacteristic) {
         if let connectPeripheral = connectPeripheral{
             connectPeripheral.device.writeValue(data, for: characteristic, type:.withoutResponse)
         }
     }
 }
 
-
 extension BleManager{
     func isConected(mac:String)->Bool{
         guard let device = connectPeripheral else { return false }
@@ -364,32 +233,14 @@ extension BleManager{
         }
         BleManager.shared.startScanDevice()
     }
-//    func checkConnected(){
-//        if BleManager.shared.isConnetd {
-//            return
-//        }
-//        
-//        let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)])
-//        for item in list {
-//            Logger.debug("当前状态",item.name ?? "",item.state)
-//            if let mac = DeviceCache.shared.getMac(item.identifier.uuidString){
-////                devices.append()
-//                BleManager.shared.connectPeripheral(DCPeripheral(device: item,mac: mac))
-//                break
-//            }
-//        }
-//        
-//        
-//    }
-    
+
     func checkSettingsConnected()->[CBPeripheral]{
-        let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)])
+        let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: JoySdkManager.serviceUUID)])
         Logger.debug("已连接设备",list)
         return list
     }
 }
 
-
 extension BleManager{
     func checkConectState(){
         guard let mac = connectPeripheral?.mac else {
index b82334a..3d0334a 100644 (file)
@@ -6,6 +6,7 @@
 //
 
 import Foundation
+import CoreBluetooth
 
 class OtaMananger:NSObject{
     static let shared = OtaMananger()
@@ -14,6 +15,14 @@ class OtaMananger:NSObject{
         super.init()
         otaManager.addDelegate(self)
     }
+    
+    static var otaServiceUUId:String{
+        return "AE00"
+    }
+    static func isOtadata(_ characteristic:CBCharacteristic)->Bool{
+//        guard let <#constant#> = <#expression#> else { return <#return value#> }
+        return (characteristic.service?.uuid.uuidString == otaServiceUUId) && (characteristic.uuid.uuidString == "AE02" || characteristic.uuid.uuidString == "AE01")
+    }
 }
 
 extension OtaMananger:JLBleAssistManagerOtaDelegate{
diff --git a/ShenYin/ShenYin/Ota/update.ufw b/ShenYin/ShenYin/Ota/update.ufw
new file mode 100644 (file)
index 0000000..91fa5a9
Binary files /dev/null and b/ShenYin/ShenYin/Ota/update.ufw differ
index d5768d3..0da4743 100644 (file)
@@ -4,22 +4,19 @@
 //
 //  Created by liangshi on 2025/9/3.
 //
-import JoyGemAI
+
 import UIKit
 class ChatHeaderView: BaseView {
     let icon = UIImageView()
     let titleLabel = UILabel()
     let desLabel = UILabel()
-    
-    var role:JoyGemSpeaker!{
-        didSet{
-            titleLabel.text = "嗨!我是".l10n + role.name
-            icon.image = UIImage(named: "role_" + role.role)
-        }
+
+    func update(name:String,role:String){
+        titleLabel.text = "嗨!我是".l10n + name
+        icon.image = UIImage(named: "role_" + role)
     }
     
     override func setupViews() {
-//        backgroundColor = .red
         addSubviews([icon,titleLabel,desLabel])
         
         icon.do { v in
@@ -27,7 +24,6 @@ class ChatHeaderView: BaseView {
             v.image = UIImage(named: "chat_xiaoyin")
         }
         titleLabel.do {v in
-            v.text = "嗨!我是小音"
             v.numberOfLines = 0
             v.textAlignment = .center
             v.textColor = .hexString("#121212")
@@ -1,5 +1,5 @@
 //
-//  NavigationBarItem.swift
+//  ChatNavigationBarItem.swift
 //  ShenYin
 //
 //  Created by liangshi on 2025/9/3.
@@ -7,8 +7,7 @@
 import UIKit
 import JoyGemAI
 
-
-class NavigationBarItem: BaseView {
+class ChatNavigationBarItem: BaseView {
     let icon = UIImageView()
     let titleLabel = UILabel()
     
@@ -52,6 +51,7 @@ class ChatRoleItem: BaseView {
         }
     }
     
+    
     override func setupViews() {
         //        backgroundColor = .red
         addSubviews([titleLabel,icon,deslabel])
index b6d491a..0b63f91 100644 (file)
@@ -9,7 +9,7 @@ import UIKit
 import JoyGemAI
 import AVFAudio
 class ChatVC:BaseVC{
-    let rightItem = NavigationBarItem(frame: CGRect(x: 0, y: 0, width: 80, height: 44))
+    let rightItem = ChatNavigationBarItem(frame: CGRect(x: 0, y: 0, width: 80, height: 44))
     let roleItem = ChatRoleItem(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
     
     let toolBar = ChatRecordBar()
@@ -141,7 +141,7 @@ class ChatVC:BaseVC{
         let vc = RoleListVC(list: roleList, selectedModel: roleItem.role) {[weak self] model in
             guard let self = self else{return}
             roleItem.role = model
-            headerView.role = model
+            headerView.update(name: model.name, role: model.role)
             JoyGemChatManager.shared().setSpeaker(model)
         }
         App.shared.goToPage(vc)
@@ -168,7 +168,7 @@ class ChatVC:BaseVC{
                 }
             }            
             self.roleItem.role = currentRole
-            self.headerView.role = currentRole
+            self.headerView.update(name: self.roleItem.role.name, role: self.roleItem.role.role)
             JoyGemChatManager.shared().setSpeaker(self.roleItem.role)
         }
     }
index 173bfaf..4751a30 100644 (file)
@@ -6,9 +6,7 @@
 //
 
 import UIKit
-import CoreBluetooth
 import DGActivityIndicatorView
-import JoyGemAI
 enum BleScanState{
     case scan
     case has
@@ -73,7 +71,6 @@ class BleScanVC: BaseVC{
             }
             else{
                 self.scanState = .none
-//                self.headerView.rippleView.stopAnimating()
             }
             self.tableView.reloadData()
         }
@@ -149,10 +146,6 @@ class BleScanHeaderView: BaseView {
             make.center.equalToSuperview()
         }
     }
-    
-
-    
-
 }
 
 class ScanStateCell: BaseTableViewCell {
index 3b68c5e..ff1b9ec 100644 (file)
@@ -6,8 +6,6 @@
 //
 
 import JoyGemAI
-
-
 class DeviceVM:BaseVM{
     static let shared = DeviceVM()
     var dataList = [HomeDeviceModel]()
index 01861ba..fd66b08 100644 (file)
@@ -6,7 +6,6 @@
 //
 
 import UIKit
-import JoyGemAI
 class CustomEqVC:BaseVC{
     private let bgView = UIView()
     private let sliderBgView = UIView()
@@ -135,26 +134,19 @@ class CustomEqVC:BaseVC{
     }
     
     override func setupData() {
-        JoyGemAIManager.shared().device.getCustomEQ {[weak self] eq in
-            Logger.debug("getCustomEQ:\(eq)");
-            self?.resetSlider(eq.bands)
-        } error: { err in
-            Logger.debug("getCustomEQ:\(err)");
+        JoyDevice.getCustomEQ {[weak self] list in
+            guard let list = list else{return}
+            self?.resetSlider(list)
         }
     }
-
     @objc func resetAction(){
         for item in list {
             item.slider.setValue(0, animated: false)
         }
-        JoyGemAIManager.shared().device.resetCustomEQ { err in
-            Logger.debug("setEQMode:\(err)");
-        }
+        JoyDevice.resetCustomEQ()
     }
     @objc func sliderValueChange(index:Int,value:Int){
-        JoyGemAIManager.shared().device.setCustomEQ(UInt(index), withGain: value) { err in
-            debugPrint("setCustomEQ:\(err)");
-        }
+        JoyDevice.setCustomEQ(index: index, value: value)
     }
     func resetSlider(_ eqs:[NSNumber]){
         for i in 0..<eqs.count {
index d465353..7d2d02d 100644 (file)
@@ -7,9 +7,10 @@
 //
 
 import UIKit
-import JoyGemAI
 import DGActivityIndicatorView
 
+
+
 class FindVC:BaseVC{
     private let titleLabel = UILabel()
     private let desLabel = UILabel()
@@ -128,7 +129,7 @@ class FindVC:BaseVC{
         }
     }
     func findAction(){
-        var mode:JoyGemFindHeadphoneMode = .cancel
+        var mode:FindType = .cancel
         if leftRadar.start &&  rightRadar.start{
             mode = .all
         }
index a534d50..456e005 100644 (file)
@@ -6,75 +6,12 @@
 //
 
 import UIKit
-import JoyGemAI
-
-enum ModeEffectsType:Int{
-    case normal
-    case fashion
-    case classic
-    case rock
-    case jazz
-    case custom
-    
-    var title:String{
-        switch self {
-        case .normal:
-            return "正常".l10n
-        case .fashion:
-            return "流行".l10n
-        case .classic:
-            return "经典".l10n
-        case .rock:
-            return "摇滚".l10n
-        case .jazz:
-            return "爵士".l10n
-        case .custom:
-            return "自定义".l10n
-        }
-    }
-    var img:String{
-        switch self {
-        case .normal:
-            return "mode_normal"
-        case .fashion:
-            return "mode_fashion"
-        case .classic:
-            return "mode_classic"
-        case .rock:
-            return "mode_rock"
-        case .jazz:
-            return "mode_jazz"
-        case .custom:
-            return "mode_custom"
-        }
-    }
-    var value:JoyGemEQMode{
-        switch self {
-        case .normal:
-            return .normal
-        case .fashion:
-            return .pop
-        case .classic:
-            return .classic
-        case .rock:
-            return .rock
-        case .jazz:
-            return .jazz
-        case .custom:
-            return .custom
-        }
-    }
-    
-    static var all:[ModeEffectsType]{
-        return [.normal,.fashion,.classic,.rock,.jazz,.custom]
-    }
-}
 
 class ModeEffectsView: BaseView {
     let titleLabel = UILabel()
     var list:[ModeEffectsType] = ModeEffectsType.all
     var itemViews = [ItemView]()
-    var selectedMode:((_ mode:JoyGemEQMode)->Void)?
+    var selectedMode:((_ mode:ModeEffectsType)->Void)?
     
     var mode:ModeEffectsType = .normal{
         didSet{
@@ -160,7 +97,7 @@ class ModeEffectsView: BaseView {
                 item.isSelected = false
             }
         }
-        selectedMode?(view.type.value)
+        selectedMode?(view.type)
     }
     
     class ItemView: BaseView {
index 1db1d24..39e0989 100644 (file)
@@ -5,7 +5,6 @@
 //  Created by liangshi on 2025/8/5.
 //
 import UIKit
-import JoyGemAI
 class ModeVC:BaseVC{
     let bgView = UIScrollView()
     let headerView = CurrentDeviceView()
@@ -71,11 +70,9 @@ class ModeVC:BaseVC{
         }
     }
     override func setupData() {
-        JoyGemAIManager.shared().device.getEQMode {[weak self] mode in
-            guard let self = self else{return}
-            effectsView.mode = ModeEffectsType.all.first(where: {$0.value == mode}) ?? .normal
-        } error: { err in
-            Logger.debug("getEQMode:\(err)");
+        JoyDevice.getEQMode {[weak self] type in
+              guard let self = self else{return}
+              effectsView.mode = type ?? .normal
         }
     }
     
@@ -92,13 +89,11 @@ extension ModeVC{
         self.findView.alpha = BleManager.shared.isConnetd ? 1:0.3
     }
     
-    func selectedModeAction(_ mode:JoyGemEQMode){
+    func selectedModeAction(_ mode:ModeEffectsType){
         if !BleManager.shared.isConnetd {
             return
         }
-        JoyGemAIManager.shared().device.setEQMode(mode) { err in
-            Logger.debug("setEQMode:\(err)");
-        }
+        JoyDevice.setEQMode(mode)
         if mode == .custom {
             App.shared.goToPage(CustomEqVC())
         }