Skip to content

Commit

Permalink
✨ (config_kit): Add 'ConfigKit'
Browse files Browse the repository at this point in the history
  • Loading branch information
MMyster committed Apr 8, 2022
1 parent 28a1805 commit 15de47f
Show file tree
Hide file tree
Showing 10 changed files with 343 additions and 0 deletions.
1 change: 1 addition & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_subdirectory(${LIBS_DIR}/BehaviorKit)
add_subdirectory(${LIBS_DIR}/BLEKit)
add_subdirectory(${LIBS_DIR}/ColorKit)
add_subdirectory(${LIBS_DIR}/CommandKit)
add_subdirectory(${LIBS_DIR}/ConfigKit)
add_subdirectory(${LIBS_DIR}/ContainerKit)
add_subdirectory(${LIBS_DIR}/FileManagerKit)
add_subdirectory(${LIBS_DIR}/FirmwareKit)
Expand Down
28 changes: 28 additions & 0 deletions libs/ConfigKit/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(ConfigKit STATIC)

target_include_directories(ConfigKit
PUBLIC
include
)

target_sources(ConfigKit
PRIVATE
source/Config.cpp
)

target_link_libraries(ConfigKit
mbed-os
FileManagerKit
)

if (${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")

leka_unit_tests_sources(
tests/Config_test.cpp
)

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

#pragma once

#include <cstdint>
#include <filesystem>
#include <optional>
#include <span>

#include "FileManagerKit.h"
#include "interface/platform/File.h"

namespace leka {

struct Config {
public:
explicit Config(const std::filesystem::path &path, uint8_t default_value = 0xFF)
: _path(_default_parent_path / path), _default_value(default_value)
{
}

[[nodiscard]] auto default_value() const -> uint8_t { return _default_value; }
[[nodiscard]] auto path() const -> std::filesystem::path { return _path; }

private:
const uint8_t _default_value;
const std::filesystem::path _default_parent_path = "/fs/conf";
const std::filesystem::path _path;
};

class ConfigKit
{
public:
explicit ConfigKit() = default;
auto read(Config const &config) -> uint8_t;
auto write(Config const &config, uint8_t data) -> bool;

private:
FileManagerKit::File _file {};
};

} // namespace leka
15 changes: 15 additions & 0 deletions libs/ConfigKit/include/ConfigList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <filesystem>

#include "ConfigKit.h"

namespace leka::config::bootloader {

inline const auto battery_level_hysteresis = Config {"bootloader_battery_level_hysteresis", 42};

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

#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <span>

#include "ConfigKit.h"
#include "LogKit.h"

using namespace leka;

auto ConfigKit::read(Config const &config) -> uint8_t
{
_file.open(config.path(), "r");
if (!_file.is_open()) {
return config.default_value();
}
auto input = std::array<uint8_t, 1> {};
_file.read(input);
_file.close();
auto data = input.front();
return data;
}

auto ConfigKit::write(Config const &config, uint8_t data) -> bool
{
_file.open(config.path(), "r+");
if (!_file.is_open()) {
return false;
}
auto output = std::array<uint8_t, 1> {data};
_file.write(output);
_file.close();
return true;
}
122 changes: 122 additions & 0 deletions libs/ConfigKit/tests/Config_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Leka - LekaOS
// Copyright 2021 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include <array>
#include <fstream>
#include <iostream>
#include <span>
#include <string>

#include "ConfigKit.h"
#include "FileManagerKit.h"
#include "LogKit.h"
#include "gtest/gtest.h"
#include "mocks/leka/File.h"

using namespace leka;

class ConfigTest : public ::testing::Test
{
protected:
// void SetUp() override {}
// void TearDown() override {}

auto spy_readConfigValue() -> uint8_t
{
auto input_data = std::array<uint8_t, 1> {};
FileManagerKit::File file {config_path.c_str()};
file.read(input_data);
file.close();
return input_data.front();
}

void spy_writeConfigValue(uint8_t data)
{
auto output_data = std::array<uint8_t, 1> {data};
FileManagerKit::File file {config_path.c_str(), "r+"};
file.write(output_data);
file.close();
}

void spy_touchConfigFile()
{
FileManagerKit::File file {config_path.c_str(), "w"};
file.close();
}
void spy_removeConfigFile() { std::remove(config_path.c_str()); }

const std::filesystem::path config_path = "/tmp/test_config.conf";
};

TEST_F(ConfigTest, initializationConfigFullPath)
{
const std::filesystem::path custom_full_path = "/tmp/test_config.conf";
Config config {custom_full_path};
ASSERT_NE(nullptr, &config);
const std::filesystem::path expected_path = "/tmp/test_config.conf";
ASSERT_EQ(expected_path, config.path());
}

TEST_F(ConfigTest, initializationWithDefaultParentPathConfig)
{
const std::filesystem::path custom_filename = "test_config.conf";
Config config {custom_filename};
ASSERT_NE(nullptr, &config);
const std::filesystem::path expected_path = "/fs/conf/test_config.conf";
ASSERT_EQ(expected_path, config.path());
}

TEST_F(ConfigTest, initializationConfigKit)
{
auto configkit = ConfigKit();
ASSERT_NE(nullptr, &configkit);
}

TEST_F(ConfigTest, readNotOpenFile)
{
Config config {config_path};
auto configkit = ConfigKit();
spy_removeConfigFile();
auto data = configkit.read(config);
ASSERT_EQ(config.default_value(), data);
}

TEST_F(ConfigTest, readEmptyFile)
{
Config config {config_path};
auto configkit = ConfigKit();
spy_removeConfigFile();
spy_touchConfigFile();
auto data = configkit.read(config);
ASSERT_EQ(0, data);
}

TEST_F(ConfigTest, read)
{
Config config {config_path};
auto configkit = ConfigKit();
spy_writeConfigValue(5);
auto data = configkit.read(config);
ASSERT_EQ(5, data);
}

TEST_F(ConfigTest, writeNotOpenFile)
{
Config config {config_path};
auto configkit = ConfigKit();
spy_removeConfigFile();
auto write = configkit.write(config, 5);
ASSERT_FALSE(write);
}

TEST_F(ConfigTest, write)
{
Config config {config_path};
auto configkit = ConfigKit();
spy_touchConfigFile();
auto write = configkit.write(config, 5);
ASSERT_TRUE(write);
auto data = spy_readConfigValue();
ASSERT_EQ(5, data);
}
1 change: 1 addition & 0 deletions spikes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_subdirectory(${SPIKES_DIR}/lk_bluetooth)
add_subdirectory(${SPIKES_DIR}/lk_cg_animations)
add_subdirectory(${SPIKES_DIR}/lk_color_kit)
add_subdirectory(${SPIKES_DIR}/lk_command_kit)
add_subdirectory(${SPIKES_DIR}/lk_config_kit)
add_subdirectory(${SPIKES_DIR}/lk_coreled)
add_subdirectory(${SPIKES_DIR}/lk_event_queue)
add_subdirectory(${SPIKES_DIR}/lk_file_reception)
Expand Down
22 changes: 22 additions & 0 deletions spikes/lk_config_kit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Leka - LekaOS
# Copyright 2022 APF France handicap
# SPDX-License-Identifier: Apache-2.0

add_mbed_executable(spike_lk_config_kit)

target_include_directories(spike_lk_config_kit
PRIVATE
.
)

target_sources(spike_lk_config_kit
PRIVATE
main.cpp
)

target_link_libraries(spike_lk_config_kit
FileManagerKit
ConfigKit
)

target_link_custom_leka_targets(spike_lk_config_kit)
71 changes: 71 additions & 0 deletions spikes/lk_config_kit/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include <cstddef>
#include <filesystem>

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

#include "ConfigKit.h"
#include "ConfigList.h"
#include "FATFileSystem.h"
#include "FileManagerKit.h"
#include "HelloWorld.h"
#include "LogKit.h"
#include "SDBlockDevice.h"

using namespace leka;
using namespace std::chrono_literals;

SDBlockDevice sd_blockdevice(SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK);
FATFileSystem fatfs("fs");

auto configkit = ConfigKit();

void initializeSD()
{
constexpr auto default_sd_blockdevice_frequency = uint64_t {25'000'000};

sd_blockdevice.init();
sd_blockdevice.frequency(default_sd_blockdevice_frequency);

fatfs.mount(&sd_blockdevice);
}

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

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

auto start = rtos::Kernel::Clock::now();

auto hello = HelloWorld();

rtos::ThisThread::sleep_for(1s);

hello.start();

initializeSD();

auto custom_data = uint8_t {0};

rtos::ThisThread::sleep_for(1s);

while (true) {
auto t = rtos::Kernel::Clock::now() - start;
log_info("A message from your board %s --> \"%s\" at %i s", MBED_CONF_APP_TARGET_NAME, hello.world,
int(t.count() / 1000));

++custom_data;
if (auto write = configkit.write(config::bootloader::battery_level_hysteresis, custom_data); !write) {
log_error("Fail to write in hysteresis config file");
return EXIT_FAILURE;
}
auto battery_level_hysteresis = configkit.read(config::bootloader::battery_level_hysteresis);
log_info("Battery level hysteresis : %d", battery_level_hysteresis);
rtos::ThisThread::sleep_for(10s);
}
}
1 change: 1 addition & 0 deletions tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ leka_register_unit_tests_for_library(BehaviorKit)
leka_register_unit_tests_for_library(BLEKit)
leka_register_unit_tests_for_library(ColorKit)
leka_register_unit_tests_for_library(CommandKit)
leka_register_unit_tests_for_library(ConfigKit)
leka_register_unit_tests_for_library(ContainerKit)
leka_register_unit_tests_for_library(FileManagerKit)
leka_register_unit_tests_for_library(FirmwareKit)
Expand Down

0 comments on commit 15de47f

Please sign in to comment.