Hosam-Eldin Mostafa 90be834102 refactor: retire LIN API generator (move to deprecated/)
With AlmTester now the single contributor-facing API, the generator at
``scripts/gen_lin_api.py`` and its output at
``tests/hardware/_generated/`` have no live consumer — the previous
commit inlined the enum classes they used to provide into
``tests/hardware/alm_helpers.py``.

Moves both to ``deprecated/`` rather than deleting outright. The
deprecated layout is self-describing:

    deprecated/
      README.md          — retirement rationale + revival instructions
      gen_lin_api.py     — was scripts/gen_lin_api.py
      _generated/
        __init__.py
        lin_api.py       — last-emitted typed frame classes + IntEnums

A note in deprecated/README.md spells out the conditions that would
make reviving the generator worthwhile (a second ECU joins, the LDF
churns fast enough to make hand-syncing miss changes, mypy-in-CI gets
adopted) and the exact command to regenerate.

Docs:

- 22_generated_lin_api.md now leads with a retired-layer banner. The
  body is preserved as the design-of-record for the historical layer.
- 05_architecture_overview.md gets a refreshed "Test-side layering"
  Mermaid (AlmTester → FrameIO → LinInterface) plus a "retired layer"
  bullet pointing at deprecated/. The "Three independent entry points"
  section is annotated rather than removed — the gen_lin_api path
  there is now historical reference.

Verified: pytest --collect-only collects 87 tests; 40 unit + mock
tests still pass. The retirement is invisible to the live framework.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:24:12 +02:00

640 lines
17 KiB
Python

"""AUTO-GENERATED from 4SEVEN_color_lib_test.ldf
SHA256: dbb57be4b671
DO NOT EDIT — re-run: python scripts/gen_lin_api.py vendor/4SEVEN_color_lib_test.ldf
Generator version: 1
"""
from __future__ import annotations
from enum import IntEnum
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frame_io import FrameIO
# === Encoding types ========================================================
class Red:
"""Signal_encoding_types.Red (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'Red'
class Green:
"""Signal_encoding_types.Green (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'Green'
class Blue:
"""Signal_encoding_types.Blue (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'Blue'
class Intensity:
"""Signal_encoding_types.Intensity (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'Intensity'
class Update(IntEnum):
"""Signal_encoding_types.Update"""
IMMEDIATE_COLOR_UPDATE = 0x00
COLOR_MEMORIZATION = 0x01
APPLY_MEMORIZED_COLOR = 0x02
DISCARD_MEMORIZED_COLOR = 0x03
class Mode(IntEnum):
"""Signal_encoding_types.Mode (logical + physical)"""
IMMEDIATE_SETPOINT = 0x00
FADING_EFFECT_1 = 0x01
FADING_EFFECT_2 = 0x02
TBD_0X03 = 0x03
TBD_0X04 = 0x04
# physical_value 5..63 scale=1.0 offset=0.0 unit='Not Used' — pass int directly
class Duration:
"""Signal_encoding_types.Duration (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 0.2
OFFSET = 0.0
UNIT = 's'
class ModuleID:
"""Signal_encoding_types.ModuleID (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'ModuleID'
class NVMStatus(IntEnum):
"""Signal_encoding_types.NVMStatus"""
NVM_OK = 0x00
NVM_NOK = 0x01
RESERVED_0X02 = 0x02
RESERVED_0X03 = 0x03
RESERVED_0X04 = 0x04
RESERVED_0X05 = 0x05
RESERVED_0X06 = 0x06
RESERVED_0X07 = 0x07
RESERVED_0X08 = 0x08
RESERVED_0X09 = 0x09
RESERVED_0X0A = 0x0A
RESERVED_0X0B = 0x0B
RESERVED_0X0C = 0x0C
RESERVED_0X0D = 0x0D
RESERVED_0X0E = 0x0E
RESERVED_0X0F = 0x0F
class VoltageStatus(IntEnum):
"""Signal_encoding_types.VoltageStatus"""
NORMAL_VOLTAGE = 0x00
POWER_UNDERVOLTAGE = 0x01
POWER_OVERVOLTAGE = 0x02
RESERVED_0X03 = 0x03
RESERVED_0X04 = 0x04
RESERVED_0X05 = 0x05
RESERVED_0X06 = 0x06
RESERVED_0X07 = 0x07
RESERVED_0X08 = 0x08
RESERVED_0X09 = 0x09
RESERVED_0X0A = 0x0A
RESERVED_0X0B = 0x0B
RESERVED_0X0C = 0x0C
RESERVED_0X0D = 0x0D
RESERVED_0X0E = 0x0E
RESERVED_0X0F = 0x0F
class ThermalStatus(IntEnum):
"""Signal_encoding_types.ThermalStatus"""
NORMAL_TEMPERATURE = 0x00
THERMAL_DERATING = 0x01
THERMAL_SHUTDOWN = 0x02
RESERVED_0X03 = 0x03
RESERVED_0X04 = 0x04
RESERVED_0X05 = 0x05
RESERVED_0X06 = 0x06
RESERVED_0X07 = 0x07
RESERVED_0X08 = 0x08
RESERVED_0X09 = 0x09
RESERVED_0X0A = 0x0A
RESERVED_0X0B = 0x0B
RESERVED_0X0C = 0x0C
RESERVED_0X0D = 0x0D
RESERVED_0X0E = 0x0E
RESERVED_0X0F = 0x0F
class LedState(IntEnum):
"""Signal_encoding_types.LED_State"""
LED_OFF = 0x00
LED_ANIMATING = 0x01
LED_ON = 0x02
RESERVED = 0x03
class NvmStaticValidEncoding(IntEnum):
"""Signal_encoding_types.NVM_Static_Valid_Encoding"""
NVM_CORRUPTED_ZERO = 0x00
NVM_VALID = 0xA55B
NVM_EMPTY_ERASED = 0xFFFF
class NvmStaticRevEncoding(IntEnum):
"""Signal_encoding_types.NVM_Static_Rev_Encoding"""
INVALID_REVISION = 0x00
REVISION_1 = 0x01
NOT_PROGRAMMED = 0xFFFF
class NvmCalibVersionEncoding:
"""Signal_encoding_types.NVM_Calib_Version_Encoding (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'Factory Calib Version (>=1 valid)'
class NvmOadccalEncoding:
"""Signal_encoding_types.NVM_OADCCAL_Encoding (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'ADC Offset Cal (signed 8-bit)'
class NvmGainadclowcalEncoding:
"""Signal_encoding_types.NVM_GainADCLowCal_Encoding (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'ADC Gain Low Temp (signed 8-bit)'
class NvmGainadchighcalEncoding:
"""Signal_encoding_types.NVM_GainADCHighCal_Encoding (physical)."""
PHY_MIN = 0
PHY_MAX = 255
SCALE = 1.0
OFFSET = 0.0
UNIT = 'ADC Gain High Temp (signed 8-bit)'
# === Frames ================================================================
class AlmReqA:
"""LDF frame ALM_Req_A — published by Master_Node."""
NAME = "ALM_Req_A"
FRAME_ID = 0x0A
LENGTH = 8
PUBLISHER = "Master_Node"
SIGNALS: tuple[str, ...] = (
"AmbLightColourRed",
"AmbLightColourGreen",
"AmbLightColourBlue",
"AmbLightIntensity",
"AmbLightUpdate",
"AmbLightMode",
"AmbLightDuration",
"AmbLightLIDFrom",
"AmbLightLIDTo",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "AmbLightColourRed", 8),
(8, "AmbLightColourGreen", 8),
(16, "AmbLightColourBlue", 8),
(24, "AmbLightIntensity", 8),
(32, "AmbLightUpdate", 2),
(34, "AmbLightMode", 6),
(40, "AmbLightDuration", 8),
(48, "AmbLightLIDFrom", 8),
(56, "AmbLightLIDTo", 8),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class AlmStatus:
"""LDF frame ALM_Status — published by ALM_Node."""
NAME = "ALM_Status"
FRAME_ID = 0x11
LENGTH = 4
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"ALMNadNo",
"ALMVoltageStatus",
"ALMThermalStatus",
"ALMNVMStatus",
"ALMLEDState",
"SigCommErr",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "ALMNadNo", 8),
(8, "ALMVoltageStatus", 4),
(12, "ALMThermalStatus", 4),
(16, "ALMNVMStatus", 4),
(20, "ALMLEDState", 2),
(24, "SigCommErr", 1),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class ColorConfigFrameRed:
"""LDF frame ColorConfigFrameRed — published by Master_Node."""
NAME = "ColorConfigFrameRed"
FRAME_ID = 0x03
LENGTH = 8
PUBLISHER = "Master_Node"
SIGNALS: tuple[str, ...] = (
"ColorConfigFrameRed_X",
"ColorConfigFrameRed_Y",
"ColorConfigFrameRed_Z",
"ColorConfigFrameRed_Vf_Cal",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "ColorConfigFrameRed_X", 16),
(16, "ColorConfigFrameRed_Y", 16),
(32, "ColorConfigFrameRed_Z", 16),
(48, "ColorConfigFrameRed_Vf_Cal", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class ColorConfigFrameGreen:
"""LDF frame ColorConfigFrameGreen — published by Master_Node."""
NAME = "ColorConfigFrameGreen"
FRAME_ID = 0x04
LENGTH = 8
PUBLISHER = "Master_Node"
SIGNALS: tuple[str, ...] = (
"ColorConfigFrameGreen_X",
"ColorConfigFrameGreen_Y",
"ColorConfigFrameGreen_Z",
"ColorConfigFrameGreen_VfCal",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "ColorConfigFrameGreen_X", 16),
(16, "ColorConfigFrameGreen_Y", 16),
(32, "ColorConfigFrameGreen_Z", 16),
(48, "ColorConfigFrameGreen_VfCal", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class ColorConfigFrameBlue:
"""LDF frame ColorConfigFrameBlue — published by Master_Node."""
NAME = "ColorConfigFrameBlue"
FRAME_ID = 0x05
LENGTH = 8
PUBLISHER = "Master_Node"
SIGNALS: tuple[str, ...] = (
"ColorConfigFrameBlue_X",
"ColorConfigFrameBlue_Y",
"ColorConfigFrameBlue_Z",
"ColorConfigFrameBlue_VfCal",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "ColorConfigFrameBlue_X", 16),
(16, "ColorConfigFrameBlue_Y", 16),
(32, "ColorConfigFrameBlue_Z", 16),
(48, "ColorConfigFrameBlue_VfCal", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class PwmFrame:
"""LDF frame PWM_Frame — published by ALM_Node."""
NAME = "PWM_Frame"
FRAME_ID = 0x12
LENGTH = 8
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"PWM_Frame_Red",
"PWM_Frame_Green",
"PWM_Frame_Blue1",
"PWM_Frame_Blue2",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "PWM_Frame_Red", 16),
(16, "PWM_Frame_Green", 16),
(32, "PWM_Frame_Blue1", 16),
(48, "PWM_Frame_Blue2", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class ConfigFrame:
"""LDF frame ConfigFrame — published by Master_Node."""
NAME = "ConfigFrame"
FRAME_ID = 0x06
LENGTH = 3
PUBLISHER = "Master_Node"
SIGNALS: tuple[str, ...] = (
"ConfigFrame_Calibration",
"ConfigFrame_EnableDerating",
"ConfigFrame_EnableCompensation",
"ConfigFrame_MaxLM",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "ConfigFrame_Calibration", 1),
(1, "ConfigFrame_EnableDerating", 1),
(2, "ConfigFrame_EnableCompensation", 1),
(3, "ConfigFrame_MaxLM", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class VfFrame:
"""LDF frame VF_Frame — published by ALM_Node."""
NAME = "VF_Frame"
FRAME_ID = 0x13
LENGTH = 8
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"VF_Frame_Red_VF",
"VF_Frame_Green_VF",
"VF_Frame_Blue1_VF",
"VF_Frame_VLED",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "VF_Frame_Red_VF", 16),
(16, "VF_Frame_Green_VF", 16),
(32, "VF_Frame_Blue1_VF", 16),
(48, "VF_Frame_VLED", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class TjFrame:
"""LDF frame Tj_Frame — published by ALM_Node."""
NAME = "Tj_Frame"
FRAME_ID = 0x14
LENGTH = 8
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"Tj_Frame_Red",
"Tj_Frame_Green",
"Tj_Frame_Blue",
"Tj_Frame_NTC",
"Calibration_status",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "Tj_Frame_Red", 16),
(16, "Tj_Frame_Green", 16),
(32, "Tj_Frame_Blue", 16),
(48, "Tj_Frame_NTC", 15),
(63, "Calibration_status", 1),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class PwmWoComp:
"""LDF frame PWM_wo_Comp — published by ALM_Node."""
NAME = "PWM_wo_Comp"
FRAME_ID = 0x15
LENGTH = 8
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"PWM_wo_Comp_Red",
"PWM_wo_Comp_Green",
"PWM_wo_Comp_Blue",
"VF_Frame_VS",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "PWM_wo_Comp_Red", 16),
(16, "PWM_wo_Comp_Green", 16),
(32, "PWM_wo_Comp_Blue", 16),
(48, "VF_Frame_VS", 16),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
class NvmDebug:
"""LDF frame NVM_Debug — published by ALM_Node."""
NAME = "NVM_Debug"
FRAME_ID = 0x16
LENGTH = 8
PUBLISHER = "ALM_Node"
SIGNALS: tuple[str, ...] = (
"NVM_Static_Valid",
"NVM_Static_Rev",
"NVM_Calib_Version",
"NVM_OADCCAL",
"NVM_GainADCLowCal",
"NVM_GainADCHighCal",
)
SIGNAL_LAYOUT: tuple[tuple[int, str, int], ...] = (
(0, "NVM_Static_Valid", 16),
(16, "NVM_Static_Rev", 16),
(32, "NVM_Calib_Version", 8),
(40, "NVM_OADCCAL", 8),
(48, "NVM_GainADCLowCal", 8),
(56, "NVM_GainADCHighCal", 8),
)
@classmethod
def send(cls, fio: "FrameIO", **signals) -> None:
fio.send(cls.NAME, **signals)
@classmethod
def receive(cls, fio: "FrameIO", timeout: float = 1.0):
return fio.receive(cls.NAME, timeout=timeout)
@classmethod
def read_signal(
cls, fio: "FrameIO", signal: str, *,
timeout: float = 1.0, default=None,
):
return fio.read_signal(cls.NAME, signal, timeout=timeout, default=default)
# === Signal → encoding map =================================================
SIGNAL_ENCODINGS: dict[str, type] = {
"ALMLEDState": LedState,
"ALMNVMStatus": NVMStatus,
"AmbLightColourBlue": Blue,
"AmbLightColourGreen": Green,
"AmbLightColourRed": Red,
"AmbLightDuration": Duration,
"AmbLightIntensity": Intensity,
"AmbLightLIDFrom": ModuleID,
"AmbLightLIDTo": ModuleID,
"AmbLightMode": Mode,
"AmbLightUpdate": Update,
"NVM_Calib_Version": NvmCalibVersionEncoding,
"NVM_GainADCHighCal": NvmGainadchighcalEncoding,
"NVM_GainADCLowCal": NvmGainadclowcalEncoding,
"NVM_OADCCAL": NvmOadccalEncoding,
"NVM_Static_Rev": NvmStaticRevEncoding,
"NVM_Static_Valid": NvmStaticValidEncoding,
}