Главная > Hard, Soft > Raspberry Pi: Как работать с Bluetooth на Java

Raspberry Pi: Как работать с Bluetooth на Java

Продолжая работать над своей задумкой, настало время получить доступ на Raspberry Pi к Bluetooth, используя Java.  Bluetooth API для Java описан в спецификации JSR-82. Поиски в Internet выдали, что сейчас широко распространена библиотека BlueCove, которая реализует JSR-82. Её настройке и будет посвящена эта статья.

Raspberry: Как работать с bluetooth на java

Библиотека представляет из себя Java API, который через JNI обращается к реализации Bluetooth для конкретной платформы. Поэтому главным условием является наличие подходящей библиотеки dll для Windows и so для Linux.

Raspberry: Как работать с bluetooth на java

Windows

Для начала работы под Windows достаточно скачать jar-файлы (я использовал версию 2.1.1) и добавить в проект. Дальше можно запустить простую программу для проверки работоспособности:

public class BlueToothTest {
	public static void main(String[]args) throws IOException {
		System.out.println("Local address: " + LocalDevice.getLocalDevice().getBluetoothAddress());
	}
}

Сперва проверка делалась под Windows 7 на ноутбуке Toshiba и эксперимент завершился ошибкой. Похоже, что версии для Toshiba ещё нет.

Exception in thread «main» java.lang.UnsatisfiedLinkError: com.intel.bluetooth.BluetoothStackToshiba.getLibraryVersion()I
at com.intel.bluetooth.BluetoothStackToshiba.getLibraryVersion(Native Method)
at com.intel.bluetooth.BlueCoveImpl.setBluetoothStack(BlueCoveImpl.java:1005)

Потом попытка была на ноутбуке DELL и она увенчалась успехом:

BlueCove version 2.1.1-SNAPSHOT on winsock
Local address: BC77377D6332
BlueCove stack shutdown completed

Linux

Для Linux ситуация сложнее. Для начала использования библиотеки нужно выполнить некоторые подготовительные действия и установить необходимые пакеты.

sudo apt-get install bluetooth bluez-utils blueman
sudo apt-get install libbluetooth-dev
sudo apt-get install ant

Для запуска пробной программы используется Runnable Jar File, который создаётся в Eclipse через Export.

java -jar bluetooth.jar

Попытка выполнить такой файл на Raspberry оканчивается ошибкой:

java.lang.UnsatisfiedLinkError: /tmp/bluecove_pi_0/libbluecove_arm.so: /tmp/bluecove_pi_0/libbluecove_arm.so: cannot open shared object file: No such file or directory

Это говорит о том, что для Linux придётся скомпилировать свою собственную версию so-файла.

mkdir bluecovelib
cd bluecovelib
wget http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63/bluecove-gpl-2.1.1-SNAPSHOT-sources.tar.gz
tar -zxvf bluecove-gpl-2.1.1-SNAPSHOT-sources.tar.gz

mkdir -p bluecove/target
cd bluecove/target
wget http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63/bluecove-2.1.1-SNAPSHOT.jar

cd ../../bluecove-gpl-2.1.1-SNAPSHOT
ant all

Результатом будет bluecove-gpl-2.1.1-SNAPSHOT.jar с нужной библиотекой so, которую можно использовать в проекте.

Для Raspberry компиляция прошла успешно и тестовая программа сразу заработала:

BlueCove version 2.1.1-SNAPSHOT on bluez
Local address: 001A7DDA7113
BlueCove stack shutdown completed

А вот попытка компиляции на Ubuntu привела к череде проблем, первой из которых была ошибка:

 java.lang.UnsatisfiedLinkError: /tmp/bluecove_merl1n_0/libbluecove.so: /tmp/bluecove_merl1n_0/libbluecove.so: undefined symbol: sdp_extract_pdu

Несколько часов поисков вывели меня на команд ldd, которая показывает зависимости.

merl1n@merl1n:~/bluecovelib2/dir$ ldd -r -v libbluecove.so
statically linked
undefined symbol: stdout (./libbluecove.so)
undefined symbol: sdp_extract_pdu (./libbluecove.so)
undefined symbol: free (./libbluecove.so)
undefined symbol: ioctl (./libbluecove.so)
undefined symbol: sdp_record_alloc (./libbluecove.so)
undefined symbol: recv (./libbluecove.so)
undefined symbol: connect (./libbluecove.so)
undefined symbol: hci_inquiry (./libbluecove.so)
undefined symbol: strerror (./libbluecove.so)
undefined symbol: hci_read_remote_name (./libbluecove.so)
undefined symbol: snprintf (./libbluecove.so)
undefined symbol: sdp_service_search_req (./libbluecove.so)
undefined symbol: hci_read_remote_version (./libbluecove.so)
undefined symbol: sdp_close (./libbluecove.so)
undefined symbol: memcpy (./libbluecove.so)
undefined symbol: sdp_device_record_unregister (./libbluecove.so)
undefined symbol: malloc (./libbluecove.so)
undefined symbol: vsnprintf (./libbluecove.so)
undefined symbol: socket (./libbluecove.so)
undefined symbol: fflush (./libbluecove.so)
undefined symbol: dlclose (./libbluecove.so)
undefined symbol: send (./libbluecove.so)
undefined symbol: sdp_list_append (./libbluecove.so)
undefined symbol: accept (./libbluecove.so)
undefined symbol: hci_close_dev (./libbluecove.so)
undefined symbol: hci_open_dev (./libbluecove.so)
undefined symbol: sdp_device_record_update (./libbluecove.so)
undefined symbol: hci_send_req (./libbluecove.so)
undefined symbol: bind (./libbluecove.so)
undefined symbol: setsockopt (./libbluecove.so)
undefined symbol: dlopen (./libbluecove.so)
undefined symbol: sdp_device_record_register (./libbluecove.so)
undefined symbol: sdp_data_get (./libbluecove.so)
undefined symbol: sdp_record_free (./libbluecove.so)
undefined symbol: listen (./libbluecove.so)
undefined symbol: dlsym (./libbluecove.so)
undefined symbol: memset (./libbluecove.so)
undefined symbol: hci_write_current_iac_lap (./libbluecove.so)
undefined symbol: hci_get_route (./libbluecove.so)
undefined symbol: poll (./libbluecove.so)
undefined symbol: sdp_service_attr_req (./libbluecove.so)
undefined symbol: shutdown (./libbluecove.so)
undefined symbol: hci_read_current_iac_lap (./libbluecove.so)
undefined symbol: hci_read_local_name (./libbluecove.so)
undefined symbol: getpeername (./libbluecove.so)
undefined symbol: fputc (./libbluecove.so)
undefined symbol: sdp_list_free (./libbluecove.so)
undefined symbol: getsockopt (./libbluecove.so)
undefined symbol: sdp_connect (./libbluecove.so)
undefined symbol: hci_send_cmd (./libbluecove.so)
undefined symbol: fwrite (./libbluecove.so)
undefined symbol: hci_read_class_of_dev (./libbluecove.so)
undefined symbol: __errno_location (./libbluecove.so)
undefined symbol: hci_read_bd_addr (./libbluecove.so)
undefined symbol: sdp_gen_record_pdu (./libbluecove.so)
undefined symbol: fcntl (./libbluecove.so)
undefined symbol: sdp_attr_remove (./libbluecove.so)
undefined symbol: close (./libbluecove.so)
undefined symbol: vfprintf (./libbluecove.so)
undefined symbol: free (./libbluecove.so)
undefined symbol: getsockname (./libbluecove.so)

дальнейшие поиски показали, что проблема оказалась в компиляторе gcc, настройки по-умолчанию которого отличаются от тех, что используются на моей Raspberry Pi. Для исправления скрипта компиляции bluecove-gpl-2.1.1-SNAPSHOT.jar пришлось сделать следующие изменения

  • <property name=»bluecove.native.linker.options» value=»-nodefaultlibs«/> => <property name=»bluecove.native.linker.options» value=»»/>
  • <arg value=»-Wl,-soname,libbluecove${library_sufix}-${product_version}»/> => <arg value=»-Wl,—no-as-needed,-soname,libbluecove${library_sufix}-${product_version}»/> (—no-as-needed — параметр отвечает за то, чтоб подключать все библиотеки, а не только те, функции которых упомянаются в коде)
  • перестановка строк

<arg value=»-L${libs-universal}»/>
<arg value=»-lbluetooth»/>
<arg line=»${bluecove.native.linker.options}»/>
<arg value=»-Wl,-soname,libbluecove${library_sufix}-${product_version}»/>

=>

<arg value=»-L${libs-universal}»/>
<arg line=»${bluecove.native.linker.options}»/>
<arg value=»-Wl,—no-as-needed,-soname,libbluecove${library_sufix}-${product_version}»/>
<arg value=»-lbluetooth»/>

После этих изменений результат команды ldd становится нужным. Он показывается, что наша новая библиотека зависит от четырёх других so-файлов и больше нет ошибки с неизвестным символом sdp_extract_pdu.

merl1n@merl1n:~/bluecovelib2/dir$ ldd -v -r libbluecove.so
linux-gate.so.1 => (0x0029e000)
libbluetooth.so.3 => /usr/lib/i386-linux-gnu/libbluetooth.so.3 (0x0024b000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x0029f000)
/lib/ld-linux.so.2 (0x00c1f000)
undefined symbol: dlopen (./libbluecove.so)
undefined symbol: dlclose (./libbluecove.so)
undefined symbol: dlsym (./libbluecove.so)

Version information:
./libbluecove.so:
libc.so.6 (GLIBC_2.1.3) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
/usr/lib/i386-linux-gnu/libbluetooth.so.3:
libc.so.6 (GLIBC_2.3) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.7) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.1.3) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.15) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3.4) => /lib/i386-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
/lib/i386-linux-gnu/libc.so.6:
ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2

Тестовая программа тоже запускается без проблем

merl1n@merl1n:~/bluecovelib2$ java -jar bluetooth.jar
BlueCove version 2.1.1-SNAPSHOT on bluez
Local address: 4CEDDE7F40FE
BlueCove stack shutdown completed

Надеюсь, мой опыт был полезен.

Categories: Hard, Soft Tags: , , ,
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.