18F323842B8F330100CABA2E /* AiAuthManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F323822B8F330100CABA2E /* AiAuthManager.h */; };
18F323852B8F330100CABA2E /* AiAuthManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F323832B8F330100CABA2E /* AiAuthManager.m */; };
18F323872B8F338300CABA2E /* AliIotConnectKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F3237D2B8F2EFC00CABA2E /* AliIotConnectKit.framework */; };
- 18F3238A2B8F4DBE00CABA2E /* PCMPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */; };
18F3238E2B8F4F7300CABA2E /* AiAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F3238C2B8F4F7300CABA2E /* AiAudioManager.h */; };
18F3238F2B8F4F7300CABA2E /* AiAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F3238D2B8F4F7300CABA2E /* AiAudioManager.m */; };
18F323952B8F525C00CABA2E /* AiTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F323932B8F525C00CABA2E /* AiTools.h */; settings = {ATTRIBUTES = (Public, ); }; };
18F323782B8F2EFB00CABA2E /* AliIotConnectKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AliIotConnectKit.xcodeproj; path = AliIotConnectKitSDK/AliIotConnectKit.xcodeproj; sourceTree = "<group>"; };
18F323822B8F330100CABA2E /* AiAuthManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiAuthManager.h; sourceTree = "<group>"; };
18F323832B8F330100CABA2E /* AiAuthManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiAuthManager.m; sourceTree = "<group>"; };
- 18F323882B8F4DBE00CABA2E /* PCMPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PCMPlayer.h; sourceTree = "<group>"; };
- 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PCMPlayer.m; sourceTree = "<group>"; };
18F3238C2B8F4F7300CABA2E /* AiAudioManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiAudioManager.h; sourceTree = "<group>"; };
18F3238D2B8F4F7300CABA2E /* AiAudioManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiAudioManager.m; sourceTree = "<group>"; };
18F323932B8F525C00CABA2E /* AiTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiTools.h; sourceTree = "<group>"; };
18BF1DCC2B81AB7C00B8D90F /* MouseSdk */ = {
isa = PBXGroup;
children = (
- 18BF1E1F2B83064D00B8D90F /* Ble */,
+ 18BF1E202B83066200B8D90F /* BleManager.h */,
+ 18BF1E212B83066200B8D90F /* BleManager.m */,
18BF1DCD2B81AB7C00B8D90F /* AppDelegate.h */,
18BF1DCE2B81AB7C00B8D90F /* AppDelegate.m */,
18BF1DD02B81AB7C00B8D90F /* ViewController.h */,
18BF1E752B832D2E00B8D90F /* ScanVC.m */,
18F3235B2B8ED78300CABA2E /* ScanCell.h */,
18F3235C2B8ED78300CABA2E /* ScanCell.m */,
- 18F323882B8F4DBE00CABA2E /* PCMPlayer.h */,
- 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */,
18F328D32B98569D00CABA2E /* Config.h */,
18F328D42B98569D00CABA2E /* Config.m */,
18BF1E042B81E18800B8D90F /* ConnectKitVC.swift */,
path = MouseSdkUITests;
sourceTree = "<group>";
};
- 18BF1E1F2B83064D00B8D90F /* Ble */ = {
- isa = PBXGroup;
- children = (
- 18BF1E202B83066200B8D90F /* BleManager.h */,
- 18BF1E212B83066200B8D90F /* BleManager.m */,
- );
- path = Ble;
- sourceTree = "<group>";
- };
18BF1E882B8362D300B8D90F /* AiMouseSdk */ = {
isa = PBXGroup;
children = (
18BF1E762B832D2E00B8D90F /* ScanVC.m in Sources */,
18BF1E222B83066200B8D90F /* BleManager.m in Sources */,
18BF1DCF2B81AB7C00B8D90F /* AppDelegate.m in Sources */,
- 18F3238A2B8F4DBE00CABA2E /* PCMPlayer.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#import <AiMouseSdk/AiMouseSdk.h>
#import "Config.h"
-//鉴权特征
+
+//ai特征
#define kAiUUID @"0783B03E-8535-B5A0-7140-A304D2194CB8"
-//Ai特征
+//鉴权特征
+//#define kAuthUUID @"0783B73E-8535-B5A0-7140-A304D2194CB7"
#define kAuthUUID @"0783B03E-8535-B5A0-7140-A304D2194CB7"
+
+
@interface BleManager ()<CBCentralManagerDelegate,CBPeripheralDelegate,AiMouseDelegate>
@property (nonatomic,strong) NSMutableArray *scanArray;
@property(nonatomic, strong) CBCentralManager *centralManager;
@property(nonatomic, strong) CBPeripheral *connectPeripheral;
@property(nonatomic, strong) CBCharacteristic *authCha;
-
+@property(nonatomic, strong) CBCharacteristic *aiCha;
@property (nonatomic,strong)NSMutableData *recordData;
@end
self.authCha = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
- if ([characteristic.UUID.UUIDString isEqualToString:kAuthUUID] ||
- [characteristic.UUID.UUIDString isEqualToString:kAiUUID]
- ) {
+ else if ([characteristic.UUID.UUIDString isEqualToString:kAiUUID]) {
+ self.aiCha = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
NSData *data = characteristic.value;
-// [self showLog:[NSString stringWithFormat:@"[receive] %@",data]];
[self showLog:[NSString stringWithFormat:@"[receive] %@",[AiTools dataToHexString:data]]];
if([characteristic.UUID.UUIDString isEqualToString:kAuthUUID]){
+ //鉴权数据
[[AiMouse shared] sendAuthDataToSdk:data];
}
else if([characteristic.UUID.UUIDString isEqualToString:kAiUUID]){
+ //AI数据
[[AiMouse shared] sendAiDataToSdk:data];
}
}
}
#pragma mark - public
+/// 连接设备
- (void)startScanDevice{
[self.scanArray removeAllObjects];
[self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO]}];
}
+/// 扫描设备
- (void)stopScanDevice{
[self.centralManager stopScan];
}
+/// 连接设备
- (void)connectPeripheral:(CBPeripheral *)peripheral{
[self.centralManager connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey : [NSNumber numberWithBool:YES]}];
}
+/// 开始鉴权
- (void)startAuth{
[[AiMouse shared] startAuthentication];
}
- (void)finishRecored:(NSData *)data{
NSString *doc = NSTemporaryDirectory();
- NSString *fullPath = [NSString stringWithFormat:@"%@2.pcm",doc];
- [self showLog:[NSString stringWithFormat:@"%@",fullPath]];
+ NSString *fullPath = [NSString stringWithFormat:@"%@.pcm",doc];
NSError *err;
[data writeToFile:fullPath options:NSDataWritingAtomic error:&err];
if (err) {
- [self showLog:[NSString stringWithFormat:@"录音保存失败%@",err.description]];
+ [self showLog:[NSString stringWithFormat:@"录音保存失败 %@",err.description]];
}
else{
- [self showLog:@"录音保存成功"];
+ [self showLog:[NSString stringWithFormat:@"录音保存成功 path = %@",fullPath]];
}
}
@end
+++ /dev/null
-////
-//// AiPlayer.m
-//// MouseSdk
-////
-//// Created by incar on 2024/2/28.
-////
-//
-////
-////
-//
-//#import "PCMPlayer.h"
-//#import <AVFoundation/AVFoundation.h>
-//
-//#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
-//