• ios开发蓝牙的基本使用


    用到的数据

    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()];

  • 相关阅读:
    移植Fatfs文件系统到工程中
    利用官方的ucosiii包中测试板的工程移植到属于自己的开发板(stmf103ZE)上
    华为Liteos移植到stm32F03ZE
    如何使用postman模拟https的post和get请求
    ubuntu 16 搭建只能上传不可下载删除ftp服务
    使用STM32F103ZET霸道主板实现LCD显示屏显示
    资源任务调度算法实现(大数据云计算作业来的)
    STM32F10xx(高容量)WiFi模块的初始化和使用
    使用STM32F103ZET霸道主板实现SD卡的读写(非文件系统)
    单片机期末实训---- 密码锁和交通灯
  • 原文地址:https://www.cnblogs.com/godlovexq/p/5843031.html
Copyright © 2020-2023  润新知