You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
8.6 KiB

2 years ago
//
// BabyPeripheralManager.m
// BluetoothStubOnIOS
//
// Created by 刘彦玮 on 15/12/12.
// Copyright © 2015年 刘彦玮. All rights reserved.
//
#import "BabyPeripheralManager.h"
#import "BabyDefine.h"
#define callbackBlock(...) if ([[babySpeaker callback] __VA_ARGS__]) [[babySpeaker callback] __VA_ARGS__ ]
@implementation BabyPeripheralManager {
int PERIPHERAL_MANAGER_INIT_WAIT_TIMES;
int didAddServices;
NSTimer *addServiceTask;
}
- (instancetype)init {
self = [super init];
if (self) {
_localName = @"baby-default-name";
_peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil options:nil];
}
return self;
}
- (BabyPeripheralManager *(^)())startAdvertising {
return ^BabyPeripheralManager *() {
if ([self canStartAdvertising]) {
PERIPHERAL_MANAGER_INIT_WAIT_TIMES = 0;
NSMutableArray *UUIDS = [NSMutableArray array];
for (CBMutableService *s in _services) {
[UUIDS addObject:s.UUID];
}
//启动广播
[_peripheralManager startAdvertising:
@{
CBAdvertisementDataServiceUUIDsKey : UUIDS
,CBAdvertisementDataLocalNameKey : _localName
}];
}
else {
PERIPHERAL_MANAGER_INIT_WAIT_TIMES++;
if (PERIPHERAL_MANAGER_INIT_WAIT_TIMES > 5) {
BabyLog(@">>>error: 第%d次等待peripheralManager打开任然失败,请检查蓝牙设备是否可用",PERIPHERAL_MANAGER_INIT_WAIT_TIMES);
}
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
self.startAdvertising();
});
BabyLog(@">>>%d次等待peripheralManager打开",PERIPHERAL_MANAGER_INIT_WAIT_TIMES);
}
return self;
};
}
- (BOOL)canStartAdvertising {
if (_peripheralManager.state != CBPeripheralManagerStatePoweredOn) {
return NO;
}
if (didAddServices != _services.count) {
return NO;
}
return YES;
}
- (BOOL)isPoweredOn {
if (_peripheralManager.state != CBPeripheralManagerStatePoweredOn) {
return NO;
}
return YES;
}
- (BabyPeripheralManager *(^)(NSArray *array))addServices {
return ^BabyPeripheralManager*(NSArray *array) {
_services = [NSMutableArray arrayWithArray:array];
[self addServicesToPeripheral];
return self;
};
}
- (void)addServicesToPeripheral {
if ([self isPoweredOn]) {
for (CBMutableService *s in _services) {
[_peripheralManager addService:s];
}
}
else {
[addServiceTask setFireDate:[NSDate distantPast]];
addServiceTask = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(addServicesToPeripheral) userInfo:nil repeats:NO];
}
}
#pragma mark - peripheralManager delegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
switch (peripheral.state) {
case CBPeripheralManagerStateUnknown:
BabyLog(@">>>CBPeripheralManagerStateUnknown");
break;
case CBPeripheralManagerStateResetting:
BabyLog(@">>>CBPeripheralManagerStateResetting");
break;
case CBPeripheralManagerStateUnsupported:
BabyLog(@">>>CBPeripheralManagerStateUnsupported");
break;
case CBPeripheralManagerStateUnauthorized:
BabyLog(@">>>CBPeripheralManagerStateUnauthorized");
break;
case CBPeripheralManagerStatePoweredOff:
BabyLog(@">>>CBPeripheralManagerStatePoweredOff");
break;
case CBPeripheralManagerStatePoweredOn:
BabyLog(@">>>CBPeripheralManagerStatePoweredOn");
//发送centralManagerDidUpdateState通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"CBPeripheralManagerStatePoweredOn" object:nil];
break;
default:
break;
}
// if([babySpeaker callback] blockOnPeripheralModelDidUpdateState) {
// [currChannel blockOnCancelScan](centralManager);
// }
callbackBlock(blockOnPeripheralModelDidUpdateState)(peripheral);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error {
didAddServices++;
callbackBlock(blockOnPeripheralModelDidAddService)(peripheral,service,error);
}
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error {
callbackBlock(blockOnPeripheralModelDidStartAdvertising)(peripheral,error);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
callbackBlock(blockOnPeripheralModelDidReceiveReadRequest)(peripheral, request);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests {
callbackBlock(blockOnPeripheralModelDidReceiveWriteRequests)(peripheral,requests);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
callbackBlock(blockOnPeripheralModelDidSubscribeToCharacteristic)(peripheral,central,characteristic);
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
callbackBlock(blockOnPeripheralModelDidUnSubscribeToCharacteristic)(peripheral,central,characteristic);
}
@end
void makeCharacteristicToService(CBMutableService *service,NSString *UUID,NSString *properties,NSString *descriptor) {
//paramter for properties
CBCharacteristicProperties prop = 0x00;
if ([properties containsString:@"r"]) {
prop = prop | CBCharacteristicPropertyRead;
}
if ([properties containsString:@"w"]) {
prop = prop | CBCharacteristicPropertyWrite;
}
if ([properties containsString:@"n"]) {
prop = prop | CBCharacteristicPropertyNotify;
}
if (properties == nil || [properties isEqualToString:@""]) {
prop = CBCharacteristicPropertyRead | CBCharacteristicPropertyWrite;
}
CBMutableCharacteristic *c = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:UUID] properties:prop value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable];
//paramter for descriptor
if (!(descriptor == nil || [descriptor isEqualToString:@""])) {
//c设置description对应的haracteristics字段描述
CBUUID *CBUUIDCharacteristicUserDescriptionStringUUID = [CBUUID UUIDWithString:CBUUIDCharacteristicUserDescriptionString];
CBMutableDescriptor *desc = [[CBMutableDescriptor alloc]initWithType: CBUUIDCharacteristicUserDescriptionStringUUID value:descriptor];
[c setDescriptors:@[desc]];
}
if (!service.characteristics) {
service.characteristics = @[];
}
NSMutableArray *cs = [service.characteristics mutableCopy];
[cs addObject:c];
service.characteristics = [cs copy];
}
void makeStaticCharacteristicToService(CBMutableService *service,NSString *UUID,NSString *descriptor,NSData *data) {
CBMutableCharacteristic *c = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:UUID] properties:CBCharacteristicPropertyRead value:data permissions:CBAttributePermissionsReadable];
//paramter for descriptor
if (!(descriptor == nil || [descriptor isEqualToString:@""])) {
//c设置description对应的haracteristics字段描述
CBUUID *CBUUIDCharacteristicUserDescriptionStringUUID = [CBUUID UUIDWithString:CBUUIDCharacteristicUserDescriptionString];
CBMutableDescriptor *desc = [[CBMutableDescriptor alloc]initWithType: CBUUIDCharacteristicUserDescriptionStringUUID value:descriptor];
[c setDescriptors:@[desc]];
}
if (!service.characteristics) {
service.characteristics = @[];
}
NSMutableArray *cs = [service.characteristics mutableCopy];
[cs addObject:c];
service.characteristics = [cs copy];
}
CBMutableService* makeCBService(NSString *UUID)
{
CBMutableService *s = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:UUID] primary:YES];
return s;
}
NSString * genUUID()
{
CFUUIDRef uuid_ref = CFUUIDCreate(NULL);
CFStringRef uuid_string_ref= CFUUIDCreateString(NULL, uuid_ref);
CFRelease(uuid_ref);
NSString *uuid = [NSString stringWithString:(__bridge NSString*)uuid_string_ref];
CFRelease(uuid_string_ref);
return uuid;
}