Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/opendisplay_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ OD_STATIC_ASSERT(sizeof(struct AuthProof) == 32, "AuthProof wire size");
/* MsdAdvertisement.status @bits MsdStatusBits. bit0 is the 9th (MSB) bit of the
* 10-bit battery voltage; bits 4-7 are a free-running main-loop nibble counter. */
#define OD_MSD_STATUS_BATTERY_VOLTAGE_BIT8 (1u << 0) /* @doc "high bit of the 10-bit battery voltage (units of 10 mV); combine with battery_voltage_low" */
#define OD_MSD_STATUS_REBOOT_FLAG (1u << 1) /* @doc "device rebooted since last read" */
#define OD_MSD_STATUS_REBOOT_FLAG (1u << 1) /* @doc "device state changed since last read (reboot or live config write)" */
#define OD_MSD_STATUS_CONNECTION_REQUESTED (1u << 2) /* @doc "device is requesting a connection" */
#define OD_MSD_STATUS_ENCRYPTION_ENABLED (1u << 3) /* @doc "application-layer encryption active (encryption_enabled and non-zero master key)" */
#define OD_MSD_STATUS_RESERVED_3 (1u << 3) /* @deprecated @doc "legacy name for OD_MSD_STATUS_ENCRYPTION_ENABLED (same bit)" */
Expand Down
10 changes: 10 additions & 0 deletions src/communication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,12 @@ void handleWriteConfig(uint8_t* data, uint16_t len) {
reloadConfigAfterSave();
}
sendResponse(ok ? responseOk : responseErr, 4);
if (ok) {
// Runs after the ACK: unlike the reload above, this only affects what
// OTHER scanners see, and updatemsdata() can block tens of ms on a
// sensor-cache miss -- no reason to make the writer's own ACK wait on it.
notifyConfigChangedOverBle();
}
}

void handleClearConfig(void) {
Expand Down Expand Up @@ -644,6 +650,10 @@ void handleWriteConfigChunk(uint8_t* data, uint16_t len) {
reloadConfigAfterSave();
}
sendResponse(saved ? ok : err, 4);
if (saved) {
// See handleWriteConfig(): deferred past the ACK on purpose.
notifyConfigChangedOverBle();
}
resetChunkedWriteState();
} else {
uint8_t ackResponse[] = {RESP_ACK, RESP_CONFIG_CHUNK, 0x00, 0x00};
Expand Down
7 changes: 7 additions & 0 deletions src/communication.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ uint16_t calculateCRC16CCITT(uint8_t* data, uint32_t len);
uint8_t getFirmwareMajor();
uint8_t getFirmwareMinor();
uint8_t getFirmwarePatch();
uint8_t getRebootFlag(); // 1 after reboot or a live config write, cleared to 0 on BLE connection
const char* getFirmwareShaString();
void handleFirmwareVersion();
void handleReadMSD();
Expand Down Expand Up @@ -80,4 +81,10 @@ void requestTransferSessionCleanup(void);
/// re-arm on both targets (see BleTransport::restartsAdvertisingOnDisconnect).
void requestAdvertisingRestart(void);

/// Set rebootFlag and refresh the advertised MSD payload immediately after a
/// config write. Unlike the two requests above this is not deferred: it is
/// safe to run synchronously from the command handler, the same way
/// updatemsdata() already runs synchronously from button/sensor call sites.
void notifyConfigChangedOverBle(void);

#endif
1 change: 0 additions & 1 deletion src/device_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ extern "C" void bootloader_util_app_start(uint32_t start_addr);

#include "ble_transport.h"

extern uint8_t rebootFlag;
extern struct GlobalConfig globalConfig;
extern uint8_t activeLedInstance;
extern bool ledFlashActive;
Expand Down
3 changes: 1 addition & 2 deletions src/display_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ extern BBEPDISP bbep;
extern struct GlobalConfig globalConfig;
extern uint8_t msd_payload[16];
extern uint8_t dynamicreturndata[11];
extern uint8_t rebootFlag;
extern uint8_t activeLedInstance;
extern bool connectionRequested;
extern uint8_t mloopcounter;
Expand Down Expand Up @@ -1868,7 +1867,7 @@ void updatemsdata(){
uint8_t temperatureByte = (uint8_t)tempEncoded;
uint8_t batteryVoltageLowByte = (uint8_t)(batteryVoltage10mv & 0xFF);
uint8_t statusByte = (((batteryVoltage10mv >> 8) & 0x01) ? OD_MSD_STATUS_BATTERY_VOLTAGE_BIT8 : 0) |
(rebootFlag ? OD_MSD_STATUS_REBOOT_FLAG : 0) |
(getRebootFlag() ? OD_MSD_STATUS_REBOOT_FLAG : 0) |
(connectionRequested ? OD_MSD_STATUS_CONNECTION_REQUESTED : 0) |
(isEncryptionEnabled() ? OD_MSD_STATUS_ENCRYPTION_ENABLED : 0) |
(((uint8_t)(mloopcounter << OD_MSD_STATUS_MAIN_LOOP_COUNTER_SHIFT)) & OD_MSD_STATUS_MAIN_LOOP_COUNTER_MASK);
Expand Down
15 changes: 15 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ uint32_t getDeepSleepCount() {
#endif
}

uint8_t getRebootFlag() {
return rebootFlag;
}

// Deferred work, serviced by loop(). File-static on purpose: these encode
// application policy, so nothing outside this file reads them, and the two that
// other translation units need to RAISE do so through the request functions
Expand Down Expand Up @@ -360,6 +364,17 @@ void requestAdvertisingRestart(void) {
s_advertisingRestartPending = true;
}

void notifyConfigChangedOverBle(void) {
// Mirrors the boot-time meaning of rebootFlag: a scanning hub sees it set in
// the advertised MSD payload and knows to reconnect and re-read config
// instead of trusting a cached copy (e.g. stale color_scheme). A config
// write changes the same on-device state a reboot would, so it must raise
// the same flag -- otherwise a live BLE write is invisible to anyone who
// isn't the client that just wrote it.
rebootFlag = 1;
updatemsdata();
}

#ifdef TARGET_ESP32
// Minimum awake window (first boot / button wake). A floor layered UNDER the
// quiet-window logic, not a replacement: sleep requires both the existing
Expand Down
5 changes: 3 additions & 2 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ uint8_t mloopcounter = 0;
#ifdef TARGET_ESP32
// Persists across deep sleep so a wake is not mistaken for a reboot. Re-armed
// on the boot-screen path in setup(), which is the only path a real reset takes.
RTC_DATA_ATTR uint8_t rebootFlag = 1; // Set to 1 after reboot, cleared to 0 after BLE connection
RTC_DATA_ATTR uint8_t rebootFlag = 1; // Set to 1 on reboot or config write, cleared to 0 on BLE connection
#else
uint8_t rebootFlag = 1; // Set to 1 after reboot, cleared to 0 after BLE connection
uint8_t rebootFlag = 1; // Set to 1 on reboot or config write, cleared to 0 on BLE connection
#endif
uint8_t connectionRequested = 0; // Reserved for future features (connection requested flag)
uint8_t dynamicreturndata[11] = {0}; // Dynamic return data blocks (bytes 2-12 in advertising payload)
Expand Down Expand Up @@ -248,6 +248,7 @@ uint8_t getFirmwareMajor();
uint8_t getFirmwareMinor();
uint8_t getFirmwarePatch();
uint32_t getDeepSleepCount(); // RTC-persisted wake cycle count on ESP32; always 0 on nRF52840
uint8_t getRebootFlag(); // 1 after reboot or a live config write, cleared to 0 on BLE connection
float readBatteryVoltage(); // Returns battery voltage in volts, or -1.0 if not configured
float readChipTemperature(); // Returns chip temperature in degrees Celsius
int getplane();
Expand Down
2 changes: 1 addition & 1 deletion tools/od-device-cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ def cmd_read_msd(args: argparse.Namespace) -> int:
voltage = info["battery_voltage_v"]
print(f"Battery voltage: {f'{voltage:.2f} V' if voltage is not None else 'unknown (raw=0 - unconfigured or not yet sampled)'}")
print(f"Chip temperature: {info['temperature_c']:.1f} C")
print(f"Reboot flag: {info['reboot_flag']}")
print(f"State changed (reboot/config): {info['reboot_flag']}")
print(f"Connection requested: {info['connection_requested']}")
print(f"Loop counter: {info['loop_counter']}")
print(f"Dynamic data (bytes 2-12): {info['dynamic_data_hex']}")
Expand Down
Loading