At the beginning

  • This is a sub-chapter. For the whole article, see the Learning Diary of Zero-based iOS development

Bluetooth Bluetooth

The actual use

  • Communicate with bluetooth devices
  • Development of iot devices
  • Recently I happened to be working on the Bluetooth project, so I learned the iOS framework by the way. The framework in the project uses BabyBluetooth

Key words Matting

  • The center device is the device used to scan the surrounding Bluetooth hardware, such as the bluetooth of a mobile phone to scan and connect to the smart bracelet, and then the mobile phone is the center device
  • Peripherals, devices being scanned, such as the smart bracelet above
  • Broadcast, the peripheral constantly sends out bluetooth signals that can be scanned by the central device
  • Services, services, peripherals broadcast and run a service, which can be understood as a function module, and the central device can read the service. Peripherals can have multiple services
  • A feature is a unit of a service. A service can have multiple features. A feature has a value
  • UUID: Identifies different services and features. It can be regarded as an ID card for services and features. UUID is used to select required services and features.
  • Subscribe, similar to listening

The info. The plist configuration

<key>NSBluetoothAlwaysUsageDescription</key>
<string></string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>YES</string>
Copy the code

Peripheral information

  • I’ll write this first, because there’s a lot of code
  • peripherals
<CBPeripheral: 0x281D34280, // Object value identifier = e6F8e0AB-6B1E-200F-056C-05750b1A0D7A, name = CH9140BLE2U, state = connecting>Copy the code
  • Broadcast data
kCBAdvDataIsConnectable = 1; kCBAdvDataLocalName = CH9140BLE2U; / / peripherals name kCBAdvDataManufacturerData = {length = 8, bytes = 0 x0cc6209000000000}; //MAC value kCBAdvDataTimestamp = "644931976.188664"; kCBAdvDataTxPowerLevel = 0;Copy the code
  • RSSI signal strength, connection quality
- 56Copy the code
  • service
<CBService: 0x2838409c0, isPrimary = YES, UUID = FFF0>
Copy the code
  • Characteristic
// first characteristic value <CBCharacteristic: 0x28118C240, UUID = FFF1, properties = 0x12, value = (null), notifying = NO> 0x28118C2A0, UUID = FFF2, properties = 0xC, Value = (null), notifying = NO> 0x28118c300, UUID = FFF3, properties = 0x1E, value = (null), notifying = NO>Copy the code

Configuring central devices

  • The purpose is to allow the device to scan for bluetooth devices outside
  • For central equipment, mission critical isScan the bluetooth,Connect the bluetooth,Gets bluetooth write and listen ports, and this port refers to the eigenvalue, generally need to be embedded to specify
  • And the whole process goes down in this order,Scan the bluetooth->Connect the bluetooth->Scanning bluetooth service->Scan bluetooth eigenvalues->Address the need for eigenvalues->Subscribe or write to Bluetooth, plus some error handling, data processing, and Bluetooth information filtering operations, you can connect to Bluetooth
  • Overall operation train of thought is relatively simple, smooth a feeling
  • The header file
#import <CoreBluetooth/CoreBluetooth.h>
Copy the code

The initial

#define Service_write_uid @"FFF0" #define CHARACTERISTIC_NOTIFY_UUID @"FFF1 #define Characteris_read_uuid @"FFF3" // The central device reads the data prepared by bluetoothCopy the code
@interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate> @property (nonatomic, strong) CBCentralManager *centralManager; @property (nonatomic, strong) CBPeripheral *peripheral; // Write port @property (nonatomic, strong) CBCharacteristic *writeCharacteristic; // Read port @property (nonatomic, strong) CBCharacteristic *notifyCharacteristic; @endCopy the code
- (void)viewDidLoad { [super viewDidLoad]; Self. CentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; UIButton *postBtn = [UIButton buttonWithType:UIButtonTypeContactAdd]; postBtn.frame = CGRectMake(100, 100, 100, 100); [postBtn addTarget:self action:@selector(didClickPost) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:postBtn]; / / active reading UIButton * readBtn = [UIButton buttonWithType: UIButtonTypeContactAdd]; readBtn.frame = CGRectMake(200, 200, 100, 100); readBtn.tintColor = [UIColor orangeColor]; [readBtn addTarget:self action:@selector(didClickGet) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:readBtn]; }Copy the code

Scanning state

- (void) centralManagerDidUpdateState: (central CBCentralManager *) {/ / bluetooth is available, Start scanning peripherals if (central.state == CBManagerStatePoweredOn) {NSLog(@" Bluetooth available - %@", central); / / scan ID, indiscriminate scanning [central scanForPeripheralsWithServices: @ [] options: nil]; / / targeted scan / / [central scanForPeripheralsWithServices: @ [[CBUUID UUIDWithString: SERVICE_UUID]] options: nil]; }}Copy the code

Find a peripheral

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral AdvertisementData :(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {// strong reference sel.peripheral = peripheral; / / filter equipment / / if ([peripheral. Name hasPrefix: @ "XX"]) {/ / [central connectPeripheral: peripheral options: nil]; / /} / / connect to write their own peripherals / / if ([peripheral. Name isEqualToString: @ "iPhone"]) {/ / [central connectPeripheral: peripheral options:nil]; // NSLog(@"%@", peripheral); // NSLog(@"%@", peripheral.name); // NSLog(@"%@", advertisementData); // NSLog(@"%@", RSSI); / / / /} for MAC value, and determine whether need NSData * data = advertisementData [@ "kCBAdvDataManufacturerData"]; If ([data isEqualToData:[self convertHexStrToData:@" 0CC6209000000000 "]]) { Can be written as tableView click method [central connectPeripheral: peripheral options: nil]; NSLog(@"%@", peripheral); NSLog(@"%@", advertisementData); NSLog(@"%@", RSSI); }}Copy the code

The connection is successful

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { [central stopScan];  // Set peripheral. Delegate = self; // Peripheral discoverServices:@[]]; // [Peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]]; NSLog(@"connecct success"); }Copy the code

Callback for connection failure

-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {NSLog(@" connection failed "); }Copy the code

disconnect

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {NSLog(@" disconnect "); / / disconnect connection can be set to [central connectPeripheral: peripheral options: nil]; }Copy the code

The discovery service

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { for (CBService *service in peripheral.services) { NSLog(@"service : %@", service); } CBService *service = peripheral.services.lastObject; [] peripheral discoverCharacteristics:@[] forService:service]; / / looking for specified features [CBUUID UUIDWithString: CHARACTERISTIC_NOFITY_UUID] / [peripheral discoverCharacteristics: @ [[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service]; }Copy the code

Found characteristics

  • Extract the corresponding eigenvalues
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError For (CBCharacteristic *characteristic in service.characteristics) {NSLog(@" all characteristics: %@", characteristic); // Get the UUID from the peripheral developer for different features that do different things, such as reading data, Write data have the characteristics of the if ([characteristic. The UUID. UUIDString isEqualToString: CHARACTERISTIC_WRITE_UUID]) {self. WriteCharacteristic = characteristic; } else if([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_NOTIFY_UUID]) { self.notifyCharacteristic = characteristic; / / subscription notice - to monitor the port [peripheral setNotifyValue: YES forCharacteristic: self. NotifyCharacteristic]; } else if([characteristic.UUID.UUIDString isEqualToString:CHARACTERISTIC_READ_UUID]) { self.readCharacteristic = characteristic; }}}Copy the code

Subscription status changes

  • Check whether the listening is successful.
-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {if (error) {NSLog(@" subscribe failed "); NSLog(@"%@",error); {} the if (characteristic isNotifying) NSLog (@ "subscribe to success"); } else {NSLog(@" unsubscribe "); }}Copy the code

Data callback received

  • Processing of received data
  • Read, listen, all go through this callback
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic Error :(NSError *)error {NSData *data = characteristic. Value; NSLog(@"%@", data); NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); }Copy the code

Write data callback

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic Error :(nullable NSError *)error {NSLog(@" write successfully "); }Copy the code

Sends messages to peripherals

- (void)didClickPost {
    NSString *str = @"i am centralManager";
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    [self.peripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
    
}
Copy the code

Actively read data from peripherals

- (void)didClickGet {
    [self.peripheral readValueForCharacteristic:self.readCharacteristic];
}
Copy the code

To NSData in hexadecimal

  • Process the MAC value of the device
- (NSData *)convertHexStrToData:(NSString *)str { if (! str || [str length] == 0) { return nil; } NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:20]; NSRange range; if ([str length] % 2 == 0) { range = NSMakeRange(0, 2); } else { range = NSMakeRange(0, 1); } for (NSInteger i = range.location; i < [str length]; i += 2) { unsigned int anInt; NSString *hexCharStr = [str substringWithRange:range]; NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr]; [scanner scanHexInt:&anInt]; NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1]; [hexData appendData:entity]; range.location += range.length; range.length = 2; } return hexData; }Copy the code

Configuring a Bluetooth Device

  • To enable the central device to scan bluetooth devices
  • The idea revolves around what does a Bluetooth device need, needservice,The eigenvalue,Broadcast informationWait, then determine the port, follow the steps to write down
  • When writing, the eigenvalue should be corresponding to the central device, and the eigenvalue should be written from an Angle. For example, the writing of the central device is also written in Bluetooth

The initial configuration

#define SERVICE_UUID @"FFF0" #define CHARACTERISTIC_NOTIFY_UUID @"FFF1" #define CHARACTERISTIC_WRITE_UUID @"FFF2" #define CHARACTERISTIC_READ_UUID @"FFF3" @interface ViewController () <CBPeripheralManagerDelegate> @property (nonatomic, strong) CBPeripheralManager *peripheralManager; @property (nonatomic, strong) CBMutableCharacteristic *notifyCharacteristic; @property (nonatomic, strong) CBMutableCharacteristic *writeCharacteristic; // Bluetooth prepares the data for the central device to read @property (nonatomic, strong) CBMutableCharacteristic *readCharacteristic; @endCopy the code
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
    UIButton *postBtn = [UIButton buttonWithType:UIButtonTypeContactAdd];
    postBtn.frame = CGRectMake(100, 100, 100, 100);
    [postBtn addTarget:self action:@selector(didClickPost) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:postBtn];
}
Copy the code

Update Bluetooth Status

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { if (peripheral.state == CBManagerStatePoweredOn) {/ / create the service and features [self setupServiceAndCharacteristics]; / / according to the service of UUID began broadcasting / / [self. PeripheralManager startAdvertising: @ {CBAdvertisementDataServiceUUIDsKey: @[[CBUUID UUIDWithString:SERVICE_UUID]]}]; }}Copy the code

Set the service and characteristic values

- (void) setupServiceAndCharacteristics {/ / create the service CBUUID * serviceID = [CBUUID UUIDWithString: SERVICE_UUID]; CBMutableService *service = [[CBMutableService alloc] initWithType:serviceID primary:YES]; / / create the service characteristics of CBUUID * characteristicNotifyID = [CBUUID UUIDWithString: CHARACTERISTIC_NOTIFY_UUID]; CBUUID *characteristicWriteID = [CBUUID UUIDWithString:CHARACTERISTIC_WRITE_UUID]; CBUUID *characteristicReadID = [CBUUID UUIDWithString:CHARACTERISTIC_READ_UUID]; //properties features included in the service, CBMutableCharacteristic *notifyCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicNotifyID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable]; CBMutableCharacteristic *writeCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicWriteID properties:CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable]; CBMutableCharacteristic *readCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicReadID properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable]; Characteristics = @[notifyCharacteristic, writeCharacteristic, readCharacteristic]; // Add the service to the management [self.peripheralManager addService:service]; / / manual to send data center equipment self notifyCharacteristic = notifyCharacteristic; self.writeCharacteristic = writeCharacteristic; self.readCharacteristic = readCharacteristic; }Copy the code

The callback function after the service is added

  • To broadcast, you can only set the UUID and broadcast name of the service
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error { [self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString: SERVICE_UUID]], CBAdvertisementDataLocalNameKey: @ "treasure to find your"}); }Copy the code

The callback function that sends a broadcast

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error {
    NSLog(@"device is  in advertising.");
}
Copy the code

A callback when a peripheral is read

  • When the central device reads data to bluetooth, the prepared data is sent to the central device
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request { Send content to the central device NSString * STR = @" I am periheral"; request.value = [str dataUsingEncoding:NSUTF8StringEncoding]; / / success response [peripheral respondToRequest: request withResult: CBATTErrorSuccess]; }Copy the code

Callback to write data

  • This means that the central device sends data to Bluetooth by writing eigenvalues
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests CBATTRequest *request = requests. LastObject; / / write data output NSLog (@ "% @", [[nsstrings alloc] initWithData: request. The value encoding: NSUTF8StringEncoding]); }Copy the code

Actively send data to central equipment

  • Send with notif eigenvalues
- (void)didClickPost { NSString *str = @"i am notifyCharacteristic"; bool sendSuccess = [self.peripheralManager updateValue:[str dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.notifyCharacteristic onSubscribedCentrals:nil]; If (sendSuccess) {NSLog(@" data sent successfully "); }else {NSLog(@" failed to send data "); }}Copy the code

Subscribe successful callback – Subscribe analog listener

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
    NSLog(@"%s",__FUNCTION__);
}
Copy the code

Unsubscribe callback

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
    NSLog(@"%s",__FUNCTION__);
}
Copy the code

conclusion

  • This article is relatively partial to use the guide, later there is time, will be the inside of the key function of the meaning of the parameters sorted out