bluetooth app not working iphone

841 views Asked by At

I have created an app that allows people to play a game of checkers over bluetooth from on iOS device to another. Each user takes turns being the peripheral and the central.

I have everything working ok except if a player ponders too long (over 20 seconds) the connection is lost. I have read something about the Security Manager Protocol which disconnect after 20 seconds if it doesn't find the stored Long Term Keys that should have been stored. I have read that I must include part of the following code in my code to disable this.

self.cp_charac = [[CBMutableCharacteristic alloc]
                  initWithType:[CBUUID UUIDWithString:CONTROL_POINT_CHARAC]
                  properties:CBCharacteristicPropertyRead | CBCharacteristicPropertyWrite |
                  CBCharacteristicPropertyWriteWithoutResponse | CBCharacteristicPropertyNotify
                  value:nil
                  permissions:CBAttributePermissionsReadEncryptionRequired | CBAttributePermissionsWriteEncryptionRequired ];

How do I either get the Long Term Keys to store them or exactly what part of the above code do I need to use and where do I put it. I can't seem to find anything like this in my code already.

Following is my code. Sorry it is so lengthy but.

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state)
{
    case CBCentralManagerStateUnsupported:
    {
        NSLog(@"State: Unsupported");

    } break;

    case CBCentralManagerStateUnauthorized:
    {
        NSLog(@"State: Unauthorized");
    } break;

    case CBCentralManagerStatePoweredOff:
    {
        NSLog(@"State: Powered Off");
    } break;

    case CBCentralManagerStatePoweredOn:
    {

//chessRecieveUUID is created from username

        [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:chessRecieveUUID]]
                                                    options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
    } break;

    case CBCentralManagerStateUnknown:
    {
        NSLog(@"State: Unknown");
    } break;

    default:
    {
    }


}}

 -(void) alertView:(UIAlertView *)alertView didDismissWithButtonIndex:    (NSInteger)buttonIndex{

if (AlertView) {
    if (buttonIndex == 0) {

        [[UIApplication sharedApplication] cancelAllLocalNotifications];
    }
}
}



-(IBAction)send:(id)sender{
    [self.centralManager stopScan];
    self.scan.hidden = NO;
    self.advertise.hidden = YES;
    self.message2.text = @".";
    [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:chessSendUUID]] }];  NSLog(@"advertising");
}

-(IBAction)yourTurn:(id)sender{
    message2.text = @".";self.messageString =@"Your Turn";
    [UIView animateWithDuration:2.0 delay:2.0 options:UIViewAnimationOptionCurveEaseIn animations:^{annimation.center = CGPointMake(250,458);} completion:^ (BOOL completed) { self.messageString = @".";
        self.scan.hidden = YES;self.advertise.hidden = YES;[self.peripheralManager stopAdvertising];[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:chessRecieveUUID]]
                                                                                                                                                options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
    }];
}




/** This callback comes whenever a peripheral that is advertising the TRANSFER_SERVICE_UUID is discovered.
 *  We check the RSSI, to make sure it's close enough that we're interested in it, and if it is,
 *  we start the connection process
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    // Reject any where the value is above reasonable range
  if (RSSI.integerValue > -15) {
        return;
    }

    // Reject if the signal strength is too low to be close enough (Close is around -22dB)
   if (RSSI.integerValue < -50) {
        return;
NSLog(@"signal too weak");
    }

    NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);

    // Ok, it's in range - have we already seen it?
    if (self.discoveredPeripheral != peripheral) {

        // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
        self.discoveredPeripheral = peripheral;

        // And connect
        NSLog(@"Connecting to peripheral %@", peripheral);
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}


/** If the connection fails for whatever reason, we need to deal with it.
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"Failed to connect to %@. (%@)", peripheral, [error localizedDescription]);
    [self cleanup];
}


/** We've connected to the peripheral, now we need to discover the services and characteristics to find the 'transfer' characteristic.
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{

    NSLog(@"Peripheral Connected");
    kingString = @"peon";

    // Stop scanning
    [self.centralManager stopScan];
    NSLog(@"Scanning stopped");

    // Clear the data that we may already have
    [self.data setLength:0];


    // Make sure we get the discovery callbacks
    peripheral.delegate = self;

    // Search only for services that match our UUID
    [peripheral discoverServices:@[[CBUUID UUIDWithString:chessRecieveUUID/*@"5D768171-6706-4F83-8EC0-01A313176755"*/]]];
}


/** The Transfer Service was discovered
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    if (error) {
        NSLog(@"Error discovering services: %@", [error localizedDescription]);
        [self cleanup];
        return;
    }

    // Discover the characteristic we want...

    // Loop through the newly filled peripheral.services array, just in case there's more than one.
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}


/** The Transfer characteristic was discovered.
 *  Once this has been found, we want to subscribe to it, which lets the peripheral know we want the data it contains
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    // Deal with errors (if any)
    if (error) {
        NSLog(@"Error discovering characteristics: %@", [error localizedDescription]);
        [self cleanup];
        return;
    }



    if([service.UUID isEqual:[CBUUID UUIDWithString:chessRecieveUUID/*@"5D768171-6706-4F83-8EC0-01A313176755"*/]]) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            NSLog(@"discovered characteristic2 %@", characteristic.UUID);
            if([characteristic.UUID isEqual:[CBUUID UUIDWithString: @"C63CBCC0-6DE3-48D5-BB59-2BEFB9F3AE01"]]) {
                NSLog(@"Found Notify Characteristic32 %@", characteristic);
                self.characteristic2 = characteristic;
                [self.discoveredPeripheral setNotifyValue:YES forCharacteristic:characteristic2];
                /*[self.discoveredPeripheral readValueForCharacteristic:characteristic3];*/
                NSLog(@"value2:%@",characteristic2.value);

            }



            // Once this is complete, we just need to wait for the data to come in.
        }}}




/** This callback lets us know more data has arrived via notification on the characteristic
 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        NSLog(@"Error discovering characteristics: %@", [error localizedDescription]);
        return;
    }

    [self.data appendData:characteristic2.value];
    [self.textview2 setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];
    NSString *stringFromData = [[NSString alloc] initWithData:characteristic2.value encoding:NSUTF8StringEncoding];



    // Have we got everything we need?
    if ([stringFromData isEqualToString:textview2.text]) {



        // We have, so show the data,
        self.textview2.text = @"";





        // Cancel our subscription to the characteristic
        [peripheral setNotifyValue:NO forCharacteristic:characteristic2];

        // and disconnect from the peripehral
        [self.centralManager cancelPeripheralConnection:peripheral];
    }


    NSArray *coorArray = [stringFromData componentsSeparatedByString:@","];
    firstString = [coorArray objectAtIndex:0];
    secondString = [coorArray objectAtIndex:1];
    thirdString = [coorArray objectAtIndex:2];
    FourthString = [coorArray objectAtIndex:3];
    FifthString = [coorArray objectAtIndex:4];
    firstString2 = [coorArray objectAtIndex:5];
    secondString2 = [coorArray objectAtIndex:6];
    NSLog(@"firststring:%@",firstString);
    NSLog(@"secondString;%@",secondString);
    NSLog(@"FourthString;%@",FourthString);
    NSLog(@"firstString2;%@",firstString2);
    NSLog(@"secondString2;%@",secondString2);
    x = firstString.intValue;
    message2.text = secondString2;
    y = secondString.intValue;
    self.textview4.text = thirdString;
    NSLog(@"x:%d",x);
    NSLog(@"y:%d",y);

    if ([message2.text isEqualToString:@"Your Turn"]) {
        self.advertise.alpha = 0.0;
        self.advertise.hidden = NO;
        [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{annimation.center = CGPointMake(61,458);self.advertise.alpha = 1.0;} completion:^ (BOOL completed) {}       ];




    }

}


/** The peripheral letting us know whether our subscribe/unsubscribe happened or not
 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        NSLog(@"Error changing notification state: %@", error.localizedDescription);
    }

    // Exit if it's not the transfer characteristic
    if (![characteristic2.UUID isEqual:[CBUUID UUIDWithString: @"C63CBCC0-6DE3-48D5-BB59-2BEFB9F3AE01"]]) {
        return;
    }
    if (![characteristic3.UUID isEqual:[CBUUID UUIDWithString:@"7445914E-E747-4E4B-9D6E-45750043F8FA"]]) {
        return;
    }

    // Notification has started
    if (characteristic2.isNotifying) {
        NSLog(@"Notification began on %@", characteristic3);
    }
    else {
        // so disconnect from the peripheral
        NSLog(@"Notification stopped on %@.  Disconnecting", characteristic2);
        [self.centralManager cancelPeripheralConnection:peripheral];
    }
}


/** Once the disconnection happens, we need to clean up our local copy of the peripheral
 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"Peripheral Disconnected");
    self.discoveredPeripheral = nil;

    // We're disconnected, so start scanning again
    [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:chessRecieveUUID/*@"61F3E180-D863-479F-96FF-7817BB0CD674"*/]]
                                                options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}


/** Call this when things either go wrong, or you're done with the connection.
 *  This cancels any subscriptions if there are any, or straight disconnects if not.
 *  (didUpdateNotificationStateForCharacteristic will cancel the connection if a subscription is involved)
 */
- (void)cleanup
{
    // Don't do anything if we're not connected
    if (self.discoveredPeripheral.state != CBPeripheralStateConnected) {
        return;
    }
    // See if we are subscribed to a characteristic on the peripheral
    if (self.discoveredPeripheral.services != nil) {
        for (CBService *service in self.discoveredPeripheral.services) {
            if (service.characteristics != nil) {
                for (characteristic2 in service.characteristics) {
                    if ([characteristic2.UUID isEqual:[CBUUID UUIDWithString: @"C63CBCC0-6DE3-48D5-BB59-2BEFB9F3AE01"]]) {
                        if (characteristic2.isNotifying) {
                            // It is notifying, so unsubscribe
                            [self.discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic2];

                            // And we're done.
                            return;
                        }
                    }
                }
            }
        }
    }

    // If we've got this far, we're connected, but we're not subscribed, so we just disconnect
    [self.centralManager cancelPeripheralConnection:self.discoveredPeripheral];
}








/** Required protocol method.  A full app should take care of all the possible states,
 *  but we're just waiting for  to know when the CBPeripheralManager is ready
 */
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
    // Opt out from any other state
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        NSLog(@"self.peripheralManager powered on.");

        // ... so build our service.

        // Start with the CBMutableCharacteristic
        self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"7445914E-E747-4E4B-9D6E-45750043F8FA"]
                                                                         properties:CBCharacteristicPropertyNotify
                                                                              value:nil
                                                                        permissions:CBAttributePermissionsReadable];

        // Then the service
        CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:chessSendUUID/*@"61F3E180-D863-479F-96FF-7817BB0CD674"*/]
                                                                           primary:YES];

        // Add the characteristic to the service
        transferService.characteristics = @[self.transferCharacteristic];

        // And add it to the peripheral manager
        [self.peripheralManager addService:transferService];
        NSLog(@"transfer char:%@",transferService.characteristics);
        NSLog(@"serviceUUID;%@",transferService.UUID);
        [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:chessSendUUID/*@"61F3E180-D863-479F-96FF-7817BB0CD674"*/]] }];
    }

    else if (peripheral.state ==CBPeripheralManagerStatePoweredOff){
        return;
    }
}

- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
{
    NSLog(@"Central subscribed to characteristic");

    xString = [NSString stringWithFormat:@"%d",ax];
    textView.text = xString;
    yString = [NSString stringWithFormat:@"%d",ay];
    textView3.text = yString;

    NSLog(@"ballcenterx2:%f",ball.center.x);
    NSLog(@"ballcentery2:%f",ball.center.y);
    NSLog(@"datatosend2:%@",dataToSend );

    // Get the data
    NSString *stringOne = self.textView.text;
    NSString *stringTwo = [stringOne stringByAppendingString:@","];
    NSString *stringThree = [stringTwo stringByAppendingString:self.textView3.text];
    NSString *stringFour = [stringThree stringByAppendingString:@","];
    NSString *stringFive = [stringFour stringByAppendingString:imageString];
    NSString *stringSix = [stringFive stringByAppendingString:@","];
    NSString *stringSeven = [stringSix stringByAppendingString:xString2];
    NSString *stringEight = [stringSeven stringByAppendingString:@","];
    NSString *stringNine = [stringEight stringByAppendingString:yString2];
    NSString *stringTen = [stringNine stringByAppendingString:@","];
    NSString *stringEleven = [stringTen stringByAppendingString:xString3];
    NSString *stringTwelve = [stringEleven stringByAppendingString:@","];
    NSString *stringThirteen = [stringTwelve stringByAppendingString:messageString];
    self.dataToSend = [stringThirteen dataUsingEncoding:NSUTF8StringEncoding];

    [self.peripheralManager updateValue:dataToSend forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
    NSLog(@"stringOne:%@",stringOne );
    NSLog(@"stringTwo:%@",stringTwo );
    NSLog(@"stringThree:%@",stringThree );
    NSLog(@"stringFour:%@",stringFour );

    NSLog(@"stringThirteen:%@",stringThirteen);
    // Reset the index
    self.sendDataIndex = 0;

    // Start sending
    [self sendData];




}


/** Recognise when the central unsubscribes
 */
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
{
    NSLog(@"Central unsubscribed from characteristic");
}

- (void)sendData
{
    [self.peripheralManager updateValue:dataToSend forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
}

- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
{[self sendData];
    // Start sending again
}
1

There are 1 answers

0
user4826471 On

I figured this out just put

self.characteristic = [[CBMutableCharacteristic alloc]
                            initWithType:[CBUUID UUIDWithString:@"C63CBCC0-6DE3-48D5-BB59-2BEFB9F3AE01"]
                            properties:CBCharacteristicPropertyRead |  CBCharacteristicPropertyNotify
                            value:nil
                            permissions:CBAttributePermissionsWriteEncryptionRequired];

in my viewdidload