蓝牙4.0BLE

//
//  Created by watering on 2017/6/22.
//  Copyright © 2017年 watering. All rights reserved.
//

#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "DeviceCommand.h"

@interface ViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate, DeviceCommandDelegate>

/** 中心设备管理器 */
@property (nonatomic, strong) CBCentralManager *centralManager;
/** 外设【注意:对要连接的外设需要进行强引用,否则会报错】 */
@property (nonatomic, strong) CBPeripheral *peripheral;
/** 配对信息(存放Data) */
@property (nonatomic, strong) NSArray<NSData *> *pairAuthDatas;
/** 显示外设名称,点击并连接外设 */
@property (weak, nonatomic) IBOutlet UIButton *showPeripheralName;
/** com */
@property (nonatomic, strong) DeviceCommand *deciceCommand;
@end

@implementation ViewController

#pragma mark - othe
/**
 一、
 1、CBUUID 对象是用于 BLE 通信中 128 位的唯一标示符。peripheral 的 service,characteristic,characteristic descriptor 都包含这个属性。这个类包含了一系列生成 UUID 的方法。
 2、UUID 有 16 位的,也有 128 位的。其中 SIG 组织提供了一部分 16 位的 UUID,这部分 UUID 主要用于公共设备,例如有个用蓝牙连接的心率监测仪,如果是用的公共的 UUID,那么无论谁做一个 app,都可以进行连接,因为它的 UUID 是 SIG 官方提供的,是公开的。如果公司是要做一个只能自己的 app 才能连接的设备,那么就需要硬件方面自定义 UUID。(关于这方面,包括通信的 GATT 协议、广播流程等详细介绍,可以看 http://www.cnblogs.com/QianChia/p/6366672.html 这篇文章。讲得比较详细,能在很大程度上帮助我们理解 BLE 通信)。
 3、CBUUID 类提供了可以将 16 位 UUID 转为 128 位 UUID 的方法。下面的代码是 SIG 提供的 16 位的心率 service UUID 转为 128 位 UUID 的方法: CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString:@"180D"];
 
 4、如果需要获取 NSString 形式的 UUID,可以访问 CBUUID 的 UUIDString 只读属性。
    NSString *uuidString = [CBUUID UUIDWithString:ServiceUUIDString1].UUIDString;
  
 二、外设唯一标识符
   在有些时候,需要获取 peripheral 的唯一标示符(比如要做自动连接或绑定用户等操作),但是在搜索到 peripheral 之后,只能拿到 identifier,而且这个 identifier 根据连接的 central 不同而不同。也就是说,不同的手机连上之后,identifier 是不同的。虽然比较坑爹,但是这并不影响你做蓝牙自动连接。
    以下都是CBPeripheral(外设)系统自带属性:
    name:蓝牙设备的名称(我们可以通过名称做蓝牙自动连接,一般同意外设名称是有自己的风格的)
    RSSI:蓝牙设备的信号强度
    state:蓝牙设备的连接状态,枚举值(CBPeripheralState)
    services:蓝牙设备包含的服务(服务都是存在一个数组中)
    identifier:蓝牙设备的 UUID 标识符
 
 三、接收 characteristic 数据
    接收 characteristic 数据的方式有两种:
    1、在需要接收数据的时候,调用 readValueForCharacteristic:,这种是需要主动去接收的。
    2、用 setNotifyValue:forCharacteristic: 方法订阅,当有数据发送时,可以直接在回调中接收。
    如果 characteristic 的数据经常变化,那么采用订阅的方式更好。
 
 四、再次连接外设(重连)
    1、调用 retrievePeripheralsWithIdentifiers: 方法,重连已知的 peripheral 列表中的 peripheral(以前发现的,或者以前连接过的)。
    2、调用 retrieveConnectedPeripheralsWithServices: 方法,重新连接当前【系统】已经连接的 peripheral。
    3、调用 scanForPeripheralsWithServices:options: 方法,连接搜索到的 peripheral。
 */

#pragma mark - lazy
#pragma mark -
- (NSArray<NSData *> *)pairAuthDatas
{
    if (!_pairAuthDatas) {
        // 具体开发时,根据配对协议加载配对需要的数据
//        _pairAuthDatas = ;
    }
    return _pairAuthDatas;
}

#pragma mark - 系统回调
#pragma mark -
- (void)viewDidLoad
{
    [super viewDidLoad];

}

#pragma mark - 事件响应
#pragma mark -
/** 初始化 中心设备管理器 */
- (IBAction)start:(UIButton *)sender
{
    // 1、初始化 中心设备管理器, 将 self 设置为代理,用于接收各种 central 事件,触发回调【centralManagerDidUpdateState:】将 queue 设置为 nil,则表示直接在主线程中运行
    // 2、初始化 中心设备管理器 之后,设置的代理会调用 centralManagerDidUpdateState: 方法,所以需要去遵循 <CBCentralManagerDelegate> 协议。这个 centralManagerDidUpdateState 的方法,能获得当前设备是否能作为 central。
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}


/** 连接外设 */
- (IBAction)connectionBut:(UIButton *)sender
{
    
}

/** 断开连接 */
- (IBAction)clickDisconnectBut:(UIButton *)sender
{
    [self disconnectPeripheral:self.centralManager peripheral:self.peripheral];
    
}

/** 初始化 */
- (void)deciceCommandInit:(CBPeripheral *)peripheral
{
    self.deciceCommand = [[DeviceCommand alloc] init];
    self.deciceCommand.delegate = self;
    [self.deciceCommand peripheral:peripheral receiveData:0];
//    [self.deciceCommand peripheral:peripheral deleteData:0];
}

#pragma mark - 数据传输代理<DeviceCommandDelegate>
- (void)getDeviceData:(NSDictionary *)dicDeviceData
{
    NSLog(@"手环获取数据 == %@",dicDeviceData);
}

- (void)getError:(NSDictionary *)dicError
{
    NSLog(@"错误码 == %@",dicError);
}

-(void)getOperateResult:(NSDictionary *)dicOperateResult
{
    NSLog(@"操作结果 == %@",dicOperateResult);
}



#pragma mark - 私有方法
#pragma mark -
// 2、扫描外设
/** 开始扫描周围外设 */
- (void)sacnNearPerpherals
{
    NSLog(@"调用【开始扫描周围外设】方法");
    // 第一个参数为 Services(服务) 的 UUID(外设端的 UUID),nil 为扫描周围所有的外设。在实际应用中,你可以传入一个 CBUUID 的数组(注意,这个 UUID 是 service 的 UUID 数组),表示只搜索当前数组包含的设备(每个 peripheral 的 service 都有唯一标识 UUID)。所以,如果你传入了这样一个数组,那么 central manager 则只会去搜素包含这些 service UUID 的 Peripheral。CBUUID 是和 peripheral 相关的,和 central 本身关系不大,如果你是做的硬件对接,那么可以向硬件同事询问。
    // 第二参数的 CBCentralManagerScanOptionAllowDuplicatesKey 为已发现的设备是否重复扫描,YES 同一设备会多次回调。nil 时默认为 NO。
    NSDictionary *dic = @{CBCentralManagerScanOptionAllowDuplicatesKey : @NO};
    
    // 此方法为连接搜索到的 外设,也就是说每次搜索到 外设 后由用户连接指定 外设
    [self.centralManager scanForPeripheralsWithServices:nil options:dic];
}

// 3、连接外设
/** 连接指定的设备 */
- (void)connectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"调用【连接指定的设备】方法");
    // 设置外设连接的规则
    if ([peripheral.name hasPrefix:@"S"]) {
        self.peripheral = peripheral;
        // 显示外设名称
        [self.showPeripheralName setTitle:peripheral.name forState:UIControlStateNormal];
        // 扫描到指定设备之后便可调用系统Api来连接外设
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}

// 4、扫描外设中的服务和特征
/** 扫描外设中的服务和特征 */
- (void)discoverPeripheralServices:(CBPeripheral *)peripheral
{
    /** 【注意】设备连接成功后,就可以扫描设备的服务了,同样是通过委托形式,扫描到结果后会进入委托方法。但是这个委托已经不再是主设备的委托(CBCentralManagerDelegate),而是外设的委托(CBPeripheralDelegate),这个委托包含了主设备与外设交互的许多回调方法,包括获取 services,获取 characteristics,获取 characteristics 的值,获取 characteristics 的 Descriptor,和 Descriptor的值,写数据,读 RSSI,用通知的方式订阅数据等等。*/
    // 1、设置外设代理
    self.peripheral.delegate = self;
    
    // 2、开始扫描外设的所有服务(nil则代表扫描所有服务,实际中最好是传入所需要的service的UUID数组,这样会省时省电)。第一步是先找到当前 peripheral 提供的 service因为 service 广播的数据有大小限制(貌似是 31 bytes),所以你实际找到的 service 的数量可能要比它广播时候说的数量要多。
    [self.peripheral discoverServices:nil];
}

// 5、把数据写到 Characteristic 中
/** 把数据写到 特征 Characteristic 中 */
- (void)writeCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic value:(NSData *)value
{
    NSLog(@"当前特征的属性【%lu】",characteristic.properties);
    // 只有 characteristic.properties(特征属性) 有 write(写入) 的权限才可以写,所以要做判断,反之出现错误
    if (characteristic.properties & CBCharacteristicPropertyWrite ||
        characteristic.properties & CBCharacteristicWriteWithoutResponse) {
        // 往 characteristic 写入数据, CBCharacteristicWriteWithResponse 表示当写入成功之后,要执行  peripheral:didWriteValueForCharacteristic:error: 方法回调
        [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
    }else{
        NSLog(@"该字段(数据)不可写入Characteristic(特征)中!");
    }
}


// 6、订阅 Characteristic 的通知【此方法决定是否能实现实时传输数据】
/** 设置通知 */
- (void)notifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic
{
    // 设置通知,数据通知会进入:didUpdateValueForCharacteristic(获取到特征的值)方法中
    // 如果是订阅,成功与否的回调是 peripheral:didUpdateNotificationStateForCharacteristic:error:,读取中的错误会以 error 形式传回。
    // 当然也不是所有 特征 都允许订阅,可以通过 CBCharacteristicPropertyNoify options 来进行判断。
    if (characteristic.properties & CBCharacteristicPropertyNotify) {
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    }
}

/** 取消通知 */
- (void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic
{
    [peripheral setNotifyValue:NO forCharacteristic:characteristic];
}

// 7、断开外设连接
/** 停止扫描且断开外设连接 */
- (void)disconnectPeripheral:(CBCentralManager *)centralManager peripheral:(CBPeripheral *)peripheral
{
    // 1、停止扫描
    [centralManager stopScan];
    // 2、断开连接
    [centralManager cancelPeripheralConnection:peripheral];
}

// 8、重新连接
/** 重新连接外设 */
- (void)reconnectThe
{

}


#pragma mark - 中心设备管理器代理<CBCentralManagerDelegate>
#pragma mark -
// 1、建立中心角色
// 检查当前app蓝牙设备是否可用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    // 在初始化 【中心设备管理器】 的时候会打开设备,只有当设备正确打开后才能使用
    switch (central.state) {
        // 蓝牙已打开,开始扫描外设
        case CBManagerStatePoweredOn:
        {
            NSLog(@">>>>>>> 蓝牙已打开,开始扫描外设");
            // 开始扫描周围的设备,自定义方法
            [self sacnNearPerpherals];
        }
            break;
        case CBManagerStatePoweredOff:
        {
            NSLog(@">>>>>>> 蓝牙未打开,系统会自动提示打开,不用自行提示");
        }
            break;
        case CBManagerStateUnsupported:
        {
            NSLog(@">>>>>>> 设备不支持蓝牙或者蓝牙4.0BLE");
        }
            break;
        case CBManagerStateUnauthorized:
        {
            NSLog(@">>>>>>> 未授权打开蓝牙");
        }
            break;
            
        default:
            break;
    }
}

/* 发现外设设备
 * central              中心设备
 * peripheral           外围设备
 * advertisementData    特征数据
 * RSSI                 信号强度
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
    // 该方法会返回找到的peripheral(如果你设置了外设过滤,那么只能找到你过滤之后的外设),所以可以使用数组将找到的 peripheral 存起来
    NSMutableString *string = [NSMutableString stringWithString:@"\n"];
    // 外设的名字
    [string appendFormat:@"NAME: %@\n",peripheral.name];
    // 外设UUID
    [string appendFormat:@"UUID(identifier):%@\n",peripheral.identifier];
    // 外设的信号强度
    [string appendFormat:@"RSSI:%@\n",RSSI];
    // 外设的特征数据
    [string appendFormat:@"advertisementData:%@\n",advertisementData];
    NSLog(@"发现的外设信息:%@",string);
    
    // 连接指定的设备 自定义方法
    [self connectPeripheral:peripheral];
    
}

// 外设连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    // 在这个方法中,可以去记录当前的连接状态等数据
    NSLog(@"当前【%@】外设连接状态 -->【成功】",peripheral.name);
    // 一旦外设连接成功,中心设备便要调用停止扫描外设
    [central stopScan];
    
    // 扫描外设中的服务和特征,自定义方法
    [self discoverPeripheralServices:peripheral];
}


// 连接外设失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"当前【%@】外设连接状态 -->【失败】",peripheral.name);
}

// 连接外设断开,协议方法
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    
    NSLog(@"当前【%@】外设连接状态 -->【断开】", peripheral.name);
}


#pragma mark - 外设代理<CBPeripheralDelegate>
#pragma mark -
// 扫描到外设服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    // 如果有错误
    if (error) {
        NSLog(@"发现【%@】外设的服务。存在【%@】错误",peripheral.name, error.localizedDescription);
    }
    
    // <CoreBluetooth>框架 提供了 CBService 类来表示 service,找到以后,它们以数组的形式存入了当前 peripheral 的 services 属性中,你可以在当前回调中遍历这个属性。
    for (CBService *service in peripheral.services) {
        NSLog(@"扫描到外设服务:【%@】",service);
        // 1、如果是搜索的全部 service 的话,你可以选择在遍历的过程中,去对比 UUID 是不是你要找的那个,进行筛选
        // 2、扫描服务的所有特征(传nil则表示所有服务的特征)
        [peripheral discoverCharacteristics:nil forService:service];
    }
}

// 扫描到服务的特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    // 如果有错误
    if (error) {
        NSLog(@"发现服务【%@】的特征。存在【%@】错误",service.UUID, error.localizedDescription);
        return;
    }
    
    // 此时 <CoreBluetooth>框架 提供了 CBCharacteristic 类来表示 characteristic。可以通过以下代码来遍历找到的 characteristic。
    for (CBCharacteristic *characteristic in service.characteristics) {
        NSLog(@"扫描到服务【%@】 的特征【%@】", service.UUID, characteristic.UUID);
#warning【重点※※】:characteristic 包含了 service 要传输的数据。获取特征的值。 当readValueForCharacteristic获取到特征的值之后会回调协议方法:peripheral:didUpdateValueForCharacteristic:error:  其中包含了要读取的数据。如果读取正确,可以用 NSData *data = characteristic.value; 来获得值。其实 readValueForCharacteristic 获取值并不是实时获取的,如果数据需要连续传输,那么就需要订阅 characteristic 了!!!
        
        // 接收数据方法根据实际情况选择(1或者2)
        // 1、手动接收特征数据(适用于数据传输不是实时)
        [peripheral readValueForCharacteristic:characteristic];
        // 搜索特征的描述(Descriptors)
        [peripheral discoverDescriptorsForCharacteristic:characteristic];
        
//        // 2、自动接收特征数据,订阅特征(适用于实时传输数据)
//        [self notifyCharacteristic:peripheral characteristic:characteristic];
//        if (!characteristic.isNotifying) {
//            // 2.1、如果使用订阅实时接收数据的话,需要判断,如果特征不再发送数据时,则需要结束订阅
//            [self cancelNotifyCharacteristic:peripheral characteristic:characteristic];
//            // 2.2、断开连接【注意】cancelPeripheralConnection:是非阻塞性的,如果在外设挂起的状态去尝试断开连接,可以能执行可能不执行,但当决定断开外设时,会调用 centralManager:didDisconnectPeripheral:error: 方法。
//            [self.centralManager cancelPeripheralConnection:peripheral];
//        }
        
        // 连接成功,开始配对,发送第一次校验的数据(也就是说往characteristic(特征)中写入数据去做校验),自定义方法
        // [self writeCharacteristic:peripheral characteristic:characteristic value:self.pairAuthDatas[0]];
    }
}

// 获取到特征的值(如果订阅了特征,那么订阅成功之后,那么数据便会实时的传回执行此回调放)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    // value 的类型是 NSData,需要自己进行数据转换解析
    NSLog(@"获取到特征【%@】的值【%@】", characteristic.UUID, [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding]);
    // 获取特征的值【注意】不是所有 characteristic 的值都是可读的,你可以通过 CBCharacteristicPropertyRead options 来进行判断。如果你尝试读取不可读的数据,那上面的代理方法会返回相应的 error。
    if (characteristic.properties & CBCharacteristicPropertyRead) {
        NSData *data = characteristic.value;
        NSLog(@"获取特征的值【%@】",data);
    }
}

// 搜索到特征的描述Descriptors
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    for (CBDescriptor *descriptor in characteristic.descriptors) {
        NSLog(@"搜索到特征:%@ 的 Descriptors:%@", characteristic.UUID, descriptor.UUID);
        // 获取到 描述 的值
        [peripheral readValueForDescriptor:descriptor];
    }
}

// 获取到 描述Descriptors 的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    
    // 这个 descriptor 都是对于特征的描述,一般都是字符串
    NSLog(@"获取到 描述Descriptors【%@】 的值【%@】", descriptor.UUID, descriptor.value);
    
    // 3、手环返回数据
    [self deciceCommandInit:peripheral];
}

// 写数据到特征中完成
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    // 如果数据写入特征失败,返回错误
    if (error) {
        NSLog(@"数据写入特征发生【%@】错误", [error localizedDescription]);
    }else {
        NSLog(@"写数据完成到特征【%@】中完成【%@】", characteristic.UUID, characteristic.value);
    }
}

// 特征订阅成功与否的回调
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    // 存在错误
    if (error) {
        NSLog(@"错误通知状态: %@", [error localizedDescription]);
    }
}

log日志

2017-06-26 15:14:58.248367 Bluetooth[2636:850796] >>>>>>> 蓝牙已打开,开始扫描外设
2017-06-26 15:14:58.248480 Bluetooth[2636:850796] 调用【开始扫描周围外设】方法
2017-06-26 15:14:58.367056 Bluetooth[2636:850796] 发现的外设信息:
NAME: (null)
UUID(identifier):C6B4B830-3E4C-4270-970F-CD69A00B8922
RSSI:-78
advertisementData:{
    kCBAdvDataIsConnectable = 1;
}
2017-06-26 15:14:58.367275 Bluetooth[2636:850796] 调用【连接指定的设备】方法
2017-06-26 15:14:59.251422 Bluetooth[2636:850796] 发现的外设信息:
NAME: SpO2023516
UUID(identifier):9B30BD01-045B-4CBD-9A0B-8FF06B1DE99F
RSSI:-66
advertisementData:{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = SpO2023516;
    kCBAdvDataTxPowerLevel = 2;
}
2017-06-26 15:14:59.251614 Bluetooth[2636:850796] 调用【连接指定的设备】方法
2017-06-26 15:14:59.317137 Bluetooth[2636:850796] 发现的外设信息:
NAME: (null)
UUID(identifier):E1811981-CFFA-4D00-BEE7-B4D466F9025E
RSSI:-77
advertisementData:{
    kCBAdvDataIsConnectable = 0;
    kCBAdvDataManufacturerData = <06000109 2000ada3 19a2941a 63cad1cf 3056112d 58a5da47 b9355065 ce>;
}
2017-06-26 15:14:59.317347 Bluetooth[2636:850796] 调用【连接指定的设备】方法
2017-06-26 15:14:59.509500 Bluetooth[2636:850796] 当前【SpO2023516】外设连接状态 -->【成功】
2017-06-26 15:14:59.572133 Bluetooth[2636:850796] 扫描到外设服务:【<CBService: 0x170271700, isPrimary = YES, UUID = Device Information>】
2017-06-26 15:14:59.573099 Bluetooth[2636:850796] 扫描到外设服务:【<CBService: 0x170271540, isPrimary = YES, UUID = 49535343-FE7D-4AE5-8FA9-9FAFD205E455>】
2017-06-26 15:14:59.577729 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Manufacturer Name String】
2017-06-26 15:14:59.578347 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Model Number String】
2017-06-26 15:14:59.578930 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Serial Number String】
2017-06-26 15:14:59.579367 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Hardware Revision String】
2017-06-26 15:14:59.579798 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Firmware Revision String】
2017-06-26 15:14:59.580215 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【Software Revision String】
2017-06-26 15:14:59.580626 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【System ID】
2017-06-26 15:14:59.581047 Bluetooth[2636:850796] 扫描到服务【Device Information】 的特征【IEEE Regulatory Certification】
2017-06-26 15:14:59.582100 Bluetooth[2636:850796] 扫描到服务【49535343-FE7D-4AE5-8FA9-9FAFD205E455】 的特征【49535343-6DAA-4D02-ABF6-19569ACA69FE】
2017-06-26 15:14:59.582467 Bluetooth[2636:850796] 扫描到服务【49535343-FE7D-4AE5-8FA9-9FAFD205E455】 的特征【49535343-ACA3-481C-91EC-D85E28A60318】
2017-06-26 15:14:59.582880 Bluetooth[2636:850796] 扫描到服务【49535343-FE7D-4AE5-8FA9-9FAFD205E455】 的特征【49535343-1E4D-4BD9-BA61-23C647249616】
2017-06-26 15:14:59.583259 Bluetooth[2636:850796] 扫描到服务【49535343-FE7D-4AE5-8FA9-9FAFD205E455】 的特征【49535343-8841-43F4-A8D4-ECBE34729BB3】
2017-06-26 15:14:59.583538 Bluetooth[2636:850796] 扫描到服务【49535343-FE7D-4AE5-8FA9-9FAFD205E455】 的特征【49535343-026E-3A9B-954C-97DAEF17E26E】
2017-06-26 15:14:59.624711 Bluetooth[2636:850796] 获取到特征【Manufacturer Name String】的值【ISSC】
2017-06-26 15:14:59.624885 Bluetooth[2636:850796] 获取特征的值【<49535343>】
2017-06-26 15:14:59.685441 Bluetooth[2636:850796] 获取到特征【Model Number String】的值【BT5050】
2017-06-26 15:14:59.685773 Bluetooth[2636:850796] 获取特征的值【<42543530 3530>】
2017-06-26 15:14:59.744974 Bluetooth[2636:850796] 获取到特征【Serial Number String】的值【8CDE52EFA344】
2017-06-26 15:14:59.745185 Bluetooth[2636:850796] 获取特征的值【<38434445 35324546 41333434>】
2017-06-26 15:14:59.806558 Bluetooth[2636:850796] 获取到特征【Hardware Revision String】的值【5050_SPP】
2017-06-26 15:14:59.806767 Bluetooth[2636:850796] 获取特征的值【<35303530 5f535050 00000000 00>】
2017-06-26 15:14:59.864906 Bluetooth[2636:850796] 获取到特征【Firmware Revision String】的值【2043032】
2017-06-26 15:14:59.865105 Bluetooth[2636:850796] 获取特征的值【<32303433 303332>】
2017-06-26 15:14:59.956905 Bluetooth[2636:850796] 获取到特征【Software Revision String】的值【0000】
2017-06-26 15:14:59.957106 Bluetooth[2636:850796] 获取特征的值【<30303030>】
2017-06-26 15:15:00.029934 Bluetooth[2636:850796] 获取到特征【System ID】的值【】
2017-06-26 15:15:00.030071 Bluetooth[2636:850796] 获取特征的值【<00000000 00000000>】
2017-06-26 15:15:00.074246 Bluetooth[2636:850796] 获取到特征【IEEE Regulatory Certification】的值【】
2017-06-26 15:15:00.074437 Bluetooth[2636:850796] 获取特征的值【<00010004 00000000>】
2017-06-26 15:15:00.256983 Bluetooth[2636:850796] 获取到特征【49535343-6DAA-4D02-ABF6-19569ACA69FE】的值【】
2017-06-26 15:15:00.257193 Bluetooth[2636:850796] 获取特征的值【<00180018 00000048 00>】
2017-06-26 15:15:00.344898 Bluetooth[2636:850796] 获取到特征【49535343-ACA3-481C-91EC-D85E28A60318】的值【】
2017-06-26 15:15:00.346958 Bluetooth[2636:850796] 搜索到特征:49535343-ACA3-481C-91EC-D85E28A60318 的 Descriptors:Client Characteristic Configuration
2017-06-26 15:15:00.464541 Bluetooth[2636:850796] 获取到特征【49535343-1E4D-4BD9-BA61-23C647249616】的值【】
2017-06-26 15:15:00.464642 Bluetooth[2636:850796] 获取特征的值【<00000000 00>】
2017-06-26 15:15:00.464920 Bluetooth[2636:850796] 搜索到特征:49535343-1E4D-4BD9-BA61-23C647249616 的 Descriptors:Client Characteristic Configuration
2017-06-26 15:15:00.556644 Bluetooth[2636:850796] 获取到特征【49535343-8841-43F4-A8D4-ECBE34729BB3】的值【】
2017-06-26 15:15:00.614704 Bluetooth[2636:850796] 获取到特征【49535343-026E-3A9B-954C-97DAEF17E26E】的值【】
2017-06-26 15:15:00.616546 Bluetooth[2636:850796] 搜索到特征:49535343-026E-3A9B-954C-97DAEF17E26E 的 Descriptors:Client Characteristic Configuration
2017-06-26 15:15:00.674995 Bluetooth[2636:850796] 获取到 描述Descriptors【Client Characteristic Configuration】 的值【0】
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容