NSOutputStream EASession прекращает отправку данных в EAAccessory

У меня есть проект, который подключается к внешнему аксессуару и передает небольшое количество данных в приложение для iOS и из него. Я могу настроить сеанс и потоки, как это делает Apple в их коде ссылки EADemo, и все, кажется, работает нормально.

У меня проблема в том, что после случайного количества времени использования приложения выходной поток перестает работать, но входной поток по-прежнему работает нормально. Я проверяю, чтобы убедиться, что hasSpaceAvailable имеет значение true перед каждой попыткой записи, и когда я читаю количество записанных байтов, все выглядит правильно. Кроме того, просмотр цикла выполнения не показывает каких-либо различий между рабочим и нерабочим, и состояние потока все еще читается как открытое.

Единственное, что я вижу по этой причине, это то, что мой аксессуар не подтверждает несколько попыток записи приложения подряд, а затем он ломается.

Как я могу обнаружить, что я нахожусь в этом состоянии и как я могу это исправить?

 // low level write method - write data to the accessory while there is space available and data to write
    - (void)_writeData {
        while (([[_session outputStream] hasSpaceAvailable]) && ([_dataToWrite length] > 0))
        {

            NSInteger bytesWritten = [[_session outputStream] write:[_dataToWrite bytes] maxLength:[_dataToWrite length]];

            if (bytesWritten == -1)
            {
                NSLog(@"write error");
                break;
            }
            else if (bytesWritten > 0)
            {
                [_dataToWrite replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
            }
        }
    }

    // low level read method - read data while there is data and space available in the input buffer
    - (void)_readData {
        NSLog(@"reading data to buffer");
    #define EAD_INPUT_BUFFER_SIZE 128
        uint8_t buf[EAD_INPUT_BUFFER_SIZE];
        while ([[_session inputStream] hasBytesAvailable])
        {
            NSInteger bytesRead = [[_session inputStream] read:buf maxLength:EAD_INPUT_BUFFER_SIZE];
            if (_dataToRead == nil) {
                _dataToRead = [[NSMutableData alloc] init];
            }
            [_dataToRead appendBytes:(void *)buf length:bytesRead];
        }

        [[NSNotificationCenter defaultCenter] postNotificationName:EASessionDataReceivedNotification object:self userInfo:nil];
    }


    // high level write data method
    - (void)writeData:(NSData *)data
    {
     //   NSLog(@"writing data to buffer");
        if (_dataToWrite == nil) {
            _dataToWrite = [[NSMutableData alloc] init];
        }

        [_dataToWrite appendData:data];
        [self _writeData];


    }

// high level read method
- (NSData *)readData:(NSUInteger)bytesToRead
{
    NSLog(@"reading data");
    NSData *data = nil;
    if ([_dataToRead length] >= bytesToRead) {
        NSRange range = NSMakeRange(0, bytesToRead);
        data = [_dataToRead subdataWithRange:range];
        [_dataToRead replaceBytesInRange:range withBytes:NULL length:0];
    }
    return data;
}

    - (BOOL)openSession
    {
         NSLog(@"openSession");
        [_accessory setDelegate:self];

        if(_session){
            [self closeSession];
        }

        _session = [[EASession alloc] initWithAccessory:_accessory forProtocol:_protocolString];

        if (_session)
        {
            _runLoop = [NSRunLoop currentRunLoop];

            [[_session inputStream] setDelegate:self];
            [[_session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [[_session inputStream] open];

            [[_session outputStream] setDelegate:self];
            [[_session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [[_session outputStream] open];
            NSLog(@"creating session succeeded!");
        }
        else
        {
            NSLog(@"creating session failed!");
        }

        return (_session != nil);
    }

1 ответ

Я думаю, что я могу испытывать ту же проблему. У меня есть аксессуар, подключенный по Bluetooth, и когда я тестирую диапазон, я часто оказываюсь в ситуации с теми же симптомами, которые вы описали в своем вопросе.

Но как определить, что проблема вызвана тем, что аксессуар не может получить данные ACK?

Я предполагаю, что в моей ситуации Аксессуар отправляет ACK, но, поскольку я нахожусь на грани диапазона Bluetooth, мой телефон никогда не получает ACK.

Прямо сейчас мой лучший выбор, чтобы попытаться обнаружить ситуацию в приложении. В моей ситуации я могу сделать это, потому что аксессуар отправит тот же пакет, если он не получит никаких данных с телефона. Поэтому, если я несколько раз увижу одни и те же данные, передаваемые с аксессуара, я прерву соединение и попросу пользователя приблизиться к аксессуару и снова подключиться.

Другие вопросы по тегам