SoFunction
Updated on 2025-04-04

iOS Bluetooth development Bluetooth connection and data reading and writing

Before doing Bluetooth development, it is best to understand some concepts:
Services: There must be one service for Bluetooth peripherals to broadcast externally, and there may be multiple services. The service contains some features, and the service can be understood as a window of a module;
Characteristic: There are many features that exist under a service. Under a service, the features can be understood as windows for specific implementation of functions. Generally, the features will have value, that is, feature values, and the features are the smallest unit for interaction with the outside world;
UUID: It can be understood as a unique identifier on Bluetooth (this means certainly not in hardware, but this understanding is easy for us to develop). In order to distinguish different services and features, or to name services and features, we use UUID to represent services and features.

Bluetooth connection can be roughly divided into the following steps

1. Create a Central Manager instance for Bluetooth management
2. Search for peripheral devices
3. Connect to peripheral devices
4. Obtain peripheral equipment services
5. Characteristics of obtaining services
6. Read data from peripheral devices
7. Send data to peripheral devices
Others: Reminder

First, we import the system's BLE framework
#import <CoreBluetooth/>

2 agreements must be followed
<CBCentralManagerDelegate, CBPeripheralDelegate>

/** Center Manager */
@property (nonatomic, strong) CBCentralManager *cMgr;

/** Peripherals connected to */
@property (nonatomic, strong) CBPeripheral *peripheral;

1. Create a Central Manager instance for Bluetooth management

-(CBCentralManager *)cmgr
{
  if (!_cmgr) {
    _cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
  }
  return _cMgr;
}
 
//This proxy method will be triggered as long as the center manager initializes it. To determine the Bluetooth status of the mobile phone- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
  switch () {
    case 0:
      NSLog(@"CBCentralManagerStateUnknown");
      break;
    case 1:
      NSLog(@"CBCentralManagerStateResetting");
      break;
    case 2:
      NSLog(@"CBCentralManagerStateUnsupported");//No Bluetooth support      break;
    case 3:
      NSLog(@"CBCentralManagerStateUnauthorized");
      break;
    case 4:
    {
      NSLog(@"CBCentralManagerStatePoweredOff");//Bluetooth not turned on    }
      break;
    case 5:
    {
      NSLog(@"CBCentralManagerStatePoweredOn");//Bluetooth is turned on       // Do some operations after the center manager is successfully enabled      // Search for peripherals      [ scanForPeripheralsWithServices:nil // Filter peripherals through certain services                       options:nil]; // dict, condition      // After the search is successful, the proxy method we found the peripheral will be called      // - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisingData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //Find peripherals    }
      break;
    default:
      break;
  }
}

2. Search for peripheral devices (I used a bracelet around me to give an example)

// Methods called after discovering peripherals- (void)centralManager:(CBCentralManager *)central // Center Manager didDiscoverPeripheral:(CBPeripheral *)peripheral // Peripherals   advertisementData:(NSDictionary *)advertisementData // Peripheral data         RSSI:(NSNumber *)RSSI // The intensity of Bluetooth signal sent by the peripheral{
  //NSLog(@"%s, line = %d, cetral = %@,peripheral = %@, advertisementData = %@, RSSI = %@", __FUNCTION__, __LINE__, central, peripheral, advertisementData, RSSI);
  
  /*
    peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341, Name = "OBand-75", state = disconnected>, advertisementData = {
    kCBAdvDataChannel = 38;
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = OBand;
    kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
    kCBAdvDataServiceUUIDs = (
    FEE7
    );
    kCBAdvDataTxPowerLevel = 0;
    }, RSSI = -55
    According to the print results, we can get the sports bracelet with its name called OBand-75
   
    */
  
  // Need to filter the connected peripherals  // 1. Signal strength (only connected to 40 or above, and more than 80 or above)  // 2. Pass the device name (the device string prefix is ​​OBand)  // At this time, our filtering rule is: have OBand prefix and the signal strength is greater than 35  // By printing, we know that RSSI is usually made with -  
  if ([ hasPrefix:@"OBand"]) {
    // Here we do some processing on our advertisingData (broadcast data carried by peripherals)    
    // Usually by filtering, we will get some peripherals and then store the peripherals into our variable array,    // Since there is only 1 sports bracelet nearby, we will first process it by 1 peripheral.    
    // Mark our peripherals and let their life cycle = vc     = peripheral;
    // After discovering it, connect    [ connectPeripheral: options:nil];
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
  }
}

3. Connect to peripheral devices

// The center manager successfully connected to the peripheral- (void)centralManager:(CBCentralManager *)central // Center Manager didConnectPeripheral:(CBPeripheral *)peripheral // Peripherals{
  NSLog(@"%s, line = %d, %@=Connection successfully", __FUNCTION__, __LINE__, );
  // After the connection is successful, you can discover services and features  
  // Set up the peripheral proxy   = self;
  
  // Peripheral discovery service, nil means no filtering  // The proxy method of the peripheral will be triggered here - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error  [ discoverServices:nil];
}
// Peripheral connection failed- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
  NSLog(@"%s, line = %d, %@=Connection failed", __FUNCTION__, __LINE__, );
}
 
// Lost connection- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
  NSLog(@"%s, line = %d, %@=Disconnect", __FUNCTION__, __LINE__, );
}

4. Obtain services for peripheral devices & 5. Obtain characteristics of services

// The proxy method called when discovering features in peripheral services (this is a relatively important method. You can find the features you need by knowing the UUID in advance, subscribe to the features, or write data to the features here)- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
  NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
  
  for (CBCharacteristic *cha in ) {
    //NSLog(@"%s, line = %d, char = %@", __FUNCTION__, __LINE__, cha);
    
  }
}

5. Read data from peripheral devices

// It will be called when updating the value of the feature (all data transmitted from Bluetooth must go through this callback. Simply put, this method is the only way for you to get the data) You can judge whether it is- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
  NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
  if (characteristic == @"The UUID of the feature you want or the feature you have found") {
  //It's the data you want  }
}

6. Send data to peripheral devices (that is, write data to Bluetooth)

You can put this method in the button's response, or write it when you find the feature, depending on how you use it for your business needs.

[ writeValue:_batteryData forCharacteristic: type:CBCharacteristicWriteWithResponse];
//The first parameter is the connected Bluetooth device ;The second parameter is which feature to write to; The third parameter is whether the record is successfully written through this response
// It should be noted whether the attributes of the feature support writing data- (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{
  /*
    typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
    CBCharacteristicPropertyBroadcast = 0x01,
    CBCharacteristicPropertyRead = 0x02,
    CBCharacteristicPropertyWriteWithoutResponse = 0x04,
    CBCharacteristicPropertyWrite = 0x08,
    CBCharacteristicPropertyNotify = 0x10,
    CBCharacteristicPropertyIndicate = 0x20,
    CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
    CBCharacteristicPropertyExtendedProperties = 0x80,
    CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200
    };
   
    Print out the permissions () of the feature, you can see that there are many types. This is an NS_OPTIONS enumeration, which can be multiple values.
    Common ones read, write, noitfy, indicator. I know that these are basically enough. The first two are read and write permissions, and the last two are notifications. The two are different notification methods.
    */
//  NSLog(@"%s, line = %d,  = %d", __FUNCTION__, __LINE__, );
  // At this time, since the enum attribute is NS_OPTIONS, an enum may correspond to multiple types, so it is impossible to use =, but should use include &}

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.