本篇博文阐述如何开发Ble蓝牙。在蓝牙中的一些常见服务,扫描,以及链接;
主蓝牙类文件.h 主蓝牙类文件.m UUID文件 蓝牙列表展示的文件一:引入Ble蓝牙的框架<CoreBluetooth/CoreBluetooth.h>
BuleHelp.h
#import <Foundation/Foundation.h>
//导入蓝牙框架
#import <CoreBluetooth/CoreBluetooth.h>
#import "DeviceModel.h"
#import "Constants.h"
#import "CommonUserDefaults.h"
#import "CommonUtil.h"
#import "TempDB.h"
#define COMMAND_PACKET_MIN_SIZE 7
@interface BlueHelp : NSObject
//蓝牙的设备搜索显示在列表中
@property (nonatomic, strong) NSMutableArray <CBPeripheral*>*periperals;
//连接peripheral
@property(nonatomic,strong) CBPeripheral *peripheral;
//连接peripheral
@property(nonatomic,strong) CBPeripheral *selectperipheral;
//中心管理者
@property (nonatomic, strong) CBCentralManager *centerManager;
@property (nonatomic,strong) DeviceModel *deviceModel;
//设备列表
@property (nonatomic,strong) NSMutableArray *deviceList;
@property (nonatomic,strong) NSMutableArray *commandArray;
//是否进行ota升级
@property (nonatomic) BOOL isOta;
@property (nonatomic) BOOL isWritePacketDataSuccess;
@property (strong,nonatomic) NSString * checkSumType;
/*!
* @property isApplicationValid
*
* @discussion flag used to check whether the application writing is success
*
*/
@property (nonatomic) BOOL isApplicationValid;
/*!
* @property checkSum
*
* @discussion checkSum received from the device for writing a single row
*
*/
@property (assign) uint8_t checkSum;
/*!
* @property startRowNumber
*
* @discussion Device flash start row number
*
*/
@property (nonatomic) int startRowNumber;
/*!
* @property endRowNumber
*
* @discussion Device flash end row number
*
*/
@property (nonatomic) int endRowNumber;
/*!
* @property siliconIDString
*
* @discussion siliconID from the device response
*
*/
@property (strong,nonatomic) NSString *siliconIDString;
/*!
* @property siliconRevString
*
* @discussion silicon rev from the device response
*
*/
@property (strong,nonatomic) NSString *siliconRevString;
//是否发送数据
@property (nonatomic) BOOL isSendData;
@property (strong,nonatomic) CommonUtil *commonUtil;
@property (strong,nonatomic) TempDB *tempDB;
@property (strong,nonatomic) NSDate *currentDate;
//时间格式化
@property(strong,nonatomic) NSDateFormatter *dateformatter;
@property(strong,nonatomic) NSString *deviceName;
//@property (nonatomic,strong) NSUserDefaults *userDefaults;
@property (nonatomic,strong) CommonUserDefaults *userDefaults;
//发送温度数据
@property (nonatomic,strong) CBCharacteristic *sendtempcharateristic;
//发送OTA数据
@property (nonatomic,strong) CBCharacteristic *sendotacharateristic;
//高/低温度数据
//@property (nonatomic,strong) CBCharacteristic *sendhighalarmcharateristic;
//
//@property (nonatomic,strong) CBCharacteristic *sendlowalarmcharateristic;
//ota
@property (nonatomic,strong) CBCharacteristic *senddfucharateristic;
//发送字符串'CR'清除机子上的最大值(3个字节)
@property (nonatomic,strong) CBCharacteristic *senddcrstrateristic;
//发送字符串'PD'机子关机(3个字节)
@property (nonatomic,strong) CBCharacteristic *senddoutstrateristic;
//静音
@property (strong,nonatomic) CBCharacteristic *sendmutealarmcharateristic;
//calset
@property(strong,nonatomic) CBCharacteristic *sendcalsetcharateristic;
//intervaltime
@property(strong,nonatomic) CBCharacteristic *sendintervaltimecharateristic;
//alarmswitch
@property(strong,nonatomic) CBCharacteristic *sendalarmswitchcharateristic;
//tempunit
@property(strong,nonatomic) CBCharacteristic *sendtempunitcharateristic;
@property(strong,nonatomic) CBCharacteristic *sendlowalarmswitchcharateristic;
///<===============方法区块=======================>
+ (id)sharedManager;
-(NSMutableArray *)getDeviceList;
-(NSMutableArray *)getPeriperalList;
-(void)startScan;
//连接蓝牙
-(void)contentBlue:(int) row;
//断开蓝牙
-(void)disContentBle;
//断开ota的蓝牙连接
-(void)disContentOtaBle;
//温度符号
-(void)writeTempUnit:(NSString *)value;
//写入报警开关
-(void)writeAlarmSwitch:(NSString *)value;
//写入mute alarm
-(void)writeMuteAlarm:(NSString *)value;
//写入CR CLERVULE
-(void)writeClearCR:(NSString *)value;
//写入interval time
-(void)writeIntervalTime:(NSString *)value;
//写入cal set
-(void)writeCalSet:(NSString *)value;
//写入设备的开关按钮
-(void)writeBluePD:(NSString *)value;
//写入低温报警
//-(void)writeLowAlarm:(NSString *)value;
//
////写入高温报警
//-(void)writeHighAlarm:(NSString *)value;
//OTA固件升级 又称为DFU
-(void)writeUpdateOTA:(NSString*)value;
-(void)writeBlueOTA:(NSString *)value;
-(void)wirteBlueOTAData:(NSData *)value;
-(void)writeLowAlarmSwitch:(NSString *)value;
-(void) discoverCharacteristicsWithCompletionHandler:(void (^) (BOOL success, NSError *error)) handler;
-(void)updateValueForCharacteristicWithCompletionHandler:(void (^) (BOOL success,id command,NSError *error)) handler;
-(void) stopUpdate;
-(void) setCheckSumType:(NSString *) type;
-(NSData *) createCommandPacketWithCommand:(uint8_t)commandCode dataLength:(unsigned short)dataLength data:(NSDictionary *)packetDataDictionary;
-(void) writeValueToCharacteristicWithData:(NSData *)data bootLoaderCommandCode:(unsigned short)commandCode;
/*
* 停止扫描
*/
-(void)stopScan;
//是否是第一次连接设备
@property(assign,nonatomic) BOOL isconnected;
//当前的时间
@property(nonatomic,assign) long currentTime;
@property(nonatomic,strong) NSString *macAddre;
@property(nonatomic,strong) NSString *macName;
-(void)disMainOtaBle;
@end
BuleHelp.m
//程序运行后,会自动调用的检查蓝牙的方法 并扫描蓝牙的方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
if ([central state] == CBCentralManagerStatePoweredOff) {
NSLog(@"CoreBluetooth BLE hardware is powered off");
}
else if ([central state] == CBCentralManagerStatePoweredOn) {
NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
[self startScan];
}
else if ([central state] == CBCentralManagerStateUnauthorized) {
NSLog(@"CoreBluetooth BLE state is unauthorized");
}
else if ([central state] == CBCentralManagerStateUnknown) {
NSLog(@"CoreBluetooth BLE state is unknown");
}
else if ([central state] == CBCentralManagerStateUnsupported) {
NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
}
}
/*
* 程序运行的时候开始扫描
*/
-(void)startScan{
_periperals = [[NSMutableArray alloc] init];
_deviceList = [[NSMutableArray alloc] init];
//2.利用中心设备扫描外部设备
[_centerManager scanForPeripheralsWithServices:nil options:nil];
}
/*
* 停止扫描
*/
-(void)stopScan{
[_centerManager stopScan];
}
/*
* 设备中可以包含 Device addre地址 放在 key:kCBAdvDataManufacturerData中既可以得到
* 1.硬件开发工程师 把地址写入到设备的厂家信息中。
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSS{
//判断如果数组中不包含当前扫描到的外部设备才保存
if (![_periperals containsObject:peripheral]){
//包扣3种设备 都需要去搜索
if([peripheral.name containsString:@"TMW012BT"]||[peripheral.name containsString:@"OTA"]){
NSLog(@"DATA: %@", advertisementData);
NSArray *keys = [advertisementData allKeys];
for (int i = 0; i < [keys count]; ++i) {
id key = [keys objectAtIndex: i];
NSString *keyName = (NSString *) key;
NSData *value = [advertisementData objectForKey: key];
if([keyName isEqualToString:@"kCBAdvDataManufacturerData"]){
NSLog(@"value is %@",value);
NSString *result = [self convertDataToHexStr:value];
NSLog(@"reslut is %@",result);
if(result!=nil&&result.length>4){
NSString *d = [result substringFromIndex:4];
NSLog(@"D IS %@",d);
// 小写
//NSString *lower = [test lowercaseString];
// 大写
NSString *upper = [d uppercaseString];
_macAddre = [NSString stringWithFormat:@"S/N:%@",upper];
}
}
if([keyName isEqualToString:@"kCBAdvDataLocalName"]){
NSString *aStr= (NSString*)value;
NSLog(@"astr is %@",aStr);
_macName = aStr;
}
}
_deviceModel = [DeviceModel new];
_deviceModel.deviceName = _macName;
//蓝牙地址
_deviceModel.deviceAddre = _macAddre;
int rssi = [RSS intValue];
NSString *range = [NSString stringWithFormat:@"%d",rssi];
NSString *rs = [NSString stringWithFormat:@"RSSI %@dBm",range];
//添加到里面
[self.periperals addObject:peripheral];
_deviceModel.deviceRssi = rs;
[_deviceList addObject:_deviceModel];
}
}
}
//解析广播里面的数据
-(void)getAdvertisementData:(NSDictionary<NSString *,id> *) advertisementData{
NSArray *keys = [advertisementData allKeys];
for (int i = 0; i < [keys count]; ++i) {
id key = [keys objectAtIndex: i];
NSString *keyName = (NSString *) key;
NSObject *value = [advertisementData objectForKey: key];
if([keyName isEqualToString:@"kCBAdvDataManufacturerData"]){
printf(" key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);
NSString *values = (NSString *) value;
NSLog(@"values is %@",values);
}
}
}
/*
* 连接蓝牙设备给外部调用的方法
* 传入的是相对应的行数
*/
-(void)contentBlue:(int) row{
[_centerManager connectPeripheral:_periperals[row] options:nil];
}
-(void)disContentBle{
//关键的断开蓝牙 通知也要停止掉
if((_peripheral!=nil && _sendtempcharateristic!=nil)){
[_peripheral setNotifyValue:NO forCharacteristic:_sendtempcharateristic];
[self disconnectPeripheral:_peripheral];
}
}
/*
* 断开ota的 连接
*/
-(void)disContentOtaBle{
if(_peripheral!=nil && _sendotacharateristic!=nil){
[_peripheral setNotifyValue:NO forCharacteristic:_sendotacharateristic];
[self disconnectPeripheral:_peripheral];
}
}
-(void)disMainOtaBle{
if(_peripheral!=nil){
[self disconnectPeripheral:_peripheral];
}
}
- (void) disconnectPeripheral:(CBPeripheral*)peripheral
{
[_centerManager cancelPeripheralConnection:peripheral];
}
//连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
NSLog(@"连接成功");
if(peripheral!=nil){
//停止扫描 这个用于自动连接的时候
[_centerManager stopScan];
//设备名称
_deviceName = peripheral.name;
_selectperipheral = peripheral;
peripheral.delegate = self;
//再去扫描服务
[peripheral discoverServices:nil];
}
}
//连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
NSLog(@"连接失败,失败原因:%@",error);
NSString *disContentBlue = @"discontentblue";
NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
//发送广播 连接失败
[[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
//断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"断开连接");
NSString *disContentBlue = @"discontentblue";
//_blueiscon = @"Disconnect";
NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
//发送广播 连接失败
[[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
//只要扫描到服务就会调用,其中的外设就是服务所在的外设
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
if (error){
NSLog(@"扫描服务出现错误,错误原因:%@",error);
}else{
//获取外设中所扫描到的服务
for (CBService *service in peripheral.services){
//拿到需要扫描的服务,例如FFF0 比如打印温度数据
//把所有的service打印出来
//从需要的服务中查找需要的特征
//从peripheral的services中扫描特征
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
//只要扫描到特征就会调用,其中的外设和服务就是特征所在的外设和服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error{
if(error){
NSLog(@"扫描特征出现错误,错误原因:%@",error);
}else{
//遍历特征,拿到需要的特征进行处理
for (CBCharacteristic *characteristic in service.characteristics){
NSLog(@"characteristic is %@",characteristic.UUID);
//如果是温度数据处理
if([characteristic.UUID isEqual:BOOT_TEMPVALUE_UUID]){
//将全部的特征信息打印出来
_isconnected = true;
_peripheral = peripheral;
_sendtempcharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//如果是ota进行ota升级
else if([characteristic.UUID isEqual:BOOT_OTA_WIRTE_UUID]){
_peripheral = peripheral;
_sendotacharateristic = characteristic;
//设置通知
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
_isOta = TRUE;
[_userDefaults saveOta:_isOta];
//[_ setBool:_isOta forKey:@"isOTA"];
NSString *s = @"OTA";
NSDictionary *tempOta = [NSDictionary dictionaryWithObject:s forKey:@"ota"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"tempOTA" object:nil userInfo:tempOta];
}
//CAL
else if([characteristic.UUID isEqual:BOOT_CAL_UUID]){
_sendcalsetcharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//interval time
else if([characteristic.UUID isEqual:BOOT_INTERVALTIME_UUID]){
_sendintervaltimecharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//Tempunit
else if([characteristic.UUID isEqual:BOOT_TEMPUNIT_UUID]){
_sendtempunitcharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//DFU
else if([characteristic.UUID isEqual:BOOT_DFU_UUID]){
_senddfucharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//发送字符串'CR'清除机子上的最大值(3个字节)
else if([characteristic.UUID isEqual:BOOT_CRSTRING_UUID]){
_senddcrstrateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//发送字符串'PD'机子关机(3个字节)
else if([characteristic.UUID isEqual:BOOT_OUTSTRING_UUID]){
_senddoutstrateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
else{
}
}
}
}
/*
设置通知
*/
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
[_centerManager stopScan];
}
/*
取消通知
*/
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
/*
接收数据解析
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//是否为Ota
if(!self.isSendOta){
if(self.readtempcharater == characteristic){
NSString *tmpData = [self.cmUtil getTempTMWData:characteristic];
if(tmpData!=nil){
//开始处理数据
NSArray *data = [tmpData componentsSeparatedByString:@","];
TmpModel *tp = [[TmpModel alloc] init];
tp.tmp = data[0];
tp.max = data[1];
tp.unit = data[2];
//电量
tp.bat = data[3];
NSDictionary *tempDict = [NSDictionary dictionaryWithObject:tp forKey:@"tempData"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofiction" object:nil userInfo:tempDict];
if([tp.bat isEqual:@"1"]){
//低电量广播
NSDictionary *LowDict = [NSDictionary dictionaryWithObject:tp forKey:@"lowData"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"lowNofiction" object:nil userInfo:LowDict];
}
}
}
}
//======================写入数据区块========================//
/*
写入发送时间
*/
-(void)writeIntervalTime:(NSString *)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.sendtimecharater!=nil){
[self writeData:value forCharacteristic:self.sendtimecharater periperalData:periperal];
}
}
/*
写入温度单位
*/
-(void)writeTmpUnit:(NSString*)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.sendunitcharater!=nil){
[self writeData:value forCharacteristic:self.sendunitcharater periperalData:periperal];
}
}
/*
写入Cal值
*/
-(void)writeCalValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.sendcalcharater!=nil){
[self writeData:value forCharacteristic:self.sendcalcharater periperalData:periperal];
}
}
/*
发送Ota使得设备进入Ota
*/
-(void)writeDfuValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.senddfucharater!=nil){
[self writeData:value forCharacteristic:self.senddfucharater periperalData:periperal];
}
}
/*
发送Max Temp实现清零选项
*/
-(void)writeClearValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.sendclearcharater!=nil){
[self writeData:value forCharacteristic:self.sendclearcharater periperalData:periperal];
}
}
/*
发送关机选项实现远程开关机
*/
-(void)writeCloseValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
if(value!=nil&&periperal!=nil&&self.sendclosecharater!=nil){
[self writeData:value forCharacteristic:self.sendclosecharater periperalData:periperal];
}
}
/*
所有写入的数据处理
*/
-(void)writeData:(NSString *)value forCharacteristic:(CBCharacteristic *)characteristic periperalData:(CBPeripheral*)periperal{
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
if(characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
{
[periperal writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}else
{
[periperal writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
}
此篇文章阐述到这,基本BLE蓝牙开发实现都详细的描述了。
您可能感兴趣的文章:iOS蓝牙开发 蓝牙连接和数据读写iOS蓝牙开发数据实时传输