Skip to content

Commit 0f672c9

Browse files
authored
Merge pull request #74 from MrAlders0n/copilot/include-debug-logging-guidelines
Fix connection status message timing and preserve error states during disconnect
2 parents db63bb8 + e969486 commit 0f672c9

2 files changed

Lines changed: 63 additions & 34 deletions

File tree

STATUS_MESSAGES.md

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,57 @@ Status messages follow these consistent conventions:
2525
- **Message**: `"Connecting"`
2626
- **Color**: Sky blue (info)
2727
- **Used in**: `connect()`
28-
- **Source**: `content/wardrive.js:1916`
29-
- **Context**: When user clicks Connect button
30-
- **Minimum Visibility**: Natural async timing during BLE pairing (typically 2-5 seconds)
28+
- **Source**: `content/wardrive.js:2005`
29+
- **Context**: When user clicks Connect button; remains visible during entire connection process (BLE pairing, channel setup, and capacity check)
30+
- **Minimum Visibility**: Natural async timing during full connection process (typically 3-8 seconds including capacity check)
3131

3232
#### Connected
3333
- **Message**: `"Connected"`
3434
- **Color**: Green (success)
3535
- **Used in**: `connect()`
36-
- **Source**: `content/wardrive.js:1926`
37-
- **Context**: After BLE device successfully pairs
38-
- **Minimum Visibility**: 500ms minimum enforced
36+
- **Source**: `content/wardrive.js:2060`
37+
- **Context**: After full connection process completes successfully (BLE paired, channel setup, and capacity check passed)
38+
- **Minimum Visibility**: Persists until user interacts with app buttons (send ping, start auto mode)
39+
- **Note**: This message now only appears after the complete connection handshake, not just after BLE pairing
3940

4041
#### Disconnecting
4142
- **Message**: `"Disconnecting"`
4243
- **Color**: Sky blue (info)
4344
- **Used in**: `disconnect()`
44-
- **Source**: `content/wardrive.js:1988`
45-
- **Context**: When user clicks Disconnect button
45+
- **Source**: `content/wardrive.js:2118`
46+
- **Context**: When user clicks Disconnect button or when automatic disconnect is triggered
4647
- **Minimum Visibility**: 500ms minimum enforced
4748

4849
#### Disconnected
4950
- **Message**: `"Disconnected"`
5051
- **Color**: Red (error)
5152
- **Used in**: `connect()`, `disconnect()`, event handlers
52-
- **Source**: `content/wardrive.js:1950`, `content/wardrive.js:2046`
53-
- **Context**: Initial state and when BLE device disconnects
53+
- **Source**: `content/wardrive.js:2073`, `content/wardrive.js:2177`
54+
- **Context**: Initial state and when BLE device disconnects normally (user-initiated or device-initiated)
5455
- **Minimum Visibility**: N/A (persists until connection is established)
56+
- **Note**: Only shown for normal disconnections; error disconnections (e.g., app down, capacity full) preserve their specific error message
5557

5658
#### Connection failed
5759
- **Message**: `"Connection failed"` (or error message)
5860
- **Color**: Red (error)
5961
- **Used in**: `connect()`, event handlers
60-
- **Source**: `content/wardrive.js:1976`, `content/wardrive.js:2059`
62+
- **Source**: `content/wardrive.js:2096`, `content/wardrive.js:2190`
6163
- **Context**: BLE connection fails or connection button error
6264
- **Minimum Visibility**: N/A (error state persists)
6365

6466
#### Channel setup failed
6567
- **Message**: `"Channel setup failed"` (or error message)
6668
- **Color**: Red (error)
6769
- **Used in**: `connect()`
68-
- **Source**: `content/wardrive.js:1944`
70+
- **Source**: `content/wardrive.js:2063`
6971
- **Context**: Channel creation or lookup fails during connection
7072
- **Minimum Visibility**: N/A (error state persists)
7173

7274
#### Disconnect failed
7375
- **Message**: `"Disconnect failed"` (or error message)
7476
- **Color**: Red (error)
7577
- **Used in**: `disconnect()`
76-
- **Source**: `content/wardrive.js:2018`
78+
- **Source**: `content/wardrive.js:2149`
7779
- **Context**: Error during disconnect operation
7880
- **Minimum Visibility**: N/A (error state persists)
7981

@@ -89,23 +91,23 @@ Status messages follow these consistent conventions:
8991
- **Context**: When connecting to device and checking if a wardriving slot is available
9092
- **Minimum Visibility**: 500ms minimum enforced (or until API response received)
9193

92-
#### WarDriving app has reached capacity
93-
- **Message**: `"WarDriving app has reached capacity"`
94+
#### Disconnected: WarDriving app has reached capacity
95+
- **Message**: `"Disconnected: WarDriving app has reached capacity"`
9496
- **Color**: Red (error)
9597
- **Used in**: `checkCapacity()`, `postToMeshMapperAPI()`
96-
- **Source**: `content/wardrive.js:1061`, `content/wardrive.js:1116`
98+
- **Source**: `content/wardrive.js:1063`, `content/wardrive.js:1120`
9799
- **Context**: Capacity check API denies slot on connect (returns allowed=false), or wardriving API returns allowed=false during active session
98-
- **Minimum Visibility**: N/A (error state persists until disconnect)
99-
- **Notes**: Displayed when the API successfully responds but indicates capacity is full
100+
- **Minimum Visibility**: N/A (error state persists; message is preserved during automatic disconnect)
101+
- **Notes**: Displayed when the API successfully responds but indicates capacity is full. When this error occurs during connection, the automatic disconnect flow preserves this status message instead of showing "Disconnected". Message format standardized with "Disconnected: " prefix to clearly indicate disconnect state.
100102

101-
#### WarDriving app is down
102-
- **Message**: `"WarDriving app is down"`
103+
#### Disconnected: WarDriving app is down
104+
- **Message**: `"Disconnected: WarDriving app is down"`
103105
- **Color**: Red (error)
104106
- **Used in**: `checkCapacity()`
105-
- **Source**: `content/wardrive.js:1050`, `content/wardrive.js:1072`
107+
- **Source**: `content/wardrive.js:1050`, `content/wardrive.js:1074`
106108
- **Context**: Capacity check API returns error status or network is unreachable during connect
107-
- **Minimum Visibility**: N/A (error state persists until disconnect)
108-
- **Notes**: Implements fail-closed policy - connection is denied if API fails or is unreachable
109+
- **Minimum Visibility**: N/A (error state persists; message is preserved during automatic disconnect)
110+
- **Notes**: Implements fail-closed policy - connection is denied if API fails or is unreachable. When this error occurs, the automatic disconnect flow preserves this status message instead of showing "Disconnected". Message format standardized with "Disconnected: " prefix to clearly indicate disconnect state.
109111

110112
#### Unable to read device public key; try again
111113
- **Message**: `"Unable to read device public key; try again"`
@@ -277,10 +279,11 @@ These messages use a hybrid approach: **first display respects 500ms minimum**,
277279
#### Idle
278280
- **Message**: `"Idle"`
279281
- **Color**: Slate (idle)
280-
- **Used in**: `connect()`, `postApiAndRefreshMap()`
281-
- **Source**: `content/wardrive.js:2060`, `content/wardrive.js:1091`
282-
- **Context**: Initial connection complete after capacity check succeeds, or manual mode after API post completes
282+
- **Used in**: `postApiAndRefreshMap()`
283+
- **Source**: `content/wardrive.js:1091`
284+
- **Context**: Manual mode after API post completes
283285
- **Minimum Visibility**: 500ms minimum enforced
286+
- **Note**: No longer shown after initial connection; "Connected" status is displayed instead and persists until user action
284287

285288
---
286289

content/wardrive.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const state = {
123123
distanceUpdateTimer: null, // Timer for updating distance display
124124
capturedPingCoords: null, // { lat, lon, accuracy } captured at ping time, used for API post after 7s delay
125125
devicePublicKey: null, // Hex string of device's public key (used for capacity check)
126+
disconnectReason: null, // Tracks the reason for disconnection (e.g., "app_down", "capacity_full", "error", "normal")
126127
repeaterTracking: {
127128
isListening: false, // Whether we're currently listening for echoes
128129
sentTimestamp: null, // Timestamp when the ping was sent
@@ -1047,7 +1048,8 @@ async function checkCapacity(reason) {
10471048
// Fail closed on network errors for connect
10481049
if (reason === "connect") {
10491050
debugError("Failing closed (denying connection) due to API error");
1050-
setStatus("WarDriving app is down", STATUS_COLORS.error);
1051+
setStatus("Disconnected: WarDriving app is down", STATUS_COLORS.error);
1052+
state.disconnectReason = "app_down"; // Track disconnect reason
10511053
return false;
10521054
}
10531055
return true; // Always allow disconnect to proceed
@@ -1058,7 +1060,8 @@ async function checkCapacity(reason) {
10581060

10591061
// Handle capacity full vs. allowed cases separately
10601062
if (data.allowed === false && reason === "connect") {
1061-
setStatus("WarDriving app has reached capacity", STATUS_COLORS.error);
1063+
setStatus("Disconnected: WarDriving app has reached capacity", STATUS_COLORS.error);
1064+
state.disconnectReason = "capacity_full"; // Track disconnect reason
10621065
}
10631066

10641067
return data.allowed === true;
@@ -1069,7 +1072,8 @@ async function checkCapacity(reason) {
10691072
// Fail closed on network errors for connect
10701073
if (reason === "connect") {
10711074
debugError("Failing closed (denying connection) due to network error");
1072-
setStatus("WarDriving app is down", STATUS_COLORS.error);
1075+
setStatus("Disconnected: WarDriving app is down", STATUS_COLORS.error);
1076+
state.disconnectReason = "app_down"; // Track disconnect reason
10731077
return false;
10741078
}
10751079

@@ -1113,7 +1117,8 @@ async function postToMeshMapperAPI(lat, lon, heardRepeats) {
11131117
const data = await response.json();
11141118
if (data.allowed === false) {
11151119
debugWarn("MeshMapper API returned allowed=false, disconnecting");
1116-
setStatus("WarDriving app has reached capacity", STATUS_COLORS.error);
1120+
setStatus("Disconnected: WarDriving app has reached capacity", STATUS_COLORS.error);
1121+
state.disconnectReason = "capacity_full"; // Track disconnect reason
11171122
// Disconnect after a brief delay to ensure user sees the message
11181123
setTimeout(() => {
11191124
disconnect().catch(err => debugError(`Disconnect after capacity denial failed: ${err.message}`));
@@ -2012,7 +2017,8 @@ async function connect() {
20122017

20132018
conn.on("connected", async () => {
20142019
debugLog("BLE connected event fired");
2015-
setStatus("Connected", STATUS_COLORS.success);
2020+
// Keep "Connecting" status visible during the full connection process
2021+
// Don't show "Connected" until everything is complete
20162022
setConnectButton(true);
20172023
connectBtn.disabled = false;
20182024
const selfInfo = await conn.getSelfInfo();
@@ -2022,6 +2028,7 @@ async function connect() {
20222028
if (!selfInfo?.publicKey || selfInfo.publicKey.length !== 32) {
20232029
debugError("Missing or invalid public key from device", selfInfo?.publicKey);
20242030
setStatus("Unable to read device public key; try again", STATUS_COLORS.error);
2031+
state.disconnectReason = "error"; // Mark as error disconnect
20252032
// Disconnect after a brief delay to ensure user sees the error message
20262033
setTimeout(() => {
20272034
disconnect().catch(err => debugError(`Disconnect after public key error failed: ${err.message}`));
@@ -2050,28 +2057,40 @@ async function connect() {
20502057
if (!allowed) {
20512058
debugWarn("Capacity check denied, disconnecting");
20522059
// Status message already set by checkCapacity()
2060+
// disconnectReason already set by checkCapacity()
20532061
// Disconnect after a brief delay to ensure user sees the message
20542062
setTimeout(() => {
20552063
disconnect().catch(err => debugError(`Disconnect after capacity denial failed: ${err.message}`));
20562064
}, 1500);
20572065
} else {
2058-
// Connection complete, set status to Idle
2059-
setStatus("Idle", STATUS_COLORS.idle);
2066+
// Connection complete, show Connected status
2067+
setStatus("Connected", STATUS_COLORS.success);
2068+
debugLog("Full connection process completed successfully");
20602069
}
20612070
} catch (e) {
20622071
debugError(`Channel setup failed: ${e.message}`, e);
20632072
setStatus(e.message || "Channel setup failed", STATUS_COLORS.error);
2073+
state.disconnectReason = "error"; // Mark as error disconnect
20642074
}
20652075
});
20662076

20672077
conn.on("disconnected", () => {
20682078
debugLog("BLE disconnected event fired");
2069-
setStatus("Disconnected", STATUS_COLORS.error);
2079+
2080+
// Only set "Disconnected" status for normal disconnections
2081+
// Preserve error messages (app_down, capacity_full, error) instead of overwriting
2082+
if (state.disconnectReason === "normal" || state.disconnectReason === null || state.disconnectReason === undefined) {
2083+
setStatus("Disconnected", STATUS_COLORS.error);
2084+
} else {
2085+
debugLog(`Preserving disconnect status for reason: ${state.disconnectReason}`);
2086+
}
2087+
20702088
setConnectButton(false);
20712089
deviceInfoEl.textContent = "—";
20722090
state.connection = null;
20732091
state.channel = null;
20742092
state.devicePublicKey = null; // Clear public key
2093+
state.disconnectReason = null; // Reset disconnect reason
20752094
stopAutoPing(true); // Ignore cooldown check on disconnect
20762095
enableControls(false);
20772096
updateAutoButton();
@@ -2105,6 +2124,12 @@ async function disconnect() {
21052124
}
21062125

21072126
connectBtn.disabled = true;
2127+
2128+
// Set disconnectReason to "normal" if not already set (for user-initiated disconnects)
2129+
if (state.disconnectReason === null || state.disconnectReason === undefined) {
2130+
state.disconnectReason = "normal";
2131+
}
2132+
21082133
setStatus("Disconnecting", STATUS_COLORS.info);
21092134

21102135
// Release capacity slot if we have a public key
@@ -2147,6 +2172,7 @@ async function disconnect() {
21472172
} catch (e) {
21482173
debugError(`BLE disconnect failed: ${e.message}`, e);
21492174
setStatus(e.message || "Disconnect failed", STATUS_COLORS.error);
2175+
state.disconnectReason = "error"; // Mark as error disconnect
21502176
} finally {
21512177
connectBtn.disabled = false;
21522178
}

0 commit comments

Comments
 (0)