feat(parsers): add TunerStudio MSL (.msl) log support - #87
Merged
Merged
Conversation
Adds a parser for the tab-delimited legacy ASCII datalog TunerStudio writes as .msl, and that RealDash writes when logging a Speeduino over Bluetooth. Closes #86. The format is a header row, a units row, then tab-delimited data. That header/units pair is what makes detection unambiguous — several other formats also lead with a Time column, so requiring a time unit under it keeps the parser from claiming tab-delimited ECUMaster or generic Time-first exports. Detection runs after MegaSquirt and before ECUMaster in the text dispatch chain. Load-bearing behaviors, documented in CLAUDE.md: - Time scale is read from the units row, never assumed - Blank and non-numeric fields carry the last known value forward, which preserves column alignment for columns like RealDash's GPS Date - Clock columns (HH:MM, HH:MM:SS) become seconds since midnight so GPS Time plots as a channel - Times are forced monotonic across concatenated sessions - GPS Latitude/Longitude keep their exported names so the Track Map matches them Adds exampleLogs/msl/, a 2000-row excerpt of the log attached to #86, trimmed to keep the leading rows where the GPS has no fix yet.
Review pass on the new MSL parser. "NaN", "inf" and "-inf" all parse successfully as f64, so a logger writing one of those for a faulted sensor would put a non-finite value into channel data — which poisons the min/max legend cache and collapses the chart's auto-bounds. Those fields now carry the last known value forward, the same as a blank. Also relaxes the units-row check to accept an export that omits trailing empty units; the time unit under the Time column is what discriminates MSL from other tab-delimited Time-first formats, not the field count. Adds a regression test that walks every bundled example log and asserts the MSL detector claims none of them.
- Cargo.toml, README shield, JSON-LD softwareVersion, hero badge, and releaseNotes tag all move to 2.14.0 - What's New: TunerStudio MSL Imports card leads the grid - Supported ECUs: adds the TunerStudio MSL badge as New, demotes RaceChrono to supported - SEO: meta description, keywords, and JSON-LD description list MSL and RealDash logs - Sitemap lastmod refreshed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #86.
Adds a parser for the tab-delimited legacy ASCII datalog TunerStudio writes as
.msl. RealDash writes the same format when it logs a Speeduino over Bluetooth, which is the reporter's use case — cable-free logging with no conversion step.Format
Header row, units row, then tab-delimited data:
That header/units pair is what makes detection unambiguous. Several formats lead with a
Timecolumn; requiring a time unit (sec,s,ms, ...) underneath it is what keeps the parser off tab-delimited ECUMaster and genericTime-first exports. Detection runs after MegaSquirt (the comma-delimited TunerStudio CSV export) and before ECUMaster indispatch_text_content.Load-bearing behaviors
Documented in
CLAUDE.mdalongside the RaceChrono and Haltech contracts:GPS Dateas18.8.2026and leaves fields blank until the GPS gets a fix. Matcheshaltech.rsandecumaster.rs.GPS Timeplots as a channel instead of reading zero.NaN/infare treated as blank — both parse asf64and would otherwise poison the min/max legend cache and collapse the chart's auto-bounds.times.GPS Latitude/GPS Longitudekeep their exported names, sofind_gps_channelsmatches them and the Track Map works out of the box.Verification
Both logs attached to #86 parse end to end through the real dispatch chain:
datalog_2026-08-18_21-51-07.msl(3.6 MB)datalog_2026-08-22_15-17-40.msl(10.0 MB)30 tests: 17 unit, 13 integration. Includes a regression test that walks every bundled example log and asserts the MSL detector claims none of them, plus assertions that no existing text parser claims an MSL log.
cargo test387 + 269 + 55 + 36 + 13 passing,cargo fmt --all -- --checkclean,cargo clippy --all-targets -- -D warningsclean.Also in this PR
exampleLogs/msl/— a 2000-row excerpt of the log attached to [Feature]: Support .msl logs from RealDash/TunerStudio #86, trimmed to keep the leading rows where the GPS has no fix yet.msladded to the file-dialog extension filter