第一:现在项目中导入CoreBluetooth.framework框架。
第二:蓝牙的使用。
在使用的类中导入#import
步骤:
<1>.首先创建和初始化中心设备CBCentralManager。
dispatch_queue_t centralQueue = dispatch_queue_create("定义线程的名字", DISPATCH_QUEUE_SERIAL);
bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSLog(@"[ScanTableViewController] [centralManagerDidUpdateState] state === %ld", (long)central.state);
if (central.state == CBCentralManagerStatePoweredOn) {
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
} else {
NSLog(@"蓝牙没有正常打开");
}
}
<2>.对外围设备进行扫描,显示到扫描结果的页面,并且对蓝牙进行连接。
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
dispatch_async(dispatch_get_main_queue(), ^{
// Add the sensor to the list and reload deta set
ScannedPeripheral* sensor = [ScannedPeripheral initWithPeripheral:peripheral rssi:RSSI.intValue isPeripheralConnected:NO];
if (![peripherals containsObject:sensor]) {
[peripherals addObject:sensor];
} else {
sensor = [peripherals objectAtIndex:[peripherals indexOfObject:sensor]];
sensor.RSSI = RSSI.intValue;
}
});
//然后反应到相应的View中
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"[ScanTableViewController] [didConnectPeripheral]");
isConnectingOneDevice = NO;
[timer invalidate];
CachedBLEDevice* device = [CachedBLEDevice defaultInstance];
if ([[DBRecorder getFMDBDeviceParameters] count]) {
[DBRecorder deleteFMDBDevice:device.mDeviceIdentifier];
}
device.mDeviceName = [peripheral name];
device.mDeviceIdentifier = [[peripheral identifier] UUIDString];
device.mAlertEnabled = false;
device.mRangeAlertEnabled = true;
device.mRangeType = RANGE_ALERT_OUT;
device.mRangeValue = RANGE_ALERT_FAR;
device.mDisconnectEnabled = true;
device.mRingtoneEnabled = true;
device.mVibrationEnabled = true;
device.mConnectionState = CONNECTION_STATE_CONNECTED;
[device setDevicePeripheral:peripheral];
NSLog(@"保存到数据库中的值:%@", [device getDevicePeripheral]);
[device persistData:1];
iSmartWatchConfiguration *configuration = [iSmartWatchConfiguration sharedConfiguration];
configuration.software.paired = YES;
[configuration save];
if (nil != connectingCell) {
[connectingCell showIndicator:NO];
}
MainTabBarViewController *mainTVC = [[MainTabBarViewController alloc] init];
[self.navigationController presentViewController:mainTVC animated:YES completion:NULL];
});
}
<3>.对已经连接的设备发现服务。
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
NSLog(@"[RecordController] [didDiscoverServices]");
if (!error) {
NSLog(@"services discovered %lu",(unsigned long)[peripheral.services count] );
for (CBService *service in peripheral.services) {
NSLog(@"service discovered: %@", service.UUID);
if ([service.UUID isEqual:batteryServiceUUID]) {
NSLog(@"Battery service found");
[self.recordPeripheral discoverCharacteristics:nil forService:service];
} else if ([service.UUID isEqual:dogpServiceUUID]) {
NSLog(@"Dogp service found");
kisfinishFile = 0;
[self.recordPeripheral discoverCharacteristics:nil forService:service];
} else if ([service.UUID isEqual:proximityLinkLossServiceUUID]) {
NSLog(@"Linkloss service is found");
[self.recordPeripheral discoverCharacteristics:nil forService:service];
}
else if ([service.UUID isEqual:proximityImmediateAlertServiceUUID]) {
NSLog(@"Immidiate Alert service is found");
[self.recordPeripheral discoverCharacteristics:nil forService:service];
}
}
} else {
NSLog(@"error in discovering services on device: %@", self.recordPeripheral.name);
}
}
<4>.对服务进行UUID判断,发现相应的特征。
-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
if (!error) {
if ([service.UUID isEqual:dogpServiceUUID]) {
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:dogpReadCharacteristicUUID]) {
NSLog(@"Dogp service read characteristic is found");
[self.recordPeripheral setNotifyValue:YES forCharacteristic:characteristic];
}
if ([characteristic.UUID isEqual:dogpWriteCharacteristicUUID]) {
NSLog(@"Dogp service write characteristic is found");
dogpWriteCharacteristic = characteristic;
}
}
}
<5>.对发现的特征进行判断,进行读取操作。
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if ([characteristic.UUID isEqual:dogpReadCharacteristicUUID]) {
NSLog(@"获取到读的UUID:%@, ---%@",characteristic.UUID, characteristic.value);
NSString *content = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(@"%s", characteristic.value.bytes);
NSLog(@"----> dogp content === %@", content);
if ([content isEqualToString:@"ios indication"]) {
[self.recordPeripheral readValueForCharacteristic:characteristic];
dogpReadCharacteristic = characteristic;
return;
}else{
NSString *hexStr = [self convertDataToHexStr:characteristic.value];
NSLog(@"手表收到的十六进制的数据:%@", hexStr);
}
}
}
<6>.对读取到的数据进行数据处理。
if ([characteristic.UUID isEqual:dogpReadCharacteristicUUID]) {
NSLog(@"获取到读的UUID:%@, ---%@",characteristic.UUID, characteristic.value);
NSString *content = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(@"%s", characteristic.value.bytes);
NSLog(@"----> dogp content === %@", content);
if ([content isEqualToString:@"ios indication"]) {
[self.recordPeripheral readValueForCharacteristic:characteristic];
dogpReadCharacteristic = characteristic;
return;
}else{
NSString *hexStr = [self convertDataToHexStr:characteristic.value];
NSLog(@"手表收到的十六进制的数据:%@", hexStr);
}
}
第三:与手表或者其他蓝牙设备进行通信。
NSInteger length = [hexStr length];
NSString *contentOfDataStr = [hexStr substringWithRange:NSMakeRange(0, length-2)];
NSString *checkStr = [hexStr substringWithRange:NSMakeRange(length-2, 2)];
//check len of data
NSLog(@"除去校验值的值:%@, 校验值:%@", contentOfDataStr, checkStr);
NSString *getCheckSum = [self checkTheString:contentOfDataStr];
NSString *comToLenStr = [hexStr substringWithRange:NSMakeRange(2, 14)];
NSString *splitCommdStr = @"";
NSFileManager *fileManager = [NSFileManager defaultManager];
//check the code
if ([[checkStr uppercaseString] isEqualToString:getCheckSum]) {
NSLog(@"check checkSum is right");
NSString *data_typeStr = [hexStr substringWithRange:NSMakeRange(10, 2)];
if ([data_typeStr isEqualToString:@"00"]) {
//The name of file
NSString *fileName = [hexStr substringWithRange:NSMakeRange(20, hexStr.length - 22)];
NSLog(@"创建的文件名:%@", fileName);
data_number = 0;
//判断文件是否存在
filePath = [self createFile:fileName type:@"1"];
NSMutableArray *dataArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"fitName"];
NSString *compare_fileName = [NSString stringWithFormat:@"FIT_%@.fit", fileName];
[dataArray addObject:@"1"];
NSLog(@"保存文件路径的数组:%@", dataArray);
NSLog(@"文件路径:%@", compare_fileName);
if (([dataArray containsObject:compare_fileName] && dataArray != NULL) || ([filePath isEqualToString:@""])) {
kisStat = @"02";
}else{
NSString *tempFile = [self createFile:[fileName stringByAppendingString:@"0"] type:@"0"];
if ([tempFile isEqualToString:@""]) {
[fileManager removeItemAtPath:tempPath error:nil];
kisStat = @"01";
}else{
tempPath = tempFile;
[fileManager createFileAtPath:tempPath contents:nil attributes:nil];
kisStat = @"00";
}
}
}else if ([data_typeStr isEqualToString:@"01"]){
//insert data into Local file
if ([self checkLenOfData:hexStr]) {
NSLog(@"data len is right");
kisStat = @"00";
data_number += 1;
NSInteger lengOfhex = hexStr.length;
NSString *dataStr = [hexStr substringWithRange:NSMakeRange(20, lengOfhex-22)];
NSLog(@"每次写入文件的数-------:%@", [dataStr uppercaseString]);
[self insertData:dataStr toFile:tempPath];
}else{
NSLog(@"data len is wrong");
kisStat = @"01";
}
}else if ([data_typeStr isEqualToString:@"02"]){
//check infomation
NSString *fileNumberStr = [hexStr substringWithRange:NSMakeRange(20, 4)];
if ([self checkInformation:[fileNumberStr uppercaseString]]){
NSLog(@"check successful");
NSString *sizeOffileStr = [hexStr substringWithRange:NSMakeRange(24, 8)];
long localLength = [self getCacheFileSize:tempPath];
long watch_length = [self getNumberOfString:[sizeOffileStr uppercaseString]];
NSLog(@"localLength:%ld, -----watch_length:%ld", localLength, watch_length);
if (localLength == watch_length) {
BOOL isChange = [fileManager moveItemAtPath:tempPath toPath:filePath error:nil];
NSLog(@"%d", isChange);
NSLog(@"temp文件大小:%ld-----file文件大小:%ld", [self getCacheFileSize:tempPath], [self getCacheFileSize:filePath]);
if (isChange) {
[fileManager removeItemAtPath:tempPath error:nil];
}else{
NSLog(@"isChange fail");
}
NSLog(@"size of file is right");
kisStat = @"00";
}else{
NSLog(@"size of file is wrong");
kisStat = @"01";
}
}else{
NSLog(@"check fail");
kisStat = @"01";
}
}else if ([data_typeStr isEqualToString:@"03"]){
//sync end
kisfinishFile = 1;
NSString *statStr = [hexStr substringWithRange:NSMakeRange(20, 2)];
if ([statStr isEqualToString:@"01"]) {
[fileManager removeItemAtPath:tempPath error:nil];
}
NSLog(@"parse file");
//获取到多少个fit文件
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDiectory = [paths objectAtIndex:0];
NSString *appDirectory = [documentDiectory stringByAppendingPathComponent:@"rftech-smartwatch-fit"];
NSArray *fileArray = [fileManager subpathsAtPath:appDirectory];
NSLog(@"同步获取到的fit文件%@", fileArray);
CustomAlertWindow *customAlertWindow = [CustomAlertWindow shareCustomAlertWindow];
if (fileArray.count != 0) {
[customAlertWindow setNotes:@"正在解析数据"];
[customAlertWindow show];
[self pareQueueManagercustom:customAlertWindow andFileManager:fileManager andFileArray:fileArray andAppDirectory:appDirectory];
}else{
[customAlertWindow dismiss];
}
}
}else{
NSLog(@"check checkSum is wrong");
kisStat = @"01";
}
if (kisfinishFile == 0) {
splitCommdStr = [self getCommandStr:comToLenStr andStat:kisStat];
NSLog(@"split of CommdStr:%@", splitCommdStr);
[self replyFit:[self convertHexStrToData:splitCommdStr]];
}