Skip to content

Commit

Permalink
🔀 Merge branch 'yann/feature/battery/add-on-data-update' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
ladislas committed Mar 10, 2022
2 parents eb0f06a + 867d102 commit e5b8e96
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 14 deletions.
5 changes: 5 additions & 0 deletions drivers/CoreEventQueue/include/CoreEventQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class CoreEventQueue : public interface::EventQueue

void call(auto f, auto... params) { _event_queue.call(f, params...); }

void call_every(std::chrono::duration<int, std::milli> duration, auto f, auto... params)
{
_event_queue.call_every(duration, f, params...);
}

// ? Overload needed for mbed::BLE compatibility
void callMbedCallback(mbed::Callback<void()> const &f);

Expand Down
28 changes: 28 additions & 0 deletions libs/BatteryKit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Leka - LekaOS
# Copyright 2022 APF France handicap
# SPDX-License-Identifier: Apache-2.0

add_library(BatteryKit STATIC)

target_include_directories(BatteryKit
PUBLIC
include
)

target_sources(BatteryKit
PRIVATE
source/BatteryKit.cpp
)

target_link_libraries(BatteryKit
mbed-os
CoreEventQueue
)

if (${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")

leka_unit_tests_sources(
tests/BatteryKit_test.cpp
)

endif()
36 changes: 36 additions & 0 deletions libs/BatteryKit/include/BatteryKit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "CoreEventQueue.h"
#include "interface/drivers/Battery.h"

namespace leka {

class BatteryKit
{
public:
explicit BatteryKit(interface::Battery &battery) : _battery(battery) {};

void start();

auto level() -> uint8_t;
auto isCharging() -> bool;
void onChargeDidStart(mbed::Callback<void()> const &callback);
void onChargeDidStop(mbed::Callback<void()> const &callback);

void onDataUpdated(std::function<void(uint8_t)> const &callback);
void onLowBattery(std::function<void()> const &callback);

private:
interface::Battery &_battery;

CoreEventQueue _event_queue {};

std::function<void(uint8_t)> _on_data_updated {};
std::function<void()> _on_low_battery {};
};

} // namespace leka
56 changes: 56 additions & 0 deletions libs/BatteryKit/source/BatteryKit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "BatteryKit.h"

using namespace leka;
using namespace std::chrono_literals;

void BatteryKit::start()
{
auto on_tick = [this] {
if (_on_low_battery && level() == 0) {
_on_low_battery();
}

if (_on_data_updated) {
_on_data_updated(level());
}
};

on_tick(); // TODO (@john_doe): only for unit tests. Due to event_queue that does not make the call
_event_queue.call_every(1s, on_tick);

_event_queue.dispatch_forever();
}

auto BatteryKit::level() -> uint8_t
{
return _battery.level();
}

auto BatteryKit::isCharging() -> bool
{
return _battery.isCharging();
}

void BatteryKit::onChargeDidStart(mbed::Callback<void()> const &callback)
{
_battery.onChargeDidStart(callback);
}

void BatteryKit::onChargeDidStop(mbed::Callback<void()> const &callback)
{
_battery.onChargeDidStop(callback);
}

void BatteryKit::onDataUpdated(std::function<void(uint8_t)> const &callback)
{
_on_data_updated = callback;
}

void BatteryKit::onLowBattery(std::function<void()> const &callback)
{
_on_low_battery = callback;
}
110 changes: 110 additions & 0 deletions libs/BatteryKit/tests/BatteryKit_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "BatteryKit.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mocks/leka/Battery.h"

using namespace leka;

using ::testing::MockFunction;
using ::testing::Return;

class BatteryKitTest : public ::testing::Test
{
protected:
BatteryKitTest() : batterykit(mock_battery) {}

// void SetUp() override {}
// void TearDown() override {}

mock::Battery mock_battery;
BatteryKit batterykit;
};

TEST_F(BatteryKitTest, instantiation)
{
EXPECT_NE(&batterykit, nullptr);
}

TEST_F(BatteryKitTest, level)
{
auto expected_value = 0x2A;

EXPECT_CALL(mock_battery, level).WillOnce(Return(expected_value));

auto actual_value = batterykit.level();

EXPECT_EQ(actual_value, expected_value);
}

TEST_F(BatteryKitTest, isCharging)
{
auto expected_value = true;

EXPECT_CALL(mock_battery, isCharging).WillOnce(Return(expected_value));

auto actual_value = batterykit.isCharging();

EXPECT_EQ(actual_value, expected_value);
}

TEST_F(BatteryKitTest, onChargeDidStart)
{
mbed::Callback<void()> callback_dummy([] {});

EXPECT_CALL(mock_battery, onChargeDidStart(callback_dummy)).Times(1);

batterykit.onChargeDidStart(callback_dummy);
}

TEST_F(BatteryKitTest, onChargeDidStop)
{
mbed::Callback<void()> callback_dummy([] {});

EXPECT_CALL(mock_battery, onChargeDidStop(callback_dummy)).Times(1);

batterykit.onChargeDidStop(callback_dummy);
}

TEST_F(BatteryKitTest, onDataUpdated)
{
auto battery_level = 0x2A;
MockFunction<void(uint8_t)> mock_on_data_updated_callback;

batterykit.onDataUpdated(mock_on_data_updated_callback.AsStdFunction());

EXPECT_CALL(mock_battery, level).WillRepeatedly(Return(battery_level));
EXPECT_CALL(mock_on_data_updated_callback, Call(battery_level)).Times(1);

batterykit.start();
}

TEST_F(BatteryKitTest, onLowBattery)
{
auto battery_level = 0x2A;
MockFunction<void()> mock_on_low_battery_callback;

batterykit.onLowBattery(mock_on_low_battery_callback.AsStdFunction());

EXPECT_CALL(mock_battery, level).WillRepeatedly(Return(battery_level));
EXPECT_CALL(mock_on_low_battery_callback, Call).Times(0);

batterykit.start();
}

TEST_F(BatteryKitTest, onLowBatteryLevelAtZero)
{
auto battery_level = 0x00;
MockFunction<void()> mock_on_low_battery_callback;

batterykit.onLowBattery(mock_on_low_battery_callback.AsStdFunction());

EXPECT_CALL(mock_battery, level).WillRepeatedly(Return(battery_level));
EXPECT_CALL(mock_on_low_battery_callback, Call).Times(1);

batterykit.start();
}
1 change: 1 addition & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

add_subdirectory(${LIBS_DIR}/BLEKit)
add_subdirectory(${LIBS_DIR}/ColorKit)
add_subdirectory(${LIBS_DIR}/BatteryKit)
add_subdirectory(${LIBS_DIR}/ContainerKit)
add_subdirectory(${LIBS_DIR}/FileSystemKit)
add_subdirectory(${LIBS_DIR}/FirmwareKit)
Expand Down
4 changes: 2 additions & 2 deletions spikes/lk_sensors_battery/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ target_sources(spike_lk_sensors_battery
)

target_link_libraries(spike_lk_sensors_battery
CoreTicker
CoreBattery
CorePwm
CoreMotor
BatteryKit
)

target_link_custom_leka_targets(spike_lk_sensors_battery)
35 changes: 23 additions & 12 deletions spikes/lk_sensors_battery/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,52 @@
// Copyright 2021-2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "drivers/BufferedSerial.h"
#include "drivers/DigitalOut.h"
#include "drivers/InterruptIn.h"
#include "rtos/ThisThread.h"

#include "BatteryKit.h"
#include "CoreBattery.h"
#include "CoreTicker.h"
#include "LogKit.h"

using namespace leka;
using namespace std::chrono;

auto charge_input = mbed::InterruptIn {PinName::BATTERY_CHARGE_STATUS};
auto corebattery = CoreBattery {PinName::BATTERY_VOLTAGE, charge_input};
auto batterykit = BatteryKit {corebattery};
auto mainboard_led = mbed::DigitalOut {LED1};

void logBatteryNewLevel(uint8_t battery_new_level)
{
if (corebattery.isCharging()) {
log_info("Battery at %d%% and in charge.", battery_new_level);
} else {
log_info("Battery at %d%%.", battery_new_level);
}
}

auto main() -> int
{
logger::init();

auto charge_input = mbed::InterruptIn {PinName::BATTERY_CHARGE_STATUS};
auto corebattery = leka::CoreBattery {PinName::BATTERY_VOLTAGE, charge_input};
auto mainboard_led = mbed::DigitalOut {LED1};

log_info("Hello, World!\n\n");

mainboard_led.write(corebattery.isCharging());

auto on_charge_on = [&mainboard_led]() { mainboard_led.write(1); };
auto on_charge_on = []() { mainboard_led.write(1); };
corebattery.onChargeDidStart(on_charge_on);

auto on_charge_off = [&mainboard_led]() { mainboard_led.write(0); };
auto on_charge_off = []() { mainboard_led.write(0); };
corebattery.onChargeDidStop(on_charge_off);

batterykit.onDataUpdated(logBatteryNewLevel);
batterykit.onLowBattery([] { mainboard_led = !mainboard_led; });

batterykit.start();

while (true) {
if (corebattery.isCharging()) {
log_info("Battery at %.2fV (%d%%) and in charge.", corebattery.voltage(), corebattery.level());
} else {
log_info("Battery at %.2fV (%d%%).", corebattery.voltage(), corebattery.level());
}
rtos::ThisThread::sleep_for(1s);
}
}
1 change: 1 addition & 0 deletions tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ leka_register_unit_tests_for_driver(CoreSTM32Hal)
leka_register_unit_tests_for_driver(CoreVideo)

# Register libraries
leka_register_unit_tests_for_library(BatteryKit)
leka_register_unit_tests_for_library(BLEKit)
leka_register_unit_tests_for_library(ColorKit)
leka_register_unit_tests_for_library(ContainerKit)
Expand Down

0 comments on commit e5b8e96

Please sign in to comment.