--- /dev/null
+12:04:56.2000: connected in underlying BLE layer.
+12:05:02.2080: discovered services: (
+ "Device Information",
+ "Human Interface Device",
+ AE00,
+ AE40,
+ Battery,
+ FF00
+)
+12:05:02.3330: discovered characteristics for service 180A: (
+ "Manufacturer Name String",
+ "Model Number String",
+ "Serial Number String",
+ "Hardware Revision String",
+ "Firmware Revision String",
+ "Software Revision String",
+ "System ID",
+ "IEEE Regulatory Certification",
+ "PnP ID"
+)
+12:05:02.4490: discovered characteristics for service 180F: (
+ "Battery Level"
+)
+12:05:02.5110: discovered characteristics for service AE40: (
+ AE41,
+ AE42
+)
+12:05:02.5690: discovered characteristics for service FF00: (
+ FF01,
+ FF02,
+ FF03
+)
+12:05:02.6300: discovered characteristics for service AE00: (
+ AE01,
+ AE02
+)
+12:05:02.6300: state changed to 'Connected'.
+12:05:03.0050: updated subscription state for characteristic 2A19___180F: subscribed
+12:05:03.0340: received update from characteristic 2A19___180F: <3c>
+12:05:03.0640: received update from characteristic 2A25___180A: <5342544a 30313445 31453030 30303030 4136>
+12:05:03.3290: received update from characteristic 2A23___180A: <00000000 00000000>
+12:05:03.4490: received update from characteristic 2A27___180A: <312e302e 30>
+12:05:03.5610: received update from characteristic 2A28___180A: <4d38>
+12:05:03.6340: received update from characteristic 2A29___180A: <4a594420 5368656e 5a68656e>
+12:05:03.6640: received update from characteristic 2A24___180A: <42542d30 574d4f2d 74623732 2d323430 34313830 315458>
\ No newline at end of file
3FCF53502D1A5C97007EC52F /* LogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FCF534D2D1A5C97007EC52F /* LogManager.h */; };
3FCF53512D1A5C97007EC52F /* LogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FCF534D2D1A5C97007EC52F /* LogManager.h */; };
3FCF53522D1A5C97007EC52F /* LogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FCF534E2D1A5C97007EC52F /* LogManager.m */; };
+ 3FF3D7372DAE442C008EBA5D /* M8MouseSdk.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FF3D7352DAE442C008EBA5D /* M8MouseSdk.h */; };
+ 3FF3D7382DAE442C008EBA5D /* M8MouseSdk.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FF3D7362DAE442C008EBA5D /* M8MouseSdk.m */; };
+ 3FF3D7392DAE442C008EBA5D /* M8MouseSdk.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FF3D7352DAE442C008EBA5D /* M8MouseSdk.h */; };
+ 3FF3D73A2DAE442C008EBA5D /* M8MouseSdk.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FF3D7362DAE442C008EBA5D /* M8MouseSdk.m */; };
+ 3FF3D75C2DAFA0BC008EBA5D /* M8MouseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FF3D75B2DAFA0BC008EBA5D /* M8MouseInfo.m */; };
+ 3FF3D75D2DAFA0BC008EBA5D /* M8MouseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FF3D75A2DAFA0BC008EBA5D /* M8MouseInfo.h */; };
+ 3FF3D75E2DAFA0BC008EBA5D /* M8MouseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FF3D75A2DAFA0BC008EBA5D /* M8MouseInfo.h */; };
+ 3FF3D75F2DAFA0BC008EBA5D /* M8MouseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FF3D75B2DAFA0BC008EBA5D /* M8MouseInfo.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3F5CE3E62D1E7BCA00A5628A /* libAiMouseSdk copy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libAiMouseSdk copy.a"; sourceTree = BUILT_PRODUCTS_DIR; };
3FCF534D2D1A5C97007EC52F /* LogManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogManager.h; sourceTree = "<group>"; };
3FCF534E2D1A5C97007EC52F /* LogManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogManager.m; sourceTree = "<group>"; };
+ 3FF3D7352DAE442C008EBA5D /* M8MouseSdk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = M8MouseSdk.h; sourceTree = "<group>"; };
+ 3FF3D7362DAE442C008EBA5D /* M8MouseSdk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = M8MouseSdk.m; sourceTree = "<group>"; };
+ 3FF3D75A2DAFA0BC008EBA5D /* M8MouseInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = M8MouseInfo.h; sourceTree = "<group>"; };
+ 3FF3D75B2DAFA0BC008EBA5D /* M8MouseInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = M8MouseInfo.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
180E7A9D2BD7BB12008558E8 = {
isa = PBXGroup;
children = (
+ 3FF3D7562DAFA058008EBA5D /* M8 */,
18E0C5842D0FF84A0093BA8F /* ByteDance */,
1899600D2CEAD78B0042505F /* Keyboard */,
18D579FF2C91733E003D5714 /* NMouseSdk */,
path = TlwMouseSdk;
sourceTree = "<group>";
};
+ 3FF3D7562DAFA058008EBA5D /* M8 */ = {
+ isa = PBXGroup;
+ children = (
+ 3FF3D7352DAE442C008EBA5D /* M8MouseSdk.h */,
+ 3FF3D7362DAE442C008EBA5D /* M8MouseSdk.m */,
+ 3FF3D75A2DAFA0BC008EBA5D /* M8MouseInfo.h */,
+ 3FF3D75B2DAFA0BC008EBA5D /* M8MouseInfo.m */,
+ );
+ path = M8;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
180E7C982BD8FC4E008558E8 /* rational.h in Headers */,
18EF7B022C7603E800AC5223 /* TlwTools.h in Headers */,
180E7CF82BD8FC4F008558E8 /* codec_id.h in Headers */,
+ 3FF3D75E2DAFA0BC008EBA5D /* M8MouseInfo.h in Headers */,
180E7C9B2BD8FC4E008558E8 /* avconfig.h in Headers */,
180E7CDA2BD8FC4E008558E8 /* avassert.h in Headers */,
180E7CCA2BD8FC4E008558E8 /* channel_layout.h in Headers */,
180E7CDB2BD8FC4E008558E8 /* hash.h in Headers */,
180E7B562BD7BD83008558E8 /* AiMouseConfig.h in Headers */,
180E7CF42BD8FC4F008558E8 /* codec.h in Headers */,
+ 3FF3D7392DAE442C008EBA5D /* M8MouseSdk.h in Headers */,
180E7C8D2BD8FC4E008558E8 /* detection_bbox.h in Headers */,
180E7CEF2BD8FC4F008558E8 /* videotoolbox.h in Headers */,
180E7CFF2BD8FC4F008558E8 /* version.h in Headers */,
18862B452C806BD900D3564D /* version.h in Headers */,
18862B462C806BD900D3564D /* ffversion.h in Headers */,
18862B472C806BD900D3564D /* intreadwrite.h in Headers */,
+ 3FF3D75D2DAFA0BC008EBA5D /* M8MouseInfo.h in Headers */,
18862B482C806BD900D3564D /* AFURLRequestSerialization.h in Headers */,
18862B492C806BD900D3564D /* buffer.h in Headers */,
18862B4A2C806BD900D3564D /* twofish.h in Headers */,
18862B8E2C806BD900D3564D /* AiMouseSdk.h in Headers */,
18862B8F2C806BD900D3564D /* qsv.h in Headers */,
18862B902C806BD900D3564D /* hmac.h in Headers */,
+ 3FF3D7372DAE442C008EBA5D /* M8MouseSdk.h in Headers */,
18862B912C806BD900D3564D /* AFNetworking.h in Headers */,
18862B922C806BD900D3564D /* threadmessage.h in Headers */,
18862B932C806BD900D3564D /* adpcm.h in Headers */,
180E7BE72BD7BD84008558E8 /* AiAudioManager.m in Sources */,
18EF7AFB2C7603E800AC5223 /* TlwTools.m in Sources */,
18EF7AFA2C7603E800AC5223 /* TlwMouseSdk.m in Sources */,
+ 3FF3D73A2DAE442C008EBA5D /* M8MouseSdk.m in Sources */,
18862A282C8064E300D3564D /* BleManager.m in Sources */,
188814C42C85C2BB009299A9 /* AESCBCHelper.m in Sources */,
+ 3FF3D75F2DAFA0BC008EBA5D /* M8MouseInfo.m in Sources */,
180E7BDF2BD7BD84008558E8 /* AiMouseConfig.m in Sources */,
18EF7AFC2C7603E800AC5223 /* AiConnectManager.m in Sources */,
181CE5C22C6EED9900EF8D07 /* AiAliAuthManager.m in Sources */,
188814C52C85C2BB009299A9 /* AESCBCHelper.m in Sources */,
18862BC62C806BD900D3564D /* AiMouseConfig.m in Sources */,
18862BC72C806BD900D3564D /* AiConnectManager.m in Sources */,
+ 3FF3D7382DAE442C008EBA5D /* M8MouseSdk.m in Sources */,
18862BC82C806BD900D3564D /* AiAliAuthManager.m in Sources */,
18862BC92C806BD900D3564D /* AFSecurityPolicy.m in Sources */,
+ 3FF3D75C2DAFA0BC008EBA5D /* M8MouseInfo.m in Sources */,
18862BCA2C806BD900D3564D /* DeviceManger.m in Sources */,
18862BCB2C806BD900D3564D /* AiAudioDecoder.m in Sources */,
18862BCC2C806BD900D3564D /* AiDeviceInfoManager.m in Sources */,
<key>AiMouseSdk copy.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
- <integer>4</integer>
+ <integer>2</integer>
</dict>
<key>AiMouseSdk.xcscheme_^#shared#^_</key>
<dict>
--- /dev/null
+//
+// M8MouseInfo.h
+// AiMouseSdk
+//
+// Created by liangshi on 2025/4/16.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface M8MouseInfo : NSObject
+@property (nonatomic, strong) NSString *battery_power;/// 电池百分百电量,0-100
+@property (nonatomic, strong) NSString *version;///软件版本
+@property (nonatomic, strong) NSString *brand;/// 品牌名称
+@property (nonatomic, strong) NSString *sn;/// 设备序列号
+///
++(M8MouseInfo *)shared;
+@end
--- /dev/null
+//
+// M8MouseInfo.m
+// AiMouseSdk
+//
+// Created by liangshi on 2025/4/16.
+//
+
+#import "M8MouseInfo.h"
+
+@implementation M8MouseInfo
+
++(M8MouseInfo *)shared{
+ static M8MouseInfo *manager = nil;
+ static dispatch_once_t oncePredicate;
+ dispatch_once(&oncePredicate, ^{
+ manager = [[M8MouseInfo alloc]init];
+ });
+ return manager;
+}
+
+- (instancetype)init{
+ self = [super init];
+ if (self) {
+
+ }
+ return self;
+}
+@end
--- /dev/null
+//
+// M8MouseSdk.h
+// AiMouseSdk
+//
+// Created by liangshi on 2025/4/15.
+//
+
+#import <Foundation/Foundation.h>
+#import "AiMouseSdk.h"
+@protocol M8MouseSdkDelegate <NSObject>
+
+/// 设备连接状态
+/// - Parameter connected: 是否连接
+- (void)m8MouseConnectStateDidChange:(BOOL)connected;
+
+
+/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
+/// - Parameter data: 数据
+- (void)m8MouseSendDeviceInfoData:(NSData *)data;
+
+/// 鼠标按键指令回调
+/// - Parameter data: 数据。
+//EF AA 0B 00 02 E1 00 E3 语音键单击开始
+//EF AA 0C 00 02 E1 00 E3 语音键单击结束
+//EF AA 05 00 02 E1 00 E3 语音键长按
+//EF AA 06 00 02 E1 00 E3 语音键长按松开
+//
+//
+//EF AA 09 00 02 E1 00 E3 M键单击
+//EF AA 01 00 02 E1 00 E3 M键长按松开
+//EF AA 02 00 02 E1 00 E3 M键长按松开
+//
+//EF AA 0A 00 02 E1 00 E3 AI键单击
+//EF AA 03 00 02 E1 00 E3 AI键长按松开
+//EF AA 04 00 02 E1 00 E3 AI键长按松开
+//
+//EF AA 0D 00 02 E1 00 E3 翻译键单击开始
+//EF AA 0E 00 02 E1 00 E3 翻译键单击结束
+//EF AA 07 00 02 E1 00 E3 翻译键长按
+//EF AA 08 00 02 E1 00 E3 翻译键长按松开
+/// 其他未定义
+- (void)m8MouseSendCmdData:(NSData *)data;
+
+/// 录音回调
+/// - Parameter data: pcm格式语音数据
+- (void)m8MouseSendRecordData:(NSData *)data;
+
+/// hid数据异常,需要重新开启监听usb设备
+- (void)m8HidDataError;
+
+/// 输出sdk日志
+/// - Parameter log: 日志
+- (void)m8MouseAddLog:(NSString *)log;
+
+@end
+
+@interface M8MouseSdk : NSObject
+@property (nonatomic, weak) id<M8MouseSdkDelegate> delegate;/// 代理
+@property (nonatomic, readonly) AiMouseConnectType connectType;//连接类型
+@property (nonatomic, readonly) BOOL connected;//是否已连接
+
+/// 断开连接
+- (void)didDisconnect;
+
+/// 切换连接类型
+/// - Parameter type: 连接类型
+- (void)switchConnect:(AiMouseConnectType)type isConnected:(BOOL)isConneted;
+
+/// 传输业务数据给sdk
+/// - Parameter data:ai特征传过来的数据
+- (void)sendAiDataToSdk:(NSData *)data;
+
+/// 传输设备信息数据给sdk
+/// - Parameter data:设备信息特征传过来的数据
+- (void)sendDeviceDataToSdk:(NSData *)data;
+
+/// 获取设备信息
+/// - Parameter completation: 如果获取成功,则deviceInfo有值,否则为nil
+- (void)getFullDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))finished;
+
+@end
--- /dev/null
+//
+// M8MouseSdk.m
+// AiMouseSdk
+//
+// Created by liangshi on 2025/4/15.
+//
+
+#import "M8MouseSdk.h"
+#import "TlwAudioManager.h"
+#import "TlwTools.h"
+#import "AiRecordManager.h"
+#import "M8MouseInfo.h"
+@interface M8MouseSdk()
+
+@property (nonatomic, strong) TlwAudioManager *audioManager;
+@property (nonatomic, strong) AiRecordManager *recordManager;
+
+@property (nonatomic,strong)void (^dongleStateCallBack)(BOOL success);
+@property (nonatomic,assign)NSInteger dongleTimes;
+
+@property (nonatomic,strong)AiMouseDeviceInfo *fullInfo;
+@property (nonatomic,assign)NSInteger questTimes;
+@end
+
+@implementation M8MouseSdk
+
+-(instancetype)init{
+ if (self = [super init]) {
+ _connectType = AiMouseConnectType_bluetooth;
+ // NSLog(@"[TlwMouseSdk]%@",[NSString stringWithFormat:@"AiMouseSdk_v%@",self.version]);
+ [self.recordManager checkPermissions];
+ }
+ return self;
+}
+
+-(NSString *)version{
+ return @"1.0.2";
+}
+
+-(TlwAudioManager *)audioManager{
+ if (!_audioManager) {
+ _audioManager = [[TlwAudioManager alloc] init];
+ __weak typeof(self) ws = self;
+ _audioManager.decodeCallBack = ^(NSData * _Nonnull data) {
+ [ws sendRecordData:data];
+ };
+ _audioManager.outputLog = ^(NSString * _Nonnull log) {
+ [ws showLog:log];
+ };
+ }
+ return _audioManager;
+}
+
+- (AiRecordManager *)recordManager{
+ if (!_recordManager) {
+ _recordManager = [[AiRecordManager alloc] init];
+ __weak typeof(self) ws = self;
+ _recordManager.didRecordData = ^(NSData * _Nonnull data) {
+ [ws showLog:[NSString stringWithFormat:@"%@",data]];
+ [ws sendRecordData:data];
+ };
+ }
+ return _recordManager;
+}
+- (void)sendOpenCmd{
+ uint8_t cmd = 0x0D;
+ uint8_t len = 0x00;
+ uint8_t tail = 0xEF;
+ NSMutableData *mData = NSMutableData.data;
+ [mData appendData:[self getHidHeader]];
+ [mData appendBytes:&cmd length:1];
+ [mData appendBytes:&len length:1];
+ [mData appendBytes:&tail length:1];
+ [self sendToDevice:mData];
+}
+
+#pragma mark - pub Api
+- (void)didDisconnect{
+ _connected = false;
+ [self stopRecord];
+}
+
+- (void)switchConnect:(AiMouseConnectType)type isConnected:(BOOL)isConneted{
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+ if(isConneted ){
+ _connected = true;
+ _connectType = type;
+ [self showLog:type == AiMouseConnectType_bluetooth?@"sdk切换到蓝牙模式":@"sdk切换到usb模式"];
+
+// if (type == AiMouseConnectType_hid ) {
+// [self.recordManager checkPermissions];
+// // [self sendOpenCmd];
+// [self checkDongleState];
+// }
+// else{
+ [self TlwConnectManager:nil connectStateDidChange:true];
+// }
+ }
+ else{
+ [self stopRecord];
+ if (self.connected) {
+ _connected = false;
+ [self TlwConnectManager:nil connectStateDidChange:false];
+ }
+ }
+}
+
+- (void)sendAiDataToSdk:(NSData *)data{
+ [self showLog:[NSString stringWithFormat:@"[receive][Voice] %@",data]];
+ if(self.connectType == AiMouseConnectType_hid){
+ }
+ else if (self.connectType == AiMouseConnectType_bluetooth){
+ [self bleReceiveAiData:data];
+ }
+}
+
+-(void)sendDeviceDataToSdk:(NSData *)data{
+ if(self.connectType == AiMouseConnectType_hid){
+ [self showLog:[NSString stringWithFormat:@"[receive][usb][info] %@",[TlwTools dataToHexString:data]]];
+ [self hidReceiveDeviceData:data];
+ }
+ else if (self.connectType == AiMouseConnectType_bluetooth){
+ [self showLog:[NSString stringWithFormat:@"[receive][ble][info] %@",[TlwTools dataToHexString:data]]];
+ [self bleReceiveDeviceData:data];
+ }
+}
+
+- (void)getFullDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))finished{
+ AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
+ info.type = 0;
+ info.battery_power = M8MouseInfo.shared.battery_power;
+ info.version = M8MouseInfo.shared.version;
+ info.brand = M8MouseInfo.shared.brand;
+ info.sn = M8MouseInfo.shared.sn;
+ info.mac = info.sn;
+ info.CPI_list = @"2400";
+ info.CPI = @"2400";
+ self.fullInfo = info;
+ finished(info,nil);
+
+}
+
+#pragma mark - check dongle
+- (void)checkDongleState{
+ self.dongleTimes = 0;
+ __weak typeof(self) ws = self;
+ [self checkDongleStateAction:^(BOOL success) {
+ ws.dongleStateCallBack = nil;
+ if (success) {
+ [ws TlwConnectManager:nil connectStateDidChange:true];
+ }
+ else{
+ [ws TlwConnectManager:nil connectStateDidChange:false];
+ }
+ }];
+}
+- (void)checkDongleStateAction:(void (^)(BOOL success))finished{
+ self.dongleStateCallBack = finished;
+ [self performSelector:@selector(sendDongleCmd) withObject:nil afterDelay:1];
+}
+- (void)sendDongleCmd{
+ self.dongleTimes++;
+ if ( self.dongleStateCallBack == nil) {
+ return;
+ }
+ if (self.dongleTimes > 2) {
+ [self TlwConnectManager:nil connectStateDidChange:false];
+ return;
+ }
+ uint8_t cmd = 0x0D;
+ uint8_t len = 0x00;
+ uint8_t tail = 0xEF;
+ NSMutableData *mData = NSMutableData.data;
+ [mData appendData:[self getHidHeader]];
+ [mData appendBytes:&cmd length:1];
+ [mData appendBytes:&len length:1];
+ [mData appendBytes:&tail length:1];
+ [self sendToDevice:mData];
+ [self performSelector:@selector(sendDongleCmd) withObject:nil afterDelay:1];
+}
+#pragma mark - ble
+- (void)bleReceiveAiData:(NSData *)data{
+ [self.audioManager receiveData:data];
+}
+
+-(void)bleReceiveDeviceData:(NSData *)data{
+ uint8 type;
+ [ [data subdataWithRange:NSMakeRange(0, 1)] getBytes:&type length:1];
+
+ uint8 len;
+ [[data subdataWithRange:NSMakeRange(1, 1)] getBytes:&len length:1];
+
+ switch (type) {
+ case 0xef:
+ {
+ //鼠标按键上报
+ NSData *subData = [data subdataWithRange:NSMakeRange(2, 1)];
+ [self sendCmdData:subData];
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+#pragma mark - hid
+- (void)hidReceiveDeviceData:(NSData *)data{
+ // 0x05fff1fec09f0114ef
+ if(data.length < 7 ){
+ [self showLog:@"收到异常数据"];
+ return;
+ }
+ if(![[[TlwTools dataToHexString:[data subdataWithRange:NSMakeRange(1, 2)]] lowercaseString] isEqualToString:@"fff1"]){
+ [self showLog:@"收到异常数据"];
+ return;
+ }
+
+ uint8 type;
+ [[data subdataWithRange:NSMakeRange(5, 1)] getBytes:&type length:1];
+
+ NSData *lenData = [data subdataWithRange:NSMakeRange(6, 1)];
+ uint8 len;
+ [lenData getBytes:&len length:1];
+
+ switch (type) {
+
+ case 0x9d:
+ {
+ uint16_t version;
+ [[data subdataWithRange:NSMakeRange(7, 2)] getBytes:&version length:2];
+
+ uint8_t state;
+ [[data subdataWithRange:NSMakeRange(9, 1)] getBytes:&state length:1];
+
+ [self showLog:[NSString stringWithFormat:@"dongle version = %d,bind = %d",version,state]];
+ if(self.dongleStateCallBack)self.dongleStateCallBack(state == 1);
+ break;
+ }
+ case 0x9f:
+ {
+ NSData *subData = [data subdataWithRange:NSMakeRange(7, 1)];
+ [self sendCmdData:subData];
+
+ uint8 cmd;
+ [subData getBytes:&cmd length:1];
+
+ if(cmd == 0x04 || cmd == 0x07 || cmd == 0x13 || cmd == 0x11 || cmd == 0x01 ||cmd == 0x09){
+ self.recordManager.startCmd = subData;
+ [self startRecord];
+ }
+ else if(cmd == 0x05 || cmd == 0x08 || cmd == 0x14 || cmd == 0x12 || cmd == 0x02 ||cmd == 0x10){
+ [self stopRecord];
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+- (NSData *)getHidHeader{
+ uint8_t head1 = 0x05;
+ uint16_t head2 = 0xF1FF;
+ uint8_t head3 = 0xfe;
+ uint8_t head4 = 0x00;
+
+ NSMutableData *mData = NSMutableData.data;
+ [mData appendBytes:&head1 length:1];
+ [mData appendBytes:&head2 length:2];
+ [mData appendBytes:&head3 length:1];
+ [mData appendBytes:&head4 length:1];
+
+ return mData;
+}
+#pragma mark - other
+- (void)sendRecordData:(NSData *)data{
+ [self showLog:[NSString stringWithFormat:@"[send][audio] %@",data]];
+ if (self.delegate) [self.delegate m8MouseSendRecordData:data];
+}
+
+- (void)sendCmdData:(NSData *)data{
+ [self showLog:[NSString stringWithFormat:@"[send] %@",data]];
+ if (self.delegate) [self.delegate m8MouseSendCmdData:data];
+}
+
+- (void)showLog:(NSString *)log{
+ if (self.delegate && [self.delegate respondsToSelector:@selector(m8MouseAddLog:)]) {
+ [self.delegate m8MouseAddLog:[NSString stringWithFormat:@"[m8]%@",log]];
+ }
+}
+
+
+- (void)sendToDevice:(NSMutableData *)data{
+ if (data.length < 64) {
+ NSInteger len = 64 - data.length;
+ for (NSInteger i = 0; i < len; i++) {
+ uint8_t d = 0x00;
+ [data appendBytes:&d length:1];
+ }
+ }
+ [self showLog:[NSString stringWithFormat:@"[send][info] %@",[TlwTools dataToHexString:data]]];
+ [self.delegate m8MouseSendDeviceInfoData:data];
+}
+#pragma mark - deviceInfo
+- (void)startRecord{
+ [self.recordManager start];
+}
+
+- (void)stopRecord{
+ if (self.recordManager.recording ) {
+ [self.recordManager stop];
+ }
+}
+
+#pragma mark - other
+-(void)TlwConnectManager:(NSString *)manager connectStateDidChange:(BOOL)connected{
+ _connected = connected;
+ [self showLog:[NSString stringWithFormat:@"连接状态 %@",connected ? @"true":@"false"]];
+ if([self.delegate respondsToSelector:@selector(m8MouseConnectStateDidChange:)]) [self.delegate m8MouseConnectStateDidChange:connected];
+}
+
+- (NSString *)getBrand:(NSData *)data{
+ NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ for (NSInteger i = 0; i < text.length;i++) {
+ if ([[text substringWithRange:NSMakeRange(i, 1)] isEqual:@"\0"]) {
+ return [text substringWithRange:NSMakeRange(0, i)];
+ }
+ }
+ return text;
+}
+- (NSString *)getFullBrand:(NSData *)data{
+ NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ NSString *replacedString = [text stringByReplacingOccurrencesOfString:@"\0" withString:@"0"];
+ return replacedString;
+}
+@end
@property (nonatomic, copy)void (^logCallBack)(NSString *log);//输出日志
@property (nonatomic, assign)AiMouseProductType productType;//
-//- (void)startScan;
-
-//- (void)stopScan;
-
-//- (void)start;
- (void)open;
//
#import "BleManager.h"
-
+#import "TlwTools.h"
+#import "M8MouseInfo.h"
// 服务id
#define kFrkServiceUUID @"FFF1"
//ai特征
//通知设备信息特征
#define kTlwNotifyDeviceInfoUUID @"FFF2"
+// 服务id
+#define kM8ServiceUUID @"FF00"
+//voice特征
+#define kM8VoiceUUID @"AE42"
+#define kM8ClickUUID @"FF03"
+
+
@interface BleManager ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic, strong) CBCentralManager *centralManager;///蓝牙管理
@property(nonatomic, strong) CBPeripheral *curentPeripheral;//连接的设备
@property(nonatomic, strong) CBCharacteristic *deviceInfoCha;//设备信息特征
-@property (nonatomic,strong) NSMutableData *recordData;//录音的数据
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) dispatch_queue_t mainQueue;
// 发现特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
-
+ for (CBCharacteristic *characteristic in service.characteristics){
+ [self showLog:characteristic.UUID.UUIDString];
+ if ([characteristic.UUID.UUIDString isEqualToString:@"2A25"]) {
+ M8MouseInfo.shared.sn = [TlwTools dataToUtf8String:characteristic.value];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:@"2A19"]) {
+ NSData *data = characteristic.value;
+ int result;
+ [data getBytes:&result length:1];
+ M8MouseInfo.shared.battery_power = [NSString stringWithFormat:@"%d",result];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:@"2A24"]) {
+ M8MouseInfo.shared.brand = [TlwTools dataToUtf8String:characteristic.value];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:@"2A26"]) {
+ M8MouseInfo.shared.version = [TlwTools dataToUtf8String:characteristic.value];
+ [self showLog:[NSString stringWithFormat:@"Firmware Revision = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:@"2A28"]) {
+ [self showLog:[NSString stringWithFormat:@"Software Revision = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+ }
+// else if ([characteristic.UUID.UUIDString isEqualToString:@"2A27"]) {
+// [self showLog:[NSString stringWithFormat:@"Hardware Revision = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+// }
+//
+
+// else if ([characteristic.UUID.UUIDString isEqualToString:@"2A23"]) {
+// [self showLog:[NSString stringWithFormat:@"System ID = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+// }
+// else if ([characteristic.UUID.UUIDString isEqualToString:@"2A2A"]) {
+// [self showLog:[NSString stringWithFormat:@"PnP ID = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+// }
+// else if ([characteristic.UUID.UUIDString isEqualToString:@"2A29"]) {
+// [self showLog:[NSString stringWithFormat:@"Manufacturer Name = %@",[TlwTools dataToUtf8String:characteristic.value]]];
+// }
+ else if ([characteristic.UUID.UUIDString isEqualToString:kM8ClickUUID]) {
+ [peripheral setNotifyValue:YES forCharacteristic:characteristic];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:kM8VoiceUUID]) {
+ //语音特征
+ [peripheral setNotifyValue:YES forCharacteristic:characteristic];
+ self.productType = AiMouseProductType_m8;
+// dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
+// dispatch_after(delayTime, dispatch_get_main_queue(), ^{
+ [self showLog:[NSString stringWithFormat:@"连接成功 = %@",peripheral.name]];
+ self.connectStateCallBack(self.curentPeripheral.name,true);
+// });
+ }
+ [self showLog:[NSString stringWithFormat:@"%@",characteristic]];
+ }
+// return;
for (CBCharacteristic *characteristic in service.characteristics){
if ([characteristic.UUID.UUIDString isEqualToString:kFrkVoiceUUID]) {
//语音特征
self.deviceInfoCha = characteristic;
}
}
+
+ for (CBCharacteristic *characteristic in service.characteristics){
+ if ([characteristic.UUID.UUIDString isEqualToString:kM8VoiceUUID]) {
+ //语音特征
+ [peripheral setNotifyValue:YES forCharacteristic:characteristic];
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:kTlwNotifyDeviceInfoUUID]) {
+ //通知设备信息特征
+ [peripheral setNotifyValue:YES forCharacteristic:characteristic];
+ self.productType = AiMouseProductType_tlw;
+ // 使用dispatch_after来延迟执行任务
+ dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
+ dispatch_after(delayTime, dispatch_get_main_queue(), ^{
+ [self showLog:[NSString stringWithFormat:@"连接成功 = %@",peripheral.name]];
+ self.connectStateCallBack(self.curentPeripheral.name,true);
+ });
+ }
+ else if ([characteristic.UUID.UUIDString isEqualToString:kTlwSetDeviceInfoUUID]) {
+ //设备信息特征
+ self.deviceInfoCha = characteristic;
+ }
+ }
}
//收到蓝牙数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
- if (self.productType == AiMouseProductType_tlw) {
+ if (self.productType == AiMouseProductType_m8) {
NSData *data = characteristic.value;
- if([characteristic.UUID.UUIDString isEqualToString:kTlwVoiceUUID]){
+ if( [characteristic.UUID.UUIDString isEqualToString:kM8ClickUUID]){
+ self.receiveInfoDataCallBack(data);
+ }
+ else{
+ if([characteristic.UUID.UUIDString isEqualToString:kM8VoiceUUID] ){
+ self.receiveVoiceDataCallBack(data);
+ }
+ }
+ }
+ else if (self.productType == AiMouseProductType_tlw) {
+ NSData *data = characteristic.value;
+ if([characteristic.UUID.UUIDString isEqualToString:kTlwVoiceUUID] || [characteristic.UUID.UUIDString isEqualToString:kM8VoiceUUID] ){
self.receiveVoiceDataCallBack(data);
}
else if([characteristic.UUID.UUIDString isEqualToString:kTlwNotifyDeviceInfoUUID]){
- (void)checkRightDevice{
for (CBService *s in self.curentPeripheral.services) {
for (CBCharacteristic *c in s.characteristics) {
- if([c.UUID.UUIDString isEqualToString:kFrkVoiceUUID] ||[c.UUID.UUIDString isEqualToString:kTlwVoiceUUID] ){
+ if([c.UUID.UUIDString isEqualToString:kFrkVoiceUUID] ||[c.UUID.UUIDString isEqualToString:kTlwVoiceUUID] ||[c.UUID.UUIDString isEqualToString:kM8VoiceUUID] ){
return;
}
}
}
#pragma mark - public
- (void)startScan{
- NSArray<CBPeripheral *> *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:kFrkServiceUUID],[CBUUID UUIDWithString:kTlwServiceUUID]]];
+ NSArray<CBPeripheral *> *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:
+ @[[CBUUID UUIDWithString:kFrkServiceUUID],
+ [CBUUID UUIDWithString:kTlwServiceUUID],
+ [CBUUID UUIDWithString:kM8ServiceUUID],
+ ]];
// [self showLog:[NSString stringWithFormat:@"查询配对过的设备%@",devices]];
if (devices.count > 0) {
[self connectPeripheral:devices[0]];
}
else{
-// [self showLog:[NSString stringWithFormat:@"开始扫描%@",@""]];
-// [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO]}];
+
}
}
NSString *text = [NSString stringWithFormat:@"[BleManager] %@",log];
if(self.logCallBack) self.logCallBack(text);
}
-#pragma mark - timer
-- (void)start{
- if (self.timer && [self.timer isValid]) {
- [self.timer invalidate];
- self.timer = nil;
- }
-// dispatch_async(dispatch_queue_create("timeoutQueue", DISPATCH_QUEUE_SERIAL), ^{
-// self.timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
-// [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
-// [[NSRunLoop currentRunLoop] run];
-// });
-// self.timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
- self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(checkConnected) userInfo:nil repeats:true];
-}
+
- (void)open{
if([DeviceManger shared].isConneted){
AiMouseProductType_tlw = 2,///泰凌微
AiMouseProductType_n = 3,///一键上网
AiMouseProductType_keyboard = 4,///键盘
+ AiMouseProductType_m8 = 5,///泰凌微m8
};
NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) AiMouseConnectType connectType;//连接类型
#pragma mark ------- 鼠标的回调
@property (nonatomic,strong)void (^authCallBack)(BOOL isSuccess);/// 鉴权回调
-@property (nonatomic, copy)void (^aiMouseSendDeviceInfoDataCallBack)(NSString *data);/// 设备信息数据回调
+//@property (nonatomic, copy)void (^aiMouseSendDeviceInfoDataCallBack)(NSString *data);/// 设备信息数据回调
@property (nonatomic, copy)void (^aiMouseSendCmdDataCallBack)(NSString *data);/// 鼠标按键指令回调
@property (nonatomic, copy)void (^begainRecoredCallBack)(void);/// 录音开始回调
@property (nonatomic, copy)void (^recordingCallBack)(NSString *data);/// 录音进行中回调
@property (nonatomic, copy)void (^finishRecoredCallBack)(NSString *data);/// 录音结束回调
-//@property (nonatomic, copy)void (^aiMouseAddLogCallBack)(NSString *log);///输出日志
-
#pragma mark ------- 接口
///单例
#import "KeyboardHidManager.h"
#import "KeyboardSdk.h"
#import "ByteDanceSdk.h"
+#import "M8MouseSdk.h"
#import "LogManager.h"
@interface DeviceManger()<TlwMouseDelegate,AiMouseDelegate,NMouseSdkDelegate,KeyboardSdkDelegate>
@property (nonatomic,strong) AiMouse *frkSdk;
@property (nonatomic,strong) NMouseSdk *nSdk;
@property (nonatomic,strong) KeyboardSdk *kbSdk;
+@property (nonatomic,strong) M8MouseSdk *m8Sdk;
@property (nonatomic,assign) AiMouseProductType productType;
//connectType 返回为0代表蓝牙,为1代表usb
- (instancetype)init{
self = [super init];
if (self) {
-// NSString *version = @"MouseSdk_v2024120303";
-// NSLog(@"[AiMouseSdk] %@",version);
-// [self showLog:version];;
-// [self setupSDK];
-// [self setupBle];
-// [self setupHid];
-// [self setupTimer];
- self.version = @"MouseSdk_v2025010303";
+ self.version = @"MouseSdk_v2025041501";
}
return self;
}
self.frkSdk = [AiMouse shared];
[self.frkSdk setDelegate:self];
+
+ self.m8Sdk = [[M8MouseSdk alloc] init];
+ [self.m8Sdk setDelegate:self];
}
- (void)setupTimer{
[TimerManager shared].timerCallBack = ^{
// [self showLog:@"timer action。。。"];
- if(self.kbSdk.connected || self.nSdk.connected || self.tlwSdk.connected || self.frkSdk.connected){
+ if(self.kbSdk.connected || self.nSdk.connected || self.tlwSdk.connected || self.frkSdk.connected|| self.m8Sdk.connected){
// [self.hid close];
}
else{
- (void)setupHid{
-
self.hid = [HidManager shared];
__weak typeof(self) ws = self;
else if (ws.hid.productType == AiMouseProductType_keyboard){
[ws.kbSdk switchConnect:AiMouseConnectType_hid isConnected:true];
}
+ else if (ws.hid.productType == AiMouseProductType_m8){
+ [ws.m8Sdk switchConnect:AiMouseConnectType_hid isConnected:true];
+ }
}
else{
if (ws.hid.productType == AiMouseProductType_n) {
[ws.kbSdk switchConnect:AiMouseConnectType_hid isConnected:false];
[ws.kbSdk didDisconnect];
}
+ else if (ws.hid.productType == AiMouseProductType_keyboard) {
+ [ws.m8Sdk switchConnect:AiMouseConnectType_hid isConnected:false];
+ [ws.m8Sdk didDisconnect];
+ }
}
};
self.hid.receiveInfoDataCallBack = ^(NSData *data) {
else if (ws.hid.productType == AiMouseProductType_keyboard) {
[ws.kbSdk sendDeviceDataToSdk:data];
}
+ else if (ws.hid.productType == AiMouseProductType_keyboard) {
+ [ws.m8Sdk sendDeviceDataToSdk:data];
+ }
};
self.hid.logCallBack = ^(NSString * _Nonnull log) {
[ws showLog:log];
else if (ws.ble.productType == AiMouseProductType_tlw) {
[ws.tlwSdk switchConnect:AiMouseConnectType_bluetooth isConnected:true];
}
+ else if (ws.ble.productType == AiMouseProductType_m8) {
+ [ws.m8Sdk switchConnect:AiMouseConnectType_bluetooth isConnected:true];
+ }
else{
[ws.frkSdk switchConnect:AiMouseConnectType_bluetooth isConnected:true];
}
else if (ws.ble.productType == AiMouseProductType_tlw) {
[ws.tlwSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
+ else if (ws.ble.productType == AiMouseProductType_m8) {
+ [ws.m8Sdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ }
else{
[ws.frkSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
else if (ws.productType == AiMouseProductType_tlw) {
[ws.tlwSdk sendDeviceDataToSdk:data];
}
+ else if (ws.productType == AiMouseProductType_m8) {
+ [ws.m8Sdk sendDeviceDataToSdk:data];
+ }
else{
[ws.frkSdk sendDeviceDataToSdk:data];
}
if (ws.productType == AiMouseProductType_tlw) {
[ws.tlwSdk sendAiDataToSdk:data];
}
+ else if (ws.productType == AiMouseProductType_m8) {
+ [ws.m8Sdk sendAiDataToSdk:data];
+ }
else{
[ws.frkSdk sendAiDataToSdk:data];
}
if (self.frkSdk != nil && self.frkSdk.connected) {
return true;
}
+ if (self.m8Sdk != nil && self.m8Sdk.connected) {
+ return true;
+ }
return false;
}
return @"1";
}
}
+ else if (self.productType == AiMouseProductType_m8) {
+ if (self.m8Sdk.connectType == AiMouseConnectType_bluetooth) {
+ return @"0";
+ }
+ else {
+ return @"1";
+ }
+ }
else{
if (self.frkSdk.connectType == AiMouseConnectType_bluetooth) {
return @"0";
else if (self.productType == AiMouseProductType_tlw) {
return self.tlwSdk.connectType;
}
+ else if (self.productType == AiMouseProductType_m8) {
+ return self.m8Sdk.connectType;
+ }
else {
return self.frkSdk.connectType;
}
}else if (self.productType == AiMouseProductType_tlw) {
[self.tlwSdk getFullDeviceInfo:finished];
}
+ else if (self.productType == AiMouseProductType_m8) {
+ [self.m8Sdk getFullDeviceInfo:finished];
+ }
else{
[self.frkSdk getDeviceInfo:finished];
}
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
}
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_frk ) {
[self.frkSdk getRSSI:finished];
}
/// 设置CPI
- (void)setCPI:(NSInteger)value completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前键盘不支持该接口"}]);
+ return;
+ }
+ if (self.productType == AiMouseProductType_m8) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
}
/// - value: 品牌名称
/// - finished: 设置结果回调
- (void)setBrand:(NSString *)brand completation:(void (^)(BOOL isSuccess,NSError *error))finished {
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 设置录音模式
- (void)setRecordMode:(int)mode completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 设置长按滚轮弹出的网页地址
- (void)setUrl:(NSString *)url completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 设置长按滚轮弹出网页开关
- (void)setUrlState:(int)state completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 设置鼠标连接模式
- (void)setMouseMode:(int)mode completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 获取录音模式
- (void)getRecordMode:(void (^)(int mode,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 获取长按滚轮弹出的网页地址
- (void)getUrl:(void (^)(NSString *url,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 获取长按滚轮弹出的网页地址开关状态
- (void)getUrlState:(void (^)(int state,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 获取鼠标连接模式
- (void)getMouseModel:(void (^)(int mode,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 打开录音
- (void)openRecord:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
/// 关闭录音
- (void)closeRecord:(void (^)(BOOL isSuccess,NSError *error))finished{
+ if (self.productType == AiMouseProductType_m8) {
+ finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
+ return;
+ }
if (self.productType == AiMouseProductType_keyboard) {
finished(false,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"当前鼠标不支持该接口"}]);
return;
if (connected) {
[self.frkSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
[self.nSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ [self.m8Sdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
if (self.aiMouseConnectStateDidChangeCallBack) {
/// M 单击0x06, 按下0x13(开始录音)抬起0x14(结束录音)
/// AI键 单击0x03, 按下0x11(开始录音)抬起0x12(结束录音)
/// 语音键 第一次单击0x01, 第二次单击0x02(结束录音) , 按下0x09(开始录音)抬起0x10(结束录音)
+/// 翻译键 第一次单击0x04(开始录音), 第二次单击0x05(结束录音), 按下0x07(开始录音) 抬起0x08(结束录音)
/// 其他未定义
///
/// /// 鼠标按键指令回调 富瑞坤
if (connected) {
[self.tlwSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
[self.frkSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ [self.m8Sdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
if (self.aiMouseConnectStateDidChangeCallBack) {
if (connected) {
[self.tlwSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
[self.nSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ [self.m8Sdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
if (self.aiMouseConnectStateDidChangeCallBack) {
- (void)aiMouseHidDataError{
[self.hid open];
}
+#pragma mark - M8MouseSdkDelegate
+/// 设备连接状态
+/// - Parameter connected: 是否连接
+- (void)m8MouseConnectStateDidChange:(BOOL)connected{
+ [self showLog:[NSString stringWithFormat:@"%@设备连接状态返回: %@",self.m8Sdk.connectType == AiMouseConnectType_bluetooth ? @"蓝牙 ":@"USB",connected ? @"true":@"false"]];
+
+ if (connected) {
+ [self.tlwSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ [self.nSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ [self.frkSdk switchConnect:AiMouseConnectType_bluetooth isConnected:false];
+ }
+
+ if (self.aiMouseConnectStateDidChangeCallBack) {
+ self.aiMouseConnectStateDidChangeCallBack(self.m8Sdk.connectType == AiMouseConnectType_bluetooth ? 0:1,connected);
+ }
+ if(self.authCallBack && connected)self.authCallBack(connected);
+}
+
+
+/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
+/// - Parameter data: 数据
+- (void)m8MouseSendDeviceInfoData:(NSData *)data{
+ if (self.m8Sdk.connectType == AiMouseConnectType_bluetooth) {
+ [self.ble writeToDevice:data];
+ }
+ else if (self.frkSdk.connectType == AiMouseConnectType_hid){
+ [self.hid writeToDevice:data];
+ }
+}
+
+/// 鼠标按键指令回调
+//EF AA 0B 00 02 E1 00 E3 语音键单击开始
+//EF AA 0C 00 02 E1 00 E3 语音键单击结束
+//EF AA 05 00 02 E1 00 E3 语音键长按
+//EF AA 06 00 02 E1 00 E3 语音键长按松开
+//
+//
+//EF AA 09 00 02 E1 00 E3 M键单击
+//EF AA 01 00 02 E1 00 E3 M键长按松开
+//EF AA 02 00 02 E1 00 E3 M键长按松开
+//
+//EF AA 0A 00 02 E1 00 E3 AI键单击
+//EF AA 03 00 02 E1 00 E3 AI键长按松开
+//EF AA 04 00 02 E1 00 E3 AI键长按松开
+//
+//EF AA 0D 00 02 E1 00 E3 翻译键单击开始
+//EF AA 0E 00 02 E1 00 E3 翻译键单击结束
+//EF AA 07 00 02 E1 00 E3 翻译键长按
+//EF AA 08 00 02 E1 00 E3 翻译键长按松开
+//@"09":@"43",
+//@"01":@"27",
+//@"02":@"28",
+//
+//@"0A":@"42",
+//@"03":@"25",
+//@"04":@"26",
+//
+//@"0B":@"31",
+//@"0C":@"32",
+//@"05":@"21",
+//@"06":@"22",
+
+//@"0D":@"04",
+//@"0E":@"05",
+//@"07":@"07",
+//@"08":@"08",
+/// 其他未定义
+- (void)m8MouseSendCmdData:(NSData *)data{
+ NSLog(@"%@",data);
+ uint8 cmd;
+ [data getBytes:&cmd length:1];
+ if( cmd == 0x01){
+ cmd = 0x27;
+ }else if( cmd == 0x02){
+ cmd = 0x28;
+ }
+ else if( cmd == 0x09){
+ cmd = 0x43;
+ }
+ else if( cmd == 0xa){
+ cmd = 0x42;
+ }
+ else if( cmd == 0x03){
+ cmd = 0x25;
+ }
+ else if( cmd == 0x4){
+ cmd = 0x26;
+ }
+ else if( cmd == 0x0B){
+ cmd = 0x31;
+ }
+ else if( cmd == 0x0C){
+ cmd = 0x32;
+ }
+ else if( cmd == 0x05){
+ cmd = 0x21;
+ }
+ else if( cmd == 0x06){
+ cmd = 0x22;
+ }
+ else if( cmd == 0x0D){
+ cmd = 0x04;
+ }
+ else if( cmd == 0x0E){
+ cmd = 0x05;
+ }
+ else if( cmd == 0x07){
+ cmd = 0x07;
+ }
+ else if( cmd == 0x08){
+ cmd = 0x08;
+ }
+ if (self.aiMouseSendCmdDataCallBack) {
+ self.aiMouseSendCmdDataCallBack([NSString stringWithFormat:@"%X",cmd]);
+ }
+
+ if(cmd == 0x04 || cmd == 0x07 || cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){
+ [self showLog:@"开始录音"];
+ self.recordData = [[NSMutableData alloc] init];
+ if (self.begainRecoredCallBack) {
+ self.begainRecoredCallBack();
+ }
+ }
+ else if(cmd == 0x05 || cmd == 0x08 || cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){
+ [self showLog:@"结束录音"];
+ [self finishRecored:self.recordData];
+ if (self.finishRecoredCallBack) {
+ NSString *base64String = [self.recordData base64EncodedStringWithOptions:0];
+ self.finishRecoredCallBack(base64String);
+ }
+ }
+}
+
+/// 录音回调
+/// - Parameter data: pcm格式语音数据
+- (void)m8MouseSendRecordData:(NSData *)data{
+ [self.recordData appendData:data];
+ if (self.recordingCallBack) {
+ self.recordingCallBack( [data base64EncodedStringWithOptions:0]);
+ }
+}
+
+/// hid数据异常,需要重新开启监听usb设备
+- (void)m8HidDataError{
+ [self.hid open];
+}
+
+/// 输出sdk日志
+/// - Parameter log: 日志
+- (void)m8MouseAddLog:(NSString *)log{
+ [self showLog:log];
+}
+
#pragma mark - other
- (void)showLog:(NSString *)log{
// if (self.aiMouseAddLogCallBack) {
if(self.logCallBack) self.logCallBack(text);
}
-///// 实际到数据长度
-//static inline int get_data_len(uint8_t *buf, u_long len) {
-// if (len <= 0 ) return 0;
-// int url_len = 0;
-// while (buf[url_len] != 0x00) url_len++;
-// return url_len;
-//}
-
/// 实际到数据长度
static inline int get_data_len(uint8_t *buf, int len) {
if (len <= 0 ) return 0;
// [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
// [[NSRunLoop currentRunLoop] run];
// });
- self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
+ self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
}
- (void)timerAction{
version = "2.0">
<Breakpoints>
<BreakpointProxy
- BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
+ BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
- uuid = "B13C82BB-F468-4E93-A44A-F14FFAD4D10D"
+ uuid = "3FEEA307-9A37-4E1D-83CF-48F35AD81EF6"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
- breakpointStackSelectionBehavior = "1"
- scope = "1"
- stopOnStyle = "0">
+ filePath = "AiMouseSdk/M8/M8MouseSdk.m"
+ startingColumnNumber = "9223372036854775807"
+ endingColumnNumber = "9223372036854775807"
+ startingLineNumber = "59"
+ endingLineNumber = "59"
+ landmarkName = "-recordManager"
+ landmarkType = "7">
+ </BreakpointContent>
+ </BreakpointProxy>
+ <BreakpointProxy
+ BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+ <BreakpointContent
+ uuid = "7811129E-8425-43E8-9FDC-75B40C321EE5"
+ shouldBeEnabled = "Yes"
+ ignoreCount = "0"
+ continueAfterRunningActions = "No"
+ filePath = "AiMouseSdk/AiMouseSdk/AiAudioManager.m"
+ startingColumnNumber = "9223372036854775807"
+ endingColumnNumber = "9223372036854775807"
+ startingLineNumber = "52"
+ endingLineNumber = "52"
+ landmarkName = "-setupAudioDecoder"
+ landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
}
});
}];
+ manager.aiMouseSendCmdDataCallBack = ^(NSString * _Nonnull data) {
+ NSLog(@"%@",[NSString stringWithFormat:@"按键指令 = %@",data]);
+ };
+ manager.recordingCallBack = ^(NSString * _Nonnull data) {
+ NSLog(@"%@",[NSString stringWithFormat:@"语音数据 = %@",data]);
+ };
}
<key>Masonry.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
- <integer>2</integer>
+ <integer>3</integer>
</dict>
<key>Pods-MouseSdk.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
- <integer>3</integer>
+ <integer>4</integer>
</dict>
</dict>
</dict>