-
-
Notifications
You must be signed in to change notification settings - Fork 960
Improve msp send #4510
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Improve msp send #4510
Conversation
WalkthroughThe changes introduce a comprehensive suite of debugging and stress-testing tools for the MSP (Multiwii Serial Protocol) JavaScript implementation. This includes real-time queue monitoring, a visual debug dashboard, and a robust stress test framework. The MSP queue logic was simplified to use a fixed timeout. Conditional dynamic loading of debug tools was added for development environments, and browser compatibility checks now recognize test environments. Extensive documentation for the new debug tools was also added. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainJS
participant DebugTools
participant Dashboard
participant QueueMonitor
participant StressTest
User->>MainJS: Load application
MainJS->>DebugTools: (If dev) Dynamically import debug tools
DebugTools->>QueueMonitor: Initialize and start monitoring
DebugTools->>Dashboard: Initialize dashboard UI
DebugTools->>StressTest: Initialize stress test module
User->>Dashboard: Toggle dashboard (keyboard shortcut)
Dashboard->>QueueMonitor: Request queue metrics and alerts
Dashboard->>StressTest: Run stress test (on user action)
StressTest->>QueueMonitor: Collect metrics during test
QueueMonitor-->>Dashboard: Send updated metrics/alerts
Dashboard-->>User: Display real-time queue status, alerts, and test results
sequenceDiagram
participant MSP
participant QueueMonitor
participant StressTest
MSP->>QueueMonitor: send_message (hooked)
QueueMonitor->>MSP: Track request start
MSP->>QueueMonitor: _dispatch_message/_removeRequestFromCallbacks (hooked)
QueueMonitor->>MSP: Track request completion/failure
StressTest->>MSP: Send test requests (various scenarios)
MSP->>QueueMonitor: All requests monitored for metrics/alerts
StressTest->>QueueMonitor: Retrieve metrics for reporting
sequenceDiagram
participant User
participant MSPTestRunner
participant QueueMonitor
participant StressTest
participant Dashboard
User->>MSPTestRunner: Run test/help/monitor command
MSPTestRunner->>QueueMonitor: Start/stop monitor, get status
MSPTestRunner->>StressTest: Run specific/full test suite
MSPTestRunner->>Dashboard: Show/hide dashboard
MSPTestRunner-->>User: Log results, show dashboard, print help
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🔇 Additional comments (9)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
src/js/msp.js (1)
402-413
:⚠️ Potential issue
_validateSendMessage
ignoresdoCallbackOnError
flagError-side invocation of
callback_msp
is unconditional. That breaks the original contract implied by thedoCallbackOnError
parameter and can trigger “double callbacks” or resolve aPromise
that expected an actual response.-_validateSendMessage(code, callback_msp) { +_validateSendMessage(code, callback_msp, doCallbackOnError = false) { … - if (callback_msp) { + if (doCallbackOnError && callback_msp) { callback_msp(); }You’ll have to forward the flag from
send_message
.
🧹 Nitpick comments (2)
src/js/msp.js (2)
423-431
: Unused field –callbackOnError
is never referenced
_createRequestObject
storescallbackOnError
, but no subsequent code reads it after the refactor. Either remove the property or reinstate the error-handling path.Eliminating dead fields simplifies debugging and reduces cognitive load.
457-467
: Aggressive timeout decay may under-shootMIN_TIMEOUT
this.timeout--
happens on every send, regardless of frequency, and can push the value belowMIN_TIMEOUT
whentimeout
has already been clamped lower elsewhere.-if (this.timeout > this.MIN_TIMEOUT) { - this.timeout--; -} +this.timeout = Math.max(this.MIN_TIMEOUT, this.timeout - 1);A simple guard prevents negative or sub-minimum timeouts.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/js/msp.js
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/js/msp.js (2)
src/js/serial.js (2)
serial
(364-364)serial
(364-364)src/js/gui.js (1)
GUI
(484-484)
🔇 Additional comments (1)
src/js/msp.js (1)
415-418
: Duplicate detection is too coarse
_isDuplicateRequest
only checks equality ofcode
; it ignores the payload (data
).
Two requests with the same MSP code but different parameters will be treated as duplicates and the second payload may never be transmitted.Consider comparing a
(code, dataHash)
tuple or always sending whendataLength > 0
(even if duplicate).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/js/msp.js (3)
390-398
: Unused allocation for duplicates
requestObj
is instantiated even when the call is considered a duplicate and then discarded. This happens on every duplicate invocation and can become a noticeable GC hot-spot under heavy traffic.Move the allocation inside the
if (!isDuplicateRequest)
block so it is only created when needed.
445-456
: Timer remains referenced after giving up – clear it to aid GCWhen
MAX_RETRIES
is exceeded the function bails out but does notclearTimeout(requestObj.timer);
.
While the timer has already fired, keeping the handle prevents some JS engines from reclaiming it promptly.if (requestObj.attempts >= this.MAX_RETRIES) { console.error(`MSP: Request ${requestObj.code} exceeded max retries (${this.MAX_RETRIES}), giving up`); - // Remove from callbacks to prevent memory leak + clearTimeout(requestObj.timer); // 💡 explicit cleanup + // Remove from callbacks to prevent memory leak this._removeRequestFromCallbacks(requestObj);
411-413
: Adaptive back-off step might starve high-latency links
this.timeout
is decreased by a fixed 5 ms on every successful send. On slow links (e.g. Bluetooth) this can quickly shrink below the real RTT, leading to unnecessary retries. Consider decaying by a percentage (e.g.timeout *= 0.9
) or pinning a lower bound based on recent RTT measurements instead of a constant 5 ms.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/js/msp.js
(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/js/msp.js (3)
src/js/serial.js (2)
serial
(364-364)serial
(364-364)src/js/data_storage.js (1)
CONFIGURATOR
(7-40)src/js/gui.js (1)
GUI
(484-484)
src/js/msp.js
Outdated
}); | ||
}, this.timeout); | ||
// Track only the first outstanding request for a given code | ||
if (!isDuplicateRequest) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if this is the reason for missing events? e.g. motor slider getting "stuck" on old values even if the slider got pulled all the way down ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - see next commit - not sure if enough - or different from master - at least seems more stable - no longer locking up on SPBEF7V3 for the moment as it does on master.
eb77f13
to
4fcad77
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/js/msp.js (1)
399-420
:⚠️ Potential issueDuplicate requests silently drop callbacks
When
isDuplicateRequest
istrue
, the newcallback_msp
is not stored anywhere, so callers issuing concurrent identical requests will never be notified.
This regresses previous behaviour and breaks APIs that rely on per-call completion.Quick remedy: attach additional callbacks to the existing request object instead of discarding them.
-const isDuplicateRequest = this.callbacks.some((instance) => instance.requestKey === requestKey); +const existingReq = this.callbacks.find((i) => i.requestKey === requestKey); +const isDuplicateRequest = Boolean(existingReq); … -if (!isDuplicateRequest) { +if (!isDuplicateRequest) { this._setupTimeout(requestObj, bufferOut); this.callbacks.push(requestObj); +} else if (callback_msp) { + // fan-out: queue extra callback(s) on the first request + (existingReq.extraCallbacks ??= []).push(callback_msp); }And, when the response arrives, invoke
extraCallbacks
as well.
🧹 Nitpick comments (4)
src/js/msp.js (4)
376-389
: Hash function may collide & yield negative keys
_createRequestKey
uses a simple 32-bit rolling hash that can:
- Produce the same hash for different payloads (higher collision risk on large traffic).
- Return negative numbers, generating keys like
123:-842150451
which are harder to eyeball/debug.Consider switching to a safer deterministic scheme, e.g. CRC-32 or base64 of the first 4 bytes plus
length
, to lower collision odds and keep keys human-readable.
421-428
: Inefficient duplicate scan — O(N) each call
this.callbacks.some()
does a linear search every timesend_message
is invoked.
WithMAX_QUEUE_SIZE
already tracked, switching to aMap<requestKey, requestObj>
would give O(1) look-ups and simplify removal logic.
433-438
: Timer handle lost if_setupTimeout
is called twice
_setupTimeout
overwritesrequestObj.timer
without clearing a possibly existing one.
Although current flow prevents re-entrance, guarding against future changes is cheap:+if (requestObj.timer) { + clearTimeout(requestObj.timer); +} requestObj.timer = setTimeout(() => { this._handleTimeout(requestObj, bufferOut); }, this.TIMEOUT);
439-472
: Retry path never resetsstart
— metrics become meaningless
requestObj.start
is set once insend_message
but never updated on retries, so any later duration calculations accumulate total wall-time, not per-attempt latency.Either reset
start
inside_handleTimeout
before re-arming the timer or drop it altogether if no longer used.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/js/msp.js
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/js/msp.js (2)
src/js/serial.js (2)
serial
(364-364)serial
(364-364)src/js/data_storage.js (1)
CONFIGURATOR
(7-40)
🔇 Additional comments (1)
src/js/msp.js (1)
69-73
:✅ Verification successful
Confirm removal of legacy
this.timeout
referencesYou have introduced a fixed
TIMEOUT
constant but removed the old adaptivethis.timeout
.
Please grep the rest of the file / project for stalethis.timeout
usages to avoid undefined-property bugs at runtime.
🏁 Script executed:
#!/bin/bash # Find any remaining references to the old timeout field rg --line-number $'this\\.timeout'Length of output: 665
No stale
this.timeout
references foundA full‐repo search for
this.timeout
only returns occurrences ofthis.timeout_array
insrc/js/gui.js
, not the legacythis.timeout
property. There are no remaining direct references to the removed adaptive timeout field—this concern can be closed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/js/msp.js (1)
482-491
:_removeRequestFromCallbacks
leaves Map/key tracking unresolvedIf you adopt the
Map
optimisation above, ensure this method also deletes therequestKey
entry to keep the structures in sync.
🧹 Nitpick comments (4)
src/js/msp.js (4)
69-73
: Expose retry parameters instead of hard-coding them
MAX_RETRIES
,MAX_QUEUE_SIZE
, andTIMEOUT
are baked into the module, making it impossible to tune behaviour from the outside (e.g. per-board, per-environment, unit-tests). Consider reading them fromCONFIGURATOR
, a constructor argument, or at least exporting setters.
399-420
: Duplicate check performsO(n)
scans on every call
this.callbacks.some(...)
linearly scans the queue. Under heavy traffic (e.g. telemetry floods) the cost grows quadratically.Two easy wins:
- Keep a
Map<requestKey, requestObj>
to getO(1)
look-ups and removals.- Build
bufferOut
after the duplicate check to avoid unnecessary encoding work when the request is dropped.
433-438
: Timer double-cleared – harmless but needless
_handleTimeout
callsclearTimeout(requestObj.timer)
(l.464) and_removeRequestFromCallbacks
does the same. The second call is redundant and can be omitted to save a micro-op.
439-480
: Constant timeout may hammer dead linksRetries fire every fixed
TIMEOUT
ms. On an unplugged device this means 10 exact re-transmits per second, wasting bandwidth and log space.
An exponential back-off (e.g.TIMEOUT * 2 ** attempts
) curbs network noise and still converges quickly when the link is restored.
🛑 Comments failed to post (1)
src/js/msp.js (1)
376-389: 🛠️ Refactor suggestion
_createRequestKey
collision risk & signed-shift bugThe DJB-style hash on a
Uint8Array
will inevitably collide for different payloads and, because& 0xffffffff
yields a signed 32-bit value, the string key can even become negative.
A wrong “duplicate” classification silently drops tracking / retries.- let hash = 0; - for (const byte of data) { - hash = ((hash << 5) - hash + byte) & 0xffffffff; - } - return `${code}:${hash}`; + // Use a stable unsigned hash (FNV-1a) to minimise collisions + let hash = 2166136261 >>> 0; + for (const byte of data) { + hash ^= byte; + hash = Math.imul(hash, 16777619) >>> 0; + } + return `${code}:${hash.toString(16)}`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// Helper function to create a unique key for request identification _createRequestKey(code, data) { if (!data || data.length === 0) { return `${code}:empty`; } // Use a stable unsigned hash (FNV-1a) to minimise collisions let hash = 2166136261 >>> 0; for (const byte of data) { hash ^= byte; hash = Math.imul(hash, 16777619) >>> 0; } return `${code}:${hash.toString(16)}`; },
🤖 Prompt for AI Agents
In src/js/msp.js around lines 376 to 389, the _createRequestKey function uses a DJB-style hash that can produce collisions and negative values due to signed 32-bit shifts. To fix this, replace the hash calculation with a more robust hashing method that avoids collisions and ensures the hash is always unsigned and positive. For example, use a standard hashing library or implement a non-signed hash function that produces a unique, non-negative key string for the given data.
src/js/msp.js
Outdated
} | ||
// Create unique key combining code and data | ||
const requestKey = this._createRequestKey(code, data); | ||
const isDuplicateRequest = this.callbacks.some((instance) => instance.requestKey === requestKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not return here if a dupe is detected ? saves your the conditions below. looks like the code is not following "one return per function" convention anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and, why not "rate-limit" the events from sliders at the source ? i bet there are different event types that need different handling anyways.... like those motor sliders, where probably first and last event is very important, but all events in between can be lost without any noticeable effect for the user, but then there are events that cannot be lost, like transmission of cli stuff ?
src/js/msp.js
Outdated
this._setupTimeout(requestObj, bufferOut); | ||
this.callbacks.push(requestObj); | ||
} | ||
|
||
this.callbacks.push(obj); | ||
|
||
// always send messages with data payload (even when there is a message already in the queue) | ||
if (data || !requestExists) { | ||
if (this.timeout > this.MIN_TIMEOUT) { | ||
this.timeout--; | ||
} | ||
|
||
// Send message if it has data or is a new request | ||
if (data || !isDuplicateRequest) { | ||
serial.send(bufferOut, (sendInfo) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(note the line range if this comment)
i would probably start the timeout and call send only if the queue is empty, or if the previous "send" succeeded?
otherwise the buffers of the serial protocols are immediately filled and can overflow
src/js/msp.js
Outdated
); | ||
|
||
// Check if max retries exceeded OR queue is too large | ||
if (requestObj.attempts >= this.MAX_RETRIES || this.callbacks.length > this.MAX_QUEUE_SIZE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would perform the queue size check prior to insertion of the objects, in the send_message function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
src/js/msp.js (4)
69-73
: Freeze or namespace retry-config constants to prevent accidental mutationDefining
MAX_RETRIES
,MAX_QUEUE_SIZE
andTIMEOUT
directly on the mutableMSP
object means any consumer can overwrite them at runtime:MSP.TIMEOUT = 1; // 💥If you really want them tweakable, expose an explicit setter.
Otherwise, lock them down:- MAX_RETRIES: 10, - MAX_QUEUE_SIZE: 50, - TIMEOUT: 1000, + MAX_RETRIES: 10, + MAX_QUEUE_SIZE: 50, + TIMEOUT: 1000, } + +Object.freeze(MSP); // or freeze only MSP.retryConfig sub-object
376-389
: Hashing scheme is fragile & collision-prone
_createRequestKey
builds a 32-bit additive hash; for large or similar payloads collisions are easy, producing false “duplicates”.
Additionallyhash
may end up negative, so keys like42:-123
and42:327375
look different but are produced from different sessions of the same data length.Consider:
- Use a stable digest (e.g. DJB2, MurmurHash) or
crypto.subtle.digest('SHA-1', data)
when available.- Fall back to
btoa(String.fromCharCode(...data))
for short payloads.- At minimum,
>>> 0
to keep the value unsigned.
421-428
: Guardcallback_sent
with a functional check
promise()
passesfalse
, socallback_sent()
may be a boolean.
A trivial typeof guard avoids accidentalfalse is not a function
mistakes if the signature changes upstream.-if (sendInfo.bytesSent === bufferOut.byteLength && callback_sent) { +if (sendInfo.bytesSent === bufferOut.byteLength && typeof callback_sent === "function") { callback_sent(); }
479-489
: O(N²) removal can hurt with large queues
indexOf
+splice
is fine for the 50-item cap, but if the limit is raised later it becomes quadratic.
Storing callbacks in aMap<requestKey, requestObj>
would give O(1) insert/remove/lookup, simplify duplicate handling, and eliminate linear scans elsewhere.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/js/msp.js
(2 hunks)
🔇 Additional comments (2)
src/js/msp.js (2)
433-438
: Timeout set-up looks good
_setupTimeout
is concise and centralises timer arming – nice.
439-477
: Retry handler: no back-off & relies onsendInfo.bytesSent
- A fixed 1 s retry interval can hammer sluggish links. Consider exponential back-off or
TIMEOUT * (1 + attempts)
to avoid congestion.- If the serial driver does not populate
bytesSent
,sendInfo.bytesSent === bufferOut.byteLength
evaluatesfalse
⇒ the request aborts immediately. Validate field presence or fall back to truthiness.- if (sendInfo.bytesSent === bufferOut.byteLength) { + if (!sendInfo || sendInfo.bytesSent === undefined || sendInfo.bytesSent === bufferOut.byteLength) {
- You re-assign
requestObj.timer
but never clear it inside_handleTimeout
.
Although the fired timer auto-invalidates, explicitlyclearTimeout(requestObj.timer)
before re-arming removes any doubt.
checking the coderrabbit "nitpicks"? i'm finding them useful outside of this project. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (8)
src/js/msp/MSP_DEBUG_README.md (5)
36-44
: Fix inconsistent import paths in documentationThe import paths shown in the examples are inconsistent. In line 39, you use
'./src/js/msp_debug_tools.js'
, but in line 44, you use'./src/js/msp_debug_tools.js'
again. These paths should be consistent and relative to where the user would typically run the code.-import './src/js/msp_debug_tools.js'; +import './js/msp/msp_debug_tools.js';And for the console import:
-import('./src/js/msp_debug_tools.js'); +import('./js/msp/msp_debug_tools.js');
217-217
: Remove duplicate word "dashboard"There's a duplicated word in the keyboard shortcuts section.
-- `Ctrl+Shift+M` - Toggle debug dashboard +- `Ctrl+Shift+M` - Toggle debug dashboard - Dashboard is draggable and resizable
280-281
: Use consistent spelling for "autoloading"The compound word should be spelled as one word for consistency.
-### Auto-loading -The debug tools auto-load when `msp_debug_tools.js` is imported. +### Autoloading +The debug tools autoload when `msp_debug_tools.js` is imported.
317-325
: Add language identifier to code blockThe fenced code block should have a language specified for proper syntax highlighting.
-``` +```text src/js/ ├── msp_queue_monitor.js # Core monitoring functionality ├── msp_stress_test.js # Stress testing framework ├── msp_debug_dashboard.js # Visual dashboard UI ├── msp_test_runner.js # Console command interface └── msp_debug_tools.js # Integration and auto-loading--- `359-359`: **Add missing article for grammatical correctness** ```diff -Same as Betaflight Configurator project. +Same as the Betaflight Configurator project.
src/js/msp/msp_stress_test.js (3)
126-126
: Use optional chaining for cleaner codeReplace manual null checks with optional chaining for better readability and safety.
-const successful = results.filter((r) => r.status === "fulfilled" && !(r.value && r.value.error)).length; +const successful = results.filter((r) => r.status === "fulfilled" && !r.value?.error).length;And for line 134:
-peakQueueSize: (this.monitor.getStatus().metrics || {}).queuePeakSize ?? 0, +peakQueueSize: this.monitor.getStatus().metrics?.queuePeakSize ?? 0,Also applies to: 134-135
231-234
: Simplify null checks with optional chainingUse optional chaining for cleaner error checking.
-const successful = results.filter((r) => r.status === "fulfilled" && !(r.value && r.value.error)).length; +const successful = results.filter((r) => r.status === "fulfilled" && !r.value?.error).length; const duplicateErrors = results.filter( - (r) => r.status === "rejected" || (r.value && r.value.error && r.value.error.includes("duplicate")), + (r) => r.status === "rejected" || r.value?.error?.includes("duplicate"), ).length;
335-335
: Apply optional chaining consistently-const successful = results.filter((r) => r.status === "fulfilled" && !(r.value && r.value.error)).length; +const successful = results.filter((r) => r.status === "fulfilled" && !r.value?.error).length;
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/js/main.js
(2 hunks)src/js/msp.js
(3 hunks)src/js/msp/MSP_DEBUG_README.md
(1 hunks)src/js/msp/msp_debug_dashboard.js
(1 hunks)src/js/msp/msp_debug_tools.js
(1 hunks)src/js/msp/msp_queue_monitor.js
(1 hunks)src/js/msp/msp_stress_test.js
(1 hunks)src/js/msp/msp_test_runner.js
(1 hunks)src/js/utils/checkBrowserCompatibility.js
(1 hunks)test/js/msp/MSPHelper.test.js
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- test/js/msp/MSPHelper.test.js
- src/js/main.js
- src/js/utils/checkBrowserCompatibility.js
- src/js/msp/msp_debug_tools.js
- src/js/msp.js
- src/js/msp/msp_queue_monitor.js
🧰 Additional context used
🪛 LanguageTool
src/js/msp/MSP_DEBUG_README.md
[uncategorized] ~36-~36: The preposition “on” seems more likely in this position than the preposition “in”.
Context: ...he Debug Tools Include the debug tools in your page: ```javascript import './src...
(AI_EN_LECTOR_REPLACEMENT_PREPOSITION_IN_ON)
[uncategorized] ~60-~60: You might be missing the article “the” here.
Context: ...press Ctrl+Shift+M **Quick test of alert system:**
javascript MSPDebug.testAl...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~116-~116: A punctuation mark might be missing here.
Context: ... Description | |---------|-------------| | MSPDebug.setTestThresholds()
| Lower...
(AI_EN_LECTOR_MISSING_PUNCTUATION)
[uncategorized] ~124-~124: A punctuation mark might be missing here.
Context: ... Description | |---------|-------------| | MSPDebug.show()
| Show visual debug ...
(AI_EN_LECTOR_MISSING_PUNCTUATION)
[duplication] ~217-~217: Possible typo: you repeated a word.
Context: ...rtcuts - Ctrl+Shift+M
- Toggle debug dashboard - Dashboard is draggable and resizable ## Example ...
(ENGLISH_WORD_REPEAT_RULE)
[misspelling] ~280-~280: This word is normally spelled as one.
Context: ...Original MSP behavior is preserved ### Auto-loading The debug tools auto-load when `msp_deb...
(EN_COMPOUNDS_AUTO_LOADING)
[misspelling] ~281-~281: This word is normally spelled as one.
Context: ...erved ### Auto-loading The debug tools auto-load when msp_debug_tools.js
is imported. ...
(EN_COMPOUNDS_AUTO_LOAD)
[uncategorized] ~313-~313: You might be missing the article “the” here.
Context: ...n as documented - Auto-loading works in development environment ## File Structure ``` src...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~344-~344: You might be missing the article “the” here.
Context: ...ry MSPTestRunner.showDashboard()
from console - Check for CSS conflicts - Verify no p...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~353-~353: The preposition ‘to’ seems more likely in this position.
Context: ...ssTestclass 2. Update monitor metrics in
MSPQueueMonitor` 3. Extend dashboard U...
(AI_HYDRA_LEO_REPLACE_IN_TO)
[uncategorized] ~359-~359: You might be missing the article “the” here.
Context: ...this documentation ## License Same as Betaflight Configurator project.
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
🪛 markdownlint-cli2 (0.17.2)
src/js/msp/MSP_DEBUG_README.md
317-317: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
🪛 Biome (1.9.4)
src/js/msp/msp_stress_test.js
[error] 126-126: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 134-135: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 231-231: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 233-234: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 335-335: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (1)
src/js/msp/msp_debug_dashboard.js (1)
1165-1166
: Good use of optional chaining for MSPTestRunnerThe optional chaining correctly handles cases where MSPTestRunner might not be loaded yet.
|
Preview URL: https://cdbdda0f.betaflight-configurator.pages.dev |
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Refactor
Tests