ios开发蓝牙的基本使用

版权声明: https://blog.csdn.net/qq_35122556/article/details/80020360

用到的数据

static NSString *kCellReuseIdentifier = @"cell";

static NSString *READ_WRITE_SERVICEID = @"要搜索的设备的特征";

static NSString *CMD_DOWN = @"指令";

static NSString *RES_SUCCEED_DOWN = @"指令";

static NSString *CMD_UP = @"指令";

static NSString *RES_SUCCEED_UP = @"指令";

static NSString *RES_FAILURE_UP = @"指令(主要发生之前需要转换为16进制的数据,及得跟做硬件的哥们沟通数据格式)";

1. 声明一下下

#import <CoreBluetooth/CoreBluetooth.h>

2 初始化在viewdidload 中

self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];

 3遵守协议

<CBCentralManagerDelegate,CBPeripheralDelegate>

4一些需要用到的属性

@property (nonatomic, strong) CBCentralManager *centralManager;

@property (nonatomic, strong) CBCharacteristic *writeCMDCharacteristic;

@property (nonatomic, strong) CBPeripheral *connectedPeripheral;

@property (nonatomic, strong) CBService *readWriteService;

@property (nonatomic, strong) NSMutableArray<CBUUID *> *characteristicIDs;

@property (nonatomic, strong) NSMutableArray<CBPeripheral *> *carLocksArray;

@property (nonatomic, strong) CBCharacteristic *readRESCharacteristic;

@property (nonatomic, strong) CBCharacteristic *readWritePasswordCharacteristic;

5 具体代码,发送信息给设备

[self.connectedPeripheral writeValue:[self convertHexStrToData:CMD_UP] forCharacteristic:self.writeCMDCharacteristic type:CBCharacteristicWriteWithoutResponse];

其中CMD_UP 是跟硬件约定好的要发的指令/我这硬件做的是要求发送的信息是16进制的 ,所以得转发,接下来的接受到的依然是16进制的信息,需要转发,方法在文章最后面。

#pragma mark - 字符串与十六进制数据转换

- (NSData *)convertHexStrToData:(NSString *)str

#pragma mark - 懒加载

-(NSMutableArray *)carLocksArray {

    if (!_carLocksArray) {

        _carLocksArray = [NSMutableArray array];

    }

    return _carLocksArray;

}

- (NSMutableArray<CBUUID *> *)characteristicIDs {

    if (!_characteristicIDs) {

        _characteristicIDs = [NSMutableArray array];

        for (NSInteger i= 0; i < 6; i ++) {

            CBUUID *uuid = [CBUUID UUIDWithString:[NSString stringWithFormat:@"FF0%ld",i+1]];

            [_characteristicIDs addObject:uuid];

        }

    }

    return _characteristicIDs;

}

addStateMessage:@"正在搜索'FF12'服务..."];

    NSLog(@"正在搜索'FF12'服务...");

    self.connectedPeripheral = peripheral;

    [self refreshUIYes];

    

}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

    [self addStateMessage:[NSString stringWithFormat:@"已断开与%@的连接",peripheral.name]];

    NSLog(@"已断开与%@的连接",peripheral.name);

    self.connectedPeripheral = nil;

    [self refreshUINo];

    [self.centralManager connectPeripheral:selectedCarLock options:nil];

    [self addStateMessage:[NSString stringWithFormat:@"正在连接 %@...",selectedCarLock.name]];

}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

    [self addStateMessage:[NSString stringWithFormat:@"未能连接上%@",peripheral.name]];

    NSLog(@"未能连接上%@",peripheral.name);

    [self refreshUINo];

}

#pragma mark - CBPeripheralDelegate

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {

    if (error) {

        [self addStateMessage:[NSString stringWithFormat:@"code:%ld,发现特征值错误: %@",error.code ,error.localizedDescription]];

        NSLog(@"code:%ld,发现特征值错误: %@",error.code ,error.localizedDescription);

        return;

    }

    

    NSString *res = [self convertDataToHexStr:characteristic.value];

    //[self addStateMessage:res];

    NSLog(@"res = %@",res);

    

    //电量

    NSMutableString *muStr = [NSMutableString stringWithFormat:@"%@",res];

    NSString *middleStr = [muStr substringWithRange:NSMakeRange(4, 8)];

    NSString *lasterStr = [muStr substringFromIndex:muStr.length-2];

    //NSLog(@"result:%@",middleStr);

    

    float batteryLow = [[self convertHexStrToString:middleStr] floatValue]/6000;

    NSLog(@"10----%f",batteryLow);

    NSLog(@"10----%@",[self convertHexStrToString:middleStr]);

    //判断是不是回复的

    NSString *topStr = @"";

    if (muStr.length > 22) {

        topStr = [muStr substringToIndex:22];

    }

    if ([topStr isEqualToString:@"ffacffffffffffffff2902"]) {//是回复的指令

        self.top_rightBtn.userInteractionEnabled = YES;

        NSString *lasterTwoStr = [muStr substringFromIndex:muStr.length-2];

        NSString *lasterFour_TwoStr = [muStr substringWithRange:NSMakeRange(muStr.length-4, 2)];

        if ([lasterTwoStr isEqualToString:@"00"]) {

            NSLog(@"=====success");

            [self refreshUIYes];

            if ([lasterFour_TwoStr isEqualToString:@"00"]) {//关锁

                NSLog(@"%@",[NSString stringWithFormat:@"关锁成功-%d",repeatNumThree]);

                [self addStateMessage:@"关锁成功"];

                deviceStatus = NO;

                [self refreshUIYes];

            }else{//开锁

                NSLog(@"%@",[NSString stringWithFormat:@"开锁成功-%d",repeatNumThree]);

                [self addStateMessage:@"开锁成功"];

                deviceStatus = YES;

                [self refreshUIYes];

            }

            repeatNumThree = 0;

        }else if ([lasterTwoStr isEqualToString:@"01"]) {

            if ([lasterFour_TwoStr isEqualToString:@"00"]) {//关锁

                NSLog(@"关锁失败");

                if (repeatNumThree <= 3) {

                    repeatNumThree ++;

                    [self liftUpAction];

                }else{

                    [self addStateMessage:@"关锁失败"];

                }

            }else{//开

                NSLog(@"开锁失败");

                if (repeatNumThree <= 3) {

                    repeatNumThree ++;

                    [self liftDownAction];

                }else{

                    [self addStateMessage:@"开锁失败"];

                }

            }

        }

    }else{

        NSLog(@"=====自动回复的指令");

        //开关状态

        //NSLog(@"%@",lasterStr);

        if ([lasterStr isEqualToString:@"43"]) {

            //NSLog(@"升起的状态");

            [self addStateMessage:@"车锁已升起,请放心"];

            deviceStatus = NO;

        }else{

            //NSLog(@"落下的状态");

            [self addStateMessage:@"车锁已经落下,可入位"];

            deviceStatus = YES;

        }

        [self refreshUIYes];

        

        //电池电量

        if ([lasterStr isEqualToString:@"43"] || [lasterStr isEqualToString:@"4f"]) {

            if (batteryLow <= 0.2) {

                self.batteryImg.image = [UIImage imageNamed:@"dian_red"];

            }else{

                self.batteryImg.image = [UIImage imageNamed:@"dian_man"];

            }

            self.batteryImg.frame = CGRectMake(2, 2, 92*batteryLow, 26);

        }

    }

    

    

    

    //    // 读取密码

    //    if (characteristic == self.readWritePasswordCharacteristic) {

    //        NSString *hexPassword = [self convertDataToHexStr:characteristic.value];

    //        NSString *decimalPassword = [self convertHexStrToString:hexPassword];

    //        [self addStateMessage:[NSString stringWithFormat:@"password = %@",decimalPassword]];

    //        NSLog(@"password = %@",decimalPassword);

    //

    //        if ([self.inputPassword isEqualToString:decimalPassword]) {

    //            // 当前点击的是更改设备名称

    //            if (self.currentSelectedIndexPath.section == 1 && self.currentSelectedIndexPath.row == 0) {

    //                // TODO 点击的是更改设备名称

    //            }

    //

    //            // 当前点击的是更改密码

    //            if (self.currentSelectedIndexPath.section == 1 && self.currentSelectedIndexPath.row == 1) {

    //                ChangePasswordViewController *changePasswordVC = [[ChangePasswordViewController alloc] initWithNibName:NSStringFromClass([ChangePasswordViewController class]) bundle:nil];

    //                changePasswordVC.delegate = self;

    //                [self.navigationController pushViewController:changePasswordVC animated:YES];

    //            }

    //        }else {

    //            [self addStateMessage:@"密码输入错误"];

    //            NSLog(@"密码输入错误");

    //        }

    //        return;

    //    }

    //

    //    if (characteristic == self.readRESCharacteristic) {

    //        NSString *resString = [self convertDataToHexStr:characteristic.value];

    //        [self addStateMessage:[NSString stringWithFormat:@"resString = %@",resString]];

    //        NSLog(@"resString = %@",resString);

    //

    //        if ([resString isEqualToString:RES_SUCCEED_UP]) {

    ////            [self addStateMessage:@"指令发送成功,设备已升起"];

    //            NSLog(@"指令发送成功,设备已升起");

    //            self.liftUpButton.enabled = NO;

    //            self.liftDownButton.enabled = YES;

    //        }

    //

    //        if ([resString isEqualToString:RES_SUCCEED_DOWN]) {

    ////            [self addStateMessage:@"指令发送成功,设备已降下"];

    //            NSLog(@"指令发送成功,设备已降下");

    //            self.liftDownButton.enabled = NO;

    //            self.liftUpButton.enabled = YES;

    //        }

    //

    //        if ([resString isEqualToString:RES_FAILURE_UP]) {

    ////            [self addStateMessage:@"车位锁为能成功升起,可能遇到障碍物"];

    //            NSLog(@"车位锁为能成功升起");

    //            self.liftUpButton.enabled = NO;

    //            self.liftUpButton.enabled = YES;

    //        }

    //    }

}

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {

    //[self addStateMessage:[NSString stringWithFormat:@"已找到指定服务,扫描特征..."]];

    NSLog(@"已找到指定服务,扫描特征...");

    for (CBService *service in peripheral.services) {

        if ([service.UUID.UUIDString isEqualToString:READ_WRITE_SERVICEID]) {

            self.readWriteService = service;

            break;

        }

    }

    if (self.readWriteService != nil) {

        [self.connectedPeripheral discoverCharacteristics:self.characteristicIDs forService:self.readWriteService];

    }

    

}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {

    [self addStateMessage:[NSString stringWithFormat:@"已经链接车位锁,等待发送指令"]];

    NSLog(@"已找到相应特征,等待发指令...");

    

    self.writeCMDCharacteristic = [service.characteristics objectAtIndex:0];

    self.readRESCharacteristic = [service.characteristics objectAtIndex:1];

    self.readWritePasswordCharacteristic = [service.characteristics objectAtIndex:4];

    [self.connectedPeripheral setNotifyValue:YES forCharacteristic:self.readRESCharacteristic];

    [self.connectedPeripheral setNotifyValue:YES forCharacteristic:self.readWritePasswordCharacteristic];

   // self.liftUpButton.enabled = YES;

    //self.liftDownButton.enabled = YES;

    

    [self.connectedPeripheral writeValue:[self convertHexStrToData:RECEIVESTATUS] forCharacteristic:self.writeCMDCharacteristic type:CBCharacteristicWriteWithoutResponse];

}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {

    [self addStateMessage:[NSString stringWithFormat:@"发送指令已完成,等待结果..."]];

    NSLog(@"发送指令已完成,等待结果...");

    

}

- (void)addStateMessage:(NSString *)message {

    NSLog(@"%@",message);

    int xStart = 10;

    if (bgStatuslab ==nil) {

    UIImage *img = [UIImage imageNamed:@"green_icon"];

    CGFloat scale = [UIScreen mainScreen].scale;

    UIImage *dot9 = [img resizableImageWithCapInsets:(UIEdgeInsets){0/scale,20/scale,5/scale,20/scale} resizingMode:UIImageResizingModeStretch];  //{top/scale,left/scale,bottom/scale,right/scale}  top  left bottom right 表示图片不拉伸的尺寸.

    self.status_new_img.image = dot9;

    bgStatuslab = [[UILabel alloc] initWithFrame:CGRectMake(xStart, 5, self.status_new_img.frame.size.width - xStart*2, self.status_new_img.frame.size.height - 10)];

    bgStatuslab.textAlignment = NSTextAlignmentCenter;

        bgStatuslab.textColor = [UIColor whiteColor];

    bgStatuslab.font = [UIFont systemFontOfSize:13];

    [self.status_new_img addSubview:bgStatuslab];

    }

    self.status_new_img.frame = CGRectMake(110, 50, [self receiveTextWidthWithString:message] + 30, 30);

    bgStatuslab.frame = CGRectMake(xStart, 5, self.status_new_img.frame.size.width - xStart*2, self.status_new_img.frame.size.height - 10);

    bgStatuslab.text = message;

}

// 得到文字的宽度

-(int)receiveTextWidthWithString:(NSString *)str

{

    CGSize maxWidth = CGSizeMake(MAXFLOAT, 20);

    NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:13]};

    CGRect rect = [str boundingRectWithSize:maxWidth options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil];

    int width = (int)rect.size.width;

    return width;

}

#pragma mark - 字符串与十六进制数据转换

- (NSData *)convertHexStrToData:(NSString *)str {

    if (!str || [str length] == 0) {

        return nil;

    }

    

    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];

    NSRange range;

    if ([str length] % 2 == 0) {

        range = NSMakeRange(0, 2);

    } else {

        range = NSMakeRange(0, 1);

    }

    for (NSInteger i = range.location; i < [str length]; i += 2) {

        unsigned int anInt;

        NSString *hexCharStr = [str substringWithRange:range];

        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];

        

        [scanner scanHexInt:&anInt];

        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];

        [hexData appendData:entity];

        

        range.location += range.length;

        range.length = 2;

    }

    

    NSLog(@"hexdata: %@", hexData);

    return hexData;

}

- (NSString *)convertDataToHexStr:(NSData *)data {

    if (!data || [data length] == 0) {

        return @"";

    }

    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];

    

    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {

        unsigned char *dataBytes = (unsigned char*)bytes;

        for (NSInteger i = 0; i < byteRange.length; i++) {

            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];

            if ([hexStr length] == 2) {

                [string appendString:hexStr];

            } else {

                [string appendFormat:@"0%@", hexStr];

            }

        }

    }];

    

    return string;

}

//16-->10

- (NSString *)convertHexStrToString:(NSString *)str {

    if (!str || [str length] == 0) {

        return nil;

    }

    

    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];

    NSRange range;

    if ([str length] % 2 == 0) {

        range = NSMakeRange(0, 2);

    } else {

        range = NSMakeRange(0, 1);

    }

    for (NSInteger i = range.location; i < [str length]; i += 2) {

        unsigned int anInt;

        NSString *hexCharStr = [str substringWithRange:range];

        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];

        

        [scanner scanHexInt:&anInt];

        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];

        [hexData appendData:entity];

        

        range.location += range.length;

        range.length = 2;

    }

    NSString *string = [[NSString alloc]initWithData:hexData encoding:NSUTF8StringEncoding];

    return string;

}

//将NSString转换成十六进制的字符串则可使用如下方式:

- (NSString *)convertStringToHexStr:(NSString *)str {

    if (!str || [str length] == 0) {

        return @"";

    }

    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

    

    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];

    

    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {

        unsigned char *dataBytes = (unsigned char*)bytes;

        for (NSInteger i = 0; i < byteRange.length; i++) {

            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];

            if ([hexStr length] == 2) {

                [string appendString:hexStr];

            } else {

                [string appendFormat:@"0%@", hexStr];

            }

        }

    }];

    

    return string;

}

 更多的需要跟做硬件的哥们去商议具体怎么沟通.

下面说说开发蓝牙遇到的坑

1.ios开发有时候连接上了无法获取蓝牙模块自动返回的值那么监听一下

[self.connectedPeripheral setNotifyValue:YES forCharacteristic:self.readRESCharacteristic];

    [self.connectedPeripheral setNotifyValue:YES forCharacteristic:self.readWritePasswordCharacteristic];

2.ios开发蓝牙,发觉手机已经连接上了,就搜索不到了.这是需要把搜索到的设备以及中央设备等弄成全局的持有.每次进来之前断开重新初始化在连接

[centerMangerDevice cancelPeripheralConnection:selectedCarLock];

        centerMangerDevice = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];

猜你喜欢

转载自blog.csdn.net/qq_35122556/article/details/80020360