diff --git a/include/interface/drivers/FirmwareVersion.h b/include/interface/drivers/FirmwareVersion.h index 13f84fd1b4..6e6361de7c 100644 --- a/include/interface/drivers/FirmwareVersion.h +++ b/include/interface/drivers/FirmwareVersion.h @@ -4,7 +4,10 @@ #pragma once +#include #include +#include +#include namespace leka { @@ -13,6 +16,15 @@ struct FirmwareVersion { uint8_t minor; uint16_t revision; // ? Use uint16_t instead of uint8_t for compatibility w/ MCUBoot Image format, see // ? https://docs.mcuboot.com/design.html + + [[nodiscard]] auto asStdArray() const -> std::span + { + std::snprintf(_formatted_output.data(), std::size(_formatted_output), _format_string, major, minor, revision); + return std::span(_formatted_output); + } + + const char *_format_string = "%u.%u.%u"; + mutable std::array _formatted_output = {}; }; } // namespace leka diff --git a/libs/BLEKit/include/BLEServiceDeviceInformation.h b/libs/BLEKit/include/BLEServiceDeviceInformation.h index 8e8323893a..b25b4654bb 100644 --- a/libs/BLEKit/include/BLEServiceDeviceInformation.h +++ b/libs/BLEKit/include/BLEServiceDeviceInformation.h @@ -5,6 +5,7 @@ #pragma once #include "CastUtils.h" +#include "interface/drivers/FirmwareVersion.h" #include "internal/BLEService.h" #include "internal/ServicesCharacteristics.h" @@ -23,6 +24,17 @@ class BLEServiceDeviceInformation : public interface::BLEService sendData(data); } + void setOSVersion(const FirmwareVersion &version) const + { + _os_version.fill('\0'); + auto version_cstr = version.asStdArray(); + + std::copy(std::begin(version_cstr), std::begin(version_cstr) + std::size(_os_version), _os_version.begin()); + + auto data = std::make_tuple(_os_version_characteristic.getValueHandle(), _os_version); + sendData(data); + } + void onDataReceived(const data_received_handle_t ¶ms) final { // do nothing @@ -47,8 +59,15 @@ class BLEServiceDeviceInformation : public interface::BLEService service::device_information::characteristic::serial_number, _serial_number.data(), _serial_number.size(), _serial_number.size(), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ}; - std::array _characteristic_table { - &_manufacturer_name_characteristic, &_model_number_characteristic, &_serial_number_characteristic}; + inline static auto _os_version = utils::cast::from_c_string_to_uint8_t_array("000.000.00000"); + + GattCharacteristic _os_version_characteristic {service::device_information::characteristic::os_version, + _os_version.data(), _os_version.size(), _os_version.size(), + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ}; + + std::array _characteristic_table { + &_manufacturer_name_characteristic, &_model_number_characteristic, &_serial_number_characteristic, + &_os_version_characteristic}; }; } // namespace leka diff --git a/libs/BLEKit/include/internal/ServicesCharacteristics.h b/libs/BLEKit/include/internal/ServicesCharacteristics.h index 21dff932b8..360caf9a24 100644 --- a/libs/BLEKit/include/internal/ServicesCharacteristics.h +++ b/libs/BLEKit/include/internal/ServicesCharacteristics.h @@ -17,6 +17,7 @@ namespace device_information { inline constexpr uint16_t manufacturer_name = GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR; inline constexpr uint16_t model_number = GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR; inline constexpr uint16_t serial_number = GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR; + inline constexpr uint16_t os_version = GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR; } // namespace characteristic } // namespace device_information diff --git a/libs/BLEKit/tests/BLEServiceDeviceInformation_test.cpp b/libs/BLEKit/tests/BLEServiceDeviceInformation_test.cpp index 9665937095..c4c7eba1ea 100644 --- a/libs/BLEKit/tests/BLEServiceDeviceInformation_test.cpp +++ b/libs/BLEKit/tests/BLEServiceDeviceInformation_test.cpp @@ -47,3 +47,27 @@ TEST(BLEServiceDeviceInformationTest, setSerialNumber) } EXPECT_TRUE(same_content); } + +TEST(BLEServiceDeviceInformationTest, setOSVersion) +{ + auto service_device_information = BLEServiceDeviceInformation {}; + + const auto os_version_size = 14; + std::array actual_os_version {}; + + auto spy_callback = [&actual_os_version](const BLEServiceDeviceInformation::data_to_send_handle_t &handle) { + for (int i = 0; i < os_version_size; i++) { + actual_os_version.at(i) = std::get<1>(handle)[i]; + } + }; + + service_device_information.onDataReadyToSend(spy_callback); + + auto os_version = FirmwareVersion {123, 234, 45678}; + auto expected_os_version = os_version.asStdArray(); // "123.234.45678" + service_device_information.setOSVersion(os_version); + + for (int i = 0; i < os_version_size; i++) { + EXPECT_EQ(actual_os_version.at(i), expected_os_version[i]); + } +} diff --git a/libs/RobotKit/include/RobotController.h b/libs/RobotKit/include/RobotController.h index 8aff159d7c..95ad4f4dcb 100644 --- a/libs/RobotKit/include/RobotController.h +++ b/libs/RobotKit/include/RobotController.h @@ -203,6 +203,9 @@ class RobotController : public interface::RobotController auto _serial_number = _serialnumberkit.getSerialNumber(); _service_device_information.setSerialNumber(_serial_number); + auto _os_version = FirmwareVersion {.major = 1, .minor = 0, .revision = 0}; + _service_device_information.setOSVersion(_os_version); + _motor_left.stop(); _motor_right.stop(); diff --git a/libs/RobotKit/tests/RobotController_test.h b/libs/RobotKit/tests/RobotController_test.h index 5308fbc324..3d9422ab7b 100644 --- a/libs/RobotKit/tests/RobotController_test.h +++ b/libs/RobotKit/tests/RobotController_test.h @@ -123,6 +123,8 @@ class RobotControllerTest : public testing::Test EXPECT_CALL(mock_mcu, getID).Times(1); EXPECT_CALL(mbed_mock_gatt, write(_, _, _, _)).Times(1); + EXPECT_CALL(mbed_mock_gatt, write(_, _, _, _)).Times(1); + expectedCallsStopMotors(); EXPECT_CALL(mock_videokit, initializeScreen).Times(1); diff --git a/libs/RobotKit/tests/RobotController_test_initializeComponents.cpp b/libs/RobotKit/tests/RobotController_test_initializeComponents.cpp index 654503e078..f8d930b641 100644 --- a/libs/RobotKit/tests/RobotController_test_initializeComponents.cpp +++ b/libs/RobotKit/tests/RobotController_test_initializeComponents.cpp @@ -22,6 +22,8 @@ TEST_F(RobotControllerTest, initializeComponents) // TODO: Specify which BLE service and what is expected if necessary EXPECT_CALL(mbed_mock_gatt, write(_, _, _, _)).Times(1); + EXPECT_CALL(mbed_mock_gatt, write(_, _, _, _)).Times(1); + expectedCallsStopMotors(); EXPECT_CALL(mock_videokit, initializeScreen).Times(1); diff --git a/spikes/lk_ble/main.cpp b/spikes/lk_ble/main.cpp index 5f5eb4fbd8..2bc20a91bb 100644 --- a/spikes/lk_ble/main.cpp +++ b/spikes/lk_ble/main.cpp @@ -60,6 +60,9 @@ auto main() -> int std::array serial_number = {"LK-2202-003300294E5350092038384B"}; service_device_information.setSerialNumber(serial_number); + auto os_version = FirmwareVersion {123, 234, 45678}; + service_device_information.setOSVersion(os_version); + blekit.onConnectionCallback([] { log_info("Connected !"); }); blekit.onDisconnectionCallback([] { log_info("Disconnected !"); });