最近写一个蓝牙项目 初步实现一下蓝牙设备连接交互,后期继续完善。。。。

1、连接蓝牙相关操作

BlueToothManger.h

//
// BlueToothManger.h
// SmartRobot
//
// Created by 杜文杰 on 2017/8/2.
// Copyright © 2017年 appleLJ. All rights reserved.
// #import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h> @interface BlueToothManger : CBCentralManager
// connectSeccuss YES 连接成功 NO 连接失败
@property (nonatomic, copy) void(^cbperipheral)(CBPeripheral *peripheral,BOOL connectSeccuss);
@property (nonatomic, copy) void(^cbCharacteristic)(CBCharacteristic *characteristic);
- (instancetype)ShareBlueToothManger;
- (CBCentralManager *)centralManager; @end

BlueToothManger.m

//
// BlueToothManger.m
// SmartRobot
//
// Created by 杜文杰 on 2017/8/2.
// Copyright © 2017年 appleLJ. All rights reserved.
// #import "BlueToothManger.h"
#import <CoreBluetooth/CoreBluetooth.h> @interface BlueToothManger ()<CBCentralManagerDelegate,CBPeripheralDelegate>
/// 中央管理者 -->管理设备的扫描 --连接
@property (nonatomic, strong) CBCentralManager *centralManager;
// 存储的设备
@property (nonatomic, strong) NSMutableArray *peripherals;
// 扫描到的设备
@property (nonatomic, strong) CBPeripheral *cbPeripheral;
// 文本
//@property (weak, nonatomic) IBOutlet UITextView *peripheralText;
// 蓝牙状态
@property (nonatomic, assign) CBManagerState peripheralState; @property (nonatomic, copy) NSString *sendServerValue; @property (nonatomic, copy) BlueToothManger *blueToothManger;
@end // 蓝牙4.0设备名
static NSString * const kBlePeripheralName = @"JDY-08";
// 通知服务
static NSString * const kNotifyServerUUID = @"FFE0";
// 写服务
static NSString * const kWriteServerUUID = @"FFE1";
// 通知特征值
static NSString * const kNotifyCharacteristicUUID = @"FFE1";
// 写特征值
static NSString * const kWriteCharacteristicUUID = @"FFE1"; @implementation BlueToothManger - (instancetype)ShareBlueToothManger
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_blueToothManger = [[BlueToothManger alloc]init];
});
return _blueToothManger; }
- (NSMutableArray *)peripherals
{
if (!_peripherals) {
_peripherals = [NSMutableArray array];
}
return _peripherals;
} - (CBCentralManager *)centralManager
{
if (!_centralManager)
{
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
return _centralManager;
} // 222 扫描设备
- (void)scanForPeripherals
{
[self.centralManager stopScan];
NSLog(@"扫描设备");
// [self showMessage:@"扫描设备"];
if (self.peripheralState == CBManagerStatePoweredOn)
{
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
} // 连接设备
- (void)connectToPeripheral
{
if (self.cbPeripheral != nil)
{
NSLog(@"连接设备");
// [self showMessage:@"连接设备"];
[self.centralManager connectPeripheral:self.cbPeripheral options:nil];
}
else
{
// [self showMessage:@"无设备可连接"];
}
} // 清空设备
- (void)clearPeripherals
{
NSLog(@"清空设备");
[self.peripherals removeAllObjects];
// self.peripheralText.text = @"";
// [self showMessage:@"清空设备"]; if (self.cbPeripheral != nil)
{
// 取消连接
NSLog(@"取消连接");
// [self showMessage:@"取消连接"];
[self.centralManager cancelPeripheralConnection:self.cbPeripheral];
}
}
////000
//- (void)viewDidLoad {
// [super viewDidLoad];
// [self centralManager];
//}
///
//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态 状态更新时调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
case CBManagerStateUnknown:{
NSLog(@"为知状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateResetting:
{
NSLog(@"重置状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateUnsupported:
{
NSLog(@"不支持的状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateUnauthorized:
{
NSLog(@"未授权的状态");
self.peripheralState = central.state;
}
break;
case CBManagerStatePoweredOff:
{
NSLog(@"关闭状态");
self.peripheralState = central.state;
}
break;
case CBManagerStatePoweredOn:
{
NSLog(@"开启状态-可用状态");
self.peripheralState = central.state;
// 链接成功开始扫描设备
[self scanForPeripherals];
NSLog(@"%ld",(long)self.peripheralState);
}
break;
default:
break;
}
}
/**
333扫描到设备 发现设备是开启状态后调用方法 @param central 中心管理者
@param peripheral 扫描到的设备
@param advertisementData 广告信息
@param RSSI 信号强度
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
// [self showMessage:[NSString stringWithFormat:@"发现设备,设备名:%@",peripheral.name]];
// 设备数组中是否存在 该设备
if (![self.peripherals containsObject:peripheral])
{
[self.peripherals addObject:peripheral];
NSLog(@"%@",peripheral); //最常用的场景是查找某一个前缀开头的设备 mogu
if ([peripheral.name hasPrefix:@"JDY"] ) {
// [self showMessage:@"开始连接"];
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
} /**
连接失败 @param central 中心管理者
@param peripheral 连接失败的设备
@param error 错误信息
*/ - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
// [self showMessage:@"连接失败"];
if ([peripheral.name isEqualToString:kBlePeripheralName])
{
[self.centralManager connectPeripheral:peripheral options:nil];
}
} /**
连接断开 @param central 中心管理者
@param peripheral 连接断开的设备
@param error 错误信息
*/ - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
// [self showMessage:@"断开连接"];
if ([peripheral.name isEqualToString:kBlePeripheralName])
{
[self.centralManager connectPeripheral:peripheral options:nil];
}
} /**
444连接成功 @param central 中心管理者
@param peripheral 连接成功的设备
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"连接设备:%@成功",peripheral.name);
// self.peripheralText.text = [NSString stringWithFormat:@"连接设备:%@成功",peripheral.name];
// [self showMessage:[NSString stringWithFormat:@"连接设备:%@成功",peripheral.name]];
// 设备
self.cbPeripheral = peripheral;
self.cbperipheral(peripheral, YES); // 设置设备的代理
peripheral.delegate = self;
// services:传入nil 代表扫描所有服务
[peripheral discoverServices:nil];
} /**
555扫描到服务 @param peripheral 服务对应的设备
@param error 扫描错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
// 遍历所有的服务
for (CBService *service in peripheral.services)
{
NSLog(@"服务:%@",service.UUID.UUIDString);
// 获取对应的服务
if ([service.UUID.UUIDString isEqualToString:kWriteServerUUID] || [service.UUID.UUIDString isEqualToString:kNotifyServerUUID])
{
// 根据服务去扫描特征
[peripheral discoverCharacteristics:nil forService:service];
}
}
} /**
666扫描到对应的特征 @param peripheral 设备
@param service 特征对应的服务
@param error 错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// 遍历所有的特征
for (CBCharacteristic *characteristic in service.characteristics)
{ NSLog(@"特征值:%@",characteristic.UUID.UUIDString);
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
{
self.cbCharacteristic(characteristic);
}
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
{
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
} - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
{
//这个方法比较好,这个是你发数据到外设的某一个特征值上面,并且响应的类型是 CBCharacteristicWriteWithResponse ,上面的官方文档也有,如果确定发送到外设了,就会给你一个回应,当然,这个也是要看外设那边的特征值UUID的属性是怎么设置的,看官方文档,人家已经说了,条件是,特征值UUID的属性:CBCharacteristicWriteWithResponse
if (!error) {
NSLog(@"说明发送成功,characteristic.uuid为:%@ 发送为%@",[characteristic.UUID UUIDString],characteristic.value);
Byte byte2[] = {0xf0, 0x3d, 0x3d, 0x5d,0x02,0xf7};
NSData* data2 = [[NSData alloc] initWithBytes:byte2 length:];
if ([characteristic.value isEqualToData:data2]) {
NSLog(@"说明发送成功,characteristic.uuid为:%@ 发送为%@",[characteristic.UUID UUIDString],characteristic.value);
}
}else{
NSLog(@"发送失败了啊!characteristic.uuid为:%@ 原因:%@",[characteristic.UUID UUIDString],error); }
//调用下面的方法后 会调用到代理的- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
[peripheral readValueForCharacteristic:characteristic];
} ///**
// 根据特征读到数据
//
// @param peripheral 读取到数据对应的设备
// @param characteristic 特征
// @param error 错误信息
// */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error
{
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
{
NSData *data = characteristic.value;
NSLog(@"%@",data);
}
} @end

2、一般在登录后的主窗口 初始化下面这个类 连接蓝牙和保存蓝牙相关数据 保存蓝牙设备值和特征值  发送数据会用到

SaveValueForBlueThooth.h

//
// SaveValueForBlueThooth.h
// SmartRobot
//
// Created by 杜文杰 on 2017/8/10.
// Copyright © 2017年 appleLJ. All rights reserved.
// #import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import "BlueToothManger.h" @interface SaveValueForBlueThooth : NSObject @property (nonatomic, strong) BlueToothManger *blueToothManager;
// 设备
@property (nonatomic, strong) CBPeripheral *peripheral;
// 特征值
@property (nonatomic, strong) CBCharacteristic *characteristic;
// 连接成功标识
@property (nonatomic, assign) BOOL connectSeccess; + (instancetype)allocWithZone:(struct _NSZone *)zone;
// 重新连接
- (void)bluetoothConnect;
// 发送数据
- (void)postValueForBlueThoothWithString:(NSString *)valueWithStr; @end

SaveValueForBlueThooth.m

//
// SaveValueForBlueThooth.m
// SmartRobot
//
// Created by 杜文杰 on 2017/8/10.
// Copyright © 2017年 appleLJ. All rights reserved.
// #import "SaveValueForBlueThooth.h" // 通知特征值
static NSString * const kNotifyCharacteristicUUID = @"FFE1"; @implementation SaveValueForBlueThooth static SaveValueForBlueThooth *_instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
// 也可以使用一次性代码
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
});
return _instance;
} // 连接蓝牙设备
- (void)bluetoothConnect
{
[self.blueToothManager connectPeripheral:self.peripheral options:nil]; } // 发送数据
- (void)postValueForBlueThoothWithString:(NSString *)valueWithStr
{ NSLog(@"设备名:%@ 特征值 %@",self.peripheral.name,self.characteristic);
// 特征值
NSString *tzName = self.characteristic.UUID.UUIDString;
// 设备名
NSString *peripheraName = self.peripheral.name;
if (tzName.length > && peripheraName.length > ) {
// 写入数据 M_1_1000_\r
NSData *data = [valueWithStr dataUsingEncoding: NSUTF8StringEncoding];
[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
NSLog(@"%@",self.characteristic.UUID.UUIDString); NSLog(@"发送成功");
}else {
[self bluetoothConnect];
NSLog(@"重新连接蓝牙");
} } @end

3、在跟控制器 主窗口中声明属性

(1)

@property (nonatomic, strong) BlueToothManger *blueToothManager;
// 设备
@property (nonatomic, strong) CBPeripheral *peripheral;
// 特征值
@property (nonatomic, strong) CBCharacteristic *characteristic;
// 连接成功标识
@property (nonatomic, assign) BOOL connectSeccess; @property (nonatomic, strong) SaveValueForBlueThooth *saveValueForBlueThooth;

(2)在 viewDidLoad中调用连接蓝牙 并保存相关 发送需要的数据

- (void)viewDidLoad {
[super viewDidLoad]; // 连接蓝牙
[self connectPeripheral]; }

(3)

#pragma  mark - 蓝牙连接
- (void)connectPeripheral
{
// 单例记录发送数据 需要用的 设备值和特征值
_saveValueForBlueThooth = [[SaveValueForBlueThooth alloc]init];
// 初始化blueToothManager类连接蓝牙设备
self.blueToothManager = [[[BlueToothManger alloc]init]ShareBlueToothManger];
[self.blueToothManager centralManager];
__block
__block typeof(SaveValueForBlueThooth *)saveValueForBlue = _saveValueForBlueThooth;
// 连接蓝牙设备成功回调
// 存储设备值
self.blueToothManager.cbperipheral = ^(CBPeripheral *peripheral, BOOL connectSeccuss) {
saveValueForBlue.peripheral = peripheral;
saveValueForBlue.connectSeccess = connectSeccuss;
};
// 存储特征值
self.blueToothManager.cbCharacteristic = ^(CBCharacteristic *characteristic) {
saveValueForBlue.characteristic = characteristic;
};
}

4、在需要发送数据的界面

(1)在 viewDidLoad中初始化类

 self.blueThoothPostValue = [[SaveValueForBlueThooth alloc]init];

(2)发送按钮点击事件

//上
- (void)topBtnEvent{
NSLog(@"up");
[self.blueThoothPostValue postValueForBlueThoothWithString:@"E 1\r"];
}

IOS蓝牙连接 初步简单封装使用的更多相关文章

  1. iOS关于蓝牙连接的简单介绍与使用

    下面是两台iPhone6连接同一台蓝牙设备的结果: **成功连接**** peripheral: <CBPeripheral: 0x1700f4500, identifier = 50084F6 ...

  2. iOS蓝牙连接流程介绍-1

    蓝牙连接流程介绍 1.1-程序员找女朋友流程介绍 0.程序员找女朋友参与者 1.你 2.受害者(女性同胞)  (1)她的性格1 性格的特点 (2)她的性格2  分析性格的特点 1.寻找女性 寻尽身边一 ...

  3. 转载 -- iOS中SDK的简单封装与使用

    一.功能总述 在博客开始的第一部分,我们先来看一下我们最终要实现的效果.下图中所表述的就是我们今天博客中要做的事情,下方的App One和App Two都植入了我们将要封装的LoginSDK, 两个A ...

  4. android 蓝牙连接端(客户端)封装

    0.权限  AndroidManifest.xml <uses-permission android:name="android.permission.BLUETOOTH"/ ...

  5. iOS蓝牙原生封装,助力智能硬件开发

    代码地址如下:http://www.demodashi.com/demo/12010.html 人工智能自1956年提出以来,一直默默无闻,近年来人工智能的发展得到重视逐渐发展起步,智能硬件.智能手环 ...

  6. 基于swift语言iOS8的蓝牙连接(初步)

    看过一些蓝牙App的事例,大体上对蓝牙的连接过程进行了了解.但是开始真正自己写一个小的BLE程序的时候就举步维艰了.那些模棱两可的概念在头脑中瞬间就蒸发了,所以还是决定从最基本的蓝牙连接过程进行.这里 ...

  7. iOS开发——UI篇OC篇&UITableView简单封装

    UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...

  8. Redisclient连接方式Hiredis简单封装使用,连接池、屏蔽连接细节

    工作须要对Hiredis进行了简单封装,实现功能: 1.API进行统一,对外仅仅提供一个接口. 2.屏蔽上层应用对连接的细节处理: 3.底层採用队列的方式保持连接池,保存连接会话. 4.重连时採用时间 ...

  9. iOS sqlite 增删改查 简单封装(基于 FMDB)

    /** *  对 sqlite 的使用进行简单封装,仅涉及简单的单表 增删改查 * *  基于 FMDB * *  操作基于 model ,数据库表字段与 model 属性一一对应,对 model 整 ...

随机推荐

  1. [数据挖掘课程笔记]人工神经网络(ANN)

    人工神经网络(Artificial Neural Networks)顾名思义,是模仿人大脑神经元结构的模型.上图是一个有隐含层的人工神经网络模型.X = (x1,x2,..,xm)是ANN的输入,也就 ...

  2. php常用加密函数总结

    $var = 123; /** * md5 加密(单项加密.不可逆) * param $var 需要加密的变量(int\float\string\bool\null),资源类型(resource)和复 ...

  3. Python 的枚举类型

    起步 Python 中的枚举类型 Python 的原生类型中并不包含枚举类型.为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库. 枚举类型可以看作 ...

  4. 将自定义参数从uboot传入kernel的并读取的方法【转】

    本文转载自:http://blog.csdn.net/qq_29729577/article/details/50580727 希望朋友们多多指点,好的技术或心得一起分享: uboot向kernel传 ...

  5. jquery特效(5)—轮播图③(鼠标悬浮停止轮播)

    今天很无聊,就接着写轮播图了,需要说明一下,这次的轮播图是在上次随笔中jquery特效(3)—轮播图①(手动点击轮播)和jquery特效(4)—轮播图②(定时自动轮播)的基础上写出来的,也就是本次随笔 ...

  6. HDU4549 M斐波那契数列 —— 斐波那契、费马小定理、矩阵快速幂

    题目链接:https://vjudge.net/problem/HDU-4549 M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Li ...

  7. 关于VLOOKUP函数的用法

    “Lookup”的汉语意思是“查找”,在Excel中与“Lookup”相关的函数有三个:VLOOKUP.HLOOKUO和LOOKUP.下面介绍VLOOKUP函数的用法. 一.功能 在表格的首列查找指定 ...

  8. 如何强制ffmpeg编码时输出一个关键帧

    http://blog.csdn.net/ashlingr/article/details/7829429 如何强制ffmpeg编码时输出一个关键帧   如何强制ffmpeg编码时输出一个关键帧 AV ...

  9. html5 3D圣诞树源码

    1. [代码][HTML]代码   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http ...

  10. POJ2217(最长公共子串)

    Secretary Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 992   Accepted: 408 Descripti ...