M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +23 -1
@@ 116,7 116,8 @@ namespace app
else if (auto responseStatusMsg = dynamic_cast<::message::bluetooth::ResponseStatus *>(msgl);
nullptr != responseStatusMsg) {
if (gui::window::name::bluetooth == getCurrentWindow()->getName()) {
- auto btStatusData = std::make_unique<gui::BluetoothStatusData>(responseStatusMsg->getStatus());
+ const auto status = responseStatusMsg->getStatus();
+ auto btStatusData = std::make_unique<gui::BluetoothStatusData>(status.state, status.visibility);
switchWindow(gui::window::name::bluetooth, std::move(btStatusData));
}
}
@@ 189,6 190,27 @@ namespace app
::settings::SystemProperties::lockPassHash,
[this](std::string value) { lockPassHash = utils::getNumericValue<unsigned int>(value); },
::settings::SettingsScope::Global);
+ settings->registerValueChange(
+ ::settings::Bluetooth::state,
+ [this](std::string value) {
+ if (gui::window::name::bluetooth == getCurrentWindow()->getName()) {
+ const auto isBtOn = utils::getNumericValue<bool>(value);
+ auto btStatusData = std::make_unique<gui::BluetoothStatusData>(
+ isBtOn ? BluetoothStatus::State::On : BluetoothStatus::State::Off);
+ switchWindow(gui::window::name::bluetooth, std::move(btStatusData));
+ }
+ },
+ ::settings::SettingsScope::Global);
+ settings->registerValueChange(
+ ::settings::Bluetooth::deviceVisibility,
+ [this](std::string value) {
+ if (gui::window::name::bluetooth == getCurrentWindow()->getName()) {
+ const auto isVisible = utils::getNumericValue<bool>(value);
+ auto btStatusData = std::make_unique<gui::BluetoothStatusData>(isVisible);
+ switchWindow(gui::window::name::bluetooth, std::move(btStatusData));
+ }
+ },
+ ::settings::SettingsScope::Global);
return ret;
}
M module-apps/application-settings-new/windows/BluetoothWindow.cpp => module-apps/application-settings-new/windows/BluetoothWindow.cpp +29 -19
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BluetoothWindow.hpp"
@@ 22,9 22,13 @@ namespace gui
void BluetoothWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
if (data != nullptr) {
- const auto newData = static_cast<BluetoothStatusData *>(data);
- isBluetoothSwitchOn = newData->getState();
- isPhoneVisibilitySwitchOn = newData->getVisibility();
+ const auto newData = static_cast<BluetoothStatusData *>(data);
+ if (const auto btState = newData->getState(); btState.has_value()) {
+ isBluetoothSwitchOn = btState.value();
+ }
+ if (const auto visibility = newData->getVisibility(); visibility.has_value()) {
+ isPhoneVisibilitySwitchOn = visibility.value();
+ }
}
rebuildOptionList();
}
@@ 36,7 40,7 @@ namespace gui
optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
utils::translateI18("app_settings_bluetooth_main"),
[=](gui::Item &item) {
- switchHandler(isBluetoothSwitchOn);
+ changeBluetoothState(isBluetoothSwitchOn);
return true;
},
[=](gui::Item &item) {
@@ 69,7 73,7 @@ namespace gui
optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
utils::translateI18("app_settings_bluetooth_phone_visibility"),
[=](gui::Item &item) {
- switchHandler(isPhoneVisibilitySwitchOn);
+ changeVisibility(isPhoneVisibilitySwitchOn);
return true;
},
[=](gui::Item &item) {
@@ 104,22 108,28 @@ namespace gui
return optionsList;
}
- void BluetoothWindow::switchHandler(bool &switchState)
+ void BluetoothWindow::changeBluetoothState(bool currentState)
{
- switchState = !switchState;
- BluetoothStatus btStatus;
+ ::message::bluetooth::SetStatus setStatus(makeDesiredStatus(!currentState, isPhoneVisibilitySwitchOn));
+ sys::Bus::SendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
+ service::name::bluetooth,
+ application);
+ }
- if (isBluetoothSwitchOn) {
- btStatus.state = BluetoothStatus::State::On;
- }
- else {
- btStatus.state = BluetoothStatus::State::Off;
- }
- btStatus.visibility = isPhoneVisibilitySwitchOn;
- ::message::bluetooth::SetStatus setStatus(btStatus);
+ void BluetoothWindow::changeVisibility(bool currentVisibility)
+ {
+ ::message::bluetooth::SetStatus setStatus(makeDesiredStatus(isBluetoothSwitchOn, !currentVisibility));
+ sys::Bus::SendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
+ service::name::bluetooth,
+ application);
+ }
- sys::Bus::SendUnicast(
- std::make_shared<::message::bluetooth::SetStatus>(setStatus), service::name::bluetooth, application);
+ BluetoothStatus BluetoothWindow::makeDesiredStatus(bool desiredBluetoothState, bool desiredVisibility) noexcept
+ {
+ BluetoothStatus status;
+ status.state = desiredBluetoothState ? BluetoothStatus::State::On : BluetoothStatus::State::Off;
+ status.visibility = desiredVisibility;
+ return status;
}
void BluetoothWindow::rebuildOptionList()
M module-apps/application-settings-new/windows/BluetoothWindow.hpp => module-apps/application-settings-new/windows/BluetoothWindow.hpp +23 -8
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 18,28 18,43 @@ namespace gui
bool isBluetoothSwitchOn = false;
bool isPhoneVisibilitySwitchOn = false;
auto bluetoothOptionsList() -> std::list<gui::Option>;
- void switchHandler(bool &switchState);
+ void changeBluetoothState(bool currentState);
+ void changeVisibility(bool currentVisibility);
void rebuildOptionList();
+
+ static BluetoothStatus makeDesiredStatus(bool desiredBluetoothState, bool desiredVisibility) noexcept;
};
class BluetoothStatusData : public SwitchData
{
public:
- explicit BluetoothStatusData(BluetoothStatus status) : SwitchData(), status(std::move(status))
+ explicit BluetoothStatusData(BluetoothStatus::State state) : state{state}
+ {}
+ explicit BluetoothStatusData(bool visibility) : visibility{visibility}
+ {}
+ BluetoothStatusData(BluetoothStatus::State state, bool visibility) : state{state}, visibility{visibility}
{}
- [[nodiscard]] auto getState() const noexcept -> bool
+
+ [[nodiscard]] auto getState() const noexcept -> std::optional<bool>
{
- if (status.state == BluetoothStatus::State::On) {
+ if (!state.has_value()) {
+ return std::nullopt;
+ }
+ if (state == BluetoothStatus::State::On) {
return true;
}
return false;
}
- [[nodiscard]] auto getVisibility() const noexcept -> bool
+ [[nodiscard]] auto getVisibility() const noexcept -> std::optional<bool>
{
- return status.visibility;
+ if (!visibility.has_value()) {
+ return std::nullopt;
+ }
+ return visibility;
}
private:
- BluetoothStatus status;
+ std::optional<BluetoothStatus::State> state;
+ std::optional<bool> visibility;
};
} // namespace gui
M module-apps/application-settings/windows/BtWindow.cpp => module-apps/application-settings/windows/BtWindow.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <functional>
@@ 106,7 106,7 @@ namespace gui
add_box_label(box, " -> Stop", [=](Item &) {
LOG_DEBUG("Stop playback");
- message_bt(application, BluetoothMessage::Request::Stop);
+ message_bt(application, BluetoothMessage::Request::StopPlayback);
return true;
});
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +86 -120
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <service-bluetooth/ServiceBluetooth.hpp>
@@ 24,10 24,6 @@
using namespace bsp;
-[[nodiscard]] auto to_string(bluetooth::Error::Code code) -> std::string
-{
- return utils::enumToString(code);
-}
namespace queues
{
constexpr inline auto io = "qBtIO";
@@ 36,112 32,110 @@ namespace queues
constexpr inline auto queueLength = 10;
constexpr inline auto triggerQueueLength = 3;
-
} // namespace queues
+namespace
+{
+ class DeviceRegistration
+ {
+ public:
+ using OnLinkKeyAddedCallback = std::function<void(const std::string &)>;
+
+ DeviceRegistration(std::shared_ptr<bluetooth::SettingsHolder> settings, OnLinkKeyAddedCallback &&onLinkKeyAdded)
+ : settings{std::move(settings)}, onLinkKeyAdded{std::move(onLinkKeyAdded)}
+ {}
+
+ [[nodiscard]] auto operator()()
+ {
+ bluetooth::KeyStorage::settings = settings;
+ bluetooth::GAP::register_scan();
+
+ auto settingsName = std::get<std::string>(settings->getValue(bluetooth::Settings::DeviceName));
+ if (settingsName.empty()) {
+ LOG_WARN("Settings name is empty!");
+ constexpr auto name = "PurePhone";
+ settings->setValue(bluetooth::Settings::DeviceName, name);
+ settingsName = name;
+ }
+ bluetooth::set_name(settingsName);
+ bluetooth::GAP::set_visibility(
+ std::visit(bluetooth::BoolVisitor{}, settings->getValue(bluetooth::Settings::Visibility)));
+
+ settings->onLinkKeyAdded = onLinkKeyAdded;
+ return bluetooth::Error::Success;
+ }
+
+ private:
+ std::shared_ptr<bluetooth::SettingsHolder> settings;
+ OnLinkKeyAddedCallback onLinkKeyAdded;
+ };
+
+ auto createStatefulController(sys::Service *service,
+ bluetooth::RunLoop *loop,
+ std::shared_ptr<bluetooth::SettingsHolder> settings,
+ std::shared_ptr<bluetooth::Profile> currentProfile,
+ DeviceRegistration::OnLinkKeyAddedCallback &&onLinkKeyAddedCallback)
+ {
+ auto driver = std::make_unique<bluetooth::Driver>(loop->getRunLoopInstance());
+ auto commandHandler = std::make_unique<bluetooth::CommandHandler>(service, settings, std::move(currentProfile));
+ return std::make_unique<bluetooth::StatefulController>(
+ std::move(driver),
+ std::move(commandHandler),
+ DeviceRegistration{std::move(settings), std::move(onLinkKeyAddedCallback)});
+ }
+} // namespace
+
BluetoothWorker::BluetoothWorker(sys::Service *service)
: Worker(service), service(service), currentProfile(std::make_shared<bluetooth::HSP>()),
settings(static_cast<ServiceBluetooth *>(service)->settingsHolder),
- runLoop(std::make_unique<bluetooth::RunLoop>()), driver(std::make_unique<bluetooth::Driver>())
+ runLoop(std::make_unique<bluetooth::RunLoop>()),
+ controller{createStatefulController(
+ service, runLoop.get(), settings, currentProfile, [this](const std::string &addr) { onLinkKeyAdded(addr); })}
{
init({
{queues::io, sizeof(bluetooth::Message), queues::queueLength},
{queues::cmd, sizeof(bluetooth::Command), queues::queueLength},
{queues::btstack, sizeof(bool), queues::triggerQueueLength},
});
+ registerQueues();
+}
+
+void BluetoothWorker::registerQueues()
+{
static_cast<ServiceBluetooth *>(service)->workerQueue = Worker::getQueueHandleByName(queues::cmd);
runLoop->setTriggerQueue(Worker::getQueueHandleByName(queues::btstack));
- driver->init(runLoop->getRunLoopInstance());
+ BlueKitchen::getInstance()->qHandle = queues[queueIO_handle]->GetQueueHandle();
}
-BluetoothWorker::~BluetoothWorker()
+void BluetoothWorker::onLinkKeyAdded(const std::string &deviceAddress)
{
- if (this->bt_worker_task != nullptr) {
- vTaskDelete(this->bt_worker_task);
+ for (auto &device : bluetooth::GAP::devices) {
+ if (bd_addr_to_str(device.address) == deviceAddress) {
+ pairedDevices.emplace_back(device);
+ settings->setValue(bluetooth::Settings::BondedDevices, SettingsSerializer::toString(pairedDevices));
+ }
}
- LOG_INFO("Worker removed");
+}
+
+BluetoothWorker::~BluetoothWorker()
+{
+ controller->shutdown();
}
auto BluetoothWorker::run() -> bool
{
LOG_INFO("-> BluetoothWorker run request");
- if (is_running) {
+ if (isRunning) {
return true;
}
- if (Worker::run()) {
- is_running = true;
- auto el = queues[queueIO_handle];
- BlueKitchen::getInstance()->qHandle = el->GetQueueHandle();
- bluetooth::KeyStorage::settings = settings;
-
- driver->registerHardwareErrorCallback(nullptr);
- bluetooth::GAP::register_scan();
-
- std::string name = "PurePhone";
- auto settingsName = std::get<std::string>(settings->getValue(bluetooth::Settings::DeviceName));
- if (settingsName.empty()) {
- LOG_ERROR("settings name empty!");
- settings->setValue(bluetooth::Settings::DeviceName, name);
- settingsName = name;
- }
-
- bluetooth::set_name(settingsName);
- bluetooth::GAP::set_visibility(
- std::visit(bluetooth::BoolVisitor(), settings->getValue(bluetooth::Settings::Visibility)));
- settings->onLinkKeyAdded = [this](std::string addr) {
- for (auto &device : bluetooth::GAP::devices) {
- if (bd_addr_to_str(device.address) == addr) {
- // found paired device
- pairedDevices.emplace_back(device);
- settings->setValue(bluetooth::Settings::BondedDevices, SettingsSerializer::toString(pairedDevices));
- }
- }
- };
-
- return driver->run() == bluetooth::Error::Success;
- }
- else {
- return false;
- }
-}
-
-auto BluetoothWorker::scan() -> bool
-{
- std::vector<Device> empty;
- bluetooth::GAP::setOwnerService(service);
- auto ret = bluetooth::GAP::scan();
- if (ret.err != bluetooth::Error::Success) {
- LOG_ERROR("Cant start scan!: %s %" PRIu32 "", to_string(ret.err).c_str(), ret.lib_code);
+ if (const auto status = Worker::run(); !status) {
return false;
}
- else {
- LOG_INFO("Scan started!");
- // open new scan window
- return true;
- }
-}
-
-void BluetoothWorker::stopScan()
-{
- bluetooth::GAP::stop_scan();
-}
-
-void BluetoothWorker::setVisibility(bool visibility)
-{
- bluetooth::GAP::set_visibility(visibility);
- settings->setValue(bluetooth::Settings::Visibility, visibility);
+ isRunning = true;
+ return true;
}
-auto BluetoothWorker::start_pan() -> bool
-{
- bluetooth::PAN::bnep_setup();
- auto err = bluetooth::PAN::bnep_start();
- if (err.err != bluetooth::Error::Success) {
- LOG_ERROR("PAN setup error: %s %" PRIu32, to_string(err.err).c_str(), err.lib_code);
- }
- return false;
-}
auto BluetoothWorker::handleCommand(QueueHandle_t queue) -> bool
{
bluetooth::Command command;
@@ 149,29 143,16 @@ auto BluetoothWorker::handleCommand(QueueHandle_t queue) -> bool
LOG_ERROR("Queue receive failure!");
return false;
}
- switch (command) {
- case bluetooth::PowerOn:
+ switch (command) {
+ case bluetooth::Command::PowerOn:
+ controller->turnOn();
break;
- case bluetooth::StartScan:
- scan();
- break;
- case bluetooth::StopScan:
- stopScan();
- break;
- case bluetooth::VisibilityOn:
- setVisibility(true);
- break;
- case bluetooth::VisibilityOff:
- setVisibility(false);
- break;
- case bluetooth::ConnectAudio:
- establishAudioConnection();
- break;
- case bluetooth::DisconnectAudio:
- disconnectAudioConnection();
+ case bluetooth::Command::PowerOff:
+ controller->turnOff();
break;
- case bluetooth::PowerOff:
+ default:
+ controller->processCommand(command);
break;
}
return true;
@@ 186,12 167,9 @@ auto BluetoothWorker::handleBtStackTrigger(QueueHandle_t queue) -> bool
}
if (notification) {
runLoop->process();
-
return true;
}
- else {
- return false;
- }
+ return false;
}
auto BluetoothWorker::handleMessage(uint32_t queueID) -> bool
@@ 269,26 247,14 @@ auto BluetoothWorker::handleMessage(uint32_t queueID) -> bool
return true;
}
-auto BluetoothWorker::establishAudioConnection() -> bool
-{
- currentProfile->setOwnerService(service);
- if (currentProfile->init() != bluetooth::Error::Success) {
- return false;
- }
- currentProfile->connect();
- return true;
-}
-auto BluetoothWorker::disconnectAudioConnection() -> bool
-{
- currentProfile->disconnect();
- return true;
-}
void BluetoothWorker::setDeviceAddress(bd_addr_t addr)
{
bluetooth::GAP::do_pairing(addr);
currentProfile->setDeviceAddress(addr);
}
+
auto BluetoothWorker::deinit() -> bool
{
+ controller->turnOff();
return Worker::deinit();
}
M module-bluetooth/Bluetooth/BluetoothWorker.hpp => module-bluetooth/Bluetooth/BluetoothWorker.hpp +12 -26
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 14,6 14,7 @@
#include "service-bluetooth/SettingsHolder.hpp"
#include "glucode/BluetoothRunLoop.hpp"
#include "interface/BluetoothDriver.hpp"
+#include "WorkerController.hpp"
struct HCI;
/// debug option for HCI (uart) commands debugging
@@ 35,18 36,6 @@ namespace bluetooth
EvtErrorRec, /// there was error o queue receive
};
- enum Command : std::uint8_t
- {
- StartScan,
- StopScan,
- VisibilityOn,
- VisibilityOff,
- ConnectAudio,
- DisconnectAudio,
- PowerOn,
- PowerOff,
- };
-
inline const char *MessageCstr(Message what)
{
switch (what) {
@@ 88,9 77,11 @@ class BluetoothWorker : private sys::Worker
queueRunloopTrigger // btstack run_loop queue
};
- TaskHandle_t bt_worker_task = nullptr;
- int is_running = false;
sys::Service *service = nullptr;
+ bool isRunning = false;
+
+ void registerQueues();
+ void onLinkKeyAdded(const std::string &deviceAddress);
public:
enum Error
@@ 104,23 95,18 @@ class BluetoothWorker : private sys::Worker
~BluetoothWorker() override;
auto handleMessage(uint32_t queueID) -> bool override;
-
auto handleCommand(QueueHandle_t queue) -> bool;
auto handleBtStackTrigger(QueueHandle_t queue) -> bool;
- bool run();
- auto scan() -> bool;
- void setVisibility(bool visibility);
- auto start_pan() -> bool;
- auto establishAudioConnection() -> bool;
- auto disconnectAudioConnection() -> bool;
- /// bluetooth stack id in use
- unsigned long active_features;
- void stopScan();
+
+ bool run() override;
void setDeviceAddress(bd_addr_t addr);
auto deinit() -> bool override;
+
+ /// bluetooth stack id in use
+ unsigned long active_features;
std::shared_ptr<bluetooth::Profile> currentProfile;
std::shared_ptr<bluetooth::SettingsHolder> settings;
std::vector<Devicei> pairedDevices;
std::unique_ptr<bluetooth::RunLoop> runLoop;
- std::unique_ptr<bluetooth::Driver> driver;
+ std::unique_ptr<bluetooth::AbstractController> controller;
};
A module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +102 -0
@@ 0,0 1,102 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "CommandHandler.hpp"
+
+#include "BtCommand.hpp"
+#include "Device.hpp"
+
+namespace bluetooth
+{
+ namespace
+ {
+ [[nodiscard]] auto toString(bluetooth::Error::Code code) -> std::string
+ {
+ return utils::enumToString(code);
+ }
+ } // namespace
+
+ CommandHandler::CommandHandler(sys::Service *service,
+ std::shared_ptr<bluetooth::SettingsHolder> settings,
+ std::shared_ptr<bluetooth::Profile> currentProfile)
+ : service{service}, settings{std::move(settings)}, currentProfile{std::move(currentProfile)}
+ {}
+
+ Error::Code CommandHandler::handle(Command command)
+ {
+ switch (command) {
+ case bluetooth::PowerOn:
+ return Error::Success;
+ case bluetooth::StartScan:
+ return scan();
+ case bluetooth::StopScan:
+ return stopScan();
+ case bluetooth::StartPan:
+ return startPan();
+ case bluetooth::VisibilityOn:
+ return setVisibility(true);
+ case bluetooth::VisibilityOff:
+ return setVisibility(false);
+ case bluetooth::ConnectAudio:
+ return establishAudioConnection();
+ case bluetooth::DisconnectAudio:
+ return disconnectAudioConnection();
+ case bluetooth::PowerOff:
+ return Error::Success;
+ }
+ return Error::LibraryError;
+ }
+
+ Error::Code CommandHandler::scan()
+ {
+ bluetooth::GAP::setOwnerService(service);
+ if (const auto ret = bluetooth::GAP::scan(); ret.err != bluetooth::Error::Success) {
+ LOG_ERROR("Cant start scan!: %s %" PRIu32 "", toString(ret.err).c_str(), ret.lib_code);
+ return ret.err;
+ }
+
+ LOG_INFO("Scan started!");
+ // open new scan window
+ return Error::Success;
+ }
+
+ Error::Code CommandHandler::stopScan()
+ {
+ bluetooth::GAP::stop_scan();
+ return Error::Success;
+ }
+
+ Error::Code CommandHandler::startPan()
+ {
+ bluetooth::PAN::bnep_setup();
+ if (const auto err = bluetooth::PAN::bnep_start(); err.err != bluetooth::Error::Success) {
+ LOG_ERROR("PAN setup error: %s %" PRIu32, toString(err.err).c_str(), err.lib_code);
+ return err.err;
+ }
+ return bluetooth::Error::Success;
+ }
+
+ Error::Code CommandHandler::setVisibility(bool visibility)
+ {
+ const auto status = bluetooth::GAP::set_visibility(visibility);
+ settings->setValue(bluetooth::Settings::Visibility, static_cast<int>(visibility));
+ return status.err;
+ }
+
+ Error::Code CommandHandler::establishAudioConnection()
+ {
+ currentProfile->setOwnerService(service);
+ if (const auto status = currentProfile->init(); status != bluetooth::Error::Success) {
+ return status;
+ }
+
+ currentProfile->connect();
+ return Error::Success;
+ }
+
+ Error::Code CommandHandler::disconnectAudioConnection()
+ {
+ currentProfile->disconnect();
+ return Error::Success;
+ }
+} // namespace bluetooth
A module-bluetooth/Bluetooth/CommandHandler.hpp => module-bluetooth/Bluetooth/CommandHandler.hpp +58 -0
@@ 0,0 1,58 @@
+// 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 "Error.hpp"
+#include "interface/profiles/Profile.hpp"
+
+#include <service-bluetooth/SettingsHolder.hpp>
+#include <Service/Service.hpp>
+
+#include <cstdint>
+
+namespace bluetooth
+{
+ enum Command : std::uint8_t
+ {
+ StartScan,
+ StopScan,
+ StartPan,
+ VisibilityOn,
+ VisibilityOff,
+ ConnectAudio,
+ DisconnectAudio,
+ PowerOn,
+ PowerOff,
+ };
+
+ class AbstractCommandHandler
+ {
+ public:
+ virtual ~AbstractCommandHandler() noexcept = default;
+
+ virtual auto handle(Command command) -> Error::Code = 0;
+ };
+
+ class CommandHandler : public AbstractCommandHandler
+ {
+ public:
+ explicit CommandHandler(sys::Service *service,
+ std::shared_ptr<bluetooth::SettingsHolder> settings,
+ std::shared_ptr<bluetooth::Profile> currentProfile);
+
+ auto handle(Command command) -> Error::Code override;
+
+ private:
+ Error::Code scan();
+ Error::Code stopScan();
+ Error::Code startPan();
+ Error::Code setVisibility(bool visibility);
+ Error::Code establishAudioConnection();
+ Error::Code disconnectAudioConnection();
+
+ sys::Service *service;
+ std::shared_ptr<bluetooth::SettingsHolder> settings;
+ std::shared_ptr<bluetooth::Profile> currentProfile;
+ };
+} // namespace bluetooth
A module-bluetooth/Bluetooth/WorkerController.cpp => module-bluetooth/Bluetooth/WorkerController.cpp +219 -0
@@ 0,0 1,219 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "WorkerController.hpp"
+
+#include "Device.hpp"
+#include "interface/profiles/Profile.hpp"
+
+#include <module-utils/log/log.hpp>
+#include <module-utils/sml/include/boost/sml.hpp>
+#include <module-utils/magic_enum/include/magic_enum.hpp>
+
+#include <queue>
+#include <deque>
+
+namespace bluetooth
+{
+ namespace sml = boost::sml;
+
+ namespace
+ {
+ struct Logger
+ {
+ template <class SM, class TEvent> void log_process_event(const TEvent &)
+ {
+ LOG_INFO("[%s][process_event] %s", sml::aux::get_type_name<SM>(), sml::aux::get_type_name<TEvent>());
+ }
+
+ template <class SM, class TGuard, class TEvent> void log_guard(const TGuard &, const TEvent &, bool result)
+ {
+ LOG_INFO("[%s][guard] %s %s %s",
+ sml::aux::get_type_name<SM>(),
+ sml::aux::get_type_name<TGuard>(),
+ sml::aux::get_type_name<TEvent>(),
+ (result ? "[OK]" : "[Reject]"));
+ }
+
+ template <class SM, class TAction, class TEvent> void log_action(const TAction &, const TEvent &)
+ {
+ LOG_INFO("[%s][action] %s %s",
+ sml::aux::get_type_name<SM>(),
+ sml::aux::get_type_name<TAction>(),
+ sml::aux::get_type_name<TEvent>());
+ }
+
+ template <class SM, class TSrcState, class TDstState>
+ void log_state_change(const TSrcState &src, const TDstState &dst)
+ {
+ LOG_INFO("[%s][transition] %s -> %s", sml::aux::get_type_name<SM>(), src.c_str(), dst.c_str());
+ }
+ };
+
+ struct TurnOn
+ {};
+ struct TurnOff
+ {};
+ struct ShutDown
+ {};
+ struct ProcessCommand
+ {
+ Command command;
+ };
+
+ class InitializationError : public std::runtime_error
+ {
+ public:
+ using std::runtime_error::runtime_error;
+ };
+
+ class ProcessingError : public std::runtime_error
+ {
+ public:
+ using std::runtime_error::runtime_error;
+ };
+
+ struct InitializationState
+ {
+ bool isInitDone = false;
+ };
+
+ struct Setup
+ {
+ public:
+ auto operator()() const
+ {
+ auto isInit = [](InitializationState &data) { return data.isInitDone; };
+ auto init = [](std::shared_ptr<AbstractDriver> &driver) {
+ if (const auto status = driver->init(); status != Error::Success) {
+ throw InitializationError{"Unable to initialize a bluetooth driver."};
+ }
+ };
+ auto setup = [](DeviceRegistrationFunction ®isterDevice, InitializationState &data) {
+ if (const auto status = registerDevice(); status != Error::Success) {
+ throw InitializationError{"Unable to initialize bluetooth"};
+ }
+ data.isInitDone = true;
+ };
+ auto startDriver = [](std::shared_ptr<AbstractDriver> &driver) {
+ if (const auto status = driver->run(); status != Error::Success) {
+ throw InitializationError{"Unable to run the bluetooth driver"};
+ }
+ };
+
+ using namespace sml;
+ // clang-format off
+ return make_transition_table(*"Setup"_s / startDriver = "StartingDriver"_s,
+ "Setup"_s + on_entry<_> [ !isInit ] / ( init, setup ),
+ "StartingDriver"_s = X);
+ // clang-format on
+ }
+ };
+
+ struct On
+ {
+ auto operator()() const
+ {
+ auto isInit = [](InitializationState &data) { return data.isInitDone; };
+ auto handleCommand = [](std::shared_ptr<AbstractCommandHandler> &processor,
+ const ProcessCommand &processCommand) {
+ if (const auto status = processor->handle(processCommand.command); status != Error::Success) {
+ throw ProcessingError{"Failed to process command"};
+ }
+ };
+
+ using namespace sml;
+ // clang-format off
+ return make_transition_table(*"Idle"_s + event<ProcessCommand> [ isInit ] / handleCommand = "Processing"_s,
+ "Processing"_s = "Idle"_s);
+ // clang-format on
+ }
+ };
+
+ class StateMachine
+ {
+ public:
+ auto operator()() const
+ {
+ auto turnOff = [](std::shared_ptr<AbstractDriver> &driver) { driver->stop(); };
+ auto printInitError = [](const InitializationError &error) { LOG_ERROR("%s", error.what()); };
+ auto printProcessingError = [](const ProcessingError &error) { LOG_ERROR("%s", error.what()); };
+
+ using namespace sml;
+ // clang-format off
+ return make_transition_table(*"Off"_s + event<TurnOn> = state<Setup>,
+ state<Setup> = state<On>,
+ state<Setup> + exception<InitializationError> / printInitError = "Off"_s,
+ state<On> + event<TurnOff> / turnOff = "Off"_s,
+ state<On> + exception<ProcessingError> / ( printProcessingError, turnOff ) = "Restart"_s,
+ "Restart"_s = state<Setup>,
+ "Off"_s + event<ShutDown> = X);
+ // clang-format on
+ }
+ };
+ } // namespace
+
+ class StatefulController::Impl
+ {
+ public:
+ Impl(Logger logger,
+ std::shared_ptr<AbstractDriver> &&driver,
+ std::shared_ptr<AbstractCommandHandler> &&handler,
+ DeviceRegistrationFunction &®isterDevice);
+
+ using SM =
+ sml::sm<StateMachine, sml::logger<Logger>, sml::defer_queue<std::deque>, sml::process_queue<std::queue>>;
+ SM sm;
+ };
+
+ StatefulController::Impl::Impl(Logger logger,
+ std::shared_ptr<AbstractDriver> &&driver,
+ std::shared_ptr<AbstractCommandHandler> &&handler,
+ DeviceRegistrationFunction &®isterDevice)
+ : sm{std::move(logger), std::move(driver), std::move(handler), std::move(registerDevice), InitializationState{}}
+ {}
+
+ StatefulController::StatefulController(std::shared_ptr<AbstractDriver> &&driver,
+ std::shared_ptr<AbstractCommandHandler> &&handler,
+ DeviceRegistrationFunction &®isterDevice)
+ : pimpl(std::make_unique<Impl>(Logger{}, std::move(driver), std::move(handler), std::move(registerDevice)))
+ {}
+
+ StatefulController::~StatefulController() noexcept = default;
+
+ void StatefulController::turnOn()
+ {
+ pimpl->sm.process_event(TurnOn{});
+ }
+
+ void StatefulController::turnOff()
+ {
+ pimpl->sm.process_event(TurnOff{});
+ }
+
+ void StatefulController::shutdown()
+ {
+ if (isOn()) {
+ turnOff();
+ }
+ pimpl->sm.process_event(ShutDown{});
+ }
+
+ auto StatefulController::isOn() const -> bool
+ {
+ using namespace sml;
+ return !pimpl->sm.is("Off"_s) && !isTerminated();
+ }
+
+ auto StatefulController::isTerminated() const -> bool
+ {
+ using namespace sml;
+ return pimpl->sm.is(X);
+ }
+
+ void StatefulController::processCommand(Command command)
+ {
+ LOG_INFO("Process command: %s", magic_enum::enum_name(command).data());
+ pimpl->sm.process_event(ProcessCommand{command});
+ }
+} // namespace bluetooth
A module-bluetooth/Bluetooth/WorkerController.hpp => module-bluetooth/Bluetooth/WorkerController.hpp +50 -0
@@ 0,0 1,50 @@
+// 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 "CommandHandler.hpp"
+#include "interface/BluetoothDriver.hpp"
+
+#include <functional>
+#include <memory>
+
+namespace bluetooth
+{
+ using DeviceRegistrationFunction = std::function<Error::Code()>;
+
+ class AbstractController
+ {
+ public:
+ virtual ~AbstractController() noexcept = default;
+
+ virtual void turnOn() = 0;
+ virtual void turnOff() = 0;
+ virtual void shutdown() = 0;
+ virtual auto isOn() const -> bool = 0;
+ virtual auto isTerminated() const -> bool = 0;
+
+ virtual void processCommand(Command command) = 0;
+ };
+
+ class StatefulController : public AbstractController
+ {
+ public:
+ StatefulController(std::shared_ptr<AbstractDriver> &&driver,
+ std::shared_ptr<AbstractCommandHandler> &&handler,
+ DeviceRegistrationFunction &®isterDevice);
+ ~StatefulController() noexcept override;
+
+ void turnOn() override;
+ void turnOff() override;
+ void shutdown() override;
+ [[nodiscard]] auto isOn() const -> bool override;
+ [[nodiscard]] auto isTerminated() const -> bool override;
+
+ void processCommand(Command command) override;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> pimpl;
+ };
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/BluetoothDriver.cpp => module-bluetooth/Bluetooth/interface/BluetoothDriver.cpp +10 -7
@@ 35,15 35,15 @@ namespace bluetooth
hci_transport_config_uart_t Driver::config;
#ifdef TARGET_RT1051
- [[maybe_unused]] auto Driver::runLoopInitTarget(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *
+ [[maybe_unused]] auto Driver::runLoopInitTarget(const btstack_run_loop *loop) -> const btstack_uart_block_t *
{
- btstack_run_loop_init(runLoop);
+ btstack_run_loop_init(loop);
const btstack_uart_block_t *uartDriver = btstack_uart_block_rt1051_instance();
return uartDriver;
}
#else
- [[maybe_unused]] auto Driver::runLoopInitLinux(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *
+ [[maybe_unused]] auto Driver::runLoopInitLinux(const btstack_run_loop *) -> const btstack_uart_block_t *
{
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
config.device_name = "/dev/telit";
@@ 53,7 53,10 @@ namespace bluetooth
}
#endif
- auto Driver::init(const btstack_run_loop *runLoop) -> Error::Code
+ Driver::Driver(const btstack_run_loop *runLoop) : runLoop{runLoop}
+ {}
+
+ auto Driver::init() -> Error::Code
{
btstack_memory_init();
config = {
@@ 164,10 167,10 @@ namespace bluetooth
return Error::Success;
}
- void Driver::registerHardwareErrorCallback(std::function<void(uint8_t)> new_callback)
+ void Driver::registerErrorCallback(const ErrorCallback &newCallback)
{
- static std::function<void(uint8_t)> callback = nullptr;
- callback = new_callback;
+ static ErrorCallback callback;
+ callback = newCallback;
hci_set_hardware_error_callback([](uint8_t val) -> void {
LOG_ERROR("Bluetooth HW ERROR! %d", val);
if (callback) {
M module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp +22 -5
@@ 9,21 9,38 @@
namespace bluetooth
{
+ class AbstractDriver
+ {
+ public:
+ using ErrorCallback = std::function<void(uint8_t)>;
+ virtual ~AbstractDriver() noexcept = default;
- class Driver
+ [[nodiscard]] virtual auto init() -> Error::Code = 0;
+ [[nodiscard]] virtual auto run() -> Error::Code = 0;
+ [[nodiscard]] virtual auto stop() -> Error::Code = 0;
+ virtual void registerErrorCallback(const ErrorCallback &newCallback) = 0;
+ };
+
+ class Driver : public AbstractDriver
{
private:
static hci_transport_config_uart_t config;
+ const btstack_run_loop *runLoop;
btstack_packet_callback_registration_t hci_event_callback_registration;
static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void local_version_information_handler(uint8_t *packet);
+#ifdef TARGET_RT1051
[[maybe_unused]] auto runLoopInitTarget(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
+#else
[[maybe_unused]] auto runLoopInitLinux(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
+#endif
public:
- auto init(const btstack_run_loop *runLoop) -> Error::Code;
- auto run() -> Error::Code;
- auto stop() -> Error::Code;
- void registerHardwareErrorCallback(std::function<void(uint8_t)> new_callback);
+ explicit Driver(const btstack_run_loop *runLoop);
+
+ [[nodiscard]] auto init() -> Error::Code override;
+ [[nodiscard]] auto run() -> Error::Code override;
+ [[nodiscard]] auto stop() -> Error::Code override;
+ void registerErrorCallback(const ErrorCallback &newCallback) override;
};
} // namespace bluetooth
M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +6 -0
@@ 6,6 6,8 @@ set(CMAKE_CXX_STANDARD 17)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BluetoothWorker.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/WorkerController.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/CommandHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/glucode/BluetoothRunLoop.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/BluetoothDriver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BtKeysStorage.cpp
@@ 68,3 70,7 @@ target_link_libraries(${PROJECT_NAME}
service-audio
${BOARD_DIR_LIBRARIES}
)
+
+if (${ENABLE_TESTS})
+ add_subdirectory(tests)
+endif()
M module-bluetooth/tests/CMakeLists.txt => module-bluetooth/tests/CMakeLists.txt +9 -0
@@ 0,0 1,9 @@
+add_catch2_executable(
+ NAME
+ StatefulController-tests
+ SRCS
+ tests-main.cpp
+ tests-StatefulController.cpp
+ LIBS
+ module-bluetooth
+)
A module-bluetooth/tests/tests-StatefulController.cpp => module-bluetooth/tests/tests-StatefulController.cpp +171 -0
@@ 0,0 1,171 @@
+// 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 "WorkerController.hpp"
+#include "interface/BluetoothDriver.hpp"
+
+#include <iostream>
+
+using namespace bluetooth;
+
+class DriverMock : public AbstractDriver
+{
+ public:
+ Error::Code init() override
+ {
+ return initReturnCode;
+ }
+ Error::Code run() override
+ {
+ return runReturnCode;
+ }
+ Error::Code stop() override
+ {
+ return stopReturnCode;
+ }
+ void registerErrorCallback(const ErrorCallback &) override
+ {}
+
+ Error::Code initReturnCode = Error::Success;
+ Error::Code runReturnCode = Error::Success;
+ Error::Code stopReturnCode = Error::Success;
+};
+
+auto InitializerMock = []() { return Error::Success; };
+
+class HandlerMock : public AbstractCommandHandler
+{
+ public:
+ Error::Code handle(Command command) override
+ {
+ return returnCode;
+ }
+
+ Error::Code returnCode = Error::Success;
+};
+
+TEST_CASE("Given StatefulController when turn on then turned on")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when error during device registration then turned off")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), []() { return Error::SystemError; }};
+ controller.turnOn();
+ REQUIRE(!controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when error during driver init then turned off")
+{
+ auto driver = std::make_unique<DriverMock>();
+ driver->initReturnCode = Error::SystemError;
+
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(!controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when error during driver run then turned off")
+{
+ auto driver = std::make_unique<DriverMock>();
+ driver->runReturnCode = Error::SystemError;
+
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(!controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when restart then don't init twice")
+{
+ auto driver = std::make_shared<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{driver, std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.turnOff();
+ REQUIRE(!controller.isOn());
+
+ driver->initReturnCode = Error::SystemError;
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when turn off in off state then turned off")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOff();
+ REQUIRE(!controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when turn off in on state then turned off")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.turnOff();
+ REQUIRE(!controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when shutdown in off state then terminated")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.shutdown();
+ REQUIRE(controller.isTerminated());
+}
+
+TEST_CASE("Given StatefulController when shutdown in on state then terminated")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.shutdown();
+ REQUIRE(controller.isTerminated());
+}
+
+TEST_CASE("Given StatefulController when process command successfully then turned on")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.processCommand(Command::PowerOn);
+ REQUIRE(controller.isOn());
+}
+
+TEST_CASE("Given StatefulController when processing command failed then restarted and turned on")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ processor->returnCode = Error::SystemError;
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.processCommand(Command::PowerOn);
+ controller.processCommand(Command::PowerOn);
+ REQUIRE(controller.isOn());
+}
A module-bluetooth/tests/tests-main.cpp => module-bluetooth/tests/tests-main.cpp +5 -0
@@ 0,0 1,5 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
+#include <catch2/catch.hpp>
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +13 -19
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Constants.hpp"
@@ 42,6 42,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
{
LOG_ERROR("Bluetooth experimental!");
worker = std::make_unique<BluetoothWorker>(this);
+ worker->run();
connect(message::bluetooth::RequestBondedDevices(), [&](sys::Message *msg) {
auto bondedDevicesStr =
@@ 65,21 66,20 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
connect(typeid(message::bluetooth::SetStatus), [&](sys::Message *msg) {
auto setStatusMsg = static_cast<message::bluetooth::SetStatus *>(msg);
- auto btStatus = setStatusMsg->getStatus();
- worker->setVisibility(btStatus.visibility);
+ auto newBtStatus = setStatusMsg->getStatus();
- switch (btStatus.state) {
+ switch (newBtStatus.state) {
case BluetoothStatus::State::On:
- worker->run();
+ sendWorkerCommand(bluetooth::Command::PowerOn);
break;
case BluetoothStatus::State::Off:
- // TODO
+ sendWorkerCommand(bluetooth::Command::PowerOff);
break;
default:
break;
}
-
- return std::make_shared<message::bluetooth::ResponseStatus>(btStatus);
+ sendWorkerCommand(newBtStatus.visibility ? bluetooth::VisibilityOn : bluetooth::VisibilityOff);
+ return sys::MessageNone{};
});
connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) {
@@ 99,7 99,6 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
auto initialState = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State));
if (static_cast<BluetoothStatus::State>(initialState) == BluetoothStatus::State::On) {
settingsHolder->setValue(bluetooth::Settings::State, static_cast<int>(BluetoothStatus::State::Off));
- worker->run();
}
};
@@ 122,15 121,10 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
switch (lmsg->req) {
case BluetoothMessage::Start:
worker->run();
-
break;
case BluetoothMessage::Scan:
- if (worker->scan()) {
- return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Success);
- }
- else {
- return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Failure);
- }
+ sendWorkerCommand(bluetooth::StartScan);
+ break;
case BluetoothMessage::StopScan:
sendWorkerCommand(bluetooth::StopScan);
break;
@@ 145,19 139,19 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
// else {
/// TODO request PPP
LOG_INFO("Start PAN");
- worker->start_pan();
+ sendWorkerCommand(bluetooth::StartPan);
// }
} break;
case BluetoothMessage::Visible: {
static bool visibility = true;
- worker->setVisibility(visibility);
+ sendWorkerCommand(visibility ? bluetooth::VisibilityOn : bluetooth::VisibilityOff);
visibility = !visibility;
} break;
case BluetoothMessage::Play:
sendWorkerCommand(bluetooth::ConnectAudio);
break;
- case BluetoothMessage::Stop:
+ case BluetoothMessage::StopPlayback:
sendWorkerCommand(bluetooth::DisconnectAudio);
break;
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 43,7 43,7 @@ class BluetoothMessage : public sys::DataMessage
PAN,
Visible,
Play,
- Stop
+ StopPlayback
};
enum Request req = Request::None;
BluetoothMessage(enum Request req = None) : sys::DataMessage(MessageType::BluetoothRequest), req(req){};
M module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp => module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp +3 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SettingsHolder.hpp"
@@ 20,7 20,8 @@ namespace bluetooth
{
settingsMap[newSetting] = value;
- settingsProvider->setValue(settingString[newSetting], std::visit(StringVisitor(), value));
+ settingsProvider->setValue(
+ settingString[newSetting], std::visit(StringVisitor(), value), ::settings::SettingsScope::Global);
LOG_INFO("setting %s set: %s", settingString[newSetting].c_str(), std::visit(StringVisitor(), value).c_str());
}
SettingsHolder::SettingsHolder(std::unique_ptr<settings::Settings> settingsPtr)
M module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp => module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// 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 <json/json11.hpp>
@@ 82,7 82,7 @@ namespace bluetooth
auto getValue(const Settings setting) -> SettingEntry;
void setValue(const Settings &newSetting, const SettingEntry &value);
std::function<void()> onStateChange;
- std::function<void(std::string addr)> onLinkKeyAdded;
+ std::function<void(const std::string &)> onLinkKeyAdded;
private:
static std::map<Settings, std::string> settingString;
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +1 -1
@@ 62,7 62,7 @@ auto DeveloperModeHelper::processPutRequest(Context &context) -> sys::ReturnCode
LOG_INFO("turning on BT from harness!");
}
else {
- request = BluetoothMessage::Request::Stop;
+ request = BluetoothMessage::Request::StopPlayback;
LOG_INFO("turning off BT from harness!");
}
std::shared_ptr<BluetoothMessage> msg = std::make_shared<BluetoothMessage>(request);