Работа с 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.
Объявление функции:

function BluetoothFindFirstRadio(

  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.
Объявление функции:
function BluetoothFindRadio(

  hFind : HBLUETOOTH_RADIO_FIND;

  var phRadio : THandle): BOOL; stdcall;

Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstRadio
phRadio
Сюда будет помещен описатель следующего найденного радиомодуля
Возвращаемые значения: ·Вернет TRUE, если устройство найдено. В phRadio корректный описатель на найденный радиомодуль. ·Вернет FALSE в случае отсутствия устройства. phRadio содержит некорректный описатель. Используйте GetLastError для получения кода ошибки.
BluetoothFindRadioClose - закрывает описатель перечисления радиомодулей Bluetooth.
Объявление функции:
function BluetoothFindRadioClose(hFind : HBLUETOOTH_RADIO_FIND): BOOL; stdcall;

Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstRadio
Возвращаемые значения: ·Вернет TRUE если описатель успешно закрыт. ·Вернет FALSE в случае ошибки. Для получения кода ошибки используйте GetLastError.
Теперь у нас достаточно знаний, чтобы получить список установленных радиомодулей Bluetooth.
Напишем вот такую процедуру:
procedure EnumRadio;

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 - возвращает информацию о радиомодуле, который представлен описателем.
Объявление функции:
function BluetoothGetRadioInfo(hRadio : THandle;

  var pRadioInfo : BLUETOOTH_RADIO_INFO): DWORD; stdcall;

Параметры:
hRadio
Описатель локального радиомодуля, который получен функцией BluetoothFindRadioFirst или BluetoothFindRadio
pRadioInfo
Структура, в которую записывается информация об указанном радиомодуле. Член dwSize должен быть равен размеру структуры
Возвращаемые значения: ·Вернет ERROR_SUCCESS если информация получена, в противном случае код ошибки.
Структура BLUETOOTH_RADIO_INFO выгляди вот так:
_BLUETOOTH_RADIO_INFO = record

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
Это уже что-то. Воспользуемся этой информацией и напишем вот такую процедуру.
procedure GetRadioInfo(hRadio: THandle);

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.
Объявление функции:
function BluetoothFindFirstDevice(

  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.
Объявление функции:
function BluetoothFindDevice(hFind : HBLUETOOTH_DEVICE_FIND;

  var pbtdi : BLUETOOTH_DEVICE_INFO): BOOL; stdcall;

Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstDevice
pbtdi
Структура BLUETOOTH_DEVICE_INFO, в которую будет помещена информацию об устройстве
Возвращаемые значения: ·Вернет TRUE, если устройство найдено. ·Вернет FALSE в случае отсутствия устройства. Используйте GetLastError для получения кода ошибки.
BluetoothFindDeviceClose - закрывает описатель перечисления устройств Bluetooth.
Объявление функции:
function BluetoothFindDeviceClose(hFind : HBLUETOOTH_DEVICE_FIND): BOOL; stdcall;

Параметры:
hFind
Описатель, который вернула функция BluetoothFindFirstDevice
Возвращаемые значения: ·Вернет TRUE если описатель успешно закрыт. ·Вернет FALSE в случае ошибки. Для получения кода ошибки используйте GetLastError.
BluetoothGetDeviceInfo - возвращает информацию об указанном устройстве Bluetooth.
Объявление функции:
function BluetoothGetDeviceInfo(hRadio : THandle;

  var pbtdi : BLUETOOTH_DEVICE_INFO): DWORD; stdcall;

Параметры:
hRadio
Описатель локального радиомодуля Bluetooth
pbtdi
Структура BLUETOOTH_DEVICE_INFO, в которую возвразается информация об устройстве. dwSize должен быть равен размеру структуры. addreess должен содержать адрес устройства, о котором хотим получить информацию.
Возвращаемые значения: ·Вернет ERROR_SUCCESS если выполнено успешно и информация занесена в структуру pbtdi. Остальные значения – код ошибки.
Обладая этими знаниями, можно написать процедуру получения информации об устройствах Bluetooth:
procedure GetDevices(_hRadio: THandle);

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.
Далее удалить из них строки
{$WEAKPACKAGEUNIT}

{$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

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...