From 537fc32b812c0eb73a6cf1371e4c57813639aacb Mon Sep 17 00:00:00 2001 From: 94xhn <87560781+94xhn@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:16:57 +0800 Subject: [PATCH 1/2] Fix NimBLEEddystoneTLM byte-order mismatch between getters and setters m_eddystoneData must always hold Eddystone-TLM wire-format (big-endian) bytes, since getData() returns it directly for the caller to memcpy straight into the BLE advertisement payload (see the BLE_EddystoneTLM_Beacon example), and setData()/getData() already treat it as raw wire bytes. The getters (getVolt/getTemp) correctly un-swap on read, but the setters (setVolt/setTemp/setCount/setTime) stored their host-order input directly with no swap, and the BeaconData default member initializers were host-order values instead of pre-swapped wire-format values. This breaks the setter/getter round trip for any value set locally (as opposed to arriving over the air via setData()), and means a freshly constructed object reports a garbage battery voltage. toString() also failed to un-swap the temperature field at all, and used unsigned division/modulo on a signed 8.8 fixed-point value, producing garbage output for negative temperatures. This mirrors the existing, correct pattern already used by the sibling NimBLEBeacon class, which swaps in its setters (setMajor/setMinor/ setManufacturerId). Fix: - setVolt/setTemp/setCount/setTime now apply ENDIAN_CHANGE_U16/U32 to their input before storing, matching what the getters already assume. - BeaconData's default volt/temp member initializers are now the wire-format (byte-swapped) encoding of the intended defaults (3300 mV, 23.0C), so a freshly constructed object reports correct values without calling a setter first. - toString() now swaps the temperature field the same way it already swaps voltage, and computes the displayed magnitude from a signed value with explicit sign handling instead of unsigned arithmetic on the raw field. No change to the over-the-air byte layout: setData()/getData() still operate on raw wire-format bytes exactly as before. --- src/NimBLEEddystoneTLM.cpp | 18 ++++++++++-------- src/NimBLEEddystoneTLM.h | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/NimBLEEddystoneTLM.cpp b/src/NimBLEEddystoneTLM.cpp index 8ee405b5..0c5d253b 100644 --- a/src/NimBLEEddystoneTLM.cpp +++ b/src/NimBLEEddystoneTLM.cpp @@ -101,10 +101,12 @@ std::string NimBLEEddystoneTLM::toString() { out += val; out += " mV\n"; - out += "Temperature "; - uint8_t intTemp = m_eddystoneData.temp / 256; - uint8_t frac = m_eddystoneData.temp % 256 * 100 / 256; - snprintf(val, sizeof(val), "%d.%d", intTemp, frac); + out += "Temperature "; + int16_t temp = ENDIAN_CHANGE_U16(m_eddystoneData.temp); + uint32_t absTemp = temp < 0 ? -static_cast(temp) : temp; + uint8_t intTemp = absTemp / 256; + uint8_t frac = absTemp % 256 * 100 / 256; + snprintf(val, sizeof(val), "%s%d.%d", (temp < 0 ? "-" : ""), intTemp, frac); out += val; out += " C\n"; @@ -188,7 +190,7 @@ void NimBLEEddystoneTLM::setVersion(uint8_t version) { * @param [in] volt The voltage in millivolts. */ void NimBLEEddystoneTLM::setVolt(uint16_t volt) { - m_eddystoneData.volt = volt; + m_eddystoneData.volt = ENDIAN_CHANGE_U16(volt); } // setVolt /** @@ -196,7 +198,7 @@ void NimBLEEddystoneTLM::setVolt(uint16_t volt) { * @param [in] temp The temperature value in 8.8 fixed point format. */ void NimBLEEddystoneTLM::setTemp(int16_t temp) { - m_eddystoneData.temp = temp; + m_eddystoneData.temp = ENDIAN_CHANGE_U16(temp); } // setTemp /** @@ -204,7 +206,7 @@ void NimBLEEddystoneTLM::setTemp(int16_t temp) { * @param [in] advCount The advertisement number. */ void NimBLEEddystoneTLM::setCount(uint32_t advCount) { - m_eddystoneData.advCount = advCount; + m_eddystoneData.advCount = ENDIAN_CHANGE_U32(advCount); } // setCount /** @@ -212,7 +214,7 @@ void NimBLEEddystoneTLM::setCount(uint32_t advCount) { * @param [in] tmil The advertisement time in milliseconds. */ void NimBLEEddystoneTLM::setTime(uint32_t tmil) { - m_eddystoneData.tmil = tmil; + m_eddystoneData.tmil = ENDIAN_CHANGE_U32(tmil); } // setTime #endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) diff --git a/src/NimBLEEddystoneTLM.h b/src/NimBLEEddystoneTLM.h index f48cf94c..fdfcb841 100644 --- a/src/NimBLEEddystoneTLM.h +++ b/src/NimBLEEddystoneTLM.h @@ -37,8 +37,8 @@ class NimBLEEddystoneTLM { struct BeaconData { uint8_t frameType{EDDYSTONE_TLM_FRAME_TYPE}; uint8_t version{0}; - uint16_t volt{3300}; - uint16_t temp{23 * 256}; + uint16_t volt{0xE40C}; // Big-endian (wire format) encoding of 3300 mV; getVolt() swaps back to host order. + uint16_t temp{0x0017}; // Big-endian (wire format) encoding of 23.0C (23 * 256); getTemp() swaps back to host order. uint32_t advCount{0}; uint32_t tmil{0}; } __attribute__((packed)); From 8679dff67500de742dd4ac9f22565e5000e6afb4 Mon Sep 17 00:00:00 2001 From: 94xhn <94xhn1@gmail.com> Date: Fri, 17 Jul 2026 19:58:41 +0800 Subject: [PATCH 2/2] fix: pad Eddystone temperature fractions A one-digit fractional component changed the displayed value; for example, 23.05 C was rendered as 23.5 C. Constraint: Eddystone temperature uses signed 8.8 fixed point Confidence: high Scope-risk: narrow Tested: seven positive/negative boundaries; MinGW GCC 8 -Werror Not-tested: hardware advertisement display --- src/NimBLEEddystoneTLM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NimBLEEddystoneTLM.cpp b/src/NimBLEEddystoneTLM.cpp index 0c5d253b..4cfd7498 100644 --- a/src/NimBLEEddystoneTLM.cpp +++ b/src/NimBLEEddystoneTLM.cpp @@ -106,7 +106,7 @@ std::string NimBLEEddystoneTLM::toString() { uint32_t absTemp = temp < 0 ? -static_cast(temp) : temp; uint8_t intTemp = absTemp / 256; uint8_t frac = absTemp % 256 * 100 / 256; - snprintf(val, sizeof(val), "%s%d.%d", (temp < 0 ? "-" : ""), intTemp, frac); + snprintf(val, sizeof(val), "%s%d.%02d", (temp < 0 ? "-" : ""), intTemp, frac); out += val; out += " C\n";