No.04 Xcode(7.x) 蓝牙

#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>

#define RX_SERVICE_UUID     @"FE20"
#define RX_CHAR_UUID        @"FE21"

@interface UITableViewController () <CBCentralManagerDelegate, CBPeripheralDelegate>

@property (nonatomic, strong) NSMutableArray *peripherals; // 外设数组

@property (nonatomic, strong) CBCentralManager *centralManager; // 中心管理者

@property (nonatomic, strong) CBPeripheral *peripheral; // 外设

@property (nonatomic, strong) CBCharacteristic *characteristic; // 特征

@end

@implementation ViewController

- (void)sendMessage {
    
    if (self.peripheral == nil || self.characteristic == nil || self.characteristic.service.peripheral != self.peripheral)
        return;
    
    NSString *string = @"OLWANDA_IL12345678";
    
    NSData *data = [NSData dataWithBytes:string.UTF8String length:string.length];
    
    NSLog(@"Blue Tooth Step 6: 确定了'外设[%@]-服务[%@]-特征[%@]'之后, 向其发送数据", self.characteristic.service.peripheral.name, self.characteristic.service.UUID.UUIDString, self.characteristic.UUID.UUIDString);
    if (self.characteristic.properties & CBCharacteristicPropertyWrite) {
        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
    } else if (self.characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) {
        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
    } else {
        NSLog(@"No write property on characteristic, %ld.", self.characteristic.properties);
    }
}

- (void)openOrShut {
    
    UIButton *button = (UIButton *)self.navigationItem.rightBarButtonItem.customView;
    
    if (button.selected) {
        
        NSLog(@"企图断开");
        button.selected = NO;
        
        [self.centralManager stopScan];
        
        if (self.peripheral)
            [self.centralManager cancelPeripheralConnection:self.peripheral];
        self.peripheral = nil;
        
        [self.tableView reloadData];
    } else {
        NSLog(@"企图扫描");
        button.selected = YES;
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        NSLog(@"Blue Tooth Step 1: 创建中心[%p], 会自动将其设置为开启状态", self.centralManager);
    }
}

- (UIBarButtonItem *)barButtonItemWithNormalTitle:(NSString *)normal andSelectedTitle:(NSString *)select target:(id)target action:(SEL)action {
    UIButton *button = [UIButton new];
    [button setTitle:normal forState:UIControlStateNormal];
    [button setTitle:select forState:UIControlStateSelected];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button setTitleColor:[UIColor brownColor] forState:UIControlStateSelected];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    [button sizeToFit];
    return [[UIBarButtonItem alloc] initWithCustomView:button];
}

#pragma mark override

- (id)init {
    self = [super init];
    if (self) {
        self.peripherals = [NSMutableArray array];
    }
    return self;
}

- (void)loadView {
    [super loadView];
    self.navigationItem.leftBarButtonItem  = [self barButtonItemWithNormalTitle:@"发送" andSelectedTitle:@"发送" target:self action:@selector(sendMessage)];
    self.navigationItem.rightBarButtonItem = [self barButtonItemWithNormalTitle:@"扫描" andSelectedTitle:@"停止" target:self action:@selector(openOrShut)];
}

#pragma mark UITableViewDelegate, UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.peripherals.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    CBPeripheral *peripheral = self.peripherals[indexPath.row];
    
    static NSString *reuseIdentifier = @"cell_id";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if (cell == nil) cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
    cell.textLabel.text = peripheral.name;
    cell.detailTextLabel.text = peripheral.identifier.UUIDString;
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    CBPeripheral *peripheral = self.peripherals[indexPath.row];
    
    peripheral.delegate = self;
    
    NSLog(@"Blue Tooth Step 3: 连接外设[%@]", peripheral.name);
    [self.centralManager connectPeripheral:peripheral options:nil];
    
    self.peripheral = peripheral;
}

#pragma mark CBCentralManagerDelegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    
    NSLog(@"  中心[%p] 状态变化为 %ld", central, central.state);
    
    if (central.state == CBCentralManagerStatePoweredOn) {
        NSLog(@"Blue Tooth Step 2: 中心[%p]变更为开启状态时, 去扫描外设", central);
        [self.centralManager scanForPeripheralsWithServices:nil options:nil];
    }
}

// 扫描外设
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
    
    NSLog(@"  中心[%p] 发现外设[%@, %@, %@]", central, peripheral.identifier.UUIDString, peripheral.name, RSSI);
    
    if ([self.peripherals containsObject:peripheral] == NO) {
        [self.peripherals addObject:peripheral];
        [self.tableView reloadData];
    }
}

// 连接外设成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Blue Tooth Step 4: 连接外设[%@]成功, 去扫描外设所有的服务", peripheral.name);
    [peripheral discoverServices:nil];
}

// 连接外设失败
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"Blue Tooth Step 4: 连接外设[%@]失败, 原因:%@", peripheral.name, error.localizedDescription);
}

#pragma mark CBPeripheralDelegate

// 扫描服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    for (CBService *service in peripheral.services) {
        NSLog(@"  外设[%@] 发现服务[%@]", peripheral.name, service.UUID.UUIDString);
        
        if ([service.UUID.UUIDString isEqualToString:RX_SERVICE_UUID]) {
            NSLog(@"Blue Tooth Step 5: 确定了外设[%@]的服务[%@]后, 去扫描该服务的所有特征", peripheral.name, service.UUID.UUIDString);
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }
}

// 扫描特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        NSString *valueStr = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];

        NSLog(@"  外设[%@] 服务[%@] 发现特征[%@, %@]", peripheral.name, service.UUID.UUIDString, characteristic.UUID.UUIDString, valueStr);
        
        if ([characteristic.UUID.UUIDString isEqualToString:RX_CHAR_UUID]) {
            self.characteristic = characteristic;
        }
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    NSLog(@"发送消息的回调 error = %@", error);
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
    NSLog(@"接收到数据 error = %@", error);
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    
    NSLog(@">>>>>>>");
    
    if (error) {
        NSLog(@"Error updating value for characteristic %@ error: %@", characteristic.UUID, [error localizedDescription]);
    }
    
    NSMutableData *recvData;
    
    [recvData appendData:characteristic.value];
    
    //已收到长度
    if ([recvData length] >= 5) {
        
        unsigned char *buffer = (unsigned char *)[recvData bytes];
        
        int nLen = buffer[3]*256 + buffer[4];
        
        if ([recvData length] == (nLen+3+2+2)) {
            NSLog(@"do something");
        }
    }
}

@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值