Използване на Java Bluetooth API (JSR-82)
Bluetooth е безжична технология разработена през 1994г., която предоставя
възможност за изграждане на ad-hoc мрежи с радиус на действие от 10см до 100м.
Обхватът зависи от мощността на предавателя:
· Клас 1: мощност 100mW (20dBm), обхват 100m и повече;
· Клас 2: мощност 2.5mW (4dBm), обхват до 10 m;
· Клас 3: мощност 1mW (0dBm), обхват до 1m.
Чрез Bluetooth могат да бъдат изграждани ad-hoc мрежи, наричани пикомрежи
(piconet). Всяка пикомрежа се състои от едно водещо обмена устройство (master) и
до 7 подчинени устройства (slaves). Всяко главно устройство предлага една или
повече услуги, които стават достъпни за участниците в пикомрежата. Стандартът
допуска едно подчинено устройство да стане водещо при условие, че в даден
момент в пикомрежата има само едно главно устройство. С цел увеличаване на
участниците в Bluetooth мрежата е възможно обединяването на няколко
пикомрежи в една мрежа - scaternet. Bluetooth комуникациите могат да бъдат от
тип point-to-point (едно главно и едно подчинено устройство) или point-to-multipoint
(едно главно и множество подчинени устройства).
Java Bluetooth API (JSR-82)
Спецификацията JSR-82 (Java API for Bluetooth Wireless Technology) предлага
необходимите класове и интерфейси за реализиране на безжични комуникации
между Bluetooth устройства. Протоколите, които спецификацията JSR-82 поддържа,
са: RFCOMM, L2CAP, SDP и OBEX, като последният не е задължително да се
имплементира. Профилите, които задължително се поддържат, са: Generic Access
Profile (GAP), Service Discovery Profile (SDP) и Serial Port Profile (SPP).
Bluetooth API се реализира чрез два пакета:
· javax.bluetooth;
· javax.obex.
Получаване на характеристиките на Bluetooth модула
Поради голямото разнообразие на Bluetooth модули е възможно различие в техните
характеристики. Те могат да бъдат получени програмно чрез използване на метод
getProperty от клас LocalDevice. Методът връща null, ако зададената като
параметър характеристика не се поддържа, или низ, описващ нейната стойност.
Проверка за наличие на Bluetooth API
Преди да се използват методите на тази API, е необходимо да се провери за
нейното наличие. Това програмно може да се реализира по следният начин:
try {
Class.forName(javax.bluetooth.LocalDevice);
// Bluetooth API е налична
catch (ClassNotFoundException e) {
// Мобилният терминал не поддържа Bluetooth API
}
Проверка дали Bluetooth модулът е включен
Проверката може да се реализира като се направи опит да се създаде обект от
клас
DiscoveryAgent, който в последствие ще бъде необходим за претърсване на
ефира за Bluetooth устройства и за получаване на услугите, които те предоставят:
try {
LocalDevice ld = LocalDevice.getLocalDevice();
DiscoveryAgent da = ld.getDiscoveryAgent();
// Bluetooth модула е включен
catch (BluetoothStateException e) {
// Bluetooth модула е изключен
}
Получаване на характеристиките на Bluetooth модула
Понякога се налага програмното осигуряване да се адаптира към характеристиките
на Bluetooth модула, например: оптималният размер на пакета при L2CAP
комуникация е стойността на параметър
bluetooth.l2cap.receiveMTU.max . На
този етап от алгоритъма може да се получи и физическият адрес на модула:
String propertyValue = LocalDevice.getProperty( име на характеристиката);
String btAddress = LocalDevice.getLocalDevice().get BluetoothAddress();
Търсене на Bluetooth устройства (device discovery)
В даден момент едно Bluetooth устройство може да се регистрира динамично към
коя да е пикомрежа. Това налага възможността за търсене на нови устройства. Те се
разпознават по своя 48-битов физически адрес.
· Откриването на устройствата зависи от настройките им за работа в този
режим (device discovery):
LocalDevice ld = LocalDevice.getLocalDevice();
ld.setDiscoverable(DiscoveryAgent.GIAC);
Ако адресът на устройството е известен и до този момент не е било адресирано
търсенето се реализира чрез метод
startInquiry от клас DiscoveryAgent.
Мотодът
startInquiry не блокира работата на нишката от тялото на която е
извикан.
Следва пример за търсене на устройства чрез метод
startInquiry.
LocalDevice ld = LocalDevice.getLocalDevice();
DiscoveryAgent da = ld.getDiscoveryAgent();
int inquiryStatus;
try {
da.startInquiry(DiscoveryAgent.GIAC, this);
catch (BluetoothStateException e) {
// не може да се стартира търсенето на устройства
}
// Изчаква се да бъдат открити всички устройства (да се извика метод
inquiryCompleted)
synchronized(this) {
try {
wait();
catch(Exception e) {}
}
// Метод deviceDiscovered: вика се за всяко открито устройство
public void deviceDiscovered(RemoteDevice rd, DeviceClass dc) {
// Буфериране на обекти
rd и dc, носещи информация за текущо откритото устройство
}
// Метод
inquiryCompleted: край на процеса на търсене на устройства
public void inquiryCompleted(int status) {
inquiryStatus = status;
synchronized(this) {
notify();
}
}
Чрез метод
inquiryCompleted се получава информация как е завършил проце-
сът на търсене - параметър
status. Той може да има една от следните стойности:
·
DiscoveryListener.INQUIRY_COMPLETED - нормално завършване на про-
цеса на търсене;
·
DiscoveryListener.INQUIRY_TERMINATED - процесът на терсене е бил
прекъснат;
DiscoveryListener.INQUIRY_ERROR - възникнала е грешка по време на процеса
на търсене.
Филтриране на намерените устройства
В обхвата на мобилния терминал може да има множество Bluetooth устройства, а
клиентът да се нуждае само от конкретна услуга, предлагана от конкретно
устройство.
Информацията за всяко открито Bluetooth устройство се съдържа в обекти
rd и
dc, които се предават като параметри на метод deviceDiscovered. В тялото на
този метод може да се интегрира логика за филтриране на откритите устройства, с
цел отстраняване на тези от които не се интересуваме. Филтрирането се реализира
чрез анализ на класа на устройството - обект
dc. Може да се реализира и чрез името
на устройството, което се получава посредством метод
getFriendlyName от клас
RemoteDevice, например:
String name = rd.getFriendlyName();
Информацията за класа на устройството е с размер 3 октета (24 бита) и е
разделена на 3 полета:
23 13 12 8 7 2 1 0
Service Class Major Device Class Minor Device Class 0 0
Mетоди за извличане на стойностите на отделните полета
getServiceClasses getMajorDeviceClass getMinorDevic eClass
Параметър GPS приемник
Име Nokia LD-3W
Поле Service Class 0x10000 ( Позициониране)
Поле Major Device Class 0x1F00 (няма валиден код)
Поле Minor Device Class 0 (няма валиден код)
Търсене на услуги (service discovery)
След като желаното устройство бъде открито се активира процес на търсене на
услугите, които то предлага. За целта се използва метод
searchServices от клас
DiscoveryAgent:
int transId = da.searchServices(int[] attr, UUID[] searchList,
DiscoveryListener listener);
Търсените услуги се идентифицират по два начина: чрез списък от атрибути,
предавани като първи параметър, и чрез списък от идентификационни кодове,
предавани като втори параметър.
Следва пример за реализиране на търсене на услуги, които използват протокол
RFCOMM (профил SPP):
// Обектът rd е получен след успешно търсене на устройства. Той идентифицира
// устройството, от чиито услуги се нуждаем
try {
int transId = da. searchServices(null, searchList, rd, this);
} catch(BluetoothStateException e) {
// не може да се стартира търсенето на услуги
}
// Изчакване, докато бъдат открити всички услуги
synchronized(this) {
try {
wait();
} catch(Exception e) {}
}
// Метод
serviceDiscovered: вика се при откриване на услуга
public void serviceDiscovered(int number, ServiceRecord[] sr) {
// Буфериране на всички (
number на брой) услуги, които са описани чрез
// масив
sr (масив от обекти от клас ServiceRecord)
}
// Метод
serviceSearchCompleted : вика се при откриване на всички услуги за дадено
// устройство. Ако са стартирани множество търсения, методът се вика
// за всяко едно от тях
public void serviceSearchCompleted (int transaction, int respCode) {
// Край на търсенето на услуги за устройство с идентификатор
transaction
// (трябва да съвпада по стойност с променлива
transId, получена от метод searchServices)
synchronized(this) {
notify();
}
}
Най-важната информация, която един обект от тип ServiceRecord (sr) съдър-
жа е URL чрез който се получава достъп до желаната услуга:
String url = sr.getConnectionURL(0, false);
В конкретният случай се указва да не се изисква проверка на автентичността на
клиента и да не се шифрира трафика (първи параметър) и, че устройството може да
бъде както подчинено, така и водещо (втори параметър). Стойностите, които се
връщат за URL за GPS приемника Nokia LD-3W, са:
btspp://000276FD55A3:1;authenticate=false;encrypt=f alse;master=false
Използване на открита услуга
След получаване на URL за достъп до желаната услуга, може да се реализира
комуникацията между клиента и сървъра. Алгоритъмът за тази комуникация зависи
от адресираната услуга. За реализацията му се използват вече изучените Java
методи за работа с входно-изходни канали.
Задача за изпълнение:
Да се напише мидлет, който реализира достъп до кой да е GSP приемник с
Bluetooth
интерфейс и визуализира на екрана на мобилния терминал следната
информация:
·
параметрите на Bluetooth модула на мобилния терминал;
·
всички открити Bluetooth устройства (device inquiry);
·
поддържаните услуги от избрано отдалечено устройство.
O
т GPS приемника:
·
брой на видимите сателити;
·
географска ширина [° ¢ ²];
·
географска дължина [° ¢ ²];
·
височина, [m];
·
скорост на движение, [km/h];
·
курс [градуси] и с думи (N, E, S, W, NE, SE, ..., NW);
·
наименование на поддържаните NMEA съобщения.
0 коментара
За да коментирате, трябва да сте влезли в профила си.
Влезте