/// 切换连接类型
/// - Parameter type: 连接类型
-- (void)switchConnect:(AiMouseConnectType)type;
+- (void)switchConnect:(AiMouseConnectType)type isConnected:(BOOL)isConneted;
/// 传输业务数据给sdk
/// - Parameter data:ai特征传过来的数据
_logLevel = level;
}
- (void)didDisconnect{
+ _connected = false;
[self showLog:@"系统断开连接"];
[self stopRecord];
[self.connectManager disConnected];
}
-- (void)switchConnect:(AiMouseConnectType)type{
- if(type != _connectType && self.connected){
- [self.connectManager disConnected];
- }
+- (void)switchConnect:(AiMouseConnectType)type isConnected:(BOOL)isConneted{
+// if(type != _connectType && self.connected){
+// [self.connectManager disConnected];
+// }
+ _connected = isConneted;
_connectType = type;
[self showLog:type == AiMouseConnectType_bluetooth?@"sdk切换到蓝牙模式":@"sdk切换到usb模式"];
-
+ [self TlwConnectManager:self.connectManager connectStateDidChange:isConneted];
if (type == AiMouseConnectType_hid) {
[self.recordManager checkPermissions];
180E7D1A2BD90032008558E8 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F325772B95737F00CABA2E /* CoreAudio.framework */; };
180E7D1B2BD9005D008558E8 /* liblzma.5.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 18CB080B2BA401D0005F5854 /* liblzma.5.tbd */; };
182B548D2BB7EC9B009F53B6 /* DeviceManger.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B548C2BB7EC9B009F53B6 /* DeviceManger.m */; };
+ 185EBE042C79D16600B2503B /* TimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 185EBE032C79D16600B2503B /* TimerManager.m */; };
1867E5A92BB2706F008FC5FB /* HidManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1867E5A82BB2706F008FC5FB /* HidManager.m */; };
18BF1DCF2B81AB7C00B8D90F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18BF1DCE2B81AB7C00B8D90F /* AppDelegate.m */; };
18BF1DD22B81AB7C00B8D90F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18BF1DD12B81AB7C00B8D90F /* ViewController.m */; };
180E7AB22BD7BBD9008558E8 /* libAiMouseSdk.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libAiMouseSdk.a; sourceTree = BUILT_PRODUCTS_DIR; };
182B548B2BB7EC9B009F53B6 /* DeviceManger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeviceManger.h; sourceTree = "<group>"; };
182B548C2BB7EC9B009F53B6 /* DeviceManger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DeviceManger.m; sourceTree = "<group>"; };
+ 185EBE022C79D16600B2503B /* TimerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TimerManager.h; sourceTree = "<group>"; };
+ 185EBE032C79D16600B2503B /* TimerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TimerManager.m; sourceTree = "<group>"; };
1867E5A72BB2706F008FC5FB /* HidManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HidManager.h; sourceTree = "<group>"; };
1867E5A82BB2706F008FC5FB /* HidManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HidManager.m; sourceTree = "<group>"; };
18BF1DCA2B81AB7C00B8D90F /* AiMouseSdk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AiMouseSdk.app; sourceTree = BUILT_PRODUCTS_DIR; };
18EF7B092C7605BF00AC5223 /* MouseSdkManager.m */,
18BF1DD02B81AB7C00B8D90F /* ViewController.h */,
18BF1DD12B81AB7C00B8D90F /* ViewController.m */,
- 18EF7B0B2C76079E00AC5223 /* TlwVC.h */,
- 18EF7B0C2C76079E00AC5223 /* TlwVC.m */,
18EF7B0E2C7607C100AC5223 /* FrkVC.h */,
18EF7B0F2C7607C100AC5223 /* FrkVC.m */,
+ 18EF7B0B2C76079E00AC5223 /* TlwVC.h */,
+ 18EF7B0C2C76079E00AC5223 /* TlwVC.m */,
18EF7B1A2C760FF700AC5223 /* TlwScanVC.h */,
18EF7B1B2C760FF700AC5223 /* TlwScanVC.m */,
18EF7B1C2C760FF700AC5223 /* TlwScanVC.xib */,
children = (
182B548B2BB7EC9B009F53B6 /* DeviceManger.h */,
182B548C2BB7EC9B009F53B6 /* DeviceManger.m */,
+ 185EBE022C79D16600B2503B /* TimerManager.h */,
+ 185EBE032C79D16600B2503B /* TimerManager.m */,
18BF1E202B83066200B8D90F /* BleManager.h */,
18BF1E212B83066200B8D90F /* BleManager.m */,
1867E5A72BB2706F008FC5FB /* HidManager.h */,
18BF1DD22B81AB7C00B8D90F /* ViewController.m in Sources */,
18BF1DD92B81AB7F00B8D90F /* main.m in Sources */,
18EF7B172C760A5B00AC5223 /* TlwBleManager.m in Sources */,
+ 185EBE042C79D16600B2503B /* TimerManager.m in Sources */,
18F328D52B98569D00CABA2E /* Config.m in Sources */,
18EF7B182C760A5B00AC5223 /* TlwHidManager.m in Sources */,
18EF7B0D2C76079E00AC5223 /* TlwVC.m in Sources */,
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
-#import "TlwMouseSdk.h"
-#import "AiMouseSdk.h"
-
-@interface BleManager : NSObject <TlwMouseDelegate>
-@property (nonatomic,copy)void (^discoverDevice)(CBPeripheral *peripheral) ;/// 扫描到设备
-@property (nonatomic,copy)void (^didConnectDevice)(CBPeripheral *peripheral);/// 连接成功
-@property (nonatomic,copy)void (^didDisConnectDevice)(CBPeripheral *peripheral);/// 断开连接
-///
-///
-@property (nonatomic,copy)void (^authCallBack)(BOOL isSuccess);/// 鉴权回调
-@property (nonatomic, copy)void (^aiMouseConnectStateDidChangeCallBack)(BOOL connected);/// 设备连接状态回调
-@property (nonatomic, copy)void (^aiMouseSendDeviceInfoDataCallBack)(NSData *data);/// 设备信息数据回调
-@property (nonatomic, copy)void (^aiMouseSendCmdDataCallBack)(NSString *data);/// 鼠标按键指令回调
-@property (nonatomic, copy)void (^begainRecoredCallBack)(void);/// 录音开始回调
-@property (nonatomic, copy)void (^recordingCallBack)(NSData *data);/// 录音进行中回调
-@property (nonatomic, copy)void (^finishRecoredCallBack)(NSData *data);/// 录音结束回调
-
-@property (nonatomic, copy)void (^aiMouseAddLogCallBack)(NSString *log);//输出日志
-/// 单利
-+(BleManager *)shared;
-
-/// 扫描
-- (void)startScanDevice;
-/// 停止扫描
-- (void)stopScanDevice;
-/// 连接设备
-/// - Parameter peripheral: 蓝牙设备
-- (void)connectPeripheral:(CBPeripheral *)peripheral;
-///当前是否处于蓝牙连接状态
-- (BOOL)isDidConnectBleDevice;
-
-///直连蓝牙设备,该函数已经处理了startScanDevice、connectPeripheral和stopScanDevice的调用
-/// - Parameter bleName:蓝牙设备名称
-- (void)connectBleDeviceWithName:(NSString *)bleName;
+@interface BleManager : NSObject
+@property (nonatomic, copy)void (^connectStateCallBack)(BOOL connected);/// 设备连接状态回调
+@property (nonatomic, copy)void (^receiveVoiceDataCallBack)(NSData *data);/// 语音数据回调
+@property (nonatomic, copy)void (^receiveInfoDataCallBack)(NSData *data);/// 设备信息数据回调
+@property (nonatomic, copy)void (^logCallBack)(NSString *log);//输出日志
+/// 单利
++(BleManager *)shared;
-/// 获取设备信息
-- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))completation;
+// bleName:蓝牙设备名称
+- (void)startScanWithName:(NSString *)bleName;
-/// 获取信号强度
-- (void)getRSSI:(void (^)(NSString *value,NSError *error))complete;
+//停止扫描
+- (void)stopScan;
+//写入数据
+-(void)writeToDevice:(NSData *)data;
@end
@interface BleManager ()<CBCentralManagerDelegate,CBPeripheralDelegate>
-{
-// dispatch_block_t _block;
- //是否是主动断开蓝牙连接的
- bool _isActiveDisconnect;
- dispatch_block_t _disconnectBlock;
-}
@property(nonatomic, strong) CBCentralManager *centralManager;///蓝牙管理
-@property(nonatomic, strong) CBPeripheral *connectPeripheral;//连接的设备
-@property(nonatomic, strong) CBCharacteristic *aiCha;//ai特征
+@property(nonatomic, strong) CBPeripheral *crrentPeripheral;//连接的设备
@property(nonatomic, strong) CBCharacteristic *deviceInfoCha;//设备信息特征
@property (nonatomic,strong) NSMutableData *recordData;//录音的数据
-
-@property (nonatomic, copy)void (^activeDisconnectCallBack)(BOOL isSuccess);//主动断开连接的回调
-
@property (nonatomic, copy) NSString *targetBleName;
@end
if (self) {
self.centralManager = [[CBCentralManager alloc]init];
self.centralManager.delegate = self;
- _isActiveDisconnect = NO;
-
-// //链接超时
-// _block = dispatch_block_create(0, ^{
-// [self showLog:(@"(BleManager)执行超时操作 ")];
-// //连接超时走这里
-// if (self.connectPeripheral == nil || self.deviceInfoCha == nil) {
-// if (self.connectPeripheral != nil) {
-// //立即取消与外围设备的连接
-// [self.centralManager cancelPeripheralConnection:self.connectPeripheral];
-// self.connectPeripheral = nil;
-// }
-// [self stopScanDevice];
-// [self showLog:(@"(BleManager)执行超时操作成功,回调连接失败回调 ")];
-// if(self.didDisConnectDevice){
-// self.didDisConnectDevice(nil);
-// }
-// }
-// });
-
- //断开连接超时
- _disconnectBlock = dispatch_block_create(0, ^{
- [self showLog:(@"(BleManager)断开连接执行超时操作 ")];
- //连接超时走这里
- if (self.connectPeripheral != nil && self.connectPeripheral.state != CBPeripheralStateDisconnected) {
- if (self.activeDisconnectCallBack) {
- self.activeDisconnectCallBack(NO);
- }
- }
- else {
- if (self.activeDisconnectCallBack) {
- self.activeDisconnectCallBack(YES);
- }
- }
- });
}
return self;
}
-- (BOOL)isDidConnectBleDevice {
- if (self.connectPeripheral == nil) {
- return NO;
- }
- //当前处于蓝牙链接状态
- if (self.connectPeripheral.state == CBPeripheralStateConnected || self.connectPeripheral.state == CBPeripheralStateConnecting) {
- return YES;
- }
- return NO;
-}
#pragma mark - CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(nonnull CBCentralManager *)central {
- [self showLog:[NSString stringWithFormat:@"centralManagerDidUpdateState:蓝牙状态 = %@",@(central.state)]];
+ [self showLog:[NSString stringWithFormat:@"当前电脑蓝牙状态 = %@",@(central.state)]];
switch (central.state) {
case CBManagerStateUnknown:
break;
case CBManagerStatePoweredOn:
- [self autoConnectDevice];
+// [self autoConnectDevice];
break;
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
-// [self showLog:[NSString stringWithFormat:@"(BleManager) didDiscoverPeripheral:扫描到设备 = %@, data = %@",peripheral,advertisementData]];
- if(self.discoverDevice){
- self.discoverDevice(peripheral);
- }
-
- //直连
if (self.targetBleName != nil && self.targetBleName.length > 0 && [self.targetBleName isEqualToString:peripheral.name]) {
[self connectPeripheral:peripheral];
}
-
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
- _isActiveDisconnect = NO;
- [self showLog:[NSString stringWithFormat:@"(BleManager) didConnectPeripheral:连接成功 name = %@",peripheral.name]];
- //要求在发现特征处返回连接成功
-// if(self.didConnectDevice){
-// self.didConnectDevice(peripheral);
-// }
+ [self showLog:[NSString stringWithFormat:@"didConnectPeripheral:连接成功 name = %@",peripheral.name]];
peripheral.delegate = self;
[peripheral discoverServices:nil];
- self.connectPeripheral = peripheral;
-
- //直连成功后直接停止扫描
- if (self.targetBleName != nil && self.targetBleName.length > 0 && [self.targetBleName isEqualToString:peripheral.name]) {
- [self stopScanDevice];
- }
-
+ self.crrentPeripheral = peripheral;
}
+
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
- [self showLog:[NSString stringWithFormat:@"(BleManager) didDisconnectPeripheral:断开连接。。。%@",error.description]];
- [self tlwMouseConnectStateDidChange:false];
-// dispatch_block_cancel(_block); // 取消定时的执行
- if (_isActiveDisconnect) {
- dispatch_block_cancel(_disconnectBlock);// 取消定时的执行
-
- if (self.activeDisconnectCallBack) {
- self.activeDisconnectCallBack(YES);
- }
- if (self.connectPeripheral != nil) {
- self.connectPeripheral = nil;
- }
- }
- else{
- //返回设备断开连接
-// [self aiMouseConnectStateDidChange:false];
- [[TlwMouse shared] didDisconnect];
-
- if(self.didDisConnectDevice){
- self.didDisConnectDevice(peripheral);
- }
- self.connectPeripheral = nil;
- [self autoConnectDevice];
- }
+ [self showLog:[NSString stringWithFormat:@"didDisconnectPeripheral:断开连接。。。%@",error.description]];
+ self.crrentPeripheral = nil;
+ self.connectStateCallBack(false);
}
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
- [self showLog:[NSString stringWithFormat:@"(BleManager) didFailToConnectPeripheral:连接失败。。。%@",error.description]];
-// dispatch_block_cancel(_block); // 取消定时的执行
- if(self.didDisConnectDevice){
- self.didDisConnectDevice(peripheral);
- }
-
- self.connectPeripheral = nil;
+ [self showLog:[NSString stringWithFormat:@"didFailToConnectPeripheral:连接失败。。。%@",error.description]];
+ self.crrentPeripheral = nil;
+ self.connectStateCallBack(false);
}
#pragma mark - CBPeripheralDelegate
//发现服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
- [self showLog:[NSString stringWithFormat:@"(BleManager) didDiscoverServices:发现服务"]];
+ [self showLog:[NSString stringWithFormat:@"didDiscoverServices:发现服务"]];
for (CBService *service in peripheral.services){
[peripheral discoverCharacteristics:nil forService:service];
}
else if ([characteristic.UUID.UUIDString isEqualToString:kSetDeviceInfoUUID]) {
//设备信息特征
self.deviceInfoCha = characteristic;
- //切换代理
- [TlwMouse shared].delegate = self;
- //切换当前连接类型
- [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth];
- [self showLog:(@"(BleManager)didDiscoverCharacteristicsForService:回调连接成功 ")];
- [self tlwMouseConnectStateDidChange:true];
- //此时才返回连接成功
- if(self.didConnectDevice){
- self.didConnectDevice(peripheral);
- }
+ [self showLog:(@"didDiscoverCharacteristicsForService:回调连接成功 ")];
+ self.connectStateCallBack(true);
}
}
}
//收到蓝牙数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
NSData *data = characteristic.value;
- [self showLog:[NSString stringWithFormat:@"(BleManager) didUpdateValueForCharacteristic:[receive] %@",data]];
- [self showLog:[NSString stringWithFormat:@"(BleManager) didUpdateValueForCharacteristic:characteristicUUID %@",characteristic.UUID.UUIDString]];
-
if([characteristic.UUID.UUIDString isEqualToString:kAiUUID]){
//AI数据
- [self showLog:[NSString stringWithFormat:@"(BleManager) didUpdateValueForCharacteristic:发送AI数据sendAiDataToSdk"]];
- [[TlwMouse shared] sendAiDataToSdk:data];
+ self.receiveVoiceDataCallBack(data);
}
else if([characteristic.UUID.UUIDString isEqualToString:kNotifyDeviceInfoUUID]){
//设备信息数据
- [self showLog:[NSString stringWithFormat:@"(BleManager) didUpdateValueForCharacteristic:发送设备信息数据sendDeviceDataToSdk"]];
- [[TlwMouse shared] sendDeviceDataToSdk:data];
- }
-}
-
-#pragma mark - TlwMouseDelegate
-/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
-/// - Parameter data: 数据
--(void)tlwMouseSendDeviceInfoData:(NSData *)data{
- if (self.connectPeripheral ==nil) {
- [self showLog:@"peripheral 为空"];
- return;
- }
- if (self.deviceInfoCha ==nil) {
- [self showLog:@"characteristic 为空"];
- return;
- }
- [self.connectPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithResponse];
-
- if (self.aiMouseSendDeviceInfoDataCallBack) {
- self.aiMouseSendDeviceInfoDataCallBack(data);
- }
-}
-
-/// 鼠标按键指令回调
-/// - Parameter data: 数据。
-/// 前 单击0x06, 按下0x13(开始录音)抬起0x14(结束录音)
-/// 中 单击0x03, 按下0x11(开始录音)抬起0x12(结束录音)
-/// 后 第一次单击0x01, 第二次单击0x02(结束录音) , 按下0x09(开始录音)抬起0x10(结束录音)
-/// 其他未定义
-///
-/// /// 鼠标按键指令回调 富瑞坤
-/// - Parameter data: 数据。
-/// 前 单击43,按下27(开始录音)抬起28(结束录音)
-/// 中 单击42, 按下25(开始录音)抬起26(结束录音)
-/// 后 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音)
-///
-/// 其他未定义
-- (void)tlwMouseSendCmdData:(NSData *)data{
- uint8 cmd;
- [data getBytes:&cmd length:1];
- if( cmd == 0x01){
- cmd = 0x31;
- }else if( cmd == 0x02){
- cmd = 0x32;
- }
- else if( cmd == 0x09){
- cmd = 0x21;
- }
- else if( cmd == 0x10){
- cmd = 0x22;
- }
- else if( cmd == 0x03){
- cmd = 0x42;
- }
- else if( cmd == 0x11){
- cmd = 0x25;
- }
- else if( cmd == 0x12){
- cmd = 0x26;
- }
- else if( cmd == 0x06){
- cmd = 0x43;
- }
- else if( cmd == 0x13){
- cmd = 0x27;
- }
- else if( cmd == 0x14){
- cmd = 0x28;
- }
-
- [self showLog:[NSString stringWithFormat:@"(BleManager) aiMouseSendCmdData:收到指令 = %X",cmd]];
-
- if (self.aiMouseSendCmdDataCallBack) {
- self.aiMouseSendCmdDataCallBack([NSString stringWithFormat:@"%X",cmd]);
- }
-
- if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){
- [self showLog:@"(BleManager) aiMouseSendCmdData:开始录音"];
- self.recordData = [[NSMutableData alloc] init];
- if (self.begainRecoredCallBack) {
- self.begainRecoredCallBack();
- }
- }
- else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){
- [self showLog:@"(BleManager) aiMouseSendCmdData:结束录音"];
- [self finishRecored:self.recordData];
- if (self.finishRecoredCallBack) {
- self.finishRecoredCallBack(self.recordData);
- }
- }
-}
-
-/// 录音回调
-/// - Parameter data: pcm格式语音数据
-- (void)tlwMouseSendRecordData:(NSData *)data{
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- [self showLog:[NSString stringWithFormat:@"(BleManager) aiMouseSendRecordData:[appendData] %@\n%@",data,base64String]];
- [self.recordData appendData:data];
- if (self.recordingCallBack) {
- self.recordingCallBack(data);
- }
-}
-/// 输出日志
-- (void)aiMouseAddLog:(NSString *)log {
- if (self.aiMouseAddLogCallBack) {
- self.aiMouseAddLogCallBack(log);
- }
-}
-
-// 连接状态改变
-- (void)tlwMouseConnectStateDidChange:(BOOL)connected{
- [self showLog:[NSString stringWithFormat:@"(BleManager) aiMouseConnectStateDidChange - 设备连接状态返回: %hhd",connected]];
-
- if (self.aiMouseConnectStateDidChangeCallBack) {
- self.aiMouseConnectStateDidChangeCallBack(connected);
- }
- if (connected == true) {
- self.authCallBack(true);
- }
- //没有连接
- if (!connected) {
- self.connectPeripheral = nil;
- self.deviceInfoCha = nil;
- self.aiCha = nil;
+ self.receiveInfoDataCallBack(data);
}
}
#pragma mark - public
-- (void)connectBleDeviceWithName:(NSString *)bleName {
+- (void)startScanWithName:(NSString *)bleName {
//如果是已连接或者正在连接,不需要在链接了
- if (self.connectPeripheral != nil ) {
- if ([self.connectPeripheral.name isEqualToString:bleName]) {
- if (self.connectPeripheral.state == CBPeripheralStateConnected || self.connectPeripheral.state == CBPeripheralStateConnecting) {
+ if (self.crrentPeripheral != nil ) {
+ if ([self.crrentPeripheral.name isEqualToString:bleName]) {
+ if (self.crrentPeripheral.state == CBPeripheralStateConnected || self.crrentPeripheral.state == CBPeripheralStateConnecting) {
return;
}
}
else {
- [self.centralManager cancelPeripheralConnection:self.connectPeripheral];
+ [self.centralManager cancelPeripheralConnection:self.crrentPeripheral];
}
}
- [self showLog:[NSString stringWithFormat:@"(BleManager) connectBleDeviceWithName:%@",bleName]];
-// [self stopScanDevice];
self.targetBleName = bleName;
- [self startScanDevice];
-
-// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(15 * NSEC_PER_SEC)), dispatch_get_main_queue(), _block);
-}
-/// 连接设备
-- (void)startScanDevice{
- [self showLog:[NSString stringWithFormat:@"(BleManager) startScanDevice:开始扫描"]];
- [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO]}];
+ NSArray<CBPeripheral *> *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
+ if (devices.count > 0 && [devices[0].name isEqualToString:bleName]) {
+ [self showLog:[NSString stringWithFormat:@"autoConnectDevice:匹配过的设备%@",devices[0].name]];
+ [self connectPeripheral:devices[0]];
+ }
+ else{
+ [self showLog:[NSString stringWithFormat:@"开始扫描 设备名称 %@",bleName]];
+ [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO]}];
+ }
}
-/// 扫描设备
-- (void)stopScanDevice{
- [self showLog:[NSString stringWithFormat:@"(BleManager) stopScanDevice:停止扫描"]];
+
+- (void)stopScan{
+ [self showLog:[NSString stringWithFormat:@"ble:停止扫描"]];
[self.centralManager stopScan];
}
/// 连接设备
- (void)connectPeripheral:(CBPeripheral *)peripheral{
- //peripheral设备已经链接
- if (self.connectPeripheral == peripheral && (self.connectPeripheral.state == CBPeripheralStateConnected || self.connectPeripheral.state == CBPeripheralStateConnecting)) {
- return;
- }
-
-
- [self showLog:[NSString stringWithFormat:@"(BleManager) connectPeripheral:连接设备"]];
- self.connectPeripheral = peripheral;
+ [self showLog:[NSString stringWithFormat:@"connectPeripheral:连接设备"]];
+ self.crrentPeripheral = peripheral;
[self.centralManager connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey : [NSNumber numberWithBool:YES]}];
}
-/// 获取设备信息
-- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{
- [self showLog:[NSString stringWithFormat:@"(BleManager) getDeviceInfo:获取设备信息"]];
- [[TlwMouse shared] getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
- AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
- info.battery_power = [NSString stringWithFormat:@"%d",deviceInfo.batteryValue] ;
- info.CPI = [NSString stringWithFormat:@"%d",deviceInfo.DPI];
- info.CPI_list = @"1,2,3,4";
- info.version = [NSString stringWithFormat:@"%d",deviceInfo.version];
- info.brand = @"NNMouse";
- info.sn = @"";
- info.mac = @"";
- completation(info,nil);
-// @property (nonatomic, assign) int DPI;/// DPI值 数值1 ~ 4 (分别对应 800 1200 1800 2400)
-// @property (nonatomic, assign) int version;///软件版本
-// @property (nonatomic, assign) int batteryState;/// 电池状态
-// @property (nonatomic, assign) int batteryValue;/// 电池百分百电量,0-100
-// ///
-// @property (nonatomic, strong) NSString *battery_power;/// 电池百分百电量,0-100
-// @property (nonatomic, strong) NSString *CPI;/// CPI值
-// @property (nonatomic, strong) NSString *CPI_list;/// 可设置的CPI参数列表
-// @property (nonatomic, strong) NSString *version;///软件版本
-// @property (nonatomic, strong) NSString *brand;/// 品牌名称
-// @property (nonatomic, strong) NSString *sn;/// 设备序列号
-// @property (nonatomic, strong) NSString *mac;///设备MAC地址
- }];
-}
-
-/// 获取信号强度
-- (void)getRSSI:(void (^)(NSString *value,NSError *error))complete {
- [self showLog:@"不支持该接口接口"];
-
-}
-
-#pragma mark - other
-//自动连接,获取已配对的蓝牙,取第一个连接
-- (void)autoConnectDevice{
-// [self showLog:[NSString stringWithFormat:@"(BleManager) autoConnectDevice:开始自动重连设备"]];
- //如果是已连接或者正在连接,则不再重连
- if (self.connectPeripheral && (self.connectPeripheral.state == CBPeripheralStateConnected || self.connectPeripheral.state == CBPeripheralStateConnecting)) {
+-(void)writeToDevice:(NSData *)data{
+ if (self.crrentPeripheral ==nil) {
+ [self showLog:@"peripheral 为空"];
return;
}
- NSArray<CBPeripheral *> *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
- if (devices.count > 0) {
- CBPeripheral *peripheral = devices[0];
- [self showLog:[NSString stringWithFormat:@"(BleManager) autoConnectDevice:匹配过的设备%@",peripheral.name]];
- [self connectPeripheral:peripheral];
+ if (self.deviceInfoCha ==nil) {
+ [self showLog:@"characteristic 为空"];
+ return;
}
-
- // 10s自动重连
- [self performSelector:@selector(autoConnectDevice) withObject:nil afterDelay:10];
+
+ [self.crrentPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithResponse];
}
+
+////自动连接,获取已配对的蓝牙,取第一个连接
+//- (void)autoConnectDevice{
+// //如果是已连接或者正在连接,则不再重连
+// if (self.crrentPeripheral && (self.crrentPeripheral.state == CBPeripheralStateConnected || self.crrentPeripheral.state == CBPeripheralStateConnecting)) {
+// return;
+// }
+// NSArray<CBPeripheral *> *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
+// if (devices.count > 0) {
+// CBPeripheral *peripheral = devices[0];
+// [self showLog:[NSString stringWithFormat:@"autoConnectDevice:匹配过的设备%@",peripheral.name]];
+// [self connectPeripheral:peripheral];
+// }
+//
+// // 10s自动重连
+// [self performSelector:@selector(autoConnectDevice) withObject:nil afterDelay:10];
+//}
- (void)showLog:(NSString *)log{
- NSLog(@"%@",log);
+ if(self.logCallBack)self.logCallBack(log);
}
//将录音数据保存
#import "HidManager.h"
#import "BleManager.h"
#import "TlwMouseSdk.h"
+#import "TimerManager.h"
-@interface DeviceManger()
-
+@interface DeviceManger()<TlwMouseDelegate>
+@property (nonatomic,strong) NSMutableData *recordData;//录音的数据
@property (nonatomic,strong) BleManager *ble;
@property (nonatomic,strong) HidManager *hid;
//connectType 返回为0代表蓝牙,为1代表usb
[self setupHid];
//先默认设置蓝牙管理对象为鼠标
- [[TlwMouse shared] setDelegate:self.ble];
+ [[TlwMouse shared] setDelegate:self];
}
return self;
}
return [TlwMouse shared].connectType;
}
-
-- (NSString *)getCurrentConnectType {
- if ([TlwMouse shared].connectType == AiMouseConnectType_bluetooth) {
- return @"0";
- }
- else {
- return @"1";
- }
-}
-
-#pragma mark ------ 设备连接相关
-- (void)begainMonitorAiMouseConnectStateDidChange:(NSString *)mouseName callBack:(void(^)(int connectType, BOOL connected))callBack{
- self.aiMouseConnectStateDidChangeCallBack = callBack;
- [self.ble connectBleDeviceWithName:mouseName];
-
-}
-
#pragma mark ------ 设备初始化
- (void)setupHid{
self.hid = [HidManager shared];
__weak typeof(self) ws = self;
- self.hid.authCallBack = ^(BOOL isSuccess) {
- if(ws.authCallBack)ws.authCallBack(isSuccess);
- };
-
- self.hid.aiMouseConnectStateDidChangeCallBack = ^(BOOL connected) {
+ self.hid.connectStateCallBack = ^(BOOL connected) {
+ if (connected) {
+ [[TlwMouse shared] switchConnect:AiMouseConnectType_hid isConnected:connected];
+ }
+
+ if(ws.authCallBack && connected)ws.authCallBack(true);
if (ws.aiMouseConnectStateDidChangeCallBack) {
ws.aiMouseConnectStateDidChangeCallBack(AiMouseConnectType_hid,connected);
}
- //连接失败时,重新初始化USB监听
- if (!connected) {
- [ws.hid close];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [ws.hid open];
- });
- }
- };
-
- self.hid.aiMouseSendCmdDataCallBack = ^(NSString * _Nonnull data) {
- if(ws.aiMouseSendCmdDataCallBack){
- ws.aiMouseSendCmdDataCallBack(data);
- }
- };
-
- self.hid.aiMouseSendDeviceInfoDataCallBack = ^(NSData * _Nonnull data) {
- if (ws.aiMouseSendDeviceInfoDataCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.aiMouseSendDeviceInfoDataCallBack(base64String);
- }
- };
- self.hid.begainRecoredCallBack = ^{
- if (ws.begainRecoredCallBack) {
- ws.begainRecoredCallBack();
- }
+
};
-
- self.hid.recordingCallBack = ^(NSData *data) {
- if (ws.recordingCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.recordingCallBack(base64String);
- }
+ self.hid.receiveInfoDataCallBack = ^(NSData *data) {
+ [[TlwMouse shared] sendDeviceDataToSdk:data];
};
-
- self.hid.finishRecoredCallBack = ^(NSData * _Nonnull data) {
- if (ws.finishRecoredCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.finishRecoredCallBack(base64String);
- }
+ self.hid.receiveVoiceDataCallBack = ^(NSData *data) {
+ [[TlwMouse shared] sendAiDataToSdk:data];
};
- self.hid.aiMouseAddLogCallBack = ^(NSString * _Nonnull log) {
+ self.hid.logCallBack = ^(NSString * _Nonnull log) {
+ [ws showLog:log];
if (ws.aiMouseAddLogCallBack) {
ws.aiMouseAddLogCallBack(log);
}
self.ble = [BleManager shared];
__weak typeof(self) ws = self;
- self.ble.authCallBack = ^(BOOL isSuccess) {
- if(ws.authCallBack)ws.authCallBack(isSuccess);
- };
-
- self.ble.aiMouseConnectStateDidChangeCallBack = ^(BOOL connected) {
+ self.ble.connectStateCallBack = ^(BOOL connected) {
+ [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth isConnected:connected];
+
+ if(ws.authCallBack && connected)ws.authCallBack(true);
if (ws.aiMouseConnectStateDidChangeCallBack) {
ws.aiMouseConnectStateDidChangeCallBack(AiMouseConnectType_bluetooth,connected);
}
-
- //蓝牙连接失败,重新初始化USB监听
- if (!connected) {
- [ws.hid close];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [ws.hid open];
- });
- }
- };
-
- self.ble.aiMouseSendCmdDataCallBack = ^(NSString * _Nonnull data) {
- if(ws.aiMouseSendCmdDataCallBack){
- ws.aiMouseSendCmdDataCallBack(data);
- }
};
-
- self.ble.aiMouseSendDeviceInfoDataCallBack = ^(NSData * _Nonnull data) {
- if (ws.aiMouseSendDeviceInfoDataCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.aiMouseSendDeviceInfoDataCallBack(base64String);
- }
- };
-
- self.ble.begainRecoredCallBack = ^{
- if (ws.begainRecoredCallBack) {
- ws.begainRecoredCallBack();
- }
+ self.ble.receiveInfoDataCallBack = ^(NSData *data) {
+ [[TlwMouse shared] sendDeviceDataToSdk:data];
};
-
- self.ble.recordingCallBack = ^(NSData *data) {
- if (ws.recordingCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.recordingCallBack(base64String);
- }
+ self.ble.receiveVoiceDataCallBack = ^(NSData *data) {
+ [[TlwMouse shared] sendAiDataToSdk:data];
};
- self.ble.finishRecoredCallBack = ^(NSData * _Nonnull data) {
- if (ws.finishRecoredCallBack) {
- // 将NSData转换为Base64编码的字符串
- NSString *base64String = [data base64EncodedStringWithOptions:0];
- ws.finishRecoredCallBack(base64String);
- }
- };
-
- self.ble.aiMouseAddLogCallBack = ^(NSString * _Nonnull log) {
+ self.ble.logCallBack = ^(NSString * _Nonnull log) {
+ [ws showLog:log];
if (ws.aiMouseAddLogCallBack) {
ws.aiMouseAddLogCallBack(log);
}
#pragma mark ------ 设备相关接口
+- (NSString *)getCurrentConnectType {
+ if ([TlwMouse shared].connectType == AiMouseConnectType_bluetooth) {
+ return @"0";
+ }
+ else {
+ return @"1";
+ }
+}
+
+- (void)begainMonitorAiMouseConnectStateDidChange:(NSString *)mouseName callBack:(void(^)(int connectType, BOOL connected))callBack{
+ self.aiMouseConnectStateDidChangeCallBack = callBack;
+ [self.ble startScanWithName:mouseName];
+
+ [TimerManager shared].timerCallBack = ^{
+// [self showLog:@"定时器。。。"];
+ if([TlwMouse shared].connected){
+ [self.ble stopScan];
+ [self.hid close];
+ }
+ else{
+ [self.ble startScanWithName:mouseName];
+ [self.hid open];
+ }
+ };
+}
///获取设备信息
- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))completation{
[[TlwMouse shared] getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
info.CPI_list = @"1,2,3,4";
info.version = [NSString stringWithFormat:@"%d",deviceInfo.version];
info.brand = @"NNMouse";
- info.sn = @"";
- info.mac = @"";
+ info.sn = @"MSCL1BKZ12105000042371";
+ info.mac = @"C0310000A583";
completation(info,nil);
}];
}
- (void)closeRecord:(void (^)(BOOL isSuccess,NSError *error))finished{
[[TlwMouse shared] closeRecord:finished];
}
+
+
+
+#pragma mark - TlwMouseDelegate
+/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
+/// - Parameter data: 数据
+-(void)tlwMouseSendDeviceInfoData:(NSData *)data{
+ [self.ble writeToDevice:data];
+ if (self.aiMouseSendDeviceInfoDataCallBack) {
+ // 将NSData转换为Base64编码的字符串
+ NSString *base64String = [data base64EncodedStringWithOptions:0];
+ self.aiMouseSendDeviceInfoDataCallBack(base64String);
+ }
+}
+
+/// 鼠标按键指令回调
+/// - Parameter data: 数据。
+/// 前 单击0x06, 按下0x13(开始录音)抬起0x14(结束录音)
+/// 中 单击0x03, 按下0x11(开始录音)抬起0x12(结束录音)
+/// 后 第一次单击0x01, 第二次单击0x02(结束录音) , 按下0x09(开始录音)抬起0x10(结束录音)
+/// 其他未定义
+///
+/// /// 鼠标按键指令回调 富瑞坤
+/// - Parameter data: 数据。
+/// 前 单击43,按下27(开始录音)抬起28(结束录音)
+/// 中 单击42, 按下25(开始录音)抬起26(结束录音)
+/// 后 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音)
+///
+/// 其他未定义
+- (void)tlwMouseSendCmdData:(NSData *)data{
+ uint8 cmd;
+ [data getBytes:&cmd length:1];
+ if( cmd == 0x01){
+ cmd = 0x31;
+ }else if( cmd == 0x02){
+ cmd = 0x32;
+ }
+ else if( cmd == 0x09){
+ cmd = 0x21;
+ }
+ else if( cmd == 0x10){
+ cmd = 0x22;
+ }
+ else if( cmd == 0x03){
+ cmd = 0x42;
+ }
+ else if( cmd == 0x11){
+ cmd = 0x25;
+ }
+ else if( cmd == 0x12){
+ cmd = 0x26;
+ }
+ else if( cmd == 0x06){
+ cmd = 0x43;
+ }
+ else if( cmd == 0x13){
+ cmd = 0x27;
+ }
+ else if( cmd == 0x14){
+ cmd = 0x28;
+ }
+
+ if (self.aiMouseSendCmdDataCallBack) {
+ self.aiMouseSendCmdDataCallBack([NSString stringWithFormat:@"%X",cmd]);
+ }
+
+ if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){
+ [self showLog:@"(BleManager) aiMouseSendCmdData:开始录音"];
+ self.recordData = [[NSMutableData alloc] init];
+ if (self.begainRecoredCallBack) {
+ self.begainRecoredCallBack();
+ }
+ }
+ else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){
+ [self showLog:@"(BleManager) aiMouseSendCmdData:结束录音"];
+ [self finishRecored:self.recordData];
+ if (self.finishRecoredCallBack) {
+ // 将NSData转换为Base64编码的字符串
+ NSString *base64String = [self.recordData base64EncodedStringWithOptions:0];
+ self.finishRecoredCallBack(base64String);
+ }
+ }
+}
+
+/// 录音回调
+/// - Parameter data: pcm格式语音数据
+- (void)tlwMouseSendRecordData:(NSData *)data{
+ [self.recordData appendData:data];
+ if (self.recordingCallBack) {
+ // 将NSData转换为Base64编码的字符串
+ NSString *base64String = [data base64EncodedStringWithOptions:0];
+ self.recordingCallBack(base64String);
+ }
+}
+/// 输出日志
+- (void)aiMouseAddLog:(NSString *)log {
+ if (self.aiMouseAddLogCallBack) {
+ self.aiMouseAddLogCallBack(log);
+ }
+}
+
+// 连接状态改变
+- (void)tlwMouseConnectStateDidChange:(BOOL)connected{
+ [self showLog:[NSString stringWithFormat:@"(BleManager) aiMouseConnectStateDidChange - 设备连接状态返回: %hhd",connected]];
+
+ if (self.aiMouseConnectStateDidChangeCallBack) {
+ self.aiMouseConnectStateDidChangeCallBack(self.getCurrentConnectType,connected);
+ }
+ if (connected == true) {
+ self.authCallBack(true);
+ }
+}
+
+- (void)showLog:(NSString *)log{
+ NSLog(@"%@",log);
+}
+//将录音数据保存
+- (void)finishRecored:(NSData *)data{
+ NSString *doc = NSTemporaryDirectory();
+ NSString *fullPath = [NSString stringWithFormat:@"%@1.pcm",doc];
+ NSError *err;
+ [data writeToFile:fullPath options:NSDataWritingAtomic error:&err];
+ if (err) {
+ [self showLog:[NSString stringWithFormat:@"录音保存失败 %@",err.description]];
+ }
+ else{
+ [self showLog:[NSString stringWithFormat:@"录音保存成功 path = %@",fullPath]];
+ }
+}
@end
//
#import <Foundation/Foundation.h>
-#import "TlwMouseSdk.h"
-#import "AiMouseSdk.h"
-NS_ASSUME_NONNULL_BEGIN
-
-@interface HidManager : NSObject<TlwMouseDelegate>
-@property (nonatomic,copy)void (^authCallBack)(BOOL isSuccess);/// 鉴权回调
-@property (nonatomic, copy)void (^aiMouseConnectStateDidChangeCallBack)(BOOL connected);/// 设备连接状态回调
-@property (nonatomic, copy)void (^aiMouseSendDeviceInfoDataCallBack)(NSData *data);/// 设备信息数据回调
-@property (nonatomic, copy)void (^aiMouseSendCmdDataCallBack)(NSString *data);/// 鼠标按键指令回调
-@property (nonatomic, copy)void (^begainRecoredCallBack)(void);/// 录音开始回调
-@property (nonatomic, copy)void (^recordingCallBack)(NSData *data);/// 录音进行中回调
-@property (nonatomic, copy)void (^finishRecoredCallBack)(NSData *data);/// 录音结束回调
+NS_ASSUME_NONNULL_BEGIN
-@property (nonatomic, copy)void (^aiMouseAddLogCallBack)(NSString *log);//输出日志
+@interface HidManager : NSObject
+@property (nonatomic, copy)void (^connectStateCallBack)(BOOL connected);/// 设备连接状态回调
+@property (nonatomic, copy)void (^receiveVoiceDataCallBack)(NSData *data);/// 语音数据回调
+@property (nonatomic, copy)void (^receiveInfoDataCallBack)(NSData *data);/// 设备信息数据回调
+@property (nonatomic, copy)void (^logCallBack)(NSString *log);//输出日志
+(HidManager *)shared;
- (void)open;
-- (void)close;
-/// 获取设备信息
-- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))completation;
-/// 获取信号强度
-- (void)getRSSI:(void (^)(NSString *value,NSError *error))complete;
+- (void)close;
+//写入数据
+-(void)writeToDevice:(NSData *)data;
@end
NS_ASSUME_NONNULL_END
#import "HidManager.h"
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
-#import "BleManager.h"
@interface HidManager ()
-{
-
-}
@property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理
@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道
-@property (nonatomic,strong) NSMutableData *recordData;//录音的数据
@end
@implementation HidManager
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
manager = [[HidManager alloc]init];
- [manager open];
});
return manager;
}
return self;
}
-- (void)open{
- //初始化
- self.deviceInfoCha = nil;
-
- [self showLog:@"(HidManager)open:打开设备"];
- self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
- IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
- IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L);
- if (ret != kIOReturnSuccess) {
- [self showLog:(@"(HidManager)open:打开hid失败!")];
- }else{
- [self showLog:(@"(HidManager)open:打开hid成功!")];
- }
- //设置匹配设备
- ////供应商id
- //const long vendorID = 0x6675;
- ////产品id
- //const long productID = 0x8601;
- //供应商id
- const long vendorID = 0x10D6;
- //产品id
- const long productID = 0xB008;
- NSMutableDictionary* dict= [NSMutableDictionary dictionary];
- [dict setValue:[NSNumber numberWithLong:productID] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
- [dict setValue:[NSNumber numberWithLong:vendorID] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
- IOHIDManagerSetDeviceMatching(self.hidManager, (__bridge CFMutableDictionaryRef)dict);
- //设置匹配到设备回调
- IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, &hidAppearDevice, NULL);
- //设置移除设备回调
- IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, &hidDisAppearDevice, NULL);
-}
-
-- (void)close{
- if (self.hidManager == nil) {
- [self showLog:@"(HidManager)close:设备已关闭"];
- return;
- }
- [self showLog:@"(HidManager)close:关闭设备"];
- IOReturn ret = IOHIDManagerClose(self.hidManager, 0);
- self.hidManager = nil;
-
- if (ret != kIOReturnSuccess) {
- [self showLog:(@"(HidManager)close:关闭设备失败!")];
- }else{
- [self showLog:(@"(HidManager)close:关闭设备成功!")];
- }
-
- self.deviceInfoCha = nil;
-}
-
#pragma mark - Hid CallBack
/// 匹配到设备回调
static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
- if ([[BleManager shared] isDidConnectBleDevice]) {
- [[HidManager shared] showLog:(@"(HidManager)hidAppearDevice:当前处于蓝牙连接状态,对监听到有USB 插入 的事件不做处理")];
- return;
- }
-
-
-
- //设备信息
[HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
- [TlwMouse shared].delegate = [HidManager shared];
- //切换当前连接类型
- [[TlwMouse shared] switchConnect:AiMouseConnectType_hid];
-
[[HidManager shared] showLog:(@"(HidManager)hidAppearDevice:回调连接成功 ")];
//注册消息回调
unsigned char InputBuffer[64];
IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL);
-
- [[HidManager shared] openDiveceAction];
-
-}
-- (void)openDiveceAction{
IOReturn result = IOHIDDeviceOpen([HidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
if (result != kIOReturnSuccess) {
- NSLog([NSString stringWithFormat:@"打开hid失败! %d",result]);
- [self performSelector:@selector(openDiveceAction) withObject:nil afterDelay:2];
+ NSLog([NSString stringWithFormat:@"打开设备失败! %d",result]);
}else{
- NSLog(@"打开hid成功!");
+ NSLog(@"打开设备成功!");
+ [HidManager shared].connectStateCallBack(true) ;
}
CFRetain([HidManager shared].deviceInfoCha);
IOHIDDeviceScheduleWithRunLoop([HidManager shared].deviceInfoCha, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
/// 设备移除回调
static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
- if ([[BleManager shared] isDidConnectBleDevice]) {
- [[HidManager shared] showLog:(@"(HidManager)hidDisAppearDevice:当前处于蓝牙连接状态,对监听到有USB 拔出 的事件不做处理")];
- return;
- }
[[HidManager shared] showLog:[NSString stringWithFormat:@"(HidManager)hidDisAppearDevice:拔出设备 %@ ",inIOHIDDeviceRef]];
//取消执行超时操作
[HidManager shared].deviceInfoCha = nil;
- [[HidManager shared] tlwMouseConnectStateDidChange:false];
- [[TlwMouse shared] didDisconnect];
+ [HidManager shared].connectStateCallBack(false) ;
}
NSData *data = [[NSData alloc] initWithBytes:report length:len];
[[HidManager shared] showLog:@"(HidManager)hidReceiveData:device数据"];
- [[TlwMouse shared] sendDeviceDataToSdk:data];
-
-
+ [HidManager shared].receiveInfoDataCallBack(data);
}
-#pragma mark - TlwMouseDelegate
-/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
-/// - Parameter data: 数据
--(void)tlwMouseSendDeviceInfoData:(NSData *)data{
- [self showLog:[NSString stringWithFormat:@"(HidManager)aiMouseSendDeviceInfoData:[send] %@",data]];
- [self sendData:data toDevice:self.deviceInfoCha];
- if (self.aiMouseSendDeviceInfoDataCallBack) {
- self.aiMouseSendDeviceInfoDataCallBack(data);
- }
-}
-/// 鼠标按键指令回调
-/// - Parameter data: 数据。
-/// 前 单击0x06, 按下0x13(开始录音)抬起0x14(结束录音)
-/// 中 单击0x03, 按下0x11(开始录音)抬起0x12(结束录音)
-/// 后 第一次单击0x01, 第二次单击0x02(结束录音) , 按下0x09(开始录音)抬起0x10(结束录音)
-/// 其他未定义
-///
-/// /// 鼠标按键指令回调 富瑞坤
-/// - Parameter data: 数据。
-/// 前 单击43,按下27(开始录音)抬起28(结束录音)
-/// 中 单击42, 按下25(开始录音)抬起26(结束录音)
-/// 后 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音)
-///
-/// 其他未定义
-- (void)tlwMouseSendCmdData:(NSData *)data{
- uint8 cmd;
- [data getBytes:&cmd length:1];
- if( cmd == 0x01){
- cmd = 0x31;
- }else if( cmd == 0x02){
- cmd = 0x32;
- }
- else if( cmd == 0x09){
- cmd = 0x21;
- }
- else if( cmd == 0x10){
- cmd = 0x22;
- }
- else if( cmd == 0x03){
- cmd = 0x42;
- }
- else if( cmd == 0x11){
- cmd = 0x25;
- }
- else if( cmd == 0x12){
- cmd = 0x26;
- }
- else if( cmd == 0x06){
- cmd = 0x43;
- }
- else if( cmd == 0x13){
- cmd = 0x27;
- }
- else if( cmd == 0x14){
- cmd = 0x28;
- }
-
- [self showLog:[NSString stringWithFormat:@"(HidManager) aiMouseSendCmdData:收到指令 = %X",cmd]];
-
- if (self.aiMouseSendCmdDataCallBack) {
- self.aiMouseSendCmdDataCallBack([NSString stringWithFormat:@"%X",cmd]);
- }
-
-
- if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){
- [self showLog:@"(HidManager)aiMouseSendCmdData:开始录音"];
- self.recordData = [[NSMutableData alloc] init];
-
- if (self.begainRecoredCallBack) {
- self.begainRecoredCallBack();
- }
- }
- else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){
- [self showLog:@"(HidManager)aiMouseSendCmdData:结束录音"];
- [self finishRecored:self.recordData];
-
- if (self.finishRecoredCallBack) {
- self.finishRecoredCallBack(self.recordData);
- }
- }
-}
+///// hid数据异常,需要重新开启监听usb设备
+//- (void)hidDataError {
+// //收到数据异常,需要关闭后重新打开
+// [self close];
+// [self open];
+//}
-/// 录音回调
-/// - Parameter data: pcm格式语音数据
-- (void)tlwMouseSendRecordData:(NSData *)data{
- [self showLog:[NSString stringWithFormat:@"(HidManager)aiMouseSendRecordData: %@",data]];
- [self.recordData appendData:data];
- if (self.recordingCallBack) {
- self.recordingCallBack(data);
- }
-}
-/// 输出日志
-- (void)aiMouseAddLog:(NSString *)log {
- if (self.aiMouseAddLogCallBack) {
- self.aiMouseAddLogCallBack(log);
+#pragma mark - public
+- (void)open{
+ //初始化
+ self.deviceInfoCha = nil;
+ self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+ IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L);
+ if (ret != kIOReturnSuccess) {
+ [self showLog:(@"(HidManager)open:打开hid失败!")];
+ }else{
+ [self showLog:(@"(HidManager)open:打开hid成功!")];
}
+ //设置匹配设备
+ ////供应商id
+ //const long vendorID = 0x6675;
+ ////产品id
+ //const long productID = 0x8601;
+ //供应商id
+ const long vendorID = 0x10D6;
+ //产品id
+ const long productID = 0xB008;
+ NSMutableDictionary* dict= [NSMutableDictionary dictionary];
+ [dict setValue:[NSNumber numberWithLong:productID] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
+ [dict setValue:[NSNumber numberWithLong:vendorID] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
+ IOHIDManagerSetDeviceMatching(self.hidManager, (__bridge CFMutableDictionaryRef)dict);
+ //设置匹配到设备回调
+ IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, &hidAppearDevice, NULL);
+ //设置移除设备回调
+ IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, &hidDisAppearDevice, NULL);
}
-// 连接状态改变
-- (void)tlwMouseConnectStateDidChange:(BOOL)connected{
- [self showLog:[NSString stringWithFormat:@"(HidManager) aiMouseConnectStateDidChange - 设备连接状态返回: %hhd",connected]];
-
- if (self.aiMouseConnectStateDidChangeCallBack) {
- self.aiMouseConnectStateDidChangeCallBack(connected);
+- (void)close{
+ if (self.hidManager == nil) {
+ [self showLog:@"(HidManager)close:设备已关闭"];
+ return;
}
- //没有连接
- if (!connected) {
- [HidManager shared].deviceInfoCha = nil;
+ [self showLog:@"(HidManager)close:关闭设备"];
+ IOReturn ret = IOHIDManagerClose(self.hidManager, 0);
+ self.hidManager = nil;
+
+ if (ret != kIOReturnSuccess) {
+ [self showLog:(@"(HidManager)close:关闭设备失败!")];
+ }else{
+ [self showLog:(@"(HidManager)close:关闭设备成功!")];
}
+ self.deviceInfoCha = nil;
}
-
-/// hid数据异常,需要重新开启监听usb设备
-- (void)hidDataError {
- //收到数据异常,需要关闭后重新打开
- [self close];
- [self open];
-}
-
-#pragma mark - public
-/// 获取设备信息
-- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{
- [self showLog:@"(HidManager)getDeviceInfo: 获取设备信息"];
- [[TlwMouse shared] getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
- AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
- info.battery_power = [NSString stringWithFormat:@"%d",deviceInfo.batteryValue] ;
- info.CPI = [NSString stringWithFormat:@"%d",deviceInfo.DPI];
- info.CPI_list = @"1,2,3,4";
- info.version = [NSString stringWithFormat:@"%d",deviceInfo.version];
- info.brand = @"NNMouse";
- info.sn = @"";
- info.mac = @"";
- completation(info,nil);
- }];
-}
-
-/// 获取信号强度
-- (void)getRSSI:(void (^)(NSString *value,NSError *error))finished {
- [self showLog:[NSString stringWithFormat:@"(HidManager) getRSSI:获取信号强度"]];
- finished(0,[NSError errorWithDomain:@"AiMouse SDK Error" code:AiMouseErrorCode_unknown userInfo:@{@"NSLocalizedDescriptionKey":@"请求失败"}]);
-}
-
/// 发送数据给设备
--(void)sendData:(NSData *)data toDevice:(IOHIDDeviceRef)device{
- if(device == nil){
+-(void)writeToDevice:(NSData *)data{
+ if(self.deviceInfoCha == nil){
[self showLog:@"(HidManager)sendData: 请先连上设备"];
return;
}
- IOReturn ret = IOHIDDeviceSetReport(device, kIOHIDReportTypeOutput, 0, data.bytes, data.length);
+ IOReturn ret = IOHIDDeviceSetReport(self.deviceInfoCha, kIOHIDReportTypeOutput, 0, data.bytes, data.length);
if (ret != kIOReturnSuccess) {
[self showLog:[NSString stringWithFormat:@"(HidManager)sendData: 发送失败! code = %d",ret]];
}else{
[self showLog:@"(HidManager)sendData: 发送成功!"];
}
}
-//将录音数据保存
-- (void)finishRecored:(NSData *)data{
-// NSString *doc = NSTemporaryDirectory();
-// NSString *fullPath = [NSString stringWithFormat:@"%@1.pcm",doc];
-// NSError *err;
-// [data writeToFile:fullPath options:NSDataWritingAtomic error:&err];
-// if (err) {
-// [self showLog:[NSString stringWithFormat:@"录音保存失败 %@",err.description]];
-// }
-// else{
-// [self showLog:[NSString stringWithFormat:@"录音保存成功 path = %@",fullPath]];
-// }
-}
+
- (void)showLog:(NSString *)log{
NSLog(@"%@",log);
--- /dev/null
+//
+// TimerManager.h
+// MouseSdk
+//
+// Created by incar on 2024/8/24.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface TimerManager : NSObject
+@property (nonatomic, copy)void (^timerCallBack)(void);
+///单例
++(TimerManager *)shared;
+@end
+
+NS_ASSUME_NONNULL_END
--- /dev/null
+//
+// TimerManager.m
+// MouseSdk
+//
+// Created by incar on 2024/8/24.
+//
+
+#import "TimerManager.h"
+
+@interface TimerManager()
+
+@property (nonatomic, strong) NSTimer *timer;
+
+@end
+
+@implementation TimerManager
+
++(TimerManager *)shared{
+ static TimerManager *manager = nil;
+ static dispatch_once_t oncePredicate;
+ dispatch_once(&oncePredicate, ^{
+ manager = [[TimerManager alloc]init];
+ [manager addSendTimer];
+ });
+ return manager;
+}
+
+#pragma mark - timer
+- (void)addSendTimer{
+ dispatch_async(dispatch_queue_create("timeoutQueue", DISPATCH_QUEUE_SERIAL), ^{
+ self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
+ [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
+ [[NSRunLoop currentRunLoop] run];
+ });
+}
+
+- (void)timerAction{
+ if(self.timerCallBack) self.timerCallBack();
+}
+
+
+@end
BleManager *manager = [BleManager shared];
__weak typeof(self) weakSelf= self;
__weak typeof(BleManager) *weakManager = manager;
- manager.discoverDevice = ^(CBPeripheral *peripheral){
- if ([weakSelf.scanArray containsObject:peripheral]){
- return;
- }
- if(peripheral.name.length == 0){
- return;
- }
- [weakSelf.scanArray addObject:peripheral];
- [weakSelf.tableView reloadData];
- };
- manager.didConnectDevice = ^(CBPeripheral * _Nonnull peripheral) {
- [weakSelf connectSuccess];
- };
- [manager startScanDevice];
+// manager.discoverDevice = ^(CBPeripheral *peripheral){
+// if ([weakSelf.scanArray containsObject:peripheral]){
+// return;
+// }
+// if(peripheral.name.length == 0){
+// return;
+// }
+// [weakSelf.scanArray addObject:peripheral];
+// [weakSelf.tableView reloadData];
+// };
+// manager.didConnectDevice = ^(CBPeripheral * _Nonnull peripheral) {
+// [weakSelf connectSuccess];
+// };
+// [manager startScanDevice];
}
- (void)tapDevice:(CBPeripheral *)peripheral{
- [[BleManager shared] connectPeripheral:peripheral];
+// [[BleManager shared] connectPeripheral:peripheral];
}
- (void)connectSuccess{
- [[BleManager shared] stopScanDevice];
+// [[BleManager shared] stopScanDevice];
dispatch_async(dispatch_get_main_queue(), ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"确定"];
//切换代理
[TlwMouse shared].delegate = self;
//切换当前连接类型
- [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth];
+// [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth];
}
}
}
}
- (void)switchConnect:(AiMouseConnectType)type{
- [[TlwMouse shared] switchConnect:type];
+ [[TlwMouse shared] switchConnect:type isConnected:true];
if ([TlwMouse shared].connectType == AiMouseConnectType_bluetooth) {
[self setupBle];
- (void)bleDidConnect:(NSNotification *)notification{
if(self.connectStateCallBack)self.connectStateCallBack(AiMouseConnectType_bluetooth,true);
+ [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth isConnected:true];
}
- (void)bleDidDisconnect:(NSNotification *)notification{
if(self.connectStateCallBack)self.connectStateCallBack(AiMouseConnectType_bluetooth,false);
- [[TlwMouse shared] switchConnect:AiMouseConnectType_hid];
+ [[TlwMouse shared] switchConnect:AiMouseConnectType_bluetooth isConnected:false];
}
@end
//设置代理
[TlwMouse shared].delegate = self;
//切换当前连接类型
- [[TlwMouse shared] switchConnect:AiMouseConnectType_hid];
+// [[TlwMouse shared] switchConnect:AiMouseConnectType_hid];
}
/// 发送数据给设备