diff options
author | Scott Murray <scott.murray@konsulko.com> | 2021-12-16 15:07:44 -0500 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2021-12-16 16:03:51 -0500 |
commit | fad93b42c285ffb463e9494070f40d3b339d732f (patch) | |
tree | 6ae60914c578bd34b8ebbde9b271859e8b87ab65 /bluetooth/bluetooth.cpp | |
parent | fe20f1b029f67dee1f790ade7a9114086f2abd38 (diff) |
Initial rework to replace app framework usage
Changes:
- Remove "core" code related to WebSocket messaging for the app
framework.
- Stub out hvac, navigation, network, and weather interfaces. This
allows building several of the demo applications without modification
for now. The network interface will definitely be reused to plumb
in a new connman-glib library derived from the previous network
binding. The others may potentially be reused to plumb in other
new backend implementations.
- Update the Network interface object constructor arguments to add a
agent registration flag. This prepares for the connman-glib
switch and means users will not need to be updated twice.
- Update the Bluetooth interface to use a new bluez-glib library that
is derived from the previous Bluetooth binding. This has been
successfully tested with a the Settings application.
- Remove signal-composer and voice API interface code as there are no
direct replacements planned. The signal-composer interface was
effectively exposing the binding events, so has little reuse
potential with a new backend. For the voice interface, if some form
of Alexa support becomes desirable, it can potentially be brought
back for adaptation if required.
- Disable compilation of the remaining interfaces for now. Some like
map, pbap, and mediaplayer are very likely to be used as the basis
for updating their associated applications, so keeping the code for
the planned iterative development seems easier.
- Updated copyright lines in all touched files.
Bug-AGL: SPEC-4182
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Change-Id: Ib717ac8ac68ec457eaee74755dcf9d4f36b79d12
Diffstat (limited to 'bluetooth/bluetooth.cpp')
-rw-r--r-- | bluetooth/bluetooth.cpp | 369 |
1 files changed, 158 insertions, 211 deletions
diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp index 82ef2f1..c58b64b 100644 --- a/bluetooth/bluetooth.cpp +++ b/bluetooth/bluetooth.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Konsulko Group + * Copyright (C) 2018-2021 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,301 +16,248 @@ #include <QDebug> -#include "callmessage.h" -#include "eventmessage.h" -#include "responsemessage.h" -#include "messagefactory.h" -#include "messageengine.h" -#include "messageenginefactory.h" +#include <bluez-glib.h> + #include "bluetooth.h" #include "bluetoothmodel.h" +#include "bluetootheventhandler.h" -Bluetooth::Bluetooth (QUrl &url, QQmlContext *context, QObject * parent) : - QObject(parent), - m_context(context) +Bluetooth::Bluetooth (bool register_agent, QQmlContext *context, QObject * parent) : + QObject(parent), + m_context(context), + m_agent(register_agent) { - m_mloop = MessageEngineFactory::getInstance().getMessageEngine(url); - m_bluetooth = new BluetoothModel(); - QObject::connect(m_mloop.get(), &MessageEngine::connected, this, &Bluetooth::onConnected); - QObject::connect(m_mloop.get(), &MessageEngine::disconnected, this, &Bluetooth::onDisconnected); - QObject::connect(m_mloop.get(), &MessageEngine::messageReceived, this, &Bluetooth::onMessageReceived); - - BluetoothModelFilter *m_model = new BluetoothModelFilter(); - m_model->setSourceModel(m_bluetooth); - m_model->setFilterFixedString("true"); - context->setContextProperty("BluetoothPairedModel", m_model); - - m_model = new BluetoothModelFilter(); - m_model->setSourceModel(m_bluetooth); - m_model->setFilterFixedString("false"); - context->setContextProperty("BluetoothDiscoveryModel", m_model); - - uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb"); - uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb"); - uuids.insert("hfp", "0000111f-0000-1000-8000-00805f9b34fb"); + m_bluetooth = new BluetoothModel(); + BluetoothModelFilter *m_model = new BluetoothModelFilter(); + m_model->setSourceModel(m_bluetooth); + m_model->setFilterFixedString("true"); + context->setContextProperty("BluetoothPairedModel", m_model); + + m_model = new BluetoothModelFilter(); + m_model->setSourceModel(m_bluetooth); + m_model->setFilterFixedString("false"); + context->setContextProperty("BluetoothDiscoveryModel", m_model); + + m_event_handler = new BluetoothEventHandler(this, register_agent); + + uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb"); + uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb"); + uuids.insert("hfp", "0000111f-0000-1000-8000-00805f9b34fb"); } Bluetooth::~Bluetooth() { } -void Bluetooth::send_command(QString verb, QJsonObject parameter) -{ - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); - btmsg->createRequest("Bluetooth-Manager", verb, parameter); - m_mloop->sendMessage(std::move(msg)); -} - void Bluetooth::setPower(bool state) { - QJsonObject parameter; - parameter.insert("powered", state ? "true" : "false"); - send_command("adapter_state", parameter); + bluez_adapter_set_powered(NULL, state ? TRUE : FALSE); } void Bluetooth::setDiscoverable(bool state) { - QJsonObject parameter; - parameter.insert("discoverable", state ? "true" : "false"); - send_command("adapter_state", parameter); + bluez_adapter_set_discoverable(NULL, state); - m_discoverable = state; + m_discoverable = state; - emit discoverableChanged(); + emit discoverableChanged(); } -void Bluetooth::discovery_command(bool state) +void Bluetooth::start() { - QJsonObject parameter; - parameter.insert("discovery", state ? "true" : "false"); + bluez_init(m_agent, m_agent, m_event_handler->init_cb, m_event_handler); +} - set_discovery_filter(); +void Bluetooth::discovery_command(bool state) +{ + set_discovery_filter(); - send_command("adapter_state", parameter); + bluez_adapter_set_discovery(NULL, state ? TRUE : FALSE); } void Bluetooth::start_discovery() { - discovery_command(true); - - // temp workaround to list already discovered devices - send_command("managed_objects", QJsonObject()); + discovery_command(true); } void Bluetooth::stop_discovery() { - discovery_command(false); + discovery_command(false); } void Bluetooth::remove_device(QString device) { - QJsonObject parameter; - parameter.insert("device", device); + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); - send_command("remove_device", parameter); + bluez_device_remove(device_cstr); } void Bluetooth::pair(QString device) { - QJsonObject parameter; - parameter.insert("device", device); + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); - send_command("pair", parameter); + bluez_device_pair(device_cstr, m_event_handler->device_pair_cb, m_event_handler); } -void Bluetooth::cancel_pair(QString device) +void Bluetooth::cancel_pair(void) { - send_command("cancel_pairing", QJsonObject()); + bluez_cancel_pairing(); } void Bluetooth::connect(QString device, QString uuid) { - QJsonObject parameter; - uuid = process_uuid(uuid); - parameter.insert("device", device); - parameter.insert("uuid", uuid); - send_command("connect", parameter); + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); + + uuid = process_uuid(uuid); + QByteArray uuid_ba = uuid.toLocal8Bit(); + const char *uuid_cstr = uuid_ba.data(); + + bluez_device_connect(device_cstr, + uuid_cstr, + m_event_handler->device_connect_cb, + m_event_handler); } void Bluetooth::connect(QString device) { - QJsonObject parameter; - parameter.insert("device", device); - send_command("connect", parameter); + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); + + bluez_device_connect(device_cstr, + NULL, + m_event_handler->device_connect_cb, + m_event_handler); } void Bluetooth::disconnect(QString device, QString uuid) { - QJsonObject parameter; - uuid = process_uuid(uuid); - parameter.insert("device", device); - parameter.insert("uuid", uuid); - send_command("disconnect", parameter); -} + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); -void Bluetooth::disconnect(QString device) -{ - QJsonObject parameter; - parameter.insert("device", device); - send_command("disconnect", parameter); -} + uuid = process_uuid(uuid); + QByteArray uuid_ba = uuid.toLocal8Bit(); + const char *uuid_cstr = uuid_ba.data(); -void Bluetooth::send_confirmation(int pincode) -{ - QJsonObject parameter; - parameter.insert("pincode", pincode); - send_command("confirm_pairing", parameter); + bluez_device_disconnect(device_cstr, uuid_cstr); } - -void Bluetooth::set_discovery_filter() +void Bluetooth::disconnect(QString device) { - QStringListIterator eventIterator(uuids.values()); - QJsonObject parameter; - QJsonArray array; - - while (eventIterator.hasNext()) - array.push_back(eventIterator.next()); + QByteArray device_ba = device.toLocal8Bit(); + const char *device_cstr = device_ba.data(); - // send inital adapter state + discovery filter - parameter.insert("filter", array); - parameter.insert("transport", "bredr"); - send_command("adapter_state", parameter); + bluez_device_disconnect(device_cstr, NULL); } -void Bluetooth::onConnected() +void Bluetooth::send_confirmation(int pincode) { - QStringListIterator eventIterator(events); - - while (eventIterator.hasNext()) { - QJsonObject parameter; - parameter.insert("value", eventIterator.next()); - send_command("subscribe", parameter); - } + QString pincode_str; + pincode_str.setNum(pincode); + QByteArray pincode_ba = pincode_str.toLocal8Bit(); + const char *pincode_cstr = pincode_ba.data(); - // send initial list - send_command("managed_objects", QJsonObject()); - - // get initial power state - send_command("adapter_state", QJsonObject()); + bluez_confirm_pairing(pincode_cstr); } -void Bluetooth::onDisconnected() +void Bluetooth::init_adapter_state(QString adapter) { - QStringListIterator eventIterator(events); + // Get initial power state + GVariant *reply = NULL; + gboolean rc = bluez_adapter_get_state(NULL, &reply); + if (rc && reply) { + GVariantDict *props_dict = g_variant_dict_new(reply); + gboolean powered = FALSE; + if (g_variant_dict_lookup(props_dict, "Powered", "b", &powered)) { + if (m_power != powered) { + m_power = powered; + emit powerChanged(m_power); + } + } + g_variant_dict_unref(props_dict); + g_variant_unref(reply); + } - while (eventIterator.hasNext()) { - QJsonObject parameter; - parameter.insert("value", eventIterator.next()); - send_command("unsubscribe", parameter); - } + // Get initial device list + refresh_device_list(); } -void Bluetooth::populateDeviceList(QJsonObject data) +void Bluetooth::refresh_device_list(void) { - QJsonArray devices = data.value("devices").toArray(); - - m_bluetooth->removeAllDevices(); - - for (auto value : devices) { - BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, value.toObject()); - m_bluetooth->addDevice(device); - } + gboolean rc; + GVariant *reply = NULL; + + rc = bluez_adapter_get_devices(NULL, &reply); + if(!rc) + return; + + m_bluetooth->removeAllDevices(); + + GVariantIter *array = NULL; + g_variant_get(reply, "a{sv}", &array); + const gchar *key = NULL; + GVariant *var = NULL; + while (g_variant_iter_next(array, "{&sv}", &key, &var)) { + BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, key, var); + if (device) + m_bluetooth->addDevice(device); + + g_variant_unref(var); + } + g_variant_iter_free(array); + g_variant_unref(reply); } -void Bluetooth::processDeviceChangesEvent(QJsonObject data) +void Bluetooth::set_discovery_filter(void) { - QString action = data.value("action").toString(); - QString id = data.value("device").toString(); - - if (id.isEmpty()) - return; - - BluetoothDevice *device = m_bluetooth->getDevice(id); - if (action == "removed") { - if (device != nullptr) - m_bluetooth->removeDevice(device); - return; - } - - BluetoothDevice *ndevice = m_bluetooth->updateDeviceProperties(device, data); - if (ndevice == nullptr) { - qDebug() << "bt - failed to create device object with id: " << id; - return; - } - if (device == nullptr) //device not previously in model - m_bluetooth->addDevice(ndevice); + QList<QString> values = uuids.values(); + QStringListIterator eventIterator(values); + + gchar **uuids_array = (gchar**) g_malloc0((values.count() + 1) * sizeof(gchar*)); + int i = 0; + while (eventIterator.hasNext()) { + QByteArray uuid_ba = eventIterator.next().toLocal8Bit(); + gchar *uuid_cstr = g_strdup(uuid_ba.data()); + uuids_array[i++] = uuid_cstr; + } + + gchar *transport = g_strdup("bredr"); + bluez_adapter_set_discovery_filter(NULL, uuids_array, transport); + + for (i = 0; i < values.count(); i++) + g_free(uuids_array[i]); + g_free(uuids_array); + g_free(transport); } -void Bluetooth::processAdapterChangesEvent(QJsonObject data) +void Bluetooth::update_adapter_power(bool powered) { - QString action = data.value("action").toString(); - if (action != "changed") - return; + if (!powered) + m_bluetooth->removeAllDevices(); - QJsonObject properties = data.value("properties").toObject(); - if (!properties.contains("powered")) - return; + if (m_power != powered) { + m_power = powered; + emit powerChanged(powered); - bool powered = properties.find("powered").value().toBool(); - if (!powered) - m_bluetooth->removeAllDevices(); + if (powered) + refresh_device_list(); + } - if (m_power != powered) { - m_power = powered; - emit powerChanged(powered); - } - if (!m_power) - m_discoverable = false; + if (!m_power) { + bool discoverable = m_discoverable; + m_discoverable = false; + if (discoverable != m_discoverable) + emit discoverableChanged(); + } } -void Bluetooth::onMessageReceived(std::shared_ptr<Message> msg) +void Bluetooth::request_confirmation(int pincode) { - if (!msg) - return; - - if (msg->isEvent()) { - std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); - QString ename = emsg->eventName(); - QString eapi = emsg->eventApi(); - QJsonObject data = emsg->eventData(); - if (eapi != "Bluetooth-Manager") - return; - if (ename == "device_changes") { - processDeviceChangesEvent(data); - } else if (ename == "adapter_changes") { - processAdapterChangesEvent(data); - } else if (ename == "agent") { - emit requestConfirmationEvent(data); - } - } else if (msg->isReply()) { - std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); - QString verb = rmsg->requestVerb(); - QJsonObject data = rmsg->replyData(); - if (rmsg->requestApi() != "Bluetooth-Manager") - return; - - if (rmsg->replyStatus() == "failed") { - qDebug() << "failed bt verb:" << verb; - if (rmsg->replyInfo().contains("No adapter")) { - m_power = false; - emit powerChanged(m_power); - } - } - else if (verb == "managed_objects") { - populateDeviceList(data); - } else if (verb == "adapter_state") { - bool powered = data.value("powered").toBool(); - if (m_power != powered) { - m_power = powered; - emit powerChanged(m_power); - } - } - } + QString pincode_str; + pincode_str.setNum(pincode); + emit requestConfirmationEvent(pincode_str); } |