Maestro-first AAOS radio regression flows for BMW iDrive racks.
- Navigates to Radio reliably (Home -> Media DET -> Source check -> Radio).
- Applies deterministic Radio preconditions from Settings.
- Opens All stations and selects station robustly (label/frequency primary, index fallback).
- Verifies backend playback truth via local control server (
http://127.0.0.1:4567). - Exposes a live local dashboard + persisted audit for run observability.
This repo does not infer platform from YAML tags:. The platform comes from the flow path you explicitly run.
- IDC23
- testcase flow:
flows/idc23/testcases/<CASE_ID>/idc23.yaml - Studio flow:
flows/idc23/testcases/<CASE_ID>/idc23.studio.yaml - optional demo wrapper layer:
flows/idc23/demo/IDC23DEV-*.yaml
- testcase flow:
- IDCEVO
- testcase flow:
flows/idcevo/testcases/<CASE_ID>/idcevo.yaml - Studio flow:
flows/idcevo/testcases/<CASE_ID>/idcevo.studio.yaml
- testcase flow:
- G70
- does not use the same single-file
<platform>.studio.yamlpattern - it is structured as multi-device side flows under
flows/g70/ - examples are
deviceA.yaml/deviceB.yamlor role-based entrypoints such ascde.yaml,rse.yaml,hu.yaml
- does not use the same single-file
Practical rule:
- run an IDC23 file for IDC23
- run an IDCEVO file for IDCEVO
- run a G70 file for G70
tags: are useful for organization, search, and demo labeling, but the runners route by the target file path, not by tags.
From Radio:
- Open Settings.
- Ensure
Switch automatically to full screen modeis OFF. - Open
Radio settings. - Ensure sorting is
Alphabetically. - Ensure
Radio infois OFF. - Close Radio settings.
- Close Settings.
Primary + fallback strategy:
- Primary: if
MAESTRO_STATION_TARGETis provided, flow scrolls until target text is visible and taps it. - Fallback: deterministic index-based tap after page scroll calculation.
Files:
- Script:
scripts/maestro/pick_random_station.js - Flow:
flows/subflows/tap_random_all_stations_entry.yaml
MAESTRO_RAND_MAX_INDEXcontrols random absolute max index.- Default:
5 - Supported max:
24(5 pages x 5 visible rows)
- Default:
FIXED_INDEX(optional) forces a deterministic absolute index for repro/debug.
Flow: flows/subflows/verify_radio_backend.yaml
Strict assertions (when backend check runs):
ok == truemedia.playing == trueaudio.audioFocus == truemedia.package == com.bmwgroup.apinext.tunermediaservice
Skip behavior:
- Control server unavailable -> check marked skipped.
- By default skipped check fails the flow (strict mode).
- Set
MAESTRO_RADIO_ALLOW_SKIP=trueonly for explicit UI-only runs.
Server:
scripts/control_server/server.js- auto-start helper:
scripts/control_server/ensure_server.bat
Main endpoints:
GET /(service info)GET /dashboard(live HTML dashboard)GET /healthGET /radio/lastGET /radio/probeGET /audit?limit=20(in-memory)GET /audit/file?limit=50(persisted tail)GET /audit/file/raw?limit=500(download JSONL)POST /radio/checkPOST /inject/swagPOST /inject/bimPOST /ehh/set
The dashboard combines:
- backend media/audio verdict (
dumpsys) - UI station/band parsing from
uiautomatorXML - device identity from
adb devices -l
Persisted audit file:
artifacts/control_server_audit.jsonl
Per-check artifacts include:
backend_verdict.jsondumpsys_audio.txtdumpsys_media_session.txtcurrent_user.txtui_dump.xml(when available)ui_dump_debug.txt
All runners call:
scripts/maestro/run_with_artifacts.ps1
Artifacts path:
artifacts/runs/<timestamp>/<flow_name>/debugartifacts/runs/<timestamp>/<flow_name>/outputartifacts/runs/<timestamp>/<flow_name>/videos/<flow_name>.mp4artifacts/runs/<timestamp>/<flow_name>/record_debug
run_single_flow.bat <DEVICE_ID> <FLOW_PATH>run_demo_suite.bat <DEVICE_ID>run_suite.bat <DEVICE_ID>run_lightning_demo.bat <DEVICE_ID>This repo supports a host-side STR cycle via Tool64Cli.exe user actions:
- Sequence:
PAD -> WOHNEN -> PARKING -> sleep(180s) -> WOHNEN -> PAD - Default EDIABAS path:
C:\EC-Apps\EDIABAS\BIN - Default action names expected in Tool64 GUI:
SET_PADSET_WOHNENSET_PARKING
Run directly:
python scripts\ediabas_str_cycle.py --ediabas-bin "C:\EC-Apps\EDIABAS\BIN"Run directly (Node.js, same CLI flags):
node scripts\ediabas_str_cycle.js --ediabas-bin "C:\EC-Apps\EDIABAS\BIN"JS-first sidecar mode (direct EDIABAS API via pydiabas, no Tool64 actions):
node scripts\ediabas_str_cycle_sidecar.js --str-seconds 180 --settle-seconds 2Sidecar dependency setup (recommended):
- Install 32-bit Python (required by EDIABAS
api32.dll). - Install sidecar dependency:
C:\Path\To\Python32\python.exe -m pip install -r scripts\requirements-pydiabas-sidecar.txt- Point runner to 32-bit Python:
set PYDIABAS_PYTHON32=C:\Path\To\Python32\python.exeSidecar diagnose/probe:
node scripts\ediabas_str_cycle_sidecar.js --diagnose --probe --probe-ecu TMODE --probe-job INFOStart sidecar HTTP service explicitly (optional):
%PYDIABAS_PYTHON32% scripts\ediabas_pydiabas_sidecar.py serve --host 127.0.0.1 --port 8777Auto mode behavior:
--mode auto(default): triesTool64Clifirst, then falls back totool32if available.--mode tool64cli: force Tool64 user-action execution.--mode tool32: force direct Tool32 job execution.
Force Tool32 mode (legacy direct jobs):
python scripts\ediabas_str_cycle.py --mode tool32 --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --tool32-prg IPB_APP1.prg --tool32-job STEUERN_ROUTINE --tool32-arg-pad "ARG;ZUSTAND_FAHRZEUG;STR;0x07" --tool32-arg-wohnen "ARG;ZUSTAND_FAHRZEUG;STR;0x05" --tool32-arg-parking "ARG;ZUSTAND_FAHRZEUG;STR;0x01"Or via wrapper:
scripts\run_action.bat ediabas-str --ediabas-bin "C:\EC-Apps\EDIABAS\BIN"Or via wrapper (Node.js):
scripts\run_action.bat ediabas-str-js --ediabas-bin "C:\EC-Apps\EDIABAS\BIN"Or via wrapper (Node.js sidecar):
scripts\run_action.bat ediabas-str-js-sidecar --str-seconds 180 --settle-seconds 2Direct API mode (experimental, no Tool64 user actions required):
node scripts\ediabas_str_cycle_api.js --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --str-seconds 180 --settle-seconds 2Wrapper form:
scripts\run_action.bat ediabas-str-js-api --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --str-seconds 180 --settle-seconds 2Direct API diagnose/probe:
node scripts\ediabas_str_cycle_api.js --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --diagnose --probe --probe-ecu TMODE --probe-job INFONotes for direct API mode:
- Uses
scripts/ediabas_api32_job.ps1bridge with calls toapi32.dll(EDIABAS API). - Targets 32-bit API loading via x86 PowerShell path when available.
- Keep Tool64 action mode as fallback if API bridge cannot be initialized on a rack.
Customize timing:
python scripts\ediabas_str_cycle.py --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --str-seconds 180 --settle-seconds 2 --retries 1Artifacts are written under:
artifacts/ediabas/str_cycle_<timestamp>/- Includes per-step Tool64 logs and
ediabas_str_audit.jsonl
If Tool64 CLI fails:
- Re-run with
--mode tool32on racks wheretool32.exeis available. - Check
ediabas_str_audit.jsonlto see which engine was used per step (tool64cliortool32) and exact return codes.
Tool64 troubleshooting (without Tool32):
python scripts\ediabas_str_cycle.py --mode tool64cli --ediabas-bin "C:\EC-Apps\EDIABAS\BIN" --diagnose --probe-action SET_PADThis writes:
diagnose_report.txtwith binary detection,--helpresult, and probe-action result.diagnose_probe_action.logwith probe action command output.
Use this to confirm if failures are due to missing action names, runtime path/dependency issues, or rack-specific Tool64 CLI behavior.
Flow action marker support:
- Add this in a Maestro YAML comment to run STR as host action:
# ACTION: ediabas-str --ediabas-bin C:\EC-Apps\EDIABAS\BIN --str-seconds 180# ACTION: ediabas-str-js --ediabas-bin C:\EC-Apps\EDIABAS\BIN --str-seconds 180# ACTION: ediabas-str-js-api --ediabas-bin C:\EC-Apps\EDIABAS\BIN --str-seconds 180# ACTION: ediabas-str-js-sidecar --str-seconds 180
Node/Python parity:
scripts/ediabas_str_cycle.jsintentionally supports the same flags asscripts/ediabas_str_cycle.pyfor zero-friction migration.
Dependency governance:
pydiabasis consumed as an external dependency for the sidecar and acknowledged inTHIRD_PARTY_NOTICES.md.- Raw downloaded package folders are ignored via
.gitignoreto avoid accidental vendoring.
End-to-end PoC runner:
scripts/g70_orchestrator.ps1- config:
scripts/g70_orchestrator.targets.json - docs:
docs/G70_MULTI_DEVICE_POC.md
Run:
powershell -ExecutionPolicy Bypass -File scripts\g70_orchestrator.ps1It generates per-run JSON/HTML/ZIP artifacts under:
artifacts/g70_orchestrator/<runId>/
- Case list index:
flows/idc23/testcases/_INDEX.txt - Case details:
flows/idc23/README.md - Per-case demo files (IDCEVODEV-style flat files):
flows/idc23/demo/IDC23DEV-*.yaml - Demo index:
flows/idc23/demo/_INDEX.txt - Master demo flow:
flows/idc23/demo/IDC23DEMO-900001__prt_pdf_full_suite.yaml - Run one case (CLI):
.\scripts\run-idc23-e2e-poc.ps1 -CaseId "ABPI-671618" -DeviceId "<IDC23_SERIAL>"
- Run full IDC23 PDF demo orchestration (single entry flow):
run_idc23_demo_suite.bat <IDC23_SERIAL>
- Studio prep helper:
.\scripts\oneclick-idc23-studio.ps1 -CaseId "ABPI-671618"
Storage optimization for pass runs:
- Set
MAESTRO_KEEP_EVIDENCE_ON_PASS=false(global runner) - Or use
-PruneEvidenceOnPassinrun-idc23-e2e-poc.ps1
Default workspace config keeps artifacts in repo:
config.yaml.maestro/config.yaml
Both point to:
artifacts/maestro_studio