diff --git a/tunie/viewer/build_viewer.py b/tunie/viewer/build_viewer.py new file mode 100644 index 0000000..fcd30d4 --- /dev/null +++ b/tunie/viewer/build_viewer.py @@ -0,0 +1,98 @@ +"""Build a self-contained HTML viewer for the Triumph tuning project. + +Extracts TuneECU's editable-surface definitions (tunable parameters, table +axes, toggleable devices, live sensors, actuator tests) from the decompiled +APK resources, combines them with the already-extracted map catalogue +(maps.json), and embeds everything into a single double-click-to-open HTML file +with no server and no external dependencies. + +Usage: + python3 viewer/build_viewer.py \ + --arrays ../work/apktool_out/res/values/arrays.xml \ + --maps maps.json \ + --template viewer/template.html \ + --out viewer/tunie-viewer.html +""" + +from __future__ import annotations + +import argparse +import json +import re +from pathlib import Path + +# Resource arrays worth surfacing, with a friendly label and short note. +DEF_ARRAYS = { + "Parameters": ("Tunable parameters", "Single-value settings TuneECU can change."), + "title_axis": ("Table axes", "The axes every fuel/ignition map is built on."), + "Devices": ("Toggleable devices", "Emissions/hardware features that can be turned off."), + "eSensor": ("Live sensors", "Channels the ECU streams while running."), + "test_devices": ("Actuator tests", "Outputs TuneECU can command for bench testing."), + "reset_devices": ("Reset routines", "Adaptations/adjustments that can be reset."), + "ftrim_name": ("Fuel-trim tables", "Per-cylinder fuel trim table names."), + "ecu": ("ECU families", "Supported ECUs; the code after ':' is the type char."), +} + +# Devices/parameters directly relevant to this bike's planned mods. +MOD_TARGETS = {"SAI", "O2 Sensor", "O2 Sensor (2)", "Exhaust Valve", "Air Flap"} + + +def _extract_arrays(arrays_xml: Path) -> dict: + s = arrays_xml.read_text(encoding="utf-8") + + def arr(name: str) -> list[str] | None: + m = re.search( + rf']*>(.*?)', s, re.S + ) + if not m: + return None + return [ + re.sub(r"\s+", " ", i.strip().strip('"')) + for i in re.findall(r"(.*?)", m.group(1), re.S) + ] + + out = {} + for name, (label, note) in DEF_ARRAYS.items(): + items = arr(name) or [] + out[name] = { + "label": label, + "note": note, + "items": [{"i": i, "text": t} for i, t in enumerate(items) if t], + } + return out + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--arrays", required=True, type=Path) + ap.add_argument("--maps", required=True, type=Path) + ap.add_argument("--template", required=True, type=Path) + ap.add_argument("--out", required=True, type=Path) + args = ap.parse_args() + + defs = _extract_arrays(args.arrays) + maps = json.loads(args.maps.read_text(encoding="utf-8")) + + payload = { + "definitions": defs, + "maps": maps, + "modTargets": sorted(MOD_TARGETS), + "meta": { + "mapCount": len(maps), + "source": "TuneECU APK resources (arrays.xml) + maps.json", + }, + } + + template = args.template.read_text(encoding="utf-8") + blob = json.dumps(payload, separators=(",", ":")) + html = template.replace("/*__DATA__*/", blob) + + args.out.write_text(html, encoding="utf-8") + kb = len(html.encode("utf-8")) / 1024 + print(f"wrote {args.out} ({kb:.0f} KB, {len(maps)} maps, " + f"{sum(len(d['items']) for d in defs.values())} definition rows)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tunie/viewer/sample_table.bin b/tunie/viewer/sample_table.bin new file mode 100644 index 0000000..8b4747a Binary files /dev/null and b/tunie/viewer/sample_table.bin differ diff --git a/tunie/viewer/template.html b/tunie/viewer/template.html new file mode 100644 index 0000000..8443c8f --- /dev/null +++ b/tunie/viewer/template.html @@ -0,0 +1,279 @@ + + + + + +tunie — Triumph tuning viewer + + + +
+

tunie

+ +
+ +
+ +
+
+ + + + ★ My bike (Keihin · mechanical · Bonneville) + +
+ + + + + +
MapECUDetails
+
+ +
+

TuneECU's full editable surface, extracted from the APK. The + highlighted devices are the SAI / O2 / exhaust + items this project plans to delete.

+
+
+ +
+
Drop a map file here (.bin or Intel .hex) — or click to choose. + +
+ +

No dump yet? This becomes useful after tunie reads a ROM. + Meanwhile you can drop any TuneECU .hex map to eyeball its bytes, + and hand-locate tables by diffing two maps.

+
+ +
+ + + + + diff --git a/tunie/viewer/tunie-viewer.html b/tunie/viewer/tunie-viewer.html new file mode 100644 index 0000000..ae28a43 --- /dev/null +++ b/tunie/viewer/tunie-viewer.html @@ -0,0 +1,279 @@ + + + + + +tunie — Triumph tuning viewer + + + +
+

tunie

+ +
+ +
+ +
+
+ + + + ★ My bike (Keihin · mechanical · Bonneville) + +
+ + + + + +
MapECUDetails
+
+ +
+

TuneECU's full editable surface, extracted from the APK. The + highlighted devices are the SAI / O2 / exhaust + items this project plans to delete.

+
+
+ +
+
Drop a map file here (.bin or Intel .hex) — or click to choose. + +
+ +

No dump yet? This becomes useful after tunie reads a ROM. + Meanwhile you can drop any TuneECU .hex map to eyeball its bytes, + and hand-locate tables by diffing two maps.

+
+ +
+ + + + +