所以我正在使用两个应用程序 . 一个充当中心,另一个是外围设备 . 可能有多个设备充当外围设备 . 当Central启动时,它开始扫描正在运行我称之为 UUIDService 的服务的外围设备 . 此服务有两个特征: vendorUUID (读取)和 totalAmount (写入) .

当外围设备发布时,它开始宣传 UUIDService ,其中 -[UIDevice identifierForVendor] 字符串为 vedorUUID 的值, niltotalAmount.

在Central上,我有一个名为 BluetoothManager 的单例,它包含一个名为 connectedUsers 的可变数组,用于跟踪连接到中心的外围设备 . 这是一个 BTUser 对象的数组,它有两个属性:uuid(NSString)和periph(CBPeripheral) .

当Central发现外围设备时,它会创建用户对象并填写对 periph 的引用:

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{    
    NSLog(@"Discovered periph advertising UUID Service");
    BTUser* user = [[BTUser alloc] init];
    user.periph = peripheral;

    [_centralManager connectPeripheral:user.periph options:nil];

    [_connectedUsers addObject:user];

    NSLog(@"User periph: %@", user.periph.identifier);

}

这段代码有效 . _connectedUsers 现在包含一个带有 periphBTUser . 然后连接:

-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{

    NSLog(@"Connected periph: %@", peripheral.name);

    BTUser* thisUser;
    for (BTUser* user in _connectedUsers)
    {
        if ([user.periph.identifier isEqual: peripheral.identifier])
        {
            thisUser = user;
            break;
        }
    }

    thisUser.periph.delegate = self;
    [thisUser.periph discoverServices:@[_uuidServiceUUID]];

}

我运行的是当我去使用外设的引用写入 totalAmount 时 .

-(void)initializePaymentWithUser:(BTUser*)user forAmount:(CGFloat)amount
{
    _isListeningForUsers = NO;

    [self stopScanningForUsers];
    NSLog(@"disconnecting from all other users");
    for (BTUser* u in _connectedUsers)
    {
        if (![u isEqual:user])
        {
            [u disconnectFromCentral:_centralManager];
        }
    }

    CBService* uuidService = user.periph.services[0];
    for (CBCharacteristic* cha in uuidService.characteristics)
    {
        if ([cha.UUID isEqual:_uuidServiceTotalAmountUUID])
        {
            NSLog(@"Writing total amount %.2f", amount);
            NSData* data = [[NSString stringWithFormat:@"%.2f", amount] dataUsingEncoding:NSUTF8StringEncoding];
            [user.periph writeValue:data
                  forCharacteristic:cha
                               type:CBCharacteristicWriteWithResponse];

            break;
        }
    }

}

它使它成为写入值的块,并且 user.periph 仍然具有与最初连接时相同的 -[CBPeripheral identifier] . 但是我收到了错误:

CoreBluetooth[WARNING] <CBPeripheral: 0x14ed28c0 identifier = B4CB35CC-2C78-7543-B083-E0B373EF66D0, Name = "iPhone", state = connected> is not a valid peripheral

外围设备从不调用 -peripheral:didWriteValueForCharacteristic:error .

为了完成这个问题,这是来自外围设备的代码块,负责宣传 UUIDService

-(void)advertiseVendorUUID:(NSString*)uuid
     paymentInitiatedBlock:(DOBluetoothPeripheralBlock)completion
{
    _uuidService = [[CBMutableService alloc] initWithType: _uuidServiceUUID
                                                  primary:YES];
    NSLog(@"Adding vendor id to characteristic: %@", uuid);
    NSData* vendorData = [uuid dataUsingEncoding:NSUTF8StringEncoding];
    _uuidServiceVendorUUIDChar = [[CBMutableCharacteristic alloc] initWithType:_uuidServiceVendorUUIDUUID
                                                                    properties:CBCharacteristicPropertyRead
                                                                         value:vendorData
                                                                   permissions:CBAttributePermissionsReadable];
    _uuidServiceTotalAmountChar = [[CBMutableCharacteristic alloc] initWithType:_uuidServiceTotalAmountUUID
                                                                     properties:CBCharacteristicPropertyWrite
                                                                          value:nil
                                                                    permissions:CBAttributePermissionsWriteable];

    _uuidService.characteristics = @[_uuidServiceVendorUUIDChar, _uuidServiceTotalAmountChar];

    [_peripheralManager addService:_uuidService];
    [_peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey: @[_uuidService.UUID],
                                           CBAdvertisementDataLocalNameKey: @"UUID"}];
}