ble编程-外设发送数据到中心

一、外设

1.在外设的.h文件中定义如下

 
 1 //周边管理者
 2 
 3 @property (nonatomic , strong) CBPeripheralManager      *peripheralManager;  4  5 // 中心  6  7 @property (nonatomic,strong) CBCentral *central;  8  9 // 特征 10 11 @property (nonatomic , strong) CBMutableCharacteristic *customCharacteristic; 12 13 // 服务 14 15 @property (nonatomic , strong) CBMutableService *customService; 16 17 // 向中心发送的数据 18 19 @property (strong, nonatomic) NSData *dataToSend; 20 21 @property (nonatomic, readwrite) NSInteger sendDataIndex;
 
 

2.然后在.m文件中进行如下操作

2.1在viewDidLoad方法中初始化外设和要发送的数据

1 // 初始化外设
2 self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
3 // 初始化数据 4 self.dataToSend = [@"snadjfkhaw加大困难的是咖啡euijferlfmn ksxncjxznvjeajfrnjadnfjasfndsafnjsadkfnjsa" dataUsingEncoding:NSUTF8StringEncoding];

2.2 Peripheral Manager被创建,状态改变时调用

       CBPeripheralManagerStatePoweredOff 设备关闭状态

       CBPeripheralManagerStateUnauthorized 未授权

       CBPeripheralManagerStateUnsupported 您的设备不支持蓝牙4.0

       CBPeripheralManagerStateResetting 重置状态

       CBPeripheralManagerStateUnknown 未知状态

 
 1 - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
 2 
 3 {  4  5 switch (peripheral.state) {  6  7 case CBPeripheralManagerStatePoweredOn:  8  9 NSLog(@"蓝牙设备已经打开,可以扫描外设"); 10 11  [self setupService]; 12 13 break; 14 15 default: 16 17 NSLog(@"外设改变状态"); 18 19 break; 20 21  } 22 23 } 24 25 - (void)setupService 26 27 { 28 29 //creates the characteristic UUID 30 31 CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID]; 32 33 //create the characteristic 34 35 self.customCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID 36 37  properties:CBCharacteristicPropertyNotify 38 39  value:nil 40 41  permissions:CBAttributePermissionsReadable]; 42 43 //create the service UUID 44 45 CBUUID *servieceUUID = [CBUUID UUIDWithString:kServiceUUID]; 46 47 //creates the service and adds the charecteristic to it 48 49 self.customService = [[CBMutableService alloc] initWithType:servieceUUID primary:YES]; 50 51 //sets the characteristics for this service 52 53  [self.customService setCharacteristics:@[self.customCharacteristic]]; 54 55 // And add it to the peripheral manager 56 57  [self.peripheralManager addService:self.customService]; 58 59 }
 

 2.3 当你执行addService方法后执行如下回调

 
 1 - (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error {
 2     if (error != nil) {  3 NSLog(@"%s,error = %@",__PRETTY_FUNCTION__, error.localizedDescription);  4 } else {  5 //starts advertising the service  6 [self.peripheralManager startAdvertising:@{CBAdvertisementDataLocalNameKey:@"服务门店",  7  CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:kServiceUUID]]}];  8  9  } 10 }
 
 

 2.4 central订阅了characteristic的值,当更新值的时候peripheral会调用

 
 1 - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
 2 {
 3 self.central = central;  4 if (_lastDeviceUUID == central.identifier) {  5 return;  6  }  7 _lastDeviceUUID = central.identifier;  8 self.sendDataIndex = 0;  9  [self sendData]; 10 } 11 12 13 #pragma mark - 向客户端发消息 14 - (void)sendData { 15 16 // 标记是否为最后一次发送 17 static BOOL sendingEOM = NO; 18 // 1. 如果是最后一次发送 19 if (sendingEOM) { 20 // 只发送 "EOM" 表示结束 21 BOOL didSend = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.customCharacteristic onSubscribedCentrals:@[self.central]]; 22 23 // 1.1. 最后一次发送成功 24 if (didSend) { 25 sendingEOM = NO; 26 NSLog(@"Sent: EOM"); 27  } 28 return; 29  } 30 // 2. 不是最后一次发送,且数据为空,则返回 31 if (self.sendDataIndex >= self.dataToSend.length) { 32 return; 33  } 34 // 3. 数据尚未发送完成,继续发送直到完成 35 BOOL didSend = YES; 36 while (didSend) { 37 // 3.1. 计算剩余多大数据量需要发送 38 NSInteger amountToSend = self.dataToSend.length - self.sendDataIndex; 39 // 不能大于20个字节 40 if (amountToSend > NOTIFY_MTU) 41 amountToSend = NOTIFY_MTU; 42 // 3.2. copy出我们想要发送的数据 43 NSData *chunk = [NSData dataWithBytes:self.dataToSend.bytes+self.sendDataIndex length:amountToSend]; 44 // 3.3. 发送 45 didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.customCharacteristic onSubscribedCentrals:@[self.central]]; 46 // 3.4. 如果没有发送成功,重新发送 47 // If it didn't work, drop out and wait for the callback 48 if (!didSend) { 49 NSLog(@"SEND ERROR"); 50 return; 51  } 52 NSString *stringFromData = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding]; 53 NSLog(@"Sent: %@", stringFromData); 54 // 3.5. 发送成功,修改已经发送成功数据index值 55 self.sendDataIndex += amountToSend; 56 // 3.6. 如果是最后一次需要发送 57 if (self.sendDataIndex >= self.dataToSend.length) { 58 // 3.6.1. 把 标识是否为最后一次发送 改为YES 59 sendingEOM = YES; 60 // 3.6.2. 发送 61 BOOL eomSent = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.customCharacteristic onSubscribedCentrals:@[self.central]]; 62 if (eomSent) { 63 // 3.6.3. 发送成功,则我们已经完成这个功能 64 sendingEOM = NO; 65 NSLog(@"Sent: EOM"); 66  } 67 return; 68  } 69  } 70 }
 

 2.5 peripheral再次准备好发送Characteristic值的更新时候调用

1 - (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
2 {
3  [self sendData]; 4 }

 2.6 当central取消订阅characteristic这个特征的值后调用方法

1 - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
2 {
3 NSLog(@"central=%@设备拒绝请求,%s,",central,__PRETTY_FUNCTION__); 4 }
 

 

二、中心

1.在中心的.h文件中定义如下

 
1 /**
2  * 中心角色
3 */ 4 @property (nonatomic , strong) CBCentralManager *centralManager; 5 @property (nonatomic , strong) CBPeripheral *peripheral; 6 @property (nonatomic, strong) CBCharacteristic *character; 7 @property (nonatomic , strong) NSMutableData *data;
 

2.然后在.m文件中进行如下操作

2.1在viewDidLoad方法中初始化中心和要发送的数据

1     //    1.建立中心角色,queue为执行队列,默认为主线程
2     self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
3 // 2.初始化显示控件 4  [self setupUI]; 5 // 3.初始化data 6 _data = [[NSMutableData alloc] init];
 

2.2 CBCentralManagerDelegate代理方法

 回调,返回当前设备蓝牙状态

 
 1 #pragma mark - CBCentralManagerDelegate 
 2 #pragma mark 回调,返回当前设备蓝牙状态
 3 - (void)centralManagerDidUpdateState:(CBCentralManager *)central {  4  5 switch (central.state) {  6 case CBCentralManagerStatePoweredOn:{  7 // 扫描外设(discover)  8 _messageLabel.text = @"蓝牙设备已经打开,可以扫描外设";  9  [self scan]; 10  } 11 break; 12 default: 13 break; 14  } 15 } 16 17 #pragma mark - 扫描外设(discover) 超时停止扫描 18 - (void)scan{ 19 /** 20  * 第一个参数指定了要搜寻的服务,如果传nil,表示搜寻搜所有的服务 21  * 第二个参数指定了CBCentralManagerScanOptionAllowDuplicatesKey为已发现的设备是否重复扫描, 22  * 如果是同一设备不会多次回调。 23 */ 24  [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}]; 25 26 } 27 
 

 发现外设,回调

 
 1 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
 2 
 3     NSLog(@"找到了服务:%@,信号质量:%@",advertisementData,RSSI);  4 self.serviceName = [advertisementData objectForKey:@"kCBAdvDataLocalName"];  5  6 if (self.peripheral != peripheral) {  7 self.peripheral = peripheral;  8 NSLog(@"开始连接blueServer:%@",peripheral);  9  [self.centralManager connectPeripheral:self.peripheral options:nil]; 10  } 11 }
 

 连接失败,回调

1 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
2     NSLog(@"Failed to connect to %@. (%@)", peripheral, [error localizedDescription]); 3  [self cleanup]; 4 }

 连接成功,回调 

 
 1 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
 2     //因为一个peripheral可能不止提供一个service  3 NSLog(@"连接成功,进一步获取peripheral的service");  4  [self.centralManager stopScan];  5  6 // 每过 0.1 秒钟执行一次 readBLEServiceRSSI 方法  7 self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(readBLEServiceRSSI) userInfo:nil repeats:YES];  8  9 [self.data setLength:0]; 10 11 // 设置代理 12 self.peripheral.delegate = self; 13 14 //查询符合条件的外设 15  [self.peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]]; 16 } 17 18 
 

 失去连接,回调

1 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
2     NSLog(@"Failed to connect to %@. (%@)", peripheral, [error localizedDescription]); 3  [self cleanup]; 4 }

 2.3 CBPeripheralDelegate代理方法

  读取到RSSI值后的操作

 

 
1 - (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {
2     NSLog(@"%s,%@",__PRETTY_FUNCTION__,peripheral); 3 int rssi = abs([peripheral.RSSI intValue]); 4 CGFloat ci = (rssi - 49) / (10 * 4.); 5 6 self.messageLabel.text = [NSString stringWithFormat:@"发现BLT4.0热点:%@,距离:%.1fm",self.serviceName,pow(10,ci)]; 7 }
 

  找到我们刚刚指定的服务

 
 1 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
 2     if (error) {  3 NSLog(@"%s,error=%@", __PRETTY_FUNCTION__, error.localizedDescription);  4  [self cleanup];  5 return;  6 } else {  7 for (CBService *service in peripheral.services) {  8 NSLog(@"发现UUID=%@的服务",service.UUID);  9 NSLog(@"开始检测这个服务的特征码..."); 10 if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) { 11  [self.peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kCharacteristicUUID]] forService:service]; 12  } 13  } 14  } 15 }
 

  如果一个特征被检测到,回调

 
 1 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
 2     if (error) {  3 NSLog(@"%s,%@",__PRETTY_FUNCTION__,error);  4  [self cleanup];  5 return;  6 } else {  7 if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {  8 for (CBCharacteristic *characteristic in service.characteristics) {  9 if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) { 10  [peripheral setNotifyValue:YES 11  forCharacteristic:characteristic]; 12 self.character=characteristic; 13  } 14  } 15  } 16  } 17 }
 

  处理蓝牙发过来的数据 

 
 1 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
 2     if (error) {  3 NSLog(@"didUpdateValueForCharacteristic - Error discovering characteristics: %@", [error localizedDescription]);  4 return;  5  }  6 NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];  7 // 如果我们获得了所有的数据  8 if ([stringFromData isEqualToString:@"EOM"]) {  9 // 显示数据 10  [self alarm:self.data]; 11 // 取消订阅 12  [peripheral setNotifyValue:NO forCharacteristic:characteristic]; 13 // 让中心失去和设备的连接 14  [self.centralManager cancelPeripheralConnection:peripheral]; 15  } 16 // 否则,拼接数据 17  [self.data appendData:characteristic.value]; 18 // Log it 19 NSLog(@"Received: %@", stringFromData); 20 }
 

 外围设备是否被注销

 
 1 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
 2     if (error) {  3 NSLog(@"%s,%@",__PRETTY_FUNCTION__,error.localizedDescription);  4  }  5 if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) {  6 return;  7  }  8 //已经发送通知  9 if (characteristic.isNotifying) { 10 NSLog(@"Notification began on %@",characteristic); 11 } else { 12 //Notification has stopped 13 //so disconnect from the peripheral 14 NSLog(@"Notification stopped on %@ Disconnecting",characteristic); 15  [self.centralManager cancelPeripheralConnection:self.peripheral]; 16  } 17 }
 

2.4 出现错误或者结束连接时调用(私有方法)

 
 1 #pragma mark - Call this when things either go wrong, or you're done with the connection.
 2 - (void)cleanup {
 3 // Don't do anything if we're not connected  4 if (!self.peripheral.isConnected) {  5 return;  6  }  7 // See if we are subscribed to a characteristic on the peripheral  8 if (self.peripheral.services != nil) {  9 for (CBService *service in self.peripheral.services) { 10 if (service.characteristics != nil) { 11 for (CBCharacteristic *characteristic in service.characteristics) { 12 if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) { 13 if (characteristic.isNotifying) { 14 // It is notifying, so unsubscribe 15  [self.peripheral setNotifyValue:NO forCharacteristic:characteristic]; 16 // And we're done. 17 return; 18  } 19  } 20  } 21  } 22  } 23  } 24 // If we've got this far, we're connected, but we're not subscribed, so we just disconnect 25  [self.centralManager cancelPeripheralConnection:self.peripheral]; 26 }

转载于:https://www.cnblogs.com/Free-Thinker/p/11213819.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值