# Configuration Resolution: What is read and when

This document explains how configuration is loaded, merged, and provided to tests and interfaces.

> Looking for the implementation deep-dive — merge semantics, type coercion,
> the forward-reference quirk in `EcuTestConfig`, and the PSU side-channel?
> See [`23_config_loader_internals.md`](23_config_loader_internals.md).

## Sources and precedence

From highest to lowest precedence:

1. In-code overrides (if `load_config(..., overrides=...)` is used)
2. Environment variable `ECU_TESTS_CONFIG` (absolute/relative path to YAML)
3. `config/test_config.yaml` (if present under the workspace root)
4. Built-in defaults

## Data model (dataclasses)

- `EcuTestConfig`
  - `interface: InterfaceConfig`
    - `type`: `mock`, `mum`, or `babylin` (deprecated)
    - `channel`: LIN channel index (0-based in SDK wrapper) — BabyLIN-specific (deprecated)
    - `bitrate`: LIN baudrate (e.g., 19200). The MUM uses this directly; BabyLIN typically takes it from the SDF (deprecated path)
    - `sdf_path`: Path to SDF file (BabyLIN; deprecated — required for typical BabyLIN operation)
    - `schedule_nr`: Schedule number to start on connect (BabyLIN; deprecated). `-1` = skip
    - `node_name`: Optional node identifier (informational)
    - `dll_path`, `func_names`: Deprecated legacy fields from the old ctypes adapter; not used with the SDK wrapper
    - `host`: MUM IP address (MUM-only). Required when `type: mum`
    - `lin_device`: MUM LIN device name (MUM-only, default `lin0`)
    - `power_device`: MUM power-control device (MUM-only, default `power_out0`)
    - `boot_settle_seconds`: Delay after MUM power-up before sending the first frame (default 0.5)
    - `frame_lengths`: Optional `{frame_id: data_length}` map for the MUM adapter to drive slave-published reads. Hex keys like `0x0A` are supported in YAML. When `ldf_path` is set, this acts as an override on top of LDF-derived lengths.
    - `ldf_path`: Optional path to a `.ldf` file. Tests can request the `ldf` fixture to obtain an `LdfDatabase` for per-frame `pack`/`unpack`; the MUM adapter additionally inherits frame lengths from the LDF. Relative paths resolve against the workspace root
  - `flash: FlashConfig`
    - `enabled`: whether to flash before tests
    - `hex_path`: path to HEX file
  - `power_supply: PowerSupplyConfig`
    - `enabled`: whether PSU features/tests are active
    - `port`: Serial device (e.g., `COM4`, `/dev/ttyUSB0`)
    - `baudrate`, `timeout`, `eol`: line settings (e.g., `"\n"` or `"\r\n"`)
    - `parity`: `N|E|O`
    - `stopbits`: `1` or `2`
    - `xonxoff`, `rtscts`, `dsrdtr`: flow control flags
    - `idn_substr`: optional substring to assert in `*IDN?`
    - `do_set`, `set_voltage`, `set_current`: optional demo/test actions

## YAML examples

Minimal mock configuration (default):

```yaml
interface:
  type: mock
  channel: 1
  bitrate: 19200
flash:
  enabled: false
```

Hardware via MUM (current default) — see also `config/mum.example.yaml`:

```yaml
interface:
  type: mum
  host: 192.168.7.2          # MUM IP address (USB-RNDIS default)
  lin_device: lin0           # MUM LIN device name
  power_device: power_out0   # MUM power-control device
  bitrate: 19200             # LIN baudrate
  boot_settle_seconds: 0.5   # Delay after power-up before first frame
  frame_lengths:
    0x0A: 8                  # ALM_Req_A
    0x11: 4                  # ALM_Status
flash:
  enabled: false
```

Hardware (BabyLIN SDK wrapper) configuration — DEPRECATED, prefer the MUM example above:

```yaml
interface:
  type: babylin           # deprecated
  channel: 0                    # 0-based channel index
  bitrate: 19200                # optional; typically driven by SDF
  node_name: "ECU_TEST_NODE"
  sdf_path: "./vendor/Example.sdf"
  schedule_nr: 0
flash:
  enabled: true
  hex_path: "firmware/ecu_firmware.hex"

Power supply configuration (either inline or merged from a dedicated YAML):

```yaml
power_supply:
  enabled: true
  port: COM4           # or /dev/ttyUSB0 on Linux
  baudrate: 115200
  timeout: 1.0
  eol: "\n"          # or "\r\n" if your device requires CRLF
  parity: N            # N|E|O
  stopbits: 1          # 1|2
  xonxoff: false
  rtscts: false
  dsrdtr: false
  idn_substr: OWON
  do_set: false
  set_voltage: 5.0
  set_current: 0.1
```
```

## Load flow

```text
tests/conftest.py: config() fixture
  → load_config(workspace_root)
    → check env var ECU_TESTS_CONFIG
    → else check config/test_config.yaml
    → else use defaults
  → convert dicts to EcuTestConfig dataclasses
  → provide to other fixtures/tests

Additionally, if present, a dedicated PSU YAML is merged into `power_supply`:

- Environment variable `OWON_PSU_CONFIG` (path to YAML), else
- `config/owon_psu.yaml` under the workspace root

This lets you keep machine-specific serial settings separate while still having
central defaults in `config/test_config.yaml`.
```

## How tests and adapters consume config

- `lin` fixture picks `mock`, `mum`, or `babylin` (deprecated) based on `interface.type`
- Mock adapter uses `bitrate` and `channel` to simulate timing/behavior
- MUM adapter uses `host`, `lin_device`, `power_device`, `bitrate`, `boot_settle_seconds`, and `frame_lengths` to open the MUM, set up the LIN bus, and power up the ECU on connect
- BabyLIN adapter (SDK wrapper, **DEPRECATED**) uses `sdf_path`, `schedule_nr`, `channel` to open the device, load the SDF, and start a schedule. `bitrate` is informational unless explicitly applied via commands/SDF. Selecting `interface.type: babylin` emits a `DeprecationWarning`.
- `flash_ecu` uses `flash.enabled` and `flash.hex_path`
- PSU-related tests or utilities read `config.power_supply` for serial parameters
  and optional actions (IDN assertions, on/off toggle, set/measure). The reference
  implementation is `ecu_framework/power/owon_psu.py`, with a hardware test in
  `tests/hardware/psu/test_owon_psu.py` and a quick demo script in `vendor/Owon/owon_psu_quick_demo.py`.

## Tips

- Keep multiple YAMLs and switch via `ECU_TESTS_CONFIG`
- Check path validity for `sdf_path` and `hex_path` before running hardware tests
- For the deprecated BabyLIN path only: ensure `vendor/BabyLIN_library.py` and the platform-specific libraries from the SDK are available on `PYTHONPATH`
- Use environment-specific YAML files for labs vs. CI
- For PSU, prefer `OWON_PSU_CONFIG` or `config/owon_psu.yaml` to avoid committing
  local COM port settings. Central defaults can live in `config/test_config.yaml`.
