• iOS开发之蓝牙业务封装


    因为公司做智能家居开发,有很多蓝牙的智能硬件。因此项目中经常需要和蓝牙打交道。为此为了提高开发效率,就把蓝牙的公共业务进行了封装。

    本文将对封装的思路做一个简单的阐述。

    首先我们需要一个头文件。在这个头文件中定义全局的宏,和结构体。看起来大概是这样的。

    //包长相关的宏
    #define MAX_PACK_LEN 2048
    #define MAX_SEND_LEN 1024
    #define MAX_SINGLE_PACKET_LEN 20
    
    /* 新协议 命令字 begin */
    /* 请求和应答协议版本命令字*/
    #define REQUEST_PROTOCOL_VERSION                0X4001
    #define RESPONSE_PROTOCOL_VERSION               0X0001
    
    #define REQUEST_BIND_BLE_DEVICE                 0X4002      // 请求绑定设备
    #define RESPONSE_BIND_BLE_DEVICE                0X0002      // 应答
    
    #define REQUEST_SYNC_DATA                       0X4006      // 请求同步数据
    #define RESPONSE_SYNC_DATA                      0X0006      // 应答
    
    #define REQUEST_KEY_DATA                        0X4008      // 请求数据
    #define RESPONSE_KEY_DATA                       0X0008      // 应答
    
    #define REQUEST_DELETE_DATA                     0X4010      // 请求删除数据
    #define RESPONSE_DELETE_DATA                    0X0010      // 应答
    
    #define REQUEST_UPGRADE_FIREWARE                0X4012      // 请求升级固件
    #define RESPONSE_UPGRADE_FIREWARE               0X0012      // 应答
    /* 新协议 命令字 end */
    
    /* 协议类型 */
    #define PROTOCOL_TYPE_UPGRADE                   0x10        // 升级协议
    #define PROTOCOL_TYPE_BUSINESS                  0x00        // 业务协议
    #define PROTOCOL_TYPE_BIND                      0x02        // 绑定协议
    
    //新的蓝牙协议包数据结构
    typedef struct
    {
        uint8_t         startflag;                  //起始标志      0XF2
        uint8_t         protocol_type;              //协议类型  升级协议:0x10 业务协议:0x00 绑定协议:0x02
        uint8_t         protocol_version;           //协议版本号
        uint8_t         reserved;                   //保留字节
        uint8_t         time[6];                    //协议时间  年以2010为基数往上累加
        uint8_t         timezone;                   //时区
        UInt16          frame_control;              //操作命令字
        uint16_t        body_length;                //数据长度
    } Ble_Protocol_Head_New;
    
    typedef struct{
        Ble_Protocol_Head_New*   head;
        uint8_t                 *body;              //包体
        uint16_t                 packet_fcs;        //FCS校验
    }Ble_Protocol_Packet_New;

    然后我们需要一个类来处理一些与具体业务无关的逻辑。比如错误处理,蓝牙数据收发,拆包和组包等这些。

    我们姑且叫这个类为BleBaseApi吧。在我们的项目中这个只暴露了两个接口。看起来大概是这样的:

    @class CLBLEBaseApi;
    typedef NS_ENUM (NSUInteger, CLBLEState){
        CLBLEStateIdle,
        CLBLEStateSending,
        CLBLEStateReceiving,
    };
    
    typedef void (^BLEScanDiscoverPeripheralsCallback) (NSArray *peripherals);
    
    @protocol CLBLEPacketHandle <NSObject>
    -(NSInteger)receivedPacketDataLength;
    -(NSInteger)totalPacketDataLength;
    
    -(NSData*)singlePacketDataDeviceResponse;  //设备收到app的数据后,要给app回复一个数据,告诉app我已经收到数据
    
    -(NSData*)singlePacketDataAppResponse;     //同理App也需要回复
    
    
    -(NSData*)fetchCompletePacketData;        //完整的数据包
    
    /**
     *  根据需要发送的数据包,做拆分,确定每一个包的数据内容
     *
     *  @return 单数数据包的内容
     */
    -(NSData*)fetchSinglePacketData;         //拆包后的数据
    
    /**
     *  解析收到的蓝牙数据
     *
     *  @param data  收到的数据
     *  @param error error信息
     *
     *  @return 如果解析完成,返回解析之后的值,如果解析失败返回空,error有值
     *  如果解析没有完成,返回空,error也是空
     */
    -(NSData*)receiveAndParseData:(NSData*)data error:(NSError**)error;
    
    
    -(id)apiManager:(CLBLEBaseApi*)manager reformData:(NSData*)data;
    @end
    
    
    
    
    
    @protocol CLBLEDataSource <NSObject>
    
    @required
    
    -(NSArray*)scanServiceArray;              //扫描到的服务       
    
    -(NSString*)readSeriveID;                 //读取数据的服务ID
    
    -(NSString*)readCharacteristicID;         //读取数据的特征ID
    
    -(NSString*)writeSeriveID;              
    
    -(NSString*)writeCharacteristicID;
    
    -(LGPeripheral*)connectedPeripheral;      //连接到的外设
    
    -(NSString *)broadName;                   //广播名
    
    @end
    
    typedef void (^BLEProgressiveDownLoadBlock) (NSInteger totalBytesRead, NSInteger totalBytesExpected);
    
    typedef void (^BLESuccessBlock) (NSData *data);
    
    typedef void (^BLEFailBlock) (NSError* error);
    
    typedef void (^BleStateBlock)(CBCentralManagerState state);
    
    @interface CLBLEBaseApi : NSObject
    
    @property (nonatomic,weak) NSObject<CLBLEDataSource>* child;
    
    @property (nonatomic,assign) CLBLEState state;
    
    @property (nonatomic,assign) BOOL bleIsReady;
    
    
    -(void)setProgressiveBlock:(BLEProgressiveDownLoadBlock)progressBlock;
    -(void)sendBLEDataWithDataPacketProtocol:(id<CLBLEPacketHandle>)packetDelegate
                                     Success:(BLESuccessBlock)successBlock
                                        fail:(BLEFailBlock)failBlock;

     其中 sendBLEDataWithDataPacketProtocol 方法处理蓝牙数据的发送接收,它的实现大概是这样子的

    -(void)sendBLEDataWithDataPacketProtocol:(id<CLBLEPacketHandle>)packetDelegate
                                     Success:(BLESuccessBlock)successBlock
                                        fail:(BLEFailBlock)failBlock{
        if (self.state!= CLBLEStateIdle) {
            NSError* error=[NSError errorWithDomain:kCLBLEManagerErrorDomain code:kBLEBusyErrorCode userInfo:@{@"message":kBLEBusyErrorCodeErrorMessage}];
            failBlock(error);
            return;
        }
        self.child=(id <CLBLEDataSource>)self;
    
        if (!self.child.connectedPeripheral) {
            NSError* error=[NSError errorWithDomain:kCLBLEManagerErrorDomain code:kBLEObjErrorCode userInfo:@{@"message":kBLEObjErrorCodeErrorMessage}];
            failBlock(error);
            return;
        }
        if (self.child.connectedPeripheral.cbPeripheral.state!=CBPeripheralStateConnected) {
            //NSError* error=[NSError errorWithDomain:kCLBLEManagerErrorDomain code:kBLECommunConnectErrorCode userInfo:@{@"message":@"设备没有连接,发个毛啊!"}];
            NSError* error=[NSError errorWithDomain:kCLBLEManagerErrorDomain code:kBLECommunConnectErrorCode userInfo:@{@"message":kBLECommunConnectErrorCodeErrorMessage}];
            failBlock(error);
            return;
        }
        self.dataPacketHandleDelegate=packetDelegate;
        [self sendBLEDataWithData:[self.dataPacketHandleDelegate fetchCompletePacketData]
                          Success:successBlock
                             fail:failBlock];
    }

    在BleBaseApi中声明了一个protocal用来获取数据包的长度以及各种数据包等,所以我们创建一个名为BleProtocal的类来负责这个事情

    typedef NSData* (^fetchSinglePacketDataBlock)();
    typedef NSData* (^receiveAndParseDataBlock)(NSData*data,NSError**error);
    typedef id    (^reformDataBlock)(NSData*data);
    
    @interface CLBLEBaseProtocol : NSObject<CLBLEPacketHandle>
    
    @property(nonatomic,strong)NSData* singleDeviceResponsePacketData;
    @property(nonatomic,strong)NSData* singleAppResponsePacketData;
    
    @property(nonatomic,strong)NSData* packetData;
    @property(nonatomic,copy)fetchSinglePacketDataBlock SinglePacketDataBlock;
    @property(nonatomic,copy)receiveAndParseDataBlock receiveAndParseDataBlock;
    @property(nonatomic,copy)reformDataBlock reformDataBlock;
    @property(nonatomic,assign) NSInteger singlePacketTotalSend;
    @property(nonatomic,assign) NSInteger  packetDataLength;
    @property(nonatomic,assign) NSInteger receiveBufferLength;
    @property(nonatomic,strong) NSMutableData* mutableReceiveData;

    这是BleProtocal的头文件,诸如 singleDeviceResponsePacketData ,packetData 这些数据都是外界传进来的。这个文件的实现大概是这样的

    -(receiveAndParseDataBlock)receiveAndParseDataBlock
    {
         __weak  CLBLEBaseProtocol * weakself = self;
        receiveAndParseDataBlock block = ^NSData*(NSData*data,NSError**error){
    
            if (!data) {
                *error=[NSError errorWithDomain:@"BLEReceiveDataHelper" code:01 userInfo:@{@"errorInfo":@"解析数据不能传空值"}];
                return nil;
    
            }
            if (data.length<=0) {
                *error=[NSError errorWithDomain:@"BLEReceiveDataHelper" code:01 userInfo:@{@"errorInfo":@"解析数据不能传空值"}];
                return nil;
            }
    
    
            if (weakself.receiveBufferLength==0) {
                uint8_t startFlag=0;
                [data getBytes:&startFlag length:1];
                if (startFlag!=0xf2) {
                    [self clear];
                    *error=[NSError errorWithDomain:@"BLEReceiveDataHelper" code:02 userInfo:@{@"errorInfo":@"起始不是0xf2"}];
                    return nil;
                }
            }
            if (!weakself.mutableReceiveData) {
                weakself.mutableReceiveData=[[NSMutableData alloc] initWithCapacity:0];
            }
            [weakself.mutableReceiveData appendData:data];
            weakself.receiveBufferLength+=data.length;
    
            if (weakself.receiveBufferLength>=sizeof(Ble_Protocol_Head_T)) {
    
                Ble_Protocol_Head_T bleProtocolHeaderT={0};
    
                int offset = (int)((size_t)&(bleProtocolHeaderT.body_length)-(size_t)&bleProtocolHeaderT);
    
                typeof (weakself.packetDataLength) length;
                [[weakself.mutableReceiveData subdataWithRange:NSMakeRange(offset, 2)] getBytes:&length length:2];
    
                weakself.packetDataLength = length;
                weakself.packetDataLength=htons(weakself.packetDataLength);
                weakself.packetDataLength=sizeof(Ble_Protocol_Head_T)+1+weakself.packetDataLength;
    
                if (weakself.receiveBufferLength>=weakself.packetDataLength) {
    
                    NSData* resultPacketData=[weakself.mutableReceiveData subdataWithRange:NSMakeRange(0, weakself.packetDataLength)];
    
                    uint8_t endFlag=0;
                    [[weakself.mutableReceiveData subdataWithRange:NSMakeRange(weakself.packetDataLength-1, 1)] getBytes:&endFlag length:1];
    
                    if (endFlag==0xf3) {
                        if (weakself.receiveBufferLength==weakself.packetDataLength) {
    //                        [weakself clear];
                        }
                        *error=nil;
                        //接收完成
                        return resultPacketData;
                    }
                    else{
                        *error=[NSError errorWithDomain:@"BLEReceiveDataHelper" code:02 userInfo:@{@"errorInfo":@"结束标志不是0xf3"}];
                        return nil;
                    }
                }
            }
            //接收 ing
            *error=nil;
            return nil;
        };
        return [block copy];
    }
    
    -(fetchSinglePacketDataBlock)SinglePacketDataBlock
    {
    
      __weak  CLBLEBaseProtocol * weakself = self;
        fetchSinglePacketDataBlock block = ^NSData*(){
    
    
            if ( weakself.singlePacketTotalSend >= weakself.packetData.length)
            {
                return nil;
            }
            int cur_send = ((self.packetData.length - _singlePacketTotalSend) > MAX_SINGLE_PACKET_LEN)? MAX_SINGLE_PACKET_LEN: (int)(self.packetData.length - self.singlePacketTotalSend);
            NSData* singleData=[self.packetData subdataWithRange:NSMakeRange(self.singlePacketTotalSend, cur_send)];
            self.singlePacketTotalSend += cur_send;
    
            return singleData;
    
        };
    
        return [block copy];
    }
    
    #pragma mark- BLEDataReformer
    -(id)apiManager:(CLBLEBaseApi *)manager reformData:(NSData *)data
    {
        return self.reformDataBlock?self.reformDataBlock(data):nil;
    }
    
    #pragma mark- CLBLEPacketHandle
    -(NSInteger)receivedPacketDataLength
    {
        return self.receiveBufferLength;
    }
    -(NSInteger)totalPacketDataLength
    {
        return self.packetDataLength;
    }
    -(NSData*)singlePacketDataDeviceResponse
    {
        return self.singleDeviceResponsePacketData;
    }
    -(NSData*)singlePacketDataAppResponse
    {
        return self.singleAppResponsePacketData;
    }
    /**
     *  一个完整包的数据内容
     *
     *  @return 完整数据包的内容
     */
    -(NSData*)fetchCompletePacketData
    {
        return self.packetData;
    }
    
    /**
     *  根据需要发送的数据包,做拆分,确定每一个包的数据内容
     *
     *  @return 单数数据包的内容
     */
    -(NSData*)fetchSinglePacketData
    {
        return self.SinglePacketDataBlock?self.SinglePacketDataBlock():nil;
    }
    
    /**
     *  解析收到的蓝牙数据
     *
     *  @param data  收到的数据
     *  @param error error信息
     *
     *  @return 如果解析完成,返回解析之后的值,如果解析失败返回空,error有值
     *  如果解析没有完成,返回空,error也是空
     */
    -(NSData*)receiveAndParseData:(NSData*)data error:(NSError**)error
    {
        return self.receiveAndParseDataBlock?self.receiveAndParseDataBlock(data,error):nil;
    }

    因为继承了<CLBLEPacketHandle> 所以实现了他的代理,通过这样将需要的数据包和数据长度传递给BleBaseApi。

    现在假设我们有一个智能床垫是蓝牙设备。我们会创建两个类分别继承自BleBaseApi和BleProtocal

    我们先看看BLEMattressProtocol。它的头文件大概如下:

    @interface BLEMattressProtocol :CLBLEBaseProtocol
    
    uint8_t ble_currentTimeOffset();
    
    void ble_gmtTimeString(uint8_t* timeValue);
    
    void ble_gmtTimeString_new(uint8_t* timeValue);
    void Init_Ble_Protocol_Head(uint8_t *packetArray,short comdNo,uint16_t dataLength,uint8_t* uniqueID,NSString *deviceVersion);
    void Init_Ble_Protocol_Head_New(uint8_t *packetArray,short comdNo,uint16_t dataLength,uint8_t* uniqueID);
    //获取统计数据的数据包
    +(BLEMattressProtocol*)getRequestStatisticalPacketData:(NSString*)uinqueIDString;
    
    //通知设备清除统计数据的数据包
    +(BLEMattressProtocol*)getDeleteStatisticalPacketData:(NSString*)uinqueIDString;
    
    
    /**
     *  获取实时数据数据包
     *
     *  @param uinqueIDString 唯一ID
     *
     *  @return 返回获取实时数据的数据包
     */
    +(BLEMattressProtocol*)getRequestRealTimePacketData:(NSString*)uinqueIDString;
    
    /**
     *  确认蓝牙升级的数据包
     *
     *  @param uinqueIDString 唯一ID
     *
     *  @return 返回获取蓝牙升级的数据包
     */
    +(BLEMattressProtocol *)getRequestConfirmUpgrade:(NSString *)uinqueIDString;
    
    
    @end

    再看看实现文件:

    //获取统计数据的数据包
    +(BLEMattressProtocol*)getRequestStatisticalPacketData:(NSString*)uinqueIDString{
        uint8_t packetHead[sizeof(Ble_Protocol_Head_T)]={0};
    //    uint8_t uinqueID[6]={0};
        uint8_t* uinqueID=(uint8_t*)[uinqueIDString UTF8String];
    
        Init_Ble_Protocol_Head(packetHead, REQUEST_GET_DATA_COMMAND, 0,uinqueID,nil);
    
        NSMutableData* packetData=[[NSMutableData alloc] initWithCapacity:0];
        NSData* packetHeadData=[NSData dataWithBytes:packetHead length:sizeof(Ble_Protocol_Head_T)];
        [packetData appendData:packetHeadData];
    
        uint8_t endCommand=BLE_PROTOCOL_END_FLAG;
        [packetData appendBytes:&endCommand length:1];
    
        BLEMattressProtocol* obj= [[self alloc] init];
        uint8_t byte[]={0};
    
    //    obj.singleAppResponsePacketData = [NSData dataWithBytes:byte length:1];
        obj.singleDeviceResponsePacketData = [NSData dataWithBytes:byte length:1];  //这里就是给BleProtocal里的那些属性赋值
        obj.packetData = packetData;
        return obj;
    
    //    return packetData;
    }

    我们再看看 MattressBLEManagerApi。下面是他的头文件。

    @interface MattressBLEManagerApi : CLBLEBaseApi<CLBLEDataSource>
    
    @property (nonatomic,strong) LGPeripheral* currentPeripheral;
    @property (nonatomic,strong) NSString* currentBroadName;
    @property (nonatomic,assign) BOOL BLEIsPowerOn;
    //固件升级时候版本号,如1.9.0
    @property (nonatomic,assign) NSString* DeviceUpgradeVersion;
    -(void)fetchHistoryDataWithSuccessBlock:(void(^)(NSData* data))success
                                  FailBlock:(void(^)(NSError* error))fail;
    
    -(void)fetchRealTimeDataSuccessBlock:(void(^)(NSData* data))success
                               FailBlock:(void(^)(NSError* error))fail;
    
    -(void)fetchRealTimeDataWithInterVal:(NSTimeInterval)interval
                                WithTimes:(NSTimeInterval)times
                                SuccessBlock:(void(^)(NSData* data))success
                               FailBlock:(void(^)(NSError* error))fail;
    
    
    -(void)fetchBLEHandShakeSuccessBlock:(void(^)(NSData* data))success
                               FailBlock:(void(^)(NSError* error))fail;
    
    
    //还没有调用
    -(void)deleteStatisticalDataWithSuccessBlock:(void(^)(NSData* data))success
                                       FailBlock:(void(^)(NSError* error))fail;
    
    -(void)fetchProtocolVersionSuccessBlock:(void(^)(NSData* data))success
                                  FailBlock:(void(^)(NSError* error))fail;
    
    -(void)stopFetchRealTimeData;
    -(void)resumeFetchRealTimeData;
    -(void)suspendFetchRealTimeData;
    
    @end

     MattressBLEManagerApi继承了 CLBLEBaseApi<CLBLEDataSource>。通过实现 CLBLEDataSource里的代理提供了广播名,服务ID,特征ID等数据。

    这个类里面我们就开始了与具体业务逻辑相关的操作了。下面看看他的实现文件。

    -(void)fetchHistoryDataWithSuccessBlock:(void(^)(NSData* data))success
                                  FailBlock:(void(^)(NSError* error))fail{
        
        NSLog(@"fetchHistoryDataWithSuccessBlock0");
        NSLog(@"CLBLEStateIdle == %d",CLBLEStateIdle);
        NSLog(@"self.state == %d",self.state);
        
        //不相等说明蓝牙繁忙
        if ( self.state != CLBLEStateIdle) {
            NSError* error=[NSError errorWithDomain:kCLBLEManagerErrorDomain code:kBLEBusyErrorCode userInfo:@{@"message":kBLEBusyErrorCodeErrorMessage}];;
            fail(error);
            return ;
        }
        __weak MattressBLEManagerApi* weakSelf=self;
        if (self.connectedPeripheral.cbPeripheral.state==CBPeripheralStateConnected) {
            sendRealTimeData =[BLEMattressProtocol getRequestStatisticalPacketData:self.uniqueID];
            [self sendBLEDataWithDataPacketProtocol:sendRealTimeData
                                            Success:^(NSData *data) {
                                                /*历史数据比较简单,获取历史数据,上传到服务器,然后通知设备,清除数据。
                                                 然后告诉外面结果就说成功了,
                                                 业务接口自己去服务器拉取数据,整个上传数据流程完毕。
                                                 */
                                                success(data);
                                                NSLog(@"data is %@",data);
                                            } fail:^(NSError *error) {
                                                NSLog(@"error is %@",error);
                                                fail(error);
                                            }];
        }
        else{
            NSLog(@"fetchHistoryDataWithSuccessBlock11");
            self.currentPeripheral=nil;
            [[CLBLEManager sharedInstance] conntectPeripheralWithBLEDataSource:self
                                                               withResultBlock:^(LGPeripheral *peripheral, NSError *error) {
                                                                   NSLog(@"fetchHistoryDataWithSuccessBlock1");
                           if (error) {
                               fail(error);
                           }
                           else{
                               weakSelf.currentPeripheral=peripheral;
                               sendRealTimeData =[BLEMattressProtocol getRequestStatisticalPacketData:self.uniqueID];
                               [weakSelf sendBLEDataWithDataPacketProtocol:sendRealTimeData
                                                               Success:^(NSData *data) {
                                                                   /*历史数据比较简单,获取历史数据,上传到服务器,然后通知设备,清除数据。
                                                                    然后告诉外面结果就说成功了,
                                                                    业务接口自己去服务器拉取数据,整个上传数据流程完毕。
                                                                    */
                                                                   success(data);
                                                                   NSLog(@"data is %@",data);
                                                               } fail:^(NSError *error) {
                                                                   NSLog(@"error is %@",error);
                                                                   fail(error);
                                                               }];
                           }
            }];
        }
    
    }

    这一段代码是获取历史数据的接口。

    除开上面那些,我们还需要对蓝牙的扫描,连接,探索,读写数据,断开等操作进行封装。所以我们创建了CLBLEManager类。他来管理这些操作。

    头文件大概如下:

    @protocol CLBLEManagerDelegate <NSObject>
    
    -(void)scanAllPeripherals:(NSArray *)allLGPeripherals;
    
    @end
    
    @interface CLBLEManager : NSObject
    
    @property (strong, nonatomic) LGPeripheral  *currentLGPeripheral;
    @property (strong, nonatomic) CBCentralManager *manager;
    +(CLBLEManager *)sharedInstance;
    
    
    //初始化蓝牙并设置读取数据的回调,自动扫描,如果扫描设备名字broadName为空,则扫描所有设备并返回列表,如果broadName不为空则返回连接上的蓝牙设备
    -(void)scanbleWithObject:(id<CLBLEDataSource>)child
             withScanTimeOut:(NSInteger)timeOut;
         //scanPeripheralBlock:(void (^)(NSArray *peripherals,NSError *error))scanPeripheralBlock;
    //连接蓝牙
    //-(void)conntectPeripheral:(LGPeripheral *)peripheral withResultBlock:(void(^)(NSError *error))connectResultBlock;
    
    -(void)conntectPeripheralWithBLEDataSource:(id<CLBLEDataSource>)child
                               withResultBlock:(void(^)(LGPeripheral* peripheral,NSError *error))connectResultBlock;
    //OAD空中升级的时候必须先扫描后连接
    -(void)oadConntectPeripheralWithBLEDataSource:(id<CLBLEDataSource>)child
                               withResultBlock:(void(^)(LGPeripheral* peripheral,NSError *error))connectResultBlock;
    
    //发送数据
    -(void)sendData:(NSData *)data peripheral:(LGPeripheral *)peripheral;
    //设置Notify
    -(void)setNotify:(LGPeripheral *)peripheral WithCBUUID:(CBUUID *)sCBUUID cCBUUID:(CBUUID *)cCBUUID withResultBlock:(void(^)(NSError *error))resultBlock withResultBlock:(void(^)(NSData *data,NSError *error))readDataBlock;
    //断开蓝牙
    -(void)disconntectPeripheral:(LGPeripheral *)peripheral withResultBlock:(void(^)(NSError *error))aCallback;

    实现文件大体如下:

    -(void)scanbleWithObject:(id<CLBLEDataSource>)child
             withScanTimeOut:(NSInteger)timeOut
    {
        
        self.broadName=nil;
        if ([child respondsToSelector:@selector(broadName)]) {
            self.broadName=[child broadName];
        }
        if ([child connectedPeripheral].name) {
            self.broadName=child.connectedPeripheral.name;
        }
        self.scanServiceArray=child.scanServiceArray;
        self.readServiceUUID=child.readSeriveID;
        self.readCharacteristic=child.readCharacteristicID;
        self.writeServiceUUID=child.writeSeriveID;
        self.writeCharacteristic=child.writeCharacteristicID;
        if(self.readServiceUUID.length==0||self.readCharacteristic.length==0||self.writeServiceUUID.length==0||self.writeCharacteristic.length==0)
        {
            [self.multicasetDelegate scanAllPeripherals:nil];
            return;
        }
        __weak CLBLEManager *weakself=self;
        if([LGCentralManager sharedInstance].centralReady)
        {
            [weakself scanWithTimeout:timeOut scanFinishBlock:^(NSArray *peripherals)
            {
                [weakself.multicasetDelegate scanAllPeripherals:peripherals];
            }];
            
        }
        self.hasConnectedPeripherals=[[NSMutableArray alloc]init];
        self.retrievePeripheralsWithIdentifiers=[[NSMutableArray alloc]init];
        self.scanPeripheralsCallback=nil;
        // Custom initialization
        
        [LGCentralManager sharedInstance].updateStateBlock =^(CBCentralManagerState state)
        {
            if (state == CBCentralManagerStatePoweredOn)
            {
                if (![LGCentralManager sharedInstance].isScanning)
                {
                    [weakself scanWithTimeout:timeOut scanFinishBlock:^(NSArray *peripherals)
                    {
                        
                        [weakself.multicasetDelegate scanAllPeripherals:peripherals];
                    }];
                }
            }
        };
        
    }

    好了,到这里就结束了。以上就是我们在项目中对蓝牙业务进行封装的一个大致思路。

  • 相关阅读:
    要使用springtest来进行单元测试 否则将无法注入 applicationContext.xml
    关键词的重要性
    发卡可以以交叉方式佩戴来增强可爱性
    红毛类型
    oracle学习总结4
    对springMVC的简单理解
    理解RESTful架构
    项目移植过程中报:“Project facet Java version 1.7 is not supported.” 错误
    svn服务器的搭建
    oracle学习总结3
  • 原文地址:https://www.cnblogs.com/yulang314/p/5088752.html
Copyright © 2020-2023  润新知