重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
iOS 蓝牙开发(二)
创新互联公司是一家专业提供和静企业网站建设,专注与做网站、网站设计、H5高端网站建设、小程序制作等业务。10年已为和静众多企业、政府机构等服务。创新互联专业网站设计公司优惠进行中。
iOS 蓝牙开发(三)
iOS 蓝牙开发(四)
在iOS中蓝牙相关实现都是在CoreBluetooth这个framework中的,所以我们创建一个单例类中需要先导入 #import CoreBluetooth/CoreBluetooth.h ,再后即可使用这个单例类进行管理我们蓝牙的扫描、连接、状态等实现。
当 central.state 为CBManagerStatePoweredOn即可开始扫描, 具体方法 [self.centralManager scanForPeripheralsWithServices:nil options:nil] 当调用 scanForPeripheralsWithServices:options: 函数时就会实时调用其代理方法 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
peripheral 是外设类 advertisementData 是广播的值,一般携带设备名, serviceUUID 等信息。 RSSI 绝对值越大,表示信号越差,设备离的越远。如果想装换成百分比强度, (RSSI+100)/1001 (这是一个约数,蓝牙信号值并不一定是-100 - 0的值)
蓝牙的连接是当中心设备扫描到可用外设后, 利用函数 [self.centralManager connectPeripheral:peripheral options:nil]; 进行链接, 当函数被调用后, 就会回调其对应的代理函数。
本篇笔记主要是记录如何初始化蓝牙的 CBCentralManager 的中心管理类,并记录如何实现扫描周边外设、如何链接、获取蓝牙当前状态。
1.什么是蓝牙4.0,蓝牙其它标准又是什么?
详细描述:低功耗蓝牙(Low Energy; LE),又视为Bluetooth Smart或蓝牙核心规格4.0版本。其特点具备节能、便于采用,是蓝牙技术专为物联网(Internet of Things; IOT)开发的技术版本。所以它最主要的特点是低功耗,普及率高。现在所说的蓝牙设备,大部分都是在说4.0设备,ble也特指4.0设备。 在4.0之前重要的版本有 2.1版本-基本速率/增强数据率(BR/EDR) 和 3.0 高速蓝牙 版本,这些统称为经典蓝牙。4.0还有4.1和4.2的小版本,其中4.2版本对传输速率做了进一步他提升,提高了2.5倍,苹果从iphone6开始使用4.2,最新的蓝牙标准为蓝牙5.0,其中最大的特点连接范围扩大了4倍,速度又提高了2倍,无连接数据广播能力提高了8倍,增加了蓝牙组网的能力。
2.蓝牙开发必须知道的概念。
2.1.1 central和peripheral:
蓝牙应用开发中,存在两种角色,分别是central和peripheral(pə’rɪfərəl) ,中文就是中心和外设。比如手机去连接智能设备,那手机就是central,智能设备就是peripheral。大多时候都是central去连接peripheral的场景。
2.1.2 广播和连接:
peripheral会发出广播,central扫描到广播后,可以对设备进行连接,发出connect请求,peripheral接收到请求后,同意连接后,central和peripheral就建立了连接。
2.1.3 连接后的操作:
write,read,notify,indecate, response or not …
indecate和notify的区别就在于,indecate是一定会收到数据,notify有可能会丢失数据(不会有central收到数据的回应),write也分为response和noresponse,如果是response,那么write成功回收到peripheral的确认消息,但是会降低写入的速率。
2.1.4 协议:
每个具体的智能设备,都约定了一组数据格式,这个就是数据协议,例如手环中获取到数据0X001023,其中第2位到第5位表示步数,那么就2310就是步数的16进制的数据,转换成10进制就是8976步,需要注意的是,设备端都是小端模式,所以取4位时候,高字节在前低字节在后。
3. iOS蓝牙应用的一般开发流程。
4. 蓝牙的数据交互。
write,read,notify,indecate, response or not … 都是容易理解的,indecate和notify对应的是长连接,建立indecate后,peripheral可以随时往central发送数据。
indecate和notify的区别就在于,indecate是一定会收到数据,notify有可能会丢失数据(不会有central收到数据的回应),write也分为response和noresponse,如果是response,那么write成功回收到peripheral的确认消息,但是会降低写入的速率。
对于一个charateristic,他的读写订阅的权限是peripheral决定的,熟悉可以被同时设置,一般会根据外设的功能来决定。
5.蓝牙ota DFU。
蓝牙ota,DFU(Device Firmware Update)指的是蓝牙设备的固件升级,其实是一整套流程,不同的蓝牙芯片,ota的流程有不同之处,我这里用ti的芯片举例。步骤为:切系统(bootloader mode),重启,传输数据,验证数据,切系统,重启,完成。
其中数据传输也会分成很多节去发送,没法送一段数据,做一次数据校验。
6.ota存在的问题。
每个智能设备的速率,功耗,存储都会有很多限制,导致很多设备会自己去实现ota的功能,自定义流程和数据传输方式,导致许多设备都是有自己私有的ota模式和协议,所以在做开发的时候,要仔细阅读设备协议中对ota的描述。
7.如何做自动重连。
只需要在设备断开连接的委托方法中,重新调用gatt.connet或者是centralManager.connet方法就可以了,无论当时设备是否有点,是否在周围,当设备再次开会或者连接到可连接范围内,都会自动被连上。
8.连接失败处理。
分两个平台来说,iOS端也有连接失败的委托,但是好像几乎不会发生这种情况,而对于同款设备,android常常会出现连接失败的情况,status != BluetoothGatt.GATT_SUCCESS,android端开发请不要把连接失败和断开连接放在一块处理,因为断开连接可以直接尝试重新连接,而连接失败后尝试重新连接,需要加一些延时,并且需要gatt.close,清空一下状态,否则会把gatt阻塞导致手机不重启蓝牙就再也无法连接任何设备的情况 。
9.后台运行。
iOS后来运行,需要设备中info.Plist权限,key:Required background modes ,value: bluetooth-central(手机作为central) , bluetooth-peripheral。
10.同时连接多个设备。
使用同一个CBCentralManager,通过进入委托的peripheral的identifier区分不同的设备,进行不同的操作和处理。
11.扫描广播包。
所有外设,只有在发出广播包的情况下,才能被central发现,绝大多数情况下,外设被连接后就不会发出广播(也有例外),很多人遇到无法找到设备的问题,大多属于这种情况。
12.提高蓝牙连接速度。
无论是iOS,还是android,都可以通过已绑定的设备,在不开启扫描的情况下进行快速连接,iOS需要的参数是peripheral的identifier,android需要mac地址。但android和iOS还是有一些区别的,比如iOS不能拿到已绑定的设备list,但是可以通过UUID去拿到peripheral的实例。而android可以拿到已绑定的设备list。android绑定过程需要手动调用createBond的方法,而iOS在连接成功一次后会自动绑定。 android在处理createBond时,常常会应为不同手机平台,不同设备,会产生兼容性的问题,这点需要注意。
13.定向扫描。
在扫描时候可以传入serviceUUID,这样可以扫描到特定条件的设备,提高扫描的速度,排除干扰。
14.如何获取mac地址。
而iOS出于苹果的安全策略问题,无法直接获得mac地址,只能得到一个mac地址换算出来的identifier。
GAP(Generic Access Profile):它用来控制设备连接和广播,GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。
GATT(Generic Attribute Profile):BLE连接都是建立在GATT协议之上的。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。
BLE中主要有两个角色:外围设备(Peripheral)和中心设备(Central)。一个中心设备可以连接多个外围设备,一个外围设备包含一个或多个服务(services),一个服务包含一个或多个特征(characteristics)。
使用CoreBluetooth库,创建CBPeripheralManager,实现CBPeripheralManagerDelegate代理
创建完该对象,会回调peripheralManagerDidUpdateState:方法判断蓝牙状态,蓝牙可用,给外设配置服务和特征
注意CBAttributePermissions
当中心设备读写设置CBAttributePermissionsReadEncryptionRequired/CBAttributePermissionsWriteEncryptionRequired权限的Characteristic时,会弹出弹框,请求建立安全连接
给外设配置服务特征后,会调用peripheralManager:didAddService:error: 服务特征全部添加完后发起广播,如果在广播时设置CBAdvertisementDataServiceUUIDsKey,会把该service广播出去,中心设备在扫描时可根据该uuid找到该设备。外围设备靠不断发广播,使中心设备发现它。
当中央端连接上了此设备并订阅了特征时会回调 didSubscribeToCharacteristic:
当接收到中央端读的请求时会调用didReceiveReadRequest:
创建CBCentralManager对象,实现CBCentralManagerDelegate代理
回调centralManagerDidUpdateState:代理方法,当central.state==CBManagerStatePoweredOn时,开启扫描,设置serviceUUIDs可扫描特定外设,CBCentralManagerScanOptionAllowDuplicatesKey设为NO不重复扫描已发现设备,YES是允许
扫描到设备会回调centralManager:didDiscoverPeripheral:advertisementData:RSSI:,RSS绝对值越大,表示信号越差,设备离的越远
关闭扫描
连接设备
发现服务
发现特征
总结一下蓝牙开发相关的知识点和注意事项,做个笔记,也希望你们能少踩坑
(公司部分蓝牙项目为混编项目,蓝牙相关处理均采用了Objective-C,故本文????均采用OC,Swift处理相同)
蓝牙4.0包含两个蓝牙标准,它是一个是 双模 的标准,它包含 传统蓝牙部分(也称经典蓝牙) 和 低功耗蓝牙部分(BLE) , 二者适用于不同的应用场景和应用条件。他们的特点如下
所以蓝牙4.0是集成了传统蓝牙和低功耗蓝牙两个标准的,并不只是低功耗蓝牙
蓝牙4.0支持两种部署方式: 双模式 和 单模式 ,双模同时支持经典蓝牙和低功耗蓝牙,而单模则只支持其中一种。
二者更多细节详见: 传统蓝牙和低功耗蓝牙的区别
iOS中蓝牙相关功能都封装进了 CoreBluetooth 类中,其中有几个常见的参数和概念
具体API参考 CoreBluetooth蓝牙开发
保存到数组中的设备可通过 UUID 来进行区分。从 iOS7之后苹果不提供外设的mac地址,外设的唯一标识换成了由mac封装加密后的UUID,需要注意的是不同的手机获取同一个外设的UUID是不同的,所以在不同手机之间UUID不是唯一的,但在本机上可以作为唯一标识(特殊情况手机刷机后也会改变UUID)。
如何获取Mac地址
一般使用场景是根据Mac地址区分某个外设
注意点:
写入数据时可能会遇到需要分包发送的情况,我们可以通过下面的API或许当前特征支持的最大的单条写入长度
maxLength 一般取决于蓝牙模块内部接收 缓冲区 的大小,很多硬件设备这个缓冲区的大小是 20 字节, 这个大小也和特征的写入权限有关,像具有写入权限 withResponse 类的特征其大小一般为 512 字节,当然这些都是取决于设备测的设置;
当我们单次发送的数据字节长度大于 maxLength 时,我们就需要采用分包的方式来发送数据了,
分包发送的逻辑类似于下面
这边延时主要是设备侧的接收模块接收数据以及处理能力有限
外围设备测和中心设备(大部分情况下是手机)保持蓝牙连接的状态下,如果长时间不产生交互,蓝牙就会断开,所以为了保持两者持续的连接状态,需要做保活处理,也就是需要持续的发送心跳包(watchdog)。相应的处理是使用一个定时器定时向设备侧发送符合设备协议格式的心跳包。
断开连接很简单,只需要调用 [self.centralManager cancelPeripheralConnection:peripheral] 传入需要断开连接的设备对象就行了。断开连接时会自动调用 centralManager:didDisconnectPeripheral:error: 代理方法。
按照之前的惯例,当error为nil时表示断开成功,error不为nil时断开失败。这种理解是错误的。
当你调用 cancelPeripheralConnection: 方法(主动断开)断开连接时error为nil ; 没有调用这个方法(异常断开)而断开时error返回的是异常断开的原因。也可以理解为主动调用断开连接方法一定会断开
接下来就是断开重连的问题了,对蓝牙功能进行封装时肯定少不了断开重连。首先断开时可通过上面的代理方法的error是否为nil判断是否是异常断开,一般情况下异常断开时是需要重连的
原因就是当设备断开连接后 peripheral.services 为nil了,当然 service.characteristics 也是nil,所以需要在断开连接时把保存这个设备对应的服务和特征全部清除,然后在连接成功时重新过一遍发现服务和发现特征的流程就好了。
iOS7 开始,Apple加入了Beacon围栏检测的API, ( iBeacon-维基百科 ), 其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用 BLE 技术向周围发送自己特有的 ID,接收到该 ID 的应用软件会根据该 ID 采取一些行动。比如,在店铺里设置 iBeacon 通信模块的话,便可让 iPhone 和 iPad 上运行一资讯告知服务器,或者由服务器向顾客发送折扣券及进店积分, 或者公司的手机打卡,只要手机靠近打卡器一定范围,手机测就向打开器发送打卡信息,从而自动打卡。这种场景还有很多。 其中一个最重要的功能就是App的唤醒功能(杀死后也能唤醒)
举一个我们的例子,我们的产品业务场景就是在进入车辆以后,需要使用蓝牙连接我们的后装车载设备以采集车辆信息和驾驶行为行程等,这里有一个问题就是在App被杀死的情况下如何唤醒App, 因为不可能要求用户每次都主动去打开App,这样体验太差。我们的做法是通过iBeacon,当我们的车辆点火以后,设备测通电,发出 iBeacon广播 ,App实现监听iBeacon相关功能后就可以唤醒我们App,然后在相应的回调的处理一些事情,比如通过蓝牙连接设备。这里的前提条件是我们的硬件设备测包含iBeacon模块,具有iBeacon功能,而且对iBeacon的广播频率也有一定的要求,长了可能唤醒的功能会不稳定,官方建议的好像是100ms,频率超高越耗电,但可以让手机或其它监听设备越快地发现iBeacon。标准的BLE广播距离是100m,这使Beacon在室内位置跟踪场景下的效果更理想。
关于iBeacon更多的使用及介绍请参考
苹果核 - iOS端近场围栏检测(一) ——iBeacon
iBeacon技术初探
蓝牙开发说简单也简单,说不简单也有点难,开发人员在首次开发蓝牙前首先需要搞清楚蓝牙开发的概念,还要了解掌握蓝牙开发的一整套流程,这样才能快速上手开发蓝牙。
蓝牙开发分为两种模式:管理者模式和中心者模式。管理者模式基本很少用到,相当于iPhone手机作为外设,自己创建服务和特性,然后用其他设备连接iPhone手机;中心者模式一般是大部分情况下都会使用的,使用中心者模式开发相当于iPhone手机作为主机,连接蓝牙外设,下面介绍蓝牙开发的例子就是使用的中心者模式来讲解的。
在这里我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios开发的,如果你正在学习ios ,我欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2018最新的iOS进阶资料和高级开发教程
一、关于蓝牙开发的一些重要的理论概念:
1、服务(services):蓝牙外设对外广播的时候一定会有一个服务,有些时候也可以是有多个服务,服务下面包含一些特性,服务可以理解成一个模块的窗口;
2、特征(characteristic):特征存在于服务下面的,一个服务下面可以有多个特征,特征可以理解成具体实现功能的窗口,一般的特性都会有value,也就是特征值,是特征和外界交互的最小单位;
3、UUID:蓝牙上的唯一标示符,为了区分不同服务和特征,就用UUID来表示。
二、蓝牙连接的主要步骤
1、创建一个CBCentralManager实例来进行蓝牙管理;
2、搜索扫描外围设备;
3、连接外围设备;
4、获得外围设备的服务;
5、获得服务的特征;
6、从外围设备读取数据;
7、给外围设备发送(写入)数据。
三、蓝牙连接和数据读写的具体步骤
1、导入苹果系统蓝牙框架
#import
2、遵循两个蓝牙框架相关的协议
3、新建两个实例属性,一个特征属性
@property (nonatomic, strong) CBCentralManager *centralManager; //中心管理者
@property (nonatomic, strong) CBPeripheral *peripheral; //连接到的外设
@property (nonatomic, strong) CBCharacteristic *characteristic; //特征
4、初始化CBCentralManager,进行蓝牙管理
- (void)viewDidLoad {
[super viewDidLoad];
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; //创建实例进行蓝牙管理
}
//若中心管理者初始化之后 就会触发下面这个代理方法 该代理方法是用来判断手机蓝牙的状态的
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
// 蓝牙可用,开始扫描外设
if (central.state == CBManagerStatePoweredOn) {
NSLog(@"蓝牙可用");
//在中心管理者成功开启之后再进行一些操作
//搜索扫描外设
// 根据SERVICE_UUID来扫描外设,如果不设置SERVICE_UUID,则扫描所有蓝牙设备
// [self.centralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:SERVICE_UUID]]}];
[central scanForPeripheralsWithServices:nil options:nil];
}
if(central.state == CBManagerStateUnsupported) {
NSLog(@"该设备不支持蓝牙");
}
if (central.state == CBManagerStatePoweredOff) {
NSLog(@"蓝牙已关闭");
}
if (central.state == CBManagerStateUnknown) {
NSLog(@"蓝牙当前状态不明确");
}
if (central.state == CBManagerStateUnauthorized) {
NSLog(@"蓝牙未被授权");
}
}
5、搜索外围设备
//执行扫描动作之后,如果扫描到外设了,就会自动回调下面的协议方法
/** 发现符合要求的外设,回调 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(@"%@====",peripheral.name);
//根据外设名字有选择性的筛选连接蓝牙设备
if ([peripheral.name hasPrefix:@"TEAMOSA"]) {
//在这里对外设携带的广播数据进行进一步的处理
if ([self.peripheraNames containsObject:peripheral.name]) {
//如果数组中包含了就不再添加
return;
}
//添加到外设名字数组中
[self.peripheraNames addObject:peripheral.name];
//标记外设,让它的生命周期与控制器的一致
self.peripheral = peripheral;
// 可以根据外设名字来过滤外设
// [central connectPeripheral:peripheral options:nil];
}
// 连接外设
// [central connectPeripheral:peripheral options:nil];
}
6、连接外围设备
//连接外围设备,中心管理者连接外设成功,如果连接成功就会回调这个协议方法
/** 连接成功 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
//连接成功之后,可以进行服务和特性的发现。 停止中心管理设备的扫描动作,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为iOS BLE4.0是支持一对多连接的),导致数据的混乱。
//停止扫描动作
[self.centralManager stopScan];
// 设置外设的代理
peripheral.delegate = self;
// 根据UUID来寻找服务
// [peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
//外设发现服务,传nil代表不过滤,一次性读出外设的所有服务
[peripheral discoverServices:nil];
NSLog(@"%s, line = %d, %@=连接成功", __FUNCTION__, __LINE__, peripheral.name);
}
//外设连接失败
/** 连接失败的回调 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);
}
//丢失连接 掉线
/** 断开连接 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);
// 断开连接可以设置重新连接
[central connectPeripheral:peripheral options:nil];
}
7、获取外围设备服务和特征
/** 发现服务 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
// 遍历出外设中所有的服务
for (CBService *service in peripheral.services) {
// NSLog(@"所有的服务:%@",service);
}
// 这里仅有一个服务,所以直接获取
CBService *service = peripheral.services.lastObject;
// 根据UUID寻找服务中的特征
// [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service];
// [peripheral discoverCharacteristics:@[service.UUID] forService:service];
[peripheral discoverCharacteristics:nil forService:service];
}
8、从外围设备读取数据
// 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法) 你可以判断是否 从外围设备读数据
/** 接收到数据回调 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
// if (characteristic == @"你要的特征的UUID或者是你已经找到的特征") {
// //characteristic.value就是你要的数据
// }
if ([peripheral.name hasPrefix:@"TEAMOSA"]){
NSData *data = characteristic.value;
NSString *value = [self hexadecimalString:data];
// NSLog(@"characteristic(读取到的): %@, data : %@, value : %@", characteristic, data, value);
}
// 拿到外设发送过来的数据
// NSData *data = characteristic.value;
// self.textFild.text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
9、向外围设备发送(写入)数据
//这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用
//[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];//第一个参数是已连接的蓝牙设备; 第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入 需要注意的是特征的属性是否支持写数据
/** 写入数据回调 */
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {
/*
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
CBCharacteristicPropertyBroadcast = 0x01,
CBCharacteristicPropertyRead = 0x02,
CBCharacteristicPropertyWriteWithoutResponse = 0x04,
CBCharacteristicPropertyWrite = 0x08,
CBCharacteristicPropertyNotify = 0x10,
CBCharacteristicPropertyIndicate = 0x20,
CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
CBCharacteristicPropertyExtendedProperties = 0x80,
CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,
CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200
};
打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值
常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式
*/
// NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);
// 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含
NSLog(@"write value success(写入成功) : %@", characteristic);
}
10、具体调用给蓝牙外设写入数据方法,这里的例子是以按钮点击事件里面来调用处理
//发送按钮点击事件
- (void)sendClick {
if (!self.characteristic) {
return;
}
_tempValue = [NSString stringWithFormat:@"%.0f", progressView.centigradeDegree];
_timeValue = [NSString stringWithFormat:@"%.0ld", (long)progressView1.timeDegree];
NSString *ttData = [NSString stringWithFormat:@"%@,%@U", _tempValue, _timeValue];
// NSString *aaa = [DataCoverTool coverFromStringToHexStr:ttData];
// 用NSData类型来写入
// NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arry];
NSData *data = [ttData dataUsingEncoding:NSUTF8StringEncoding];
// NSData *data = [self dataWithString:ttData];
// 根据上面的特征self.characteristic来写入数据
[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];