/// 发送给蓝牙设备
/// - Parameter data: 传输的数据
-- (void)sendToBle:(NSData *)data;
+- (void)aiIotSendToBle:(NSData *)data;
@end
@interface AiIot : NSObject
@property (nonatomic, weak) id<AiIotDelegate> delegate;
-+(id)shared;
++(AiIot *)shared;
- (void)startLogin;
-
/// 将数据传输给sdk处理
/// - Parameter data: 传输的数据
- (void)sendToSdk:(NSData *)data;
#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, ^{
}
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
--- /dev/null
+//
+// AiIotAudioManager.h
+// AiSdk
+//
+// Created by incar on 2024/2/28.
+//
+
+#import <Foundation/Foundation.h>
+
+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
--- /dev/null
+//
+// 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
- (void)login;
-- (void)sendToConnectKit:(NSData *)data;
+- (void)receiveData:(NSData *)data;
@end
NS_ASSUME_NONNULL_END
}
#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, ^{
--- /dev/null
+//
+// AiIotTools.h
+// AiSdk
+//
+// Created by incar on 2024/2/28.
+//
+
+#import <Foundation/Foundation.h>
+
+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
--- /dev/null
+//
+// 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
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 */
18F323782B8F2EFB00CABA2E /* AliIotConnectKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AliIotConnectKit.xcodeproj; path = AliIotConnectKitSDK/AliIotConnectKit.xcodeproj; sourceTree = "<group>"; };
18F323822B8F330100CABA2E /* AiIotConnectManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotConnectManager.h; sourceTree = "<group>"; };
18F323832B8F330100CABA2E /* AiIotConnectManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotConnectManager.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 /* AiIotAudioManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotAudioManager.h; sourceTree = "<group>"; };
+ 18F3238D2B8F4F7300CABA2E /* AiIotAudioManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotAudioManager.m; sourceTree = "<group>"; };
+ 18F323932B8F525C00CABA2E /* AiIotTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiIotTools.h; sourceTree = "<group>"; };
+ 18F323942B8F525C00CABA2E /* AiIotTools.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiIotTools.m; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
/* End PBXFileReference section */
18F323612B8F13D600CABA2E /* LogVC.m */,
18F323762B8F2DAD00CABA2E /* AliIotTools.h */,
18F323752B8F2DAC00CABA2E /* AliIotTools.m */,
+ 18F323882B8F4DBE00CABA2E /* PCMPlayer.h */,
+ 18F323892B8F4DBE00CABA2E /* PCMPlayer.m */,
18BF1E042B81E18800B8D90F /* ConnectKitVC.swift */,
18BF1DD32B81AB7F00B8D90F /* Assets.xcassets */,
18BF1DD52B81AB7F00B8D90F /* Main.storyboard */,
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 */,
);
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;
};
18BF1E762B832D2E00B8D90F /* ScanVC.m in Sources */,
18BF1E222B83066200B8D90F /* BleManager.m in Sources */,
18BF1DCF2B81AB7C00B8D90F /* AppDelegate.m in Sources */,
+ 18F3238A2B8F4DBE00CABA2E /* PCMPlayer.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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;
<key>AiSdk.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
- <integer>3</integer>
+ <integer>2</integer>
</dict>
<key>MouseSdk.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
- <integer>2</integer>
+ <integer>3</integer>
</dict>
</dict>
</dict>
#import "BleManager.h"
-
+#import <AiSdk/AiSdk.h>
@interface BleManager ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic,strong) NSMutableArray *scanArray;
@property(nonatomic, strong) CBCentralManager *centralManager;
@property(nonatomic, strong) CBCharacteristic *writeCha;
@property(nonatomic, strong) CBCharacteristic *notifyCha;
-@property(nonatomic, assign) BOOL isSdkInitSuccess;
@end
@implementation BleManager
self = [super init];
if (self) {
self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
+ [AiIot shared].delegate = self;
}
return self;
}
}
#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];
}
}
- (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{
[self.connectPeripheral writeValue:data forCharacteristic:self.writeCha type:CBCharacteristicWriteWithoutResponse];
}
-
+- (void)receiveDataFromBle:(NSData *)data{
+ NSLog(@"[receive] %@",data);
+ [[AiIot shared] sendToSdk:data];
+}
@end
--- /dev/null
+////
+//// AiIotPlayer.h
+//// MouseSdk
+////
+//// Created by incar on 2024/2/28.
+////
+//
+//// .h 文件
+//#import <Foundation/Foundation.h>
+//#import <AudioToolbox/AudioToolbox.h>
+//
+//NS_ASSUME_NONNULL_BEGIN
+//
+//@protocol PCMPlayerDelegate <NSObject>
+//
+///// 准备好了,可以开始播放了,回调
+//- (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 <PCMPlayerDelegate> 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
--- /dev/null
+////
+//// AiIotPlayer.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
+//
- (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;
};
manager.didConnectDevice = ^(CBPeripheral * _Nonnull peripheral) {
NSLog(@"连接成功");
+ [weakManager stopScanDevice];
[weakSelf dismissViewController:weakSelf];
};
[manager startScanDevice];
#import "AliIotTools.h"
#import "Ble/BleManager.h"
#import "Ble/BleTools.h"
-#import <AiSdk/AiSdk.h>
+
@interface ViewController ()
}
- (void)checkFGSStatus{
- [[AiIot shared] startLogin];
+// [[AiIot shared] startLogin];
}
- (void)connectLp{