Разработка Для Ос Sailfish: Работа С Bluetooth

Привет! Данная статья является продолжением серии статей, посвященных разработке под мобильную платформу Sailfish OS. На этот раз мы поговорим об использовании Bluetooth для установления соединения между двумя устройствами и передачи данных.



Bluetooth

Технология Bluetooth позволяет создать беспроводное соединение, благодаря которому можно передавать абсолютно любые данные.

Существует ряд задач, для которых Bluetooth является распространенным решением, например, передача файлов с одного устройства на другое, подключение к Bluetooth-гарнитурам или удаленное управление сканерами и принтерами.



Пример приложения

Мы рассмотрим использование технологии Bluetooth на примере реализации приложения для обмена строк.

Давай позвоним ему Bluetooth-мессенджер .

Приложение будет работать в двух режимах: серверном и клиентском.

Сервер зарегистрирует службу Bluetooth и ответит на клиентское соединение.

Клиент будет искать созданный сервис, подключаться к нему и передавать данные.

В результате вам понадобятся два устройства под управлением ОС Sailfish.



Разработка для ОС Sailfish: работа с Bluetooth



Разработка для ОС Sailfish: работа с Bluetooth

В результате приложение будет работать следующим образом:
  1. Клиент ищет сервер с зарегистрированным сервисом.

  2. Отправляет строку на найденный сервер.

  3. Сервер получает строку и отображает ее на экране.

  4. Полученная строка расширяется и отправляется обратно клиенту.

  5. Клиент отображает расширенную строку на экране и отключается от сервера.



Разработка для ОС Sailfish: работа с Bluetooth



Разработка для ОС Sailfish: работа с Bluetooth

Реализация данного приложения будет полностью охватывать необходимые инструменты для установления связи между двумя устройствами и обмена данными между ними.



Предоставление повышенных привилегий приложению

Для взаимодействия с Bluetooth приложению иногда требуются повышенные привилегии (на поиск сервисов, изменение настроек видимости, сопряжение устройств).

Если у вас нет повышенных привилегий, некоторые функции будут недоступны, поэтому мы рекомендуем предоставить их приложению, работающему с Bluetooth. Для отладки вам необходимо запустить приложение, используя девел-су с флагом -п .

Это позволяет приложению запускаться с повышенными привилегиями, а выходные данные отладки будут доступны в консоли.

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   

devel-su -p /usr/bin/bluetooth-messenger

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

Во-первых, исполняемый файл приложения необходимо запустить с помощью вызывающий .

вызывающий находит основную функцию приложения и запускает ее с переданными ей аргументами.

Это настраивается в .

рабочий стол файл проекта со следующей строкой:

Exec=invoker --type=silica-qt5 -s /usr/bin/bluetooth-messenger

Во-вторых, вам необходимо создать в каталоге файл с именем, соответствующим имени исполняемого файла.

/usr/share/maplauncherd/privileges.d/ и поместите туда строку:

/usr/bin/bluetooth-messenger,

Запятая в конце строки обязательна.

Таким образом, при нажатии на значок приложения пользователь запустит его с повышенными привилегиями.



Управление статусом Bluetooth

Для начала нужно понять, как можно контролировать состояние Bluetooth. Для этого воспользуемся системой D-Bus, взаимодействие с которой было описано в одна из предыдущих статей .

С помощью этой системы у нас есть возможность включать и выключать питание Bluetooth, а также настраивать видимость для других устройств.

Для включения Bluetooth необходимо воспользоваться услугой net.connman .

Об интерфейсе net.connman в пути /net/connman/технология/Bluetooth есть метод Установитьсвойство , с помощью которого можно задать значение свойства Работает , который отвечает за то, включен ли Bluetooth или нет. Свойство установлено следующим образом:

QDBusInterface bluetoothInterface("net.connman", "/net/connman/technology/bluetooth", "net.connman.Technology", QDBusConnection::systemBus(), this); bluetoothInterface.call("SetProperty", "Powered", QVariant::fromValue(QDBusVariant(true)));

Создать экземпляр QDBusИнтерфейс используя сервис, путь и интерфейс, перечисленные ранее.

Затем мы вызываем метод интерфейса Установитьсвойство с двумя аргументами: именем свойства и значением.

После включения Bluetooth будет полезно настроить видимость для других устройств.

Для этого мы используем сервис org.bluez .

Сначала вам нужно получить путь, соответствующий текущему устройству.

Для этого перейдите по корневому пути на интерфейсе org.bluez.Менеджер вызвать метод Адаптер по умолчанию , содержащий в выходных аргументах путь к текущему адаптеру, который мы позже будем использовать для установки видимости.



QDBusInterface adapterListInterface("org.bluez", "/", "org.bluez.Manager", QDBusConnection::systemBus(), this); QVariant adapterPath = adapterListInterface.call("DefaultAdapter").

arguments().

at(0);

После получения пути вам нужно использовать метод для установки видимости Установитьсвойство на интерфейсе org.bluez.Адаптер чтобы установить следующие свойства:

  • Обнаруживаемыйтаймаут – время в секундах ( беззнаковое целое число ), в течение которого устройство будет доступно для обнаружения после включения обнаружения.

    Если установлено значение 0, обнаружение начинается без таймера.

  • Обнаруживаемый - в зависимости от стоимости истинный или ЛОЖЬ включает или выключает обнаружение.

Мы включаем неограниченное время обнаружения с помощью следующих строк:

QDBusInterface bluetoothAdapter("org.bluez", adapterPath.value<QDBusObjectPath>().

path(), "org.bluez.Adapter", QDBusConnection::systemBus(), this); bluetoothAdapter.call("SetProperty", "DiscoverableTimeout", QVariant::fromValue(QDBusVariant(0U))); bluetoothAdapter.call("SetProperty", "Discoverable", QVariant::fromValue(QDBusVariant(true)));

Следует отметить, что для настройки параметров видимости приложение должно быть запущено с повышенными привилегиями.



Регистрация службы Bluetooth

Для начала нам нужно создать сервер и зарегистрировать на нем сервис.

Этот сервис будет получать сообщения от клиентов и отвечать на них.

Для решения этой проблемы создадим класс Сервер сообщений , заголовочный файл которого будет содержать следующее:

class MessengerServer : public QObject { Q_OBJECT public: explicit MessengerServer(QObject *parent = 0); ~MessengerServer(); Q_INVOKABLE void startServer(); Q_INVOKABLE void stopServer(); signals: void messageReceived(QString message); private: QBluetoothServer *bluetoothServer; QBluetoothServiceInfo serviceInfo; QBluetoothSocket *socket; const QString SERVICE_UUID = "1f2d6c5b-6a86-4b30-8b4e-3990043d73f1"; private slots: void clientConnected(); void clientDisconnected(); void readSocket(); };

Теперь давайте подробнее рассмотрим компоненты и содержание методов этого класса.

Устройство может уведомлять другие устройства, осуществляющие поиск через Bluetooth, зарегистрировав службу.

Для этого используется класс QBluetoothСервер .

С его помощью можно создать Bluetooth-сервер и зарегистрировать на нем сервис, который будет сообщать устройствам, что это такое.

QBluetoothСервер содержит набор методов для установки сервера на устройство и регистрации сервиса.

Особый интерес представляют:

  • Конструктор QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, родительский объект QObject*) – служит для инициализации сервера, принимает в качестве аргументов протокол и родителя QObject .

    В нашем примере мы будем использовать протокол RFCOMM.

  • Метод прослушивать (const QBluetoothAddress& адрес, порт quint16) – начинает прослушивать входящие соединения по переданному адресу и порту.

  • Сигнал ошибка (QBluetoothServer::Ошибка ошибки) — вызывается при возникновении ошибок сервера (Bluetooth выключен, служба уже зарегистрирована и т. д.), где в качестве аргумента доступна сама ошибка.

  • Сигнал новоеСоединение() – Вызывается при наличии нового запроса на соединение.

Остальные методы используются для остановки сервера, получения текущего адреса или порта, проверки статуса и других.

Они не так уж и интересны, и о них можно прочитать в официальной документации.

После того как мы подняли сервер, нам необходимо зарегистрировать сервис.

Служба — это описание службы, выполняющей определенные обязанности.

Описывает сервис, использующий объект QBluetoothServiceInfo путем установки атрибутов с использованием специальных методов.

Для решения поставленной выше задачи воспользуемся методом стартСервер() :

bluetoothServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); connect(bluetoothServer, &QBluetoothServer::newConnection, this, &MessengerServer::clientConnected); QBluetoothAddress bluetoothAddress = QBluetoothLocalDevice().

address(); bluetoothServer->listen(bluetoothAddress);

Первая строка — создать сервер, использующий RFCOMM в качестве протокола.

Затем подключаем сигнал о новом подключении к слоту нашего класса.

После этого включаем прослушивание по нашему адресу, для чего создаём экземпляр текущего устройства, из которого извлекаем его адрес и передаем методу слушать() .

Вот так мы устанавливаем сервер.

Для регистрации сервиса требуется больше кода для указания всех параметров, необходимых для его работы:

serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, "BT message sender"); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, "Example message sender"); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, "fruct.org"); serviceInfo.setServiceUuid(QBluetoothUuid(SERVICE_UUID));

Здесь мы задаем имя сервиса, описание, поставщика услуг (например, название компании) и уникальный идентификатор (в данном приложении он содержится в константе в виде строки и указывается в формате ххххххх-хххх-хххх-хххх-хххххххххх , Где Икс шестнадцатеричное число).

Первые три атрибута дают базовое представление о найденной службе, а четвертый может использоваться устройствами для поиска конкретной службы.



QBluetoothServiceInfo::Sequence classId; classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId); classId.prepend(QVariant::fromValue(QBluetoothUuid(SERVICE_UUID))); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);

В конструкции такого типа используется последовательность ( QBluetoothServiceInfo::Sequence ), чтобы установить другие атрибуты.

В этом случае мы устанавливаем уникальный идентификатор сервиса.

Таким образом сервер сообщает вам, какие услуги он предоставляет.

QBluetoothServiceInfo::Sequence publicBrowse; publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse);

С помощью этих строк мы устанавливаем публичную группу поиска, которая позволит устройствам свободно находить этот сервис.

В противном случае услуга не будет найдена.



QBluetoothServiceInfo::Sequence protocol; QBluetoothServiceInfo::Sequence protocolDescriptorList; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) << QVariant::fromValue(quint8(bluetoothServer->serverPort())); protocolDescriptorList.append(QVariant::fromValue(protocol)); serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);

Здесь для доступа к сервису устанавливаем протокол RFCOMM, аналогичный тому, который используется сервером.



serviceInfo.registerService(bluetoothAddress);

Наконец, мы регистрируем созданный сервис по адресу, полученному ранее и используемому сервером.

Теперь сервис будет виден при поиске по Bluetooth с другими устройствами.



Работа с входящими соединениями

Теперь, когда служба зарегистрирована и приложение готово принимать входящие соединения, ему необходимо их обработать.

Как упоминалось ранее, сервер приложений должен принять строку от клиента, расширить ее и отправить обратно.

Когда клиент подключается к серверу, мы создаем сокет, представленный в виде экземпляра.

QBluetoothSocket , который можно получить, вызвав метод следующееPendingConnection() в экземпляре класса QBluetoothСервер .

Сокет имеет целый набор сигналов, позволяющих отслеживать его состояние, наиболее полезными из которых являются:

  • связанный() – Вызывается при создании сокетного соединения.

  • отключен() – вызывается при разрыве соединения.

  • ошибка (ошибка QBluetoothSocket::SocketError) – вызывается при возникновении ошибки, ее тип передается в качестве аргумента.

  • готовЧитать() – Вызывается, когда новые данные доступны для чтения в сокете.

Мы используем их для обработки входящих соединений.

Ранее мы прикрепили сигнал новоеСоединение() в слот клиентСоединенный() , рассмотрим его реализацию.



void MessengerServer::clientConnected() { //.

socket = bluetoothServer->nextPendingConnection(); connect(socket, &QBluetoothSocket::readyRead, this, &MessengerServer::readSocket); connect(socket, &QBluetoothSocket::disconnected, this, &MessengerServer::clientDisconnected); }

Объект QBluetoothSocket является наследником QIOУстройство , в результате ему доступны методы чтения строки, символа, выбранного количества символов и т. д. Методы чтения (как и методы записи) используют QByteArray , который позволяет передавать не только строки, но и любые другие данные в виде набора байтов.

Таким образом можно передавать любые типы данных, независимо от их содержания.

В нашем примере для обработки входящих сообщений мы подключили сигнал готовЧитать() с методом чтениеСокет() , код которого выглядит следующим образом:

void MessengerServer::readSocket() { //.

const QString message = QString::fromUtf8(socket->readLine().

trimmed()); emit messageReceived(message); QString reversedMessage; for (int i = message.size() - 1; i >= 0; i--) { reversedMessage.append(message.at(i)); } socket->write(reversedMessage.toUtf8()); }

Для чтения данных в виде массива байтов мы используем метод читатьстроку() , после чего преобразуем прочитанную строку в строку, разворачиваем ее и отправляем обратно методом писать() , преобразуя обратно в массив байтов.

Таким образом, реализованный нами сервер способен принимать строку от любого другого устройства по Bluetooth и возвращать ее обратно в развернутом виде.



Поиск услуг

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

Как найти устройство, предоставляющее необходимый сервис? Сначала нужно выполнить поиск сервисов, доступных на видимых Bluetooth-устройствах, и только потом подключаться к нему.

Заголовочный файл клиента имеет следующее содержимое:

class MessengerClient : public QObject { Q_OBJECT public: explicit MessengerClient(QObject *parent = 0); ~MessengerClient(); Q_INVOKABLE void startDiscovery(const QString &messageToSend); Q_INVOKABLE void stopDiscovery(); private: const QString SERVICE_UUID = "1f2d6c5b-6a86-4b30-8b4e-3990043d73f1"; QString message; QBluetoothSocket *socket = NULL; QBluetoothDeviceDiscoveryAgent* discoveryAgent; QBluetoothDeviceInfo device; QBluetoothLocalDevice localDevice; void requestPairing(const QBluetoothAddress &address); void startClient(const QBluetoothAddress &address); void stopClient(); signals: void messageReceived(QString message); void clientStatusChanged(QString text); private slots: void deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo); void pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); void pairingError(QBluetoothLocalDevice::Error error); void socketConnected(); void deviceSearchFinished(); void readSocket(); };

Давайте рассмотрим компоненты, необходимые для реализации поиска сервиса и отправки сообщений.

Для поиска сервисов в библиотеке Qt предусмотрен класс QBluetoothServiceDiscoveryAgent .

Он позволяет автоматически проверять все устройства на наличие определенного сервиса, который мы ищем по UUID. В дальнейшем, когда сервис будет найден, объект этого класса инициирует соответствующий сигнал, с помощью которого мы можем обработать результат поиска.

Следует отметить, что для использования этого класса необходимо, чтобы приложение запускалось с повышенными привилегиями.

Класс содержит следующие интересующие нас методы:

  • setUuidFilter (const QBluetoothUuid &uuid) – задает UUID того сервиса, с помощью которого вы хотите найти.

    Существует также аналогичный метод установки нескольких UUID.

  • setRemoteAddress (const QBluetoothAddress &адрес) – задает адрес устройства, на котором вы хотите найти услугу.

    Можно использовать, если известен точный адрес устройства, которое необходимо найти.

  • начинать() – запускает поиск услуг.

  • останавливаться() – прекращает поиск услуг.

  • обнаруженные услуги() – возвращает список найденных сервисов.

  • прозрачный() – очищает список найденных сервисов.

Сигналы полезны для обработки результата:
  • serviceDiscovered(const QBluetoothServiceInfo &info) – вызывается при обнаружении службы, информация о ней передается с аргументом.

  • законченный() – вызывается, когда поиск завершен.

  • ошибка (QBluetoothServiceDiscoveryAgent::Ошибка ошибки) – Вызывается при возникновении ошибок.

Для поиска конкретного нашего сервиса необходимо установить метод установитьUuidFilter() фильтровать по UUID, который мы указали при регистрации сервиса и использовании метода начинать() Чтобы начать поиск.

После этого при обнаружении нашего сервиса сработает сигнал сервисобнаружен() .

Экопировать QBluetoothServiceInfo содержит информацию о найденном сервисе (имя, UUID, информацию об устройстве, на котором он зарегистрирован и т. д.).

Мы будем использовать экземпляр этого класса для подключения к сервису, о котором будет упомянуто позже.

Конкретно в нашем примере мы рассмотрим еще один класс, не требующий повышенных привилегий — QBluetoothDeviceDiscoveryAgent .

Его можно использовать для поиска устройств, а не сервисов, и он не требует повышенных привилегий.

Для каждого найденного устройства мы будем смотреть зарегистрированные на устройстве сервисы, и если наш сервис есть в списке, то считаем сервис найденным и в дальнейшем будем подключаться к нему.

QBluetoothDeviceDiscoveryAgent состоит из небольшого количества методов поиска устройств.

Наиболее полезными являются следующие:

  • начинать() – начинает поиск устройств.

  • останавливаться() – прекращает поиск устройств.

  • обнаруженные устройства() – возвращает список всех найденных устройств.

  • ошибка() – возвращает тип последней ошибки, обнаруженной при поиске.

    Существует также сигнал, который будет запущен сразу после возникновения ошибки с типом ошибки в качестве аргумента.

  • ошибкаТекст() – возвращает текст последней произошедшей ошибки.

Также в случае обнаружения устройства сразу же сработает сигнализация.

устройствоОбнаружено(const QBluetoothDeviceInfo &info) , который можно использовать для обработки результата.

Информация о найденных устройствах представлена в виде объекта QDeviceInfo .

Вы можете извлечь данные из этого объекта с помощью специальных методов.

Наиболее интересны следующие:

  • адрес() – mac-адрес найденного устройства.

    Используется при поиске любых устройств, кроме macOS и iOS.

  • устройствоUuid() – уникальный идентификатор найденного устройства.

    Используется только при поиске устройств на macOS и iOS.

  • имя() – имя найденного устройства.

  • сервисUuids() – список уникальных идентификаторов зарегистрированных сервисов.

Теперь, когда мы знаем, как искать службы на устройствах Bluetooth, попробуем найти свою собственную службу.

В конструкторе инициализируем объект для поиска устройств:

MessengerClient::MessengerClient(QObject *parent) : QObject(parent) { //.

discoveryAgent = new QBluetoothDeviceDiscoveryAgent(localDevice.address()); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &MessengerClient::deviceDiscovered); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &MessengerClient::deviceSearchFinished); //.

}

Сначала создайте экземпляр QBluetoothDeviceDiscoveryAgent , которому мы передаем в качестве аргумента адрес текущего устройства Bluetooth. Затем к нашему текущему присоединяем два объектных сигнала: устройствообнаружено() для обработки нового найденного устройства и законченный() для обработки завершения поиска.

Метод запуска поиска содержит следующие строки:

void MessengerClient::startDiscovery(const QString &messageToSend) { //.

this->message = messageToSend; discoveryAgent->start(); //.

}

Здесь сохраняем сообщение, которое необходимо передать и начинаем поиск устройств.

Слот используется для обработки найденных устройств устройствообнаружено() , к которому мы ранее подключили сигнал:

void MessengerClient::deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) { //.

if (deviceInfo.serviceUuids().

contains(QBluetoothUuid(SERVICE_UUID))) { emit clientStatusChanged(QStringLiteral("Device found")); discoveryAgent->stop(); requestPairing(deviceInfo.address()); } }

Как говорилось ранее, мы смотрим на список уникальных идентификаторов сервисов, чтобы найти в нем свой зарегистрированный.

Когда найдено первое устройство, предоставляющее искомую нам услугу, мы завершаем поиск и вызываем метод для установления сопряжения между устройствами.



Сопряжение устройств

Сопряжение устройств — важный аспект связи устройств с помощью Bluetooth. Это означает, что два устройства устанавливают доверительные отношения друг с другом и имеют доступ к более широкому набору вариантов взаимодействия (например, удаленному управлению).

Конкретно в нашем примере сопряжение не требуется, но мы его установим, чтобы посмотреть, как это делается в общем случае.

Для установления сопряжения требуются повышенные привилегии.

Класс используется для сопряжения устройств.

QBluetoothLocalDevice .

Мы уже использовали его ранее в серверном коде для получения адреса текущего устройства.

Он также используется для сопряжения устройств.

Нас интересуют методы:

  • PairingStatus (const QBluetoothAddress &address) – позволяет получить статус сопряжения между текущим устройством и устройством по адресу.

    Возвращает одно из следующих значений:

  • requestPairing (const QBluetoothAddress &address, сопряжение) – запрашивает изменение статуса сопряжения с устройством (второй аргумент – Paired для установления сопряжения или Unpaired для разрыва).

и сигналы:
  • PairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing Pairing) – возвращается, когда статус сопряжения был успешно изменен.

  • error(QBluetoothLocalDevice::Error error) – возвращается, если произошла ошибка при изменении статуса сопряжения (включая отмену предложения сопряжения на одном из устройств).

Мы можем получить адрес удаленного устройства, вызвав метод адрес() на копии QBluetoothDeviceInfo , в дальнейшем будем использовать его при установлении сопряжения и подключении к сервису.

Теперь попробуем установить сопряжение между двумя устройствами.

Во-первых, давайте добавим сигнальное соединение в конструктор клиентского класса:

connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, this, &MessengerClient::pairingFinished); connect(&localDevice, &QBluetoothLocalDevice::error, this, &MessengerClient::pairingError);

Экопировать QBluetoothLocalDevice в данном случае это поле класса.

Слот спариваниеЗавершено() содержит строку, которая запускает клиент startClient (адрес) , А ошибка спаривания() – отладочный вывод. Для установления спаривания мы реализовали метод запросСопряжение() со следующим содержанием:

void MessengerClient::requestPairing(const QBluetoothAddress &address) { //.

if (localDevice.pairingStatus(address) == QBluetoothLocalDevice::Paired) { startClient(address); } else { localDevice.requestPairing(address, QBluetoothLocalDevice::Paired); } }

Если устройства уже сопряжены, то просто инициируем соединение с сервером, в противном случае запрашиваем сопряжение.

В результате, если сопряжение успешно установлено, также инициируется соединение с сервером, а в случае ошибки мы уведомляем пользователя о проблеме.



Подключение к серверу

Ээкземпляр класса QBluetoothDeviceInfo , соответствующий найденному устройству, содержит метод получения адреса, достаточного для подключения к сервису.

Для этой цели используется QBluetoothSocket , достаточно с помощью конструктора создать экземпляр этого класса, передав ему протокол RFCOMM и вызвав метод ConnectToService() , которому в качестве аргументов передается адрес из экземпляра QBluetoothDeviceInfo и порт, на котором необходимо установить соединение.

Чтобы установить соединение с сервисом, необходимо указать порт 1. Теперь давайте рассмотрим процесс установления соединения, отправки и получения данных с помощью сокета.

Клиент использует то же самое QBluetoothSocket как на сервере, что позволяет нам использовать ранее рассмотренные сигналы для реализации обработчиков и методов записи данных в сокет. Метод стартКлиент() устанавливает соединение с устройством, предоставляющим услугу, с помощью сокета:

void MessengerClient::startClient(const QBluetoothDeviceInfo &deviceInfo) { //.

socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); connect(socket, &QBluetoothSocket::connected, this, &MessengerClient::socketConnected); connect(socket, &QBluetoothSocket::readyRead, this, &MessengerClient::readSocket); socket->connectToService(deviceInfo.address(), 1); }

Мы создаем экземпляр сокета с протоколом RFCOMM и подключаем его сигналы к слотам нашего класса.

Затем вызов метода ConnectToService() подключиться к другому устройству.

Следует отметить, что если бы мы использовали класс QBluetoothServiceInfo , что позволяет получать информацию о найденных сервисах в виде экземпляров QBluetoothServiceInfo , то достаточно будет вызвать метод ConnectToService() с одним аргументом, принимающим информацию об услуге.

Метод сокетСоединенный() вызывается при установлении сокетного соединения, внутри него мы отправляем данные на сервер:

void MessengerClient::socketConnected() { //.

socket->write(message.toUtf8()); }

Здесь используется тот же класс сокета, что и на сервере, поэтому мы можем передавать любые данные в виде массива байтов.

Как мы помним, код сервера позволяет получить строку, раскрыть ее и вернуть нам; для обработки входящего сообщения мы подключили слот чтениеСокет() с сигналом готовЧитать() .

Этот слот выглядит следующим образом:

void MessengerClient::readSocket() { //.

QString receivedMessage = QString::fromUtf8(socket->readLine().

trimmed()); emit messageReceived(receivedMessage); }



Результат

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

Мы также рассмотрели процедуру поиска устройства.

Упомянутого в статье материала достаточно для реализации передачи любых данных между двумя устройствами.

Пример кода приложения доступен по адресу GitHub .

Технические вопросы также можно обсудить по адресу канал русскоязычного сообщества Sailfish OS в Telegram или группа вконтакте .

Автор: Сергей Аверкиев Теги: #sailfish os #Qt #Bluetooth #Разработка мобильных приложений #Qt #Разработка для Sailfish OS

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.