Работа с Bluetooth в Delphi
Работа с Bluetooth в Delphi
Часть 1
© 2006 Петриченко Михаил,Soft Service Company
Вступление
Этой статьей хочу начать серию по работе с Bluetooth в Delphi под Microsoft Windows XP. Так как тема весьма сложная, прошу внимательно читать. Повторяться не буду.
Все программы написаны на Delphi 6 и тестировались со стандартным стеком Bluetooth от Microsoft под Windows XP + SP2.
Все необходимые библиотеки прилагаются. Так что дополнительно ничего качать не нужно. При разработке использовал только API функции с JEDI.
Описание функций будут даны в стиле Object Pascal. Сионистов просьба обращаться к MSDN и Microsoft Platform SDK.
Получение списка установленных радиомодулей Bluetooth
Итак, для начала попробуем получить список установленных на компьютере радиомодулей Bluetooth.
BluetoothFindFirstRadio - начинает перечисление локальных радиомодулей Bluetooth.
Объявление функции:
const pbtfrp : PBlueToothFindRadioParams;
var phRadio : THandle): HBLUETOOTH_RADIO_FIND; stdcall;
Параметры:
pbtfrp
указатель на структуру BLUETOOTH_FIND_RADIO_PARAMS. Член dwSize этой структуры должен содержать размер структуры (устанавливается посредством SizeOf(BLUETOOTH_FIND_RADIO_PARAMS)).
phRadio
описатель (Handle) найденного устройства.
Возвращаемые значения: ·В случае успешного выполнения функция вернет корректный описатель в phRadio и корректный описатель в качестве результата ·В случае ошибки будет возвращен 0. Для получения кода ошибки используйте функцию GetLastError
BluetoothFindRadio - находит следующий установленный радиомодуль Bluetooth.
Объявление функции:
hFind : HBLUETOOTH_RADIO_FIND;
var phRadio : THandle): BOOL; stdcall;
Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstRadio
phRadio
Сюда будет помещен описатель следующего найденного радиомодуля
Возвращаемые значения: ·Вернет TRUE, если устройство найдено. В phRadio корректный описатель на найденный радиомодуль. ·Вернет FALSE в случае отсутствия устройства. phRadio содержит некорректный описатель. Используйте GetLastError для получения кода ошибки.
BluetoothFindRadioClose - закрывает описатель перечисления радиомодулей Bluetooth.
Объявление функции:
Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstRadio
Возвращаемые значения: ·Вернет TRUE если описатель успешно закрыт. ·Вернет FALSE в случае ошибки. Для получения кода ошибки используйте GetLastError.
Теперь у нас достаточно знаний, чтобы получить список установленных радиомодулей Bluetooth.
Напишем вот такую процедуру:
var
hRadio: THandle;
BFRP: BLUETOOTH_FIND_RADIO_PARAMS;
hFind: HBLUETOOTH_RADIO_FIND;
begin
// Инициализация структуры BLUETOOTH_FIND_RADIO_PARAMS
BFRP.dwSize := SizeOf(BFRP);
// Начинаем поиск
hFind := BluetoothFindFirstRadio(@BFRP, hRadio);
if (hFind <> 0) then
begin
repeat
// Что-то сделать с полученным описателем
// Закрыть описатель устройства
CloseHandle(hRadio);
// Находим следующее устройство
until (not BluetoothFindRadio(hFind, hRadio));
// Закрываем поиск
BluetoothFindRadioClose(hFind);
end;
end;
Это, конечно, все здорово, но в принципе бесполезно. Давайте что-нибудь сделаем еще. Например, получим информацию о радиомодуле Bluetooth.
Получение информации о радиомодуле Bluetooth
Для получения информации о радиомодуле Bluetooth используется функция
BluetoothGetRadioInfo - возвращает информацию о радиомодуле, который представлен описателем.
Объявление функции:
var pRadioInfo : BLUETOOTH_RADIO_INFO): DWORD; stdcall;
Параметры:
hRadio
Описатель локального радиомодуля, который получен функцией BluetoothFindRadioFirst или BluetoothFindRadio
pRadioInfo
Структура, в которую записывается информация об указанном радиомодуле. Член dwSize должен быть равен размеру структуры
Возвращаемые значения: ·Вернет ERROR_SUCCESS если информация получена, в противном случае код ошибки.
Структура BLUETOOTH_RADIO_INFO выгляди вот так:
dwSize : dword;
address : BLUETOOTH_ADDRESS;
szName : array [0..BLUETOOTH_MAX_NAME_SIZE - 1] of widechar;
ulClassofDevice : ulong;
lmpSubversion : word;
manufacturer : word;
end;
dwSize
Размер структуры в байтах
address
Адрес локального радиомодуля
szName
Имя радиомодуля
ulClassofDevice
Класс устройства
lmpSubversion
Устанавливается производителем
manufacturer
Код производителя (константы BTH_MFG_Xxx). Для получения новых кодов обратитесь к сайту спецификаций Bluetooth
Это уже что-то. Воспользуемся этой информацией и напишем вот такую процедуру.
var RadioInfo: BLUETOOTH_RADIO_INFO;
begin
// Инициализация структуры BLUETOOTH_RADIO_INFO
FillChar(RadioInfo, 0, SizeOf(RadioInfo));
RadioInfo.dwSize := SizeOf(RadioInfo);
// Получаем информацию
if (BluetoothGetRadioInfo(hRadio, RadioInfo) = ERROR_SUCCESS) then
begin
// Используем полученную информацию
end;
end;
Заключение
Вот пока и все. В следующей статье рассмотрим, как получить список присоединенных устройств и опросить сервисы, которые они представляют.
Работа с Bluetooth в Delphi
Часть 2
© 2006 Петриченко Михаил,Soft Service Company
Вступление
В первой части статьи мы научились получать список локальных радиомодулей Bluetooth и узнавать их свойства.
Теперь пришло время получить список устройств Bluetooth, которые подключены к нашим локальным радиомодулям.
Получение списка устройств Bluetooth
Для получения списка устройств Bluetooth нам понадобятся следующие функции (они очень похожи на функции, используемые для получения списка локальных радиомодулей).
BluetoothFindFirstDevice - начинает перечисление устройств Bluetooth.
Объявление функции:
const pbtsp : BLUETOOTH_DEVICE_SEARCH_PARAMS;
var pbtdi : BLUETOOTH_DEVICE_INFO): HBLUETOOTH_DEVICE_FIND; stdcall;
Параметры:
Pbtsp
Указатель на структуру BLUETOOTH_DEVICE_SEARCH_PARAMS. Член dwSize этой структуры должен содержать размер структуры (устанавливается посредством SizeOf(BLUETOOTH_DEVICE_SEARCH_PARAMS)). Член hRadio должен содержать описатель локального радиомодуля, полученный вызовом функции BluetoothFindFirstRadio.
Pbtdi
Структура BLUETOOTH_DEVICE_INFO в которую будет возвращена информации об устройстве Bluetooth.
Возвращаемые значения: ·В случае успешного выполнения функция вернет корректный описатель в качестве результата. ·В случае ошибки будет возвращен 0. Для получения кода ошибки используйте функцию GetLastError
BluetoothFindDevice - находит следующее устройство Bluetooth.
Объявление функции:
var pbtdi : BLUETOOTH_DEVICE_INFO): BOOL; stdcall;
Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstDevice
pbtdi
Структура BLUETOOTH_DEVICE_INFO, в которую будет помещена информацию об устройстве
Возвращаемые значения: ·Вернет TRUE, если устройство найдено. ·Вернет FALSE в случае отсутствия устройства. Используйте GetLastError для получения кода ошибки.
BluetoothFindDeviceClose - закрывает описатель перечисления устройств Bluetooth.
Объявление функции:
Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstDevice
Возвращаемые значения: ·Вернет TRUE если описатель успешно закрыт. ·Вернет FALSE в случае ошибки. Для получения кода ошибки используйте GetLastError.
BluetoothGetDeviceInfo - возвращает информацию об указанном устройстве Bluetooth.
Объявление функции:
var pbtdi : BLUETOOTH_DEVICE_INFO): DWORD; stdcall;
Параметры:
hRadio
Описатель локального радиомодуля Bluetooth
pbtdi
Структура BLUETOOTH_DEVICE_INFO, в которую возвразается информация об устройстве. dwSize должен быть равен размеру структуры. addreess должен содержать адрес устройства, о котором хотим получить информацию.
Возвращаемые значения: ·Вернет ERROR_SUCCESS если выполнено успешно и информация занесена в структуру pbtdi. Остальные значения – код ошибки.
Обладая этими знаниями, можно написать процедуру получения информации об устройствах Bluetooth:
var
DeviceInfo: PBLUETOOTH_DEVICE_INFO;
DeviceSearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS;
DeviceFind: HBLUETOOTH_DEVICE_FIND;
begin
// Инициализация структуры BLUETOOTH_DEVICE_SEARCH_PARAMS
with DeviceSearchParams do
begin
dwSize := SizeOf(BLUETOOTH_DEVICE_SEARCH_PARAMS);
fReturnRemembered := true; // Вернуть запомненные
hRadio := _hRadio;
end;
// Инициализация структуры BLUETOOTH_DEVICE_INFO
FillChar(DeviceInfo, SizeOf(BLUETOOTH_DEVICE_INFO), 0);
DeviceInfo.dwSize := SizeOf(PBLUETOOTH_DEVICE_INFO);
// Начинаем поиск
DeviceFind := BluetoothFindFirstDevice(DeviceSearchParams, DeviceInfo);
if (DeviceFind <> 0) then begin
repeat
// Что-то сделать с полученными данными
// Инициализация структуры BLUETOOTH_DEVICE_INFO
FillChar(DeviceInfo, SizeOf(BLUETOOTH_DEVICE_INFO), 0);
DeviceInfo.dwSize := SizeOf(PBLUETOOTH_DEVICE_INFO);
// Находим следующее устройство
until (not BluetoothFindDevice(DeviceFind, DeviceInfo));
// Закрываем поиск
BluetoothFindDeviceClose(DeviceFind);
end;
end;
Заключение
Пока все. В следующей части рассмотрим способы получения информации о сервисах, предоставляемых устройствами Bluetooth.
Работа с Bluetooth в Delphi
Часть 3
© 2006 Петриченко Михаил,Soft Service Company
Вступление
И так, в предыдущих частях мы научились получать список локальных радиомодулей Bluetooth и удаленных устройств Bluetooth. Нам осталось научиться получать список сервисов, предоставляемых удаленным устройством и управлять локальными радиомодулями. Так же, необходимо разобраться, как же все-таки передаются данные между различными устройствами Bluetooth.
В этой части, а она будет самой длинной и информативной, мы создадим программу, которая поможет нам обобщить полученную информацию и покажет, как использовать новые функции, которые здесь будут описаны.
Прежде, чем мы приступим, давайте определимся в терминах. Microsoft в своей документации вводит два термина: Radio и Device. Radio – это локальный радиомодуль Bluetooth (USB-брелок, интегрированное решение, в общем то, что установлено на вашем компьютере). Device – это то устройство Bluetooth с которым вы хотите обмениваться информацией. Будь то телефон, КПК, гарнитура или еще что-то. Важно понимать, что если мы пишем программу для PDA, то когда она работает на PDA - его модуль Bluetooth будет Radio, а компьютер - Device. Если же она работает на компьютере, то компьютерный модуль – Radio, а PDA – Device.
Что мы знаем
К сожалению, документация Microsoft по Bluetooth API и работе с Bluetooth настолько скудна (у меня получилось 50 страниц в Word с оформлением), а примеров они вообще не предоставляют, что из нее очень трудно понять, как же все-таки работает эта технология.
Когда я только начинал изучать этот предмет, я перерыл весь Internet, но так ничего вразумительного не нашел.
По-этому, здесь мне хочется дать наиболее полную и подробную информацию об этом вопросе, что бы вы не столкнулись с той же проблемой отсутствия информации.
И так, приступим.
Создание проекта
Давайте создадим в Delphi новый проект и сохраним его под именем BTWork, а модуль – под именем Main.
Главную и пока единственную форму, назовем fmMain. Заголовок BTWork.
Теперь нам понадобятся файл JwaBluetoothAPI.pas, JwaBtHDef.pas и JwaBthSdpDef.pas. Их можно найти в примерах из предыдущих частей или в библиотеке BTClasses.
Для того, чтобы не тянуть с собой все остальные файлы из JWA, давайте эти чуть-чуть исправим. Найдите в них строку
usesJwaWindows
и замените JwaWindows на Windows.
Далее удалить из них строки
{$HPPEMIT ''}
{$HPPEMIT '#include "bluetoothapis.h"'}
{$HPPEMIT ''}
{$I jediapilib.inc}
И в файле JwaBluetoothAPI удалите все, что находится между {$IFDEF DYNAMIC_LINK} и {$ELSE} вместе с этими DEF. И в конце этого файле удалите {$ENDIF}.
Далее, в JwaBluetoothAPI.pas после
implementationusesJwaWinDLLNames;
Напишите
constbtapi = 'irprops.cpl';
Да простят нас ребята, которые эту библиотеку писали!
Все эти действия я делал для того, что бы уменьшить архив примера. Да и не нужно тянуть за собой много лишнего. Хотя сама библиотека весьма полезна. Один модуль JwaWindows чего стоит. Там очень много интересного есть. Ну да ладно – что-то я отвлекся.
После того, как мы кастрировали эти модули, давайте добавим их в наш проект. Готово?
В этом приложении мы будем получать список локальных радиомодулей, устройств, к ним присоединенных, список сервисов, предоставляемых устройствами. Также мы должны управлять радиомодулями и научиться проходить авторизацию.
Приступаем.
Оформление главной формы
На главную форму поместим компонент TPanel и установите следующие свойства:
Свойство
Значение
Align
al
Caption
Name
Panel
Далее поместим компонент TTreeView и установите свойства как в таблице:
Свойство
Значение
Align
alLeft
Cursor
crHandPoint
HideSelection
False
HotTrack
True
Name
TreeView
ReadOnly
True
Отправить комментарий