精华内容
下载资源
问答
  • 手机可以连接多少个蓝牙设备?

    千次阅读 2020-08-14 07:54:22
    这是一个课题研究,蓝牙的东西我们可以先不说,我们讨论一个产品需求。我经常遇到一个场景,就是我用我的手机连上TWS蓝牙耳机听音乐,然后呢,我没有开车,我下地铁的时候,我需要打开我的手机,打...

    这是一个课题研究,蓝牙的东西我们可以先不说,我们讨论一个产品需求。

    我经常遇到一个场景,就是我用我的手机连上TWS蓝牙耳机听音乐,然后呢,我没有开车,我下地铁的时候,我需要打开我的手机,打开某个共享单车应用界面,使用这个界面去给共享单车解锁。如果手机只能连接一个蓝牙设备,那我要是想给共享单车解锁的话,我就需要断开我的TWS蓝牙耳机,这个是一个非常不好的体验,所以,就存在一个手机同时连接两个蓝牙或者多个蓝牙设备的情况。

    一个手机连接两个蓝牙设备图

    经过各方寻找「放心,我不是用百度,而是用google」,终于知道在Android p之后,Android可以支持同时连接 5 个音频蓝牙设备,并且,我用我的手机进行了测试,发现确实可以连接 5 个蓝牙音频设备。在连接5个音频设备之后,我还想再连接第六台的时候,在界面上显示已经连接上,但是已经不能播放音频了。

    同时连接上5台音频设备

    呃~ 

    所以我们作为一个Android 手机使用者,而且是一个底层开发人员,应该去看看这个设置的位置,他在手机的「开发者选项」位置有一个选项说明了最大连接个数,有的手机厂商也会阉割这个功能。

    开发者选项,看到最大连接蓝牙个数

    能不能做到一个手机同时向多个蓝牙设备传输音频信号呢?

    答案是现在不可以,马上很快可能就可以了。

    我们目前的蓝牙连接音频的情况是这样的

    蓝牙点对点传输音频

    最近,我说最近啊,现在我写这篇文章的时间是 2020年8月13日,也就是这个时间前后,新出来了一个技术,这个技术叫做 「Bluetooth LE Audio」,这个技术的一个特点就是脱离蓝牙的点对点传输的功能,使用路由的方式来传输,就像我们听广播电台一样,所有人都可以听到同一个广播电台的声音,如果你和很多朋友一起,他们也能同时接收到你的蓝牙音频信号。

    就像下面这张图这样,期待这样的技术面世吧,这样之后,很多应用场景就会变成现实。

    广播路由通讯方式

    当然了,如果需要接收这个广播,使用这个蓝牙特性,需要发送和接收方都运行了这个新蓝牙特性。

      推荐阅读:

        专辑|Linux文章汇总

        专辑|程序人生

        专辑|C语言

    嵌入式Linux

    微信扫描二维码,关注我的公众号 

    展开全文
  • iOS蓝牙连接设备

    千次阅读 2017-09-07 11:37:30
    连接多蓝牙设备与单台连接蓝牙设备的道理是一样,同样需要首先发现蓝牙设备然后把发现的设备添加到一个 NSMutableArray 保存起来。具体看下面代码:首先 我们需要创建 @property (nonatomic,strong ) ...

    1. 框架
    利用蓝牙CoreBluetooth框架 在7.0以上就用这个连接蓝牙框架。

    2.连接
    连接多台蓝牙设备与单台连接蓝牙设备的道理是一样,同样需要首先发现蓝牙设备然后把发现的设备添加到一个 NSMutableArray 保存起来。

    具体看下面代码:

    首先 我们需要创建

    @property (nonatomic,strong ) CBCentralManager *manager;// 中心设备
    @property (nonatomic,strong ) NSMutableArray   <CBPeripheral*>*devices;// 扫描到的外围设备
    @property (nonatomic, strong) NSMutableArray   *connectSuccess;//连接成功的的外设
    

    上面 CBCentralManager 是指定的中心设备(手机 ,平板…)

    而 CBPeripheral 所指的是需要连接的蓝牙设备(耳机,手表,手环…等等)

    需要一个 connectSuccess 用来保存连接成功的设备。

    设置 CBCentralManager 代理

    @interface ViewController ()<CBCentralManagerDelegate>
    

    当打开程序的时候就要实现此代理 CBCentralManagerDelegate

    并自动检查手机蓝牙是否打开,只有打开的时候才会去自动的扫描蓝牙设备

    //中心设备状态改变的代理必须实现
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
        switch (central.state)
        {
            case CBManagerStatePoweredOn:
                NSLog(@"蓝牙已打开");
                //自动开始扫描
                [self startScan];
                break;
            case CBManagerStateUnknown:
                break;
            case CBManagerStatePoweredOff:
                NSLog(@"蓝牙未打开");
                
                break;
            case CBManagerStateResetting:
                //            [self showInfo:@"蓝牙初始化中"];
                break;
            case CBManagerStateUnsupported:
                NSLog(@"蓝牙不支持状态");
                
                //            [self showInfo:@"蓝牙不支持状态"];
                break;
            case CBManagerStateUnauthorized:
                //            [self showInfo:@"蓝牙设备未授权"];
                break;
            default:
                break;
        }
    }
    
    

    扫描蓝牙

    下面的代码 扫描不是一直在进行 15秒后结束扫描

    /*
     * 开始扫描
     */
    -(void) startScan{
        NSLog(@"scan....");
        [self.manager scanForPeripheralsWithServices:nil options:nil];
        //15秒后停止。
        //(开启扫描后会不停的扫描)
        [self performSelector:@selector(stopScan) withObject:nil afterDelay:15];
    }
    
    

    停止扫描

    中心设备停止(手机、平板…)

    /**
     *  停止扫描
     */
    -(void)stopScan{
        [self.manager stopScan];
        NSLog(@"stopScan....");
    }
    

    扫描到设备就要添加设备 最好是放到tableview中

    并所有扫描出来的 peripheral 添加到 self.devices 中

    相应的tableview也要刷新一下

    /**
     *  扫描蓝牙的代理
     *
     *  @param central           中心设备
     *  @param peripheral        扫描到的蓝牙
     *  @param advertisementData 在ios中蓝牙广播信息中通常会包含以下4种类型的信息。ios的蓝牙通信协议中不接受其他类型的广播信息。
     因此需要注意的是,如果需要在扫描设备时,通过蓝牙设备的Mac地址来唯一辨别设备,那么需要与蓝牙设备的硬件工程师沟通好:将所需要的Mac地址放到一下几种类型的广播信息中。
     通常放到kCBAdvDataManufacturerData这个字段中。
     kCBAdvDataIsConnectable = 1;
     kCBAdvDataLocalName = XXXXXX;
     kCBAdvDataManufacturerData = <XXXXXXXX>;
     kCBAdvDataTxPowerLevel = 0;
     *  @param RSSI              信号强度
     */
    //扫描到的蓝牙设备添加到devices数组中,刷新列表
    -(void)centralManager:(CBCentralManager *)central
    didDiscoverPeripheral:(CBPeripheral *)peripheral
        advertisementData:(NSDictionary<NSString *,id> *)advertisementData
                     RSSI:(NSNumber *)RSSI{
        if (![self.devices containsObject:peripheral]) {
            [self.devices addObject:peripheral];
            [self.tableView reloadData];
            NSLog(@"发现外围设备:%@---RSSI:%@---advertisementData:%@",peripheral,RSSI,advertisementData);
        }
    }
    
    

    点击tableview中各个蓝牙选择项 并连接蓝牙 提示给用户 连接成功

    并把连接成功的 peripheral 添加到 self.connectSuccess中

    /**
     *  蓝牙连接成功时候的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前连接的设备
     */
    -(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
        NSLog(@"%@名字的蓝牙连接成功",peripheral.name);
        _maincell.txtDeviceContent.text = @"已连接";
        //cell.detailTextLabel.text = @"已连接";
        [self.connectSuccess addObject:peripheral];
    }
    
    

    同样也有失败和断开的时候

    失败的时候不做处理 也可以做处理
    但是断开的时候 需要把 连接成功的 self.connectSuccess 设备移除掉
    并在tableview中把 连接成功的文字清空。这样就变为没有连接的状态

    /**
     *  蓝牙链接失败的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前连接的外设
     *  @param error      错误信息
     */
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;{
        NSLog(@"%@名字的蓝牙连接失败",peripheral.name);
    }
    /**
     *  蓝牙断开连接的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前需要断开连接的外设
     *  @param error      错误信息
     */
    -(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
        NSLog(@"%@名字的蓝牙断开链接",peripheral.name);
        _maincell.txtDeviceContent.text = @"";
        
        for(int i=0;i<_connectSuccess.count;i++){
            CBPeripheral *p = [_connectSuccess objectAtIndex:i];
            if ([p.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]) {
                [self.connectSuccess removeObject:p];
            }
        }
    }
    
    

    具体的连接的代码如下:
    头部没有东西
    ViewController.m

    //
    //  ViewController.m
    //
    
    #import "ViewController.h"
    #import <CoreBluetooth/CoreBluetooth.h>
    #import "mainViewCell.h"
    
    
    @interface ViewController ()<CBCentralManagerDelegate,UITableViewDelegate,UITableViewDataSource>
    
    
    - (IBAction)btnSure:(id)sender;
    
    
    @property (weak, nonatomic) IBOutlet UITableView *tableView;
    
    @property(nonatomic,strong) mainViewCell *maincell;
    @property (nonatomic,strong ) CBCentralManager *manager;// 中心设备
    @property (nonatomic,strong ) NSMutableArray   <CBPeripheral*>*devices;// 扫描到的外围设备
    @property (nonatomic, strong) NSMutableArray   *connectSuccess;//链接成功的的外设
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIColor *blues = [self stringTOColor:@"#436EEE"];
        [self.navigationController.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],UITextAttributeTextColor,nil]];
        [self.navigationController.navigationBar setBarTintColor:blues];
        self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
        
        UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
        self.navigationItem.backBarButtonItem = item;
        
        _maincell = [[mainViewCell alloc] init];
        self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        self.devices = [NSMutableArray array];
        self.connectSuccess = [NSMutableArray array];
        
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
        
        //创建下啦刷新
        //UIRefreshControl *rc = [[UIRefreshControl alloc] init];
        //rc.attributedTitle = [[NSAttributedString alloc] initWithString:@"Drop Scan"];
        
        //[rc addTarget:self action:@selector(redreshTableView) forControlEvents:UIControlEventValueChanged];
        
        //self.refreshControl = rc;
        
       
        
    }
    
    /*
     * 字符串转为颜色值
     */
    - (UIColor *) stringTOColor:(NSString *)str
    {
        if (!str || [str isEqualToString:@""]) {
            return nil;
        }
        unsigned red,green,blue;
        NSRange range;
        range.length = 2;
        range.location = 1;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&red];
        range.location = 3;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&green];
        range.location = 5;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&blue];
        UIColor *color= [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1];
        return color;
    }
    
    /*
     * 开始扫描
     */
    -(void) startScan{
        NSLog(@"scan....");
        
        [self.manager scanForPeripheralsWithServices:nil options:nil];
        
        //[self.manager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];
        //3秒后停止。(开启扫描后会不停的扫描)
        [self performSelector:@selector(stopScan) withObject:nil afterDelay:15];
    }
    
    /**
     *  停止扫描
     */
    -(void)stopScan{
        [self.manager stopScan];
        NSLog(@"stopScan....");
    }
    
    //中心设备状态改变的代理必须实现
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
        switch (central.state)
        {
            case CBManagerStatePoweredOn:
                NSLog(@"蓝牙已打开");
                //自动开始扫描
                [self startScan];
                break;
            case CBManagerStateUnknown:
                break;
            case CBManagerStatePoweredOff:
                NSLog(@"蓝牙未打开");
                
                break;
            case CBManagerStateResetting:
                //            [self showInfo:@"蓝牙初始化中"];
                break;
            case CBManagerStateUnsupported:
                NSLog(@"蓝牙不支持状态");
                
                //            [self showInfo:@"蓝牙不支持状态"];
                break;
            case CBManagerStateUnauthorized:
                //            [self showInfo:@"蓝牙设备未授权"];
                break;
            default:
                break;
        }
    }
    
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    /**
     *  扫描蓝牙的代理
     *
     *  @param central           中心设备
     *  @param peripheral        扫描到的蓝牙
     *  @param advertisementData 在ios中蓝牙广播信息中通常会包含以下4种类型的信息。ios的蓝牙通信协议中不接受其他类型的广播信息。
     因此需要注意的是,如果需要在扫描设备时,通过蓝牙设备的Mac地址来唯一辨别设备,那么需要与蓝牙设备的硬件工程师沟通好:将所需要的Mac地址放到一下几种类型的广播信息中。
     通常放到kCBAdvDataManufacturerData这个字段中。
     kCBAdvDataIsConnectable = 1;
     kCBAdvDataLocalName = XXXXXX;
     kCBAdvDataManufacturerData = <XXXXXXXX>;
     kCBAdvDataTxPowerLevel = 0;
     *  @param RSSI              信号强度
     */
    //扫描到的蓝牙设备添加到devices数组中,刷新列表
    -(void)centralManager:(CBCentralManager *)central
    didDiscoverPeripheral:(CBPeripheral *)peripheral
        advertisementData:(NSDictionary<NSString *,id> *)advertisementData
                     RSSI:(NSNumber *)RSSI{
        if (![self.devices containsObject:peripheral]) {
            [self.devices addObject:peripheral];
            [self.tableView reloadData];
            NSLog(@"发现外围设备:%@---RSSI:%@---advertisementData:%@",peripheral,RSSI,advertisementData);
        }
    }
    /**
     *  蓝牙连接成功时候的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前连接的设备
     */
    -(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
        NSLog(@"%@名字的蓝牙连接成功",peripheral.name);
        _maincell.txtDeviceContent.text = @"已连接";
        //cell.detailTextLabel.text = @"已连接";
        [self.connectSuccess addObject:peripheral];
    }
    /**
     *  蓝牙链接失败的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前连接的外设
     *  @param error      错误信息
     */
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;{
        NSLog(@"%@名字的蓝牙连接失败",peripheral.name);
    }
    /**
     *  蓝牙断开连接的代理
     *
     *  @param central    中心设备
     *  @param peripheral 当前需要断开连接的外设
     *  @param error      错误信息
     */
    -(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
        NSLog(@"%@名字的蓝牙断开链接",peripheral.name);
        _maincell.txtDeviceContent.text = @"";
        
        for(int i=0;i<_connectSuccess.count;i++){
            CBPeripheral *p = [_connectSuccess objectAtIndex:i];
            if ([p.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]) {
                [self.connectSuccess removeObject:p];
            }
    
        }
        
        /*for (CBPeripheral *p in self.connectSuccess) {
            if ([p.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]) {
                [self.connectSuccess removeObject:p];
            }
        }*/
    }
    
    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        [self.manager connectPeripheral:self.devices[indexPath.row] options:nil];
        _maincell = [tableView cellForRowAtIndexPath:indexPath];
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return self.devices.count;
        
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        static NSString *CellIdentifier = @"ViewCell";
        
        mainViewCell *cell1 = [tableView
                                  dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell1 == nil) {
            cell1 = [[mainViewCell alloc]
                     initWithStyle:UITableViewCellStyleValue1
                     reuseIdentifier:CellIdentifier];
        }
        
        if (!self.devices[indexPath.row].name) {
            cell1.txtDeviceName.text=@"null";
        }else{
            cell1.txtDeviceName.text=self.devices[indexPath.row].name;
            //cell1.txtDeviceAddre.text=self.devices[indexPath.row].identifier;
            NSString *c = [NSString stringWithFormat:@"%@",self.devices[indexPath.row].identifier];
            NSString *b = NULL;
            if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0) {
                b = [c substringFromIndex:30];
            }else{
                b = [c substringFromIndex:30];
            }
            cell1.txtDeviceAddre.text = b;
        }
        return cell1;
        
    }
    
    
    -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
        mainViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath];
        if ([cell2.txtDeviceContent.text isEqualToString:@"已连接"]) {
            return YES;
        }
        return NO;
    }
    
    - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
        _maincell = [tableView cellForRowAtIndexPath:indexPath];
        UITableViewRowAction *disconnect = [UITableViewRowAction rowActionWithStyle:1 title:@"断开连接" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
            //断开蓝牙连接
            CBPeripheral *peripheral = self.devices[indexPath.row];
            [self.manager cancelPeripheralConnection:peripheral];
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
        }];
        return @[disconnect];
    }
    
    
    - (IBAction)btnSure:(id)sender {
        LinkViewController *link = [[LinkViewController alloc] init];
        if (self.connectSuccess.count > 0)
        {
            for (int i = 0; i < self.connectSuccess.count; i++) {
                CBPeripheral *p = self.connectSuccess[i];
                if (i == 0) {
                    link.oneperipheral = p;
                }
                else if (i == 1) {
                    link.twoperipheral = p;
                }
                else if(i == 2){
                    link.threeperipheral = p;
                }
                else if(i==3){
                    link.fourperipheral = p;
                }
                else if(i==4){
                    link.fiveperipheral = p;
                }
                else if(i==5){
                    link.sexperipheral = p;
                }
                else if(i==6){
                    link.sevenperipheral = p;
                }
            }
            [self.navigationController pushViewController:link animated:YES];
        }
    }
    
    @end
    
    

    3.数据读取
    这里的数据读取是分开来写的 如果是同样的设备 并底层给的UUID 接收和发送数据是同样的话可以写一个就可以并可以用tabview 中的cell来写
    但是如果需要连接不相同的UUID的时候 并解析格式不一样介意使用多个

    我创建的是view 可以使用MVC 来实现 创建NSObject也可以 毕竟是 数据获取

    用不上view

    如 OneView.h

    #import <UIKit/UIKit.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface OneView : UIView<CBPeripheralDelegate>
    
    @property (nonatomic, strong) UITextView *textView;
    @property (nonatomic, strong) CBCharacteristic *oneNotiC, *oneWriteC;
    @property (nonatomic, strong) NSMutableString *mutStr;
    
    @end
    

    OneView.m 如下

    在这个里面 我们连接到设备之后 需要读取 peripheral 里面的UUID 包含了服务和特征的 UUID

    首先读取服务的 一样的要实现 CBPeripheralDelegate 代理

    #pragma mark - 外围设备服务的代理
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
        //NSLog(@"123");
        for (CBService *s in peripheral.services) {
            NSLog(@"%@",[s.UUID UUIDString]);
            [peripheral discoverCharacteristics:nil forService:s];
        }
    }
    
    

    当发现了服务UUID之后 我们需要 服务里面的具体携带的特征UUID 也是数据解析的 UUID

    这里面有些是多余的你可以选择你自己需要的

    #pragma mark 2. 外围设备 扫描到服务下有哪些特征
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error
    {
        if (error){
            NSLog(@"扫描特征出现错误,错误原因:%@",error);
        }else{
            //拿到服务中所有的特征
            NSArray *characteristics = service.characteristics;
            //遍历特征,拿到需要的特征进行处理
            for (CBCharacteristic *characteristic in characteristics){
                NSLog(@"所有的特征为:%@",characteristic.UUID.UUIDString);
                //如果是温度数据处理
                if([characteristic.UUID.UUIDString isEqualToString:@"底层给你的UUID"]){
                    //将全部的特征信息打印出来
                    //_peripheral = peripheral;
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"%@",characteristic);
                }
                //这里是发送 设备设置蓝牙发送温度数据的值
                else if([characteristic.UUID.UUIDString isEqualToString:@"底层给你的UUID"]){
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"写入的值为:%@",characteristic);
                }
                //如果是ota进行ota升级
                else if([characteristic.UUID.UUIDString isEqualToString:@"底层给你的UUID"]){
                    //_peripheral = peripheral;
                    //设置通知
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSString *s = @"OTA";
                    NSDictionary *tempOta = [NSDictionary dictionaryWithObject:s forKey:@"ota"];
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"tempOTA" object:nil userInfo:tempOta];
                }
                //无键按钮DFU
                else if([characteristic.UUID.UUIDString isEqualToString:@"底层给你的UUID"]){
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"写入的OTA值为:%@",characteristic);
                }
            }
        }
    }
    
    

    当读取到你需要的UUID的时候直接读取数据
    在这里面你 可以用你们底层给你们的算法去解析数据

    我写的不代表你的

    #pragma mark 3.接收外围设备的数据(这里就能接到蓝牙发送过来的数据,具体协议就要看你们是怎么定义的)
    -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
        
        NSString *temps=[self getTempData:characteristic];
        //self.textView.text = temps;
        //发送广播来更新通知信息
        //第一个的温度数据
        
        NSString *blename = peripheral.name;
        NSString *c = [NSString stringWithFormat:@"%@",peripheral.identifier];
        NSString *b = NULL;
        if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0) {
            b = [c substringFromIndex:30];
        }else{
            b = [c substringFromIndex:30];
        }
    
        NSString *bleaddre = b;
        NSString *tempss = [temps stringByAppendingString:@","];
        NSString *tempsss = [blename stringByAppendingString:@","];
        NSString *tempssss = [tempsss stringByAppendingString:bleaddre];
        NSString *tempsssss = [tempss stringByAppendingString:tempssss];
        
        NSDictionary *tempDict = [NSDictionary dictionaryWithObject:tempsssss forKey:@"tempOne"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofictionOne" object:nil userInfo:tempDict];
    }
    
    

    还需要打开通知 我这个项目是通过接收通知来更新温度数据的

    //设置通知
    -(void)notifyCharacteristic:(CBPeripheral *)peripheral
                 characteristic:(CBCharacteristic *)characteristic{
        //设置通知,数据通知会进入:didUpdateValueForCharacteristic方法
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        //[_centerManager stopScan];
    }
    
    

    OneView.m详细代码

    //
    //  OneView.m
    //  LHTempProject
    //
    //  Created by rnd on 2017/5/2.
    //  Copyright © 2017年 GoDream. All rights reserved.
    //
    
    #import "OneView.h"
    
    @implementation OneView
    
    -(instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
            self.mutStr = [NSMutableString string];
            //[self addTextView];
        }
        return self;
    }
    
    //添加textView
    -(void)addTextView{
        self.textView = [[UITextView alloc] initWithFrame:self.bounds];
        self.textView.backgroundColor = [UIColor whiteColor];
        [self addSubview:self.textView];
    }
    
    #pragma mark - 外围设备服务的代理
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
        //NSLog(@"123");
        for (CBService *s in peripheral.services) {
            NSLog(@"%@",[s.UUID UUIDString]);
            [peripheral discoverCharacteristics:nil forService:s];
        }
    }
    #pragma mark 2. 外围设备 扫描到服务下有哪些特征
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error
    {
        if (error){
            NSLog(@"扫描特征出现错误,错误原因:%@",error);
        }else{
            //拿到服务中所有的特征
            NSArray *characteristics = service.characteristics;
            //遍历特征,拿到需要的特征进行处理
            for (CBCharacteristic *characteristic in characteristics){
                NSLog(@"所有的特征为:%@",characteristic.UUID.UUIDString);
                //如果是温度数据处理
                if([characteristic.UUID.UUIDString isEqualToString:@"783F2991-23E0-4BDC-AC16-78601BD84B39"]){
                    //将全部的特征信息打印出来
                    //_peripheral = peripheral;
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"%@",characteristic);
                }
                //这里是发送 设备设置蓝牙发送温度数据的值
                else if([characteristic.UUID.UUIDString isEqualToString:@"849B5163-93BE-4229-9A6A-BB38D6471917"]){
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"写入的值为:%@",characteristic);
                }
                //如果是ota进行ota升级
                else if([characteristic.UUID.UUIDString isEqualToString:@"00060001-F8CE-11E4-ABF4-0002A5D5C51B"]){
                    //_peripheral = peripheral;
                    //设置通知
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSString *s = @"OTA";
                    NSDictionary *tempOta = [NSDictionary dictionaryWithObject:s forKey:@"ota"];
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"tempOTA" object:nil userInfo:tempOta];
                }
                //无键按钮DFU
                else if([characteristic.UUID.UUIDString isEqualToString:@"33040179-CAC9-4A06-B83D-433ED3F8C55E"]){
                    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                    NSLog(@"写入的OTA值为:%@",characteristic);
                }
            }
        }
        
    }
    
    #pragma mark 3.接收外围设备的数据(这里就能接到蓝牙发送过来的数据,具体协议就要看你们是怎么定义的)
    -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
        
        NSString *temps=[self getTempData:characteristic];
        //self.textView.text = temps;
        //发送广播来更新通知信息
        //第一个的温度数据
        
        NSString *blename = peripheral.name;
        NSString *c = [NSString stringWithFormat:@"%@",peripheral.identifier];
        NSString *b = NULL;
        if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0) {
            b = [c substringFromIndex:30];
        }else{
            b = [c substringFromIndex:30];
        }
    
        NSString *bleaddre = b;
        NSString *tempss = [temps stringByAppendingString:@","];
        NSString *tempsss = [blename stringByAppendingString:@","];
        NSString *tempssss = [tempsss stringByAppendingString:bleaddre];
        NSString *tempsssss = [tempss stringByAppendingString:tempssss];
        
        NSDictionary *tempDict = [NSDictionary dictionaryWithObject:tempsssss forKey:@"tempOne"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofictionOne" object:nil userInfo:tempDict];
    }
    
    //设置通知
    -(void)notifyCharacteristic:(CBPeripheral *)peripheral
                 characteristic:(CBCharacteristic *)characteristic{
        //设置通知,数据通知会进入:didUpdateValueForCharacteristic方法
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        //[_centerManager stopScan];
    }
    
    /*
     * 温度数据的转换
     */
    
    -(NSString *)getTempDatas:(CBCharacteristic *)characteristic{
        NSString *tempUnit;
        int temps = 0;
        NSData *data= characteristic.value;
        if(data!=nil){
            const uint8_t *bytes = [data bytes];
            int b0,b1,b2,b3;
            b0 = bytes[1]&0xff;
            b1 = bytes[2]&0xff;
            b2 = bytes[3]&0xff;
            b3 = bytes[4]&0xff;
            
            temps = (b0<<24)|(b1<<16)|(b2<<8)|b3;
            const uint8_t flagByte = bytes[0];
            if ((flagByte & 0x01) != 0) {
                tempUnit = @"°F";
                //[_userDefaults setObject:tempUnit forKey:@"tempUnit"]; //存储温度数据
            } else {
                tempUnit = @"°C";
                //[_userDefaults setObject:tempUnit forKey:@"tempUnit"];
            }
        }
        
        float a = temps;
        //保留小数点后面的1位小数
        NSString *s = [NSString stringWithFormat:@"%.1f",a/10];
        NSString *ss = [NSString stringWithFormat:@"%@,%@",s,tempUnit];
        return ss;
    }
    
    -(NSString *)getTempData:(CBCharacteristic *)characteristic{
        NSString *tempUnit;
        int temps = 0;
        int alarm = 0;
        int normal = 0;
        NSData *data= characteristic.value;
        if(data!=nil){
            const uint8_t *bytes = [data bytes];
            int b0,b1,b2,b3,b4,b5,b6,b7,b8,b9;
            b0 = bytes[0]&0xff;
            b1 = bytes[1]&0xff;
            b2 = bytes[2]&0xff;
            b3 = bytes[3]&0xff;
            b4 = bytes[4]&0xff;
            b5 = bytes[5]&0xff;
            b6 = bytes[6]&0xff;
            b7 = bytes[7]&0xff;
            b8 = bytes[8]&0xff;
            b9 = bytes[9]&0xff;
            
            temps = (b5<<24)|(b4<<16)|(b3<<8)|b2;
            
            alarm = (b9<<24)|(b8<<16)|(b7<<8)|b6;
            
            const uint8_t flagBB = bytes[1];
            
            normal = flagBB&0x01;
            
            const uint8_t flagByte = bytes[0];
            
            if ((flagByte & 0x01) != 0) {
                tempUnit = @"°F";
                //[_userDefaults setObject:tempUnit forKey:@"tempUnit"]; //存储温度数据
            } else {
                tempUnit = @"°C";
                //[_userDefaults setObject:tempUnit forKey:@"tempUnit"];
            }
        }
        
        float a = temps;
        //保留小数点后面的1位小数
        NSString *am = [NSString stringWithFormat:@"%d",alarm];
        NSString *no = [NSString stringWithFormat:@"%d",normal];
        
        NSString *zuhe = [am stringByAppendingString:@","];
        
        NSString *zuhe1 = [zuhe stringByAppendingString:no];
        
        NSString *s = [NSString stringWithFormat:@"%.1f",a];
        //NSString *ss = [NSString stringWithFormat:@"%@,%@",s,tempUnit];
        NSString *ss = [NSString stringWithFormat:@"%@,%@,%@",s,tempUnit,zuhe1];
        
        return ss;
    }
    @end
    
    

    4.展示数据
    把读取出来的数据放到一个界面里面显示

    LinkViewController.h

    //
    //  LinkViewController.h
    //  LHTempProject
    //
    //  Created by rnd on 2017/5/2.
    //  Copyright © 2017年 GoDream. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    #import "OneView.h"
    #import "TwoView.h"
    #import "ThreeView.h"
    #import "FourView.h"
    #import "FiveView.h"
    #import "SixView.h"
    #import "SevenView.h"
    #import "NormalUtil.h"
    
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface LinkViewController : UIViewController
    
    @property(nonatomic,strong) CBPeripheral *oneperipheral;
    
    @property(nonatomic,strong) CBPeripheral *twoperipheral;
    
    @property(nonatomic,strong) CBPeripheral *threeperipheral;
    
    @property(nonatomic,strong) CBPeripheral *fourperipheral;
    
    @property(nonatomic,strong) CBPeripheral *fiveperipheral;
    
    @property(nonatomic,strong) CBPeripheral *sexperipheral;
    
    @property(nonatomic,strong) CBPeripheral *sevenperipheral;
    
    //显示温度的数值 关键 切换
    @property(nonatomic,strong) UILabel *labelTempOne;
    
    @property(nonatomic,strong) UILabel *labelSymbolOne;
    
    @property(nonatomic,strong) UILabel *labelTempTwo;
    
    @property(nonatomic,strong) UILabel *labelSymbolTwo;
    
    @property(nonatomic,strong) UILabel *labelTempThree;
    
    @property(nonatomic,strong) UILabel *labelSymbolThree;
    
    @property(nonatomic,strong) UILabel *labelTempFour;
    
    @property(nonatomic,strong) UILabel *labelSymbolFour;
    
    @property(nonatomic,strong) UILabel *labelTempFive;
    
    @property(nonatomic,strong) UILabel *labelSymbolFive;
    
    @property(nonatomic,strong) UILabel *labelTempSix;
    
    @property(nonatomic,strong) UILabel *labelSymbolSix;
    
    @property(nonatomic,strong) UILabel *labelTempSeven;
    
    @property(nonatomic,strong) UILabel *labelSymbolSeven;
    
    //两个label
    @property(nonatomic,strong) UILabel *labelNameOne;
    
    @property(nonatomic,strong) UILabel *labelAddreOne;
    
    @property(nonatomic,strong) UILabel *labelNameTwo;
    
    @property(nonatomic,strong) UILabel *labelAddreTwo;
    
    @property(nonatomic,strong) UILabel *labelNameThree;
    
    @property(nonatomic,strong) UILabel *labelAddreThree;
    
    @property(nonatomic,strong) UILabel *labelNameFour;
    
    @property(nonatomic,strong) UILabel *labelAddreFour;
    
    @property(nonatomic,strong) UILabel *labelNameFive;
    
    @property(nonatomic,strong) UILabel *labelAddreFive;
    
    @property(nonatomic,strong) UILabel *labelNameSix;
    
    @property(nonatomic,strong) UILabel *labelAddreSix;
    
    @property(nonatomic,strong) UILabel *labelNameSeven;
    
    @property(nonatomic,strong) UILabel *labelAddreSeven;
    
    @property(nonatomic,strong) NormalUtil *normalUtil;
    
    @end
    
    

    LinkViewController.m

    //
    //  LinkViewController.m
    //  LHTempProject
    //
    //  Created by rnd on 2017/5/2.
    //  Copyright © 2017年 GoDream. All rights reserved.
    //
    
    #import "LinkViewController.h"
    
    #ifdef __OBJC__
    
    //define this constant if you want to use Masonry without the 'mas_' prefix
    #define MAS_SHORTHAND
    
    //define this constant if you want to enable auto-boxing for default syntax
    #define MAS_SHORTHAND_GLOBALS
    
    #import "Masonry.h"
    
    #endif
    
    @interface LinkViewController ()<UIScrollViewDelegate>
    
    @property(nonatomic,strong)OneView *one;
    @property(nonatomic,strong)TwoView *two;
    @property(nonatomic,strong)ThreeView *three;
    @property(nonatomic,strong)FourView *four;
    @property(nonatomic,strong)FiveView *five;
    @property(nonatomic,strong)SixView *six;
    @property(nonatomic,strong)SevenView *seven;
    
    @property(nonatomic,strong)UIScrollView *myscrollview;
    
    @end
    
    @implementation LinkViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        _normalUtil = [NormalUtil sharedManager];
        
        [self setUIView];
        
        [self setValues];
        
        //发现左边外设的服务 (运行到这个方法会进入leftView.m文件中的外围设备服务的代理)
        [self.oneperipheral discoverServices:nil];
        //发现右边外设的服务
        [self.twoperipheral discoverServices:nil];
        
        [self setNotification];
        
    }
    
    //初始化值显示
    -(void) setValues{
        //_labelTempOne.text = @"No Data";
        _labelTempOne.text = @"Load.";
        _labelTempTwo.text = @"Load.";
        _labelTempThree.text = @"Load.";
        _labelTempFour.text = @"Load.";
        _labelTempFive.text = @"Load.";
        _labelTempSix.text = @"Load.";
        _labelTempSeven.text = @"Load.";
        
        _labelTempOne.textAlignment = NSTextAlignmentCenter;
        _labelTempTwo.textAlignment = NSTextAlignmentCenter;
        _labelTempThree.textAlignment = NSTextAlignmentCenter;
        _labelTempFour.textAlignment = NSTextAlignmentCenter;
        _labelTempFive.textAlignment = NSTextAlignmentCenter;
        _labelTempSix.textAlignment = NSTextAlignmentCenter;
        _labelTempSeven.textAlignment = NSTextAlignmentCenter;
        
        _labelNameOne.text = @"";
        _labelAddreOne.text = @"";
        _labelNameTwo.text = @"";
        _labelAddreTwo.text = @"";
        _labelNameThree.text = @"";
        _labelAddreThree.text = @"";
        _labelNameFour.text = @"";
        _labelAddreFour.text = @"";
        _labelNameFive.text = @"";
        _labelAddreFive.text = @"";
        _labelNameSix.text = @"";
        _labelAddreSix.text = @"";
        _labelNameSeven.text = @"";
        _labelAddreSeven.text = @"";
        
    }
    
    //接收通知
    -(void)setNotification{
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionOne:) name:@"tempNofictionOne" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionTwo:) name:@"tempNofictionTwo" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionThree:) name:@"tempNofictionThree" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionFour:) name:@"tempNofictionFour" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionFive:) name:@"tempNofictionFive" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionSix:) name:@"tempNofictionSix" object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletionSeven:) name:@"tempNofictionSeven" object:nil];
    }
    
    /*
     接到温度数据的通知
     */
    -(void)tempCompletionOne:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempOne"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempOne.textAlignment = NSTextAlignmentCenter;
        _labelSymbolOne.textAlignment = NSTextAlignmentCenter;
        //这里面做数据判断
        //int temp = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempOne.text = allarry[0];
        }else if(normal == 1){
            _labelTempOne.text = @"HHH";
        }else if(normal == 2){
            _labelTempOne.text = @"LLL";
        }else{
            _labelTempOne.text = @"NONE";
        }
        _labelSymbolOne.text = allarry[1];
        _labelNameOne.text = allarry[5];
        _labelAddreOne.text = allarry[4];
    }
    
    -(void)tempCompletionTwo:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempTwo"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempTwo.textAlignment = NSTextAlignmentCenter;
        _labelSymbolTwo.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempTwo.text = allarry[0];
        }else if(normal == 1){
            _labelTempTwo.text = @"HHH";
        }else if(normal == 2){
            _labelTempTwo.text = @"LLL";
        }else{
            _labelTempTwo.text = @"NONE";
        }
        _labelSymbolTwo.text = allarry[1];
        _labelNameTwo.text = allarry[5];
        _labelAddreTwo.text = allarry[4];
    }
    
    -(void)tempCompletionThree:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempThree"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempThree.textAlignment = NSTextAlignmentCenter;
        _labelSymbolThree.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempThree.text = allarry[0];
        }else if(normal == 1){
            _labelTempThree.text = @"HHH";
        }else if(normal == 2){
            _labelTempThree.text = @"LLL";
        }else{
            _labelTempThree.text = @"NONE";
        }
        _labelSymbolThree.text = allarry[1];
        _labelNameThree.text = allarry[5];
        _labelAddreThree.text = allarry[4];
    }
    
    -(void)tempCompletionFour:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempFour"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempFour.textAlignment = NSTextAlignmentCenter;
        _labelSymbolFour.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempFour.text = allarry[0];
        }else if(normal == 1){
            _labelTempFour.text = @"HHH";
        }else if(normal == 2){
            _labelTempFour.text = @"LLL";
        }else{
            _labelTempFour.text = @"NONE";
        }
        _labelSymbolFour.text = allarry[1];
        _labelNameFour.text = allarry[5];
        _labelAddreFour.text = allarry[4];
    }
    
    -(void)tempCompletionFive:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempFive"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempFive.textAlignment = NSTextAlignmentCenter;
        _labelSymbolFive.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempFive.text = allarry[0];
        }else if(normal == 1){
            _labelTempFive.text = @"HHH";
        }else if(normal == 2){
            _labelTempFive.text = @"LLL";
        }else{
            _labelTempFive.text = @"NONE";
        }
        _labelSymbolFive.text = allarry[1];
        _labelNameFive.text = allarry[5];
        _labelAddreFive.text = allarry[4];
    }
    
    -(void)tempCompletionSix:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempSix"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempSix.textAlignment = NSTextAlignmentCenter;
        _labelSymbolSix.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempSix.text = allarry[0];
        }else if(normal == 1){
            _labelTempSix.text = @"HHH";
        }else if(normal == 2){
            _labelTempSix.text = @"LLL";
        }else{
            _labelTempSix.text = @"NONE";
        }
        _labelSymbolSix.text = allarry[1];
        _labelNameSix.text = allarry[5];
        _labelAddreSix.text = allarry[4];
    }
    
    -(void)tempCompletionSeven:(NSNotification*)notification{
        NSDictionary *temps = [notification userInfo];
        NSString *all = [temps objectForKey:@"tempSeven"];
        NSArray *allarry = [all componentsSeparatedByString:@","];
        _labelTempSeven.textAlignment = NSTextAlignmentCenter;
        _labelSymbolSeven.textAlignment = NSTextAlignmentCenter;
        //int a = [allarry[0] intValue];
        int normal = [allarry[3] intValue];
        if(normal==0){
            _labelTempSeven.text = allarry[0];
        }else if(normal == 1){
            _labelTempSeven.text = @"HHH";
        }else if(normal == 2){
            _labelTempSeven.text = @"LLL";
        }else{
            _labelTempSeven.text = @"NONE";
        }
        _labelSymbolSeven.text = allarry[1];
        _labelNameSeven.text = allarry[5];
        _labelAddreSeven.text = allarry[4];}
    
    //加载UIView
    -(void)setUIView{
        NSString *getpm = [_normalUtil getPingMuWindow];
        
        int a  = [getpm intValue];
        
        _myscrollview = [[UIScrollView alloc] init];
        _myscrollview.delegate = self;
        // 设置内容大小
        _myscrollview.contentSize = CGSizeMake(a, 1100);
        // 提示用户,Indicators flash
        //[UIScrollView flashScrollIndicators];
        // 是否同时运动,lock
        _myscrollview.scrollEnabled = YES;
        
        _myscrollview.directionalLockEnabled = YES;
        
        _myscrollview.backgroundColor = [self stringTOColor:@"#D6D6D6"];
        [self.view addSubview:_myscrollview];
        
        [_myscrollview makeConstraints:^(MASConstraintMaker *make){
            make.left.equalTo(self.view).offset(0);
            make.right.equalTo(self.view).offset(0);
            make.top.equalTo(self.view).offset(0);
            make.bottom.equalTo(self.view).offset(0);
        }];
        
        
        //创建主要的View
        UIView *mainView = [[UIView alloc] init];
        mainView.backgroundColor = [self stringTOColor:@"#D6D6D6"];
        [_myscrollview addSubview:mainView];
        
        //给主view添加约束
        [mainView makeConstraints:^(MASConstraintMaker *make){
            make.edges.equalTo(_myscrollview);
            make.width.equalTo(_myscrollview);
            //make.top.equalTo(_myscrollview).offset(64);
            make.height.equalTo(_myscrollview).multipliedBy(1.5);
        }];
        
        
        /*UIColor *blues = [self stringTOColor:@"#436EEE"];
         
         //创建一个导航栏
         UINavigationBar *navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, a, 64)];
         //创建一个导航栏集合
         UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:@"111"];
         //在这个集合Item中添加标题,按钮
         //style:设置按钮的风格,一共有三种选择
         //action:@selector:设置按钮的点击事件
         //创建一个左边按钮
         UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:@"< Back" style:UIBarButtonItemStyleDone target:self action:@selector(clickLeftButton)];
         
         //设置导航栏的内容
         [navItem setTitle:@"Display Device"];
         
         //把导航栏集合添加到导航栏中,设置动画关闭
         [navBar pushNavigationItem:navItem animated:NO];
         
         [navBar setBarTintColor:blues];
         
         //[navBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],UITextAttributeTextColor,nil]];
         
         [navBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor],
         NSFontAttributeName:[UIFont boldSystemFontOfSize:20]
         }];
         //把左右两个按钮添加到导航栏集合中去
         [navItem setLeftBarButtonItem:leftButton];
         
         [leftButton setTintColor:[UIColor whiteColor]];
         
         //将标题栏中的内容全部添加到主视图当中
         [self.view addSubview:navBar];*/
        
        //添加View头部
        UIView *topView = [UIView new];
        [mainView addSubview:topView];
        
        [topView makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(mainView).offset(0);
            make.left.equalTo(mainView).offset(0);
            make.right.equalTo(mainView).offset(0);
            make.height.equalTo(@0);
        }];
        
        
        //添加第一个显示温度view
        _one = [[OneView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _one.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_one];
        
        _oneperipheral.delegate = _one;
        
        //添加里面的布局模式
        //UIColor *bgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"circle.png"]];
        
        UIView *c1 = [[UIView alloc] init];
        
        [_one addSubview:c1];
        
        [c1 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_one).offset(10);
            make.left.equalTo(_one).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle1 = [[UIImageView alloc] init];
        circle1.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [_one addSubview:circle1];
        
        [circle1 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c1).offset(0);
            make.left.equalTo(c1).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempOne = [[UILabel alloc] init];
        
        [circle1 addSubview:_labelTempOne];
        
        [_labelTempOne makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c1).offset(15);
            make.centerX.equalTo(c1);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolOne = [[UILabel alloc] init];
        
        [circle1 addSubview:_labelSymbolOne];
        
        [_labelSymbolOne makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempOne).offset(25);
            make.centerX.equalTo(c1);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameOne  = [[UILabel alloc] init];
        _labelNameOne.text = @"";
        _labelNameOne.textColor = [UIColor blackColor];
        
        //设置字体的大小
        [_one addSubview:_labelNameOne];
        
        [_labelNameOne makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_one).offset(20);
            make.left.equalTo(_one).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreOne = [[UILabel alloc] init];
        _labelAddreOne.text = @"";
        _labelAddreOne.textColor = [UIColor blackColor];
        [_one addSubview:_labelAddreOne];
        
        [_labelAddreOne makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_one).offset(50);
            make.left.equalTo(_one).offset(130);
            make.width.equalTo(@200);
            make.height.equalTo(@30);
        }];
        
        
        //添加第二个view
        _two = [[TwoView alloc]initWithFrame:CGRectMake(0, 101, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _two.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_two];
        
        _twoperipheral.delegate = _two;
        
        UIView *c2 = [[UIView alloc] init];
        
        [_two addSubview:c2];
        
        [c2 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_two).offset(10);
            make.left.equalTo(_two).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle2 = [[UIImageView alloc] init];
        circle2.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c2 addSubview:circle2];
        
        [circle2 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c2).offset(0);
            make.left.equalTo(c2).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempTwo = [[UILabel alloc] init];
        
        [c2 addSubview:_labelTempTwo];
        
        [_labelTempTwo makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c2).offset(15);
            make.centerX.equalTo(c2);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolTwo = [[UILabel alloc] init];
        
        [c2 addSubview:_labelSymbolTwo];
        
        [_labelSymbolTwo makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempTwo).offset(25);
            make.centerX.equalTo(c2);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameTwo  = [[UILabel alloc] init];
        _labelNameTwo.text = @"";
        _labelNameTwo.textColor = [UIColor blackColor];
        [_two addSubview:_labelNameTwo];
        
        [_labelNameTwo makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_two).offset(20);
            make.left.equalTo(_two).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreTwo = [[UILabel alloc] init];
        _labelAddreTwo.text = @"";
        _labelAddreTwo.textColor = [UIColor blackColor];
        [_two addSubview:_labelAddreTwo];
        
        [_labelAddreTwo makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_two).offset(50);
            make.left.equalTo(_two).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        //添加第三个view
        _three = [[ThreeView alloc]initWithFrame:CGRectMake(0, 202, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _three.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_three];
        
        _threeperipheral.delegate = _three;
        
        UIView *c3 = [[UIView alloc] init];
        
        [_three addSubview:c3];
        
        [c3 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_three).offset(10);
            make.left.equalTo(_three).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle3 = [[UIImageView alloc] init];
        circle3.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c3 addSubview:circle3];
        
        [circle3 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c3).offset(0);
            make.left.equalTo(c3).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempThree = [[UILabel alloc] init];
        
        [c3 addSubview:_labelTempThree];
        
        [_labelTempThree makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c3).offset(15);
            make.centerX.equalTo(c3);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolThree = [[UILabel alloc] init];
        
        [c3 addSubview:_labelSymbolThree];
        
        [_labelSymbolThree makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempThree).offset(25);
            make.centerX.equalTo(c3);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameThree  = [[UILabel alloc] init];
        _labelNameThree.text = @"";
        _labelNameThree.textColor = [UIColor blackColor];
        [_three addSubview:_labelNameThree];
        
        [_labelNameThree makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_three).offset(20);
            make.left.equalTo(_three).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreThree = [[UILabel alloc] init];
        _labelAddreThree.text = @"";
        _labelAddreThree.textColor = [UIColor blackColor];
        [_three addSubview:_labelAddreThree];
        
        [_labelAddreThree makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_three).offset(50);
            make.left.equalTo(_three).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        //添加第4个view
        _four = [[FourView alloc]initWithFrame:CGRectMake(0, 303, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _four.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_four];
        _fourperipheral.delegate = _four;
        UIView *c4 = [[UIView alloc] init];
        [_four addSubview:c4];
        [c4 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_four).offset(10);
            make.left.equalTo(_four).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle4 = [[UIImageView alloc] init];
        circle4.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c4 addSubview:circle4];
        
        [circle4 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c4).offset(0);
            make.left.equalTo(c4).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempFour = [[UILabel alloc] init];
        
        [c4 addSubview:_labelTempFour];
        
        [_labelTempFour makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c4).offset(15);
            make.centerX.equalTo(c4);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolFour = [[UILabel alloc] init];
        
        [c4 addSubview:_labelSymbolFour];
        
        [_labelSymbolFour makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempFour).offset(25);
            make.centerX.equalTo(c4);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameFour  = [[UILabel alloc] init];
        _labelNameFour.text = @"";
        _labelNameFour.textColor = [UIColor blackColor];
        [_four addSubview:_labelNameFour];
        
        [_labelNameFour makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_four).offset(20);
            make.left.equalTo(_four).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreFour = [[UILabel alloc] init];
        _labelAddreFour.text = @"";
        _labelAddreFour.textColor = [UIColor blackColor];
        [_four addSubview:_labelAddreFour];
        
        [_labelAddreFour makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_four).offset(50);
            make.left.equalTo(_four).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        
        //添加第5个view
        _five = [[FiveView alloc]initWithFrame:CGRectMake(0, 404, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _five.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_five];
        _fiveperipheral.delegate = _five;
        UIView *c5 = [[UIView alloc] init];
        [_five addSubview:c5];
        [c5 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_five).offset(10);
            make.left.equalTo(_five).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle5 = [[UIImageView alloc] init];
        circle5.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c5 addSubview:circle5];
        
        [circle5 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c5).offset(0);
            make.left.equalTo(c5).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempFive = [[UILabel alloc] init];
        
        [c5 addSubview:_labelTempFive];
        
        [_labelTempFive makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c5).offset(15);
            make.centerX.equalTo(c5);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolFive = [[UILabel alloc] init];
        
        [c5 addSubview:_labelSymbolFive];
        
        [_labelSymbolFive makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempFive).offset(25);
            make.centerX.equalTo(c4);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameFive  = [[UILabel alloc] init];
        _labelNameFive.text = @"";
        _labelNameFive.textColor = [UIColor blackColor];
        [_five addSubview:_labelNameFive];
        
        [_labelNameFive makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_five).offset(20);
            make.left.equalTo(_five).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreFive = [[UILabel alloc] init];
        _labelAddreFive.text = @"";
        _labelAddreFive.textColor = [UIColor blackColor];
        [_five addSubview:_labelAddreFive];
        
        [_labelAddreFive makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_five).offset(50);
            make.left.equalTo(_five).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        
        //第六个view
        _six = [[SixView alloc]initWithFrame:CGRectMake(0, 505, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _six.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_six];
        _sexperipheral.delegate = _six;
        UIView *c6 = [[UIView alloc] init];
        [_six addSubview:c6];
        [c6 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_six).offset(10);
            make.left.equalTo(_six).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle6 = [[UIImageView alloc] init];
        circle6.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c6 addSubview:circle6];
        
        [circle6 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c6).offset(0);
            make.left.equalTo(c6).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempSix = [[UILabel alloc] init];
        
        [c6 addSubview:_labelTempSix];
        
        [_labelTempSix makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c6).offset(15);
            make.centerX.equalTo(c6);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolSix = [[UILabel alloc] init];
        
        [c6 addSubview:_labelSymbolSix];
        
        [_labelSymbolSix makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempSix).offset(25);
            make.centerX.equalTo(c6);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameSix  = [[UILabel alloc] init];
        _labelNameSix.text = @"";
        _labelNameSix.textColor = [UIColor blackColor];
        [_six addSubview:_labelNameSix];
        
        [_labelNameSix makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_six).offset(20);
            make.left.equalTo(_six).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreSix = [[UILabel alloc] init];
        _labelAddreSix.text = @"";
        _labelAddreSix.textColor = [UIColor blackColor];
        [_six addSubview:_labelAddreSix];
        
        [_labelAddreSix makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_six).offset(50);
            make.left.equalTo(_six).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        
        //第7个view
        _seven = [[SevenView alloc]initWithFrame:CGRectMake(0, 606, [UIScreen mainScreen].bounds.size.width, 100)];
        
        _seven.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:_seven];
        _sevenperipheral.delegate = _seven;
        UIView *c7 = [[UIView alloc] init];
        [_seven addSubview:c7];
        [c7 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_seven).offset(10);
            make.left.equalTo(_seven).offset(35);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        UIImageView *circle7 = [[UIImageView alloc] init];
        circle7.image = [UIImage imageNamed:@"circle.png"];
        //[circle1 setBackgroundColor:bgColor];
        
        [c7 addSubview:circle7];
        
        [circle7 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c7).offset(0);
            make.left.equalTo(c7).offset(0);
            make.width.equalTo(@80);
            make.height.equalTo(@80);
        }];
        
        _labelTempSeven = [[UILabel alloc] init];
        
        [c7 addSubview:_labelTempSeven];
        
        [_labelTempSeven makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(c7).offset(15);
            make.centerX.equalTo(c7);
            make.width.equalTo(@80);
            make.height.equalTo(@30);
        }];
        
        _labelSymbolSeven = [[UILabel alloc] init];
        
        [c7 addSubview:_labelSymbolSeven];
        
        [_labelSymbolSeven makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_labelTempSeven).offset(25);
            make.centerX.equalTo(c6);
            make.width.equalTo(@80);
            make.height.equalTo(@25);
        }];
        
        //添加第一个2个label
        _labelNameSeven  = [[UILabel alloc] init];
        _labelNameSeven.text = @"";
        _labelNameSeven.textColor = [UIColor blackColor];
        [_seven addSubview:_labelNameSeven];
        
        [_labelNameSeven makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_seven).offset(20);
            make.left.equalTo(_seven).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        _labelAddreSeven = [[UILabel alloc] init];
        _labelAddreSeven.text = @"";
        _labelAddreSeven.textColor = [UIColor blackColor];
        [_seven addSubview:_labelAddreSeven];
        
        [_labelAddreSeven makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(_seven).offset(50);
            make.left.equalTo(_seven).offset(130);
            make.width.equalTo(@100);
            make.height.equalTo(@30);
        }];
        
        
        //备用一个
        UIView *cys8 = [[UIView alloc] init];
        cys8.backgroundColor = [UIColor whiteColor];
        [mainView addSubview:cys8];
        
        [cys8 makeConstraints:^(MASConstraintMaker *make){
            make.top.equalTo(mainView).offset(707);
            make.left.equalTo(mainView).offset(0);
            make.right.equalTo(mainView).offset(0);
            make.bottom.equalTo(mainView).offset(0);
        }];
        
    }
    
    -(void)clickLeftButton{
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    
    - (BOOL)navigationShouldPopOnBackButton{
        [self dismissViewControllerAnimated:YES completion:nil];
        return YES;
    }
    
    /*
     * 字符串转为颜色值
     */
    - (UIColor *) stringTOColor:(NSString *)str
    {
        if (!str || [str isEqualToString:@""]) {
            return nil;
        }
        unsigned red,green,blue;
        NSRange range;
        range.length = 2;
        range.location = 1;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&red];
        range.location = 3;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&green];
        range.location = 5;
        [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&blue];
        UIColor *color= [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1];
        return color;
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        
    }
    
    // 是否支持滑动至顶部
    - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
    {
        return YES;
    }
    
    @end
    
    

    上面的代码 我用的是通过 接收到蓝牙的通知来 更新温度数据的显示。

    上面这个版本写的太low了 如果你想要更高级的连接方式请查看

    https://github.com/QuickDevelopers/BleManageSwift

    这个库我一直会维护

    源码如下:

    http://download.csdn.net/download/a1989214/9968056

    展开全文
  • BluetoothChat手机与串口模块通信...小黄人独家推出基于bluetoothchat的,手机靠近蓝牙模块自动连接蓝牙模块,断后自动重连,多设备自由切换,记忆连接,可后台运行。连接成功率百分之百。可以应用在工业通讯,手...

    BluetoothChat手机与串口模块通信靠近自动连接2.0apk示例:链接: https://pan.baidu.com/s/1YoMNNBfLTAuXm2XukG5s9g 提取码: sm3h

     

    全球首创的新技术。小黄人独家推出基于bluetoothchat的,手机靠近蓝牙模块自动连接蓝牙模块,断后自动重连,多设备自由切换,记忆连接,可后台运行。连接成功率百分之百。可以应用在工业通讯,手机游戏,自动解锁等领域。也可以手机靠近手机自动连接,换UUID即可。欢迎定制。

    1.初次连接要配对。

    2.蓝牙未打开会提示打开。这个也可以设为自动打开,得延时,一般5秒,且返回值不知什么时候返回,所以不用这种方法,以前老版本是用这个方法。

    3.各状态都有提示。连接成功,断开,丢失,无法连接等。

    4.按返回键,可后台运行。

    5.在有效范围内自动连接,断后自动重连。

    可选的定制功能有:十六进制/字符切换发送与接收,按键名与命令自定义,界面,保存,接收处理,通信协议自定义。

    有问题请留言。

    --------by 小黄人软件

    BluetoothChatService.java源码:

     

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.example.android.BluetoothChat;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.UUID;
    
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothServerSocket;
    import android.bluetooth.BluetoothSocket;
    import android.content.Context;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    /**
     * This class does all the work for setting up and managing Bluetooth
     * connections with other devices. It has a thread that listens for
     * incoming connections, a thread for connecting with a device, and a
     * thread for performing data transmissions when connected.
     */
    public class BluetoothChatService {
        // Debugging
        private static final String TAG = "BluetoothChatService";
        private static final boolean D = true;
    
        // Name for the SDP record when creating server socket
        private static final String NAME = "BluetoothChat";
    
        // Unique UUID for this application
    						 				
    //	private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    	private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//¥Æø⁄  	
    
        // Member fields
        private final BluetoothAdapter mAdapter;
        private final Handler mHandler;
        private AcceptThread mAcceptThread;
        private ConnectThread mConnectThread;
        private ConnectedThread mConnectedThread;
        private int mState;
    
        // Constants that indicate the current connection state
        public static final int STATE_NONE = 0;       // we're doing nothing
        public static final int STATE_LISTEN = 1;     // now listening for incoming connections
        public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
        public static final int STATE_CONNECTED = 3;  // now connected to a remote device
    
        /**
         * Constructor. Prepares a new BluetoothChat session.
         * @param context  The UI Activity Context
         * @param handler  A Handler to send messages back to the UI Activity
         */
        public BluetoothChatService(Context context, Handler handler) {
            mAdapter = BluetoothAdapter.getDefaultAdapter();
            mState = STATE_NONE;
            mHandler = handler;
        }
    
        /**
         * Set the current state of the chat connection
         * @param state  An integer defining the current connection state
         */
        private synchronized void setState(int state) {
            if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
            mState = state;
    
            // Give the new state to the Handler so the UI Activity can update
            mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
        }
    
        /**
         * Return the current connection state. */
        public synchronized int getState() {
            return mState;
        }
    
        /**
         * Start the chat service. Specifically start AcceptThread to begin a
         * session in listening (server) mode. Called by the Activity onResume() */
        public synchronized void start() {
            if (D) Log.d(TAG, "start");
    
            // Cancel any thread attempting to make a connection
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
    
            // Cancel any thread currently running a connection
            if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
    
            // Start the thread to listen on a BluetoothServerSocket
            if (mAcceptThread == null) {
                mAcceptThread = new AcceptThread();
                mAcceptThread.start();
            }
            setState(STATE_LISTEN);
        }
    
        /**
         * Start the ConnectThread to initiate a connection to a remote device.
         * @param device  The BluetoothDevice to connect
         */
        public synchronized void connect(BluetoothDevice device) {
            if (D) Log.d(TAG, "connect to: " + device);
    
            // Cancel any thread attempting to make a connection
            if (mState == STATE_CONNECTING) {
                if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
            }
    
            // Cancel any thread currently running a connection
            if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
    
            // Start the thread to connect with the given device
            mConnectThread = new ConnectThread(device);
            mConnectThread.start();
            setState(STATE_CONNECTING);
        }
    
        /**
         * Start the ConnectedThread to begin managing a Bluetooth connection
         * @param socket  The BluetoothSocket on which the connection was made
         * @param device  The BluetoothDevice that has been connected
         */
        public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
            if (D) Log.d(TAG, "connected");
    
            // Cancel the thread that completed the connection
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
    
            // Cancel any thread currently running a connection
            if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
    
            // Cancel the accept thread because we only want to connect to one device
            if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
    
            // Start the thread to manage the connection and perform transmissions
            mConnectedThread = new ConnectedThread(socket);
            mConnectedThread.start();
    
            // Send the name of the connected device back to the UI Activity
            Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
            Bundle bundle = new Bundle();
            bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
            bundle.putString(BluetoothChat.DEVICE_ADDRESS, device.getAddress());
            msg.setData(bundle);
            mHandler.sendMessage(msg);
    
            setState(STATE_CONNECTED);
        }
    
        /**
         * Stop all threads
         */
        public synchronized void stop() {
            if (D) Log.d(TAG, "stop");
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
            if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
            if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
            setState(STATE_NONE);
        }
    
        /**
         * Write to the ConnectedThread in an unsynchronized manner
         * @param out The bytes to write
         * @see ConnectedThread#write(byte[])
         */
        public void write(byte[] out) {
            // Create temporary object
            ConnectedThread r;
            // Synchronize a copy of the ConnectedThread
            synchronized (this) {
                if (mState != STATE_CONNECTED) return;
                r = mConnectedThread;
            }
            // Perform the write unsynchronized
            r.write(out);
        }
    
        /**
         * Indicate that the connection attempt failed and notify the UI Activity.
         */
        private void connectionFailed() {
            setState(STATE_LISTEN);
    
            // Send a failure message back to the Activity
            Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    
        /**
         * Indicate that the connection was lost and notify the UI Activity.
         */
        private void connectionLost() {
            setState(STATE_LISTEN);
    
            // Send a failure message back to the Activity
            Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    
        /**
         * This thread runs while listening for incoming connections. It behaves
         * like a server-side client. It runs until a connection is accepted
         * (or until cancelled).
         */
        private class AcceptThread extends Thread {
            // The local server socket
            private final BluetoothServerSocket mmServerSocket;
    
            public AcceptThread() {
                BluetoothServerSocket tmp = null;
    
                // Create a new listening server socket
                try {
                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
                } catch (IOException e) {
                    Log.e(TAG, "listen() failed", e);
                }
                mmServerSocket = tmp;
            }
    
            public void run() {
                if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
                setName("AcceptThread");
                BluetoothSocket socket = null;
    
                // Listen to the server socket if we're not connected
                while (mState != STATE_CONNECTED) {
                    try {
                        // This is a blocking call and will only return on a
                        // successful connection or an exception
                        socket = mmServerSocket.accept();
                    } catch (IOException e) {
                        Log.e(TAG, "accept() failed", e);
                        break;
                    }
    
                    // If a connection was accepted
                    if (socket != null) {
                        synchronized (BluetoothChatService.this) {
                            switch (mState) {
                            case STATE_LISTEN:
                            case STATE_CONNECTING:
                                // Situation normal. Start the connected thread.
                                connected(socket, socket.getRemoteDevice());
                                break;
                            case STATE_NONE:
                            case STATE_CONNECTED:
                                // Either not ready or already connected. Terminate new socket.
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    Log.e(TAG, "Could not close unwanted socket", e);
                                }
                                break;
                            }
                        }
                    }
                }
                if (D) Log.i(TAG, "END mAcceptThread");
            }
    
            public void cancel() {
                if (D) Log.d(TAG, "cancel " + this);
                try {
                    mmServerSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "close() of server failed", e);
                }
            }
        }
    
    
        /**
         * This thread runs while attempting to make an outgoing connection
         * with a device. It runs straight through; the connection either
         * succeeds or fails.
         */
        private class ConnectThread extends Thread {
            private final BluetoothSocket mmSocket;
            private final BluetoothDevice mmDevice;
    
            public ConnectThread(BluetoothDevice device) {
                mmDevice = device;
                BluetoothSocket tmp = null;
    
                // Get a BluetoothSocket for a connection with the
                // given BluetoothDevice
                try {
                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
                } catch (IOException e) {
                    Log.e(TAG, "create() failed", e);
                }
                mmSocket = tmp;
            }
    
            public void run() {
                Log.i(TAG, "BEGIN mConnectThread");
                setName("ConnectThread");
    
                // Always cancel discovery because it will slow down a connection
                mAdapter.cancelDiscovery();
    
                // Make a connection to the BluetoothSocket
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    mmSocket.connect();
                } catch (IOException e) {
                    connectionFailed();
                    // Close the socket
                    try {
                        mmSocket.close();
                    } catch (IOException e2) {
                        Log.e(TAG, "unable to close() socket during connection failure", e2);
                    }
                    // Start the service over to restart listening mode
                    BluetoothChatService.this.start();
                    return;
                }
    
                // Reset the ConnectThread because we're done
                synchronized (BluetoothChatService.this) {
                    mConnectThread = null;
                }
    
                // Start the connected thread
                connected(mmSocket, mmDevice);
            }
    
            public void cancel() {
                try {
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "close() of connect socket failed", e);
                }
            }
        }
    
        /**
         * This thread runs during a connection with a remote device.
         * It handles all incoming and outgoing transmissions.
         */
        private class ConnectedThread extends Thread {
            private final BluetoothSocket mmSocket;
            private final InputStream mmInStream;
            private final OutputStream mmOutStream;
    
            public ConnectedThread(BluetoothSocket socket) {
                Log.d(TAG, "create ConnectedThread");
                mmSocket = socket;
                InputStream tmpIn = null;
                OutputStream tmpOut = null;
    
                // Get the BluetoothSocket input and output streams
                try {
                    tmpIn = socket.getInputStream();
                    tmpOut = socket.getOutputStream();
                } catch (IOException e) {
                    Log.e(TAG, "temp sockets not created", e);
                }
    
                mmInStream = tmpIn;
                mmOutStream = tmpOut;
            }
    
            public void run() {
                Log.i(TAG, "BEGIN mConnectedThread");
                byte[] buffer = new byte[1024];
                int bytes;
    
                // Keep listening to the InputStream while connected
                while (true) {
                    try {
                        // Read from the InputStream
                        bytes = mmInStream.read(buffer);
    
                        // Send the obtained bytes to the UI Activity
                        mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                                .sendToTarget();
                    } catch (IOException e) {
                        Log.e(TAG, "disconnected", e);
                        connectionLost();
                        break;
                    }
                }
            }
    
            /**
             * Write to the connected OutStream.
             * @param buffer  The bytes to write
             */
            public void write(byte[] buffer) {
                try {
                    mmOutStream.write(buffer);
    
                    // Share the sent message back to the UI Activity
                    mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
                            .sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "Exception during write", e);
                }
            }
    
            public void cancel() {
                try {
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "close() of connect socket failed", e);
                }
            }
        }
    }
    

     

     

     

     

     

    展开全文
  • Android实现一个App同时通过蓝牙连接或多设备,并同时获取他们返回的数据,有没有什么办法可以实现? 要是有Demo就更好啦。
    Android实现一个App同时通过蓝牙连接两台或多台设备,并同时获取他们返回的数据,有没有什么办法可以实现?
    
    要是有Demo就更好啦。
    展开全文
  • IOS-蓝牙后台连接

    2015-06-11 10:40:54
    最近在公司负责项目中得蓝牙通信这块,有一个无法避免的问题是,要求程序在进入后台,或者是手机处于锁屏状态下时仍然能保持蓝牙连接且能正常接收数据。本来以为要添加一些判断之类的代码,其实实现起来很简单:
  • 最近简单弄手机蓝牙连多设备,如蓝牙打印机,蓝牙扫描仪等等,需要手机蓝牙可以同时操作多设备的需求,简单的了解了一下。 目前手机蓝牙一般可以连多设备了,版本好像是蓝牙4.2以上,好像也可以多个蓝牙设备...
  • iOS 蓝牙连接设备

    2021-02-02 11:20:53
    手机可以同时连接个蓝牙设备吗
  • 本次是更新了的蓝牙4.0连接设备并能够读取各各设备的数据,已经修复完成,可以使用并有讲解过程
  • android手机蓝牙自动配对,连接,互发消息示例

    千次下载 热门讨论 2012-08-27 09:00:27
    2.另一台手机运行程序后选择客户端,自动搜索选择了服务端的手机,进行自动配对(第一次手机之间的配对需要人工确认,后面不需要),并自动连接。这时在两台手机上均可看见连接成功,然后可以互发消息进行聊天 3....
  • Android 蓝牙连接

    千次阅读 2019-05-01 18:06:32
    最多可以同时和7其它蓝牙设备建立连接,进行通信。蓝牙可分为两大类:传统蓝牙蓝牙3.0规范之前),低功耗蓝牙蓝牙4.0规范之后)。 Android 从4.3版本(API Level 18)开始支持低功耗蓝牙Bluetooth Low Energy...
  • 大家好,今天带来的是关于QCY-T5真无线蓝牙耳机游戏延时的测试,这款耳机...接下来就实际测试一下这款蓝牙耳机在不同设备上的延迟表现,这里我选用了两台手机一台苹果8、一台红米NOTE8 PRO,两台手机都是蓝牙5.0的...
  • 但电脑可以同时蓝牙连接2台天猫精灵,但系统默认只能选一个默认蓝牙输出设备。 微软官方说法:“您的电脑可以链接多个蓝牙设备,但是在选择作为输入设备时只能够使用其中的一个设备作为默认设备。如果您是链接两套...
  • 一个能够连接台蓝牙设备的库,它可以作为client端,也可以为server端。支持主机/从机,外围设备连接。在发送消息时,它内部支持队列控制,避免因蓝牙间隔出现操作失败的情况。 开始使用 1. 主机client 扫描...
  • 蓝牙BLE如何连接连接设备

    千次阅读 2016-12-31 05:24:28
    现在能实现的是一个设备与平板连接并传输数据,请问能不能实现两太设备同时连接平板并传输数据?
  • Android蓝牙A2DP连接实现

    千次阅读 2019-03-10 14:26:47
    开发环境: 开发工具:Androidstudio ...开发功能:Android中蓝牙连接A2DP设备,蓝牙耳机设备 功能实现: 本应用提供以下功能: 第:开启蓝牙:查找过滤掉A2DP设备 第三:连接A2DP设备 ...
  • 1.在写Demo时,用测试机连接蓝牙打印机,发现P7可以连接,而其余的手机都连接失败,找了上午资料也没解决这问题。 接着我把P7的蓝牙断开,这样我用别的手机就连接上了。 说明:出现有手机能连上,其余手机...
  • 1.一台手机运行程序后选择服务端,自动打开蓝牙蓝牙被发现(手机的打开蓝牙被发现功能需要人工确认),等待被连接 2.另一台手机运行程序后选择客户端,自动搜索选择了服务端的手机,进行自动配对(手机与手机的...
  • 但是,由于采用了称为Multipoint的协议,许多蓝牙耳机可以连接到多设备。 并非所有耳机都支持它,但是Bose,Sennheiser,Beats等制造商的大多数中高端耳机都支持。 甚至来自Jabra等制造商的廉价耳机也具有...
  • Filco圣手二代键盘蓝牙连接方法

    千次阅读 2021-04-08 09:50:51
    按下小键盘中数字键1-4中的一个(一共可以连4设备) (如果你选的数字之前连接过其他设备,可以在第2步做完之后先按两秒清除按钮,再选择数字。清除按钮在蓝灯和红灯右边。) 在要连接的设备(以电脑为例)中,...
  • 如何让一个TWS连接个手机

    千次阅读 2019-05-14 10:54:13
    首先我们先和第一台手机连接,配对后取出其中一耳机。 接着,关闭充电盒盖子,跟第一台已连接TWS的手机保持一定的距离(10米以上),再长按充电盒背部的按钮,重置TWS,再跟第台手机配对连接。 这样,TWS就能...
  • 首先要打开手机蓝牙功能,平常大家不用...选择打开蓝牙步骤:设置蓝牙,配对蓝牙蓝牙界面里按菜单键可以看到重命名、超时检测、显示接受到的文件三菜单,重命名可以把手机命名为自己喜欢的容易识别的名称 比...
  • 1.手机安装GPSshare,本地或...3.如果使用蓝牙配对连接,虚拟串口软件连接手机的ip:50000端口,生成一个GPS串口。市场有人说不支持wifi连接其实可以支持,勾选gpsshare的usb模式,连接手机wifi的ip:50000即可。 4.完成
  • 安卓蓝牙搜索的最大时间长度是多少,一个手机最多能够搜索到多少其他的设备
  • 当通过蓝牙与另手机配对时,您可以发送您的错误来攻击您的对手。 你也会受到错误的攻击。 你将需要使用你最强大的武器,手指来杀死他们。 每种类型的错误都有不同的能力。 当你用完你的HP时,你就输了。 怎么玩...
  • 原文2016-09 博客搬家过来的文章之前给孩子上机器人课买过一个机器人, 是用USB连接的,每次调试程序都要插上USB线, 然后拔下来之后, 试验.很不方便.乐高EV3有蓝牙方便多了, EV3可以放在地上, 直接在电脑里调程序,不用...
  • :win7如何连接多媒体电脑蓝牙音箱,win7连接多媒体电脑蓝牙音箱win7如何连接多媒体电脑蓝牙音箱,win7连接多媒体电脑蓝牙音箱多媒体电脑蓝牙音箱用途广泛,非常时尚,已经成为很多潮流人士的听音伙伴,拥有款...
  • 整理一个蓝牙开源库

    2020-11-26 15:38:06
    公司要做一个蓝牙项目,关于蓝牙的需求就是蓝牙连接医疗设备,设备测出数据后通过蓝牙发送给手机/平板,时间有限,就在GitHub上找了一个蓝牙开源库,用起来还不错 地址:...
  • SoundLink Revolve 蓝牙扬声器 SoundLink Revolve+ 蓝牙扬声器 您可以将您的 Bose 扬声器配对在一起,然后使用 Bose Connect 应用程序(推荐)或扬声器的控制按钮在以下模式下播放: 派对模式(同时播放左右扬声器...
  • 分钟读懂低功耗蓝牙(BLE)连接数据包1.概述 BLE 连接过程中有三重要的数据包:SCAN_REQ, SCAN_RSP 和 CONNECT_REQ。 SCAN_REQ: 扫描请求,由主设备(MASTER DEVICE)向从设备(SLAVE DEVICE)发出,目的是...
  • 当用户使用TWS耳机时,手机通过蓝牙发送数据至一个耳机接收端,此接收端会把立体声通过无线传输的方式转发到另一个接收端,组成立体声系统。早期的TWS耳机很大的缺点就在于左右耳机接收数据存在延迟,如果不解决此...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,921
精华内容 5,968
关键字:

一台手机连接2个蓝牙