From: liangzhenying <867174124@qq.com> Date: Thu, 29 Feb 2024 08:15:54 +0000 (+0800) Subject: 增加声音解析指令 X-Git-Tag: 阿里鉴权~34 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=666166ae04e12382d514ac99c0846e6213a5d336;p=mirrors%2FMouseSdk-MacOS.git 增加声音解析指令 --- diff --git a/Document/1.pcm b/Document/1.pcm new file mode 100644 index 0000000..b7357d6 Binary files /dev/null and b/Document/1.pcm differ diff --git a/Document/Output.pcm b/Document/Output.pcm new file mode 100644 index 0000000..04e9e91 Binary files /dev/null and b/Document/Output.pcm differ diff --git a/Document/abc.pcm b/Document/abc.pcm new file mode 100644 index 0000000..d934169 Binary files /dev/null and b/Document/abc.pcm differ diff --git a/Document/scb2.bin b/Document/scb2.bin new file mode 100644 index 0000000..3448625 Binary files /dev/null and b/Document/scb2.bin differ diff --git "a/Document/\346\210\252\345\261\2172024-02-29 15.33.35.png" "b/Document/\346\210\252\345\261\2172024-02-29 15.33.35.png" new file mode 100644 index 0000000..65c72ae Binary files /dev/null and "b/Document/\346\210\252\345\261\2172024-02-29 15.33.35.png" differ diff --git a/MouseSdk/AiSdk/AiIot.h b/MouseSdk/AiSdk/AiIot.h index 3de4ab4..b8c68c7 100644 --- a/MouseSdk/AiSdk/AiIot.h +++ b/MouseSdk/AiSdk/AiIot.h @@ -18,18 +18,17 @@ NS_ASSUME_NONNULL_BEGIN /// 发送给蓝牙设备 /// - Parameter data: 传输的数据 -- (void)sendToBle:(NSData *)data; +- (void)aiIotSendToBle:(NSData *)data; @end @interface AiIot : NSObject @property (nonatomic, weak) id delegate; -+(id)shared; ++(AiIot *)shared; - (void)startLogin; - /// 将数据传输给sdk处理 /// - Parameter data: 传输的数据 - (void)sendToSdk:(NSData *)data; diff --git a/MouseSdk/AiSdk/AiIot.m b/MouseSdk/AiSdk/AiIot.m index 86739c0..800278f 100644 --- a/MouseSdk/AiSdk/AiIot.m +++ b/MouseSdk/AiSdk/AiIot.m @@ -7,13 +7,16 @@ #import "AiIot.h" #import "AiIotConnectManager.h" +#import "AiIotAudioManager.h" +#import "AiIotTools.h" @interface AiIot() @property (nonatomic, strong) AiIotConnectManager *loginManager; +@property (nonatomic, strong) AiIotAudioManager *audioManager; @end @implementation AiIot -+(id)shared{ ++(AiIot *)shared{ static AiIot *manager = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ @@ -32,27 +35,53 @@ } return _loginManager; } +-(AiIotAudioManager *)audioManager{ + if (!_audioManager) { + _audioManager = [[AiIotAudioManager alloc] init]; + __weak typeof(self) ws = self; + _audioManager.outputData = ^(NSData * _Nonnull data) { + [ws willSendToBle:data]; + }; + _audioManager.outputLog = ^(NSString * _Nonnull log) { + [ws showLog:log]; + }; + } + return _audioManager; +} - (void)startLogin{ [self.loginManager login]; } - (void)sendToSdk:(NSData *)data{ - uint8_t cmdType = 0x00; - switch (cmdType) { - case 0x00: - [self.loginManager sendToConnectKit:data]; - break; - - default: - break; + NSString *str = [[AiIotTools dataToHexString:data] lowercaseString]; + if([str hasPrefix:@"0affff64"] || [str hasPrefix:@"9c31"]){ + //声音 + [self.audioManager receiveData:data]; } + else{ + [self showLog:@"未实现指令"]; + } +// uint8_t cmdType = 0x00; +// switch (cmdType) { +// case 0x00: +// [self.loginManager receiveData:data]; +// break; +// case 0x01: +// [self.audioManager receiveData:data]; +// break; +// default: +// break; +// } } - (void)willSendToBle:(NSData *)data{ if (self.delegate) { - [self.delegate sendToBle:data]; + [self.delegate aiIotSendToBle:data]; } } +- (void)showLog:(NSString *)log{ + NSLog(@"%@",log); +} @end diff --git a/MouseSdk/AiSdk/AiIotAudioManager.h b/MouseSdk/AiSdk/AiIotAudioManager.h new file mode 100644 index 0000000..cf47d6e --- /dev/null +++ b/MouseSdk/AiSdk/AiIotAudioManager.h @@ -0,0 +1,19 @@ +// +// AiIotAudioManager.h +// AiSdk +// +// Created by incar on 2024/2/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AiIotAudioManager : NSObject +@property (nonatomic,strong)void (^outputData)(NSData *data); +@property (nonatomic,strong)void (^outputLog)(NSString *log); + +- (void)receiveData:(NSData *)data; +@end + +NS_ASSUME_NONNULL_END diff --git a/MouseSdk/AiSdk/AiIotAudioManager.m b/MouseSdk/AiSdk/AiIotAudioManager.m new file mode 100644 index 0000000..f18e6ca --- /dev/null +++ b/MouseSdk/AiSdk/AiIotAudioManager.m @@ -0,0 +1,60 @@ +// +// AiIotAudioManager.m +// AiSdk +// +// Created by incar on 2024/2/28. +// + +#import "AiIotAudioManager.h" +#import "AiIotTools.h" +@interface AiIotAudioManager () +@property (nonatomic,strong)NSMutableData *recvData; +@end + +@implementation AiIotAudioManager + +- (void)receiveData:(NSData *)data{ + NSString *str = [[AiIotTools dataToHexString:data] lowercaseString]; + if([str hasPrefix:@"0affff641431"]){ + [self showLog:@"开始录音"]; + self.recvData = [[NSMutableData alloc] init]; + } + if([str hasPrefix:@"0affff641432"]){ + [self showLog:@"结束录音"]; + [self showLog:[NSString stringWithFormat:@"完整声音数据 %@",self.recvData]]; + [self finishRecevice:self.recvData]; + self.recvData = nil; + } + else if([str hasPrefix:@"9c31"] && data.length >= 32){ + NSData *sub = [data subdataWithRange:NSMakeRange(2, data.length - 2)]; +// [self showLog:[NSString stringWithFormat:@"截取的数据 %@",sub]]; + [self.recvData appendData:sub]; + } + else{ + [self showLog:@"未实现指令"]; + } +} + +- (void)finishRecevice:(NSData *)data{ + + NSString *doc = NSHomeDirectory(); + NSString *fullPath = [NSString stringWithFormat:@"%@/Documents/1.pcm",doc]; + [self showLog:[NSString stringWithFormat:@"%@",fullPath]]; + NSError *err; + [data writeToFile:fullPath options:NSDataWritingAtomic error:&err]; + if (err) { + [self showLog:[NSString stringWithFormat:@"保存失败%@",err.description]]; + } + else{ + [self showLog:@"保存成功"]; + } +} + +- (void)showLog:(NSString *)log{ + if (self.outputLog) { + self.outputLog(log); + } +} + + +@end diff --git a/MouseSdk/AiSdk/AiIotConnectManager.h b/MouseSdk/AiSdk/AiIotConnectManager.h index eb23530..06b7675 100644 --- a/MouseSdk/AiSdk/AiIotConnectManager.h +++ b/MouseSdk/AiSdk/AiIotConnectManager.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)login; -- (void)sendToConnectKit:(NSData *)data; +- (void)receiveData:(NSData *)data; @end NS_ASSUME_NONNULL_END diff --git a/MouseSdk/AiSdk/AiIotConnectManager.m b/MouseSdk/AiSdk/AiIotConnectManager.m index c9afcf3..15fe2bc 100644 --- a/MouseSdk/AiSdk/AiIotConnectManager.m +++ b/MouseSdk/AiSdk/AiIotConnectManager.m @@ -74,7 +74,7 @@ } #pragma mark - -- (void)sendToConnectKit:(NSData *)data { +- (void)receiveData:(NSData *)data { data = [data subdataWithRange:NSMakeRange(1, data.length -1)]; __weak typeof(self) ws = self; dispatch_async(_bizbus_connect_queue, ^{ diff --git a/MouseSdk/AiSdk/AiIotTools.h b/MouseSdk/AiSdk/AiIotTools.h new file mode 100644 index 0000000..4df1896 --- /dev/null +++ b/MouseSdk/AiSdk/AiIotTools.h @@ -0,0 +1,21 @@ +// +// AiIotTools.h +// AiSdk +// +// Created by incar on 2024/2/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AiIotTools : NSObject ++ (NSString *)dataToHexString:(NSData *)data; + ++ (NSString *)dataToHexString_placeholder:(NSData *)data; + ++ (NSData *)hexStringToData:(NSString *)hexStr ; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MouseSdk/AiSdk/AiIotTools.m b/MouseSdk/AiSdk/AiIotTools.m new file mode 100644 index 0000000..1f08f72 --- /dev/null +++ b/MouseSdk/AiSdk/AiIotTools.m @@ -0,0 +1,54 @@ +// +// AiIotTools.m +// AiSdk +// +// Created by incar on 2024/2/28. +// + +#import "AiIotTools.h" + +@implementation AiIotTools ++ (NSString *)dataToHexString:(NSData *)data { + NSUInteger length = data.length; + NSMutableString *result = [NSMutableString stringWithCapacity:length * 2]; + const unsigned char *byte = data.bytes; + for (int i = 0; i < length; i++, byte++) { + [result appendFormat:@"%02X", *byte]; + } + return result; +} + ++ (NSString *)dataToHexString_placeholder:(NSData *)data { + NSUInteger length = data.length; + NSString *placeholder = @" "; + NSMutableString *result = [NSMutableString stringWithCapacity:length * 2]; + const unsigned char *byte = data.bytes; + for (int i = 0; i < length; i++, byte++) { + [result appendFormat:@"%02X%@", *byte, placeholder]; + } + return result; +} + ++ (NSData *)hexStringToData:(NSString *)hexStr { + hexStr = [hexStr stringByReplacingOccurrencesOfString:@" " withString:@""]; + hexStr = [hexStr lowercaseString]; + NSUInteger len = hexStr.length; + if (!len) return nil; + unichar *buf = malloc(sizeof(unichar) * len); + if (!buf) return nil; + [hexStr getCharacters:buf range:NSMakeRange(0, len)]; + + NSMutableData *result = [NSMutableData data]; + unsigned char bytes; + char str[3] = { '\0', '\0', '\0' }; + int i; + for (i = 0; i < len / 2; i++) { + str[0] = buf[i * 2]; + str[1] = buf[i * 2 + 1]; + bytes = strtol(str, NULL, 16); + [result appendBytes:&bytes length:1]; + } + free(buf); + return result; +} +@end diff --git a/MouseSdk/MouseSdk.xcodeproj/project.pbxproj b/MouseSdk/MouseSdk.xcodeproj/project.pbxproj index 0ab32ab..ea1e68d 100644 --- a/MouseSdk/MouseSdk.xcodeproj/project.pbxproj +++ b/MouseSdk/MouseSdk.xcodeproj/project.pbxproj @@ -32,6 +32,11 @@ 18F323842B8F330100CABA2E /* AiIotConnectManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F323822B8F330100CABA2E /* AiIotConnectManager.h */; }; 18F323852B8F330100CABA2E /* AiIotConnectManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F323832B8F330100CABA2E /* AiIotConnectManager.m */; }; 18F323872B8F338300CABA2E /* AliIotConnectKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F3237D2B8F2EFC00CABA2E /* AliIotConnectKit.framework */; }; + 18F3238A2B8F4DBE00CABA2E /* PCMPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */; }; + 18F3238E2B8F4F7300CABA2E /* AiIotAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F3238C2B8F4F7300CABA2E /* AiIotAudioManager.h */; }; + 18F3238F2B8F4F7300CABA2E /* AiIotAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F3238D2B8F4F7300CABA2E /* AiIotAudioManager.m */; }; + 18F323952B8F525C00CABA2E /* AiIotTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F323932B8F525C00CABA2E /* AiIotTools.h */; }; + 18F323962B8F525C00CABA2E /* AiIotTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F323942B8F525C00CABA2E /* AiIotTools.m */; }; 8A6657BD1406314D4CBB7CEF /* libPods-MouseSdk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0311DF3AD67ED792549B96BD /* libPods-MouseSdk.a */; }; /* End PBXBuildFile section */ @@ -118,6 +123,12 @@ 18F323782B8F2EFB00CABA2E /* AliIotConnectKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AliIotConnectKit.xcodeproj; path = AliIotConnectKitSDK/AliIotConnectKit.xcodeproj; sourceTree = ""; }; 18F323822B8F330100CABA2E /* AiIotConnectManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotConnectManager.h; sourceTree = ""; }; 18F323832B8F330100CABA2E /* AiIotConnectManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotConnectManager.m; sourceTree = ""; }; + 18F323882B8F4DBE00CABA2E /* PCMPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PCMPlayer.h; sourceTree = ""; }; + 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PCMPlayer.m; sourceTree = ""; }; + 18F3238C2B8F4F7300CABA2E /* AiIotAudioManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotAudioManager.h; sourceTree = ""; }; + 18F3238D2B8F4F7300CABA2E /* AiIotAudioManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotAudioManager.m; sourceTree = ""; }; + 18F323932B8F525C00CABA2E /* AiIotTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotTools.h; sourceTree = ""; }; + 18F323942B8F525C00CABA2E /* AiIotTools.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotTools.m; sourceTree = ""; }; 51DE1118FCBA78EBEE6FE2CD /* Pods-MouseSdk.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MouseSdk.release.xcconfig"; path = "Target Support Files/Pods-MouseSdk/Pods-MouseSdk.release.xcconfig"; sourceTree = ""; }; 811936622867478806C1A8BB /* Pods-MouseSdk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MouseSdk.debug.xcconfig"; path = "Target Support Files/Pods-MouseSdk/Pods-MouseSdk.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -199,6 +210,8 @@ 18F323612B8F13D600CABA2E /* LogVC.m */, 18F323762B8F2DAD00CABA2E /* AliIotTools.h */, 18F323752B8F2DAC00CABA2E /* AliIotTools.m */, + 18F323882B8F4DBE00CABA2E /* PCMPlayer.h */, + 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */, 18BF1E042B81E18800B8D90F /* ConnectKitVC.swift */, 18BF1DD32B81AB7F00B8D90F /* Assets.xcassets */, 18BF1DD52B81AB7F00B8D90F /* Main.storyboard */, @@ -243,6 +256,10 @@ 18BF1E892B8362D300B8D90F /* AiSdk.h */, 18F323652B8F1C1900CABA2E /* AiIot.h */, 18F323662B8F1C1900CABA2E /* AiIot.m */, + 18F323932B8F525C00CABA2E /* AiIotTools.h */, + 18F323942B8F525C00CABA2E /* AiIotTools.m */, + 18F3238C2B8F4F7300CABA2E /* AiIotAudioManager.h */, + 18F3238D2B8F4F7300CABA2E /* AiIotAudioManager.m */, 18F323822B8F330100CABA2E /* AiIotConnectManager.h */, 18F323832B8F330100CABA2E /* AiIotConnectManager.m */, ); @@ -281,9 +298,11 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 18F3238E2B8F4F7300CABA2E /* AiIotAudioManager.h in Headers */, 18BF1E8A2B8362D300B8D90F /* AiSdk.h in Headers */, 18F323672B8F1C1900CABA2E /* AiIot.h in Headers */, 18F323842B8F330100CABA2E /* AiIotConnectManager.h in Headers */, + 18F323952B8F525C00CABA2E /* AiIotTools.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -500,6 +519,7 @@ 18BF1E762B832D2E00B8D90F /* ScanVC.m in Sources */, 18BF1E222B83066200B8D90F /* BleManager.m in Sources */, 18BF1DCF2B81AB7C00B8D90F /* AppDelegate.m in Sources */, + 18F3238A2B8F4DBE00CABA2E /* PCMPlayer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -524,7 +544,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 18F3238F2B8F4F7300CABA2E /* AiIotAudioManager.m in Sources */, 18F323682B8F1C1900CABA2E /* AiIot.m in Sources */, + 18F323962B8F525C00CABA2E /* AiIotTools.m in Sources */, 18F323852B8F330100CABA2E /* AiIotConnectManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MouseSdk/MouseSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist b/MouseSdk/MouseSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist index 6cbfd27..4c533f1 100644 --- a/MouseSdk/MouseSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/MouseSdk/MouseSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AiSdk.xcscheme_^#shared#^_ orderHint - 3 + 2 MouseSdk.xcscheme_^#shared#^_ orderHint - 2 + 3 diff --git a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate index 0baa9c9..dee9fce 100644 Binary files a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate and b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MouseSdk/MouseSdk/Ble/BleManager.m b/MouseSdk/MouseSdk/Ble/BleManager.m index 7f8db83..06d10ff 100644 --- a/MouseSdk/MouseSdk/Ble/BleManager.m +++ b/MouseSdk/MouseSdk/Ble/BleManager.m @@ -8,7 +8,7 @@ #import "BleManager.h" - +#import @interface BleManager () @property (nonatomic,strong) NSMutableArray *scanArray; @property(nonatomic, strong) CBCentralManager *centralManager; @@ -16,7 +16,6 @@ @property(nonatomic, strong) CBCharacteristic *writeCha; @property(nonatomic, strong) CBCharacteristic *notifyCha; -@property(nonatomic, assign) BOOL isSdkInitSuccess; @end @implementation BleManager @@ -40,6 +39,7 @@ self = [super init]; if (self) { self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil]; + [AiIot shared].delegate = self; } return self; } @@ -100,19 +100,33 @@ } #pragma mark - CBPeripheralDelegate - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { +// for (CBService *service in peripheral.services){ +// [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FED7"],[CBUUID UUIDWithString:@"FED8"]] forService:service]; +// } for (CBService *service in peripheral.services){ - [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FED7"],[CBUUID UUIDWithString:@"FED8"]] forService:service]; + [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"0783B03E-8535-B5A0-7140-A304D2495CB8"]] forService:service]; } } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { +// for (CBCharacteristic *characteristic in service.characteristics){ +// if ([characteristic.UUID.UUIDString isEqualToString:@"FED7"]) { +// self.writeCha = characteristic; +// //找到写入的uuid后,调用sdk配置方法 +//// [AliIot.shareInstance configSDK]; +// } +// if ([characteristic.UUID.UUIDString isEqualToString:@"FED8"]) { +// self.notifyCha = characteristic; +// [peripheral setNotifyValue:YES forCharacteristic:characteristic]; +// } +// } for (CBCharacteristic *characteristic in service.characteristics){ - if ([characteristic.UUID.UUIDString isEqualToString:@"FED7"]) { - self.writeCha = characteristic; - //找到写入的uuid后,调用sdk配置方法 -// [AliIot.shareInstance configSDK]; - } - if ([characteristic.UUID.UUIDString isEqualToString:@"FED8"]) { +// if ([characteristic.UUID.UUIDString isEqualToString:@"FED7"]) { +// self.writeCha = characteristic; +// //找到写入的uuid后,调用sdk配置方法 +//// [AliIot.shareInstance configSDK]; +// } + if ([characteristic.UUID.UUIDString isEqualToString:@"0783B03E-8535-B5A0-7140-A304D2495CB8"]) { self.notifyCha = characteristic; [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } @@ -120,13 +134,13 @@ } - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { - NSLog(@"[receive] %@",characteristic.value); - //收到蓝牙设备发送过来的数据,转发给sdk处理 -// [AliIot.shareInstance handleReceivedData:characteristic.value]; + [self receiveDataFromBle:characteristic.value]; } -#pragma mark - AliIotSDKCallbackProtocol - +#pragma mark - AiIotDelegate +- (void)aiIotSendToBle:(NSData *)data{ + [self sendToBle:data]; +} #pragma mark - public - (void)startScanDevice{ @@ -157,5 +171,8 @@ [self.connectPeripheral writeValue:data forCharacteristic:self.writeCha type:CBCharacteristicWriteWithoutResponse]; } - +- (void)receiveDataFromBle:(NSData *)data{ + NSLog(@"[receive] %@",data); + [[AiIot shared] sendToSdk:data]; +} @end diff --git a/MouseSdk/MouseSdk/PCMPlayer.h b/MouseSdk/MouseSdk/PCMPlayer.h new file mode 100644 index 0000000..e21d29e --- /dev/null +++ b/MouseSdk/MouseSdk/PCMPlayer.h @@ -0,0 +1,76 @@ +//// +//// AiIotPlayer.h +//// MouseSdk +//// +//// Created by incar on 2024/2/28. +//// +// +//// .h 文件 +//#import +//#import +// +//NS_ASSUME_NONNULL_BEGIN +// +//@protocol PCMPlayerDelegate +// +///// 准备好了,可以开始播放了,回调 +//- (void)readlyToPlay; +// +///// 播放完成回调 +//- (void)playFinished; +// +///// 播放暂停回调 +//- (void)playPausedIfNeed; +// +///// 播放开始回调 +//- (void)playResumeIfNeed; +// +/////更新buffer的位置回调 +//- (void)updateBufferPositon:(float)bufferPosition; +// +///// 播放错误的回调 +//- (void)playerCallBackFaiure:(NSString *)errorStr; +// +// +//@end +// +//@interface PCMPlayer : NSObject +// +///// 当前的播放进度 +//@property(nonatomic,assign)NSInteger currentPlayPosition; +// +///// 音频长度 +//@property(nonatomic,assign)NSInteger audioLength; +// +//@property(nonatomic,weak)id delegate; +///// 当前的播放状态 +//@property(nonatomic,assign,getter=isPlayerPlaying)BOOL playerPlaying; +// +///// 是否准备好开始播放 +//@property(nonatomic,assign,getter=isReadyToPlay)BOOL readyToPlay; +// +///// 是否缓存完成 +//@property(nonatomic,assign,getter=isFinished)BOOL finished; +// +///// 初始化sdk +///// @param audioType 传入audioType +//- (instancetype)initWithType:(NSString *)audioType; +// +///// 开始播放 +//- (void)startPlay; +///// 暂停播放 +//- (void)pausePlay; +//// 恢复播放 +//- (void)resumePlay; +///// 停止播放 +//- (void)stopPlay; +// +/////回调当次buffer的数据 +///// @param data 当次buffer获取到的数据 +///// @param length 数据的总长度 +//- (void)appendData:(NSData *)data totalDatalength:(float)length endFlag:(BOOL)endflag; +// +// +//@end +// +//NS_ASSUME_NONNULL_END diff --git a/MouseSdk/MouseSdk/PCMPlayer.m b/MouseSdk/MouseSdk/PCMPlayer.m new file mode 100644 index 0000000..e923c1b --- /dev/null +++ b/MouseSdk/MouseSdk/PCMPlayer.m @@ -0,0 +1,354 @@ +//// +//// AiIotPlayer.m +//// MouseSdk +//// +//// Created by incar on 2024/2/28. +//// +// +//// +//// +// +//#import "PCMPlayer.h" +//#import +// +//#define QUEUE_BUFFER_SIZE 3 //缓冲器个数 +//#define SAMPLE_RATE_16K 16000 //采样频率 +//#define SAMPLE_RATE_8K 8000 //采样频率 +// +//@interface PCMPlayer() { +// AudioQueueRef audioQueue; //音频播放队列 +// AudioStreamBasicDescription _audioDescription; +// AudioQueueBufferRef audioQueueBuffers[QUEUE_BUFFER_SIZE]; //音频缓存 +// BOOL audioQueueBufferUsed[QUEUE_BUFFER_SIZE]; //判断音频缓存是否在使用 +// NSLock *sysnLock; +// OSStatus osState; +// unsigned int temPaket; //切割的数据包的大小 +//} +// +///// 播放数据源 +//@property(nonatomic,strong,nullable)NSMutableArray * dataArray; +///// 播放进度单位为s +//@property(nonatomic,assign)NSInteger playPosition; +///// 播放的过程中因为数据不足而暂停 +//@property(nonatomic,assign,getter=isPausePlayIfNeed)BOOL pausePlayIfNeed; +// +//@end +//@implementation PCMPlayer +// +//- (instancetype)initWithType:(NSString *)audioType { +// if (self = [super init]) { +// sysnLock = [[NSLock alloc]init]; +// //设置音频参数 具体的信息需要问后台 +// if ([audioType isEqualToString:@"8k"]) { +// _audioDescription.mSampleRate = SAMPLE_RATE_8K; +// temPaket = 1600; +// }else { +// _audioDescription.mSampleRate = SAMPLE_RATE_16K; +// temPaket = 3200; +// } +// _audioDescription.mFormatID = kAudioFormatLinearPCM; +// // 下面这个是保存音频数据的方式的说明,如可以根据大端字节序或小端字节序,浮点数或整数以及不同体位去保存数据 +// _audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; +// //1单声道 2双声道 +// _audioDescription.mChannelsPerFrame = 1; +// //每一个packet一侦数据,每个数据包下的桢数,即每个数据包里面有多少桢 +// _audioDescription.mFramesPerPacket = 1; +// //每个采样点16bit量化 语音每采样点占用位数 +// _audioDescription.mBitsPerChannel = 16; +// _audioDescription.mBytesPerFrame = (_audioDescription.mBitsPerChannel / 8) * _audioDescription.mChannelsPerFrame; +// //每个数据包的bytes总数,每桢的bytes数*每个数据包的桢数 +// _audioDescription.mBytesPerPacket = _audioDescription.mBytesPerFrame * _audioDescription.mFramesPerPacket; +// // 使用player的内部线程播放 新建输出 +// AudioQueueNewOutput(&_audioDescription, AudioPlayerAQInputCallback, (__bridge void * _Nullable)(self), nil, 0, 0, &audioQueue); +// +// AVAudioSession *session = [AVAudioSession sharedInstance]; +//// [session setActive:YES error:nil]; +//// [session setCategory:AVAudioSessionCategoryPlayback error:nil]; +// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(AVAudioSessionInterruptionNotification:) name:AVAudioSessionInterruptionNotification object:session]; +// +// // 设置音量 +// AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1.0); +// // 初始化需要的缓冲区 +// [self initPlayBuffer]; +// _playPosition = 0; +// _playerPlaying = NO; +// _readyToPlay = NO; +// _pausePlayIfNeed = NO; +// } +// return self; +//} +// +//// MARK: 播放逻辑控制 +// +//- (void)initPlayBuffer { +// for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { +// audioQueueBufferUsed[i] = false; +// osState = AudioQueueAllocateBuffer(audioQueue, temPaket, &audioQueueBuffers[i]); +// } +//} +// +//- (void)startPlay { +// [self startPlayNeedCallBack:YES]; +//} +//- (void)pausePlay { +// [self pausePlayNeedCallBack:YES]; +//} +// +//- (void)resumePlay { +// [self resumePlayNeedCallBack:YES]; +//} +// +//- (void)stopPlay { +// osState = AudioQueueStop(audioQueue, YES); +// if (osState != noErr) { +// [self callBackPlayerFailureMessage:@"AudioQueueStop Error"]; +// return ; +// } +// self.playerPlaying = NO; +// _readyToPlay = NO; +// [self callBackIsPlaying:self.isPlayerPlaying]; +//} +// +//- (void)startPlayNeedCallBack:(BOOL)needCallBack { +// osState = AudioQueueStart(audioQueue, NULL); +// if (osState != noErr) { +// [self callBackPlayerFailureMessage:@"AudioQueueStart Error"]; +// return; +// } +// self.playerPlaying = YES; +// if (needCallBack) { +// [self callBackIsPlaying:self.isPlayerPlaying]; +// } +//} +// +//- (void)pausePlayNeedCallBack:(BOOL)needCallBack { +// osState = AudioQueuePause(audioQueue); +// if (osState != noErr) { +// [self callBackPlayerFailureMessage:@"AudioQueuePause Error"]; +// return ; +// } +// self.playerPlaying = NO; +// if (needCallBack) { +// [self callBackIsPlaying:self.isPlayerPlaying]; +// } +//} +// +//- (void)resumePlayNeedCallBack:(BOOL)needCallBack { +// osState = AudioQueueStart(audioQueue, NULL); +// if (osState != noErr) { +// [self callBackPlayerFailureMessage:@"AudioQueueStart (resume) Error"]; +// return ; +// } +// self.playerPlaying = YES; +// if (needCallBack) { +// [self callBackIsPlaying:self.isPlayerPlaying]; +// } +//} +// +//- (void)callBackIsPlaying:(BOOL)isPlaying { +// if (isPlaying) { +// if (self.delegate && [self.delegate respondsToSelector:@selector(playResumeIfNeed)]) { +// [self.delegate playResumeIfNeed]; +// } +// }else { +// if (self.delegate && [self.delegate respondsToSelector:@selector(playPausedIfNeed)]) { +// [self.delegate playPausedIfNeed]; +// } +// } +//} +// +//- (void)appendData:(NSData *)data totalDatalength:(float)length endFlag:(BOOL)endflag { +// +// NSArray *dataArray = [self arrayWithPcmData:data]; +// [self.dataArray addObjectsFromArray:dataArray]; +// +// self.finished = endflag; +// +// // 更新音频数据的总长度 +// if (endflag) { +// self.audioLength = self.dataArray.count *0.1; +// }else { +// self.audioLength = length*0.26; +// } +// +// // 回调音频数据的buffer长度 +// if (self.delegate && [self.delegate respondsToSelector:@selector(updateBufferPositon:)]) { +// if (endflag) { +// [self.delegate updateBufferPositon:1.0]; +// }else { +// float progress = self.dataArray.count *0.1/(length*0.26); +// if (progress >= 1) { +// progress = 1; +// } +// [self.delegate updateBufferPositon:progress]; +// } +// } +// +// // 中断后继续播放 +// if (self.isPausePlayIfNeed) { +// [self startPlayNeedCallBack:NO]; +// self.pausePlayIfNeed = NO; +// } +// +// // 准备播放 +// if (self.dataArray.count > QUEUE_BUFFER_SIZE && self.readyToPlay == NO) { +// self.readyToPlay = YES; +// [self enqueueTheBuffer]; +// if (self.delegate && [self.delegate respondsToSelector:@selector(readlyToPlay)]) { +// [self.delegate readlyToPlay]; +// } +// } +// +//} +//// 把数据按照指定的长度切割成指定的长度 +//- (NSArray *)arrayWithPcmData:(NSData *)data { +// NSMutableArray *tempDataArray = [NSMutableArray array]; +// NSInteger count= data.length/temPaket + 1; +// for (int i = 0; i < count; i++) { +// NSData *subData ; +// if (i ==count-1) { +// subData =[data subdataWithRange:NSMakeRange(i*temPaket, data.length-i*temPaket)]; +// }else { +// subData = [data subdataWithRange:NSMakeRange(i*temPaket, temPaket)]; +// } +// // mark: 如果切割的数据为空,不要添加到buffer中来 +// if (subData.length<=0) { +// continue; +// } +// [tempDataArray addObject:subData]; +// } +// return tempDataArray; +//} +// +//- (void)enqueueTheBuffer { +// for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { +// if (!audioQueueBufferUsed[i]) { +// [self dataEnqueTheAudioBufferIndex:i]; +// } +// } +//} +// +//- (void)dataEnqueTheAudioBufferIndex:(NSInteger)bufferIndex { +// [sysnLock lock]; +// audioQueueBufferUsed[bufferIndex] = false; +// NSData * tempData; +// if(self.dataArray.count <= _playPosition) { +// Byte *bytes = (Byte*)malloc(temPaket); +// tempData = [NSData dataWithBytes:bytes length:temPaket]; +// }else { +// tempData = self.dataArray[_playPosition]; +// } +// +// NSUInteger len = tempData.length; +// Byte *bytes = (Byte*)malloc(len); +// [tempData getBytes:bytes length:len]; +// audioQueueBuffers[bufferIndex] -> mAudioDataByteSize = (unsigned int)len; +// // 把bytes的头地址开始的len字节给mAudioData +// memcpy(audioQueueBuffers[bufferIndex] -> mAudioData, bytes, len); +// if (bytes) { +// free(bytes); +// } +// _playPosition++; +// audioQueueBufferUsed[bufferIndex] = true; +// AudioQueueEnqueueBuffer(audioQueue, audioQueueBuffers[bufferIndex], 0, NULL); +// [sysnLock unlock]; +//} +//// ************************** 回调 ********************************** +// +//// 回调回来把buffer状态设为未使用 +//static void AudioPlayerAQInputCallback(void* inUserData,AudioQueueRef audioQueueRef, AudioQueueBufferRef audioQueueBufferRef) { +// +// PCMPlayer* player = (__bridge PCMPlayer*)inUserData; +// +// [player resetBufferState:audioQueueRef and:audioQueueBufferRef]; +//} +// +//- (void)resetBufferState:(AudioQueueRef)audioQueueRef and:(AudioQueueBufferRef)audioQueueBufferRef { +// // 当数据超过播放长度时回调 +// if (self.dataArray.count == _playPosition) { +// if (self.isFinished) { +// self.pausePlayIfNeed = NO; +// [self callBackPlayStatePauseOrResume]; +// }else { +// self.pausePlayIfNeed = YES; +// } +// [self pausePlayNeedCallBack:NO]; +// } +// // 将这个buffer设为未使用 +// for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { +// if (audioQueueBufferRef == audioQueueBuffers[i]) { +// // 追加buffer数据 +// [self dataEnqueTheAudioBufferIndex:i]; +// +// } +// } +// +// +//} +// +//- (void)callBackPlayStatePauseOrResume { +// // 播放长度不够的控制 +// dispatch_async(dispatch_get_main_queue(), ^{ +// if (self.isFinished) { +// if (self.delegate && [self.delegate respondsToSelector:@selector(playFinished)]) { +// [self.delegate playFinished]; +// } +// }else { +// if (self.delegate && [self.delegate respondsToSelector:@selector(playPausedIfNeed)]) { +// [self.delegate playPausedIfNeed]; +// } +// } +// }); +//} +// +// +//// ************************** 内存回收 ********************************** +// +//- (void)dealloc { +// +// if (audioQueue != nil) { +// AudioQueueStop(audioQueue,true); +// } +// +// audioQueue = nil; +// sysnLock = nil; +//} +////MARK:----接收通知方法---------- +//- (void)AVAudioSessionInterruptionNotification: (NSNotification *)notificaiton { +//// NSLog(@"%@", notificaiton.userInfo); +// +// AVAudioSessionInterruptionType type = [notificaiton.userInfo[AVAudioSessionInterruptionTypeKey] intValue]; +// +// static BOOL isLastPlayStatePlaying = NO; +// if (type == AVAudioSessionInterruptionTypeBegan) { +// if (self.isPlayerPlaying) { +// isLastPlayStatePlaying = YES; +// }else { +// isLastPlayStatePlaying = NO; +// } +// +// }else if (type == AVAudioSessionInterruptionTypeEnded && isLastPlayStatePlaying){ +// [self startPlayNeedCallBack:NO]; +// } +//} +//- (void)callBackPlayerFailureMessage:(NSString *)message { +// if (self.delegate && [self.delegate respondsToSelector:@selector(playerCallBackFaiure:)]) { +// [self.delegate playerCallBackFaiure:message]; +// } +//} +// +//// MARK: - custom Accessor - +// +//- (NSInteger)currentPlayPosition { +// return self.playPosition/10; +//} +// +//- (NSMutableArray *)dataArray { +// if (!_dataArray) { +// _dataArray = [NSMutableArray array]; +// } +// return _dataArray; +//} +// +//@end +// diff --git a/MouseSdk/MouseSdk/ScanVC.m b/MouseSdk/MouseSdk/ScanVC.m index 5e65855..4b383ef 100644 --- a/MouseSdk/MouseSdk/ScanVC.m +++ b/MouseSdk/MouseSdk/ScanVC.m @@ -71,7 +71,7 @@ - (void)setupBle{ BleManager *manager = [BleManager shared]; __weak typeof(self) weakSelf= self; -// __weak typeof(BleManager) *weakManager = manager; + __weak typeof(BleManager) *weakManager = manager; manager.discoverDevice = ^(CBPeripheral *peripheral,NSDictionary *advertisementData){ if ([weakSelf.scanArray containsObject:peripheral]){ return; @@ -90,6 +90,7 @@ }; manager.didConnectDevice = ^(CBPeripheral * _Nonnull peripheral) { NSLog(@"连接成功"); + [weakManager stopScanDevice]; [weakSelf dismissViewController:weakSelf]; }; [manager startScanDevice]; diff --git a/MouseSdk/MouseSdk/ViewController.m b/MouseSdk/MouseSdk/ViewController.m index 0fa5639..8fc77de 100644 --- a/MouseSdk/MouseSdk/ViewController.m +++ b/MouseSdk/MouseSdk/ViewController.m @@ -10,7 +10,7 @@ #import "AliIotTools.h" #import "Ble/BleManager.h" #import "Ble/BleTools.h" -#import + @interface ViewController () @@ -102,7 +102,7 @@ } - (void)checkFGSStatus{ - [[AiIot shared] startLogin]; +// [[AiIot shared] startLogin]; } - (void)connectLp{