2013-07-09 4 views
1

Я работаю над использованием BLE в проекте, ранее использующем устройства MFi. Целью является достижение своего рода последовательного соединения.Corebluetooth: переключение подключенного периферийного устройства из вида в другое

С EAaccessory у меня появился popover с просьбой подключить устройство и работал нормально.

Используя CB, я добавил представление, которое я вызываю для сканирования, и выберите устройство для подключения. Я могу подключить устройство в порядке, но когда я вернусь к основному виду, я потеряю соединение с периферией.

CoreBluetooth[WARNING] <CBConcretePeripheral: ... IsConnected = YES> is being dealloc'ed while connected 

Так как я не гений, ни хороший программист Иос ... Может кто-то мне точку в правильном направлении, чтобы сохранить подключенное периферийное от одного вида к основным?

Я попытался понять образец от ConnectBlue, производителя BT-устройств в моем проекте, но они используют Storyboard, а я нет. Используя их демо, я могу подключиться к периферии, на главном экране и поболтать с ним на другом экране.

Я попытался Google, но ничего не нашел.

Edit: Код соединительная часть

#import "ScanTableViewController.h" 
#import <CoreBluetooth/CBCentralManager.h> 
#import <CoreBluetooth/CBPeripheral.h> 
#import "DiscoveredPeripheral.h" 
#import "ScanCell.h" 

typedef enum 
{ 
    SCAN_S_NOT_LOADED, 
    SCAN_S_DISAPPEARED, 
    SCAN_S_WILL_DISAPPEAR, 
    SCAN_S_APPEARED_IDLE, 
    SCAN_S_APPEARED_SCANNING 

} SCAN_State; 
@interface ScanTableViewController() 

@end 


@implementation ScanTableViewController 
{ 
    SCAN_State   state; 

    CBCentralManager *cbCentralManager; 
    NSMutableArray  *discoveredPeripherals; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSLog(@"Scan viewDidLoad"); 

    cbCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 
    // Do any additional setup after loading the view from its nib. 
    CGRect tableViewFrame = self.view.bounds; 

    UITableView *tableview = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStylePlain]; 

    self.myTableView = tableview; 
    self.myTableView.rowHeight = 60; 
    self.myTableView.dataSource = self; 
    self.myTableView.delegate = self; 
    //Make sure our table view resizes correctly 
    self.myTableView.autoresizingMask = 
    UIViewAutoresizingFlexibleWidth | 
    UIViewAutoresizingFlexibleHeight; 
    [self.view addSubview:tableview]; 

    discoveredPeripherals = [[NSMutableArray alloc] init]; 

    //[cbCentralManager retrieveConnectedPeripherals]; 

    state = SCAN_S_DISAPPEARED; 

} 

- (void)viewDidUnload 
{ 
    //[self setScanButton:nil]; 
    [super viewDidUnload]; 
    NSLog(@"Scan viewDidUnload"); 
    cbCentralManager = nil; 

    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 

    state = SCAN_S_NOT_LOADED; 

} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    NSLog(@"Scan viewWillAppear"); 
    [self.myTableView reloadData]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
    NSLog(@"Scan viewDidAppear"); 

    [self clearPeriph]; 

    state = SCAN_S_APPEARED_IDLE; 

    [self.myTableView reloadData]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
NSLog(@"Scan viewWillDisappear"); 
//[self scan: FALSE]; 

state = SCAN_S_WILL_DISAPPEAR; 

[super viewWillDisappear:animated]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
[super viewDidDisappear:animated]; 
NSLog(@"Scan viewDidDisappear"); 

state = SCAN_S_DISAPPEARED; 
} 

-(void) enterForeground 
{ 
    NSLog(@"Scan enterForeground"); 
    [self clearPeriph]; 

    state = SCAN_S_APPEARED_IDLE; 
} 

-(void) enterBackground 
{ 
    NSLog(@"Scan enterBackground"); 
    [self scan: FALSE]; 

    state = SCAN_S_DISAPPEARED; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void) initWithPeripherals: (NSMutableArray*) dp 
{ 
    NSLog(@"Scan initWithPeripherals"); 
    discoveredPeripherals = dp; 

    state = SCAN_S_NOT_LOADED; 
} 

#pragma mark - Table view data source 

// Customize the number of sections in the table view. 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    //NSLog(@"Nombre de sections"); 
    return 2; 
} 

// Customize the number of rows in the table view. 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // Return the number of rows in the section. 
    NSInteger nRows; 

    switch(section) 
    { 
     case 0: 
      nRows = 1; 
      break; 

     case 1: 
      NSLog(@"Scan Nbre ligne section 1 : %i",discoveredPeripherals.count); 
      nRows = discoveredPeripherals.count; 
      break; 

     default: 
      nRows = 0; 
      break; 
    } 

    return nRows; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    //NSLog(@"Remplissage"); 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ; 
     cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton; 
    } 

    NSLog(@"Scan Section table:%u",indexPath.section); 

    switch(indexPath.section) 
    { 
     case 0: 
     { 
      cell.textLabel.text = @""; 
      if(state == SCAN_S_APPEARED_SCANNING) 
      { 
       cell.textLabel.text = @"Stop Scan"; 
       //cell.labelInfo.text = @"Active"; 

       //[cell.activityView startAnimating]; 
      } 
      else 
      { 
       cell.textLabel.text = @"Start Scan"; 
       //cell.labelInfo.text = @"Inactive"; 
       // 
       //[cell.activityView stopAnimating]; 
      } 
      break; 
     } 
     case 1: 
     { 
      if ([discoveredPeripherals count] > 0) 
      { 
       DiscoveredPeripheral* discoveredPeripheral; 
       discoveredPeripheral = [discoveredPeripherals objectAtIndex:indexPath.row]; 
       cell.textLabel.text =discoveredPeripheral.peripheral.name; 
      } 

      cell.detailTextLabel.textColor = [UIColor blackColor]; 
     } 
    } 
    return cell; 
} 

- (NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{ 
    NSString *str; 

    switch(section) 
    { 
     case 0: 
      str = @"Bluetooth Low Energy Scanning"; 
      break; 

     case 1: 
      str = @"Found Devices"; 
      break; 

     default: 
      break; 
    } 

    return str; 
} 

#pragma mark - Table view delegate 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

    if(cbCentralManager.state == CBCentralManagerStatePoweredOn) 
    { 
     //ScanCell* cell = (ScanCell*)[tableView cellForRowAtIndexPath:indexPath]; 
     //static NSString *CellIdentifier = @"Cell"; 
     UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
     if(indexPath.section == 0) 
     { 
      if(state == SCAN_S_APPEARED_SCANNING) 
      { 
       [self scan: FALSE]; 

       cell.textLabel.text = @"Start Scan"; 
       //cell.labelInfo.text = @"Inactive"; 
       //[cell.activityView stopAnimating]; 

       state = SCAN_S_APPEARED_IDLE; 
      } 
      else if((state == SCAN_S_APPEARED_IDLE) && 
        (cbCentralManager.state == CBCentralManagerStatePoweredOn)) 
      { 

       [self scan: TRUE]; 

       cell.textLabel.text = @"Stop Scan"; 
       //cell.labelInfo.text = @"Active"; 
       //[cell.activityView startAnimating]; 

       state = SCAN_S_APPEARED_SCANNING; 
      } 
     } 
     else 
     { 
      DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:indexPath.row]; 

      NSDictionary *dictionary; 

      switch (dp.state) 
      { 
       case DP_STATE_IDLE: 

        cell.textLabel.text = @"Connecting"; 

        //[cell.activityView startAnimating]; 

        dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]; 

        [cbCentralManager connectPeripheral:dp.peripheral options:dictionary]; 

        dp.state = DP_STATE_CONNECTING; 
        break; 

       case DP_STATE_CONNECTED: 
       case DP_STATE_CONNECTING: 
        [cbCentralManager cancelPeripheralConnection:dp.peripheral]; 

        cell.textLabel.text = @""; 

        //[cell.activityView stopAnimating]; 
        cell.accessoryType = UITableViewCellAccessoryNone; 

        dp.state = DP_STATE_IDLE; 
        break; 

       default: 
        break; 
      } 
     } 

     [tableView deselectRowAtIndexPath:indexPath animated:YES]; 
    } 
} 

- (void) scan: (bool) enable 
{ 
    if(enable == TRUE) 
    { 
     NSLog(@"Scan Scan ON"); 
     NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBCentralManagerScanOptionAllowDuplicatesKey]; 

     [cbCentralManager scanForPeripheralsWithServices:nil options:dictionary]; 
    } 
    else 
    { 
     NSLog(@"Scan Scan Off"); 
     [cbCentralManager stopScan]; 
    } 
} 

- (IBAction)startScan:(id)sender { 

    if(state == SCAN_S_APPEARED_IDLE) 
    { 
     [self scan: TRUE]; 

     state = SCAN_S_APPEARED_SCANNING; 
    } 
    else if(state == SCAN_S_APPEARED_SCANNING) 
    { 
     [self scan: FALSE]; 

     state = SCAN_S_APPEARED_IDLE; 
    } 
} 

- (void) clearPeriphForRow: (NSInteger)row 
{ 
    DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row]; 

    //if((dp.peripheral.isConnected == FALSE) && 
    // ((dp.state == DP_STATE_CONNECTED) || (dp.state == DP_STATE_DISCONNECTING))) 
    if(dp.peripheral.isConnected == FALSE) 
    { 
     dp.state = DP_STATE_IDLE; 
    } 
    else if((dp.peripheral.isConnected == TRUE) && 
      (dp.state != DP_STATE_CONNECTED)) 
    { 
     dp.state = DP_STATE_CONNECTED; 
    } 

    if(dp.state == DP_STATE_IDLE) 
    { 
     [discoveredPeripherals removeObjectAtIndex:row]; 

     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:1]; 
     //ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 
     UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 
     //[cell.activityView stopAnimating]; 

     cell.accessoryType = UITableViewCellAccessoryNone; 

     [self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

- (void) clearPeriph 
{ 
    if(self->discoveredPeripherals.count > 0) 
    { 
     for(int i = discoveredPeripherals.count - 1; i >= 0 ; i--) 
     { 
      [self clearPeriphForRow:i]; 
     } 
    } 

    [self.myTableView reloadData]; 
} 

- (IBAction)clearPeripherals:(id)sender { 

    [self clearPeriph]; 

    [self scan: FALSE]; 

    state = SCAN_S_APPEARED_IDLE; 
} 

- (NSInteger)getRowForPeripheral: (CBPeripheral*)peripheral 
{ 
    NSInteger row = -1; 
    DiscoveredPeripheral* p; 

    for(int i = 0; (i < discoveredPeripherals.count) && (row == -1); i++) 
    { 
     p = [discoveredPeripherals objectAtIndex:i]; 

     if([peripheral isEqual:p.peripheral] == TRUE) 
     { 
      row = i; 
     } 
    } 

    return row; 
} 

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral 
{ 
    NSInteger row = [self getRowForPeripheral:peripheral]; 

    if(row != -1) 
    { 
     NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1]; 
     UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 
     //ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

     cell.textLabel.text = [[NSString alloc] initWithFormat:@"Connected"]; 

     //[cell.activityView stopAnimating]; 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 

     DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row]; 

     dp.state = DP_STATE_CONNECTED; 

     //[peripheral discoverServices:nil]; 

     //[self scan:FALSE]; 

     //[[self navigationController] popViewControllerAnimated:NO]; 
     //[self.delegate didConnectedPeriph:dp]; 
    } 
} 

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error 
{ 
    NSInteger row = [self getRowForPeripheral:peripheral]; 

    if(row != -1) 
    { 
     NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1]; 

     UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 
     //ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

     cell.textLabel.text = [[NSString alloc] initWithFormat:@""]; 

     cell.accessoryType = UITableViewCellAccessoryNone; 
     //[cell.activityView stopAnimating]; 

     DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row]; 

     dp.state = DP_STATE_IDLE; 
    } 
} 

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI 
{ 
    bool new = TRUE; 
    DiscoveredPeripheral* discPeripheral; 
    int row = -1; 

    if((state == SCAN_S_APPEARED_SCANNING) && 
     (peripheral != nil)) 
    { 

     for(int i = 0; (i < discoveredPeripherals.count) && (new == TRUE); i++) 
     { 
      NSLog(@"Scan Ajout periph"); 
      discPeripheral = [discoveredPeripherals objectAtIndex:i]; 

      if(discPeripheral.peripheral == peripheral) 
      { 
       new = false; 
       row = i; 

       discPeripheral.peripheral = peripheral; 
      } 
     } 

     if(new == TRUE) 
     { 
      discPeripheral = [[DiscoveredPeripheral alloc] initWithPeripheral:peripheral andAdvertisment:advertisementData andRssi:RSSI]; 

      discPeripheral.rssi = RSSI; 

      if(peripheral.isConnected == TRUE) 
      { 
       discPeripheral.state = DP_STATE_CONNECTED; 
      } 

      [discoveredPeripherals addObject:discPeripheral]; 
      NSLog(@"Scan Ajout periph, total:%i",[discoveredPeripherals count]); 
      NSLog(@"Scan %i: Add %@",[discoveredPeripherals count]-1, discPeripheral.peripheral.name); 

      NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[discoveredPeripherals count]-1 inSection:1]; 
      NSLog(@"Scan Nouveau periph, index:%i, section:%i",indexPath.row,indexPath.section); 
      UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 
      cell.textLabel.text = discPeripheral.peripheral.name; 
      //[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
      [self.myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     } 
     else 
     { 
      discPeripheral.peripheral = peripheral; 
      discPeripheral.advertisment = advertisementData; 
      discPeripheral.rssi = RSSI; 

      NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1]; 
      UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 

      //ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

      //NSLog(@"%i: Update %@", row, discPeripheral.peripheral.name); 

      cell.textLabel.text = discPeripheral.peripheral.name; 
      //cell.labelInfo.text = [[NSString alloc] initWithFormat:@"RSSI: %@", discPeripheral.rssi]; 
     } 
    } 
} 


- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error 
{ 
    NSInteger row = [self getRowForPeripheral:peripheral]; 

    if(row != -1) 
    { 
     NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1]; 
     UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath]; 

     //ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 

     cell.textLabel.text = [[NSString alloc] initWithFormat:@""]; 

     cell.accessoryType = UITableViewCellAccessoryNone; 
     //[cell.activityView stopAnimating]; 

     DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row]; 

     dp.state = DP_STATE_IDLE; 
    } 
} 

- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals 
{ 
    //DiscoveredPeripheral* discPeripheral; 
    CBPeripheral*   peripheral; 

    for(int i = 0; i < peripherals.count; i++) 
    { 
     peripheral = [peripherals objectAtIndex:i]; 

     /* 
     discPeripheral = [[DiscoveredPeripheral alloc] initWithPeripheral:peripheral andAdvertisment:nil andRssi:nil]; 

     if(peripheral.isConnected == TRUE) 
     { 
     discPeripheral.state = DP_STATE_CONNECTED; 
     } 

     [discoveredPeripherals addObject:discPeripheral]; 

     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[discoveredPeripherals count] - 1 inSection:1]; 

     [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     */ 

     //[cbCentralManager cancelPeripheralConnection:peripheral]; 

     NSDictionary *dictionary; 

     dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]; 

     [cbCentralManager connectPeripheral:peripheral options:dictionary]; 

    } 
} 

- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals 
{ 

} 


- (void)centralManagerDidUpdateState:(CBCentralManager *)central 
{ 
    //NSLog(@"Central Manager State: %d", [central state]); 

    if(central.state == CBCentralManagerStatePoweredOn) 
    { 
     [cbCentralManager retrieveConnectedPeripherals]; 
    } 
} 

@end 

Edit: Этот вид вызывается из контроллера представления. Контроллер представления принимает данные от bluetooth, записывает и отображает данные. Я хотел бы получить отдельный вид для подключения к периферийному устройству BLE, вернуться к основному виду, подключить последовательный порт и запустить. Во второй раз, если периферийное устройство потеряно, попробуйте подключиться к нему, иначе вы увидите сообщение о подключении и предупредите пользователя.

Cheers.

Cedric

+0

Не могли бы вы показать код вашего метода подключения? Вы отслеживаете периферийное устройство, которое хотите подключить? – Larme

+0

Larme: Я добавил код, но дело в том, что я не знаю, как сохранить следы периферийных устройств, которые я подключаю, и подключенных. – Cedric

+0

В вашем классе вы добавляете: 'CBPeripheral * yourPeripheral', и когда он соединяется (в методе делегата):' yourPeripheral = peripheral; '. Обратите внимание, что вы можете создать sharedInstance своего класса BLECommunication и называть его всякий раз, когда захотите (например, в каждом из ViewController). – Larme

ответ

2

Необходимо сохранить периферийное устройство. Как только вы удаляете периферийный объект, iOS отключает соединение. Сохраните объект CBPeripheral в переменной и не забудьте передать его обратно в основное представление, когда окно просмотра закрывается.

1

Очень красивый способ управлять всеми процессами bluetooth - это модель однопользовательского режима. Вы можете переместить весь свой код Bluetooth в отдельный класс NSObject и объявить этот файл как одноэлементный. Создайте функцию в вашем классе singleton, чтобы инициировать connectPeripheral после обнаружения вашего устройства. Всякий раз, когда вы подключаетесь, вы можете сохранить периферийное устройство, к которому вы подключаетесь, в качестве переменной или в массиве, если у вас несколько устройств. Это довольно просто, как только вы получите это. Используя этот метод реализации, вы можете обратиться к своему подключенному периферийному устройству из любого места вашего приложения. Надеюсь, это помогло!

+0

да, что я пошел – Cedric

Смежные вопросы