Delphi і Bluetooth. Частина 4 (исходники), Різне, Програмування, статті

Частина 1 :: Частина 2 :: Частина 3 

Вступ


Нарешті я добрався і до заключної, як я сподіваюся, частини статті про Bluetooth.


Тут я постараюся викласти в доступній формі, як же все-таки передавати дані через Bluetooth. Я не буду приводити тут якихось готових прикладів додатків. Дам лише теорію. До практики, я думаю, ви перейдете самі.


Як ви пам’ятаєте з попередніх моїх статей, ми використовуємо виключно Windows API для роботи з Bluetooth. Відразу хочу обмовитися, що описані тут способи не будуть працювати з драйверами BlueSoliel і VIDCOMM. В кінці статті я розповім, як встановити драйвера від Microsoft, якщо ви це ще не зробили.


Отже, приступаємо.


Що ви повинні знати


Перш ніж почати викладати основний матеріал, я хочу сформулювати вимоги до ваших знань.


Ви повинні розуміти роботу з мережами в Microsoft Windows і знати терміни і визначення, дані мною в попередніх статтях. Я буду часто відсилати до пройденого матеріалу, що б не повторюватися.


Ви також повинні більш-менш розбиратися в технології Winsock.


Bluetooth і Winsock


Як не дивно це звучить, але Microsoft вирішила реалізувати всю функціональність з передачі даних за допомогою Windows Socket Model. Тим, хто писав щось для IrDA це має здатися знайомим.


На мій погляд – правильне рішення. Навіщо город городити, коли вже є перевірені засоби.


Я не буду описувати тут всі правила застосування функцій WinSock до роботи з Bluetooth. Зупинюся лише на практичній стороні питання. А саме – передача даних.


У статті ми зробимо простенький Bluetooth-клієнт, який буде приєднуватися до віддаленого пристрою як до модему і дозволить вам виконувати AT-команди. Дуже корисна річ. Врахуйте, що даний клієнт буде вимагати авторизації пристроїв і не буде вимагати наявності в системі будь-яких віртуальних COM-портів.


Сервіси та профілі


Сервіси та профілі … Це два наріжних поняття Bluetooth. У певному сенсі – вони ідентичні.


Сервіс – Додаток-сервер, який реєструє певним чином параметри в стеці протоколів Bluetooth. Найменування (GUID) всіх сервісів строго визначені Bluetooth.org.


Профіль – Угоди і стандарти роботи сервісу. Зрозуміліше пояснити не зможу.


Початок


І так, перш ніж можна буде використовувати бібліотеку WinSock, її необхідно ініціалізувати. Робиться це викликом функції WSAStartup. Ось як вона виглядає:


function WSAStartup(
    wVersionRequired: Word;
var lpWSAData:        WSAData): Integer; stdcall;


Не буду описувати всі параметри, так як вони є в будь-довідкової системі (MSDN, Delphi). Скажу тільки, що для використання WinSock з Bluetooth необхідно вказати як параметр wVersionRequired номер версії $0202.


Ось як виглядає виклик цієї функції:


var
  Data: WSADATA;
begin
  if WSAStartUp($0202, Data) <> 0 then
    raise Exception.Create(‘Winsock Initialization Failed.’);


По закінченню роботи з WinSock бібліотеку необхідно звільнити. Для цього існує функція WSACleanup.


function WSACleanup: Integer; stdcall;


Викликається вона просто, без всяких параметрів. Значення, що повертається, в принципі, можна не перевіряти:


begin
  WSACleanup;


Створення клієнта


Після того, як бібліотека инициализирована, ми можемо викликати функції WinSock. Давайте створимо простий сокет, для роботи з Bluetooth пристроями. Для цього необхідно викликати функцію socket.


function socket(af, type_, protocol: Integer): TSocket; stdcall;


Ось як це робиться:


var
  ASocket: TSocket;
begin
  ASocket := socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
  if ASocket = INVALID_SOCKET then RaiseLastOsError;


Функція поверне коректний описувач сокета, або INVALID_SOCKET у разі помилки. Запам’ятайте, Що Bluetooth підтримує тільки потокові сокети (SOCK_STREAM).


Далі нам необхідно заповнити структуру SOCKADDR_BTH. У цю структуру записується інформація про сервер, до якого нам потрібно підключитися (адреса, сервіс і т.п.). Робиться це в такий спосіб:


var
  Addr: SOCKADDR_BTH;
  AddrSize: DWORD;
begin
  AddrSize := SizeOf(SOCKADDR_BTH);
  FillChar(Addr, AddrSize, 0);


  with Addr do begin
    addressFamily := AF_BTH;
    btAddr := ADeviceAddress;
    serviceClassId := SerialPortServiceClass_UUID;
    port := DWORD(BT_PORT_ANY);
  end;


Тут у змінній ADeviceAddress повинен бути адреса пристрою (Int64), Приєднуємося до будь-якого порту (BT_PORT_ANY) Сервісу SerialPortServiceClass.


Далі викликаємо функцію connect, яка має вигляд:


function connect(s: TSocket; name: PSockAddr; namelen: Integer): Integer; stdcall;


Робиться це ось так:


begin
  if connect(ASocket, @Addr, AddrSize) <> 0 then RaiseLastOsError;


Якщо функція виконається успішно, поверне 0, в іншому випадку відмінне від нуля значення.


Після того, як з’єднання встановлено, можна надсилати та отримувати дані через сокет функціями send і recv.


function send(s: TSocket; var buf; len, flags: Integer): Integer; stdcall;
function recv(s: TSocket; var buf; len, flags: Integer): Integer; stdcall;


Функції повертають кількість переданих або прийнятих байт в разі успіху і негативне число у разі помилки. Кількість переданих або прийнятих байт може бути менше, ніж зазначена в параметрі len довжина буфера. Тоді вам потрібно повторити передачу / прийом залишилися байт.


Ну і закриття сокета здійснюється викликом функції closesocket:


function closesocket(s: TSocket): Integer; stdcall;


Знову ж таки, повертається значення можна проігнорувати (якщо ви знаєте, що робите).


Загалом те, вищевказаний матеріал не представляє нічого нового для тих, хто хоч раз програмував під WinSock. Єдине, на що слід звернути увагу, це нові константи AF_BTH і BTHPROTO_RFCOMM.


Створення сервера


Як і створення клієнта, створення сервера нічим не відрізняється від створення сервера для будь-якої служби WinSock.


І так, почнемо. Сокет створюється також як і в наведеному вище прикладі для клієнта. Точно також заповнюємо структуру Addt: SOCKADDR_BTH. Тільки в якості адреси пристрою вказуємо 0. Далі, необхідно прив’язати сокет до адреси. Робиться це функцією bind:


function bind(s: TSocket; name: PSockAddr; namelen: Integer): Integer; stdcall;


Яка викликається наступним чином:


begin
  if Bind(ASocket, @Addr, AddrSize) <> 0 then RaiseLastOsError;


Далі викликаємо функцію listen, для того щоб сервер почав прослуховувати сокет на предмет підключення клієнтів і функцію accept для прийому вхідного підключення:


function listen(s: TSocket; backlog: Integer): Integer; stdcall;
function accept(s: TSocket; addr: PSockAddr; addrlen: PINT): TSocket; stdcall;


Робиться це ось так:


var
  AClientSocket: TSocket;
begin
  if listen(ASocket, 10) <> 0 then RaiseLastOSError;
  AClientSocket = accept(ASocket, nil, nil);


Після підключення клієнта можна працювати з AClientSocket – Передавати і приймати дані.


Якщо ви не бажаєте більше приймати вхідні підключення, закрийте слухає сокет.


Що залишилося за кадром


Як і обіцяв, я коротко описав процедури, необхідні для побудови простого клієнта і сервера, які будуть працювати з Bluetooth через WinSock.


Однак, тут я не розглядав питання реєстрації сервісів і протоколи верхнього рівня.


Наведеної тут інформації достатньо для того, що б ви могли створити додаток клієнт, яке з’єднається з ваші телефоном по Bluetooth і зможе виконувати AT-команди.


Більш повну інформацію і робочі приклади можна знайти тут: www.btframework.com.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*