{"id":7357,"library":"ldfparser","title":"LDF Parser","description":"ldfparser is a Python library designed to parse LIN Description Files (LDF), enabling extraction of signal names, frame definitions, and facilitating encoding and decoding of LIN messages. It supports LIN standards 1.3, 2.0, 2.1, and 2.2A. Currently, the library is in a pre-release state, which means that features might undergo changes between minor versions.","status":"active","version":"0.26.0","language":"en","source_language":"en","source_url":"https://github.com/c4deszes/ldfparser","tags":["LIN","LDF","automotive","parser","CAN bus"],"install":[{"cmd":"pip install ldfparser","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"The primary function to load and parse an LDF file.","symbol":"parse_ldf","correct":"from ldfparser import parse_ldf"},{"note":"The LDF object is returned by parse_ldf and provides access to parsed data.","symbol":"LDF","correct":"import ldfparser\nldf = ldfparser.parse_ldf(path='file.ldf')"}],"quickstart":{"code":"import ldfparser\nimport os\nimport tempfile\nimport binascii\n\n# Create a dummy LDF file for demonstration\nldf_content = \"\"\"\nLIN_description_file;\nLIN_protocol_version = \"2.1\";\nLIN_language_version = \"2.1\";\nLIN_speed = 19.2 kbps;\nNodes {\n    Master: MasterNode, 5 ms, 0.1 ms;\n    Slaves: SlaveNode1;\n}\nSignals {\n    EngineRPM: 12, 0, MasterNode, MasterNode;\n    CoolantTemp: 8, 12, MasterNode, MasterNode;\n}\nFrames {\n    EngineFrame: 0x10, 8, MasterNode;\n    Signals {\n        EngineRPM, 0;\n        CoolantTemp, 2;\n    }\n}\nSignal_encoding_types {\n    MotorRPM_encoding:\n        physical_value,\n        0, 255, 1, 0, \"RPM\";\n}\nSignal_representation {\n    MotorRPM_encoding: EngineRPM;\n}\n\"\"\"\n\nwith tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.ldf') as temp_ldf_file:\n    temp_ldf_file.write(ldf_content)\n    ldf_path = temp_ldf_file.name\n\ntry:\n    # Load LDF\n    ldf = ldfparser.parse_ldf(path=ldf_path)\n    print(f\"Successfully parsed LDF from: {ldf_path}\")\n\n    # Get baudrate\n    print(f\"Baudrate: {ldf.get_baudrate()} kbps\")\n\n    # Get an unconditional frame\n    frame = ldf.get_unconditional_frame('EngineFrame')\n    print(f\"Frame 'EngineFrame' ID: {frame.frame_id}, Length: {frame.length} bytes\")\n\n    # Encode signal values\n    signal_values = {\"EngineRPM\": 1500, \"CoolantTemp\": 95}\n    message = frame.encode(signal_values)\n    print(f\"Encoded message for {signal_values}: 0x{binascii.hexlify(message).decode('utf-8')}\")\n\n    # Decode message\n    decoded_values = frame.decode(message)\n    print(f\"Decoded message: {decoded_values}\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    # Clean up the temporary LDF file\n    if os.path.exists(ldf_path):\n        os.remove(ldf_path)\n","lang":"python","description":"This quickstart demonstrates how to parse an LDF file, retrieve network parameters like baudrate, access specific frames, and then encode and decode LIN messages using defined signals. A temporary LDF file is created for a runnable example."},"warnings":[{"fix":"Migrate code to use `signal.frames` (which returns a list) instead of `signal.frame` when iterating over signal ownership.","message":"As of v0.26.0, `signal.frames` is the new way to determine signal owners for compatibility with signals associated with multiple frames. While `signal.frame` is still set if a signal belongs to only one frame, relying on `signal.frame` directly for multi-frame signals is discouraged.","severity":"breaking","affected_versions":">=0.26.0"},{"fix":"Review any logic that depends on the previous rounding-down behavior for physical value conversions and adjust expectations or implement custom rounding if needed.","message":"In v0.26.0, physical values are now rounded to the nearest integer during conversion, rather than always rounded down. This can change the output of decoded signals.","severity":"breaking","affected_versions":">=0.26.0"},{"fix":"Update function calls to their snake_case equivalents (e.g., `parse_ldf`) and use getter methods (e.g., `ldf.get_frame('FrameName')`) to ensure future compatibility.","message":"Prior to v0.10.0, several functions like `parseLDF`, `parseLDFtoDict`, `parseComments`, and direct attribute access like `LDF.frame(x)` were common. These have been deprecated in favor of snake_case function names (`parse_ldf`) and proper getter methods.","severity":"deprecated","affected_versions":"<0.10.0"},{"fix":"It is highly recommended to pin the exact minor version (e.g., `ldfparser==0.26.0`) in production environments and perform thorough integration tests when updating to a new minor version.","message":"The library is in a 'pre-release' state, and features may break between minor versions. This means APIs or internal behaviors can change without a major version increment.","severity":"gotcha","affected_versions":"All pre-1.0.0 versions"},{"fix":"If parsing issues occur, first verify the LDF file with a commercial tool (e.g., Vector LDF Explorer). If the LDF is valid, consider opening an issue with an anonymized LDF snippet.","message":"Due to known ambiguities or errors in LIN standard documentation, `ldfparser` cannot guarantee parsing correctness for *all* LDF files.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure the LDF file exists at the specified path and that the Python process has read permissions for it. Double-check the file name and directory.","cause":"The path provided to `ldfparser.parse_ldf` does not point to an accessible LDF file.","error":"FileNotFoundError: 'non_existent.ldf' doesn't exist"},{"fix":"Verify the exact name of the frame or signal in the LDF file. Use `ldf.frames` or `ldf.signals` to inspect available names or iterate through them.","cause":"Attempted to access a frame (e.g., `ldf.get_unconditional_frame('Frame_X')`) or signal that does not exist or is misspelled in the parsed LDF.","error":"KeyError: 'Frame_X'"},{"fix":"Use `signal.frames` (which is a list of frames) to determine the owners of a signal. Iterate over this list if a signal can belong to multiple frames. For signals with a single frame owner, `signal.frame` will still be populated for backward compatibility.","cause":"Attempting to access `signal.frame` when the signal is associated with multiple frames, especially after v0.26.0 which introduced `signal.frames`.","error":"AttributeError: 'LinSignal' object has no attribute 'frame'"},{"fix":"Review the LDF file for syntax errors. Validate it with a commercial LDF editor if possible. Consider simplifying the LDF to isolate the problematic section or upgrading `ldfparser` if it's an old version with a known parsing bug.","cause":"The provided LDF file contains syntax errors or deviations from the LIN standard that the parser cannot handle, leading to a parsing failure.","error":"ldfparser.parser.LDFParserException: Error parsing LDF file: ..."}]}