From 46b89140540ad9eaca3e5ae39838b158488cbf80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kamo=C5=84?= Date: Fri, 5 Mar 2021 16:08:28 +0100 Subject: [PATCH] [EGD-5945] Bluetooth-harness API messages This PR: * provides Bluetooth-Harness API messages definition [EGD-5944] * provides Bluetooth-Harness API messages implementation * provides Bluetooth-Harness API usage on harness side [EGD-5946] * provides Bluetooth-Harness tests [EGD-5947] --- .../ApplicationSettings.cpp | 6 +- module-bluetooth/Bluetooth/CommandHandler.cpp | 22 +- module-bluetooth/Bluetooth/CommandHandler.hpp | 4 +- .../interface/profiles/A2DP/A2DP.cpp | 8 +- .../service-bluetooth/ServiceBluetooth.cpp | 375 ++++++++++-------- .../service-bluetooth/BluetoothMessage.hpp | 28 +- .../service-bluetooth/ServiceBluetooth.hpp | 43 +- .../service-bluetooth/messages/Disconnect.hpp | 3 + .../service-desktop/CMakeLists.txt | 2 + .../service-desktop/DesktopMessages.cpp | 22 +- module-services/service-desktop/README.md | 14 +- .../service-desktop/ServiceDesktop.cpp | 19 +- .../endpoints/bluetooth/BluetoothEndpoint.cpp | 4 +- .../bluetooth/BluetoothEventMessages.cpp | 16 + .../bluetooth/BluetoothEventMessages.hpp | 23 ++ .../endpoints/bluetooth/BluetoothHelper.cpp | 105 ++++- .../endpoints/bluetooth/BluetoothHelper.hpp | 39 +- .../bluetooth/BluetoothMessagesHandler.cpp | 82 ++++ .../bluetooth/BluetoothMessagesHandler.hpp | 38 ++ .../service-desktop/DesktopMessages.hpp | 21 - .../service-desktop/DeveloperModeMessage.hpp | 1 - .../service-desktop/ServiceDesktop.hpp | 6 + source/MessageType.hpp | 1 + test/pytest/service-bluetooth/bt_fixtures.py | 65 +++ test/pytest/service-bluetooth/bt_utils.py | 133 +++++-- .../test_basic_control_dev_perspective.py | 55 +++ .../test_pairing_dev_perspective.py | 80 ++++ ...ing.py => test_pairing_hmi_perspective.py} | 7 +- test/pytest/service-desktop/test_bluetooth.py | 75 ---- 29 files changed, 885 insertions(+), 412 deletions(-) create mode 100644 module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.cpp create mode 100644 module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.hpp create mode 100644 module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.cpp create mode 100644 module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.hpp create mode 100644 test/pytest/service-bluetooth/bt_fixtures.py create mode 100644 test/pytest/service-bluetooth/test_basic_control_dev_perspective.py create mode 100644 test/pytest/service-bluetooth/test_pairing_dev_perspective.py rename test/pytest/service-bluetooth/{test_pairing.py => test_pairing_hmi_perspective.py} (91%) delete mode 100644 test/pytest/service-desktop/test_bluetooth.py diff --git a/module-apps/application-settings/ApplicationSettings.cpp b/module-apps/application-settings/ApplicationSettings.cpp index 5f482576547b87f36ff78990576c177d6d993c6d..42f5bd77cba1fdbb03106c69a298d5d49a383bf8 100644 --- a/module-apps/application-settings/ApplicationSettings.cpp +++ b/module-apps/application-settings/ApplicationSettings.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -63,10 +64,9 @@ namespace app if (reinterpret_cast(retMsg.get())->retCode == sys::ReturnCodes::Success) { return retMsg; } - if (auto btmsg = dynamic_cast(msgl); btmsg != nullptr) { - auto devices = btmsg->devices; + if (auto btmsg = dynamic_cast(msgl); btmsg != nullptr) { LOG_INFO("received BT Scan message!"); - auto data = std::make_unique(devices); + auto data = std::make_unique(btmsg->getDevices()); windowsFactory.build(this, gui::name::window::name_btscan); switchWindow(gui::name::window::name_btscan, gui::ShowMode::GUI_SHOW_INIT, std::move(data)); diff --git a/module-bluetooth/Bluetooth/CommandHandler.cpp b/module-bluetooth/Bluetooth/CommandHandler.cpp index 1bae984d50798309f47eb746a656357f07fb846b..27acbf05f996cc4f1b7ad0c7555a30d4877f53e1 100644 --- a/module-bluetooth/Bluetooth/CommandHandler.cpp +++ b/module-bluetooth/Bluetooth/CommandHandler.cpp @@ -2,16 +2,19 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "CommandHandler.hpp" +#include #include -#include #include - #include #include "Device.hpp" #include "BtCommand.hpp" +#include +#include +#include "GAP/GAP.hpp" + extern "C" { #include @@ -42,6 +45,8 @@ namespace bluetooth return Error::Success; case bluetooth::Command::StartScan: return scan(); + case bluetooth::Command::getDevicesAvailable: + return availableDevices(); case bluetooth::Command::StopScan: return stopScan(); case bluetooth::Command::StartPan: @@ -83,7 +88,6 @@ namespace bluetooth } LOG_INFO("Scan started!"); - static_cast(service)->scanStartedCallback(); // open new scan window return Error::Success; } @@ -92,7 +96,6 @@ namespace bluetooth { LOG_INFO("Stopping scan!"); driver->stopScan(); - static_cast(service)->scanStoppedCallback(); return Error::Success; } @@ -117,16 +120,12 @@ namespace bluetooth { profileManager->init(); LOG_INFO("Connecting audio with %s", bd_addr_to_str(addr)); - std::string devAddr{bd_addr_to_str(addr)}; - settings->setValue(bluetooth::Settings::ConnectedDevice, std::move(devAddr)); profileManager->connect(addr); - return Error::Success; } Error::Code CommandHandler::disconnectAudioConnection() { - settings->setValue(bluetooth::Settings::ConnectedDevice, std::string()); profileManager->disconnect(); return Error::Success; } @@ -157,4 +156,11 @@ namespace bluetooth return driver->unpair(addr) ? Error::Success : Error::LibraryError; } + Error::Code CommandHandler::availableDevices() + { + auto msg = std::make_shared(bluetooth::GAP::getDevicesList()); + static_cast(service)->bus.sendUnicast(std::move(msg), service::name::service_desktop); + + return Error::Success; + } } // namespace bluetooth diff --git a/module-bluetooth/Bluetooth/CommandHandler.hpp b/module-bluetooth/Bluetooth/CommandHandler.hpp index eb3533473039f0767436f639c8ad7c6797e6a99b..cf71639ea5a29fad43e186958575b90a82428fac 100644 --- a/module-bluetooth/Bluetooth/CommandHandler.hpp +++ b/module-bluetooth/Bluetooth/CommandHandler.hpp @@ -12,6 +12,7 @@ namespace sys { class Service; + class Message; } namespace bluetooth @@ -24,6 +25,7 @@ namespace bluetooth { StartScan, StopScan, + getDevicesAvailable, StartPan, VisibilityOn, VisibilityOff, @@ -91,7 +93,7 @@ namespace bluetooth Error::Code disconnectAudioConnection(); Error::Code pair(bd_addr_t addr); Error::Code unpair(bd_addr_t addr); - + Error::Code availableDevices(); Error::Code switchAudioProfile(); sys::Service *service; std::shared_ptr settings; diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp index 223f79734724542b8a1747058ca79b9825b111e9..b7fca598807f149e21e777df3a476a3c80ea99d8 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp @@ -18,6 +18,7 @@ #include #include #include "service-bluetooth/messages/Connect.hpp" +#include "service-bluetooth/messages/Disconnect.hpp" #include "service-bluetooth/Constants.hpp" extern "C" { @@ -336,7 +337,7 @@ namespace bluetooth auto &busProxy = const_cast(ownerService)->bus; busProxy.sendUnicast( std::make_shared(std::move(deviceAddress), false), - "ApplicationSettingsNew"); + service::name::bluetooth); break; } AVRCP::mediaTracker.a2dp_cid = cid; @@ -349,7 +350,7 @@ namespace bluetooth isConnected = true; auto &busProxy = const_cast(ownerService)->bus; busProxy.sendUnicast(std::make_shared(std::move(deviceAddress), true), - "ApplicationSettingsNew"); + service::name::bluetooth); break; } case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: { @@ -572,7 +573,8 @@ namespace bluetooth AVRCP::mediaTracker.a2dp_cid = 0; LOG_INFO("A2DP Source: Signaling released.\n\n"); auto &busProxy = const_cast(ownerService)->bus; - busProxy.sendUnicast(std::make_shared(), service::name::bluetooth); + busProxy.sendUnicast(std::make_shared(), + service::name::bluetooth); } isConnected = false; break; diff --git a/module-services/service-bluetooth/ServiceBluetooth.cpp b/module-services/service-bluetooth/ServiceBluetooth.cpp index 23788fd009717bd5ee16a23fb5c76b78aec34d2a..85187019f961a7048c9d5da0c8d98dc21f227cba 100644 --- a/module-services/service-bluetooth/ServiceBluetooth.cpp +++ b/module-services/service-bluetooth/ServiceBluetooth.cpp @@ -14,7 +14,9 @@ #include "service-bluetooth/messages/Disconnect.hpp" #include "service-bluetooth/messages/Status.hpp" #include "service-bluetooth/messages/SetStatus.hpp" -#include +#include "service-bluetooth/messages/BondedDevices.hpp" +#include "service-bluetooth/messages/Unpair.hpp" +#include "service-bluetooth/messages/SetDeviceName.hpp" #include #include "SystemManager/messages/SentinelRegistrationMessage.hpp" @@ -22,15 +24,17 @@ #include #include #include -#include -#include +#include +#include #include #include -#include + +#include namespace { constexpr auto BluetoothServiceStackDepth = 2560U; + inline constexpr auto nameSettingsNew = "ApplicationSettingsNew"; } // namespace ServiceBluetooth::ServiceBluetooth() : sys::Service(service::name::bluetooth, "", BluetoothServiceStackDepth) @@ -63,111 +67,67 @@ sys::ReturnCodes ServiceBluetooth::InitHandler() worker->run(); connect(message::bluetooth::RequestBondedDevices(), [&](sys::Message *msg) { - 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)); - - return std::make_shared( - SettingsSerializer::fromString(bondedDevicesStr), std::move(connectedAddress)); + auto request = static_cast(msg); + return handle(request); }); connect(message::bluetooth::RequestStatus(), [&](sys::Message *msg) { - BluetoothStatus status; - - auto state = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State)); - auto visibility = - std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::Visibility)); - status.state = static_cast(state); - status.visibility = visibility; - - return std::make_shared(status); + auto request = static_cast(msg); + return handle(request); }); connect(typeid(message::bluetooth::SetStatus), [&](sys::Message *msg) { - auto setStatusMsg = static_cast(msg); - auto newBtStatus = setStatusMsg->getStatus(); - - switch (newBtStatus.state) { - case BluetoothStatus::State::On: - if (msg->sender == "ServiceDesktop") { - enabledFromHarness = true; - LOG_INFO("BT enabled from Harness"); - } - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOn)); - break; - case BluetoothStatus::State::Off: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOff)); - enabledFromHarness = false; - break; - default: - break; - } - bluetooth::Command command(newBtStatus.visibility ? bluetooth::Command::Type::VisibilityOn - : bluetooth::Command::Type::VisibilityOff); - sendWorkerCommand(command); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); connect(typeid(BluetoothPairMessage), [&](sys::Message *msg) { - auto pairMsg = static_cast(msg); - const auto addrString = pairMsg->addr; - bd_addr_t addr; - sscanf_bd_addr(addrString.c_str(), addr); - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Pair, addr)); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); connect(typeid(message::bluetooth::Unpair), [&](sys::Message *msg) { - auto unpairMsg = static_cast(msg); - const auto addrString = unpairMsg->getAddr(); - bd_addr_t addr; - sscanf_bd_addr(addrString.c_str(), addr); - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Unpair, addr)); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); connect(typeid(message::bluetooth::SetDeviceName), [&](sys::Message *msg) { - auto setNameMsg = static_cast(msg); - auto newName = setNameMsg->getName(); - bluetooth::set_name(newName); - settingsHolder->setValue(bluetooth::Settings::DeviceName, newName); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); - connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) { - using namespace sdesktop::developerMode; - auto req = static_cast(msg); - if (typeid(*req->event) == typeid(sdesktop::bluetooth::BluetoothStatusRequestEvent)) { - auto state = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State)); - auto event = std::make_unique(state); - auto message = std::make_shared(std::move(event)); - bus.sendUnicast(std::move(message), service::name::service_desktop); - } - - return sys::MessageNone{}; + connect(typeid(sdesktop::developerMode::DeveloperModeRequest), [&](sys::Message *msg) { + auto request = static_cast(msg); + return handle(request); }); connect(typeid(message::bluetooth::Connect), [&](sys::Message *msg) { - auto connectMsg = static_cast(msg); - const auto addrString = connectMsg->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)); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); connect(typeid(message::bluetooth::Disconnect), [&](sys::Message *msg) { - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::DisconnectAudio)); - return sys::MessageNone{}; + auto request = static_cast(msg); + return handle(request); }); - connect(typeid(BluetoothDeviceDisconnectedMessage), [&](sys::Message *msg) { - settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, std::string()); + connect(typeid(BluetoothMessage), [&](sys::Message *msg) { + auto request = static_cast(msg); + return handle(request); + }); + + connect(typeid(BluetoothAddrMessage), [&](sys::Message *msg) { + auto request = static_cast(msg); + return handle(request); + }); + + connect(typeid(message::bluetooth::ConnectResult), [&](sys::Message *msg) { + auto result = static_cast(msg); + return handle(result); + }); - sendDevicesAfterDisconnect(); - return sys::MessageNone{}; + connect(typeid(message::bluetooth::DisconnectResult), [&](sys::Message *msg) { + auto result = static_cast(msg); + return handle(result); }); settingsHolder->onStateChange = [this]() { @@ -191,78 +151,9 @@ void ServiceBluetooth::ProcessCloseReason(sys::CloseReason closeReason) sendCloseReadyMessage(this); } -sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) +sys::MessagePointer ServiceBluetooth::DataReceivedHandler([[maybe_unused]] sys::DataMessage *msg, + [[maybe_unused]] sys::ResponseMessage *resp) { - try { - switch (static_cast(msg->messageType)) { - case MessageType::BluetoothRequest: { - BluetoothMessage *lmsg = dynamic_cast(msg); - LOG_INFO("Bluetooth request!"); - switch (lmsg->req) { - case BluetoothMessage::Start: - break; - case BluetoothMessage::Scan: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartScan)); - break; - case BluetoothMessage::StopScan: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StopScan)); - break; - case BluetoothMessage::PAN: { - /// TODO request lwip first... - /// because TODO blocking message - wrecks system - LOG_INFO("Request LwIP running!"); - // auto ret = message_lwip(this, LwIP_message::Request::Start); - // if (ret != sys::ReturnCodes::Success) { - // LOG_ERROR("Request for LwIP start failed"); - // } - // else { - /// TODO request PPP - LOG_INFO("Start PAN"); - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartPan)); - // } - } break; - case BluetoothMessage::Visible: { - static bool visibility = true; - bluetooth::Command command(visibility ? bluetooth::Command::Type::VisibilityOn - : bluetooth::Command::Type::VisibilityOff); - sendWorkerCommand(command); - visibility = !visibility; - } break; - - case BluetoothMessage::Play: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartStream)); - break; - case BluetoothMessage::SwitchProfile: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::SwitchProfile)); - - break; - case BluetoothMessage::Disconnect: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::DisconnectAudio)); - break; - case BluetoothMessage::Stop: - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StopStream)); - break; - - default: - break; - } - break; - } - case MessageType::BluetoothAddrResult: { - auto addrMsg = static_cast(msg); - std::string addrString{bd_addr_to_str(addrMsg->addr)}; - LOG_INFO("Connecting with %s", addrString.c_str()); - sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio, addrMsg->addr)); - - } break; - default: - break; - } - } - catch (std::exception &ex) { - LOG_ERROR("Exception on BtService!: %s", ex.what()); - } - return std::make_shared(); } @@ -275,29 +166,177 @@ void ServiceBluetooth::sendWorkerCommand(bluetooth::Command command) { xQueueSend(workerQueue, &command, portMAX_DELAY); } -void ServiceBluetooth::scanStartedCallback() + +auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestBondedDevices *msg) + -> std::shared_ptr +{ + 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)); + + return std::make_shared(SettingsSerializer::fromString(bondedDevicesStr), + std::move(connectedAddress)); +} + +auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestStatus *msg) -> std::shared_ptr +{ + auto state = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State)); + auto visibility = std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::Visibility)); + + BluetoothStatus status{static_cast(state), status.visibility = visibility}; + return std::make_shared(status); +} + +auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr { - if (enabledFromHarness) { - auto event = std::make_unique(); - auto message = std::make_shared(std::move(event)); - bus.sendUnicast(std::move(message), service::name::service_desktop); + auto newBtStatus = msg->getStatus(); + + switch (newBtStatus.state) { + case BluetoothStatus::State::On: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOn)); + break; + case BluetoothStatus::State::Off: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOff)); + break; + default: + break; } + bluetooth::Command command(newBtStatus.visibility ? bluetooth::Command::Type::VisibilityOn + : bluetooth::Command::Type::VisibilityOff); + sendWorkerCommand(command); + return sys::MessageNone{}; } -void ServiceBluetooth::scanStoppedCallback() +auto ServiceBluetooth::handle(BluetoothPairMessage *msg) -> std::shared_ptr { - if (enabledFromHarness) { - auto event = std::make_unique(); - auto message = std::make_shared(std::move(event)); - bus.sendUnicast(std::move(message), service::name::service_desktop); + const auto addrString = msg->addr; + bd_addr_t addr; + sscanf_bd_addr(addrString.c_str(), addr); + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Pair, addr)); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle(message::bluetooth::Unpair *msg) -> std::shared_ptr +{ + const auto addrString = msg->getAddr(); + bd_addr_t addr; + sscanf_bd_addr(addrString.c_str(), addr); + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Unpair, addr)); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle(message::bluetooth::SetDeviceName *msg) -> std::shared_ptr +{ + auto newName = msg->getName(); + bluetooth::set_name(newName); + settingsHolder->setValue(bluetooth::Settings::DeviceName, newName); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle(message::bluetooth::Connect *msg) -> std::shared_ptr +{ + 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)); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle(message::bluetooth::ConnectResult *msg) -> std::shared_ptr +{ + if (msg->isSucceed()) { + settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, msg->getAddr()); } + bus.sendUnicast(std::make_shared(*msg), nameSettingsNew); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::Disconnect *msg) -> std::shared_ptr +{ + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::DisconnectAudio)); + return sys::MessageNone{}; } -void ServiceBluetooth::sendDevicesAfterDisconnect() +auto ServiceBluetooth::handle(message::bluetooth::DisconnectResult *msg) -> std::shared_ptr { + settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, std::string()); auto bondedDevicesStr = std::visit(bluetooth::StringVisitor(), this->settingsHolder->getValue(bluetooth::Settings::BondedDevices)); - bus.sendUnicast(std::make_shared( SettingsSerializer::fromString(bondedDevicesStr), std::string()), - "ApplicationSettingsNew"); + nameSettingsNew); + return sys::MessageNone{}; +} + +auto ServiceBluetooth::handle(BluetoothMessage *msg) -> std::shared_ptr +{ + LOG_INFO("Bluetooth request!"); + switch (msg->req) { + case BluetoothMessage::Start: + break; + case BluetoothMessage::Scan: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartScan)); + break; + case BluetoothMessage::StopScan: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StopScan)); + break; + case BluetoothMessage::getDevicesAvailable: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::getDevicesAvailable)); + break; + case BluetoothMessage::PAN: { + /// TODO request lwip first... + /// because TODO blocking message - wrecks system + LOG_INFO("Request LwIP running!"); + // auto ret = message_lwip(this, LwIP_message::Request::Start); + // if (ret != sys::ReturnCodes::Success) { + // LOG_ERROR("Request for LwIP start failed"); + // } + // else { + /// TODO request PPP + LOG_INFO("Start PAN"); + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartPan)); + // } + } break; + case BluetoothMessage::Visible: { + auto visibility = + not std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::Visibility)); + bluetooth::Command command(visibility ? bluetooth::Command::Type::VisibilityOn + : bluetooth::Command::Type::VisibilityOff); + sendWorkerCommand(command); + } break; + case BluetoothMessage::Play: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartStream)); + break; + case BluetoothMessage::SwitchProfile: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::SwitchProfile)); + break; + case BluetoothMessage::Disconnect: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::DisconnectAudio)); + break; + case BluetoothMessage::Stop: + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StopStream)); + break; + default: + break; + } + + return std::make_shared(); +} + +auto ServiceBluetooth::handle(BluetoothAddrMessage *msg) -> std::shared_ptr +{ + 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)); + return std::make_shared(); +} + +auto ServiceBluetooth::handle(sdesktop::developerMode::DeveloperModeRequest *msg) -> std::shared_ptr +{ + if (typeid(*msg->event) == typeid(sdesktop::bluetooth::GetAvailableDevicesEvent)) { + sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::getDevicesAvailable)); + } + return sys::MessageNone{}; } diff --git a/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp b/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp index ade04912c82c966d51a5bcb672e8c510dae55d47..4aa56571cdb863e85282874d4dfa75393ecf4ebe 100644 --- a/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +++ b/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp @@ -34,6 +34,7 @@ class BluetoothMessage : public sys::DataMessage Start, Scan, StopScan, + getDevicesAvailable, PAN, Visible, Play, @@ -47,16 +48,6 @@ class BluetoothMessage : public sys::DataMessage ~BluetoothMessage() override = default; }; -class BluetoothScanResultMessage : public sys::DataMessage -{ - public: - std::vector devices; - BluetoothScanResultMessage(std::vector devices) - : sys::DataMessage(MessageType::BluetoothScanResult), devices(std::move(devices)) - {} - ~BluetoothScanResultMessage() override = default; -}; - class BluetoothPairResultMessage : public sys::DataMessage { public: @@ -78,16 +69,6 @@ class BluetoothPairResultMessage : public sys::DataMessage bool succeed; }; -class BluetoothScanMessage : public sys::DataMessage -{ - public: - std::vector devices; - BluetoothScanMessage(std::vector devices) - : sys::DataMessage(MessageType::BluetoothScanResult), devices(std::move(devices)) - {} - ~BluetoothScanMessage() override = default; -}; - class BluetoothAddrMessage : public sys::DataMessage { public: @@ -150,10 +131,3 @@ class BluetoothRequestStreamResultMessage : public sys::DataMessage private: std::shared_ptr data; }; - -class BluetoothDeviceDisconnectedMessage : public sys::DataMessage -{ - public: - BluetoothDeviceDisconnectedMessage() : DataMessage(MessageType::BluetoothDeviceDisconnected) - {} -}; diff --git a/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp b/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp index 3fd07457f92892fa03674c1f9099100be226497f..eed4d09070bfe87e610da85a2452b9f7717fc27d 100644 --- a/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +++ b/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp @@ -11,7 +11,6 @@ #include #include #include -#include "BluetoothMessage.hpp" #include "ProfileManager.hpp" #include @@ -23,6 +22,30 @@ namespace settings class Settings; } +namespace sdesktop +{ + class Event; + namespace developerMode + { + class DeveloperModeRequest; + class DeveloperModeMessageWrapper; + } // namespace developerMode +} // namespace sdesktop + +namespace message::bluetooth +{ + class RequestBondedDevices; + class RequestStatus; + class SetStatus; + class Unpair; + class SetDeviceName; + class Connect; + class ConnectResult; + class Disconnect; + class DisconnectResult; + +} // namespace message::bluetooth + class ServiceBluetooth : public sys::Service { @@ -39,14 +62,24 @@ class ServiceBluetooth : public sys::Service QueueHandle_t workerQueue = nullptr; std::shared_ptr settingsHolder; bluetooth::ProfileManager *profileManagerPtr = nullptr; - void scanStartedCallback(); - void scanStoppedCallback(); private: std::unique_ptr worker; std::shared_ptr cpuSentinel; - bool enabledFromHarness = false; - void sendDevicesAfterDisconnect(); + + [[nodiscard]] auto handle(message::bluetooth::RequestBondedDevices *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::RequestStatus *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(BluetoothPairMessage *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::Unpair *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::SetDeviceName *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::Connect *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::ConnectResult *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::Disconnect *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::DisconnectResult *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(BluetoothMessage *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(BluetoothAddrMessage *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(sdesktop::developerMode::DeveloperModeRequest *msg) -> std::shared_ptr; }; namespace sys diff --git a/module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp b/module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp index 90f3f049b67100ef2c697f9279415bfd1f96ec82..f0dc34ef6d52c36e2d2789fb75436dd233f1ce78 100644 --- a/module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp +++ b/module-services/service-bluetooth/service-bluetooth/messages/Disconnect.hpp @@ -9,4 +9,7 @@ namespace message::bluetooth { class Disconnect : public BluetoothMessage {}; + + class DisconnectResult : public BluetoothMessage + {}; } // namespace message::bluetooth diff --git a/module-services/service-desktop/CMakeLists.txt b/module-services/service-desktop/CMakeLists.txt index 2e5fbccfd439ad0305042b753de0c15d18354c36..ef7b4de62251c76403eb97d5750af5085ff9f27d 100644 --- a/module-services/service-desktop/CMakeLists.txt +++ b/module-services/service-desktop/CMakeLists.txt @@ -6,6 +6,8 @@ set(SOURCES endpoints/backup/BackupRestore.cpp endpoints/bluetooth/BluetoothEndpoint.cpp endpoints/bluetooth/BluetoothHelper.cpp + endpoints/bluetooth/BluetoothEventMessages.cpp + endpoints/bluetooth/BluetoothMessagesHandler.cpp endpoints/calllog/CalllogEndpoint.cpp endpoints/calllog/CalllogHelper.cpp endpoints/contacts/ContactHelper.cpp diff --git a/module-services/service-desktop/DesktopMessages.cpp b/module-services/service-desktop/DesktopMessages.cpp index 80e32a4f147dad1f12969486c2e57d1c895451e6..d3a9423d797050991dce9a30afd95e552393b358 100644 --- a/module-services/service-desktop/DesktopMessages.cpp +++ b/module-services/service-desktop/DesktopMessages.cpp @@ -3,6 +3,7 @@ #include "service-desktop/DesktopMessages.hpp" #include "parser/MessageHandler.hpp" +#include namespace sdesktop { @@ -31,26 +32,5 @@ namespace sdesktop context.setResponseBody(json11::Json::object{{json::developerMode::cellularStateInfo, stateStr}}); } } // namespace developerMode - namespace bluetooth - { - BluetoothStatusRequestEvent::BluetoothStatusRequestEvent(int state) - { - context.setResponseStatus(http::Code::OK); - context.setEndpoint(EndpointType::bluetooth); - context.setResponseBody(json11::Json::object{{json::bluetooth::state, state}}); - } - ScanStartedEvent::ScanStartedEvent() - { - context.setResponseStatus(http::Code::OK); - context.setEndpoint(EndpointType::bluetooth); - context.setResponseBody(json11::Json::object{{json::bluetooth::scan, json::bluetooth::btOn}}); - } - ScanStoppedEvent::ScanStoppedEvent() - { - context.setResponseStatus(http::Code::OK); - context.setEndpoint(EndpointType::bluetooth); - context.setResponseBody(json11::Json::object{{json::bluetooth::scan, json::bluetooth::btOff}}); - } - } // namespace bluetooth } // namespace sdesktop diff --git a/module-services/service-desktop/README.md b/module-services/service-desktop/README.md index a3be10d3b50117dcd89c8809311e86cc1f17f835..ba604656e3368e85a6248e925c255e28502c70c2 100644 --- a/module-services/service-desktop/README.md +++ b/module-services/service-desktop/README.md @@ -1,11 +1,11 @@ Service Desktop ================= -This service is handling communication between Mudita Deskatop App and PurePhone. +This service is handling communication between Mudita Desktop App and PurePhone. **Note: Service desktop is disabled by default. -To turn it on, please uncomment this line in mail.cpp:** +To turn it on, please uncomment this line in main.cpp:** ` ret |= sys::SystemManager::CreateService(std::make_shared(), sysmgr.get()); ` @@ -148,18 +148,18 @@ response: ### Service documentation -#### Hi level view +#### High level view ![Flowchart](./doc/how_machine_works.svg) #### System asynchronous calls synchronization -Calls from outside world are REST like. This means that: -- for one request -- there is one response +Calls from the outside world are REST-like. This means that: +- each call contains single request +- for each call event there is a single response -To provide synchronous response for asynchronous system calls we have special mechanism. +To provide a synchronous response for a asynchronous system call we have special mechanism. 1. Send: `DeveloperModeRequest` message with special `Event` Data 2. Process `DeveloperModeRequest` in system, fill in `Event` Data diff --git a/module-services/service-desktop/ServiceDesktop.cpp b/module-services/service-desktop/ServiceDesktop.cpp index d942026c4f64d615451193b0fa9062e0a3c09139..3cb785b1c60ffa339d4f1178dc4e5472f64a06a0 100644 --- a/module-services/service-desktop/ServiceDesktop.cpp +++ b/module-services/service-desktop/ServiceDesktop.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -58,7 +59,9 @@ namespace } } // namespace -ServiceDesktop::ServiceDesktop() : sys::Service(service::name::service_desktop, "", sdesktop::service_stack) +ServiceDesktop::ServiceDesktop() + : sys::Service(service::name::service_desktop, "", sdesktop::service_stack), + btMsgHandler(std::make_unique(this)) { LOG_INFO("[ServiceDesktop] Initializing"); @@ -237,6 +240,20 @@ sys::ReturnCodes ServiceDesktop::InitHandler() return sys::MessageNone{}; }); + connect(typeid(message::bluetooth::ResponseStatus), [&](sys::Message *msg) { + auto msgl = static_cast(msg); + return btMsgHandler->handle(msgl); + }); + + connect(typeid(message::bluetooth::ResponseBondedDevices), [&](sys::Message *msg) { + auto msgl = static_cast(msg); + return btMsgHandler->handle(msgl); + }); + + connect(typeid(message::bluetooth::ResponseVisibleDevices), [&](sys::Message *msg) { + auto msgl = static_cast(msg); + return btMsgHandler->handle(msgl); + }); settings->registerValueChange(updateos::settings::history, [this](const std::string &value) { updateOS->setInitialHistory(value); }); diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothEndpoint.cpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothEndpoint.cpp index c0b3357e78e1bb6bb6415d96327dd7545c879129..7ac9a3e8f0d6511bb9d3a1adf424fbc506f9843c 100644 --- a/module-services/service-desktop/endpoints/bluetooth/BluetoothEndpoint.cpp +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothEndpoint.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "BluetoothHelper.hpp" + #include "BluetoothEndpoint.hpp" #include @@ -13,11 +13,13 @@ auto BluetoothEndpoint::handle(Context &context) -> void helper->processGetRequest(context); break; case http::Method::post: + helper->processPostRequest(context); break; case http::Method::put: helper->processPutRequest(context); break; case http::Method::del: + helper->processDeleteRequest(context); break; } } diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.cpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b680fa3c0ef60c289879823640e3a419b9279a6 --- /dev/null +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "BluetoothEventMessages.hpp" + +namespace sdesktop::bluetooth +{ + using namespace parserFSM; + + BluetoothEvent::BluetoothEvent() + { + context.setResponseStatus(http::Code::OK); + context.setEndpoint(EndpointType::bluetooth); + } + +} // namespace sdesktop::bluetooth diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.hpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f346dab01762f965e3695bd99ddb532a5835358f --- /dev/null +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothEventMessages.hpp @@ -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 +#include + +namespace sdesktop::bluetooth +{ + class BluetoothEvent : public Event + { + public: + BluetoothEvent(); + }; + + class GetAvailableDevicesEvent : public BluetoothEvent + { + public: + GetAvailableDevicesEvent() = default; + }; + +} // namespace sdesktop::bluetooth diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp index ddbf21d914537c246dcc6e7918baa2216073b3b0..a2b82fb5ba6878aa51b551b92537bcf15c2d01cf 100644 --- a/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.cpp @@ -2,52 +2,119 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "BluetoothHelper.hpp" -#include +#include "BluetoothEventMessages.hpp" #include #include #include +#include + +#include +#include +#include +#include +#include + +namespace btConsts = parserFSM::json::bluetooth; auto parserFSM::BluetoothHelper::processPutRequest(parserFSM::Context &context) -> sys::ReturnCodes { auto body = context.getBody(); - if (auto command = body[json::bluetooth::command].string_value(); !command.empty()) { - BluetoothMessage::Request btRequest{}; - - if (command == json::bluetooth::scanOn) { - btRequest = BluetoothMessage::Request::Scan; + std::unique_ptr msg; + if (auto command = body[btConsts::command].string_value(); !command.empty()) { + if (command == btConsts::commands::scanOn) { + msg = std::make_unique(BluetoothMessage::Request::Scan); + } + else if (command == btConsts::commands::scanOff) { + msg = std::make_unique(BluetoothMessage::Request::StopScan); } - else if (command == json::bluetooth::scanOff) { - btRequest = BluetoothMessage::Request::StopScan; + else if (command == btConsts::commands::changeVisibility) { + msg = std::make_unique(BluetoothMessage::Request::Visible); } - ownerServicePtr->bus.sendUnicast(std::make_shared(btRequest), "ServiceBluetooth"); } - else if (auto state = body[json::bluetooth::state].string_value(); !state.empty()) { + else if (auto state = body[btConsts::state].object_items(); !state.empty()) { BluetoothStatus status{}; - if (state == json::bluetooth::btOn) { + const auto &power = state[btConsts::states::power]; + if (power == json::bluetooth::on) { status.state = BluetoothStatus::State::On; LOG_INFO("turning on BT from harness!"); } - else if (state == json::bluetooth::btOff) { + else if (power == json::bluetooth::off) { status.state = BluetoothStatus::State::Off; LOG_INFO("turning off BT from harness!"); } - ::message::bluetooth::SetStatus setStatus(status); + const auto &visibility = state[btConsts::states::visibility]; + status.visibility = visibility == json::bluetooth::on; - ownerServicePtr->bus.sendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)), - "ServiceBluetooth"); - MessageHandler::putToSendQueue(context.createSimpleResponse()); + ::message::bluetooth::SetStatus setStatus(status); + msg = std::make_unique<::message::bluetooth::SetStatus>(std::move(setStatus)); } + sendRequest(context, std::move(msg)); + MessageHandler::putToSendQueue(context.createSimpleResponse()); return sys::ReturnCodes::Unresolved; } auto parserFSM::BluetoothHelper::processGetRequest(parserFSM::Context &context) -> sys::ReturnCodes { auto body = context.getBody(); + std::unique_ptr msg; if (body[json::bluetooth::state].bool_value()) { + msg = std::make_unique<::message::bluetooth::RequestStatus>(); + } + else if (auto devices = body[json::bluetooth::devices].string_value(); !devices.empty()) { + if (devices == json::bluetooth::devicesValues::scanned) { + auto event = std::make_unique(); + msg = std::make_unique(std::move(event)); + } + else if (devices == json::bluetooth::devicesValues::bonded) { + msg = std::make_unique<::message::bluetooth::RequestBondedDevices>(); + } + } - auto event = std::make_unique(); - auto msg = std::make_shared(std::move(event)); - ownerServicePtr->bus.sendUnicast(std::move(msg), "ServiceBluetooth"); + sendRequest(context, std::move(msg)); + return sys::ReturnCodes::Unresolved; +} + +auto parserFSM::BluetoothHelper::processPostRequest(Context &context) -> sys::ReturnCodes +{ + auto body = context.getBody(); + std::unique_ptr msg; + if (auto address = body[json::bluetooth::connect].string_value(); !address.empty()) { + msg = std::make_unique<::message::bluetooth::Connect>(std::move(address)); } + else if (auto address = body[json::bluetooth::pair].string_value(); !address.empty()) { + LOG_INFO("Requesting pairing with %s form harness", address.c_str()); + msg = std::make_unique(std::move(address)); + } + + sendRequest(context, std::move(msg)); + MessageHandler::putToSendQueue(context.createSimpleResponse()); return sys::ReturnCodes::Unresolved; } + +auto parserFSM::BluetoothHelper::processDeleteRequest(Context &context) -> sys::ReturnCodes +{ + auto body = context.getBody(); + std::unique_ptr msg; + if (auto command = body[json::bluetooth::command].string_value(); !command.empty()) { + if (command == json::bluetooth::commands::disconnect) { + msg = std::make_unique<::message::bluetooth::Disconnect>(); + } + } + else if (auto address = body[json::bluetooth::unpair].string_value(); !address.empty()) { + LOG_INFO("Requesting pairing with %s form harness", address.c_str()); + msg = std::make_unique<::message::bluetooth::Unpair>(std::move(address)); + } + sendRequest(context, std::move(msg)); + MessageHandler::putToSendQueue(context.createSimpleResponse()); + return sys::ReturnCodes::Unresolved; +} +void parserFSM::BluetoothHelper::sendRequest(parserFSM::Context &context, std::unique_ptr msg) +{ + if (msg != nullptr) { + ownerServicePtr->bus.sendUnicast(std::move(msg), "ServiceBluetooth"); + } + else { + LOG_ERROR("No valid request created, returning simpleResponse ..."); + MessageHandler::putToSendQueue(context.createSimpleResponse()); + } +} diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.hpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.hpp index dfa08423ed4059c0f137be295e5c2c9610a5e513..27d9edb7202647fc18df98f2f252c21d918eeaa3 100644 --- a/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.hpp +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothHelper.hpp @@ -3,7 +3,6 @@ #pragma once #include - #include #include #include @@ -19,21 +18,49 @@ namespace parserFSM class BluetoothHelper { sys::Service *ownerServicePtr = nullptr; + void sendRequest(parserFSM::Context &context, std::unique_ptr msg); public: BluetoothHelper(sys::Service *_ownerServicePtr) : ownerServicePtr(_ownerServicePtr){}; auto processPutRequest(Context &context) -> sys::ReturnCodes; auto processGetRequest(Context &context) -> sys::ReturnCodes; + auto processPostRequest(Context &context) -> sys::ReturnCodes; + auto processDeleteRequest(Context &context) -> sys::ReturnCodes; }; namespace json::bluetooth { inline constexpr auto state = "state"; - inline constexpr auto btOn = "on"; - inline constexpr auto btOff = "off"; - inline constexpr auto scanOn = "scanOn"; - inline constexpr auto scanOff = "scanOff"; - inline constexpr auto scan = "scan"; + namespace states + { + inline constexpr auto power = "power"; + inline constexpr auto visibility = "visibility"; + } // namespace states + inline constexpr auto on = "on"; + inline constexpr auto off = "off"; + inline constexpr auto scan = "scan"; + inline constexpr auto command = "command"; + namespace commands + { + inline constexpr auto scanOn = "scanOn"; + inline constexpr auto scanOff = "scanOff"; + inline constexpr auto disconnect = "disconnect"; + inline constexpr auto changeVisibility = "changeVisibility"; + } // namespace commands + inline constexpr auto success = "success"; + inline constexpr auto failure = "failure"; + + inline constexpr auto pair = "pair"; + inline constexpr auto unpair = "unpair"; + inline constexpr auto connect = "connect"; + inline constexpr auto devices = "devices"; + namespace devicesValues + { + inline constexpr auto address = "address"; + inline constexpr auto name = "name"; + inline constexpr auto scanned = "scanned"; + inline constexpr auto bonded = "bonded"; + } // namespace devicesValues } // namespace json::bluetooth } // namespace parserFSM diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.cpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..800ee5fec3bd6f694209e1d48dae469be90b8380 --- /dev/null +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.cpp @@ -0,0 +1,82 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "BluetoothMessagesHandler.hpp" +#include "BluetoothEventMessages.hpp" +#include "BluetoothHelper.hpp" +#include +#include +#include + +namespace sdesktop::bluetooth +{ + class ResponseEvent : public sdesktop::bluetooth::BluetoothEvent + { + public: + ResponseEvent(json11::Json::object responseBody) + { + context.setResponseBody(std::move(responseBody)); + } + }; + +} // namespace sdesktop::bluetooth +using namespace sdesktop::bluetooth; +namespace btConstants = parserFSM::json::bluetooth; + +namespace +{ + json11::Json::object device2json(const Devicei &device) + { + LOG_DEBUG("Device: name=%s, address=%s", device.name.c_str(), bd_addr_to_str(device.address)); + return json11::Json::object{{btConstants::devicesValues::address, std::string(bd_addr_to_str(device.address))}, + {btConstants::devicesValues::name, device.name}}; + } + json11::Json::array devices2json(const std::vector &devices) + { + json11::Json::array serialized; + serialized.reserve(devices.size()); + for (const auto &device : devices) { + serialized.emplace_back(device2json(device)); + } + return serialized; + } +} // namespace + +BluetoothMessagesHandler::BluetoothMessagesHandler(sys::Service *ownerService) : ownerService(ownerService) +{} + +auto BluetoothMessagesHandler::handle(message::bluetooth::ResponseStatus *msg) -> std::shared_ptr +{ + auto status = msg->getStatus(); + json11::Json::object responseBody( + {{btConstants::state, + json11::Json::object{ + {btConstants::states::power, + status.state == BluetoothStatus::State::On ? btConstants::on : btConstants::off}, + {btConstants::states::visibility, status.visibility ? btConstants::on : btConstants::off}}}}); + send(std::make_unique(std::move(responseBody))); + return std::make_shared(); +} + +auto BluetoothMessagesHandler::handle(message::bluetooth::ResponseBondedDevices *msg) + -> std::shared_ptr +{ + LOG_DEBUG("Currently connected device address=%s", msg->getAddressOfConnectedDevice().c_str()); + json11::Json::object responseBody({{btConstants::devices, devices2json(msg->getDevices())}, + {btConstants::devicesValues::address, msg->getAddressOfConnectedDevice()}}); + send(std::make_unique(std::move(responseBody))); + return std::make_shared(); +} +auto BluetoothMessagesHandler::handle(message::bluetooth::ResponseVisibleDevices *msg) + -> std::shared_ptr +{ + json11::Json::object responseBody({{btConstants::devices, devices2json(msg->getDevices())}}); + send(std::make_unique(std::move(responseBody))); + return std::make_shared(); +} + +void BluetoothMessagesHandler::send(std::unique_ptr event) +{ + auto message = std::make_shared(std::move(event)); + ownerService->bus.sendUnicast(std::move(message), service::name::service_desktop); +} diff --git a/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.hpp b/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ba41a8e3961090407a896a4828e80b2e1bd4ece6 --- /dev/null +++ b/module-services/service-desktop/endpoints/bluetooth/BluetoothMessagesHandler.hpp @@ -0,0 +1,38 @@ +// 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 +#include +#include +#include + +namespace sys +{ + class Service; +} + +namespace sdesktop::developerMode +{ + class DeveloperModeRequest; +} + +namespace sdesktop::bluetooth +{ + class ResponseEvent; + class BluetoothMessagesHandler + { + sys::Service *ownerService = nullptr; + + void send(std::unique_ptr event); + + public: + BluetoothMessagesHandler(sys::Service *ownerService); + + [[nodiscard]] auto handle(message::bluetooth::ResponseStatus *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::ResponseBondedDevices *msg) + -> std::shared_ptr; + [[nodiscard]] auto handle(message::bluetooth::ResponseVisibleDevices *msg) + -> std::shared_ptr; + }; +} // namespace sdesktop::bluetooth diff --git a/module-services/service-desktop/service-desktop/DesktopMessages.hpp b/module-services/service-desktop/service-desktop/DesktopMessages.hpp index 09a983f35678d1e1c8d442f764a5fa3600220484..4434c51422bdd5ff8ec60598c07dfab6933fc445 100644 --- a/module-services/service-desktop/service-desktop/DesktopMessages.hpp +++ b/module-services/service-desktop/service-desktop/DesktopMessages.hpp @@ -4,7 +4,6 @@ #pragma once #include -#include #include #include @@ -198,26 +197,6 @@ namespace sdesktop }; } // namespace developerMode - namespace bluetooth - { - class BluetoothStatusRequestEvent : public Event - { - public: - BluetoothStatusRequestEvent() = default; - explicit BluetoothStatusRequestEvent(int state); - }; - class ScanStartedEvent : public Event - { - public: - ScanStartedEvent(); - }; - class ScanStoppedEvent : public Event - { - public: - ScanStoppedEvent(); - }; - - } // namespace bluetooth namespace transfer { diff --git a/module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp b/module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp index 6c31b419e7a5b1357d31f93d18a13eff11a2bd9c..fc17cf3dc82cf503081f285f72d113361e38112c 100644 --- a/module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp +++ b/module-services/service-desktop/service-desktop/DeveloperModeMessage.hpp @@ -14,6 +14,5 @@ namespace sdesktop::developerMode std::unique_ptr event; explicit DeveloperModeRequest(std::unique_ptr event); DeveloperModeRequest(); - ~DeveloperModeRequest() override = default; }; } // namespace sdesktop::developerMode diff --git a/module-services/service-desktop/service-desktop/ServiceDesktop.hpp b/module-services/service-desktop/service-desktop/ServiceDesktop.hpp index 23a26843b3150d1f35b99d34da9420ccfaa2de42..2a03b30809226db575fd8ec4577a99af49892769 100644 --- a/module-services/service-desktop/service-desktop/ServiceDesktop.hpp +++ b/module-services/service-desktop/service-desktop/ServiceDesktop.hpp @@ -35,6 +35,11 @@ namespace sdesktop }; // namespace sdesktop +namespace sdesktop::bluetooth +{ + class BluetoothMessagesHandler; +} + class ServiceDesktop : public sys::Service { public: @@ -83,6 +88,7 @@ class ServiceDesktop : public sys::Service std::unique_ptr usbSecurityModel; std::unique_ptr settings; std::unique_ptr transferTimer; + std::unique_ptr btMsgHandler; }; namespace sys diff --git a/source/MessageType.hpp b/source/MessageType.hpp index 494d9891a73859816b5c6ea98ba8c2e519ee92cf..a20e1cb0053e484419c025c40b89f003c2b589b6 100644 --- a/source/MessageType.hpp +++ b/source/MessageType.hpp @@ -215,6 +215,7 @@ enum class MessageType Restore, Factory, DeveloperModeRequest, + DeveloperModeMessageWrapper, PasscodeRequest, TransferTimer, diff --git a/test/pytest/service-bluetooth/bt_fixtures.py b/test/pytest/service-bluetooth/bt_fixtures.py new file mode 100644 index 0000000000000000000000000000000000000000..643ed3d23d97fbfb40f65cb62e5e33cea148cb7a --- /dev/null +++ b/test/pytest/service-bluetooth/bt_fixtures.py @@ -0,0 +1,65 @@ +# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +import pytest +from harness import log +from harness.interface.defs import key_codes, status +from harness.dom_parser_utils import * +import time +from bt_utils import * + +@pytest.fixture(scope='function') +def bt_main_window(harness): + current_window_content = get_window_content(harness, 1) + assert item_contains_recursively(current_window_content, 'WindowName', 'MainWindow' ) + harness.connection.send_key_code(key_codes["enter"]) + + log.info("Navigating to ApplicationSettings") + harness.open_application("settings") + if harness.connection.get_application_name() != "ApplicationSettingsNew": + time.sleep(5) + assert harness.connection.get_application_name() == "ApplicationSettingsNew" + + log.info("Opening Bluetooth") + harness.connection.send_key_code(key_codes["down"]) + harness.connection.send_key_code(key_codes["enter"]) + +@pytest.fixture(scope='function') +def bt_reset(harness): + current_window_content = get_window_content(harness, 1) + assert item_contains_recursively(current_window_content, 'WindowName', 'Bluetooth' ) + + parent_of_list_items = find_parent(current_window_content, 'ListItem') + if item_has_child_that_contains_recursively( parent_of_list_items, [('TextValue','Bluetooth'), ('TextValue', 'ON')] ) : + log.info("Bluetooth is ON, turing OFF...") + harness.connection.send_key_code(key_codes["enter"]) + + current_window_content = get_window_content(harness, 1) + parent_of_list_items = find_parent(current_window_content, 'ListItem') + assert item_has_child_that_contains_recursively( parent_of_list_items, [('TextValue','Bluetooth'), ('TextValue', 'OFF')] ) + + log.info("Turing Bluetooth ON...") + harness.connection.send_key_code(key_codes["enter"]) + +@pytest.fixture(scope='function') +def bt_all_devices(harness): + log.info("Navigating to AllDevices window...") + time.sleep(1) + harness.connection.send_key_code(key_codes["down"]) + harness.connection.send_key_code(key_codes["enter"]) + + current_window_content = get_window_content(harness, 1) + assert item_contains_recursively(current_window_content, 'WindowName', 'AllDevices') + +@pytest.fixture(scope='function') +def bt_state_on(harness): + status = bt_get_state(harness) + if status["power"] == "off": + bt_set_status(harness, "on") + + +@pytest.fixture(scope='function') +def bt_state_off(harness): + status = bt_get_state(harness) + if status["power"] == "on": + bt_set_status(harness, "off") diff --git a/test/pytest/service-bluetooth/bt_utils.py b/test/pytest/service-bluetooth/bt_utils.py index b6fff20a21c034a66535d949d7834c9e08966ddd..97ed59dcc4be0f69158b988389e83578282e26d7 100644 --- a/test/pytest/service-bluetooth/bt_utils.py +++ b/test/pytest/service-bluetooth/bt_utils.py @@ -1,48 +1,95 @@ -import pytest +# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +from harness.interface.defs import status from harness import log -from harness.interface.defs import key_codes -from harness.dom_parser_utils import * import time -@pytest.fixture(scope='function') -def bt_main_window(harness): - current_window_content = get_window_content(harness, 1) - assert item_contains_recursively(current_window_content, 'WindowName', 'MainWindow' ) - harness.connection.send_key_code(key_codes["enter"]) - - log.info("Navigating to ApplicationSettings") - harness.open_application("settings") - if harness.connection.get_application_name() != "ApplicationSettingsNew": - time.sleep(5) - assert harness.connection.get_application_name() == "ApplicationSettingsNew" - - log.info("Opening Bluetooth") - harness.connection.send_key_code(key_codes["down"]) - harness.connection.send_key_code(key_codes["enter"]) - -@pytest.fixture(scope='function') -def bt_reset(harness): - current_window_content = get_window_content(harness, 1) - assert item_contains_recursively(current_window_content, 'WindowName', 'Bluetooth' ) - - parent_of_list_items = find_parent(current_window_content, 'ListItem') - if item_has_child_that_contains_recursively( parent_of_list_items, [('TextValue','Bluetooth'), ('TextValue', 'ON')] ) : - log.info("Bluetooth is ON, turing OFF...") - harness.connection.send_key_code(key_codes["enter"]) - - current_window_content = get_window_content(harness, 1) - parent_of_list_items = find_parent(current_window_content, 'ListItem') - assert item_has_child_that_contains_recursively( parent_of_list_items, [('TextValue','Bluetooth'), ('TextValue', 'OFF')] ) - - log.info("Turing Bluetooth ON...") - harness.connection.send_key_code(key_codes["enter"]) - -@pytest.fixture(scope='function') -def bt_all_devices(harness): - log.info("Navigating to AllDevices window...") +def bt_get_state(harness): time.sleep(1) - harness.connection.send_key_code(key_codes["down"]) - harness.connection.send_key_code(key_codes["enter"]) + body = {"state": True} + ret = harness.endpoint_request("bluetooth", "get", body) + assert ret["status"] == status["OK"] + return ret["body"]["state"] + +def bt_set_status(harness, power, visibility = "off"): + log.info("Turning Bluetooth {} with visibility {}...".format(power, visibility)) + body = {"state": {"power" : power , "visibility" : visibility }} + ret = harness.endpoint_request("bluetooth", "put", body) + assert ret["status"] == status["OK"] + +def bt_command(harness, command, http_method = "put"): + log.info("Sending command: {} with http_method={}".format(command, http_method)) + body = {"command": command} + ret = harness.endpoint_request("bluetooth", http_method, body) + assert ret["status"] == status["OK"] + +def bt_pair_command(harness, pair_command, address, http_method): + log.info("Requesting {}ing with address={}...".format(pair_command, address)) + body = {pair_command: address} + ret = harness.endpoint_request("bluetooth", http_method, body) + assert ret["status"] == status["OK"] + +def bt_get_device_by_name(devices, name) -> dict : + for device in devices: + if device["name"] == name : + return device + return {} + +def bt_find_device(harness, device_origin, device_name, max_attempts = 7): + log.info("Getting {} devices".format(device_origin)) + body = {"devices": device_origin} + + for i in range(max_attempts): + ret = harness.endpoint_request("bluetooth", "get", body) + device = bt_get_device_by_name(ret["body"]["devices"], device_name) + if device: + log.info("Found {}, address={}".format(device_name, device.get('address'))) + return device + if i != max_attempts - 1: + log.info("Device {} not found, retrying...".format(device_name)) + time.sleep(2) + return {} + +def bt_is_device_forgotten(harness, device_name, max_attempts = 7): + log.info("Checking if pair forgetting succeeded...") + body = {"devices": "bonded"} + + for i in range(max_attempts): + ret = harness.endpoint_request("bluetooth", "get", body) + device = bt_get_device_by_name(ret["body"]["devices"], device_name) + if not device: + return True + if i != max_attempts - 1: + log.info("Device {} still paired, retrying...".format(device_name)) + time.sleep(2) + return False + +def bt_get_connected_address(harness, max_attempts = 10): + log.info("Getting address of connected device") + body = {"devices": "bonded"} + + for i in range(max_attempts): + ret = harness.endpoint_request("bluetooth", "get", body) + address = ret["body"]["address"] + if len(address) > 0: + log.info("Device connected={}".format(address)) + return address + if i != max_attempts - 1: + log.info("No device connected, retrying...") + time.sleep(2) + return "" + +def bt_is_device_disconnected(harness, max_attempts = 7): + log.info("Checking if disconnecting succeeded...") + body = {"devices": "bonded"} - current_window_content = get_window_content(harness, 1) - assert item_contains_recursively(current_window_content, 'WindowName', 'AllDevices') + for i in range(max_attempts): + ret = harness.endpoint_request("bluetooth", "get", body) + address = ret["body"]["address"] + if len(address) == 0: + return True + if i != max_attempts - 1: + log.info("Device {} connected, retrying...".format(address)) + time.sleep(2) + return False diff --git a/test/pytest/service-bluetooth/test_basic_control_dev_perspective.py b/test/pytest/service-bluetooth/test_basic_control_dev_perspective.py new file mode 100644 index 0000000000000000000000000000000000000000..6f80a7d881332efcd943ededd4de3805d82a1167 --- /dev/null +++ b/test/pytest/service-bluetooth/test_basic_control_dev_perspective.py @@ -0,0 +1,55 @@ +# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +import time +import pytest +from harness import log +from harness.dom_parser_utils import * +from bt_fixtures import * +from bt_utils import * + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("bt_state_off") +@pytest.mark.usefixtures("usb_unlocked") +def test_bt_turning_on_off(harness): + state = bt_get_state(harness) + assert state["power"] == "off" + log.info("BT turned off.") + + bt_set_status(harness, "on") + + state = bt_get_state(harness) + assert state["power"] == "on" + log.info("BT turned on successfully") + + bt_set_status(harness, "off") + + state = bt_get_state(harness) + assert state["power"] == "off" + log.info("BT turned off successfully") + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("bt_state_on") +@pytest.mark.usefixtures("usb_unlocked") +def test_bt_visibility_on_off(harness): + state = bt_get_state(harness) + assert state["power"] == "on" + + visibility = state["visibility"] + log.info("Device visibility is {}".format(visibility)) + time.sleep(1) + bt_command(harness, "changeVisibility") + + time.sleep(1) + state = bt_get_state(harness) + assert (visibility != state["visibility"]) + visibility = state["visibility"] + log.info("Device visibility is {}".format(visibility)) + + time.sleep(1) + bt_command(harness, "changeVisibility") + + time.sleep(1) + state = bt_get_state(harness) + assert (visibility != state["visibility"]) + diff --git a/test/pytest/service-bluetooth/test_pairing_dev_perspective.py b/test/pytest/service-bluetooth/test_pairing_dev_perspective.py new file mode 100644 index 0000000000000000000000000000000000000000..a2730e4bc6d5371f6b076fb513758be2948cd1f8 --- /dev/null +++ b/test/pytest/service-bluetooth/test_pairing_dev_perspective.py @@ -0,0 +1,80 @@ +# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +import time +import pytest +from harness import log +from bt_fixtures import * +from bt_utils import * + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("bt_state_on") +@pytest.mark.usefixtures("usb_unlocked") +@pytest.mark.skipif("not config.getvalue('--bt_device')", reason='--bt_device was not specified') +def test_bt_pairing_dev(harness, bt_device): + time.sleep(1) + bt_command(harness, "scanOn") + + time.sleep(1) + device = bt_find_device(harness, "scanned", bt_device) + assert device + address = device.get('address') + + bt_pair_command(harness, "pair", address, "post") + time.sleep(1) + bt_command(harness, "scanOff") + + time.sleep(1) + device = bt_find_device(harness, "bonded", bt_device) + assert device + assert device.get('address') == address + + bt_set_status(harness, "off") + time.sleep(1) + bt_set_status(harness, "on") + time.sleep(1) + + time.sleep(1) + log.info("Checking if {} is still paired after turning BT off-on...".format(bt_device)) + device = bt_find_device(harness, "bonded", bt_device) + assert device + assert device.get('address') == address + + bt_pair_command(harness, "unpair", address, "del") + assert bt_is_device_forgotten(harness, bt_device) + log.info("Device {} successfully unpaired.".format(address)) + + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("bt_state_on") +@pytest.mark.usefixtures("usb_unlocked") +@pytest.mark.skipif("not config.getvalue('--bt_device')", reason='--bt_device was not specified') +def test_bt_connection_dev(harness, bt_device): + time.sleep(1) + bt_command(harness, "scanOn") + + time.sleep(1) + device = bt_find_device(harness, "scanned", bt_device) + assert device + address = device.get('address') + + bt_pair_command(harness, "pair", address, "post") + time.sleep(1) + bt_command(harness, "scanOff") + + time.sleep(1) + device = bt_find_device(harness, "bonded", bt_device) + assert device + assert device.get('address') == address + + bt_pair_command(harness, "connect", address, "post") + time.sleep(1) + connected_address = bt_get_connected_address(harness) + assert connected_address == address + + bt_command(harness, "disconnect", "del") + assert bt_is_device_disconnected(harness) + + bt_pair_command(harness, "unpair", address, "del") + assert bt_is_device_forgotten(harness, bt_device) + log.info("Device {} successfully unpaired.".format(address)) diff --git a/test/pytest/service-bluetooth/test_pairing.py b/test/pytest/service-bluetooth/test_pairing_hmi_perspective.py similarity index 91% rename from test/pytest/service-bluetooth/test_pairing.py rename to test/pytest/service-bluetooth/test_pairing_hmi_perspective.py index d722f39c27c01039f8115e2cb1e31f7d37605928..698282c465446336db3bddcf6e550097754582e0 100644 --- a/test/pytest/service-bluetooth/test_pairing.py +++ b/test/pytest/service-bluetooth/test_pairing_hmi_perspective.py @@ -1,9 +1,12 @@ +# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + import time import pytest from harness import log from harness.dom_parser_utils import * from harness.interface.defs import key_codes -from bt_utils import * +from bt_fixtures import * @pytest.mark.rt1051 @pytest.mark.usefixtures("bt_all_devices") @@ -12,7 +15,7 @@ from bt_utils import * @pytest.mark.usefixtures("phone_in_desktop") @pytest.mark.usefixtures("phone_unlocked") @pytest.mark.skipif("not config.getvalue('--bt_device')", reason='--bt_device was not specified') -def test_bt_pairing(harness, bt_device): +def test_bt_pairing_hmi(harness, bt_device): if not bt_device: return bt_device_name = bt_device diff --git a/test/pytest/service-desktop/test_bluetooth.py b/test/pytest/service-desktop/test_bluetooth.py deleted file mode 100644 index 3a3eb4929d4512d2b329826654c8239b793a6db3..0000000000000000000000000000000000000000 --- a/test/pytest/service-desktop/test_bluetooth.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -import pytest -from harness.interface.defs import status -from harness import log -import time - - -@pytest.mark.rt1051 -@pytest.mark.service_desktop_test -@pytest.mark.usefixtures("usb_unlocked") -def test_bluetooth_on_off(harness): - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - print(ret) - assert ret["status"] == status["OK"] - if ret["body"]["state"] == 0: - log.info("BT turned off, turning on...") - body = {"state": "on"} - ret = harness.endpoint_request("bluetooth", "put", body) - - time.sleep(5) - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - - assert ret["status"] == status["OK"] - - assert ret["body"]["state"] == 1 - - log.info("BT turning off...") - body = {"state": "off"} - ret = harness.endpoint_request("bluetooth", "put", body) - - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - assert ret["body"]["state"] == 0 - - -@pytest.mark.rt1051 -@pytest.mark.service_desktop_test -@pytest.mark.usefixtures("usb_unlocked") -def test_bluetooth_scan(harness): - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - print(ret) - assert ret["status"] == status["OK"] - if ret["body"]["state"] == 0: - log.info("BT turned off, turning on...") - body = {"state": "on"} - ret = harness.endpoint_request("bluetooth", "put", body) - - time.sleep(5) - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - - assert ret["status"] == status["OK"] - - assert ret["body"]["state"] == 1 - - body = {"command": "scanOn"} - ret = harness.endpoint_request("bluetooth", "put", body) - assert ret["body"]["scan"] == "on" - - time.sleep(1) - body = {"command": "scanOff"} - ret = harness.endpoint_request("bluetooth", "put", body) - assert ret["body"]["scan"] == "off" - - body = {"state": "off"} - ret = harness.endpoint_request("bluetooth", "put", body) - - body = {"state": True} - ret = harness.endpoint_request("bluetooth", "get", body) - assert ret["body"]["state"] == 0