32 Commits

Author SHA1 Message Date
7710dd34e8 update the install packages to copy the python site packages to venv 2026-05-08 19:10:22 +02:00
afd9da8206 docs: hardware test infrastructure, session-managed PSU, settle-then-validate
Documents the new layers introduced over the past several commits.

- docs/19_frame_io_and_alm_helpers.md (new): full reference for the
  FrameIO and AlmTester helpers — three access levels (high/mid/low),
  full API tables, fixture wiring, cookbook patterns, and §7
  describing the four-phase SETUP/PROCEDURE/ASSERT/TEARDOWN test
  pattern with the three template flavors plus a §7.4 link to the
  PSU+LIN template.

- docs/14_power_supply.md: rewritten and expanded.
    §3 cross-platform port resolution (Windows / WSL1 / WSL2 +
       usbipd-win / Linux native compatibility table)
    §4 auto-detection via idn_substr
    §5 session-managed power: contract for tests, must-not list,
       what changed in the existing tests
    §6 the settle-then-validate pattern: two-delays table (PSU
       bench-dependent vs ECU firmware-dependent), copy-paste
       example, tuning guidance for ECU_VALIDATION_TIME_S
    §6 PSU settling characterization (-m psu_settling)
    §7 library API reference table + safe_off_on_close
    §9 troubleshooting expanded with WSL2 usbipd-win + dialout

- docs/18_test_catalog.md: voltage-tolerance section refreshed for
  the settle-then-validate shape, new "Hardware – PSU settling
  (opt-in)" category, new §8 "Hardware-test infrastructure"
  documenting conftest.py, frame_io.py, alm_helpers.py,
  psu_helpers.py, and both templates.

- docs/05_architecture_overview.md: components list split into
  framework core / hardware test layer / artifacts. Mermaid diagram
  gained a Hardware-test helpers subgraph showing FrameIO,
  AlmTester, rgb_to_pwm, and the templates. Data/control flow
  summary describes the session-managed PSU and the helper layer.

- docs/15_report_properties_cheatsheet.md: PSU section split into
  per-test (function-scoped rp) and module-scoped (testsuite
  property) blocks; added psu_resolved_port, psu_resolved_idn,
  psu_settled_s, validation_time_s.

- docs/README.md: links to the new doc 19.

- README.md, TESTING_FRAMEWORK_GUIDE.md: project-structure trees
  expanded to show the full current layout — every file and
  directory under tests/hardware/ (conftest, helpers, templates,
  tests), tests/unit/, config/, docs/, scripts/, and vendor/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:02:42 +02:00
11b5402b14 tests/hardware: add copyable, heavily-commented test templates
Two starting-point files for new hardware tests. Leading underscore
in the filenames keeps pytest from collecting them.

- _test_case_template.py — for ALM_Node-touching MUM tests.
  Three flavors with full SETUP / PROCEDURE / ASSERT / TEARDOWN
  section markers:
    A) minimal: relies on the autouse _reset_to_off (LED OFF
       baseline) — no per-test setup/teardown
    B) with isolation: try/finally pattern for tests that mutate
       persistent ECU state (e.g. ConfigFrame)
    C) single-signal probe: fio.read_signal one-shot

  Inline comments explain pytest fundamentals (fixture, scope,
  autouse, yield, rp), the four-phase pattern, and the
  must/must-not contract.

- _test_case_template_psu_lin.py — for tests that drive the PSU
  AND observe the LIN bus (over/undervoltage tolerance, brown-out,
  supply transients). Three flavors:
    A) overvoltage: apply OV via apply_voltage_and_settle, single
       status read after validation hold, assert OverVoltage
    B) undervoltage: symmetric for UV
    C) parametrized voltage sweep
  Documents the three-layer safety guarantee (session
  safe_off_on_close / autouse _park_at_nominal / per-test
  try/finally) and the rule that tests never call set_output(False)
  or close() — the session fixture owns the PSU lifecycle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:02:13 +02:00
29a7a44c8b tests/hardware: settle-then-validate PSU helpers + voltage-tolerance tests
Voltage-changing tests can't sleep a fixed amount and assume the
rail is there — Owon settling is bench-dependent and typically
asymmetric (up-step ≠ down-step). New shared helpers and tests use
the rail's measured value to drive timing.

- tests/hardware/psu_helpers.py:
    wait_until_settled(psu, target_v, ...)
        polls measure_voltage_v() until within tol, returns
        (elapsed_s, trace) or (None, trace) on timeout
    apply_voltage_and_settle(psu, target_v, validation_time, ...)
        composite: set setpoint → wait until measured matches →
        sleep validation_time so the firmware-side observer can
        detect and republish status. Raises on settle timeout.
    downsample_trace, plus DEFAULT_VOLTAGE_TOL_V (0.10),
    DEFAULT_POLL_INTERVAL_S (0.05), DEFAULT_SETTLE_TIMEOUT_S (10.0),
    DEFAULT_VALIDATION_TIME_S (1.0).

- test_overvolt.py: voltage-tolerance suite. Each test (over,
  under, parametrized sweep) uses apply_voltage_and_settle for the
  procedure, the autouse _park_at_nominal fixture (also via the
  helper), and a single deterministic ALM_Status read after the
  validation hold instead of polling-the-bus.

- test_psu_voltage_settling.py: characterization test, opt-in via
  the new psu_settling marker. Walks four (start_v, target_v)
  transitions and records settling_time_s + voltage_trace per case.
  Values feed directly into test_overvolt's ECU_VALIDATION_TIME_S
  budgeting.

- pytest.ini:
    junit_family = legacy  → record_property() entries now actually
        appear in reports/junit.xml (the default xunit2 silently
        dropped them with a collect-time warning, breaking the
        conftest plugin's metadata round-trip)
    psu_settling marker registered

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:01:49 +02:00
eac662b139 tests/hardware: session-scoped PSU fixture so the bench stays powered
On benches where the Owon PSU powers the ECU, every per-file PSU
fixture that closed the port (sending 'output 0' on close) browned
out the bench between modules — every MUM test that ran after a
closed PSU connection failed with "ECU not responding".

New tests/hardware/conftest.py provides three session-scoped
fixtures:

- _psu_or_none: tolerant. Opens the Owon PSU once via resolve_port,
  parks at config.power_supply.set_voltage / set_current, enables
  output. Yields the live OwonPSU or None. Closes (with
  safe_off_on_close=True) at session end — the bench ends safely
  de-energized.

- _psu_powers_bench: autouse=True. Realizes _psu_or_none so even
  tests that don't request `psu` by name benefit from the
  session-level power-up. No-op if PSU isn't configured.

- psu: public. Skips cleanly when the PSU isn't reachable.

Contract for tests:
  - request `psu` if you need to read measurements or change voltage
  - restore nominal voltage in your finally block
  - MUST NOT call psu.set_output(False) (would brown out the bench)
  - MUST NOT call psu.close() (the session fixture owns it)

test_owon_psu.py becomes read-only:
  - removed the local module-scoped psu fixture
  - removed the set_output toggle (would have killed the session)
  - now validates IDN, output_is_on(), and parsed measurements
    against the always-on PSU. Renamed to
    test_owon_psu_idn_and_measurements to reflect the new shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:01:01 +02:00
f5a4ba532b tests/hardware: add FrameIO + AlmTester helper layer
Splits hardware-test concerns into two reusable modules and rebuilds
test_mum_alm_animation.py on top of them.

- frame_io.py — generic LDF-driven I/O class. Knows nothing about
  ALM. Three access levels:
    high: send/receive/read_signal by frame and signal name
    mid:  pack/unpack — bytes ↔ signals without I/O
    low:  send_raw/receive_raw — bypass the LDF entirely
  Plus introspection: frame, frame_id, frame_length. Frame lookups
  are cached per FrameIO instance.

- alm_helpers.py — ALM_Node domain helpers built on FrameIO.
  AlmTester class bound to (fio, nad) exposes:
    force_off, read_led_state, wait_for_state,
    measure_animating_window, assert_pwm_matches_rgb,
    assert_pwm_wo_comp_matches_rgb
  Plus pure utilities (ntc_kelvin_to_celsius, pwm_within_tol) and
  the LED-state / pacing / PWM-tolerance constants. PWM assertions
  use vendor/rgb_to_pwm.py (compute_pwm) at the runtime
  Tj_Frame_NTC temperature.

- test_mum_alm_animation.py rewritten:
    * fio + alm fixtures replace the previous dict-based _ctx
    * SETUP / PROCEDURE / ASSERT / TEARDOWN section markers
    * test_mode1_fade now wraps its ConfigFrame change in
      try/finally so EnableCompensation is restored even on
      assertion failure (was leaking state into later tests)
    * test_disable_compensation_pwm_wo_comp uses the four-phase
      pattern explicitly

Sibling imports work because pytest's default rootdir mode puts the
test file's directory on sys.path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:00:36 +02:00
c6d7669b90 power: cross-platform PSU port resolver, parsed numerics, safe-off
owon_psu.py upgrades (all backward-compatible):

- SerialParams.from_config() and OwonPSU.from_config() factories that
  translate the YAML power_supply block (parity 'N', stopbits 1.0)
  into pyserial constants — eliminates the boilerplate every test
  was duplicating.

- Parsed-numeric measurement helpers: measure_voltage_v(),
  measure_current_a(), output_is_on(). Tests can now assert on
  floats / bools instead of regex-ing strings.

- safe_off_on_close=True (new ctor kwarg, default on) — close()
  sends 'output 0' before closing the port. Last-ditch protection
  against leaving the bench powered on after an aborted test.
  Keyword-only so the historical positional ctor signature is
  preserved.

- Cross-platform port resolver: windows_com_to_linux,
  linux_serial_to_windows, candidate_ports, resolve_port. The
  resolver tries the configured port verbatim, then its
  cross-platform translation (COM7 ↔ /dev/ttyS6 on WSL1), then
  Linux USB-serial paths (/dev/ttyUSB*, /dev/ttyACM*), then a full
  scan_ports() with optional idn_substr filter. One bench config
  works on Windows, WSL1, WSL2 + usbipd-win, and native Linux.

- try_idn_on_port refactored to use OwonPSU internally, removing
  ~25 lines of duplicated serial-port plumbing.

ecu_framework/power/__init__.py re-exports the new helpers so tests
can do `from ecu_framework.power import resolve_port, ...`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:00:12 +02:00
079abc9356 vendor: add closed-form RGB→PWM calculator for ALM tests
Pure-Python port of the Input Sheet RGB→PWM pipeline (color management
+ luminance management + temperature compensation) used by the ALM
firmware. Exposes compute_pwm(r, g, b, temp_c) returning both the
non-compensated and the temperature-compensated 16-bit PWM tuples.

Imported by tests/hardware/alm_helpers.py to predict expected PWM
values from RGB inputs in PWM-validation assertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:59:31 +02:00
582764d410 Mark legacy BabyLIN adapter as deprecated across code and docs
The MUM (Melexis Universal Master) adapter is the current default; the
BabyLIN SDK adapter is retained only for backward compatibility with
existing rigs.

Code:
- Emit DeprecationWarning when BabyLinInterface is instantiated and
  when tests/conftest.py routes interface.type=='babylin' to it.
- Update module/class docstrings in ecu_framework/{__init__,config,
  lin/__init__,lin/babylin}.py to label BabyLIN-specific fields and
  paths as deprecated.

Config / scripts / pytest:
- pytest.ini: relabel the babylin marker as deprecated.
- config/{babylin.example,examples,test_config}.yaml: add deprecation
  banners and field comments.
- scripts/99-babylin.rules and scripts/pi_install.sh: annotate the
  udev-rule install block as legacy-only.

Documentation:
- TESTING_FRAMEWORK_GUIDE.md, docs/08_babylin_internals.md, and
  vendor/README.md: prepend explicit "DEPRECATED" banners.
- docs/{README,01,02,04,05,07,09,10,12,13,14,15,18,DEVELOPER_COMMIT_
  GUIDE}.md: relabel "legacy" to "deprecated" where babylin is
  mentioned, present MUM as the primary path, and steer new work
  toward the MUM examples.

No tests, configs, or modules were deleted; existing BabyLIN setups
keep working but now produce a clear DeprecationWarning at runtime.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:32:24 +02:00
d268d845ce add ldf parser 2026-04-29 00:56:07 +02:00
a10187844a add ldf parser 2026-04-29 00:55:53 +02:00
0656f3a0e1 update mum document 2026-04-28 23:47:17 +02:00
b8f52bea39 Add MUM support in the testing framework 2026-04-28 23:37:53 +02:00
58aa7350e6 Fix power supply control 2026-02-04 19:45:23 +01:00
528ab239dc FIXUP! rename the tryout script to quick demo 2025-10-24 23:58:38 +02:00
0a18d03d4f FIXUP! update project structure in the readme file 2025-10-24 23:39:09 +02:00
092767ab51 FIXUP! update architecture over view for the power supply integration 2025-10-24 23:28:46 +02:00
e552e9a8e9 Add Owon power supply library, and test cases 2025-10-24 23:24:54 +02:00
b988cdaae5 FIXUP! update documentation 2025-10-20 21:30:38 +02:00
73c5d044c0 FIXUP! update documentation 2025-10-20 21:29:36 +02:00
363cc2f361 FIXUP! update documentation 2025-10-20 21:27:57 +02:00
4364dc2067 FIXUP! update documentation 2025-10-20 21:25:47 +02:00
a0996e12c9 FIXUP! update documentation 2025-10-20 21:20:58 +02:00
93463789a5 FIXUP! update documentation 2025-10-20 20:54:40 +02:00
030a813177 FIXUP! fix diagrame parsing issue 2025-10-20 20:43:55 +02:00
ffe3f7afe3 FIXUP! fix diagrame parsing issue 2025-10-20 20:43:02 +02:00
16fc92cacd FIXUP! fix diagrame parsing issue 2025-10-20 20:41:32 +02:00
74e5f84239 FIXUP! update documentation 2025-10-20 20:41:04 +02:00
558c39de0a FIXUP! fix diagrame parsing issue 2025-10-20 20:37:41 +02:00
b918e0444b FIXUP! fix diagrame parsing issue 2025-10-20 20:34:50 +02:00
17ae041792 ECU framework: docs, reporting plugin (HTML metadata + requirements JSON + CI summary), .gitignore updates 2025-10-20 20:21:05 +02:00
88c28d4ab8 Initial commit 2025-10-15 23:59:51 +02:00