增加声音解析指令
authorliangzhenying <867174124@qq.com>
Thu, 29 Feb 2024 08:15:54 +0000 (16:15 +0800)
committerliangzhenying <867174124@qq.com>
Thu, 29 Feb 2024 08:15:54 +0000 (16:15 +0800)
21 files changed:
Document/1.pcm [new file with mode: 0644]
Document/Output.pcm [new file with mode: 0644]
Document/abc.pcm [new file with mode: 0644]
Document/scb2.bin [new file with mode: 0644]
Document/截屏2024-02-29 15.33.35.png [new file with mode: 0644]
MouseSdk/AiSdk/AiIot.h
MouseSdk/AiSdk/AiIot.m
MouseSdk/AiSdk/AiIotAudioManager.h [new file with mode: 0644]
MouseSdk/AiSdk/AiIotAudioManager.m [new file with mode: 0644]
MouseSdk/AiSdk/AiIotConnectManager.h
MouseSdk/AiSdk/AiIotConnectManager.m
MouseSdk/AiSdk/AiIotTools.h [new file with mode: 0644]
MouseSdk/AiSdk/AiIotTools.m [new file with mode: 0644]
MouseSdk/MouseSdk.xcodeproj/project.pbxproj
MouseSdk/MouseSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist
MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate
MouseSdk/MouseSdk/Ble/BleManager.m
MouseSdk/MouseSdk/PCMPlayer.h [new file with mode: 0644]
MouseSdk/MouseSdk/PCMPlayer.m [new file with mode: 0644]
MouseSdk/MouseSdk/ScanVC.m
MouseSdk/MouseSdk/ViewController.m

diff --git a/Document/1.pcm b/Document/1.pcm
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
index 0000000..3448625
Binary files /dev/null and b/Document/scb2.bin differ
diff --git a/Document/截屏2024-02-29 15.33.35.png b/Document/截屏2024-02-29 15.33.35.png
new file mode 100644 (file)
index 0000000..65c72ae
Binary files /dev/null and "b/Document/\346\210\252\345\261\2172024-02-29 15.33.35.png" differ
index 3de4ab4..b8c68c7 100644 (file)
@@ -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<AiIotDelegate> delegate;
 
-+(id)shared;
++(AiIot *)shared;
 
 - (void)startLogin;
 
-
 /// 将数据传输给sdk处理
 /// - Parameter data: 传输的数据
 - (void)sendToSdk:(NSData *)data;
index 86739c0..800278f 100644 (file)
@@ -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, ^{
     }
     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 (file)
index 0000000..cf47d6e
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  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
diff --git a/MouseSdk/AiSdk/AiIotAudioManager.m b/MouseSdk/AiSdk/AiIotAudioManager.m
new file mode 100644 (file)
index 0000000..f18e6ca
--- /dev/null
@@ -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
index eb23530..06b7675 100644 (file)
@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (void)login;
 
-- (void)sendToConnectKit:(NSData *)data;
+- (void)receiveData:(NSData *)data;
 @end
 
 NS_ASSUME_NONNULL_END
index c9afcf3..15fe2bc 100644 (file)
@@ -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 (file)
index 0000000..4df1896
--- /dev/null
@@ -0,0 +1,21 @@
+//
+//  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
diff --git a/MouseSdk/AiSdk/AiIotTools.m b/MouseSdk/AiSdk/AiIotTools.m
new file mode 100644 (file)
index 0000000..1f08f72
--- /dev/null
@@ -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
index 0ab32ab..ea1e68d 100644 (file)
                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;
index 6cbfd27..4c533f1 100644 (file)
@@ -7,12 +7,12 @@
                <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>
index 0baa9c9..dee9fce 100644 (file)
Binary files a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate and b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate differ
index 7f8db83..06d10ff 100644 (file)
@@ -8,7 +8,7 @@
 
 
 #import "BleManager.h"
-
+#import <AiSdk/AiSdk.h>
 @interface BleManager ()<CBCentralManagerDelegate,CBPeripheralDelegate>
 @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;
 }
 }
 #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
diff --git a/MouseSdk/MouseSdk/PCMPlayer.h b/MouseSdk/MouseSdk/PCMPlayer.h
new file mode 100644 (file)
index 0000000..e21d29e
--- /dev/null
@@ -0,0 +1,76 @@
+////
+////  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
diff --git a/MouseSdk/MouseSdk/PCMPlayer.m b/MouseSdk/MouseSdk/PCMPlayer.m
new file mode 100644 (file)
index 0000000..e923c1b
--- /dev/null
@@ -0,0 +1,354 @@
+////
+////  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
+//
index 5e65855..4b383ef 100644 (file)
@@ -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];
index 0fa5639..8fc77de 100644 (file)
@@ -10,7 +10,7 @@
 #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{