IOS之BLE蓝牙读取数据与写入数据

版权声明:本文为博主原创文章,未经博主允许不得转载。若有问题,请联系QQ1215192693 https://blog.csdn.net/qq_37523448/article/details/84238958

1.本篇文章归纳了详细的蓝牙读取,与蓝牙写入的通信。
2.借助公司最近一直研发蓝牙设备项目,博主一路走过来,也遇到不少的坑,希望在此能够给予更多看官的帮助。

  • 蓝牙的读取
  • UUID的主要类文件,归纳放置在一个文件:Constants.h
#define APP_NAME    @"DishTemp"

//温度值功能: 发送实时温度数据, 572.0ㄈ(共7个字节),字符串形式.1
#define BOOT_TEMPVALUE_UUID [CBUUID UUIDWithString:@"此处为你们硬件工程师提供的UUID"]

/* OTA Upgrade */
#pragma mark - OTA Upgrade

#define FLASH_ARRAY_ID   @"flashArrayID"
#define FLASH_ROW_NUMBER  @"flashRowNumber"

#define COMMAND_START_BYTE    0x01
#define COMMAND_END_BYTE      0x17
//Bootloader command codes

#define VERIFY_CHECKSUM       0x31
#define GET_FLASH_SIZE        0x32
#define SEND_DATA             0x37
#define ENTER_BOOTLOADER      0x38
#define PROGRAM_ROW           0x39
#define VERIFY_ROW            0x3A
#define EXIT_BOOTLOADER       0x3B


// Bootloader status/Error codes

#define SUCCESS               @"0x00"
#define ERROR_FILE            @"0x01"
#define ERROR_EOF             @"0x02"
#define ERROR_LENGTH          @"0x03"
#define ERROR_DATA            @"0x04"
#define ERROR_COMMAND         @"0x05"
#define ERROR_DEVICE          @"0x06"
#define ERROR_VERSION         @"0x07"
#define ERROR_CHECKSUM        @"0x08"
#define ERROR_ARRAY           @"0x09"
#define ERROR_ROW             @"0x0A"
#define ERROR_BOOTLOADER      @"0x0B"
#define ERROR_APPLICATION     @"0x0C"
#define ERROR_ACTIVE          @"0x0D"
#define ERROR_UNKNOWN         @"0x0F"
#define ERROR_ABORT           @"0xFF"


#define UPGRADE_BTN_TITLE_FOR_SEPERATE_SELECTION    @"NEXT"
#define UPGRADE_BTN_TITLE_DEFAULT                   @"UPGRADE"

#define COMMAND_START_BYTE    0x01
#define COMMAND_END_BYTE      0x17

#define CHECK_SUM   @"checkSum"
#define CRC_16      @"crc_16"
#define ROW_DATA    @"rowData"

/* File parsing alerts */
#define FILE_FORMAT_ERROR           @"FileFormatError"
#define PARSING_ERROR               @"ParsingError"
#define FILE_EMPTY_ERROR            @"FileEmpty"

#define LOCALIZEDSTRING(string) NSLocalizedString(string, nil)

蓝牙链接上之后,读取到服务:BlueHelp.m

//只要扫描到特征就会调用,其中的外设和服务就是特征所在的外设和服务
- (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];
            }
     
            //Tempunit
            else if([characteristic.UUID isEqual:BOOT_TEMPUNIT_UUID]){
                _sendtempunitcharateristic = characteristic;
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }
            else{
                ..........
            }
        }
    }
}

得到蓝牙温度,现在就需要解析温度数据

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    BOOL ota = [_userDefaults getOta];
    NSLog(@"ISOTA is %d",ota);
    //不是OTA的情况 也不是发送数据的情况
    //顺序依次为 温度是否正常->温度值->温度符号->温度地址->温度报警值->温度报警静音->温度报警开关->电压提示
    if(!ota&&!_isSendData){
        NSString *temp=[self getTempTMWData:characteristic];
        NSArray *tmp = [temp componentsSeparatedByString:@","];
        
        NSString *nomal = tmp[0];
        NSString *temptemp = tmp[1];
        NSString *tempunit = tmp[2];
        int tempaddre = [tmp[3] intValue];
        
       // NSLog(@"DSADASFDSGFG%@sss%@www%@",nomal,temptemp,tempunit);
        
        self.currentDate = [NSDate date];
        NSString *dateString = [_dateformatter stringFromDate:self.currentDate];
        NSDate *logDate = [_dateformatter dateFromString:dateString];
        long logTime= (long)[logDate timeIntervalSince1970];
        
        //如果要等于F的时候
        if(_currentTime!=logTime){
            if([tempunit isEqualToString:@"F"]){
                //float floatString = [temptemp floatValue];
                //float aa = [_commonUtil convertFahrenheitToCelcius:floatString];
                //正常的时候
                if(tempaddre==0){
                    //NSString *ftempWendu =  [NSString stringWithFormat:@"%f",aa];
                    //NSString *ftempSymbol = @"C";
                    //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:ftempWendu saveTempSymbol:ftempSymbol saveTemptime:logTime];
                }else if(tempaddre==1){
                    //NSString *ftempSymbol = @"C";
                    //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:@"999" saveTempSymbol:ftempSymbol saveTemptime:logTime];
                }
            }else{
                if(tempaddre==0){
                    //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:temptemp saveTempSymbol:tempunit saveTemptime:logTime];
                }else if(tempaddre==1){
                    //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:@"999" saveTempSymbol:tempunit saveTemptime:logTime];
                }
            }
            _currentTime = logTime;
        }
        
        //发送所有数据
        NSDictionary *tempDict = [NSDictionary dictionaryWithObject:temp forKey:@"tempData"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofiction" object:nil userInfo:tempDict];
        
    }

引入BlueHelp.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) 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;

@end

此时就是显示的界面,接收蓝牙的广播

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletion:) name:@"tempNofiction" object:nil];

接收到广播,把信息展示出来

-(void)tempCompletion:(NSNotification*)notification{
    //第一次加载的时候需要这么执行
    if(_onceLoad){
        [_progress closeLoadingView];
        _tempView.leftView.hidden = FALSE;
        _tempView.rightView.hidden = FALSE;
        _onceLoad = FALSE;
    }
    
    //顺序依次为 温度是否正常->温度值->温度符号->温度地址->温度报警值->温度报警静音->温度报警开关->电压提示-静音报警开关
    // 0-1-2-3-4-5-6-7-8
    NSDictionary *temp = [notification userInfo];
    NSString *tempData = [temp objectForKey:@"tempData"];
    //测试打印
    //NSLog(@"传过来的温度是:%@",tempData);
    NSArray *tp = [tempData componentsSeparatedByString:@","];
    
    
    _temptemp = tp[0];//时实温度
    _TmaxTemp = tp[1];//最大温度
    _tempunit = tp[2];//温度符号
    _mutesound = [tp[3] intValue];//低电压判断

    //save temp... unit.
    //存储地址
    [_userDefaults saveMacAddre:self.maclistdata];
    [_userDefaults saveTempUnit:_tempunit macAddre:self.maclistdata];
    [_userDefaults saveCorF:_tempunit macAddre:self.maclistdata];
    //save high alarm.
    
    //当为第一次运行的时候 都统一默认为5秒
    if(_onceRun&&!_onceRunApp){
     
        _tempView.txtaddre.text = self.maclistdata;
        //存入蓝牙地址
        if(self.maclistdata!=nil){
            [_userDefaults saveMacAddre:self.maclistdata];
        }
        //存入温度符号
        if(_tempunit!=nil){
            [_userDefaults saveTempUnit:_tempunit macAddre:self.maclistdata];
        }
        
        //获取当前的时间
        NSString *time = [_userDefaults getUpdateTime:self.maclistdata];
        if(time!=nil){
            [_blueHelp writeIntervalTime:time];
        }else{
            [_blueHelp writeIntervalTime:@"5"];
        }

        //调式程序
        //[_blueHelp writeHighAlarm:@"-10"];
        
        //发送cal值
        NSString *cal = [_userDefaults getCal:self.maclistdata currentSymbol:_tempunit];
        if([cal isEqualToString:@""]||cal==nil){
            cal = @"0";
        }
        NSString *calSymbol = [_userDefaults getCalSymbol:self.maclistdata];
        if([_tempunit isEqualToString:calSymbol]){
            [self sendCalSet:cal];
        }else{
            if([_tempunit isEqualToString:@"°C"]){
                if([calSymbol isEqualToString:@"°F"]){
                    float a = [cal floatValue];
                    float b = [_commonUtil convertFahrenheitCalCelcius:a];
                    NSString *bb = [NSString stringWithFormat:@"%0.1f",b];
                    [self sendCalSet:bb];
                }
            }else{
                if([calSymbol isEqualToString:@"°C"]){
                    float a = [cal floatValue];
                    float b = [_commonUtil convertCelciusCalFahren:a];
                    NSString *bb = [NSString stringWithFormat:@"%0.1f",b];
                    [self sendCalSet:bb];
                }
            }
        }
        _onceRun = FALSE;
    }
    
    /*
     * 更新于 2017/11/16 14:44
     */
    //为1的时候显示 低电量 当为低电量的时候所有的事件也要执行
    [self displayFont:_voltage];
    [self showData];
}

2.写入蓝牙的功能

  1. 首先根据自己的项目需求
  2. 然后跟硬件工程师协商好
  3. 发送的字符规格,节数等等

如下:发送“pd”,给底层,为设备的关机

		NSString *otapd = @"PD";
        [_blueHelp writeBluePD:otapd];//调用写入的类,发送pd
//PD设备关机
-(void)writeBluePD:(NSString *)value{
    _isSendData = TRUE;
    [self writeClearPD:value forCharacteristic:_senddoutstrateristic];
    
}
//写入PD的区块
-(void)writeClearPD:(NSString *)value forCharacteristic:(CBCharacteristic *)characteristic
{
    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"send data pd and is:%@",data);
    //is no write bluetooth data
    if(_senddoutstrateristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
    {
        //send phone on bluetooth data
        [_selectperipheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
    }else
    {
        [_selectperipheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
    }
    //NSLog(@"已经向外设%@的特征值%@写入数据",_peripheral.name,characteristic.description);
    _isSendData = FALSE;
}

BlueHelp.h文件

//发送字符串'PD'机子关机(3个字节)
@property (nonatomic,strong) CBCharacteristic *senddoutstrateristic;

//写入设备的开关按钮
-(void)writeBluePD:(NSString *)value;

BuleHelp.m文件

读取到蓝牙UUID服务的时候,加上这个
//发送字符串'PD'机子关机(3个字节)
            else if([characteristic.UUID isEqual:BOOT_OUTSTRING_UUID]){
                _senddoutstrateristic = characteristic;
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }

最后,经过测试完毕,蓝牙的读取和写入就阐述到此,如有不懂的可以留言。若有帮助,麻烦点个赞,谢谢您的阅读!~

猜你喜欢

转载自blog.csdn.net/qq_37523448/article/details/84238958
今日推荐