Связь

Инфракрасное соединение

Несмотря на растущую популярность Wi-Fi, Bluetooth и других беспроводных технологий, по-прежнему не сдает своих позиций и передача данных через инфракрасный порт. Например, все мы каждый день применяем инфракрасный порт при использовании дистанционного пульта телевизора! Вы можете использовать этот способ работы в своих приложениях для передачи разных типов данных.

Так как в этой технологии для передачи данных используется свет, то необходимо прямое соединение устройств, чтобы между ними не было препятствий. Несмотря на подобное ограничение, соеди­нение через инфракрасный порт по-прежнему широко использу­ется в цифровых камерах, КПК и ноутбуках. В этой главе будет показано, как использовать инфракрасный порт при помощи клас­са IrDAClient, входящего в библиотеку классов. NET Compact Frame­work.

История и теория

Основанная в 1993 году как некоммерческая организация, Ассо­циация инфракрасной передачи данных (Infrared Data Association, или сокращенно IrDA) является международной ассоциацией (www. irda. org), создающей и продвигающей стандарты инфракрас­ной связи, позволяющие пользователям соединять устройства для передачи данных. Стандарты Infrared Data Association поддержи­вают огромное число устройств. На данный момент существует несколько версий технологии IrDA, которые различаются скоро­стью передачи данных

Протокол IrDA позволяет соединяться с другим устройством без проводов при помощи ИК-излучения. Порт IrDA позволяет уста­навливать связь на расстоянии до 1-2 метров. Интерфейс IrDA предполагает малую мощность потребления, что позволяет созда­вать недорогую продукцию.

Класс IrDAClient

Практически все устройства под управлением Windows Mobile име­ют встроенные инфракрасные порты. Библиотека. NET Compact Framework имеет в своем составе классы, позволяющие работать с инфракрасной связью.

Инфракрасная связь осуществляется между двумя устройствами по принципу «сервер-клиент». Устройство, работающее как сервер, предлагает другому компьютеру установить связь для передачи дан­ных через инфракрасный порт. Для осуществления передачи необ­ходимо передать идентификатор устройства и имя устройства. Кли­ент ждет вызова необходимой службы и откликается на ее запрос, В результате между двумя компьютерами устанавливается связь.

За инфракрасное соединение отвечает специальный класс I rDACl і ent, который может выступать и в роли сервера, и в роли клиента. Дан­ный класс входит в библиотеку System. Net. IrDA. dlL Таким образом, при использовании класса I rDACl lent необходимо добавить в проект ссылку на указанную библиотеку.

Для чтения и передачи данных используется метод GetStream, рабо­тающий с основным потоком данных. Компьютер-клиент должен знать имя устройства, с которым нужно установить связь. Програм­ма может поочередно опросить все доступные устройства и выбрать нужное устройство для связи. Алгоритм подключения устройства к инфракрасному порту другого устройства приведен далее.

1. Создать новый экземпляр класса I rDACl і ent.

2. Получить список доступных устройств с помощью метода IrDAClient. DiscoverDevices. Можно ограничить количество оп­рашиваемых устройств при помощи параметра maxDevices. Ме­тод DiscoverDevices возвращает массив объектов IrDADevicelnfo.

3. Нужно исследовать каждый объект IrDADevicelnfo из получен­ного массива, чтобы найти необходимое устройство для связи.

4. Если подобное устройство найдено, то при помощи метода IrDAClient Connect производится соединение. При этом необхо­димо указать имя службы

Создание программы д ля работы с ИК-связью

В этом разделе будет создано приложение, которое будет соединять­ся с другим устройством и пересылать ему текстовый файл. Прежде всего нужно создать новый проект IrDA CS. На форме надо размес­тить три кнопки, список и строку состояния.

Кнопка butFindDevs предназначена для поиска устройств, кнопка butSend — для отправки текстового сообщения, а кнопка butRecei ve служит для приема сообщения. В списке 1 і stBoxl будет отображать­ся информация об обнаруженных устройствах, а в строке состояния будут отображаться сообщения о производимых операциях. Для пе­редачи данных и работы с файлами нам необходимо импортировать несколько пространств имен, как это показано в листинге 12.1.

Листинг 12.1

Imports System. Net Imports System.10 Imports System. Net. Sockets

Для работы с инфракрасной связью необходимо подключить к про­екту класс I rDACl і ent. Для этого выполним команду меню Project ► Add Reference и в диалоговом окне выберем пункт System. Net Л rDa.

Теперь нужно объявить переменные на уровне класса, как показа­но в листинге 12.2

Листинг 12.2

private IrDAListener irListen: private IrDAClient irClient; private IrDAEndPoint irEndP; private IrDADeviceInfo[] irDevices:

string fileSend; string fileReceive; string irServiceName;

int buffersize;

В конструкторе формы надо создать экземпляр класса IrDAClient, задать имена файлов для приема и отправки сообщения, указать имя службы, установить размер буфера для передаваемого файла и так­же временно сделать недоступными кнопки для отправки и посылки сообщения. Соответствующий код приведен в листинге 12.3.

Листинг 12.3

public FormlO

^……. „……. . ,ч продолжение &

ImtіalіzeComponent();

Листинг 12.3 (продолжение)

irClient = new I rDACl і ent О;

// Файлы, предназначенные для отправки и приема fileSend = ”.\Му DocumentsWsend. txt": fileReceive = ”.\Му DocumentsWreceive. txt":

// Задаем имя для службы IrDA // Это может быть любое слово

// Другие устройства для примера должны использовать это же // слово

irServiceName = "IrDAFtp":

// Устанавливаем максимальный размер буфера для передаваемого // файла

buffersize = 256:

// Делаем недоступными кнопки отправки и посылки сообщений // до тех пор. пока не будут обнаружены устройства butSend. Enabled — false: butReceive. Enabled = false:

}

Обнаружение устройств

Теперь надо написать код для кнопки butFindDevs, предназначен­ной для обнаружения устройств. При тестировании примера не­обходимо направить инфракрасные порты устройств друг на дру­га. Код, ответственный за выполнение этой задачи, приведен в листинге 12.4.

Листинг 12.4

private void butFindDevs Click(object sender. EventArgs e)

{

// Ищем доступные устройства с инфракрасной связью // и помещаем их в список // Поиск не более трех доступных устройств irDevices = irClient. DiscoverDevices(2):

// Если устройства не найдены, то выводим сообщение if (irDevices. Length — 0)

{

MessageBox. Show("Устройства с ИК-портами не обнаружены!"): return:

}

// Перечисляем массив IrDADevicelnfo

// и выводим информацию о каждом устройстве в список

string device;

int ID;

listBoxl. Items. ClearO;

foreach (IrDADevicelnfo irDevice in irDevices)

{

ID = BitConverter. Тоїnt32(irDevice. DevicelD, 0); device = ID. ToStringO + " " + irDevice. DeviceName + " "

+ irDevice. CharacterSet + " " + irDevice. Hints;

1 і stBoxl. Iterns. Add(device);

}

1 іstBoxl. Selectedlndex = 0; if (irDevices. Length > 0) statusBarl. Text = irDevices. Length. ToStringO + ” устройств(а)";

// Делаем доступными кнопки для отправки и посылки сообщения butSend. Enabled = true; butReceive. Enabled = true;

}

Передача данных

Код для отправки и посылки файлов приведен в листинге 12.5.

Листинг 12.5

private void butSendCl ick (object sender, EventArgs e)

{

// Открываем файл для отправки и получаем его поток

Stream fileStream;

try

{

fileStream = new FileStream(fileSend, FileMode. Open);

}

catch (Exception exFile)

{

MessageBox. ShowC’He могу открыть " + exFile. ToStringO); return:

>

// Создаем IrDA-клиент с установленным именем службы,

продолжение &

Листинг 12.5 (продолжение)

II которое должно совпадать с именем службы на другом

// IrDA-клиенте

try

{

irClient = new IrDAClient(irServiceName);

}

catch (SocketException exS)

{

MessageBox. Show("Ошибка сокета: " + exS. Message +

" — Вы щелкнули на кнопке Получить на другом устройстве?"): return:

}

// Получим поток

Stream baseStream = irClient. GetStreamO;

// Получим размер отправляемого файла // и запишем это значение в поток byte[] length =

Bi tConverter. GetBytes((і nt)fі 1eStream. Length); baseStream. Write(length, 0, length. Length):

// Создаем буфер для чтения файла byte[] buffer = new byte[buffersize];

// Показываем число отправленных байт int fileLength = (int)fileStream. Length: statusBarl. Text = "Отправлено " + fileLength + " байт";

// Читаем файловый поток в базовом потоке while (fileLength > 0)

{

int numRead = fileStream. Read(buffer. 0. buffer. Length); baseStream. Write(buffer, 0, numRead); fileLength -= numRead;

}

fileStream. CloseO; baseStream. Close(); irClient. CloseO;

statusBarl. Text =* "Файл отправлен”;

}

private void butReceiveCl ick (object sender, EventArgs e)

{

// Создаем поток для записи файла

Stream writeStream;

try

{

writeStream = new FileStream(fileReceive, FileMode. OpenOrCreate):

}

catch (Exception)

{

MessageBox. ShowC’He могу открыть "+ fileReceive + " для записи"): return:

}

// Создаем соединение с помощью класса IrDAEndPoint // для выбранного устройства из списка // Начинаем прослушку входящих сообщений // из устройства с объектом IrDAListener try

{

int і = 1 іstBoxl. Selectedlndex; irEndP = new IrDAEndPoint(irDevices[i].DeviceID, irServiceName): irListen = new IrDAListener(irEndP); irListen. StartO:

>

catch (SocketException exSoc)

{

MessageBox. ShowC’He могу прослушивать на службе "+irServiceName + ": "

+ exSoc. ErrorCode);

}

// Показываем прослушивание выбранного устройства statusBarl. Text = "Прослушка " +

1 і stBoxl. Selectedltem. ToStri ng():

// Создаем соединение

// для службы, обнаруженной прослушкой

Листинг 12.5 (продолжение)

IrDAClient irClient; try

{

irClient = irListen. AcceptlrDAClientO;

}

catch (SocketException exp)

{

MessageBox. ShowC’He могу принять сокет "+ exp. ErrorCode); return:

}

// Показываем, идет ли передача файла if (irListen. PendingO = true)

statusBarl. Text = "Передача из " + і rClі ent. RemoteMachi neName;

el se

statusBarl. Text = "Нет передачи из " + і rClі ent. RemoteMachi neName;

// Получим поток из клиента

Stream baseStream = irClient. GetStreamO;

int numToRead:

// Создаем буфер для чтения файла byte[] buffer = new byte[buffersize];

// Читаем поток данных, который содержит // данные из передающего устройства numToRead = 4; while (numToRead > 0)

{

int numRead = baseStream. Read(buffer, 0, numToRead); numToRead •= numRead;

}

// Получим размер буфера для показа // числа байт для записи в файл numToRead = BitConverter. ToInt32(buffer, 0); statusBarl. Text = "Записываем "+ numToRead + " байт";

// Записываем поток в файл до тех пор,

// пока не будут прочитаны все байты while (numToRead > 0)

{

int numRead = baseStream. Read(buffer, 0, buffer. Length); numToRead -= numRead;

writeStream. Write(buffer, 0. numRead);

}

// Сообщаем, что файл получен statusBarl. Text = "Файл получен";

baseStream. Close(); wrі teStream. Close(); irListen. StopO; irClient. CloseO;

}

Итак, можно запустить приложение на двух устройствах и попро­бовать отправить и принять файл. Перед тестированием программы нужно создать текстовый документ send. txt с любым содержанием. Затем нужно повернуть друг к друїу инфракрасные датчики двух уст­ройств и на первом устройстве нажать кнопку Искать. Если поиск за­вершился успешно, то в списке отобразится имя второго устройства.

Затем на втором устройстве надо нажать кнопку Принять, а на пер­вом устройстве нажать кнопку Отправить. В результате ваших дей­ствий текст сообщения из файла send. txt должен быть передан на другое устройство и сохранен в файле receive. txt.

К сожалению, данный пример нельзя тестировать на эмуляторе. Для проведения эксперимента вам необходимо иметь два настоящих ус­тройства. Так как у меня нет второго КПК, я решил воспользоваться в качестве второго устройства своим смартфоном под управлением Windows Mobile 2005. Поскольку графический интерфейс программ для смартфонов не поддерживает кнопки, мне пришлось добавить в решение новый проект IrDA_Smartphone_CS и частично переписать код программы.

Вместо кнопок использовалось меню, а вместо элемента управле­ния ListBox — элемент ComboBox. Но можно было обойтись и без со­здания текстовых файлов, а просто считывать данные из потока. В этом случае наша программа приобрела бы черты чата. Также можно написать какую-нибудь игру, в которой участвуют два игро­ка. С помощью инфракрасной связи вы можете передавать инфор­мацию, например, о сделанном ходе в шахматах.

Технология Bluetooth

Несмотря на свою дешевизну и простоту, инфракрасное соедине­ние имеет несколько существенных недостатков. К ним относятся маленький радиус действия и возможность связи в пределах пря­мой видимости. Этих недостатков лишено Bluetooth-соединение.

Но и тут не обошлось без ложки дегтя в бочке меда. Во-первых, су­ществует два различных подхода к реализации Bluetooth-соедине — ний, которые не совместимы друг с другом. Во-вторых, пока не су­ществует поддержки этой технологии в управляемом коде. NET Compact Framework. Примеры с Bluetooth-связью мы будем приво­дить для устройств под управлением Windows Mobile 5.0, так как они гарантированно используют одну и ту же реализацию Bluetooth — технологии. Так как библиотека. NET Compact Framework не имеет в своем составе классов, работающих с Bluetooth, то придется вос­пользоваться вызовами функций Windows API, как показано в лис­тинге 12.6.

Листинг 12.6

public enum RadioMode {

Off = 0.

Connectable = 1.

Discoverable = 2 }

III <summary>

III Получает текущий статус bluetooth

III </summary>

III <param name="dwMode">фла г и</param>

III <returns></returns>

[Dl1 Import("BthUti1.dll")]

public static extern int BthGetMode(out RadioMode dwMode);

III <summary>

III Устанавливает новый режин bluetooth

III </summary>

III <param пате="(МЫе">флаги для установки режина</рагат>

III <returns></returns>

[Dl1Import("BthUti1.dll”)]

public static extern int BthSetMode(RadioMode dwMode);

private void mnuOnCl ick (object sender. EventArgs e)

{

BthSetMode(Radi oMode. Connectable);

IblStatus. Text * Radi oMode. Connectable. ToStringO;

}

private void Forml_Load(object sender, EventArgs e)

{

RadioMode mode;

int ret = BthGetMode (out mode);

1Ы Status. Text = mode. ToStringO;

}

private void mnuOff_Click(object sender, EventArgs e)

{

BthSetMode(RadioMode. Off);

IblStatus. Text = Radi oMode. Off. ToStringO;

}

В этом примере после запуска приложения текущий режим Bluetooth определяется при помощи функции BthGetMode, а с помощью команд меню пользователь может включать или выключать Bluetooth-соеди — нение, используя функцию BthSetMode.

Несколько слов о связи

Несомненно, маленькие мобильные устройства, будь то смартфон или КПК, идеально подходят на роль коммуникационных уст­ройств. В этой главе были приведены только самые простые при­меры использования связи между устройствами. В последнее вре­мя набирают обороты такие виды связи, как Wi-Fi, GPS и GPRS. Кроме того, мобильные устройства имеют в своем составе браузе­ры для путешествия по Всемирной паутине. Таким образом, серь­езному разработчику необходимо освоить весь спектр технологий, связанных с обменом данными между устройствами.

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Confirm that you are not a bot - select a man with raised hand: