diff --git a/libs/BLEKit/include/BLEServiceMonitoring.h b/libs/BLEKit/include/BLEServiceMonitoring.h index e1244f1aa2..5e46e24b5e 100644 --- a/libs/BLEKit/include/BLEServiceMonitoring.h +++ b/libs/BLEKit/include/BLEServiceMonitoring.h @@ -43,8 +43,29 @@ class BLEServiceMonitoring : public interface::BLEService sendData(data); } + void setTemperature(float value) + { + std::memcpy(temperature.data(), &value, 4); + + auto data = std::make_tuple(_temperature_characteristic.getValueHandle(), temperature); + sendData(data); + } + + void setHumidity(float value) + { + std::memcpy(humidity.data(), &value, 4); + + auto data = std::make_tuple(_humidity_characteristic.getValueHandle(), humidity); + sendData(data); + } + auto isScreensaverEnable() const -> bool { return _screensaver_enable; } + void onTemperatureHumidityRequested(const std::function &callback) + { + _on_temperature_humidity_requested_callback = callback; + } + void onDataReceived(const data_received_handle_t ¶ms) final { if (params.handle == _screensaver_enable_characteristic.getValueHandle()) { @@ -68,7 +89,11 @@ class BLEServiceMonitoring : public interface::BLEService void onDataRequested(const data_requested_handle_t ¶ms) final { - // do nothing + if ((params.handle == _temperature_characteristic.getValueHandle() || + params.handle == _humidity_characteristic.getValueHandle()) && + _on_temperature_humidity_requested_callback != nullptr) { + _on_temperature_humidity_requested_callback(); + } } private: @@ -79,6 +104,18 @@ class BLEServiceMonitoring : public interface::BLEService GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY, }; + std::array temperature {}; + ReadOnlyArrayGattCharacteristic _temperature_characteristic { + service::monitoring::characteristic::temperature, temperature.begin(), + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY}; + + std::array humidity {}; + ReadOnlyArrayGattCharacteristic _humidity_characteristic { + service::monitoring::characteristic::humidity, humidity.begin(), + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY}; + + std::function _on_temperature_humidity_requested_callback {}; + bool _screensaver_enable {true}; WriteOnlyGattCharacteristic _screensaver_enable_characteristic { service::monitoring::characteristic::screensaver_enable, @@ -106,9 +143,10 @@ class BLEServiceMonitoring : public interface::BLEService GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY, }; - std::array _characteristic_table { + std::array _characteristic_table { &_charging_status_characteristic, &_screensaver_enable_characteristic, &_soft_reboot_characteristic, - &_hard_reboot_characteristic, &_negotiated_mtu_characteristic, + &_hard_reboot_characteristic, &_negotiated_mtu_characteristic, &_temperature_characteristic, + &_humidity_characteristic, }; }; diff --git a/libs/BLEKit/include/internal/ServicesCharacteristics.h b/libs/BLEKit/include/internal/ServicesCharacteristics.h index 13611a664b..6c0716ff8d 100644 --- a/libs/BLEKit/include/internal/ServicesCharacteristics.h +++ b/libs/BLEKit/include/internal/ServicesCharacteristics.h @@ -42,6 +42,8 @@ namespace monitoring { inline constexpr uint16_t soft_reboot = 0x8382; inline constexpr uint16_t hard_reboot = 0x7282; inline constexpr UUID::LongUUIDBytes_t negotiated_mtu = {"NEGOTIATED_MTU"}; + inline constexpr UUID::LongUUIDBytes_t temperature = {"TEMPERATURE"}; + inline constexpr UUID::LongUUIDBytes_t humidity = {"HUMIDITY"}; } // namespace characteristic } // namespace monitoring diff --git a/libs/BLEKit/tests/BLEServiceMonitoring_test.cpp b/libs/BLEKit/tests/BLEServiceMonitoring_test.cpp index 4313915412..b9d3833db1 100644 --- a/libs/BLEKit/tests/BLEServiceMonitoring_test.cpp +++ b/libs/BLEKit/tests/BLEServiceMonitoring_test.cpp @@ -54,6 +54,71 @@ TEST_F(BLEServiceMonitoringTest, setChargingStatus) EXPECT_FALSE(actual_charging_status); } +TEST_F(BLEServiceMonitoringTest, setTemperature) +{ + std::array actual_temperature {}; + std::array expected_temperature {}; + + auto spy_callback = [&actual_temperature](const BLEServiceMonitoring::data_to_send_handle_t &handle) { + for (auto i = 0; i < std::size(actual_temperature); i++) { + actual_temperature.at(i) = std::get<1>(handle)[i]; + } + }; + + service_monitoring.onDataReadyToSend(spy_callback); + + service_monitoring.setTemperature(31.4159); + expected_temperature = {0xC3, 0x53, 0xFB, 0x41}; // 31.4159, little-endian as in Swift + EXPECT_EQ(actual_temperature, expected_temperature); +} + +TEST_F(BLEServiceMonitoringTest, setHumidity) +{ + std::array actual_humidity {}; + std::array expected_humidity {}; + + auto spy_callback = [&actual_humidity](const BLEServiceMonitoring::data_to_send_handle_t &handle) { + for (auto i = 0; i < std::size(actual_humidity); i++) { + actual_humidity.at(i) = std::get<1>(handle)[i]; + } + }; + + service_monitoring.onDataReadyToSend(spy_callback); + + service_monitoring.setHumidity(51.24); + expected_humidity = {0xC3, 0xF5, 0x4C, 0x42}; // 51.24 little-endian as in Swift + EXPECT_EQ(actual_humidity, expected_humidity); +} + +TEST_F(BLEServiceMonitoringTest, onTemperatureHumidityRequested) +{ + testing::MockFunction mock_callback {}; + service_monitoring.onTemperatureHumidityRequested(mock_callback.AsStdFunction()); + + EXPECT_CALL(mock_callback, Call).Times(1); + + service_monitoring.onDataRequested(data_requested_handle); +} + +TEST_F(BLEServiceMonitoringTest, onTemperatureHumidityRequestedNotSameHandle) +{ + testing::MockFunction mock_callback {}; + service_monitoring.onTemperatureHumidityRequested(mock_callback.AsStdFunction()); + + data_requested_handle.handle = 0xFFFF; + + EXPECT_CALL(mock_callback, Call).Times(0); + + service_monitoring.onDataRequested(data_requested_handle); +} + +TEST_F(BLEServiceMonitoringTest, onTemperatureHumidityRequestedtUnset) +{ + service_monitoring.onTemperatureHumidityRequested(nullptr); + + service_monitoring.onDataRequested(data_requested_handle); +} + TEST_F(BLEServiceMonitoringTest, isScreensaverEnableDefault) { auto actual_is_screensaver_enable = service_monitoring.isScreensaverEnable();