BlueBoss — обнаружение Bluetooth
Обзор
Bluetooth сейчас применяется во многих устройствах, предоставляя их пользователям возможность работы с беспроводными аксессуарами. Этот протокол позволяет пользователям обнаруживать любые совместимые устройства, находящиеся поблизости. Почему бы не посмотреть, кто находится рядом с вами? Почему бы при обнаружении совместимого устройства не запустить некоторую программу или не известить вас?
Энди Конкол (Andy Konkol) – https://copyandwaste.com
Оборудование:
· адаптер Bluetooth («свисток» для USB);
· внутренний («мама») коаксиальный разъем (SMA Female);
· кабель-переходник с коаксиального «папы» на ВЧ-«папу» (N-male);
· антенна 2.4 GHz с внутренним ВЧ-разъемом (N-female).
ПО:
· Coding4fun Developer Kit (EN);
· программа окна-уведомления Роберта Мисьяка (Robert Misiak) (EN).
Загрузки:
· загрузить исходный код и исполняемые файлы (EN).
Программное и аппаратные средства Bluetooth
Bluetooth служит для беспроводного взаимодействия устройств на малых расстояниях. Между тем, очень простая модификация аппаратуры позволяет расширить возможности Bluetooth — для этого используется антенна 2.4 ГГц, применяемая в WiFi-сетях 802.11 a/b/g.
Описание доработки Bluetooth-адаптера для подключения внешней антенны легко найти в Интернете. Принцип весьма прост: найти антенный контакт и припаять его к разъему для подключения внешней антенны. Я купил очень дешевый USB-адаптер Bluetooth на аукционе eBay. Открыв его корпус, я нашел на плате трассу антенны и припаял к ней коаксиальный разъем-«маму», закрепив его на адаптере изоляционным материалом. У меня получился Bluetooth-адаптер с разъемом для внешней антенны, подключив которую можно обнаруживать устройства на большем расстоянии.
Для подключения антенны нужен шнур-переходник. Я использую кабель-переходник коаксиальный «папа» — ВЧ-«папа». Один конец переходника я подключаю к своему адаптеру, а другой — к антенне 9 дБ с внешним ВЧ-разъемом.
ПО
Для работы с моим модернизированным «железом» мне потребовался набор инструментальных средств Coding4Fun Toolkit, содержащий API для Bluetooth-устройств. Этот API позволяет делать многие интересные вещи, но мне нужны лишь два метода из библиотеки ServiceAndDeviceDiscovery: DiscoverAllDevices и DiscoverDeviceByName.
DiscoverAllDevices позволяет «сканировать» эфир на частоте 2.4 ГГц и сообщать о найденных устройствах.
С помощью DiscoverDeviceByName можно искать устройство с определенным именем и сообщать о его наличии или отсутствии.
1: private bool DevicePresent()
2: {
3: BluetoothDeviceServicesManager workerBTMgr = new BluetoothDeviceServicesManager();
4: Device workerDevice = workerBTMgr.DiscoverDeviceByName(_watchItem.DeviceName);
5:
6: return (workerDevice != null);
7: }
8:
9: public void Run(String Operation)
10: {
11: switch (Operation)
12: {
13: case "SingleDevice":
14: if (DevicePresent())
15: {
16: _parentForm.Invoke(_parentForm.AddToDeviceSeenList, new object[] { _watchItem });
17: }
18: else
19: {
20: _parentForm.Invoke(_parentForm.RemoveFromDeviceSeenList, new object[] { _watchItem });
21: }
22: break;
23: case "AllDevices":
24: BluetoothDeviceServicesManager workerBTMgr = new BluetoothDeviceServicesManager();
25: List<Device> Devices = workerBTMgr.DiscoverAllDevices();
26: _parentForm.Invoke(_parentForm.ThreadUpdateDiscoverBox, new object[] { Devices });
27: break;
28: }
29: }
Оба этих метода находят лишь те устройства, которые работают в режиме, допускающем их обнаружение (большинство производителей устанавливают этот режим по умолчанию). Данные два метода позволяют мне определять наличие поблизости того или иного устройства. А затем я могу генерировать уведомления или вызывать нужные программы, в зависимости от того, какие устройства нашлись.
Чтобы интерфейс пользователя программы не зависал при выполнении поиска, мне требуется два рабочих потока. Один поток обнаруживает все устройства и отображает их в окне со списком, а другой ищет устройства по их именам, записанным в списке поиска. Я не специалист по многопоточному программированию, но реализовать эти два потока мне удалось без проблем.
Интерфейс пользователя
Поскольку кнопки «Add to watchlist» (добавить в список поиска) и «Edit» (изменить), по сути, имеют идентичное назначение, я решил реализовать перегрузку формы. Мне также требуется отслеживать родительскую форму и отключать ее при появлении WatchItemForm.
Вторая перегрузка позволяет мне вносить в элемент управления формы текст, соответствующий выбранному элементу списка WatchItem (кнопка «Edit»).
1: public WatchItemForm(Form1 f, String DeviceName)
2: {
3: InitializeComponent();
4: this._parentForm = f;
5: lblDeviceName.Text = DeviceName;
6: }
7:
8: public WatchItemForm(Form1 f, WatchItem item)
9: {
10: InitializeComponent();
11: this._parentForm = f;
12:
13: lblDeviceName.Text = item.DeviceName;
14: tbxPicturePath.Text = item.ImagePath;
15: tbxProgramPath.Text = item.ProgramPath;
16: this._parentForm.Enabled = true;
17: }
Я захотел использовать всплывающее окно с уведомлением и использовал программу Роберта Мисьяка NotifyWindow (EN). Это очень простая библиотека, позволяющая легко создавать всплывающие окна. Я изменил NotifyWindow, добавив переменную picturepath и окно с рисунком на форме. Как видите, создание NotifyWindow проблем не представляет:
1: public void NotifyDeviceWindow(WatchItem x)
2: {
3: NotifyWindow nw;
4: nw = new NotifyWindow();
5: // Проверка уведомительного сообщения
6: if (x.AlertMessage == null)
7: {
8: nw.Text = x.DeviceName;
9: }
10: else
11: {
12: nw.Text = x.AlertMessage;
13: }
14: // Проверка рисунка
15: if (x.ImagePath != null)
16: {
17: FileInfo imgfile = new FileInfo(x.ImagePath);
18: if (imgfile.Exists)
19: {
20: nw.PicturePath = x.ImagePath;
21: }
22: else
23: {
24: MessageBox.Show("Image does not exist");
25: }
26: }
27: nw.Notify();
28:
29: if (x.ProgramPath != null)
30: {
31: RunProcess(x.ProgramPath);
32: }
33: }
Последовательность действий и алгоритм программы
- Пользователь щелкает кнопку Discover (обнаружить), в результате чего порождается поток, который просматривает находящиеся поблизости устройства Bluetooth.
- Поток завершается и обновляет содержимое списка Devices (устройства).
- Пользователь выбирает одно из обнаруженных устройств и щелкает кнопку «Add to watchlist» (добавить в список поиска). Порождается форма искомого устройства, в которой задаются текст сообщения, путь к рисунку и путь к исполняемой программе.
- Пользователь щелкает кнопку сохранения, после чего создается объект WatchItem, который добавляется в список watchList.
- Запускается таймер, по которому каждые 10 секунд создается поток, анализирующий наличие устройства с заданным именем.
- При обнаружении данного устройства, оно добавляется в список deviceSeenList, отправляется сообщение-оповещение и запускается назначенная программа.
- Если в следующем цикле таймера данное устройство по-прежнему обнаруживается, уведомление не отправляется. Если устройство больше не обнаруживается, оно удаляется из deviceSeenList.