zoukankan      html  css  js  c++  java
  • 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()];

  • 相关阅读:
    file is universal (3 slices) but does not contain a(n) armv7s slice error for static libraries on iOS
    WebImageButton does not change images after being enabled in Javascript
    ajax OPTION
    编程遍历页面上所有TextBox控件并给它赋值为string.Empty?
    获取海洋天气预报
    C#线程系列教程(1):BeginInvoke和EndInvoke方法
    js控制只能输入数字和小数点
    Response.AddHeader(,)
    ManualResetEvent的理解
    Convert.ToInt32、int.Parse(Int32.Parse)、int.TryParse、(int) 区别
  • 原文地址:https://www.cnblogs.com/godlovexq/p/5843031.html
Copyright © 2011-2022 走看看