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