From b3f03429b389f4bf17dc60782b05de2062c15c75 Mon Sep 17 00:00:00 2001 From: Pascal Roobrouck Date: Wed, 23 Jul 2025 10:02:51 +0200 Subject: [PATCH 1/3] feature showing and responding the SNR correctly. I found a bug in the float to int functions for negative numbers. added the reponse for deviceStatusAnswer --- lib/application/maincontroller.cpp | 2 +- lib/float/float.cpp | 4 +-- lib/logging/logging.cpp | 3 --- lib/lorawan/lorawan.cpp | 23 +++++++++------- lib/lorawan/lorawan.hpp | 5 +++- lib/sensors/battery.cpp | 19 ++++++++++++- lib/sensors/battery.hpp | 1 + lib/sx126x/sx126x.cpp | 13 +++------ platformio.ini | 8 +++--- test/generic/test_float/test.cpp | 43 +++++++++++++++++++----------- 10 files changed, 76 insertions(+), 45 deletions(-) diff --git a/lib/application/maincontroller.cpp b/lib/application/maincontroller.cpp index 0dc073eb..4ec2d757 100644 --- a/lib/application/maincontroller.cpp +++ b/lib/application/maincontroller.cpp @@ -389,7 +389,7 @@ void mainController::showLoRaWanStatus() { screen::setText(2, tmpString); snprintf(tmpString, screen::maxConsoleTextLength, "rx1Delay : %u", static_cast(LoRaWAN::rx1DelayInSeconds)); screen::setText(3, tmpString); - snprintf(tmpString, screen::maxConsoleTextLength, "Margin : %u", static_cast(LoRaWAN::margin)); + snprintf(tmpString, screen::maxConsoleTextLength, "Margin : %u", static_cast(LoRaWAN::uplinkMargin)); screen::setText(4, tmpString); snprintf(tmpString, screen::maxConsoleTextLength, "Gateways : %u", static_cast(LoRaWAN::gatewayCount)); screen::setText(5, tmpString); diff --git a/lib/float/float.cpp b/lib/float/float.cpp index 86dfad5d..b1797a22 100644 --- a/lib/float/float.cpp +++ b/lib/float/float.cpp @@ -4,11 +4,11 @@ #include int32_t integerPart(const float value, const uint32_t decimals) { - return (static_cast(round(value * factorFloat(decimals))) / factorInt(decimals)); + return static_cast(roundf(value * factorFloat(decimals))) / static_cast(factorInt(decimals)); } uint32_t fractionalPart(const float value, const uint32_t decimals) { - return static_cast(round(value * factorFloat(decimals))) - (integerPart(value, decimals) * factorInt(decimals)); + return abs(static_cast(roundf(value * factorFloat(decimals))) - (integerPart(value, decimals) * factorInt(decimals))); } float factorFloat(const uint32_t decimals) { diff --git a/lib/logging/logging.cpp b/lib/logging/logging.cpp index 683fa148..0f3c1296 100644 --- a/lib/logging/logging.cpp +++ b/lib/logging/logging.cpp @@ -27,9 +27,6 @@ char logging::buffer[bufferLength]{}; void logging::initialize() { enable(logging::destination::uart1); - - enable(logging::source::lorawanData); - enable(logging::source::error); enable(logging::source::criticalError); } diff --git a/lib/lorawan/lorawan.cpp b/lib/lorawan/lorawan.cpp index 40b2b60d..3b2800f3 100644 --- a/lib/lorawan/lorawan.cpp +++ b/lib/lorawan/lorawan.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #ifndef generic #include "main.h" @@ -54,7 +55,7 @@ txRxCycleState LoRaWAN::state{txRxCycleState::idle}; linearBuffer LoRaWAN::macIn; linearBuffer LoRaWAN::macOut; -uint32_t LoRaWAN::margin{0}; +uint32_t LoRaWAN::uplinkMargin{0}; uint32_t LoRaWAN::gatewayCount{0}; #pragma endregion @@ -896,11 +897,11 @@ void LoRaWAN::removeNonStickyMacStuff() { void LoRaWAN::processLinkCheckAnswer() { constexpr uint32_t linkCheckAnswerLength{3}; // commandId, margin, GwCnt - margin = macIn[1]; // margin : [0..254] = value in dB above the demodulation floor -> the higher the better, margin [255] = reserved + uplinkMargin = macIn[1]; // margin : [0..254] = value in dB above the demodulation floor -> the higher the better, margin [255] = reserved gatewayCount = macIn[2]; // GwCnt : number of gateways that successfully received the last uplink macIn.consume(linkCheckAnswerLength); // consume all bytes - logging::snprintf(logging::source::lorawanMac, "LinkCheckAnswer : margin = %d, gatewayCount = %d \n", margin, gatewayCount); + logging::snprintf(logging::source::lorawanMac, "LinkCheckAnswer : margin = %d, gatewayCount = %d \n", uplinkMargin, gatewayCount); } void LoRaWAN::processLinkAdaptiveDataRateRequest() { @@ -911,7 +912,6 @@ void LoRaWAN::processLinkAdaptiveDataRateRequest() { macIn.consume(linkAdaptiveDataRateRequestLength); logging::snprintf(logging::source::lorawanMac, "LinkAdaptiveDataRateRequest : 0x%02X, 0x%04X, 0x%02X \n", dataRateTxPower, chMask, redundancy); - constexpr uint32_t linkAdaptiveDataRateAnswerLength{2}; // commandId, status uint8_t answer[linkAdaptiveDataRateAnswerLength]; answer[0] = static_cast(macCommand::linkAdaptiveDataRateAnswer); @@ -926,7 +926,6 @@ void LoRaWAN::processDutyCycleRequest() { macIn.consume(dutyCycleRequestLength); logging::snprintf(logging::source::lorawanMac, "DutyCycleRequest : 0x%02X \n", dutyCycle); - constexpr uint32_t dutyCycleAnswerLength{1}; uint8_t answer[dutyCycleAnswerLength]; answer[0] = static_cast(macCommand::dutyCycleAnswer); @@ -958,8 +957,14 @@ void LoRaWAN::processDeviceStatusRequest() { constexpr uint32_t deviceStatusAnswerLength{3}; // commandId, batteryLevel, margin uint8_t answer[deviceStatusAnswerLength]; answer[0] = static_cast(macCommand::deviceStatusAnswer); - answer[1] = static_cast(255); // The end-device was not able to measure the battery level - answer[2] = static_cast(10); // TODO : implement real value here + answer[1] = battery::stateOfChargeLoRaWAN(); + answer[2] = static_cast(10); // TODO : implement real value here + + // int8_t snr_db = snr_raw / 4; // SNR in full dB + // if (snr_db < -32) snr_db = -32; + // if (snr_db > 31) snr_db = 31; + // uint8_t margin = ((uint8_t)snr_db) & 0x3F; // zero out bits 7 and 6 + macOut.append(answer, deviceStatusAnswerLength); logging::snprintf(logging::source::lorawanMac, "DeviceStatusAnswer : 0x%02X, 0x%02X \n", answer[1], answer[2]); } @@ -1096,13 +1101,13 @@ void LoRaWAN::sendUplink(uint8_t theFramePort, const uint8_t applicationData[], } void LoRaWAN::getReceivedDownlinkMessage() { - // sx126x::getReceivedMessage(); - // downlinkMessage.processDownlinkMessage(applicationPayloadReceived); goTo(txRxCycleState::idle); } messageType LoRaWAN::decodeMessage() { + // sx126x::getPacketSnr(); // 1. read the raw message from the radio receiveBuffer + uint8_t response[2]; sx126x::executeGetCommand(sx126x::command::getRxBufferStatus, response, 2); loRaPayloadLength = response[0]; diff --git a/lib/lorawan/lorawan.hpp b/lib/lorawan/lorawan.hpp index 6719886a..b303e525 100644 --- a/lib/lorawan/lorawan.hpp +++ b/lib/lorawan/lorawan.hpp @@ -85,8 +85,11 @@ class LoRaWAN { static void dumpRawMessagePayload(); static void dumpTransmitSettings(); - static uint32_t margin; + static uint32_t uplinkMargin; + static uint32_t downlinkMargin; static uint32_t gatewayCount; + + static uint32_t currentDataRateIndex; static deviceAddress DevAddr; static aesKey applicationKey; diff --git a/lib/sensors/battery.cpp b/lib/sensors/battery.cpp index dc0aed45..7b62905c 100644 --- a/lib/sensors/battery.cpp +++ b/lib/sensors/battery.cpp @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #ifndef generic #include @@ -94,3 +94,20 @@ float battery::voltageFromRaw(const uint32_t rawADC) { return mockBatteryVoltage; #endif } + +uint8_t battery::stateOfChargeLoRaWAN() { + if (power::hasUsbPower()) { + return 0x00; // LoRaWAN® L2 1.0.4 Specification - line 1106 : The end-device is connected to an external power source. + } + if (!channels[stateOfCharge].isActive()) { + return 0xFF; // LoRaWAN® L2 1.0.4 Specification - line 1106 : The end-device was not able to measure the battery level. (because this sensorC channel is not active) + } + int32_t result = static_cast(channels[stateOfCharge].value() * 254.0F); + if (result > 254) { + result = 254; + } + if (result < 1) { + result = 1; + } + return static_cast(result); +} diff --git a/lib/sensors/battery.hpp b/lib/sensors/battery.hpp index 824f650a..8be20b54 100644 --- a/lib/sensors/battery.hpp +++ b/lib/sensors/battery.hpp @@ -28,6 +28,7 @@ class battery { static bool samplingIsReady(); static uint32_t readSample(); static float voltageFromRaw(const uint32_t rawADC); + static uint8_t stateOfChargeLoRaWAN(); #ifndef unitTesting private: diff --git a/lib/sx126x/sx126x.cpp b/lib/sx126x/sx126x.cpp index 58041dbc..ed4f7513 100644 --- a/lib/sx126x/sx126x.cpp +++ b/lib/sx126x/sx126x.cpp @@ -39,17 +39,12 @@ uint8_t sx126x::getStatus() { } float sx126x::getPacketSnr() { - // RssiPkt = (-1 * response[0])/2; - // SnrPkt = response[1] / 4; - // SignalRssiPkt = -response[2]/2; - uint8_t response[3]; sx126x::executeGetCommand(sx126x::command::getPacketStatus, response, 3); - - int8_t snr; - std::memcpy(&snr, &response[1], 1); - - return (static_cast(snr) / 4.0f); + int8_t snrAsByte; + std::memcpy(&snrAsByte, &response[1], 1); + float result = static_cast(snrAsByte) / 4.0F; + return result; } void sx126x::configForTransmit(spreadingFactor theSpreadingFactor, uint32_t frequency, uint8_t* payload, uint32_t payloadLength) { diff --git a/platformio.ini b/platformio.ini index a3fe8bc0..cbb08ff6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -131,14 +131,14 @@ test_filter = ;generic/test_applicationevent ;generic/test_graphics ;generic/test_lorawan_deviceaddress - generic/test_framecount - generic/test_lorawan_0_general + ;generic/test_framecount + ;generic/test_lorawan_0_general ;generic/test_lorawan_1_rawmessage ;generic/test_lorawan_2_crypto ;generic/test_lorawan_3_txrxcycle ;generic/test_lorawan_4_mac ;generic/test_sx126x - ;generic/test_float + generic/test_float ;generic/test_aeskey ;generic/test_aesblock ;generic/test_hexascii @@ -165,7 +165,7 @@ test_filter = -debug_test = generic/test_lorawan_2_crypto +debug_test = generic/test_float ; ############################################################################# diff --git a/test/generic/test_float/test.cpp b/test/generic/test_float/test.cpp index a948942d..2314e5b9 100644 --- a/test/generic/test_float/test.cpp +++ b/test/generic/test_float/test.cpp @@ -8,26 +8,39 @@ extern uint8_t mockBME680Registers[256]; extern uint8_t mockTSL2591Registers[256]; -void setUp(void) { // before each test -} -void tearDown(void) { // after each test -} +void setUp(void) {} +void tearDown(void) {} + void test_integerPart() { - TEST_ASSERT_EQUAL_INT(10, integerPart(10.4, 0)); - TEST_ASSERT_EQUAL_INT(11, integerPart(10.5, 0)); - TEST_ASSERT_EQUAL_INT(10, integerPart(10.4, 1)); - TEST_ASSERT_EQUAL_INT(10, integerPart(10.5, 1)); - TEST_ASSERT_EQUAL_INT(11, integerPart(10.95, 1)); + TEST_ASSERT_EQUAL_INT(10, integerPart(10.4F, 0)); + TEST_ASSERT_EQUAL_INT(11, integerPart(10.5F, 0)); + TEST_ASSERT_EQUAL_INT(10, integerPart(10.4F, 1)); + TEST_ASSERT_EQUAL_INT(10, integerPart(10.5F, 1)); + TEST_ASSERT_EQUAL_INT(11, integerPart(10.95F, 1)); + + + TEST_ASSERT_EQUAL_INT(-10, integerPart(-10.4F, 0)); + TEST_ASSERT_EQUAL_INT(-11, integerPart(-10.5F, 0)); + TEST_ASSERT_EQUAL_INT(-10, integerPart(-10.4F, 1)); + TEST_ASSERT_EQUAL_INT(-10, integerPart(-10.5F, 1)); + TEST_ASSERT_EQUAL_INT(-11, integerPart(-10.95F, 1)); } void test_fractionalPart() { - TEST_ASSERT_EQUAL_INT(0, fractionalPart(10.49, 0)); - TEST_ASSERT_EQUAL_INT(0, fractionalPart(10.51, 0)); - TEST_ASSERT_EQUAL_INT(4, fractionalPart(10.44, 1)); - TEST_ASSERT_EQUAL_INT(5, fractionalPart(10.45, 1)); - TEST_ASSERT_EQUAL_INT(44, fractionalPart(10.44, 2)); - TEST_ASSERT_EQUAL_INT(45, fractionalPart(10.45, 2)); + TEST_ASSERT_EQUAL_INT(0, fractionalPart(10.49F, 0)); + TEST_ASSERT_EQUAL_INT(0, fractionalPart(10.51F, 0)); + TEST_ASSERT_EQUAL_INT(4, fractionalPart(10.44F, 1)); + TEST_ASSERT_EQUAL_INT(5, fractionalPart(10.45F, 1)); + TEST_ASSERT_EQUAL_INT(44, fractionalPart(10.44F, 2)); + TEST_ASSERT_EQUAL_INT(45, fractionalPart(10.45F, 2)); + + TEST_ASSERT_EQUAL_INT(0, fractionalPart(-10.49F, 0)); + TEST_ASSERT_EQUAL_INT(0, fractionalPart(-10.51F, 0)); + TEST_ASSERT_EQUAL_INT(4, fractionalPart(-10.44F, 1)); + TEST_ASSERT_EQUAL_INT(5, fractionalPart(-10.45F, 1)); + TEST_ASSERT_EQUAL_INT(44, fractionalPart(-10.44F, 2)); + TEST_ASSERT_EQUAL_INT(45, fractionalPart(-10.45F, 2)); } void test_factorFloat() { From db6a5ee2a5ee6b85367b43cf72275de40ca424d6 Mon Sep 17 00:00:00 2001 From: Pascal Roobrouck Date: Wed, 23 Jul 2025 21:32:16 +0200 Subject: [PATCH 2/3] reconnect sonarcloud --- .github/workflows/testbuildrelease.yml | 4 ++-- sonar-project.properties | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testbuildrelease.yml b/.github/workflows/testbuildrelease.yml index 3c65bcac..d3ccbeee 100644 --- a/.github/workflows/testbuildrelease.yml +++ b/.github/workflows/testbuildrelease.yml @@ -232,8 +232,8 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: | sonar-scanner \ - --define sonar.projectKey=Strooom_MuMo-v2-Node-SW \ - --define sonar.organization=strooom-1 \ + --define sonar.projectKey=strooom_mumo-sw \ + --define sonar.organization=strooom \ --define sonar.coverageReportPaths=coverage.xml - name: Attach Binary to Workflow run diff --git a/sonar-project.properties b/sonar-project.properties index 22fd28d8..bc0e5bce 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,5 +1,6 @@ -sonar.projectKey=MuMo-v2-Node-SW -sonar.projectName=MuMo-v2-Node-SW +sonar.projectKey=strooom_mumo-sw +sonar.organization=strooom +sonar.projectName=strooom_mumo-sw sonar.projectVersion=1.0 sonar.sources=src, lib sonar.tests=test From e27d61d26451a01b480c9d303419bcb6f84be4ee Mon Sep 17 00:00:00 2001 From: Pascal Roobrouck Date: Wed, 23 Jul 2025 22:09:23 +0200 Subject: [PATCH 3/3] fix badge to sonarCloud --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 50c929b6..077abb0d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ ![workflow](https://github.com/strooom/MuMo-v2-Node-SW/actions/workflows/testbuildrelease.yml/badge.svg) [![codecov](https://codecov.io/gh/Strooom/MuMo-v2-Node-SW/graph/badge.svg?token=7KF1NA1ACQ)](https://codecov.io/gh/Strooom/MuMo-v2-Node-SW) [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Strooom_MuMo-v2-Node-SW&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Strooom_MuMo-v2-Node-SW) - +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=strooom_mumo-sw&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=strooom_mumo-sw) # LoRaWAN development for STM32WLE using PlatformIO and STM32CubeIDE