Я пытаюсь создать приложение для Android, которое подключается к двум модулям Bluetooth HC-05 (которые подключены к Arduino).
Я могу подключиться к обоим из них, и если я отправляю данные только одному из них, все работает нормально, если я отправляю данные обоим, однако он может работать в течение некоторого времени, но затем он перестает отправлять на одно устройство.
На одном телефоне это приводит к сбою приложения, на другом - ничего (исключение или уведомление о разрыве соединения) не происходит.
Итак, я проверил Интернет, и в большей части говорится, что вы можете подключиться к двум устройствам Bluetooth одновременно (например, здесь).
Я не могу понять, в чем причина этой ошибки. Но у меня есть идеи. Может быть, тогда кто-то сможет подтвердить, или знает настоящую проблему или еще лучше ее решение :)
Поскольку я использую два модуля Bluetooth HC-05, у них одинаковый UUID, что, как я полагаю, может быть проблематичным, потому что этот UUID не уникален для одного устройства. Но я не уверен, что проблема в этом. Может кто знает как поменять UUID HC-05?
Обратите внимание, что я отправляю данные через случайные интервалы на обе машины. Так что я думаю, что это могло вызвать проблему. В какой-то момент приложение пытается отправить сообщение сразу на два устройства, и это вызывает проблемы. Итак, я думаю о том, чтобы сделать какое-то обходное решение для этого. Но я не знаю, как это сделать. Может быть, какой-то стек, в который я помещаю данные и устройство, на которое они должны отправить, а затем я отправляю их элемент за элементом, возможно, с некоторой задержкой между ними. Таким образом, отправка данных несколько «синхронизирована». Однако я не знаю, хорошее ли это решение, и я благодарен за любой совет, который я мог получить.
Итак, прямо сейчас я подключаюсь к таким устройствам:
public void connect(String mac){
Set<BluetoothDevice> bondedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
for (BluetoothDevice devices : bondedDevices)
if (devices.getAddress().equals(mac)) {
this.device = devices;
break;
}
if (this.device == null) {
//some error handling
} else {
UUID id= UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
this.socket = this.device.createRfcommSocketToServiceRecord(id);
this.socket.connect();
this.outputStream = this.socket.getOutputStream();
final InputStream st = this.socket.getInputStream();
//some more init stuff
} catch (Exception e) {
e.printStackTrace();
this.disconnect();
}
}
}
И я отправляю такие данные (без лишнего кода):
byte[] send = new byte[9];
//fill Data
try {
this.outputStream.write(send);
this.outputStream.flush();
} catch (Exception e) {
//Displaying Toast with Error message
Toast.makeText(DirtyCode.appcont, e.getMessage(), Toast.LENGTH_LONG).show();
Log.e("SEND EXCEPTION:" + device.getName(), e.getMessage());
e.printStackTrace();
return false;
}
Так что я также думал, что мне может понадобиться как-то использовать BluetoothServerSocket. Но я в этом не уверен.
Соединение работает идеально с одним подключенным устройством или с двумя подключенными устройствами, но отправка выполняется только на одно устройство (отправка очень случайных данных на второе обычно работает очень долго, прежде чем вызвать проблемы).
Я пытался решить это в течение долгого времени, но я не могу заставить его работать, поэтому любая помощь действительно приветствуется.
У меня нет исключения, по крайней мере, я не смог где-то его поймать. Как только я получил исключение, соединение системы / программного обеспечения прервано или подобное.
Значит, процесс просто вылетает, без каких-либо следов в логарифме?
на одном телефоне даже не вылетает я просто перестаю принимать на одном устройстве BT. с другой стороны, у меня не было следов в логарифме. это просто останавливается
Хм, я бы хотел увидеть весь код, который имеет дело с жизненным циклом вашего сокета: создание, использование и отключение.
Итак, мое создание и использование уже под вопросом (код для отправки выполняется либо обработчиком, либо когда пользователь нажимает кнопку). Это код, который я использую для отключения: try { pause(); // send some data outputStream.close(); outputStream =null; socket.close(); } catch (Exception e) { e.printStackTrace(); }
Этого кода недостаточно; Я пытаюсь определить ответы на такие вопросы, как: 1.) Как быстро два сокета запускаются относительно друг друга 2.) Как долго они существуют одновременно 3.) На каких потоках они работают 4.) Как вы подсказываете им отправлять больше данных и 5) Как часто они подключаются и логика переподключения. Судя по опубликованному вами рекламному объявлению, похоже, что вы отправляете 9 байтов на устройство, а затем немедленно отключаетесь, что делает маловероятным, что вы когда-либо одновременно подключаетесь.
Я подключаюсь к одному BTDevice, отправляю 9 байтов, затем подключаюсь к другому BTDevice и отправляю 9 байтов на это устройство. Чем на протяжении всего приложения я никогда не подключаюсь повторно. Я просто время от времени отправляю на устройства 9 байтов. Иногда я отправляю их на одно устройство, а затем сразу после этого на другое. Я тестировал его, отправляя два таких устройства каждые 5 секунд или около того. например Device1 9 байтов -5sec- Device1 9 байтов -5sec- Device2 9 байтов -5sec- и затем повторить. через 5 сек.
Итак, я предполагаю, что 1.) каждый сокет запускается в своем собственном выделенном фоновом потоке 2.) что вы правильно обработали все проблемы синхронизации потоков и 3.) у вас есть соответствующая логика обработки ошибок и повторного подключения на случай, если произойдет одно соединение. проблема. Это верно? И на своем первом телефоне вы, должно быть, определили точную строку, которая вызывает сбой, возможно, заключив ее в скобки с операторами журнала?
Как определить, что 1 устройство "перестало принимать"? Откуда вы знаете, что ваш код Arduino не является проблемой?
Пока я вообще не выполнял синхронизацию, и outputStream.write () не обязательно вызывается из другого потока. И я не получаю ничего от устройств BT, поэтому я не слушаю никаких входящих данных. На arduino мне нужно распечатать на последовательный порт количество доступных байтов из модуля Bluetooth (Serial.available ()), когда он входит в метод проверки входящих данных BT. Итак, я знаю, что он проверяет, и я знаю, что он не получил никаких данных. Иногда я замечал, что, хотя я вызываю flush (), для отправки данных требуется такое же время (дольше, чем обычно.
Я хотел бы получить более подробную информацию о том, как вы используете потоки, на основе вашего ответа и утверждения «в какой-то момент приложение пытается отправить на два устройства одновременно, и это вызывает проблемы». Я не могу быть уверен, что вы правильная обработка всех проблем безопасности потоков. Другая проблема заключается в вашем утверждении, что сокеты не работают без выброса, и программа вылетает без какого-либо вывода logcat. Обе ситуации кажутся мне очень маловероятными. Чтобы объяснить это, нужно сделать больше. Вы уверены, что знаете, как использовать logcat? И можно ли определить точную линию, на которой происходит сбой?
Также убедитесь, что вы не затираете существующую ссылку, когда присваиваете значение this.socket
/ this.outputStream
... Я предполагаю, что у вас есть 2 экземпляра любого класса, который содержит эти члены, но это не ясно в опубликованном коде.
Спасибо за помощь. Я проведу еще несколько исследований о том, где возникает ошибка в ближайшие дни, и опубликую больше этого кода, чем. В примерах кода ключевое слово this не обязательно, поэтому нет локальной переменной с таким же именем. Есть только один глобальный поток сокета / вывода.
OK. Удачи. Кстати, я не имел в виду локальную переменную. Я имею в виду, какой бы класс ни содержал эту переменную - вам нужно убедиться, что у вас есть как минимум 2 из них. Это важно!
«Есть только один глобальный сокет / выходной поток» - звучит неправильно. У вас два подключения, вам нужно две розетки. Если у вас два сокета, вам нужно два выходных потока.
Вы не можете одновременно подключиться к нескольким устройствам BT, каждое из которых имеет одну и ту же услугу BT. Это звучит так: у вас есть два динамика BT, вы подключили их оба, и вы начали музыку, а затем воспроизводятся оба динамика. Невозможно.
Но вы можете подключить несколько устройств BT, каждое из которых является отдельной службой BT: Например: одновременное использование мыши BT и динамика BT. Это возможно.
Хорошо, спасибо за эту информацию. Итак, тип службы BT определяется через UUID, верно? Значит, изменение одного UUID может сработать? И есть объяснение, почему он работает несколько раз (с двумя устройствами, получающими данные с одним и тем же UUID)?
Пожалуйста, посмотрите эту ветку: stackoverflow.com/questions/13964342/…, и это: bluetooth.com/specifications/assigned-numbers/service-discov ery
-1 Устройства BT имеют MAC-адреса, которые делают их однозначно идентифицируемыми. UUID предназначен только для обнаружения служб, например идентификаторов классов USB-устройств. Фактически, вы должны иметь возможность подключаться к двум парам динамиков BT одновременно, если бы вы были склонны писать клиентское программное обеспечение, поддерживающее это.
@ greeble31 Вы хотите изменить прошивку клиентского устройства?
В этом случае изменение прошивки не требуется, поскольку сокеты создаются по указанию программного обеспечения пользовательского пространства.
Думая о BT UUID как о TCP-портах, может быть полезно понять, как работает bluetooth UUID. Они работают как сокеты TCP, и нам нужно, чтобы сокеты поддерживали множественное соединение, по крайней мере, на стороне сервера. Например, в BT 5.0 появилась новая функция под названием Dual Audio; если у вас есть телефон с поддержкой BT 5.0, вы можете одновременно подключить два обычных (не BT 5.0) динамика. Потому что серверная сторона поддерживает двойной BT Audio и может одновременно подключать два аудиоустройства. Таким образом, требуется, чтобы используемый нами стандарт BT поддерживал множественное соединение с одним и тем же UUID.
Я согласен с аналогией с TCP, но не думаю, что она применима к случаю OP; его программное обеспечение действует как клиент. HC-05 действуют как два отдельных сервера.
Какое исключение при обрыве связи со вторым устройством?