~aleteoryx/muditaos

2be81bdf0a4ef0698a39c3298c45b594711a370e — Bartosz Cichocki 3 years ago 8f64c10
[MOS-365] Add BT battery handling

Added handling of the battery state in HFP profile
M .github/workflows/github-actions-pr-checklist-check.yml => .github/workflows/github-actions-pr-checklist-check.yml +1 -1
@@ 1,7 1,7 @@
name: 'PR Tasks Completed Check'
on:
  pull_request:
    types: [opened, edited]
    types: [opened, edited, synchronize, ready_for_review, unlocked]

jobs:
  task-check:

M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +2 -0
@@ 82,6 82,8 @@ namespace bluetooth
            return profileManager->setSignalStrengthData(command.getData());
        case Command::OperatorNameData:
            return profileManager->setOperatorNameData(command.getData());
        case Command::BatteryLevelData:
            return profileManager->setBatteryLevelData(command.getData());
        case Command::StartStream:
            profileManager->start();
            return Error::Success;

A module-bluetooth/Bluetooth/command/BatteryLevel.hpp => module-bluetooth/Bluetooth/command/BatteryLevel.hpp +51 -0
@@ 0,0 1,51 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
namespace bluetooth
{

    class BatteryLevel
    {
        static constexpr auto batteryLowValue = 0;
        static constexpr auto batteryMaxValue = 100;

      public:
        explicit BatteryLevel(unsigned int level) : level(level){};
        BatteryLevel() = default;
        auto getBatteryLevel() const -> unsigned int
        {
            return std::clamp<unsigned int>(level, batteryLowValue, batteryMaxValue);
        }
        auto getBatteryLevelBars() const -> unsigned int
        {
            constexpr auto level1Threshold = 15;
            constexpr auto level2Threshold = 35;
            constexpr auto level3Threshold = 55;
            constexpr auto level4Threshold = 75;
            constexpr auto level5Threshold = 95;

            if (level < level1Threshold) {
                return 0;
            }
            else if (level < level2Threshold) {
                return 1;
            }
            else if (level < level3Threshold) {
                return 2;
            }
            else if (level < level4Threshold) {
                return 3;
            }
            else if (level < level5Threshold) {
                return 4;
            }
            else {
                return 5;
            }
        }

      private:
        unsigned int level = 0;
    };
} // namespace bluetooth

A module-bluetooth/Bluetooth/command/BatteryLevelData.cpp => module-bluetooth/Bluetooth/command/BatteryLevelData.cpp +14 -0
@@ 0,0 1,14 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BatteryLevelData.hpp"

namespace bluetooth
{
    BatteryLevelData::BatteryLevelData(const BatteryLevel &level) : level(level)
    {}
    auto BatteryLevelData::getData() -> DataVariant
    {
        return level;
    }
} // namespace bluetooth

A module-bluetooth/Bluetooth/command/BatteryLevelData.hpp => module-bluetooth/Bluetooth/command/BatteryLevelData.hpp +20 -0
@@ 0,0 1,20 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "CommandData.hpp"

namespace bluetooth
{

    class BatteryLevelData : public CommandData
    {
      public:
        explicit BatteryLevelData(const BatteryLevel &level);
        auto getData() -> DataVariant override;

      private:
        BatteryLevel level;
    };

} // namespace bluetooth

M module-bluetooth/Bluetooth/command/Command.hpp => module-bluetooth/Bluetooth/command/Command.hpp +1 -0
@@ 33,6 33,7 @@ namespace bluetooth
            IncomingCallNumber,
            SignalStrengthData,
            OperatorNameData,
            BatteryLevelData,
            None,
        };


M module-bluetooth/Bluetooth/command/CommandData.hpp => module-bluetooth/Bluetooth/command/CommandData.hpp +3 -1
@@ 8,10 8,12 @@
#include "Device.hpp"
#include "EventStore.hpp"
#include "OperatorName.hpp"
#include "BatteryLevel.hpp"

namespace bluetooth
{
    using DataVariant = std::variant<OperatorName, Store::SignalStrength, Devicei, utils::PhoneNumber::View>;
    using DataVariant =
        std::variant<BatteryLevel, OperatorName, Store::SignalStrength, Devicei, utils::PhoneNumber::View>;

    class CommandData
    {

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +4 -0
@@ 133,6 133,10 @@ namespace bluetooth
        LOG_INFO("Setting operator name in A2DP - ignoring");
        return Error::Success;
    }
    auto A2DP::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code
    {
        return Error::Success;
    }

    const sys::Service *A2DP::A2DPImpl::ownerService;
    QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +2 -0
@@ 44,6 44,8 @@ namespace bluetooth
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;
        /// @return Success - ignoring in A2DP
        [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override;
        /// @return Success - ignoring in A2DP
        [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override;

        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;


M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +12 -1
@@ 114,6 114,11 @@ namespace bluetooth
        LOG_DEBUG("Setting operator name: %s", name.data());
        return pimpl->setOperatorName(name);
    }
    auto HFP::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code
    {
        LOG_DEBUG("Setting battery level: %d", level.getBatteryLevel());
        return pimpl->setBatteryLevel(level);
    }

    HFP::~HFP() = default;



@@ 136,7 141,7 @@ namespace bluetooth
        {1, "service", 0, 1, 1, 0, 0, 0},
        {2, "call", 0, 1, 0, 1, 1, 0},
        {3, "callsetup", 0, 3, 0, 1, 1, 0},
        {4, "battchg", 0, 5, 3, 0, 0, 0},
        {4, "battchg", 0, 5, 3, 0, 1, 0},
        {5, "signal", 0, 4, 5, 0, 1, 0},
        {6, "roam", 0, 1, 0, 0, 1, 0},
        {7, "callheld", 0, 2, 0, 1, 1, 0}};


@@ 511,5 516,11 @@ namespace bluetooth
        LOG_DEBUG("Operator set name result: %d", result);
        return Error::Success;
    }
    auto HFP::HFPImpl::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code
    {
        auto result = hfp_ag_set_battery_level(level.getBatteryLevelBars());
        LOG_DEBUG("Battery level (bars): %d, set result: %d", level.getBatteryLevelBars(), result);
        return Error::Success;
    }

} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp +1 -0
@@ 50,6 50,7 @@ namespace bluetooth
        /// @return Success
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;
        [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override;
        [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override;

        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;


M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +1 -0
@@ 32,6 32,7 @@ namespace bluetooth
        [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code;
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code;
        [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code;
        [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code;

      private:
        static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +4 -0
@@ 389,6 389,10 @@ namespace bluetooth
    {
        return Error::Success;
    }
    auto HSP::setBatteryLevel(const BatteryLevel &name) const noexcept -> Error::Code
    {
        return Error::Success;
    }

    void HSP::HSPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
    {

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +2 -0
@@ 48,6 48,8 @@ namespace bluetooth
        [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;
        /// @return Success - ignoring in HSP
        [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override;
        /// @return Success - ignoring in HSP
        [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override;

        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;


M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +4 -0
@@ 9,6 9,7 @@
#include <service-bluetooth/ServiceBluetoothCommon.hpp>

#include <memory>
#include <command/BatteryLevel.hpp>

namespace bluetooth
{


@@ 45,6 46,9 @@ namespace bluetooth
        /// Sets the operator name in HFP profile
        /// @return Error code that determines, whether operation was successful or not
        [[nodiscard]] virtual auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code = 0;
        /// Sets the operator name in HFP profile
        /// @return Error code that determines, whether operation was successful or not
        [[nodiscard]] virtual auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code = 0;

      protected:
        static void initSdp();

M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +9 -0
@@ 146,5 146,14 @@ namespace bluetooth
        LOG_ERROR("No profile, returning!");
        return Error::NotReady;
    }
    auto ProfileManager::setBatteryLevelData(const DataVariant &data) -> Error::Code
    {
        auto batteryLevel = std::get<BatteryLevel>(data);
        if (currentProfilePtr) {
            return currentProfilePtr->setBatteryLevel(batteryLevel);
        }
        LOG_ERROR("No profile, returning!");
        return Error::NotReady;
    }

} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +1 -0
@@ 48,6 48,7 @@ namespace bluetooth
        auto setIncomingCallNumber(const DataVariant &data) -> Error::Code;
        auto setSignalStrengthData(const DataVariant &data) -> Error::Code;
        auto setOperatorNameData(const DataVariant &data) -> Error::Code;
        auto setBatteryLevelData(const DataVariant &data) -> Error::Code;

        auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code;


M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +1 -0
@@ 36,6 36,7 @@ set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/command/PhoneNumberData.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/command/SignalStrengthData.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/command/OperatorNameData.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/command/BatteryLevelData.cpp

        )


M module-bluetooth/tests/tests-command.cpp => module-bluetooth/tests/tests-command.cpp +36 -0
@@ 6,6 6,7 @@
#include <command/Command.hpp>
#include <command/DeviceData.hpp>
#include <command/PhoneNumberData.hpp>
#include <command/BatteryLevelData.hpp>

using namespace bluetooth;



@@ 31,3 32,38 @@ TEST_CASE("Command data handling test")
    REQUIRE(number == std::get<utils::PhoneNumber::View>(receivedCommand.getData()));
    REQUIRE(receivedCommand.getType() == bluetooth::Command::PowerOn);
}

TEST_CASE("BatteryLevel test")
{

    SECTION("1/5")
    {
        auto data = BatteryLevel(10);
        REQUIRE(data.getBatteryLevel() == 10);
        REQUIRE(data.getBatteryLevelBars() == 0);
    }
    SECTION("2/5")
    {
        auto data = BatteryLevel(20);
        REQUIRE(data.getBatteryLevel() == 20);
        REQUIRE(data.getBatteryLevelBars() == 1);
    }
    SECTION("3/5")
    {
        auto data = BatteryLevel(100);
        REQUIRE(data.getBatteryLevel() == 100);
        REQUIRE(data.getBatteryLevelBars() == 5);
    }
    SECTION("4/5")
    {
        auto data = BatteryLevel(500);
        REQUIRE(data.getBatteryLevel() == 100);
        REQUIRE(data.getBatteryLevelBars() == 5);
    }
    SECTION("5/5")
    {
        auto data = BatteryLevel(0);
        REQUIRE(data.getBatteryLevel() == 0);
        REQUIRE(data.getBatteryLevelBars() == 0);
    }
}

M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +12 -0
@@ 45,6 45,8 @@
#include <command/DeviceData.hpp>
#include <command/SignalStrengthData.hpp>
#include <command/OperatorNameData.hpp>
#include <command/BatteryLevelData.hpp>
#include <service-evtmgr/BatteryMessages.hpp>

namespace
{


@@ 118,6 120,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
    connectHandler<CellularCallActiveNotification>();
    connectHandler<CellularSignalStrengthUpdateNotification>();
    connectHandler<CellularCurrentOperatorNameNotification>();
    connectHandler<sevm::BatteryStatusChangeMessage>();

    settingsHolder->onStateChange = [this]() {
        auto initialState = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State));


@@ 556,6 559,15 @@ auto ServiceBluetooth::handle(message::bluetooth::RequestStatusIndicatorData *ms

    // just to execute proper handle method and sending it back to worker
    bus.sendUnicast(std::make_shared<CellularSignalStrengthUpdateNotification>(), service::name::bluetooth);
    bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), service::name::bluetooth);

    return sys::MessageNone{};
}
auto ServiceBluetooth::handle(sevm::BatteryStatusChangeMessage *msg) -> std::shared_ptr<sys::Message>
{
    auto batteryLevel = Store::Battery::get().level;
    LOG_INFO("Bluetooth: Battery level %d", batteryLevel);
    auto commandData = std::make_unique<bluetooth::BatteryLevelData>(bluetooth::BatteryLevel(batteryLevel));
    sendWorkerCommand(bluetooth::Command::Type::BatteryLevelData, std::move(commandData));
    return sys::MessageNone{};
}

M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +6 -0
@@ 58,6 58,11 @@ namespace message::bluetooth
    class RequestStatusIndicatorData;
} // namespace message::bluetooth

namespace sevm
{
    class BatteryStatusChangeMessage;
}

class CellularCallerIdMessage;
class CellularCallActiveNotification;
class CellularSignalStrengthUpdateNotification;


@@ 126,6 131,7 @@ class ServiceBluetooth : public sys::Service
    [[nodiscard]] auto handle(CellularCallActiveNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularSignalStrengthUpdateNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(CellularCurrentOperatorNameNotification *msg) -> std::shared_ptr<sys::Message>;
    [[nodiscard]] auto handle(sevm::BatteryStatusChangeMessage *msg) -> std::shared_ptr<sys::Message>;
};

namespace sys

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +1 -0
@@ 156,6 156,7 @@ sys::ReturnCodes EventManagerCommon::InitHandler()
                bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), targetApplication);
            }
            bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), service::name::service_desktop);
            bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), service::name::bluetooth);
        }
        return sys::msgHandled();
    });