服务和特征都是用UUID来唯一标识的,UUID的概念如果不清楚请自行google,国际蓝牙组织为一些很典型的设备(比如测量心跳和血压的设备)规定了标准的service UUID(特征的UUID比较多,这里就不列举了),如下:

#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 // 告警服务
#define BLE_UUID_BATTERY_SERVICE 0x180F // 电池服务
#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 // 血压服务
#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 // 当前时间服务
#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 // 骑自行车的速度和节奏服务
#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A // 设备信息服务
#define BLE_UUID_GLUCOSE_SERVICE 0x1808 // 葡萄糖服务
#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 // 健康温度计服务
#define BLE_UUID_HEART_RATE_SERVICE 0x180D // 心率服务
#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 // 人机界面设备服务
#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 // 立即报警服务
#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 // 连接丢失服务
#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 // DST变化服务
#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E // 电话警戒状态
#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 // 参考时间更新
#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 // 运行速度和节奏
#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 // 扫描参数服务
#define BLE_UUID_TX_POWER_SERVICE 0x1804 // 发射功率服务
#define BLE_UUID_CGM_SERVICE 0x181A // 动态血糖监测

// 当发现了我们所需要的characteristic,我们最想做的就是查看下这个characteristic的value是多少。也就是说,我们需要一个接收数据的操作。

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

在CoreBluetooth中,提供了两种方法:
1. [peripheral readValueForCharacteristic:characteristic];

  peripheral是我们程序中的外设,characteristic是我们那个感兴趣的characteristic当调用这个方法后,程序会回调一个方法:
  - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

  上面的第二个参数:(CBCharacteristic *)characteristic -----我们直接用characteristic.value就获取到了感兴趣的characteristic的value,类型是NSData的,之后就可以对值进行操作了。

  PS:回调的前提是要设置代理,不要忘了。这个方法比较直接,也符合我们的一般逻辑,下面介绍第二种方法

2. [peripheral setNotifyValue:YES forCharacteristic:characteristic];  Subscribe“订阅”
  第一个参数设置为YES,至于为啥,后面我说说我的理解。第二个参数同样是我们感兴趣的characteristic。
  调用这个方法后,程序会回调一个方法:
  - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  这方法能做什么?我觉得主要是一些错误判断,利用上面第三个参数error,如果出错,系统把错误信息放在error中,可以打印显示。
  之后在这个方法中调用[peripheral readValueForCharacteristic:characteristic]同样会回调1中那个回调方法,
  - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  我们同样在这里处理数据,跟1中一样。
  跟1相比,多走了一步,多了一个参数notifyValue,这个参数我感觉就是一个标志量,当为YES的时候,我要订阅这个characteristic,之后每当这个characteristic的value发生变化时,都会回调

  - (void)peripheral:(CBPeripheral *)peripheral  didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  就好像我要订阅这个杂志(characteristic),每当有新版本的杂志发行时(value值改变),你就要给我送一本(回调方法),为啥给我送?因为我订阅了。
  所以呢,这种方法在某些情况下是比1更高效的,就是我们需要操作的characteristic的value经常发生变化时。比如心率仪这些设备的心率characteristic的value。

最后还有一个重要的补充,当我们已经找到了我们感兴趣的characteristic后,他的value并不一定通过1方法或者2方法就可以接收的,就算可以接收,有时候只能用1,有时候只能用2。

这牵扯到characteristic的一个property:

typedef enum
{
  CBCharacteristicPropertyBroadcast = 0x01,
  CBCharacteristicPropertyRead = 0x02,
  CBCharacteristicPropertyWriteWithoutResponse = 0x04,
  CBCharacteristicPropertyWrite = 0x08,
  CBCharacteristicPropertyNotify = 0x10,
  CBCharacteristicPropertyIndicate = 0x20,
  CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
  CBCharacteristicPropertyExtendedProperties = 0x80,
  CBCharacteristicPropertyNotifyEncryptionRequired = 0x100,
  CBCharacteristicPropertyIndicateEncryptionRequired = 0x200,
} CBCharacteristicProperties;

当为read(0x02)的时候,我们用1方法可以查看,用2就会出错。当为notify(0x10)的时候我们就得用2方法。其他就不说明了,比如write就只能写value······

所以当我们想查看value的时候,先了解一下这个characteristic的property,看是不是能让我们读的。

怎么查看?找BLE外设的设备厂商或者查看外设的说明书。

    "<CBCharacteristic: 0x1565ee50,   UUID = System ID,             properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x156806b0,   UUID = Model Number String,       properties = 0x2,   value = (null), notifying = NO>",  

    "<CBCharacteristic: 0x1567f9e0,   UUID = Serial Number String,        properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x1565a640,   UUID = Firmware Revision String,     properties = 0x2,   value = (null), notifying = NO>",    

    "<CBCharacteristic: 0x15682f70,   UUID = Hardware Revision String,     properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x1564bdf0,   UUID = Software Revision String,       properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x1565a8c0,   UUID = Manufacturer Name String,      properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x15683cd0,   UUID = IEEE Regulatory Certification,    properties = 0x2,   value = (null), notifying = NO>",

    "<CBCharacteristic: 0x15683bf0,   UUID = PnP ID,                  properties = 0x2,   value = (null), notifying = NO>"

推荐将value经常变化的characteristic的property设为notify(CBCharacteristicPropertyNotify)。

iOS 学习笔记 三 (2015.03.05)的更多相关文章

  1. iOS 学习笔记三【segmentedControl分段控制器详细使用方法】

    在iOS开发过程中,分段控制器的使用频率还是蛮高的,下面是我写的一个简单的demo,大家可以把代码直接复制过去,就可以使用,ios9最新支持. // // ViewController.m // 03 ...

  2. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

  3. iOS学习笔记总结整理

    来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...

  4. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  5. iOS学习笔记10-UIView动画

    上次学习了iOS学习笔记09-核心动画CoreAnimation,这次继续学习动画,上次使用的CoreAnimation很多人感觉使用起来很繁琐,有没有更加方便的动画效果实现呢?答案是有的,那就是UI ...

  6. iOS学习笔记之ARC内存管理

    iOS学习笔记之ARC内存管理 写在前面 ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式. 指针变量与对象所有权 指针变量暗含了对其 ...

  7. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  8. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

  9. iOS学习笔记之UITableViewController&UITableView

    iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论 ...

随机推荐

  1. JavaScript:JavaScript中常见获取对象元素的方法

    介绍: javascript中常见的3种获取元素的方法,分别是通过元素ID.通过标签名字和通过类名字来获取 操作如下: 1.getElementById DOM提供了一个名为getElementByI ...

  2. JavaScript:JavaScript语法的详细介绍

    JavaScript语法:只要Java会了,基本上javascript语法就会了. ——变量的定义 ——程序的结构控制 ——数组操作 ——函数的定义即使用 基本的test.html代码如下,它会导入下 ...

  3. 目标检测的图像特征提取之(一)HOG特征

    http://blog.csdn.net/liulina603/article/details/8291093

  4. Eclipse中文注释乱码解决

    将别人的项目或JAVA文件导入到自己的Eclipse中时,常常会出现JAVA文件的中文注释变成乱码的情况,主要原因就是别人的IDE编码格式和自己的Eclipse编码格式不同. 总结网上的建议和自己的体 ...

  5. box2dweb之关节joint(连接器)

    1 概述 前篇基础文章看完后基本上就应该对box2dweb能上手了,下面来介绍一下box2dweb非常重要的一个概念,关节(joint)也有叫连接器的,总之是一个意思.下面是关节详细的类库说明: BO ...

  6. APN 推送

    推送的各种状态 http://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled ...

  7. Java基础之写文件——将素数写入文件中(PrimesToFile)

    控制台程序,计算素数.创建文件路径.写文件. import static java.lang.Math.ceil; import static java.lang.Math.sqrt; import ...

  8. JS,CSS,HTML制作网页首页,视频轮播,隐藏点击等等。

    在整个项目中,总共写了1000+的代码,可以更加简单优化的.整个主页交互效果能基本,包括轮播,视频,点击变化形状,移入蒙版,瀑布流加载滑动,旋转等等.轮播导航没有完全做完,暂时做了往右无限推动.个人觉 ...

  9. nyist 673 悟空的难题

    http://acm.nyist.net/JudgeOnline/problem.php?pid=673 悟空的难题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 ...

  10. acm算法模板(4)

    杂乱小模板 状态压缩dp小技巧 x&-x是取x的最后一个1的位置. x-=x&-x是去掉x的最后一个1. 读入外挂 int nxt_int(){// neg or pos    cha ...