M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +40 -22
@@ 73,10 73,10 @@
#include <service-bluetooth/messages/ResponseVisibleDevices.hpp>
#include <service-bluetooth/messages/Status.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
-#include <service-db/agents/settings/SystemSettings.hpp>
+#include <service-bluetooth/messages/Disconnect.hpp>
#include <service-db/Settings.hpp>
+#include <service-db/agents/settings/SystemSettings.hpp>
#include <module-services/service-appmgr/include/service-appmgr/Constants.hpp>
-#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp>
#include <module-services/service-evtmgr/service-evtmgr/Constants.hpp>
#include <module-services/service-evtmgr/service-evtmgr/EVMessages.hpp>
@@ 86,6 86,7 @@
#include <apps-common/windows/Dialog.hpp>
#include <i18n/i18n.hpp>
+#include <service-bluetooth/messages/SyncDevices.hpp>
namespace app
{
@@ 106,6 107,7 @@ namespace app
AsyncCallbackReceiver{this}, soundsPlayer{std::make_shared<SoundsPlayer>(this)}
{
bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
+ bus.channels.push_back(sys::BusChannel::BluetoothNotifications);
CellularServiceAPI::SubscribeForOwnNumber(this, [&](const std::string &number) {
selectedSimNumber = number;
@@ 115,6 117,7 @@ namespace app
Store::GSM::get()->sim == selectedSim) {
CellularServiceAPI::RequestForOwnNumber(this);
}
+ bluetoothSettingsModel = std::make_shared<BluetoothSettingsModel>(this);
}
ApplicationSettings::~ApplicationSettings()
@@ 179,12 182,21 @@ namespace app
return sys::MessageNone{};
});
+ connect(typeid(::message::bluetooth::SyncDevices), [&](sys::Message *msg) {
+ auto message = static_cast<::message::bluetooth::SyncDevices *>(msg);
+ bluetoothSettingsModel->replaceDevicesList(message->getDevices());
+
+ if (gui::window::name::all_devices == getCurrentWindow()->getName()) {
+ switchWindow(gui::window::name::all_devices);
+ }
+ return sys::MessageNone{};
+ });
connect(typeid(::message::bluetooth::ResponseBondedDevices), [&](sys::Message *msg) {
- auto responseBondedDevicesMsg = static_cast<::message::bluetooth::ResponseBondedDevices *>(msg);
+ auto message = static_cast<::message::bluetooth::ResponseBondedDevices *>(msg);
+ bluetoothSettingsModel->replaceDevicesList(message->getDevices());
+
if (gui::window::name::all_devices == getCurrentWindow()->getName()) {
- auto bondedDevicesData = std::make_unique<gui::BondedDevicesData>(
- responseBondedDevicesMsg->getDevices(), responseBondedDevicesMsg->getAddressOfConnectedDevice());
- switchWindow(gui::window::name::all_devices, std::move(bondedDevicesData));
+ switchWindow(gui::window::name::all_devices);
}
return sys::MessageNone{};
});
@@ 204,13 216,12 @@ namespace app
connect(typeid(BluetoothPairResultMessage), [&](sys::Message *msg) {
auto bluetoothPairResultMsg = static_cast<BluetoothPairResultMessage *>(msg);
+ auto device = bluetoothPairResultMsg->getDevice();
if (bluetoothPairResultMsg->isSucceed()) {
- bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(),
- service::name::bluetooth);
return sys::MessageNone{};
}
- auto addr = bluetoothPairResultMsg->getAddr();
- auto message = std::make_shared<BluetoothPairMessage>(std::move(addr));
+ auto message = std::make_shared<BluetoothPairMessage>(device);
+
switchToAllDevicesViaBtErrorPrompt(std::move(message), "app_settings_bluetooth_pairing_error_message");
return sys::MessageNone{};
@@ 221,31 232,37 @@ namespace app
return sys::MessageNone{};
});
+ connect(typeid(::message::bluetooth::ProfileStatus), [&](sys::Message *msg) { return sys::MessageNone{}; });
+
connect(typeid(::message::bluetooth::UnpairResult), [&](sys::Message *msg) {
auto unpairResultMsg = static_cast<::message::bluetooth::UnpairResult *>(msg);
if (unpairResultMsg->isSucceed()) {
return sys::MessageNone{};
}
- auto addr = unpairResultMsg->getAddr();
- bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(), service::name::bluetooth);
- auto message = std::make_shared<message::bluetooth::Unpair>(std::move(addr));
+ auto device = unpairResultMsg->getDevice();
+ auto message = std::make_shared<message::bluetooth::Unpair>(device);
switchToAllDevicesViaBtErrorPrompt(std::move(message), "app_settings_bluetooth_unpairing_error_message");
return sys::MessageNone{};
});
connect(typeid(::message::bluetooth::ConnectResult), [&](sys::Message *msg) {
auto connectResultMsg = static_cast<::message::bluetooth::ConnectResult *>(msg);
+ auto device = connectResultMsg->getDevice();
+
if (connectResultMsg->isSucceed()) {
- bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(),
- service::name::bluetooth);
return sys::MessageNone{};
}
- auto addr = connectResultMsg->getAddr();
- auto message = std::make_shared<message::bluetooth::Connect>(std::move(addr));
+
+ auto message = std::make_shared<message::bluetooth::Connect>(device);
switchToAllDevicesViaBtErrorPrompt(std::move(message), "app_settings_bluetooth_connecting_error_message");
return sys::MessageNone{};
});
-
+ connect(typeid(::message::bluetooth::DisconnectResult), [&](sys::Message *msg) {
+ if (gui::window::name::all_devices == getCurrentWindow()->getName()) {
+ switchWindow(gui::window::name::all_devices);
+ }
+ return sys::MessageNone{};
+ });
connect(typeid(::message::bluetooth::InitializationResult), [&](sys::Message *msg) {
auto initializationResultMsg = static_cast<::message::bluetooth::InitializationResult *>(msg);
if (initializationResultMsg->isSucceed()) {
@@ 339,6 356,7 @@ namespace app
[this](const std::string &value) { notificationsWhenLocked = utils::getNumericValue<bool>(value); },
::settings::SettingsScope::Global);
+ bluetoothSettingsModel->requestBondedDevices();
return ret;
}
@@ 374,11 392,11 @@ namespace app
windowsFactory.attach(gui::window::name::bluetooth, [](Application *app, const std::string &name) {
return std::make_unique<gui::BluetoothWindow>(app);
});
- windowsFactory.attach(gui::window::name::add_device, [](Application *app, const std::string &name) {
- return std::make_unique<gui::AddDeviceWindow>(app);
+ windowsFactory.attach(gui::window::name::add_device, [this](Application *app, const std::string &name) {
+ return std::make_unique<gui::AddDeviceWindow>(app, bluetoothSettingsModel);
});
- windowsFactory.attach(gui::window::name::all_devices, [](Application *app, const std::string &name) {
- return std::make_unique<gui::AllDevicesWindow>(app);
+ windowsFactory.attach(gui::window::name::all_devices, [this](Application *app, const std::string &name) {
+ return std::make_unique<gui::AllDevicesWindow>(app, bluetoothSettingsModel);
});
windowsFactory.attach(gui::window::name::phone_name, [](Application *app, const std::string &name) {
return std::make_unique<gui::PhoneNameWindow>(app);
M module-apps/application-settings/CMakeLists.txt => module-apps/application-settings/CMakeLists.txt +1 -0
@@ 31,6 31,7 @@ target_sources(application-settings
models/system/SARInfoRepository.cpp
models/system/TechnicalInformationModel.cpp
models/system/TechnicalInformationRepository.cpp
+ models/bluetooth/BluetoothSettingsModel.cpp
presenter/network/SimContactsImportWindowPresenter.cpp
presenter/system/SARInfoWindowPresenter.cpp
presenter/system/TechnicalWindowPresenter.cpp
M module-apps/application-settings/include/application-settings/ApplicationSettings.hpp => module-apps/application-settings/include/application-settings/ApplicationSettings.hpp +2 -0
@@ 11,6 11,7 @@
#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <EventStore.hpp>
+#include <application-settings/models/bluetooth/BluetoothSettingsModel.hpp>
class AudioStopNotification; // Forward declaration
@@ 188,6 189,7 @@ namespace app
bool callsFromFavorites = false;
int connectionFrequency = 0;
bool flightModeOn = true;
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel = nullptr;
};
template <> struct ManifestTraits<ApplicationSettings>
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp +84 -25
@@ 8,80 8,139 @@
#include <service-bluetooth/messages/Connect.hpp>
#include <service-bluetooth/messages/DeviceName.hpp>
#include <service-bluetooth/messages/Disconnect.hpp>
-#include <service-bluetooth/messages/Status.hpp>
#include <service-bluetooth/messages/SetStatus.hpp>
#include <service-bluetooth/messages/SetDeviceName.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
+#include <service-bluetooth/messages/SyncDevices.hpp>
-BluetoothSettingsModel::BluetoothSettingsModel(app::Application *application) : application{application}
+BluetoothSettingsModel::BluetoothSettingsModel(sys::Service *service) : service{service}
{}
void BluetoothSettingsModel::requestStatus()
{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestStatus>(), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestStatus>(), service::name::bluetooth);
}
void BluetoothSettingsModel::setStatus(const bool desiredBluetoothState, const bool desiredVisibility)
{
- BluetoothStatus status{.state = desiredBluetoothState ? BluetoothStatus::State::On : BluetoothStatus::State::Off,
- .visibility = desiredVisibility};
+ status.state = desiredBluetoothState ? BluetoothStatus::State::On : BluetoothStatus::State::Off;
+ status.visibility = desiredVisibility;
message::bluetooth::SetStatus setStatus(status);
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
+ service::name::bluetooth);
}
void BluetoothSettingsModel::requestDeviceName()
{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestDeviceName>(), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestDeviceName>(), service::name::bluetooth);
}
void BluetoothSettingsModel::setDeviceName(const UTF8 &deviceName)
{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::SetDeviceName>(deviceName),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::SetDeviceName>(deviceName), service::name::bluetooth);
}
void BluetoothSettingsModel::requestBondedDevices()
{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(), service::name::bluetooth);
}
void BluetoothSettingsModel::requestScan()
{
- application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Scan),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Scan),
+ service::name::bluetooth);
}
void BluetoothSettingsModel::stopScan()
{
- application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::StopScan),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::StopScan),
+ service::name::bluetooth);
}
-void BluetoothSettingsModel::requestDevicePair(const std::string &addr)
+void BluetoothSettingsModel::requestDevicePair(const Devicei &device)
{
- application->bus.sendUnicast(std::make_shared<BluetoothPairMessage>(addr), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<BluetoothPairMessage>(device), service::name::bluetooth);
}
-void BluetoothSettingsModel::requestDeviceUnpair(const std::string &addr)
+void BluetoothSettingsModel::requestDeviceUnpair(const Devicei &device)
{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Unpair>(addr), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::Unpair>(device), service::name::bluetooth);
}
void BluetoothSettingsModel::responsePasskey(const std::string &passkey)
{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey),
- service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey), service::name::bluetooth);
}
-void BluetoothSettingsModel::requestConnection(const std::string &addr)
+void BluetoothSettingsModel::requestConnection(const Devicei &device)
{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Connect>(addr), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::Connect>(device), service::name::bluetooth);
}
void BluetoothSettingsModel::requestDisconnection()
{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Disconnect>(), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::Disconnect>(), service::name::bluetooth);
+}
+void BluetoothSettingsModel::replaceDevicesList(const std::vector<Devicei> &devicesList)
+{
+ devices = devicesList;
+}
+void BluetoothSettingsModel::setActiveDeviceState(const DeviceState &state)
+{
+ auto activeDevice = getActiveDevice();
+ if (activeDevice.has_value()) {
+ activeDevice.value().get().deviceState = state;
+ }
+}
+auto BluetoothSettingsModel::getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>
+{
+ try {
+ return devices.at(activeDeviceIndex);
+ }
+ catch (const std::out_of_range &oor) {
+ LOG_WARN("NO DEVICE FOUND!");
+ return std::nullopt;
+ }
+}
+auto BluetoothSettingsModel::getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>
+{
+ try {
+ return devices.at(selectedDeviceIndex);
+ }
+ catch (const std::out_of_range &oor) {
+ LOG_WARN("NO DEVICE FOUND!");
+ return std::nullopt;
+ }
+}
+void BluetoothSettingsModel::setActiveDevice(const Devicei &device)
+{
+ auto itr = std::find(std::begin(devices), std::end(devices), device);
+ activeDeviceIndex = std::distance(std::begin(devices), itr);
+}
+void BluetoothSettingsModel::setSelectedDevice(const Devicei &device)
+{
+ auto itr = std::find(std::begin(devices), std::end(devices), device);
+ selectedDeviceIndex = std::distance(std::begin(devices), itr);
+}
+
+auto BluetoothSettingsModel::getDevices() -> std::vector<Devicei> &
+{
+ return devices;
+}
+auto BluetoothSettingsModel::isDeviceConnecting() -> bool
+{
+
+ auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [](const Devicei &device) {
+ return device.deviceState == DeviceState::Connecting;
+ });
+
+ if (deviceIt != std::end(devices)) {
+ return true;
+ }
+ return false;
+}
+auto BluetoothSettingsModel::getStatus() const -> const BluetoothStatus
+{
+ return status;
}
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp +21 -5
@@ 4,6 4,8 @@
#pragma once
#include "Application.hpp"
+#include <Device.hpp>
+#include <service-bluetooth/messages/Status.hpp>
extern "C"
{
@@ 13,7 15,7 @@ extern "C"
class BluetoothSettingsModel
{
public:
- explicit BluetoothSettingsModel(app::Application *application);
+ explicit BluetoothSettingsModel(sys::Service *service);
void requestStatus();
void setStatus(bool desiredBluetoothState, bool desiredVisibility);
@@ 22,12 24,26 @@ class BluetoothSettingsModel
void requestBondedDevices();
void requestScan();
void stopScan();
- void requestDevicePair(const std::string &addr);
- void requestDeviceUnpair(const std::string &addr);
+ void requestDevicePair(const Devicei &device);
+ void requestDeviceUnpair(const Devicei &device);
void responsePasskey(const std::string &passkey);
- void requestConnection(const std::string &addr);
+ void requestConnection(const Devicei &device);
void requestDisconnection();
+ void replaceDevicesList(const std::vector<Devicei> &devicesList);
+ void setActiveDeviceState(const DeviceState &state);
+ auto getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>;
+ auto getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>;
+ void setActiveDevice(const Devicei &device);
+ void setSelectedDevice(const Devicei &device);
+ auto getDevices() -> std::vector<Devicei> &;
+ auto isDeviceConnecting() -> bool;
+ auto getStatus() const -> const BluetoothStatus;
+
private:
- app::Application *application = nullptr;
+ std::vector<Devicei> devices{};
+ std::uint16_t activeDeviceIndex = 0;
+ std::uint16_t selectedDeviceIndex = 0;
+ sys::Service *service = nullptr;
+ BluetoothStatus status{};
};
M module-apps/application-settings/windows/bluetooth/AddDeviceWindow.cpp => module-apps/application-settings/windows/bluetooth/AddDeviceWindow.cpp +6 -7
@@ 12,9 12,10 @@
namespace gui
{
- AddDeviceWindow::AddDeviceWindow(app::Application *app) : BaseSettingsWindow(app, window::name::add_device)
+ AddDeviceWindow::AddDeviceWindow(app::Application *app,
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel)
+ : BaseSettingsWindow(app, window::name::add_device), bluetoothSettingsModel(bluetoothSettingsModel)
{
- bluetoothSettingsModel = std::make_unique<BluetoothSettingsModel>(application);
}
void AddDeviceWindow::onBeforeShow(ShowMode /*mode*/, SwitchData *data)
@@ 35,13 36,11 @@ namespace gui
{
std::list<gui::Option> optionsList;
- for (const auto &device : devices) {
+ for (auto &device : devices) {
optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
device.name,
- [=](gui::Item & /*unused*/) {
- auto pairingDeviceData = std::make_unique<PairingDeviceData>(device);
- application->switchWindow(gui::window::name::all_devices, std::move(pairingDeviceData));
- bluetoothSettingsModel->requestDevicePair(bd_addr_to_str(device.address));
+ [&](gui::Item & /*unused*/) {
+ bluetoothSettingsModel->requestDevicePair(device);
application->switchWindow(gui::window::name::all_devices);
return true;
},
M module-apps/application-settings/windows/bluetooth/AddDeviceWindow.hpp => module-apps/application-settings/windows/bluetooth/AddDeviceWindow.hpp +2 -2
@@ 13,14 13,14 @@ namespace gui
class AddDeviceWindow : public BaseSettingsWindow
{
public:
- explicit AddDeviceWindow(app::Application *app);
+ AddDeviceWindow(app::Application *app, std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel);
private:
void onBeforeShow(ShowMode mode, SwitchData *data) override;
void onClose(CloseReason reason) override;
auto buildOptionsList() -> std::list<Option> override;
- std::unique_ptr<BluetoothSettingsModel> bluetoothSettingsModel;
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel{};
std::vector<Devicei> devices;
};
}; // namespace gui
M module-apps/application-settings/windows/bluetooth/AllDevicesWindow.cpp => module-apps/application-settings/windows/bluetooth/AllDevicesWindow.cpp +60 -74
@@ 4,8 4,8 @@
#include "AllDevicesWindow.hpp"
#include <application-settings/data/BondedDevicesData.hpp>
-#include <application-settings/data/PairingDeviceData.hpp>
#include <application-settings/windows/WindowNames.hpp>
+#include <application-settings/widgets/SettingsStyle.hpp>
#include <DialogMetadataMessage.hpp>
#include <InputEvent.hpp>
@@ 15,10 15,10 @@
namespace gui
{
- AllDevicesWindow::AllDevicesWindow(app::Application *app) : BaseSettingsWindow(app, window::name::all_devices)
+ AllDevicesWindow::AllDevicesWindow(app::Application *app,
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel)
+ : BaseSettingsWindow(app, window::name::all_devices), bluetoothSettingsModel(bluetoothSettingsModel)
{
- bluetoothSettingsModel = std::make_unique<BluetoothSettingsModel>(application);
- bluetoothSettingsModel->requestBondedDevices();
buildInterface();
}
@@ 45,31 45,9 @@ namespace gui
{
if (mode == ShowMode::GUI_SHOW_RETURN) {
bluetoothSettingsModel->stopScan();
- if (activeDevice.state == ActiveDevice::DeviceState::Connecting) {
- activeDevice.address.clear();
- activeDevice.state = ActiveDevice::DeviceState::Unknown;
- }
- else if (activeDevice.state == ActiveDevice::DeviceState::Pairing) {
- devices.erase(std::remove_if(devices.begin(),
- devices.end(),
- [&](const auto &device) {
- return (bd_addr_to_str(device.address) == activeDevice.address);
- }),
- devices.end());
-
- activeDevice.address.clear();
- activeDevice.state = ActiveDevice::DeviceState::Unknown;
- }
}
if (const auto bondedDevicesData = dynamic_cast<BondedDevicesData *>(data); bondedDevicesData != nullptr) {
- devices = bondedDevicesData->getDevices();
- activeDevice.address = bondedDevicesData->getAddressOfConnectedDevice();
- activeDevice.state = ActiveDevice::DeviceState::Connected;
- }
- else if (const auto pairingDeviceData = dynamic_cast<PairingDeviceData *>(data); pairingDeviceData != nullptr) {
- activeDevice.address = bd_addr_to_str(pairingDeviceData->getPairingDevice().address);
- activeDevice.state = ActiveDevice::DeviceState::Pairing;
- devices.emplace_back(pairingDeviceData->getPairingDevice());
+ bluetoothSettingsModel->replaceDevicesList(bondedDevicesData->getDevices());
}
refreshOptionsList();
}
@@ 90,15 68,12 @@ namespace gui
return true;
}
if (inputEvent.is(KeyCode::KEY_LF)) {
- devices.erase(std::remove_if(devices.begin(),
- devices.end(),
- [&](const auto &device) {
- return (bd_addr_to_str(device.address) == addressOfDeviceSelected);
- }),
- devices.end());
bottomBar->setActive(BottomBar::Side::LEFT, false);
bottomBar->setActive(BottomBar::Side::CENTER, false);
- bluetoothSettingsModel->requestDeviceUnpair(addressOfDeviceSelected);
+ auto selectedDevice = bluetoothSettingsModel->getSelectedDevice();
+ if (selectedDevice.has_value()) {
+ bluetoothSettingsModel->requestDeviceUnpair(selectedDevice.value().get());
+ }
refreshOptionsList();
return true;
}
@@ 107,30 82,25 @@ namespace gui
auto AllDevicesWindow::buildOptionsList() -> std::list<Option>
{
- bottomBar->setActive(BottomBar::Side::CENTER, !devices.empty());
-
+ bottomBar->setActive(BottomBar::Side::CENTER, !bluetoothSettingsModel->getDevices().empty());
std::list<gui::Option> optionsList;
- for (const auto &device : devices) {
- ActiveDevice newDevice(bd_addr_to_str(device.address));
- newDevice.address == activeDevice.address ? newDevice.state = activeDevice.state
- : newDevice.state = ActiveDevice::DeviceState::Paired;
- UTF8 textOnCenter = getTextOnCenter(newDevice.state);
- option::SettingRightItem rightItem = getRightItem(newDevice.state);
- UTF8 textOnRight = getTextOnRight(newDevice.state);
+
+ for (const auto &device : bluetoothSettingsModel->getDevices()) {
+ UTF8 textOnCenter = getTextOnCenter(device.deviceState);
+ option::SettingRightItem rightItem = getRightItem(device.deviceState);
+ UTF8 textOnRight = getTextOnRight(device.deviceState);
optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
device.name,
- [=](gui::Item & /*item*/) {
- return handleDeviceAction(newDevice);
- },
+ [=](gui::Item & /*item*/) { return handleDeviceAction(device); },
[=](gui::Item &item) {
if (item.focus) {
this->setBottomBarText(textOnCenter, BottomBar::Side::CENTER);
- if (newDevice.state != ActiveDevice::DeviceState::Pairing) {
+ if (device.deviceState != DeviceState::Pairing) {
this->setBottomBarText(utils::translate("common_forget"), BottomBar::Side::LEFT);
this->bottomBar->setActive(BottomBar::Side::LEFT, true);
}
- addressOfDeviceSelected = newDevice.address;
+ bluetoothSettingsModel->setSelectedDevice(device);
}
return true;
},
@@ 142,64 112,80 @@ namespace gui
return optionsList;
}
- UTF8 AllDevicesWindow::getTextOnCenter(const ActiveDevice::DeviceState &state) const
+ UTF8 AllDevicesWindow::getTextOnCenter(const DeviceState &state) const
{
switch (state) {
- case ActiveDevice::DeviceState::Connected:
+ case DeviceState::Connected:
return utils::translate("common_disconnect");
- case ActiveDevice::DeviceState::Paired:
+ case DeviceState::Paired:
+ if (bluetoothSettingsModel->isDeviceConnecting()) {
+ break;
+ }
return utils::translate("common_connect");
- case ActiveDevice::DeviceState::Pairing:
- case ActiveDevice::DeviceState::Connecting:
- case ActiveDevice::DeviceState::Unknown:
+ case DeviceState::Pairing:
+ [[fallthrough]];
+ case DeviceState::Connecting:
+ [[fallthrough]];
+ case DeviceState::Unknown:
+ [[fallthrough]];
+ case DeviceState::ConnectedAudio:
+ [[fallthrough]];
+ case DeviceState::ConnectedVoice:
break;
}
return UTF8();
}
- UTF8 AllDevicesWindow::getTextOnRight(const ActiveDevice::DeviceState &state) const
+ UTF8 AllDevicesWindow::getTextOnRight(const DeviceState &state) const
{
switch (state) {
- case ActiveDevice::DeviceState::Connected:
+ case DeviceState::Connected:
return utils::translate("app_settings_option_connected");
- case ActiveDevice::DeviceState::Connecting:
+ case DeviceState::Connecting:
return utils::translate("app_settings_option_connecting");
- case ActiveDevice::DeviceState::Pairing:
+ case DeviceState::Pairing:
return utils::translate("app_settings_option_pairing");
- case ActiveDevice::DeviceState::Paired:
- case ActiveDevice::DeviceState::Unknown:
+ case DeviceState::Paired:
+ [[fallthrough]];
+ case DeviceState::Unknown:
+ [[fallthrough]];
+ case DeviceState::ConnectedAudio:
+ [[fallthrough]];
+ case DeviceState::ConnectedVoice:
break;
}
return UTF8();
}
- option::SettingRightItem AllDevicesWindow::getRightItem(const ActiveDevice::DeviceState &state) const
+ option::SettingRightItem AllDevicesWindow::getRightItem(const DeviceState &state) const
{
switch (state) {
- case ActiveDevice::DeviceState::Connected:
- case ActiveDevice::DeviceState::Connecting:
- case ActiveDevice::DeviceState::Pairing:
+ case DeviceState::Connected:
+ [[fallthrough]];
+ case DeviceState::Connecting:
+ [[fallthrough]];
+ case DeviceState::Pairing:
return option::SettingRightItem::Text;
- case ActiveDevice::DeviceState::Paired:
+ case DeviceState::Paired:
return option::SettingRightItem::Bt;
- case ActiveDevice::DeviceState::Unknown:
+ case DeviceState::Unknown:
+ [[fallthrough]];
+ case DeviceState::ConnectedAudio:
+ [[fallthrough]];
+ case DeviceState::ConnectedVoice:
break;
}
return option::SettingRightItem::Disabled;
}
- auto AllDevicesWindow::handleDeviceAction(const ActiveDevice &newDevice) -> bool
+ auto AllDevicesWindow::handleDeviceAction(const Devicei &device) -> bool
{
- if (newDevice.state == ActiveDevice::DeviceState::Connected) {
- activeDevice.address.clear();
- activeDevice.state = ActiveDevice::DeviceState::Unknown;
+ if (device.deviceState == DeviceState::Connected) {
bluetoothSettingsModel->requestDisconnection();
refreshOptionsList();
}
- else if (newDevice.state == ActiveDevice::DeviceState::Paired) {
- activeDevice.address = newDevice.address;
- activeDevice.state = ActiveDevice::DeviceState::Connecting;
- bluetoothSettingsModel->requestConnection(newDevice.address);
+ else if (device.deviceState == DeviceState::Paired && !bluetoothSettingsModel->isDeviceConnecting()) {
+ bluetoothSettingsModel->requestConnection(device);
refreshOptionsList();
}
return true;
M module-apps/application-settings/windows/bluetooth/AllDevicesWindow.hpp => module-apps/application-settings/windows/bluetooth/AllDevicesWindow.hpp +7 -30
@@ 2,52 2,29 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include <application-settings/models/bluetooth/BluetoothSettingsModel.hpp>
#include <application-settings/windows/BaseSettingsWindow.hpp>
-
-#include <Device.hpp>
+#include <application-settings/models/bluetooth/BluetoothSettingsModel.hpp>
namespace gui
{
class Image;
- class ActiveDevice
- {
- public:
- explicit ActiveDevice(std::string address) : address(std::move(address))
- {}
- ActiveDevice() = default;
- enum class DeviceState
- {
- Connected,
- Connecting,
- Pairing,
- Paired,
- Unknown
- };
- DeviceState state = DeviceState::Unknown;
- std::string address;
- };
-
class AllDevicesWindow : public BaseSettingsWindow
{
public:
- explicit AllDevicesWindow(app::Application *app);
+ AllDevicesWindow(app::Application *app, std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel);
private:
void buildInterface() override;
auto buildOptionsList() -> std::list<Option> override;
void onBeforeShow(ShowMode mode, SwitchData *data) override;
auto onInput(const InputEvent &inputEvent) -> bool override;
- UTF8 getTextOnCenter(const ActiveDevice::DeviceState &) const;
- UTF8 getTextOnRight(const ActiveDevice::DeviceState &) const;
- option::SettingRightItem getRightItem(const ActiveDevice::DeviceState &) const;
- auto handleDeviceAction(const ActiveDevice &) -> bool;
+ UTF8 getTextOnCenter(const DeviceState &) const;
+ UTF8 getTextOnRight(const DeviceState &) const;
+ option::SettingRightItem getRightItem(const DeviceState &) const;
+ auto handleDeviceAction(const Devicei &) -> bool;
- ActiveDevice activeDevice;
- std::vector<Devicei> devices{};
- std::string addressOfDeviceSelected;
- std::unique_ptr<BluetoothSettingsModel> bluetoothSettingsModel{};
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel{};
};
} // namespace gui
M module-apps/application-settings/windows/bluetooth/PhoneNameWindow.hpp => module-apps/application-settings/windows/bluetooth/PhoneNameWindow.hpp +0 -1
@@ 3,7 3,6 @@
#pragma once
#include <application-settings/models/bluetooth/BluetoothSettingsModel.hpp>
-
#include <Text.hpp>
namespace gui
M module-apps/tests/CMakeLists.txt => module-apps/tests/CMakeLists.txt +1 -0
@@ 5,6 5,7 @@ add_catch2_executable(
tests-main.cpp
test-CallbackStorage.cpp
test-PhoneModesPolicies.cpp
+ tests-BluetoothSettingsModel.cpp
LIBS
module-apps
)
A module-apps/tests/tests-BluetoothSettingsModel.cpp => module-apps/tests/tests-BluetoothSettingsModel.cpp +145 -0
@@ 0,0 1,145 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <catch2/catch.hpp>
+#include "Device.hpp"
+#include "application-settings/models/bluetooth/BluetoothSettingsModel.hpp"
+
+TEST_CASE("Devicei comparison")
+{
+ Devicei device1{"Dev1"};
+ Devicei device2{"Dev2"};
+ Devicei device3{"Dev1"};
+
+ bd_addr_t addr1;
+ bd_addr_t addr2;
+
+ std::string addr1Str{"00:12:6F:E7:9D:05"};
+ std::string addr2Str{"F8:5C:7D:17:E4:8F"};
+
+ sscanf_bd_addr(addr1Str.c_str(), addr1);
+ sscanf_bd_addr(addr2Str.c_str(), addr2);
+
+ SECTION("Same addresses and names")
+ {
+ device1.setAddress(&addr1);
+ device3.setAddress(&addr1);
+ REQUIRE(device1 == device3);
+ }
+
+ SECTION("Different addresses and names")
+ {
+ device1.setAddress(&addr1);
+ device2.setAddress(&addr2);
+ REQUIRE_FALSE(device1 == device3);
+ }
+
+ SECTION("Same names and different addresses")
+ {
+ device1.setAddress(&addr1);
+ device3.setAddress(&addr2);
+ REQUIRE_FALSE(device1 == device3);
+ }
+}
+
+TEST_CASE("Device handling")
+{
+ BluetoothSettingsModel settingsModel{nullptr};
+
+ Devicei device1{"Dev1"};
+ Devicei device2{"Dev2"};
+ Devicei device3{"Dev1"};
+ Devicei device4{"Dev4"};
+ Devicei dummy{""};
+
+ bd_addr_t addr1;
+ bd_addr_t addr2;
+ bd_addr_t addr3;
+
+ std::string addr1Str{"00:12:6F:E7:9D:05"};
+ std::string addr2Str{"F8:5C:7D:17:E4:8F"};
+ std::string addr3Str{"F8:5C:7D:17:E4:00"};
+
+ sscanf_bd_addr(addr1Str.c_str(), addr1);
+ sscanf_bd_addr(addr2Str.c_str(), addr2);
+ sscanf_bd_addr(addr3Str.c_str(), addr3);
+
+ device1.setAddress(&addr1);
+ device2.setAddress(&addr2);
+ device3.setAddress(&addr1);
+ device4.setAddress(&addr2);
+
+ std::vector<Devicei> devicesList;
+
+ devicesList.push_back(device1);
+ devicesList.push_back(device2);
+ devicesList.push_back(device3);
+
+ SECTION("Replace devices list")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+ REQUIRE(settingsModel.getDevices().size() == 3);
+ REQUIRE(settingsModel.getDevices() == devicesList);
+ }
+
+ SECTION("Set active device")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setActiveDevice(device2);
+ REQUIRE(settingsModel.getActiveDevice().has_value());
+ REQUIRE(settingsModel.getActiveDevice().value().get() == device2);
+ }
+
+ SECTION("Set wrong active device")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setActiveDevice(device4);
+ REQUIRE_FALSE(settingsModel.getActiveDevice().has_value());
+ }
+
+ SECTION("Set selected device")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setSelectedDevice(device2);
+ REQUIRE(settingsModel.getSelectedDevice().has_value());
+ REQUIRE(settingsModel.getSelectedDevice().value().get() == device2);
+ }
+
+ SECTION("Set wrong selected device")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setSelectedDevice(device4);
+ REQUIRE_FALSE(settingsModel.getSelectedDevice().has_value());
+ }
+
+ SECTION("Set active device state")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setActiveDevice(device2);
+ settingsModel.setActiveDeviceState(DeviceState::Connected);
+ REQUIRE(settingsModel.getActiveDevice().value().get().deviceState == DeviceState::Connected);
+ }
+
+ SECTION("Is device connecting? - true")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setActiveDevice(device2);
+ settingsModel.setActiveDeviceState(DeviceState::Connecting);
+ REQUIRE(settingsModel.isDeviceConnecting());
+ }
+
+ SECTION("Is device connecting? - false")
+ {
+ settingsModel.replaceDevicesList(devicesList);
+
+ settingsModel.setActiveDevice(device2);
+ settingsModel.setActiveDeviceState(DeviceState::Connected);
+ REQUIRE_FALSE(settingsModel.isDeviceConnecting());
+ }
+}
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +3 -1
@@ 158,7 158,9 @@ auto BluetoothWorker::handleCommand(QueueHandle_t queue) -> bool
break;
case bluetooth::Command::Unpair:
controller->processCommand(command);
- removeFromBoundDevices(command.getAddress());
+ removeFromBoundDevices(command.getDevice().address);
+ break;
+ case bluetooth::Command::None:
break;
default:
controller->processCommand(command);
M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +10 -10
@@ 52,15 52,15 @@ namespace bluetooth
case bluetooth::Command::StartPan:
return startPan();
case bluetooth::Command::Pair:
- return pair(command.getAddress());
+ return pair(command.getDevice());
case bluetooth::Command::Unpair:
- return unpair(command.getAddress());
+ return unpair(command.getDevice());
case bluetooth::Command::VisibilityOn:
return setVisibility(true);
case bluetooth::Command::VisibilityOff:
return setVisibility(false);
case bluetooth::Command::ConnectAudio:
- return establishAudioConnection(command.getAddress());
+ return establishAudioConnection(command.getDevice());
case bluetooth::Command::DisconnectAudio:
return disconnectAudioConnection();
case bluetooth::Command::PowerOff:
@@ 122,11 122,11 @@ namespace bluetooth
return Error::Success;
}
- Error::Code CommandHandler::establishAudioConnection(uint8_t *addr)
+ Error::Code CommandHandler::establishAudioConnection(const Devicei &device)
{
profileManager->init();
LOG_INFO("Connecting audio");
- profileManager->connect(addr);
+ profileManager->connect(device);
return Error::Success;
}
@@ 136,10 136,10 @@ namespace bluetooth
profileManager->disconnect();
return Error::Success;
}
- Error::Code CommandHandler::pair(bd_addr_t addr)
+ Error::Code CommandHandler::pair(const Devicei &device)
{
LOG_INFO("Pairing...");
- const auto error_code = driver->pair(addr) ? Error::Success : Error::LibraryError;
+ const auto error_code = driver->pair(device) ? Error::Success : Error::LibraryError;
LOG_INFO("Pairing result: %s", magic_enum::enum_name(error_code).data());
return error_code;
}
@@ 157,13 157,13 @@ namespace bluetooth
profileManager->switchProfile(profile);
return Error::Success;
}
- Error::Code CommandHandler::unpair(uint8_t *addr)
+ Error::Code CommandHandler::unpair(const Devicei &device)
{
LOG_INFO("Unpairing...");
- if (profileManager->isAddressActuallyUsed(addr)) {
+ if (profileManager->isAddressActuallyUsed(device.address)) {
profileManager->disconnect();
}
- const auto error_code = driver->unpair(addr) ? Error::Success : Error::LibraryError;
+ const auto error_code = driver->unpair(device) ? Error::Success : Error::LibraryError;
LOG_INFO("Unpairing result: %s", magic_enum::enum_name(error_code).data());
return error_code;
}
M module-bluetooth/Bluetooth/CommandHandler.hpp => module-bluetooth/Bluetooth/CommandHandler.hpp +9 -12
@@ 44,13 44,10 @@ namespace bluetooth
None,
};
- explicit Command(Command::Type type, std::optional<uint8_t *> addr = std::nullopt) : type(type)
+ explicit Command(Command::Type type, std::optional<Devicei> dev = std::nullopt) : type(type)
{
- if (addr) {
- bd_addr_copy(address, addr.value());
- }
- else {
- memset(address, 0, sizeof(bd_addr_t));
+ if (dev.has_value()) {
+ device = dev.value();
}
}
@@ 59,13 56,13 @@ namespace bluetooth
return type;
}
- auto getAddress() -> uint8_t *
+ auto getDevice() const noexcept -> Devicei
{
- return address;
+ return device;
}
private:
- bd_addr_t address{};
+ Devicei device{};
Type type;
};
@@ 92,10 89,10 @@ namespace bluetooth
Error::Code stopScan();
Error::Code startPan();
Error::Code setVisibility(bool visibility);
- Error::Code establishAudioConnection(bd_addr_t addr);
+ Error::Code establishAudioConnection(const Devicei &device);
Error::Code disconnectAudioConnection();
- Error::Code pair(bd_addr_t addr);
- Error::Code unpair(bd_addr_t addr);
+ Error::Code pair(const Devicei &device);
+ Error::Code unpair(const Devicei &device);
Error::Code availableDevices();
Error::Code switchAudioProfile();
sys::Service *service;
M module-bluetooth/Bluetooth/Device.hpp => module-bluetooth/Bluetooth/Device.hpp +32 -2
@@ 5,6 5,7 @@
#include <array>
#include <cstring>
#include <module-bluetooth/lib/btstack/src/bluetooth.h>
+#include <btstack_util.h>
#include <string>
#include <utility>
@@ 73,6 74,17 @@ static inline std::string getListOfSupportedServicesInString(uint32_t cod)
return res;
}
+enum class DeviceState
+{
+ Connected,
+ ConnectedAudio,
+ ConnectedVoice,
+ Connecting,
+ Pairing,
+ Paired,
+ Unknown
+};
+
struct Devicei : public Device
{
public:
@@ 81,14 93,32 @@ struct Devicei : public Device
uint16_t clockOffset;
uint32_t classOfDevice; ///> Class of Device/Service
DEVICE_STATE state;
+ DeviceState deviceState;
- Devicei(std::string name = "") : Device(std::move(name))
- {}
+ explicit Devicei(std::string name = "") : Device(std::move(name))
+ {
+ memset(address, 0, sizeof(address));
+ }
~Devicei() override = default;
void setAddress(bd_addr_t *addr)
{
memcpy(&address, addr, sizeof address);
}
+
+ inline bool operator==(const Devicei &cmpDevice) const
+ {
+ return (cmpDevice.name == name) && (bd_addr_cmp(cmpDevice.address, address) == 0);
+ }
+
+ inline bool operator!=(const Devicei &cmpDevice) const
+ {
+ return (cmpDevice.name != name) || (bd_addr_cmp(cmpDevice.address, address) != 0);
+ }
+
+ auto address_str() const -> const char *
+ {
+ return bd_addr_to_str(address);
+ }
};
struct DeviceMetadata_t
M module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp +3 -2
@@ 4,6 4,7 @@
#pragma once
#include <functional>
+#include "Device.hpp"
#include "Error.hpp"
namespace bluetooth
@@ 20,8 21,8 @@ namespace bluetooth
[[nodiscard]] virtual auto scan() -> Error = 0;
virtual void stopScan() = 0;
virtual void setVisibility(bool visibility) = 0;
- [[nodiscard]] virtual auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool = 0;
- [[nodiscard]] virtual auto unpair(uint8_t *addr) -> bool = 0;
+ [[nodiscard]] virtual auto pair(Devicei device, std::uint8_t protectionLevel = 0) -> bool = 0;
+ [[nodiscard]] virtual auto unpair(Devicei device) -> bool = 0;
virtual void registerErrorCallback(const ErrorCallback &newCallback) = 0;
};
M module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp +5 -4
@@ 203,12 203,13 @@ namespace bluetooth
{
gap->setVisibility(visibility);
}
- auto Driver::pair(uint8_t *addr, std::uint8_t protectionLevel) -> bool
+ auto Driver::pair(Devicei device, std::uint8_t protectionLevel) -> bool
{
- return gap->pair(addr, protectionLevel);
+ LOG_FATAL("Device: %s, addr: %s", device.name.c_str(), device.address_str());
+ return gap->pair(device, protectionLevel);
}
- auto Driver::unpair(uint8_t *addr) -> bool
+ auto Driver::unpair(Devicei device) -> bool
{
- return gap->unpair(addr);
+ return gap->unpair(device);
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp +2 -2
@@ 40,7 40,7 @@ namespace bluetooth
auto scan() -> Error override;
void stopScan() override;
void setVisibility(bool visibility) override;
- auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool override;
- auto unpair(uint8_t *addr) -> bool override;
+ auto pair(Devicei device, std::uint8_t protectionLevel = 0) -> bool override;
+ auto unpair(Devicei device) -> bool override;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +15 -15
@@ 64,9 64,9 @@ namespace bluetooth
return pimpl->init();
}
- void A2DP::setDeviceAddress(uint8_t *addr)
+ void A2DP::setDevice(const Devicei &device)
{
- pimpl->setDeviceAddress(addr);
+ pimpl->setDevice(device);
}
void A2DP::setOwnerService(const sys::Service *service)
@@ 118,7 118,6 @@ namespace bluetooth
const sys::Service *A2DP::A2DPImpl::ownerService;
QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;
QueueHandle_t A2DP::A2DPImpl::sinkQueue = nullptr;
- bd_addr_t A2DP::A2DPImpl::deviceAddr;
DeviceMetadata_t A2DP::A2DPImpl::metadata;
btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration;
std::array<uint8_t, 150> A2DP::A2DPImpl::sdpSourceServiceBuffer;
@@ 130,6 129,7 @@ namespace bluetooth
std::shared_ptr<BluetoothAudioDevice> A2DP::A2DPImpl::audioDevice;
bool A2DP::A2DPImpl::isConnected = false;
+ Devicei A2DP::A2DPImpl::device;
/* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
auto A2DP::A2DPImpl::init() -> Error::Code
@@ 329,9 329,8 @@ namespace bluetooth
AVRCP::mediaTracker.a2dp_cid = 0;
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(
- std::make_shared<message::bluetooth::ConnectResult>(std::move(deviceAddress), false),
- service::name::bluetooth);
+ busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, false),
+ service::name::bluetooth);
break;
}
AVRCP::mediaTracker.a2dp_cid = cid;
@@ 342,7 341,7 @@ namespace bluetooth
AVRCP::mediaTracker.local_seid);
isConnected = true;
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(std::move(deviceAddress), true),
+ busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, true),
service::name::bluetooth);
break;
}
@@ 550,7 549,9 @@ namespace bluetooth
avrcp_target_set_playback_status(AVRCP::mediaTracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
}
-
+ auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
+ busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
stopTimer(&AVRCP::mediaTracker);
break;
}
@@ 560,9 561,6 @@ namespace bluetooth
AVRCP::mediaTracker.avrcp_cid = 0;
AVRCP::mediaTracker.a2dp_cid = 0;
LOG_INFO("A2DP Source: Signaling released.\n\n");
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(),
- service::name::bluetooth);
}
isConnected = false;
break;
@@ 577,19 575,21 @@ namespace bluetooth
disconnect();
}
LOG_INFO("Starting playback");
- a2dp_source_establish_stream(deviceAddr, &AVRCP::mediaTracker.a2dp_cid);
+ a2dp_source_establish_stream(device.address, &AVRCP::mediaTracker.a2dp_cid);
}
void A2DP::A2DPImpl::disconnect()
{
LOG_INFO("Stopping playback");
a2dp_source_disconnect(AVRCP::mediaTracker.a2dp_cid);
+ auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
+ busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device), service::name::bluetooth);
}
- void A2DP::A2DPImpl::setDeviceAddress(bd_addr_t addr)
+ void A2DP::A2DPImpl::setDevice(const Devicei &dev)
{
- bd_addr_copy(deviceAddr, addr);
- LOG_INFO("Address set!");
+ device = dev;
+ LOG_INFO("Device set!");
}
void A2DP::A2DPImpl::setOwnerService(const sys::Service *service)
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +1 -1
@@ 23,7 23,7 @@ namespace bluetooth
auto operator=(A2DP &&other) noexcept -> A2DP &;
auto init() -> Error::Code override;
- void setDeviceAddress(uint8_t *addr) override;
+ void setDevice(const Devicei &device) override;
void setOwnerService(const sys::Service *service) override;
void connect() override;
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +2 -2
@@ 34,7 34,6 @@ namespace bluetooth
static constexpr int MEDIA_CAP_SIZE = 4;
static std::array<uint8_t, SDP_BUFFER_LENGTH> sdpSourceServiceBuffer;
- static bd_addr_t deviceAddr;
static btstack_packet_callback_registration_t hciEventCallbackRegistration;
static std::array<uint8_t, MEDIA_CAP_SIZE> mediaSbcCodecCapabilities;
static const sys::Service *ownerService;
@@ 51,6 50,7 @@ namespace bluetooth
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
static bool isConnected;
static std::shared_ptr<BluetoothAudioDevice> audioDevice;
+ static Devicei device;
public:
auto init() -> Error::Code;
@@ 58,7 58,7 @@ namespace bluetooth
void disconnect();
void start();
void stop();
- void setDeviceAddress(bd_addr_t addr);
+ void setDevice(const Devicei &dev);
void setOwnerService(const sys::Service *service);
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +16 -20
@@ 8,7 8,6 @@
#include <service-bluetooth/messages/ResponseVisibleDevices.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
-#include <application-settings/ApplicationSettings.hpp>
extern "C"
{
#include "btstack.h"
@@ 16,7 15,7 @@ extern "C"
};
namespace bluetooth
{
- std::string GAP::currentlyProcessedDeviceAddr;
+ Devicei GAP::currentlyProccesedDevice;
sys::Service *GAP::ownerService = nullptr;
std::vector<Devicei> GAP::devices;
btstack_packet_callback_registration_t GAP::cb_handler;
@@ 59,16 58,18 @@ namespace bluetooth
LOG_INFO("Visibility: %s", visibility ? "true" : "false");
}
- auto GAP::pair(std::uint8_t *addr, std::uint8_t protectionLevel) -> bool
+ auto GAP::pair(const Devicei &device, std::uint8_t protectionLevel) -> bool
{
if (hci_get_state() == HCI_STATE_WORKING) {
- currentlyProcessedDeviceAddr = bd_addr_to_str(addr);
- return gap_dedicated_bonding(addr, protectionLevel) == 0;
+ auto devIndex = getDeviceIndexForAddress(devices, device.address);
+ currentlyProccesedDevice = devices.at(devIndex);
+
+ return gap_dedicated_bonding(const_cast<uint8_t *>(device.address), protectionLevel) == 0;
}
return false;
}
- auto getDeviceIndexForAddress(const std::vector<Devicei> &devs, bd_addr_t addr) -> int
+ auto GAP::getDeviceIndexForAddress(const std::vector<Devicei> &devs, const bd_addr_t addr) -> int
{
auto result = std::find_if(std::begin(devs), std::end(devs), [addr](const Devicei &device) {
return bd_addr_cmp(addr, device.address) == 0;
@@ 84,8 85,7 @@ namespace bluetooth
void GAP::sendDevices()
{
auto msg = std::make_shared<message::bluetooth::ResponseVisibleDevices>(devices);
- ownerService->bus.sendUnicast(msg, "ApplicationSettings");
- ownerService->bus.sendUnicast(std::move(msg), app::name_settings);
+ ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
}
auto GAP::startScan() -> int
@@ 207,9 207,8 @@ namespace bluetooth
{
auto result = packet[2];
- auto msg = std::make_shared<BluetoothPairResultMessage>(currentlyProcessedDeviceAddr, result == 0u);
- currentlyProcessedDeviceAddr.clear();
- ownerService->bus.sendUnicast(std::move(msg), app::name_settings);
+ auto msg = std::make_shared<BluetoothPairResultMessage>(currentlyProccesedDevice, result == 0u);
+ ownerService->bus.sendUnicast(std::move(msg), "ServiceBluetooth");
}
/* @text In ACTIVE, the following events are processed:
* - GAP Inquiry result event: BTstack provides a unified inquiry result that contain
@@ 262,7 261,7 @@ namespace bluetooth
LOG_DEBUG("PIN code request!");
hci_event_pin_code_request_get_bd_addr(packet, address);
auto msg = std::make_shared<::message::bluetooth::RequestPasskey>();
- ownerService->bus.sendUnicast(std::move(msg), app::name_settings);
+ ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
}
const auto eventType = hci_event_packet_get_type(packet);
switch (state) {
@@ 285,21 284,18 @@ namespace bluetooth
{
return devices;
}
- auto GAP::unpair(uint8_t *addr) -> bool
+ auto GAP::unpair(const Devicei &device) -> bool
{
LOG_INFO("Unpairing device");
- gap_drop_link_key_for_bd_addr(addr);
+ gap_drop_link_key_for_bd_addr(const_cast<uint8_t *>(device.address));
LOG_INFO("Device unpaired");
- std::string unpairedDevAddr{bd_addr_to_str(addr)};
- ownerService->bus.sendUnicast(
- std::make_shared<message::bluetooth::UnpairResult>(std::move(unpairedDevAddr), true), app::name_settings);
+ ownerService->bus.sendMulticast(std::make_shared<message::bluetooth::UnpairResult>(device, true),
+ sys::BusChannel::BluetoothNotifications);
return true;
}
void GAP::respondPinCode(const std::string &pin)
{
- bd_addr_t address{};
- sscanf_bd_addr(currentlyProcessedDeviceAddr.c_str(), address);
- gap_pin_code_response(address, pin.c_str());
+ gap_pin_code_response(currentlyProccesedDevice.address, pin.c_str());
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp +4 -4
@@ 42,6 42,7 @@ namespace bluetooth
static void processNameRequestComplete(std::uint8_t *packet, bd_addr_t &addr);
static void processDedicatedBondingCompleted(std::uint8_t *packet, bd_addr_t &addr);
static void initStateHandler(std::uint8_t eventType, std::uint8_t *packet);
+ static auto getDeviceIndexForAddress(const std::vector<Devicei> &devs, const bd_addr_t addr) -> int;
public:
/// THIS have to be called prior to Bt system start!
@@ 49,13 50,12 @@ namespace bluetooth
auto scan() -> Error;
void stopScan();
void setVisibility(bool visibility);
- auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool;
- auto unpair(uint8_t *addr) -> bool;
+ auto pair(const Devicei &device, std::uint8_t protectionLevel = 0) -> bool;
+ auto unpair(const Devicei &device) -> bool;
static auto getDevicesList() -> const std::vector<Devicei> &;
- static auto isServiceSupportedByRemote(bd_addr_t addr, uint32_t typeOfService) -> bool;
static void respondPinCode(const std::string &pin);
- static std::string currentlyProcessedDeviceAddr;
+ static Devicei currentlyProccesedDevice;
explicit GAP(sys::Service *owner);
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +7 -5
@@ 40,9 40,9 @@ namespace bluetooth
return pimpl->init();
}
- void HFP::setDeviceAddress(uint8_t *addr)
+ void HFP::setDevice(const Devicei &device)
{
- pimpl->setDeviceAddress(addr);
+ pimpl->setDevice(device);
}
void HFP::setOwnerService(const sys::Service *service)
@@ 116,6 116,8 @@ namespace bluetooth
{1, 1},
{2, 1},
};
+ Devicei HFP::HFPImpl::device;
+
void HFP::HFPImpl::dump_supported_codecs(void)
{
LOG_DEBUG("Supported codecs: ");
@@ 357,10 359,10 @@ namespace bluetooth
hfp_ag_release_service_level_connection(aclHandle);
}
- void HFP::HFPImpl::setDeviceAddress(bd_addr_t addr)
+ void HFP::HFPImpl::setDevice(Devicei dev)
{
- bd_addr_copy(deviceAddr, addr);
- LOG_DEBUG("Address set!");
+ device = dev;
+ LOG_DEBUG("Device set!");
}
void HFP::HFPImpl::setOwnerService(const sys::Service *service)
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp +1 -1
@@ 25,7 25,7 @@ namespace bluetooth
auto operator=(HFP &&other) noexcept -> HFP &;
auto init() -> Error::Code override;
- void setDeviceAddress(uint8_t *addr) override;
+ void setDevice(const Devicei &device) override;
void setOwnerService(const sys::Service *service) override;
void connect() override;
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +2 -1
@@ 24,7 24,7 @@ namespace bluetooth
void initializeCall() const noexcept;
void connect();
void disconnect();
- void setDeviceAddress(bd_addr_t addr);
+ void setDevice(Devicei device);
void setOwnerService(const sys::Service *service);
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
@@ 54,5 54,6 @@ namespace bluetooth
static const char *call_hold_services[5];
[[maybe_unused]] static int hf_indicators_nr;
[[maybe_unused]] static hfp_generic_status_indicator_t hf_indicators[2];
+ static Devicei device;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +8 -7
@@ 12,6 12,7 @@
#include <service-audio/AudioMessage.hpp>
#include <service-bluetooth/Constants.hpp>
#include <service-bluetooth/messages/AudioVolume.hpp>
+#include <service-bluetooth/messages/Disconnect.hpp>
#include <service-cellular/service-cellular/CellularServiceAPI.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-audio/AudioServiceAPI.hpp>
@@ 46,9 47,9 @@ namespace bluetooth
return pimpl->init();
}
- void HSP::setDeviceAddress(uint8_t *addr)
+ void HSP::setDevice(const Devicei &device)
{
- pimpl->setDeviceAddress(addr);
+ pimpl->setDevice(device);
}
void HSP::setOwnerService(const sys::Service *service)
@@ 98,7 99,6 @@ namespace bluetooth
HSP::~HSP() = default;
uint16_t HSP::HSPImpl::scoHandle = HCI_CON_HANDLE_INVALID;
- bd_addr_t HSP::HSPImpl::deviceAddr;
std::array<char, commandBufferLength> HSP::HSPImpl::ATcommandBuffer;
std::array<uint8_t, serviceBufferLength> HSP::HSPImpl::serviceBuffer;
std::unique_ptr<SCO> HSP::HSPImpl::sco;
@@ 110,6 110,7 @@ namespace bluetooth
bool HSP::HSPImpl::callAnswered = false;
bool HSP::HSPImpl::isRinging = false;
std::shared_ptr<HSPAudioDevice> HSP::HSPImpl::audioDevice;
+ Devicei HSP::HSPImpl::device;
void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
{
@@ 303,7 304,7 @@ namespace bluetooth
if (isConnected) {
disconnect();
}
- hsp_ag_connect(deviceAddr);
+ hsp_ag_connect(device.address);
}
void HSP::HSPImpl::disconnect()
@@ 312,10 313,10 @@ namespace bluetooth
hsp_ag_disconnect();
}
- void HSP::HSPImpl::setDeviceAddress(bd_addr_t addr)
+ void HSP::HSPImpl::setDevice(const Devicei &dev)
{
- bd_addr_copy(deviceAddr, addr);
- LOG_DEBUG("Address set!");
+ device = dev;
+ LOG_INFO("Device set!");
}
void HSP::HSPImpl::setOwnerService(const sys::Service *service)
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +1 -1
@@ 24,7 24,7 @@ namespace bluetooth
auto operator=(HSP &&other) noexcept -> HSP &;
auto init() -> Error::Code override;
- void setDeviceAddress(uint8_t *addr) override;
+ void setDevice(const Devicei &device) override;
void setOwnerService(const sys::Service *service) override;
void connect() override;
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +2 -2
@@ 24,7 24,7 @@ namespace bluetooth
void initializeCall() const noexcept;
void connect();
void disconnect();
- void setDeviceAddress(bd_addr_t addr);
+ void setDevice(const Devicei &dev);
void setOwnerService(const sys::Service *service);
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
@@ 42,11 42,11 @@ namespace bluetooth
static std::unique_ptr<CellularInterface> cellularInterface;
static std::unique_ptr<AudioInterface> audioInterface;
static std::array<char, commandBufferLength> ATcommandBuffer;
- static bd_addr_t deviceAddr;
static const sys::Service *ownerService;
static bool isConnected;
static bool callAnswered;
static bool isRinging;
static std::shared_ptr<HSPAudioDevice> audioDevice;
+ static Devicei device;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +1 -1
@@ 17,7 17,7 @@ namespace bluetooth
public:
virtual ~Profile() = default;
virtual auto init() -> Error::Code = 0;
- virtual void setDeviceAddress(uint8_t *addr) = 0;
+ virtual void setDevice(const Devicei &device) = 0;
virtual void setOwnerService(const sys::Service *service) = 0;
virtual void connect() = 0;
virtual void start() = 0;
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +3 -4
@@ 39,12 39,11 @@ namespace bluetooth
return Error::Success;
}
- auto ProfileManager::connect(bd_addr_t address) -> Error::Code
+ auto ProfileManager::connect(const Devicei &device) -> Error::Code
{
- bd_addr_copy(remoteAddr, address);
for (auto &[profileName, ptr] : profilesList) {
if (ptr != nullptr) {
- ptr->setDeviceAddress(remoteAddr);
+ ptr->setDevice(device);
ptr->connect();
}
}
@@ 117,7 116,7 @@ namespace bluetooth
profilesList[profileType]->setAudioDevice(device);
return switchProfile(profileType);
}
- auto ProfileManager::isAddressActuallyUsed(bd_addr_t address) -> bool
+ auto ProfileManager::isAddressActuallyUsed(const bd_addr_t address) -> bool
{
return !static_cast<bool>(bd_addr_cmp(address, remoteAddr));
}
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +2 -2
@@ 32,7 32,7 @@ namespace bluetooth
auto init() -> Error::Code;
- auto connect(bd_addr_t address) -> Error::Code;
+ auto connect(const Devicei &device) -> Error::Code;
auto disconnect() -> Error::Code;
@@ 43,7 43,7 @@ namespace bluetooth
auto startRinging() -> Error::Code;
auto stopRinging() -> Error::Code;
auto initializeCall() -> Error::Code;
- auto isAddressActuallyUsed(bd_addr_t address) -> bool;
+ auto isAddressActuallyUsed(const bd_addr_t address) -> bool;
auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code;
M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +0 -1
@@ 47,7 47,6 @@ target_compile_options(${PROJECT_NAME}
-Wno-missing-field-initializers
-Wno-unused-function
-Wno-implicit-fallthrough
-
# C only flags
"$<$<COMPILE_LANGUAGE:C>:-Wno-old-style-declaration>"
)
M module-bluetooth/tests/CMakeLists.txt => module-bluetooth/tests/CMakeLists.txt +2 -1
@@ 1,9 1,10 @@
add_catch2_executable(
NAME
- StatefulController-tests
+ Bluetooth-tests
SRCS
tests-main.cpp
tests-StatefulController.cpp
+ tests-BluetoothDevicesModel.cpp
LIBS
module-sys
module-bluetooth
A module-bluetooth/tests/tests-BluetoothDevicesModel.cpp => module-bluetooth/tests/tests-BluetoothDevicesModel.cpp +130 -0
@@ 0,0 1,130 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <catch2/catch.hpp>
+#include "Device.hpp"
+#include "service-bluetooth/BluetoothDevicesModel.hpp"
+TEST_CASE("Devicei comparison")
+{
+ Devicei device1{"Dev1"};
+ Devicei device2{"Dev2"};
+ Devicei device3{"Dev1"};
+
+ bd_addr_t addr1;
+ bd_addr_t addr2;
+
+ std::string addr1Str{"00:12:6F:E7:9D:05"};
+ std::string addr2Str{"F8:5C:7D:17:E4:8F"};
+
+ sscanf_bd_addr(addr1Str.c_str(), addr1);
+ sscanf_bd_addr(addr2Str.c_str(), addr2);
+
+ SECTION("Same addresses and names")
+ {
+ device1.setAddress(&addr1);
+ device3.setAddress(&addr1);
+ REQUIRE(device1 == device3);
+ }
+
+ SECTION("Different addresses and names")
+ {
+ device1.setAddress(&addr1);
+ device2.setAddress(&addr2);
+ REQUIRE_FALSE(device1 == device3);
+ }
+
+ SECTION("Same names and different addresses")
+ {
+ device1.setAddress(&addr1);
+ device3.setAddress(&addr2);
+ REQUIRE_FALSE(device1 == device3);
+ }
+
+ SECTION("Different addresses and names - != operator")
+ {
+ device1.setAddress(&addr1);
+ device2.setAddress(&addr2);
+ REQUIRE(device1 != device3);
+ }
+
+ SECTION("Same names and different addresses - != operator")
+ {
+ device1.setAddress(&addr1);
+ device3.setAddress(&addr2);
+ REQUIRE(device1 != device3);
+ }
+}
+
+TEST_CASE("Device handling")
+{
+ BluetoothDevicesModel devicesModel{nullptr};
+
+ Devicei device1{"Dev1"};
+ Devicei device2{"Dev2"};
+ Devicei device3{"Dev1"};
+ Devicei device4{"Dev4"};
+ Devicei dummy{""};
+
+ bd_addr_t addr1;
+ bd_addr_t addr2;
+ bd_addr_t addr3;
+
+ std::string addr1Str{"00:12:6F:E7:9D:05"};
+ std::string addr2Str{"F8:5C:7D:17:E4:8F"};
+ std::string addr3Str{"F8:5C:7D:17:E4:00"};
+
+ sscanf_bd_addr(addr1Str.c_str(), addr1);
+ sscanf_bd_addr(addr2Str.c_str(), addr2);
+ sscanf_bd_addr(addr3Str.c_str(), addr3);
+
+ device1.setAddress(&addr1);
+ device2.setAddress(&addr2);
+ device3.setAddress(&addr1);
+ device4.setAddress(&addr2);
+
+ devicesModel.insertDevice(device1);
+ devicesModel.insertDevice(device2);
+ devicesModel.insertDevice(device3);
+
+ SECTION("Add device to the list")
+ {
+ devicesModel.insertDevice(Devicei{"testDevice"});
+ REQUIRE(devicesModel.getDevices().size() == 4);
+ }
+
+ SECTION("Merge device list")
+ {
+ std::vector<Devicei> devicesList, targetList;
+ Devicei dummy{"dummyDevice"};
+ dummy.setAddress(&addr3);
+ devicesList.push_back(dummy);
+
+ targetList.push_back(dummy);
+ targetList.push_back(device1);
+ targetList.push_back(device2);
+
+ devicesModel.mergeDevicesList(devicesList);
+
+ REQUIRE(!devicesModel.getDeviceByAddress(addr1Str).value().get().name.empty());
+ REQUIRE(!devicesModel.getDeviceByAddress(addr2Str).value().get().name.empty());
+ REQUIRE(!devicesModel.getDeviceByAddress(addr3Str).value().get().name.empty());
+ REQUIRE(devicesModel.getDevices().size() == 3);
+ }
+
+ SECTION("Get device with wrong address")
+ {
+ std::string addrStr{"10:12:6F:E8:9D:05"};
+ REQUIRE_FALSE(devicesModel.getDeviceByAddress(addrStr).has_value());
+ }
+
+ SECTION("Get device with correct address")
+ {
+ REQUIRE(devicesModel.getDeviceByAddress(addr2Str).value().get().name == "Dev2");
+ }
+
+ SECTION("Remove device from the list")
+ {
+ devicesModel.removeDevice(device2);
+ REQUIRE(devicesModel.getDevices().size() == 2);
+ }
+}
M module-bluetooth/tests/tests-StatefulController.cpp => module-bluetooth/tests/tests-StatefulController.cpp +2 -2
@@ 30,11 30,11 @@ class DriverMock : public AbstractDriver
{}
void setVisibility(bool visibility) override
{}
- bool pair(uint8_t *addr, std::uint8_t protectionLevel = 0) override
+ bool pair(Devicei device, std::uint8_t protectionLevel = 0) override
{
return true;
}
- bool unpair(uint8_t *addr) override
+ bool unpair(Devicei device) override
{
return true;
}
M module-services/service-bluetooth/CMakeLists.txt => module-services/service-bluetooth/CMakeLists.txt +1 -0
@@ 7,6 7,7 @@ set(SOURCES
service-bluetooth/SettingsHolder.cpp
service-bluetooth/SettingsSerializer.cpp
service-bluetooth/BluetoothMessage.cpp
+ service-bluetooth/BluetoothDevicesModel.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +83 -32
@@ 21,6 21,7 @@
#include "service-bluetooth/messages/Unpair.hpp"
#include "service-bluetooth/messages/SetDeviceName.hpp"
#include "service-bluetooth/messages/Ring.hpp"
+#include "service-bluetooth/BluetoothDevicesModel.hpp"
#include "service-bluetooth/messages/BluetoothModeChanged.hpp"
#include "SystemManager/messages/SentinelRegistrationMessage.hpp"
@@ 56,15 57,16 @@ ServiceBluetooth::~ServiceBluetooth()
LOG_INFO("[ServiceBluetooth] Cleaning resources");
}
-// This code is experimental:
-// this means it is an init point of bluetooth feature handling
sys::ReturnCodes ServiceBluetooth::InitHandler()
{
auto settings = std::make_unique<settings::Settings>();
settings->init(service::ServiceProxy(shared_from_this()));
settingsHolder = std::make_shared<bluetooth::SettingsHolder>(std::move(settings));
+ bluetoothDevicesModel = std::make_shared<BluetoothDevicesModel>(this);
bluetooth::KeyStorage::settings = settingsHolder;
+ bus.channels.push_back(sys::BusChannel::BluetoothNotifications);
+
worker = std::make_unique<BluetoothWorker>(this);
worker->run();
@@ 83,6 85,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
connectHandler<BluetoothAudioStartMessage>();
connectHandler<BluetoothMessage>();
connectHandler<BluetoothPairMessage>();
+ connectHandler<BluetoothPairResultMessage>();
connectHandler<message::bluetooth::A2DPVolume>();
connectHandler<message::bluetooth::HSPVolume>();
connectHandler<message::bluetooth::Ring>();
@@ 147,14 150,14 @@ auto ServiceBluetooth::handle(BluetoothAudioStartMessage *msg) -> std::shared_pt
auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestBondedDevices *msg)
-> std::shared_ptr<sys::Message>
{
- LOG_INFO("Requested bonded devices!");
auto bondedDevicesStr =
std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::BondedDevices));
- auto connectedAddress =
- std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::ConnectedDevice));
+ bluetoothDevicesModel->mergeDevicesList(SettingsSerializer::fromString(bondedDevicesStr));
- return std::make_shared<message::bluetooth::ResponseBondedDevices>(SettingsSerializer::fromString(bondedDevicesStr),
- std::move(connectedAddress));
+ bus.sendMulticast(
+ std::make_shared<message::bluetooth::ResponseBondedDevices>(bluetoothDevicesModel->getDevices(), ""),
+ sys::BusChannel::BluetoothNotifications);
+ return sys::MessageNone{};
}
auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestStatus *msg) -> std::shared_ptr<sys::Message>
@@ 163,7 166,9 @@ auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestStatus
auto visibility = std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::Visibility));
BluetoothStatus status{static_cast<BluetoothStatus::State>(state), status.visibility = visibility};
- return std::make_shared<message::bluetooth::ResponseStatus>(status);
+ bus.sendMulticast(std::make_shared<message::bluetooth::ResponseStatus>(status),
+ sys::BusChannel::BluetoothNotifications);
+ return sys::MessageNone{};
}
auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr<sys::Message>
@@ 177,6 182,12 @@ auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared
bus.sendMulticast(
std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Enabled),
sys::BusChannel::BluetoothModeChanges);
+ {
+ auto bondedDevicesStr = std::visit(bluetooth::StringVisitor(),
+ this->settingsHolder->getValue(bluetooth::Settings::BondedDevices));
+ bluetoothDevicesModel->mergeDevicesList(SettingsSerializer::fromString(bondedDevicesStr));
+ bluetoothDevicesModel->syncDevicesWithApp();
+ }
break;
case BluetoothStatus::State::Off:
sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOff));
@@ 196,19 207,41 @@ auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared
auto ServiceBluetooth::handle(BluetoothPairMessage *msg) -> std::shared_ptr<sys::Message>
{
- const auto addrString = msg->addr;
- bd_addr_t addr;
- sscanf_bd_addr(addrString.c_str(), addr);
- sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Pair, addr));
+ auto device = msg->getDevice();
+ bluetoothDevicesModel->removeDevice(device);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Pair, device));
+
+ device.deviceState = DeviceState::Pairing;
+ bluetoothDevicesModel->insertDevice(device);
+
+ bluetoothDevicesModel->syncDevicesWithApp();
+
+ return sys::MessageNone{};
+}
+
+auto ServiceBluetooth::handle(BluetoothPairResultMessage *msg) -> std::shared_ptr<sys::Message>
+{
+ auto device = msg->getDevice();
+ if (msg->isSucceed()) {
+ bluetoothDevicesModel->setInternalDeviceState(device, DeviceState::Paired);
+ }
+ else {
+ bluetoothDevicesModel->removeDevice(device);
+ }
+
+ bluetoothDevicesModel->syncDevicesWithApp();
+
+ bus.sendMulticast(std::make_shared<BluetoothPairResultMessage>(msg->getDevice(), msg->isSucceed()),
+ sys::BusChannel::BluetoothNotifications);
+
return sys::MessageNone{};
}
auto ServiceBluetooth::handle(message::bluetooth::Unpair *msg) -> std::shared_ptr<sys::Message>
{
- const auto addrString = msg->getAddr();
- bd_addr_t addr;
- sscanf_bd_addr(addrString.c_str(), addr);
- sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Unpair, addr));
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Unpair, msg->getDevice()));
+ bluetoothDevicesModel->removeDevice(msg->getDevice());
+
return sys::MessageNone{};
}
@@ 218,7 251,9 @@ auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestDevice
auto deviceNameString =
std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::DeviceName));
- return std::make_shared<message::bluetooth::ResponseDeviceName>(std::move(deviceNameString));
+ bus.sendMulticast(std::make_shared<message::bluetooth::ResponseDeviceName>(std::move(deviceNameString)),
+ sys::BusChannel::BluetoothNotifications);
+ return sys::MessageNone{};
}
auto ServiceBluetooth::handle(message::bluetooth::SetDeviceName *msg) -> std::shared_ptr<sys::Message>
@@ 233,24 268,36 @@ auto ServiceBluetooth::handle(message::bluetooth::SetDeviceName *msg) -> std::sh
auto ServiceBluetooth::handle(message::bluetooth::Connect *msg) -> std::shared_ptr<sys::Message>
{
- const auto addrString = msg->getAddr();
- LOG_DEBUG("Connecting with %s", addrString.c_str());
- bd_addr_t addr;
- sscanf_bd_addr(addrString.c_str(), addr);
- sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio, addr));
+ auto device = msg->getDevice();
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio, device));
+
+ bluetoothDevicesModel->setInternalDeviceState(device, DeviceState::Connecting);
+ bluetoothDevicesModel->syncDevicesWithApp();
return sys::MessageNone{};
}
auto ServiceBluetooth::handle(message::bluetooth::ConnectResult *msg) -> std::shared_ptr<sys::Message>
{
if (msg->isSucceed()) {
- settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, msg->getAddr());
+ auto device = msg->getDevice();
+ bluetoothDevicesModel->setInternalDeviceState(device, DeviceState::Connected);
+
+ settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, bd_addr_to_str(device.address));
startTimeoutTimer();
bus.sendMulticast(
std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Connected),
sys::BusChannel::BluetoothModeChanges);
}
- bus.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(*msg), nameSettings);
+
+ for (auto &device : bluetoothDevicesModel->getDevices()) {
+ if (device.deviceState == DeviceState::Connecting) {
+ device.deviceState = DeviceState::Paired;
+ }
+ }
+
+ bluetoothDevicesModel->syncDevicesWithApp();
+ bus.sendMulticast(std::make_shared<message::bluetooth::ConnectResult>(*msg),
+ sys::BusChannel::BluetoothNotifications);
return sys::MessageNone{};
}
@@ 262,14 309,20 @@ auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::Disconnect *m
auto ServiceBluetooth::handle(message::bluetooth::DisconnectResult *msg) -> std::shared_ptr<sys::Message>
{
+ auto deviceAddr =
+ std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::ConnectedDevice));
+
+ auto device = bluetoothDevicesModel->getDeviceByAddress(deviceAddr);
+ if (device.has_value()) {
+ device.value().get().deviceState = DeviceState::Paired;
+ }
+ bluetoothDevicesModel->syncDevicesWithApp();
settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, std::string());
bus.sendMulticast(std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Enabled),
sys::BusChannel::BluetoothModeChanges);
- auto bondedDevicesStr =
- std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::BondedDevices));
- bus.sendUnicast(std::make_shared<message::bluetooth::ResponseBondedDevices>(
- SettingsSerializer::fromString(bondedDevicesStr), std::string()),
- nameSettings);
+
+ bus.sendMulticast(std::make_shared<message::bluetooth::DisconnectResult>(msg->getDevice()),
+ sys::BusChannel::BluetoothNotifications);
stopTimeoutTimer();
return sys::MessageNone{};
@@ 342,9 395,7 @@ auto ServiceBluetooth::handle(BluetoothMessage *msg) -> std::shared_ptr<sys::Mes
auto ServiceBluetooth::handle(BluetoothAddrMessage *msg) -> std::shared_ptr<sys::Message>
{
- std::string addrString{bd_addr_to_str(msg->addr)};
- LOG_INFO("Connecting with %s", addrString.c_str());
- sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio, msg->addr));
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio, msg->device));
return std::make_shared<sys::ResponseMessage>();
}
A module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.cpp +76 -0
@@ 0,0 1,76 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BluetoothDevicesModel.hpp"
+#include <service-bluetooth/messages/BondedDevices.hpp>
+
+BluetoothDevicesModel::BluetoothDevicesModel(sys::Service *service) : service{service}
+{}
+
+void BluetoothDevicesModel::mergeDevicesList(const std::vector<Devicei> &devicesList)
+{
+ devices.insert(std::end(devices), std::begin(devicesList), std::end(devicesList));
+
+ // remove duplicates
+ auto end = std::end(devices);
+ for (auto it = std::begin(devices); it != end; ++it) {
+ end = std::remove(it + 1, end, *it);
+ }
+ devices.erase(end, std::end(devices));
+}
+
+void BluetoothDevicesModel::insertDevice(const Devicei &device)
+{
+ devices.emplace_back(device);
+ syncDevicesWithApp();
+}
+auto BluetoothDevicesModel::getDeviceByAddress(const std::string &address)
+ -> std::optional<std::reference_wrapper<Devicei>>
+{
+
+ auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [address](const Devicei &device) {
+ return bd_addr_to_str(device.address) == address;
+ });
+
+ if (deviceIt == std::end(devices)) {
+ return std::nullopt;
+ }
+ return std::ref(*deviceIt);
+}
+auto BluetoothDevicesModel::getDeviceByAddress(const bd_addr_t address)
+ -> std::optional<std::reference_wrapper<Devicei>>
+{
+
+ auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [address](const Devicei &device) {
+ return std::memcmp(address, device.address, sizeof(bd_addr_t)) == 0;
+ });
+
+ if (deviceIt == std::end(devices)) {
+ return std::nullopt;
+ }
+ return std::ref(*deviceIt);
+}
+void BluetoothDevicesModel::removeDevice(const Devicei &device)
+{
+ auto position = std::find(std::begin(devices), std::end(devices), device);
+ if (position != std::end(devices)) {
+ devices.erase(position);
+ }
+ syncDevicesWithApp();
+}
+auto BluetoothDevicesModel::getDevices() -> std::vector<Devicei> &
+{
+ return devices;
+}
+void BluetoothDevicesModel::syncDevicesWithApp()
+{
+ if (service != nullptr) {
+ service->bus.sendMulticast(std::make_shared<::message::bluetooth::SyncDevices>(devices),
+ sys::BusChannel::BluetoothNotifications);
+ }
+}
+void BluetoothDevicesModel::setInternalDeviceState(const Devicei &device, const DeviceState &state)
+{
+ auto dev = getDeviceByAddress(device.address);
+ dev.value().get().deviceState = state;
+}
A module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.hpp +31 -0
@@ 0,0 1,31 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Application.hpp"
+#include <Device.hpp>
+#include "service-bluetooth/messages/SyncDevices.hpp"
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
+class BluetoothDevicesModel
+{
+ public:
+ explicit BluetoothDevicesModel(sys::Service *service);
+
+ void mergeDevicesList(const std::vector<Devicei> &devicesList);
+ auto getDeviceByAddress(const std::string &address) -> std::optional<std::reference_wrapper<Devicei>>;
+ auto getDeviceByAddress(const bd_addr_t address) -> std::optional<std::reference_wrapper<Devicei>>;
+ void insertDevice(const Devicei &device);
+ void removeDevice(const Devicei &device);
+ auto getDevices() -> std::vector<Devicei> &;
+ void syncDevicesWithApp();
+ void setInternalDeviceState(const Devicei &device, const DeviceState &state);
+
+ private:
+ std::vector<Devicei> devices{};
+ sys::Service *service = nullptr;
+};
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp +8 -5
@@ 9,10 9,13 @@ extern "C"
}
#include <utility>
-BluetoothAddrMessage::BluetoothAddrMessage(std::string addr) : sys::DataMessage(MessageType::BluetoothAddrResult)
+BluetoothAddrMessage::BluetoothAddrMessage(Devicei device)
+ : sys::DataMessage(MessageType::BluetoothAddrResult), device(device)
+{}
+BluetoothPairMessage::BluetoothPairMessage(Devicei device)
+ : sys::DataMessage(MessageType::BluetoothPairResult), device(device)
+{}
+auto BluetoothPairMessage::getDevice() const noexcept -> Devicei
{
- sscanf_bd_addr(addr.c_str(), this->addr);
+ return device;
}
-BluetoothPairMessage::BluetoothPairMessage(std::string addr)
- : sys::DataMessage(MessageType::BluetoothPairResult), addr(std::move(addr))
-{}
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +10 -10
@@ 51,12 51,12 @@ class BluetoothMessage : public sys::DataMessage
class BluetoothPairResultMessage : public sys::DataMessage
{
public:
- explicit BluetoothPairResultMessage(std::string addr, bool succeed)
- : sys::DataMessage(MessageType::BluetoothPairResult), addr(std::move(addr)), succeed(succeed)
+ explicit BluetoothPairResultMessage(const Devicei device, bool succeed)
+ : sys::DataMessage(MessageType::BluetoothPairResult), device(device), succeed(succeed)
{}
- [[nodiscard]] auto getAddr() const -> std::string
+ [[nodiscard]] auto getDevice() const -> Devicei
{
- return addr;
+ return device;
}
[[nodiscard]] auto isSucceed() const noexcept -> bool
{
@@ 64,24 64,24 @@ class BluetoothPairResultMessage : public sys::DataMessage
}
private:
- std::string addr;
- std::string name;
+ Devicei device;
bool succeed;
};
class BluetoothAddrMessage : public sys::DataMessage
{
public:
- bd_addr_t addr;
- explicit BluetoothAddrMessage(std::string addr);
+ Devicei device;
+ explicit BluetoothAddrMessage(Devicei device);
~BluetoothAddrMessage() override = default;
};
class BluetoothPairMessage : public sys::DataMessage
{
public:
- std::string addr;
- explicit BluetoothPairMessage(std::string addr);
+ Devicei device;
+ explicit BluetoothPairMessage(Devicei device);
+ [[nodiscard]] auto getDevice() const noexcept -> Devicei;
~BluetoothPairMessage() override = default;
};
A module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.cpp +172 -0
@@ 0,0 1,172 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BluetoothSettingsModel.hpp"
+
+#include <service-bluetooth/Constants.hpp>
+#include <service-bluetooth/messages/BondedDevices.hpp>
+#include <service-bluetooth/messages/Connect.hpp>
+#include <service-bluetooth/messages/DeviceName.hpp>
+#include <service-bluetooth/messages/Disconnect.hpp>
+#include <service-bluetooth/messages/Status.hpp>
+#include <service-bluetooth/messages/SetStatus.hpp>
+#include <service-bluetooth/messages/SetDeviceName.hpp>
+#include <service-bluetooth/messages/Passkey.hpp>
+#include <service-bluetooth/messages/Unpair.hpp>
+
+BluetoothSettingsModel::BluetoothSettingsModel(app::Application *application) : application{application}
+{}
+
+void BluetoothSettingsModel::requestStatus()
+{
+ application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestStatus>(), service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::setStatus(const bool desiredBluetoothState, const bool desiredVisibility)
+{
+ BluetoothStatus status{.state = desiredBluetoothState ? BluetoothStatus::State::On : BluetoothStatus::State::Off,
+ .visibility = desiredVisibility};
+ message::bluetooth::SetStatus setStatus(status);
+ application->bus.sendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestDeviceName()
+{
+ application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestDeviceName>(), service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::setDeviceName(const UTF8 &deviceName)
+{
+ application->bus.sendUnicast(std::make_shared<message::bluetooth::SetDeviceName>(deviceName),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestBondedDevices()
+{
+ application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestScan()
+{
+ application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Scan),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::stopScan()
+{
+ application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::StopScan),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestDevicePair(const std::string &addr)
+{
+ application->bus.sendUnicast(std::make_shared<BluetoothPairMessage>(addr), service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestDeviceUnpair(const Devicei &device)
+{
+ application->bus.sendUnicast(std::make_shared<message::bluetooth::Unpair>(bd_addr_to_str(device.address)),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::responsePasskey(const std::string &passkey)
+{
+ application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey),
+ service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestConnection(const std::string &addr)
+{
+ application->bus.sendUnicast(std::make_shared<message::bluetooth::Connect>(addr), service::name::bluetooth);
+}
+
+void BluetoothSettingsModel::requestDisconnection()
+{
+ application->bus.sendUnicast(std::make_shared<message::bluetooth::Disconnect>(), service::name::bluetooth);
+}
+void BluetoothSettingsModel::mergeDevicesList(const std::vector<Devicei> &devicesList)
+{
+ devices.insert(std::end(devices), std::begin(devicesList), std::end(devicesList));
+
+ // remove duplicates
+ auto end = std::end(devices);
+ for (auto it = std::begin(devices); it != end; ++it) {
+ end = std::remove(it + 1, end, *it);
+ }
+ devices.erase(end, std::end(devices));
+}
+void BluetoothSettingsModel::setActiveDeviceState(const DeviceState &state)
+{
+ auto activeDevice = getActiveDevice();
+ if (activeDevice.has_value()) {
+ activeDevice.value().get().deviceState = state;
+ }
+}
+auto BluetoothSettingsModel::getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>
+{
+ try {
+ return devices.at(activeDeviceIndex);
+ }
+ catch (const std::out_of_range &oor) {
+ LOG_FATAL("NO DEVICE FOUND!");
+ return std::nullopt;
+ }
+}
+auto BluetoothSettingsModel::getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>
+{
+ try {
+ return devices.at(selectedDeviceIndex);
+ }
+ catch (const std::out_of_range &oor) {
+ LOG_FATAL("NO DEVICE FOUND!");
+ return std::nullopt;
+ }
+}
+void BluetoothSettingsModel::setActiveDevice(const Devicei &device)
+{
+ auto itr = std::find(std::begin(devices), std::end(devices), device);
+ activeDeviceIndex = std::distance(std::begin(devices), itr);
+}
+void BluetoothSettingsModel::setSelectedDevice(const Devicei &device)
+{
+ auto itr = std::find(std::begin(devices), std::end(devices), device);
+ selectedDeviceIndex = std::distance(std::begin(devices), itr);
+}
+void BluetoothSettingsModel::insertDevice(const Devicei device)
+{
+ devices.emplace_back(device);
+}
+auto BluetoothSettingsModel::getDeviceByAddress(const std::string &address)
+ -> std::optional<std::reference_wrapper<Devicei>>
+{
+ auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [address](const Devicei &device) {
+ return bd_addr_to_str(device.address) == address;
+ });
+
+ if (deviceIt == std::end(devices)) {
+ return std::nullopt;
+ }
+ return std::ref(*deviceIt);
+}
+void BluetoothSettingsModel::removeDevice(const Devicei &device)
+{
+ devices.erase(std::remove(std::begin(devices), std::end(devices), device), std::end(devices));
+}
+auto BluetoothSettingsModel::getDevices() -> std::vector<Devicei> &
+{
+ return devices;
+}
+auto BluetoothSettingsModel::isDeviceConnecting() -> bool
+{
+
+ auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [](const Devicei &device) {
+ return device.deviceState == DeviceState::Connecting;
+ });
+
+ if (deviceIt != std::end(devices)) {
+ return true;
+ }
+ return false;
+}
A module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.hpp +59 -0
@@ 0,0 1,59 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Application.hpp"
+#include <Device.hpp>
+
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
+class ActiveDevice
+{
+ public:
+ explicit ActiveDevice(std::string address) : address(std::move(address))
+ {}
+ ActiveDevice() = default;
+ DeviceState state = DeviceState::Unknown;
+ std::string address;
+};
+
+class BluetoothSettingsModel
+{
+ public:
+ explicit BluetoothSettingsModel(app::Application *application);
+
+ void requestStatus();
+ void setStatus(bool desiredBluetoothState, bool desiredVisibility);
+ void requestDeviceName();
+ void setDeviceName(const UTF8 &deviceName);
+ void requestBondedDevices();
+ void requestScan();
+ void stopScan();
+ void requestDevicePair(const std::string &addr);
+ void requestDeviceUnpair(const Devicei &device);
+ void responsePasskey(const std::string &passkey);
+ void requestConnection(const std::string &addr);
+ void requestDisconnection();
+ void replaceDevicesList(const std::vector<Devicei> &devicesList);
+ void setActiveDeviceState(const DeviceState &state);
+ auto getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>;
+ auto getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>;
+ auto getDeviceByAddress(const std::string &address) -> std::optional<std::reference_wrapper<Devicei>>;
+ void setActiveDevice(const Devicei &device);
+ void setSelectedDevice(const Devicei &device);
+ void insertDevice(Devicei device);
+ void removeDevice(const Devicei &device);
+ auto getDevices() -> std::vector<Devicei> &;
+ auto isDeviceConnecting() -> bool;
+
+ private:
+ std::vector<Devicei> devices{};
+ std::uint16_t activeDeviceIndex = 0;
+ std::uint16_t selectedDeviceIndex = 0;
+ app::Application *application = nullptr;
+ Devicei dummyDevice{""};
+};
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +5 -0
@@ 12,6 12,7 @@
#include <service-audio/ServiceAudio.hpp>
#include <module-bluetooth/Bluetooth/CommandHandler.hpp>
#include "ProfileManager.hpp"
+#include "BluetoothDevicesModel.hpp"
#include <Service/CpuSentinel.hpp>
#include <Timers/TimerHandle.hpp>
@@ 52,6 53,7 @@ namespace message::bluetooth
class HSPVolume;
class Ring;
class StartAudioRouting;
+ class GetBluetoothDevicesModel;
} // namespace message::bluetooth
class ServiceBluetooth : public sys::Service
@@ 75,6 77,7 @@ class ServiceBluetooth : public sys::Service
std::unique_ptr<BluetoothWorker> worker;
std::shared_ptr<sys::CpuSentinel> cpuSentinel;
sys::TimerHandle connectionTimeoutTimer;
+ std::shared_ptr<BluetoothDevicesModel> bluetoothDevicesModel{};
void startTimeoutTimer();
void stopTimeoutTimer();
@@ 88,6 91,7 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(message::bluetooth::RequestStatus *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(BluetoothPairMessage *msg) -> std::shared_ptr<sys::Message>;
+ [[nodiscard]] auto handle(BluetoothPairResultMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::Unpair *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::RequestDeviceName *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::SetDeviceName *msg) -> std::shared_ptr<sys::Message>;
@@ 104,6 108,7 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(message::bluetooth::Ring *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::ResponsePasskey *msg) -> std::shared_ptr<sys::Message>;
+ [[nodiscard]] auto handle(message::bluetooth::GetBluetoothDevicesModel *msg) -> std::shared_ptr<sys::Message>;
};
namespace sys
M module-services/service-bluetooth/service-bluetooth/SettingsSerializer.cpp => module-services/service-bluetooth/service-bluetooth/SettingsSerializer.cpp +1 -0
@@ 41,6 41,7 @@ auto SettingsSerializer::fromString(const std::string &jsonStr) -> std::vector<D
Devicei temp;
sscanf_bd_addr(device[strings::addr].string_value().c_str(), temp.address);
temp.name = device[strings::name].string_value();
+ temp.deviceState = DeviceState::Paired;
devicesVector.emplace_back(temp);
}
return devicesVector;
M module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp => module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp +8 -8
@@ 10,25 10,25 @@ namespace message::bluetooth
class Connect : public BluetoothMessage
{
public:
- explicit Connect(std::string addr) : addr(std::move(addr))
+ explicit Connect(Devicei device) : device(std::move(device))
{}
- [[nodiscard]] auto getAddr() const -> std::string
+ [[nodiscard]] auto getDevice() const -> Devicei
{
- return addr;
+ return device;
}
private:
- std::string addr;
+ Devicei device;
};
class ConnectResult : public BluetoothMessage
{
public:
- explicit ConnectResult(std::string addr, bool succeed) : addr(std::move(addr)), succeed(succeed)
+ explicit ConnectResult(Devicei device, bool succeed) : device(device), succeed(succeed)
{}
- [[nodiscard]] auto getAddr() const -> std::string
+ [[nodiscard]] auto getDevice() const -> Devicei
{
- return addr;
+ return device;
}
[[nodiscard]] auto isSucceed() const noexcept -> bool
{
@@ 36,7 36,7 @@ namespace message::bluetooth
}
private:
- std::string addr;
+ Devicei device;
bool succeed;
};
} // namespace message::bluetooth
M module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp => module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp +12 -1
@@ 11,5 11,16 @@ namespace message::bluetooth
{};
class DisconnectResult : public BluetoothMessage
- {};
+ {
+ public:
+ explicit DisconnectResult(Devicei device) : device(device)
+ {}
+ [[nodiscard]] auto getDevice() const -> Devicei
+ {
+ return device;
+ }
+
+ private:
+ Devicei device;
+ };
} // namespace message::bluetooth
M module-services/service-bluetooth/service-bluetooth/messages/Status.hpp => module-services/service-bluetooth/service-bluetooth/messages/Status.hpp +21 -1
@@ 4,7 4,7 @@
#pragma once
#include "service-bluetooth/BluetoothMessage.hpp"
-
+#include <Bluetooth/interface/profiles/AudioProfile.hpp>
namespace message::bluetooth
{
@@ 24,4 24,24 @@ namespace message::bluetooth
private:
BluetoothStatus status;
};
+
+ class ProfileStatus : public BluetoothMessage
+ {
+ public:
+ ProfileStatus(::bluetooth::AudioProfile profile, bool isConnected) : isConnected(isConnected), profile(profile)
+ {}
+
+ [[nodiscard]] auto getProfile() const noexcept -> ::bluetooth::AudioProfile
+ {
+ return profile;
+ }
+ [[nodiscard]] auto isProfileConnected() const noexcept -> bool
+ {
+ return isConnected;
+ }
+
+ private:
+ bool isConnected;
+ ::bluetooth::AudioProfile profile;
+ };
} // namespace message::bluetooth
A module-services/service-bluetooth/service-bluetooth/messages/SyncDevices.hpp => module-services/service-bluetooth/service-bluetooth/messages/SyncDevices.hpp +23 -0
@@ 0,0 1,23 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "service-bluetooth/BluetoothMessage.hpp"
+
+namespace message::bluetooth
+{
+ class SyncDevices : public BluetoothMessage
+ {
+ public:
+ explicit SyncDevices(std::vector<Devicei> devices) : devices(std::move(devices))
+ {}
+ [[nodiscard]] auto getDevices() const noexcept -> std::vector<Devicei>
+ {
+ return devices;
+ }
+
+ private:
+ std::vector<Devicei> devices;
+ };
+} // namespace message::bluetooth
M module-services/service-bluetooth/service-bluetooth/messages/Unpair.hpp => module-services/service-bluetooth/service-bluetooth/messages/Unpair.hpp +8 -8
@@ 10,25 10,25 @@ namespace message::bluetooth
class Unpair : public BluetoothMessage
{
public:
- explicit Unpair(std::string addr) : addr(std::move(addr))
+ explicit Unpair(Devicei device) : device(device)
{}
- [[nodiscard]] auto getAddr() const -> std::string
+ [[nodiscard]] auto getDevice() const -> Devicei
{
- return addr;
+ return device;
}
private:
- std::string addr;
+ Devicei device;
};
class UnpairResult : public BluetoothMessage
{
public:
- explicit UnpairResult(std::string addr, bool succeed) : addr(std::move(addr)), succeed(succeed)
+ explicit UnpairResult(Devicei device, bool succeed) : device(device), succeed(succeed)
{}
- [[nodiscard]] auto getAddr() const -> std::string
+ [[nodiscard]] auto getDevice() const -> Devicei
{
- return addr;
+ return device;
}
[[nodiscard]] auto isSucceed() const noexcept -> bool
{
@@ 36,7 36,7 @@ namespace message::bluetooth
}
private:
- std::string addr;
+ Devicei device;
bool succeed;
};
} // namespace message::bluetooth
M module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp => module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp +9 -3
@@ 79,11 79,15 @@ auto parserFSM::BluetoothHelper::processPostRequest(Context &context) -> sys::Re
auto body = context.getBody();
std::unique_ptr<sys::Message> msg;
if (auto address = body[json::bluetooth::connect].string_value(); !address.empty()) {
- msg = std::make_unique<::message::bluetooth::Connect>(std::move(address));
+ auto device = Devicei("DevMode device");
+ sscanf_bd_addr(address.c_str(), device.address);
+ msg = std::make_unique<::message::bluetooth::Connect>(device);
}
else if (auto address = body[json::bluetooth::pair].string_value(); !address.empty()) {
+ auto device = Devicei("DevMode device");
+ sscanf_bd_addr(address.c_str(), device.address);
LOG_INFO("Requesting pairing form harness");
- msg = std::make_unique<BluetoothPairMessage>(std::move(address));
+ msg = std::make_unique<BluetoothPairMessage>(device);
}
sendRequest(context, std::move(msg));
@@ 102,7 106,9 @@ auto parserFSM::BluetoothHelper::processDeleteRequest(Context &context) -> sys::
}
else if (auto address = body[json::bluetooth::unpair].string_value(); !address.empty()) {
LOG_INFO("Requesting pairing form harness");
- msg = std::make_unique<::message::bluetooth::Unpair>(std::move(address));
+ auto device = Devicei("DevMode device");
+ sscanf_bd_addr(address.c_str(), device.address);
+ msg = std::make_unique<::message::bluetooth::Unpair>(device);
}
sendRequest(context, std::move(msg));
MessageHandler::putToSendQueue(context.createSimpleResponse());
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +18 -0
@@ 29,6 29,8 @@
#include <service-desktop/DesktopMessages.hpp>
#include <service-time/Constants.hpp>
#include <service-time/service-time/TimeMessage.hpp>
+#include <service-bluetooth/messages/Status.hpp>
+#include <application-settings/ApplicationSettings.hpp>
#include <cassert>
#include <fstream>
@@ 40,6 42,7 @@
#include <EventStore.hpp>
#include <ticks.hpp>
#include <purefs/filesystem_paths.hpp>
+#include <Constants.hpp>
namespace
{
@@ 91,6 94,21 @@ sys::MessagePointer EventManagerCommon::DataReceivedHandler(sys::DataMessage *ms
handled = true;
}
else if (auto msg = dynamic_cast<AudioEventRequest *>(msgl); msg) {
+ auto event = msg->getEvent();
+ switch (event->getType()) {
+ case audio::EventType::BlutoothA2DPDeviceState: {
+ auto message = std::make_shared<message::bluetooth::ProfileStatus>(
+ bluetooth::AudioProfile::A2DP, (event->getDeviceState() == audio::Event::DeviceState::Connected));
+ bus.sendUnicast(message, app::name_settings);
+ } break;
+ case audio::EventType::BlutoothHSPDeviceState: {
+ auto message = std::make_shared<message::bluetooth::ProfileStatus>(
+ bluetooth::AudioProfile::HSP, (event->getDeviceState() == audio::Event::DeviceState::Connected));
+ bus.sendUnicast(message, app::name_settings);
+ } break;
+ default:
+ break;
+ }
AudioServiceAPI::SendEvent(this, msg->getEvent());
handled = true;
}
M module-sys/Service/Common.hpp => module-sys/Service/Common.hpp +4 -1
@@ 25,7 25,8 @@ namespace sys
PhoneModeChanges,
PhoneLockChanges,
AlarmChanges,
- BluetoothModeChanges
+ BluetoothModeChanges,
+ BluetoothNotifications
};
enum class ServicePriority
@@ 123,6 124,8 @@ inline const char *c_str(sys::BusChannel channel)
return "PhoneModeChanges";
case sys::BusChannel::BluetoothModeChanges:
return "BluetoothModeChanges";
+ case sys::BusChannel::BluetoothNotifications:
+ return "BluetoothNotifications";
case sys::BusChannel::PhoneLockChanges:
return "PhoneLockChanges";
case sys::BusChannel::AlarmChanges:
M products/PurePhone/services/appmgr/ApplicationManager.cpp => products/PurePhone/services/appmgr/ApplicationManager.cpp +1 -0
@@ 48,6 48,7 @@ namespace app::manager
this, autoLockTimerName, sys::timer::InfiniteTimeout, [this](sys::Timer &) { onPhoneLocked(); });
bus.channels.push_back(sys::BusChannel::BluetoothModeChanges);
+ bus.channels.push_back(sys::BusChannel::BluetoothNotifications);
bus.channels.push_back(sys::BusChannel::PhoneModeChanges);
bus.channels.push_back(sys::BusChannel::PhoneLockChanges);
bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);