BabyCentralManager.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. BabyBluetooth
  3. 简单易用的蓝牙ble库,基于CoreBluetooth 作者:刘彦玮
  4. https://github.com/coolnameismy/BabyBluetooth
  5. */
  6. // Created by 刘彦玮 on 15/7/30.
  7. // Copyright (c) 2015年 刘彦玮. All rights reserved.
  8. //
  9. #import "BabyCentralManager.h"
  10. #import "BabyCallback.h"
  11. @implementation BabyCentralManager
  12. #define currChannel [babySpeaker callbackOnCurrChannel]
  13. - (instancetype)init {
  14. self = [super init];
  15. if (self) {
  16. #if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0
  17. NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  18. //蓝牙power没打开时alert提示框
  19. [NSNumber numberWithBool:YES],CBCentralManagerOptionShowPowerAlertKey,
  20. //重设centralManager恢复的IdentifierKey
  21. @"babyBluetoothRestore",CBCentralManagerOptionRestoreIdentifierKey,
  22. nil];
  23. #else
  24. NSDictionary *options = nil;
  25. #endif
  26. NSArray *backgroundModes = [[[NSBundle mainBundle] infoDictionary]objectForKey:@"UIBackgroundModes"];
  27. if ([backgroundModes containsObject:@"bluetooth-central"]) {
  28. //后台模式
  29. centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil options:options];
  30. }
  31. else {
  32. //非后台模式
  33. centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
  34. }
  35. //pocket
  36. pocket = [[NSMutableDictionary alloc]init];
  37. connectedPeripherals = [[NSMutableArray alloc]init];
  38. discoverPeripherals = [[NSMutableArray alloc]init];
  39. reConnectPeripherals = [[NSMutableArray alloc]init];
  40. }
  41. return self;
  42. }
  43. #pragma mark - 接收到通知
  44. //扫描Peripherals
  45. - (void)scanPeripherals {
  46. [centralManager scanForPeripheralsWithServices:[currChannel babyOptions].scanForPeripheralsWithServices options:[currChannel babyOptions].scanForPeripheralsWithOptions];
  47. }
  48. //连接Peripherals
  49. - (void)connectToPeripheral:(CBPeripheral *)peripheral{
  50. [centralManager connectPeripheral:peripheral options:[currChannel babyOptions].connectPeripheralWithOptions];
  51. }
  52. //断开设备连接
  53. - (void)cancelPeripheralConnection:(CBPeripheral *)peripheral {
  54. [centralManager cancelPeripheralConnection:peripheral];
  55. }
  56. //断开所有已连接的设备
  57. - (void)cancelAllPeripheralsConnection {
  58. for (int i=0;i<connectedPeripherals.count;i++) {
  59. [centralManager cancelPeripheralConnection:connectedPeripherals[i]];
  60. }
  61. }
  62. //停止扫描
  63. - (void)cancelScan {
  64. [centralManager stopScan];
  65. //停止扫描callback
  66. if([currChannel blockOnCancelScan]) {
  67. [currChannel blockOnCancelScan](centralManager);
  68. }
  69. }
  70. #pragma mark - CBCentralManagerDelegate委托方法
  71. - (void)centralManagerDidUpdateState:(CBCentralManager *)central {
  72. //发送通知
  73. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtCentralManagerDidUpdateState object:@{@"central":central}];
  74. switch (central.state) {
  75. case CBCentralManagerStateUnknown:
  76. BabyLog(@">>>CBCentralManagerStateUnknown");
  77. break;
  78. case CBCentralManagerStateResetting:
  79. BabyLog(@">>>CBCentralManagerStateResetting");
  80. break;
  81. case CBCentralManagerStateUnsupported:
  82. BabyLog(@">>>CBCentralManagerStateUnsupported");
  83. break;
  84. case CBCentralManagerStateUnauthorized:
  85. BabyLog(@">>>CBCentralManagerStateUnauthorized");
  86. break;
  87. case CBCentralManagerStatePoweredOff:
  88. BabyLog(@">>>CBCentralManagerStatePoweredOff");
  89. break;
  90. case CBCentralManagerStatePoweredOn:
  91. BabyLog(@">>>CBCentralManagerStatePoweredOn");
  92. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtCentralManagerEnable object:@{@"central":central}];
  93. break;
  94. default:
  95. break;
  96. }
  97. //状态改变callback
  98. if ([currChannel blockOnCentralManagerDidUpdateState]) {
  99. [currChannel blockOnCentralManagerDidUpdateState](central);
  100. }
  101. }
  102. - (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict {
  103. }
  104. //扫描到Peripherals
  105. - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
  106. //日志
  107. //BabyLog(@"当扫描到设备:%@",peripheral.name);
  108. [self addDiscoverPeripheral:peripheral];
  109. //发出通知
  110. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidDiscoverPeripheral
  111. object:@{@"central":central,@"peripheral":peripheral,@"advertisementData":advertisementData,@"RSSI":RSSI}];
  112. //扫描到设备callback
  113. if ([currChannel filterOnDiscoverPeripherals]) {
  114. if ([currChannel filterOnDiscoverPeripherals](peripheral.name,advertisementData,RSSI)) {
  115. if ([currChannel blockOnDiscoverPeripherals]) {
  116. [[babySpeaker callbackOnCurrChannel] blockOnDiscoverPeripherals](central,peripheral,advertisementData,RSSI);
  117. }
  118. }
  119. }
  120. //处理连接设备
  121. if (needConnectPeripheral) {
  122. if ([currChannel filterOnconnectToPeripherals](peripheral.name,advertisementData,RSSI)) {
  123. [centralManager connectPeripheral:peripheral options:[currChannel babyOptions].connectPeripheralWithOptions];
  124. //开一个定时器监控连接超时的情况
  125. connectTimer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(disconnect:) userInfo:peripheral repeats:NO];
  126. }
  127. }
  128. }
  129. //停止扫描
  130. - (void)disconnect:(id)sender {
  131. [centralManager stopScan];
  132. }
  133. //连接到Peripherals-成功
  134. - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
  135. //发出通知
  136. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidConnectPeripheral
  137. object:@{@"central":central,@"peripheral":peripheral}];
  138. //设置委托
  139. [peripheral setDelegate:self];
  140. //BabyLog(@">>>连接到名称为(%@)的设备-成功",peripheral.name);
  141. [connectTimer invalidate];//停止时钟
  142. [self addPeripheral:peripheral];
  143. //执行回叫
  144. //扫描到设备callback
  145. if ([currChannel blockOnConnectedPeripheral]) {
  146. [currChannel blockOnConnectedPeripheral](central,peripheral);
  147. }
  148. //扫描外设的服务
  149. if (needDiscoverServices) {
  150. [peripheral discoverServices:[currChannel babyOptions].discoverWithServices];
  151. //discoverIncludedServices
  152. }
  153. }
  154. //连接到Peripherals-失败
  155. - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
  156. //发出通知
  157. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidFailToConnectPeripheral
  158. object:@{@"central":central,@"peripheral":peripheral,@"error":error?error:@""}];
  159. // BabyLog(@">>>连接到名称为(%@)的设备-失败,原因:%@",[peripheral name],[error localizedDescription]);
  160. if ([currChannel blockOnFailToConnect]) {
  161. [currChannel blockOnFailToConnect](central,peripheral,error);
  162. }
  163. }
  164. //Peripherals断开连接
  165. - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
  166. //发出通知
  167. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidDisconnectPeripheral
  168. object:@{@"central":central,@"peripheral":peripheral,@"error":error?error:@""}];
  169. // BabyLog(@">>>外设连接断开连接 %@: %@\n", [peripheral name], [error localizedDescription]);
  170. if (error)
  171. {
  172. BabyLog(@">>> didDisconnectPeripheral for %@ with error: %@", peripheral.name, [error localizedDescription]);
  173. }
  174. [self deletePeripheral:peripheral];
  175. if ([currChannel blockOnDisconnect]) {
  176. [currChannel blockOnDisconnect](central,peripheral,error);
  177. }
  178. //判断是否全部链接都已经段开,调用blockOnCancelAllPeripheralsConnection委托
  179. if ([self findConnectedPeripherals].count == 0) {
  180. //停止扫描callback
  181. if ([currChannel blockOnCancelAllPeripheralsConnection]) {
  182. [currChannel blockOnCancelAllPeripheralsConnection](centralManager);
  183. }
  184. // BabyLog(@">>> stopConnectAllPerihperals");
  185. }
  186. //检查并重新连接需要重连的设备
  187. if ([reConnectPeripherals containsObject:peripheral]) {
  188. [self connectToPeripheral:peripheral];
  189. }
  190. }
  191. //扫描到服务
  192. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
  193. //发出通知
  194. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidDiscoverServices
  195. object:@{@"peripheral":peripheral,@"error":error?error:@""}];
  196. // BabyLog(@">>>扫描到服务:%@",peripheral.services);
  197. if (error) {
  198. BabyLog(@">>>didDiscoverServices for %@ with error: %@", peripheral.name, [error localizedDescription]);
  199. }
  200. //回叫block
  201. if ([currChannel blockOnDiscoverServices]) {
  202. [currChannel blockOnDiscoverServices](peripheral,error);
  203. }
  204. //discover characteristics
  205. if (needDiscoverCharacteristics) {
  206. for (CBService *service in peripheral.services) {
  207. [peripheral discoverCharacteristics:[currChannel babyOptions].discoverWithCharacteristics forService:service];
  208. }
  209. }
  210. }
  211. //发现服务的Characteristics
  212. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
  213. //发出通知
  214. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidDiscoverCharacteristicsForService
  215. object:@{@"peripheral":peripheral,@"service":service,@"error":error?error:@""}];
  216. if (error) {
  217. BabyLog(@"error didDiscoverCharacteristicsForService for %@ with error: %@", service.UUID, [error localizedDescription]);
  218. // return;
  219. }
  220. //回叫block
  221. if ([currChannel blockOnDiscoverCharacteristics]) {
  222. [currChannel blockOnDiscoverCharacteristics](peripheral,service,error);
  223. }
  224. //如果需要更新Characteristic的值
  225. if (needReadValueForCharacteristic) {
  226. for (CBCharacteristic *characteristic in service.characteristics) {
  227. [peripheral readValueForCharacteristic:characteristic];
  228. //判断读写权限
  229. // if (characteristic.properties & CBCharacteristicPropertyRead ) {
  230. // [peripheral readValueForCharacteristic:characteristic];
  231. // }
  232. }
  233. }
  234. //如果搜索Characteristic的Descriptors
  235. if (needDiscoverDescriptorsForCharacteristic) {
  236. for (CBCharacteristic *characteristic in service.characteristics) {
  237. [peripheral discoverDescriptorsForCharacteristic:characteristic];
  238. }
  239. }
  240. }
  241. //读取Characteristics的值
  242. - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  243. //发出通知
  244. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidUpdateValueForCharacteristic
  245. object:@{@"peripheral":peripheral,@"characteristic":characteristic,@"error":error?error:@""}];
  246. if (error) {
  247. BabyLog(@"error didUpdateValueForCharacteristic %@ with error: %@", characteristic.UUID, [error localizedDescription]);
  248. // return;
  249. }
  250. //查找字段订阅
  251. if ([babySpeaker notifyCallback:characteristic]) {
  252. [babySpeaker notifyCallback:characteristic](peripheral,characteristic,error);
  253. return;
  254. }
  255. //回叫block
  256. if ([currChannel blockOnReadValueForCharacteristic]) {
  257. [currChannel blockOnReadValueForCharacteristic](peripheral,characteristic,error);
  258. }
  259. }
  260. //发现Characteristics的Descriptors
  261. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  262. if (error) {
  263. BabyLog(@"error Discovered DescriptorsForCharacteristic for %@ with error: %@", characteristic.UUID, [error localizedDescription]);
  264. // return;
  265. }
  266. //回叫block
  267. if ([currChannel blockOnDiscoverDescriptorsForCharacteristic]) {
  268. [currChannel blockOnDiscoverDescriptorsForCharacteristic](peripheral,characteristic,error);
  269. }
  270. //如果需要更新Characteristic的Descriptors
  271. if (needReadValueForDescriptors) {
  272. for (CBDescriptor *d in characteristic.descriptors) {
  273. [peripheral readValueForDescriptor:d];
  274. }
  275. }
  276. //执行一次的方法
  277. if (oneReadValueForDescriptors) {
  278. for (CBDescriptor *d in characteristic.descriptors) {
  279. [peripheral readValueForDescriptor:d];
  280. }
  281. oneReadValueForDescriptors = NO;
  282. }
  283. }
  284. //读取Characteristics的Descriptors的值
  285. - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
  286. if (error) {
  287. BabyLog(@"error didUpdateValueForDescriptor for %@ with error: %@", descriptor.UUID, [error localizedDescription]);
  288. // return;
  289. }
  290. //回叫block
  291. if ([currChannel blockOnReadValueForDescriptors]) {
  292. [currChannel blockOnReadValueForDescriptors](peripheral,descriptor,error);
  293. }
  294. }
  295. - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  296. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidWriteValueForCharacteristic object:@{@"characteristic":characteristic,@"error":error?error:@""}];
  297. // BabyLog(@">>>didWriteValueForCharacteristic");
  298. // BabyLog(@">>>uuid:%@,new value:%@",characteristic.UUID,characteristic.value);
  299. if ([currChannel blockOnDidWriteValueForCharacteristic]) {
  300. [currChannel blockOnDidWriteValueForCharacteristic](characteristic,error);
  301. }
  302. }
  303. - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
  304. // BabyLog(@">>>didWriteValueForCharacteristic");
  305. // BabyLog(@">>>uuid:%@,new value:%@",descriptor.UUID,descriptor.value);
  306. if ([currChannel blockOnDidWriteValueForDescriptor]) {
  307. [currChannel blockOnDidWriteValueForDescriptor](descriptor,error);
  308. }
  309. }
  310. //characteristic.isNotifying 状态改变
  311. - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  312. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidUpdateNotificationStateForCharacteristic object:@{@"characteristic":characteristic,@"error":error?error:@""}];
  313. BabyLog(@">>>didUpdateNotificationStateForCharacteristic");
  314. BabyLog(@">>>uuid:%@,isNotifying:%@",characteristic.UUID,characteristic.isNotifying?@"isNotifying":@"Notifying");
  315. if ([currChannel blockOnDidUpdateNotificationStateForCharacteristic]) {
  316. [currChannel blockOnDidUpdateNotificationStateForCharacteristic](characteristic,error);
  317. }
  318. }
  319. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(NSError *)error {
  320. if ([currChannel blockOnDidDiscoverIncludedServicesForService]) {
  321. [currChannel blockOnDidDiscoverIncludedServicesForService](service,error);
  322. }
  323. }
  324. # if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
  325. - (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error {
  326. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidReadRSSI object:@{@"peripheral":peripheral,@"RSSI":peripheral.RSSI,@"error":error?error:@""}];
  327. BabyLog(@">>>peripheralDidUpdateRSSI -> RSSI:%@",peripheral.RSSI);
  328. if ([currChannel blockOnDidReadRSSI]) {
  329. [currChannel blockOnDidReadRSSI](peripheral.RSSI,error);
  330. }
  331. }
  332. #else
  333. - (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
  334. [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidReadRSSI object:@{@"peripheral":peripheral,@"RSSI":RSSI,@"error":error?error:@""}];
  335. BabyLog(@">>>peripheralDidUpdateRSSI -> RSSI:%@",RSSI);
  336. if ([currChannel blockOnDidReadRSSI]) {
  337. [currChannel blockOnDidReadRSSI](RSSI,error);
  338. }
  339. }
  340. #endif
  341. - (void)peripheralDidUpdateName:(CBPeripheral *)peripheral {
  342. if ([currChannel blockOnDidUpdateName]) {
  343. [currChannel blockOnDidUpdateName](peripheral);
  344. }
  345. }
  346. - (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray *)invalidatedServices {
  347. if ([currChannel blockOnDidModifyServices]) {
  348. [currChannel blockOnDidModifyServices](peripheral,invalidatedServices);
  349. }
  350. }
  351. /**
  352. sometimes ever,sometimes never. 相聚有时,后会无期
  353. this is center with peripheral's story
  354. **/
  355. //sometimes ever:添加断开重连接的设备
  356. - (void)sometimes_ever:(CBPeripheral *)peripheral {
  357. if (![reConnectPeripherals containsObject:peripheral]) {
  358. [reConnectPeripherals addObject:peripheral];
  359. }
  360. }
  361. //sometimes never:删除需要重连接的设备
  362. - (void)sometimes_never:(CBPeripheral *)peripheral {
  363. [reConnectPeripherals removeObject:peripheral];
  364. }
  365. #pragma mark - 私有方法
  366. #pragma mark - 设备list管理
  367. - (void)addDiscoverPeripheral:(CBPeripheral *)peripheral{
  368. if (![discoverPeripherals containsObject:peripheral]) {
  369. [discoverPeripherals addObject:peripheral];
  370. }
  371. }
  372. - (void)addPeripheral:(CBPeripheral *)peripheral {
  373. if (![connectedPeripherals containsObject:peripheral]) {
  374. [connectedPeripherals addObject:peripheral];
  375. }
  376. }
  377. - (void)deletePeripheral:(CBPeripheral *)peripheral{
  378. [connectedPeripherals removeObject:peripheral];
  379. }
  380. - (CBPeripheral *)findConnectedPeripheral:(NSString *)peripheralName {
  381. for (CBPeripheral *p in connectedPeripherals) {
  382. if ([p.name isEqualToString:peripheralName]) {
  383. return p;
  384. }
  385. }
  386. return nil;
  387. }
  388. - (NSArray *)findConnectedPeripherals{
  389. return connectedPeripherals;
  390. }
  391. @end