简介:

  很早前就像总结一下手机通过蓝牙连接外设的知识点,但是由于项目比较急,也没有时间去总结。今天刚好看到一篇别人的博客,我就结合的总结了一下。

实现的流程

  1. 建立中心角色

  2. 扫描外设(discover)

  3. 连接外设(connect)

  4. 扫描外设中的服务和特征(discover)

- 4.1 获取外设的services

- 4.2 获取外设的Characteristics,获取Characteristics的值,获取Characteristics的Descriptor和Descriptor的值

5. 与外设做数据交互(explore and interact)

6. 订阅Characteristic的通知

7.断开连接(disconnect)

8.模拟器蓝牙调试,慎用,最好还是用真机去调试。

代码实现:

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>#define MyPeripheralName @"MyPeripheralName"
#define MySUUID @"XXXX"
#define MyCUUID @"XXXX"#define kNotificationConnected @"kNotificationConnected"
#define kNotificationDisconnected @"kNotificationDisconnected"typedef enum _EN_Command_Type
{EN_Command_Invalid = -1,EN_Command_Start = 0x0,EN_Command_Mode1 = 0x1,EN_Command_Mode2,EN_Command_Mode3,EN_Command_Mode4,EN_Command_Mode5,EN_Command_Mode6,EN_Command_Mode7,EN_Command_Mode8,EN_Command_Mode9,EN_Command_Stop,EN_Command_Shutdown,//关机
}EN_CommandType;@interface MSBluetoothManager : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>@property (nonatomic,assign)BOOL bluetoothPowerOn;/***  单例方法**  @return 单例*/
+(MSBluetoothManager*)shareInstance;/***  开始扫描*/
-(void)startScan;/***  停止扫描*/
-(void)stopScan;/***  连接*/
-(void)startconnect;/***  取消连接*/
-(void)cancelConnect;/***  向设备写数据*/
-(BOOL)writeData:(NSData*)data;/***  是否可以准备好写数据**  @return 是否可以准备好写数据*/
-(BOOL)isReady;/***  发送命令**  @param command 命令内容**  @return 是否发送成功*/
-(BOOL)sendCommand:(EN_CommandType)command;@end

View Code

由于代理方法比较多,我就不一一做介绍 了

#import "MSBluetoothManager.h"
#import "TKAlertCenter.h"
#define SCACN_INTERVALS 1.5@interface MSBluetoothManager()
@property BOOL cbReady;
@property (nonatomic,strong) CBCentralManager *cbCM;
@property (strong,nonatomic) NSMutableArray *nDevices;
@property (strong,nonatomic) NSMutableArray *nServices;
@property (strong,nonatomic) NSMutableArray *nCharacteristics;@property (strong,nonatomic) CBPeripheral *cbPeripheral;
@property (strong,nonatomic) CBService *cbServices;
@property (strong,nonatomic) CBCharacteristic *cbCharacteristcs;@end@implementation MSBluetoothManager+(MSBluetoothManager*)shareInstance
{static dispatch_once_t pred = 0;__strong static MSBluetoothManager *_sharedObject = nil;dispatch_once(&pred, ^{_sharedObject = [[self alloc] init]; // or some other init method
    });return _sharedObject;
}#pragma mark -对外接口
/***  开始扫描*/
-(void)startScan
{if(_bluetoothPowerOn){if( !_cbReady   ){[self updateLog:@"Scan for Peripheral..."];[_cbCM scanForPeripheralsWithServices:nil options:nil];//        [self performSelector:@selector(startScan) withObject:nil afterDelay:SCACN_INTERVALS];
        }}else{//弹框提示,请去系统中打开蓝牙[[TKAlertCenter defaultCenter]postAlertWithMessage:NSLocalizedString(@"Please open the Bluetooth on system settings", @"请到系统设置中打开蓝牙")];}}/***  停止扫描*/
-(void)stopScan
{[self updateLog:@"stop scan..."];[_cbCM stopScan];[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startScan) object:nil];
}/***  连接*/
-(void)startconnect
{if (_cbReady ==false){[self.cbCM connectPeripheral:_cbPeripheral options:nil];}
}/***  取消连接*/
-(void)cancelConnect
{if(_cbReady){[_cbCM cancelPeripheralConnection:_cbPeripheral];}}/***  向设备写数据*/
-(BOOL)writeData:(NSData*)data
{BOOL ret = NO;if([data length] >0){[self writeCharacteristic:_cbPeripheral sUUID:MySUUID cUUID:MyCUUID data:data];ret = YES;}return ret;
}/***  是否可以准备好写数据**  @return 是否可以准备好写数据*/
-(BOOL)isReady
{return _cbReady;
}/***  发送命令**  @param command 命令内容**  @return 是否发送成功*/
-(BOOL)sendCommand:(EN_CommandType)command
{NSLog(@"begin send command:%d",command);BOOL ret  = NO;if([self isReady]){unsigned char data [6]= {0};data[0] = 0xa5;*(data+1) = 0x01;*(data+2) = 0x01;switch (command) {case EN_Command_Start:{}break;case EN_Command_Stop:{command = 0x00;}break;case EN_Command_Mode1:break;case EN_Command_Mode2:break;case EN_Command_Mode3:break;case EN_Command_Mode4:case EN_Command_Mode5:case EN_Command_Mode6:case EN_Command_Mode7:case EN_Command_Mode8:case EN_Command_Mode9:{
//                datastr = [NSString stringWithFormat:@"%d",command];
            }break;case EN_Command_Shutdown:{command = 0x5a;}default:break;}NSLog(@"send command:%d",command);*(data+3) = command;//        datastr = @"1234567890";//        NSNumber* num = @(0x01);//        NSData* data = [datastr dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
        do_crc(data,6);//        char a[10]= {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2};NSData *nsdata = [NSData dataWithBytes:data length: sizeof(char)*6];NSLog(@"send data: %@",nsdata);//真正发送命令ret = [self writeData:nsdata];}return ret;
}#pragma mark -CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{switch (central.state) {case CBCentralManagerStatePoweredOff:[self updateLog:@"CoreBluetooth BLE hardware is Powered off"];//对外抛出断开连接的通知[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDisconnected object:nil];_cbReady = FALSE;_bluetoothPowerOn = FALSE;break;case CBCentralManagerStatePoweredOn:[self updateLog:@"CoreBluetooth BLE hardware is Powered on and ready"];_bluetoothPowerOn = YES;break;//cbReady = true;case CBCentralManagerStateResetting:
//            _cbReady = FALSE;[self updateLog:@"CoreBluetooth BLE hardware is resetting"];break;case CBCentralManagerStateUnauthorized:[self updateLog:@"CoreBluetooth BLE state is unauthorized"];
//            _cbReady = FALSE;break;case CBCentralManagerStateUnknown:[self updateLog:@"CoreBluetooth BLE state is unknown"];break;case CBCentralManagerStateUnsupported:
//            _cbReady = FALSE;[self updateLog:@"CoreBluetooth BLE hardware is unsupported on this platform"];break;default:break;}
}//已发现从机设备
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {[self updateLog:[NSString stringWithFormat:@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.identifier, advertisementData]];BOOL replace = NO;// Match if we have this device from beforefor (int ii=0; ii < _nDevices.count; ii++) {CBPeripheral *p = [_nDevices objectAtIndex:ii];if ([p isEqual:peripheral]) {[_nDevices replaceObjectAtIndex:ii withObject:peripheral];replace = YES;}}if (!replace) {if ([peripheral.name isEqualToString:MyPeripheralName]) {[_nDevices addObject:peripheral];[self updateLog:@"has found MyPeripheralName!\r\n"];_cbPeripheral = peripheral;}}if(_cbPeripheral ){//开始连接
        [self startconnect];}
}//已链接到从机
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {//取消重连[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startScan) object:nil];[self updateLog:[NSString stringWithFormat:@"Connection successfull to peripheral: %@ with UUID: %@",peripheral,peripheral.identifier]];//Do somenthing after successfull connection.//发现services//设置peripheral的delegate未self非常重要,否则,didDiscoverServices无法回调peripheral.delegate = self;[_cbPeripheral discoverServices:nil];_cbReady = true;[self updateLog:@"didConnectPeripheral"];//对外抛出连接的通知[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationConnected object:nil];//统计[AVAnalytics event:@"ConnectToHardWare"];}//已断开从机的链接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {[self updateLog:[NSString stringWithFormat:@"Disconnected from peripheral: %@ with UUID: %@",peripheral,peripheral.identifier]];//Do something when a peripheral is disconnected._cbReady = false;//对外抛出断开连接的通知[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDisconnected object:nil];//统计[AVAnalytics event:@"DisconnectToHardWare"];//尝试重连dispatch_async(dispatch_get_main_queue(), ^{[self startScan];});
}- (void) centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals {[self updateLog:[NSString stringWithFormat:@"Currently connected peripherals :"]];int i = 0;for(CBPeripheral *peripheral in peripherals) {[self updateLog:[NSString stringWithFormat:@"[%d] - peripheral : %@ with UUID : %@",i,peripheral,peripheral.identifier]];i++;//Do something on each connected peripheral.
    }}- (void) centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals {[self updateLog:[NSString stringWithFormat:@"Currently known peripherals :"]];int i = 0;for(CBPeripheral *peripheral in peripherals) {[self updateLog:[NSString stringWithFormat:@"[%d] - peripheral : %@ with UUID : %@",i,peripheral,peripheral.identifier]];i++;//Do something on each known peripheral.
    }
}//delegate of CBPeripheral
//已搜索到services
-(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{[self updateLog:@"Found Services."];int i=0;for (CBService *s in peripheral.services) {[self.nServices addObject:s];}for (CBService *s in peripheral.services) {[self updateLog:[NSString stringWithFormat:@"%d :Service UUID: %@(%@)",i,s.UUID.data,s.UUID]];i++;[peripheral discoverCharacteristics:nil forService:s];}
}#pragma mark -CBPeripheralDelegate
//
////已读到char
//-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//    if (error) {
//        return;
//    }
//    unsigned char data[characteristic.value.length];
//    [characteristic.value getBytes:&data];
//
//
//}//已搜索到Characteristics
-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{[self updateLog:[NSString stringWithFormat:@"Found Characteristics in Service:%@ (%@)",service.UUID.data ,service.UUID]];for (CBCharacteristic *c in service.characteristics) {[self updateLog:[NSString stringWithFormat:@"Characteristic UUID: %@ (%@)",c.UUID.data,c.UUID]];[_nCharacteristics addObject:c];}
}//已读到char
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{if (error) {return;}unsigned char data[characteristic.value.length];[characteristic.value getBytes:&data];NSDate*date = [NSDate date];NSCalendar*calendar = [NSCalendar currentCalendar];NSDateComponents*comps;comps =[calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit |NSSecondCalendarUnit) fromDate:date];NSInteger hour = [comps hour];NSInteger minute = [comps minute];NSInteger second = [comps second];[self updateLog:[NSString stringWithFormat:@"char update! [%ld:%ld:%ld],char = %d",hour,minute,second,data[0]]];
}#pragma mark -内部函数
-(id)init
{if(self = [super init]){_cbCM = [[CBCentralManager alloc] initWithDelegate:self queue:nil];_cbServices =[[CBService alloc]init];_cbCharacteristcs =[[CBCharacteristic alloc]init];//列表初始化_nDevices = [[NSMutableArray alloc]init];_nServices = [[NSMutableArray alloc]init];_nCharacteristics = [[NSMutableArray alloc]init];_cbReady = FALSE;_bluetoothPowerOn = FALSE;}return self;
}-(void)updateLog:(NSString *)s
{//用回NSLog,NSLog(@"%@",s );
}-(void)writeCharacteristic:(CBPeripheral *)peripheral sUUID:(NSString *)sUUID cUUID:(NSString *)cUUID data:(NSData *)data {// Sends data to BLE peripheral to process HID and send EHIF command to PCfor ( CBService *service in peripheral.services ) {if ([service.UUID isEqual:[CBUUID UUIDWithString:sUUID]]) {for ( CBCharacteristic *characteristic in service.characteristics ) {if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:cUUID]]) {[self updateLog:@"has reached\r\n"];/* EVERYTHING IS FOUND, WRITE characteristic ! */[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];}}}}
}-(void)setNotificationForCharacteristic:(CBPeripheral *)peripheral sUUID:(NSString *)sUUID cUUID:(NSString *)cUUID enable:(BOOL)enable {for ( CBService *service in peripheral.services ) {if ([service.UUID isEqual:[CBUUID UUIDWithString:sUUID]]) {for (CBCharacteristic *characteristic in service.characteristics ) {if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:cUUID]]){/* Everything is found, set notification ! */[peripheral setNotifyValue:enable forCharacteristic:characteristic];}}}}
}- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{[self updateLog:[NSString stringWithFormat:@"%@",error]];}void  do_crc(unsigned char *data,unsigned short int length)
{//此处为加密算法,略去

}@end

View Code

转载于:https://www.cnblogs.com/HJQ2016/p/5790347.html

第二篇、通过蓝牙连接外设相关推荐

  1. B站黑马测试第二篇P204:navicat连接本地tpshop2.0数据库

    一.前置条件 1.下载phpStudy 2.下载TPshop软件 下载地址:点击这里黑马老师的博客后,ctrl+f键搜索关键字:'phpStudy'和'TPshop'下载. 二.环境部署 参考视频:B ...

  2. 第二篇:可靠连接,TCP协议全解析

    文章目录 一.前言 二.TCP报文结构 三.TCP连接(重点:三次握手和四次挥手) 3.1 三次握手建立连接 3.2 四次挥手释放连接 3.3 wireshark演示 四.TCP可靠连接 4.1 序号 ...

  3. 自己动手实现蓝牙MESH应用系列 | 第一篇:蓝牙MESH基础概念介绍

    文章目录 1. 前言 2. 概述 2.1. 蓝牙风格(Flavors) 2.2. mesh网络的动机 2.3. mesh网络中的消息传输方式 2.3.1. 以消息为中心的通信 - 发布/订阅(publ ...

  4. tcp连接多久会自动断开_苹果M1 Mac用户报告蓝牙连接问题:外设经常会断开

    IT之家 11 月 25 日消息 据外媒 AppleInsider 报道,一些新的 M1 MacBook Air.13 英寸 MacBook Pro 和 Mac mini 的用户正面临蓝牙连接问题,并 ...

  5. iOS 蓝牙开发(二)iOS 连接外设的代码实现

    上一篇文章介绍了蓝牙的技术知识,这里我们具体说明一下中心模式的应用场景.主设备(手机去扫描连接外设,发现外设服务和属性,操作服务和属性的应用.一般来说,外设(蓝牙设备,比如智能手环之类的东西),会由硬 ...

  6. 苹果M1 Mac遇到蓝牙连外设连接不稳定经常断开怎么办?

    外媒指出,许多新的 M1 MacBook Air,MacBook Pro 和 Mac mini 用户遇到了蓝牙连接的问题,这对于独立的 Mac mini 来说尤其令人烦恼.问题包括经常与外设断开连接, ...

  7. Noah Mt4跟单系统制作第二篇 Mt4TradeApi连接服务器篇

    Noah Mt4跟单系统制作第二篇 Mt4TradeApi连接服务器篇 using System; using Mt4TradeApi;namespace Demo {class Program{st ...

  8. Android 蓝牙连接 ESC/POS 热敏打印机打印(ESC/POS指令篇)

    上一篇 主要介绍了如何通过蓝牙连接到打印机.这一篇,我们就介绍如何向打印机发送打印指令,来打印字符和图片. =====================2017.05.09 更新============ ...

  9. 杰理之测试盒蓝牙连接提示音使能【篇】

    该配置为1时,则提示音使能.在蓝牙连接成功会测试盒会播放"connected"的提示音,蓝牙断开会播放"disconnected"的提示音.(加载默认配置是为1 ...

最新文章

  1. Dokku和Docker的完美配合
  2. 关于java使用javacomm20-win32实践总结 (转)
  3. oralce之 10046对Hash Join分析
  4. android+note2+分辨率,魅蓝Note2的屏幕尺寸是多少?魅蓝Note2的分辨率是多少?
  5. [UOJ299][CTSC2017] 游戏
  6. window统计文本字节_【NLP】机器如何认识文本 ?NLP中的Tokenization方法总结
  7. Hdu 1794 【二维成段更新】.cpp
  8. 新手程序员必读的十本经典著作
  9. 查看ESP32模组中Flash颗粒以及芯片信息
  10. NetSuite 精益实施的ALV实践
  11. 爱因斯坦的逻辑思维题
  12. 怎么在python提取别的数据了_别再问如何用python提取PDF内容了!
  13. PADS(7)——在PADS Layout一次性添加泪滴
  14. 打瓶颈,破性能,性能大牛教你怎么玩转性能测试
  15. Android 6种加载网络图片的第三方详解
  16. 哪吒之魔童降世视听语言影评_《哪吒之魔童降世》影评4篇
  17. 微服务架构集成RabbitMQ给用户推送消息(发送短信,发送邮件,发送站内信息)
  18. 多分类模型Accuracy, Precision, Recall和F1-score的超级无敌深入探讨
  19. 元宇宙六大技术全景图
  20. AD18为PCB文件添加LOGO图标

热门文章

  1. openresty开发系列25--openresty中使用json模块
  2. vue axios拦截器的封装
  3. 数据结构——树、森林和二叉树之间的转换
  4. 关于fckEditor的功能配置-PHP版
  5. 关于“中国大妈”的用户画像
  6. 记住:用户不是傻*,她是你的老婆大人
  7. PMCAFF老友会,产品圈年度最具份量的聚会
  8. 【随笔】工程师都是性情中人
  9. 20172307 2018-2019-1 《程序设计与数据结构》实验3报告
  10. 初探AngularJS6.x---目录结构说明