Skip to content

Commit

Permalink
Merge pull request #13 from c4deszes/feature/ldf-versions
Browse files Browse the repository at this point in the history
Reworked Lark file and parser
  • Loading branch information
c4deszes authored Nov 3, 2020
2 parents 967c8cc + fbbe8e7 commit 345c3fb
Show file tree
Hide file tree
Showing 30 changed files with 1,610 additions and 940 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,21 @@ jobs:
- name: Test & Coverage
run: pytest --cov=ldfparser --cov-report xml

- name: Run examples
- name: Run Examples
run: |
python examples/create_frame.py
python examples/read_frame.py
python examples/signal_encoding.py
python ./examples/communication.py
python ./examples/ldf2json.py
- name: Package
run: |
python setup.py sdist bdist_wheel
- name: Archive package
uses: actions/upload-artifact@v2
with:
name: package
path: dist/

- name: Upload coverage results
uses: codecov/codecov-action@v1
with:
Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LDF Parser

[![Workflow](https://github.com/c4deszes/ldfparser/workflows/CI/badge.svg)](https://github.com/c4deszes/ldfparser/actions)
[![Workflow](https://github.com/c4deszes/ldfparser/workflows/CI/badge.svg?branch=master)](https://github.com/c4deszes/ldfparser/actions)
[![PyPI version](https://badge.fury.io/py/ldfparser.svg)](https://badge.fury.io/py/ldfparser)
[![codecov.io](https://codecov.io/github/c4deszes/ldfparser/coverage.svg?branch=master)](https://codecov.io/github/c4deszes/ldfparser?branch=master)
[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org)
Expand All @@ -9,6 +9,15 @@
---

## Disclaimer

The tool has been written according the LIN standards 1.3, 2.0, 2.1 and 2.2A, but due to errors in the documentation there's no guarantee that the library will be able to parse your LDF. In such cases if possible first verify the LDF with a commercial tool
such as Vector LDF Explorer or the tool that was used to create the LDF. If the LDF seems to be correct then open a new issue. I also recommend trying the LDF to JSON conversion mechanism, see if that succeeds.

Since the LDF usually contains sensitive information try to provide either an anonymized version with signals and frames obfuscated or just the relevant segments in an example LDF.

---

## Example

```python
Expand Down Expand Up @@ -54,10 +63,6 @@ print(binascii.hexlify(message))

### Currently not supported

+ Signals longer than 16 bits

+ Ascii and BCD signal values

+ Scheduling table

+ Diagnostics
Expand All @@ -72,7 +77,7 @@ Install via `pip install ldfparser`

## Credits

Inspired by [uCAN-LIN LinUSBConverter](https://github.com/uCAN-LIN/LinUSBConverter), specifically the LDF parsing mechanism via [Lark](https://github.com/lark-parser/lark)
Inspired by [uCAN-LIN LinUSBConverter](https://github.com/uCAN-LIN/LinUSBConverter), specifically the LDF parsing mechanism via [Lark](https://github.com/lark-parser/lark). Previously the library included most of the lark file, parsing code and examples, since 0.5.0 they've been completely rewritten to better accomodate the different LIN standards.

---

Expand Down
16 changes: 16 additions & 0 deletions examples/communication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os
import ldfparser

class LinMaster:

def send_frame(self, baudrate: int, frame_id: int, data: bytearray):
# LIN Tool specific functionality
pass

if __name__ == "__main__":
ldf = ldfparser.parseLDF(os.path.join(os.path.dirname(__file__), 'lin22.ldf'))
lin_master = LinMaster()
requestFrame = ldf.frame('CEM_Frm1')
requestData = requestFrame.data({"InternalLightsRequest": 'on'}, ldf.converters)

lin_master.send_frame(ldf.baudrate, requestFrame.frame_id, requestData)
14 changes: 0 additions & 14 deletions examples/create_frame.py

This file was deleted.

7 changes: 7 additions & 0 deletions examples/ldf2json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os
import json
import ldfparser

if __name__ == "__main__":
ldf = ldfparser.parseLDFtoDict(os.path.join(os.path.dirname(__file__), 'lin22.ldf'))
print(json.dumps(ldf))
141 changes: 141 additions & 0 deletions examples/lin22.ldf
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*******************************************************/
/* This is the example LDF from LIN 2.2A specification */
/*******************************************************/

// Source: https://lin-cia.org/fileadmin/microsites/lin-cia.org/resources/documents/LIN_2.2A.pdf

LIN_description_file;
LIN_protocol_version = "2.2";
LIN_language_version = "2.2";
LIN_speed = 19.2 kbps;
Channel_name = "DB";

Nodes {
Master: CEM, 5 ms, 0.1 ms;
Slaves: LSM, RSM;
}

Signals {
InternalLightsRequest: 2, 0, CEM, LSM, RSM;
RightIntLightsSwitch: 8, 0, RSM, CEM;
LeftIntLightsSwitch: 8, 0, LSM, CEM;
LSMerror: 1, 0, LSM, CEM;
RSMerror: 1, 0, RSM, CEM;
IntTest: 2, 0, LSM, CEM;
}

Frames {
CEM_Frm1: 0x01, CEM, 1 {
InternalLightsRequest, 0;
}
LSM_Frm1: 0x02, LSM, 2 {
LeftIntLightsSwitch, 8;
}
LSM_Frm2: 0x03, LSM, 1 {
LSMerror, 0;
IntTest, 1;
}
RSM_Frm1: 0x04, RSM, 2 {
RightIntLightsSwitch, 8;
}
RSM_Frm2: 0x05, RSM, 1 {
RSMerror, 0;
}
}

Event_triggered_frames {
Node_Status_Event : Collision_resolver, 0x06, RSM_Frm1, LSM_Frm1;
}

Node_attributes {
RSM {
LIN_protocol = "2.0";
configured_NAD = 0x20;
product_id = 0x4E4E, 0x4553, 1;
response_error = RSMerror;
P2_min = 150 ms;
ST_min = 50 ms;
configurable_frames {
Node_Status_Event=0x000; CEM_Frm1 = 0x0001; RSM_Frm1 = 0x0002;
RSM_Frm2 = 0x0003;
}
}
LSM {
LIN_protocol = "2.2";
configured_NAD = 0x21;
initial_NAD = 0x01;
product_id = 0x4A4F, 0x4841;
response_error = LSMerror;
fault_state_signals = IntTest;
P2_min = 150 ms;
ST_min = 50 ms;
configurable_frames {
Node_Status_Event;
CEM_Frm1;
LSM_Frm1;
LSM_Frm2;
}
}
}

Schedule_tables {
Configuration_Schedule {
AssignNAD {LSM} delay 15 ms;
AssignFrameIdRange {LSM, 0} delay 15 ms;
AssignFrameId {RSM, CEM_Frm1} delay 15 ms;
AssignFrameId {RSM, RSM_Frm1} delay 15 ms;
AssignFrameId {RSM, RSM_Frm2} delay 15 ms;
}
Normal_Schedule {
CEM_Frm1 delay 15 ms;
LSM_Frm2 delay 15 ms;
RSM_Frm2 delay 15 ms;
Node_Status_Event delay 10 ms;
}
MRF_schedule {
MasterReq delay 10 ms;
}
SRF_schedule {
SlaveResp delay 10 ms;
}
Collision_resolver { // Keep timing of other frames if collision
CEM_Frm1 delay 15 ms;
LSM_Frm2 delay 15 ms;
RSM_Frm2 delay 15 ms;
RSM_Frm1 delay 10 ms; // Poll the RSM node
CEM_Frm1 delay 15 ms;
LSM_Frm2 delay 15 ms;
RSM_Frm2 delay 15 ms;
LSM_Frm1 delay 10 ms; // Poll the LSM node
}
}

Signal_encoding_types {
Dig2Bit {
logical_value, 0, "off";
logical_value, 1, "on";
logical_value, 2, "error";
logical_value, 3, "void";
}
ErrorEncoding {
logical_value, 0, "OK";
logical_value, 1, "error";
}
FaultStateEncoding {
logical_value, 0, "No test result";
logical_value, 1, "failed";
logical_value, 2, "passed";
logical_value, 3, "not used";
}
LightEncoding {
logical_value, 0, "Off";
physical_value, 1, 254, 1, 100, "lux";
logical_value, 255, "error";
}
}
Signal_representation {
Dig2Bit: InternalLightsRequest;
ErrorEncoding: RSMerror, LSMerror;
FaultStateEncoding: IntError;
LightEncoding: RightIntLightsSwitch, LefttIntLightsSwitch;
}
66 changes: 0 additions & 66 deletions examples/network.ldf

This file was deleted.

11 changes: 0 additions & 11 deletions examples/read_frame.py

This file was deleted.

12 changes: 0 additions & 12 deletions examples/read_header.py

This file was deleted.

15 changes: 0 additions & 15 deletions examples/signal_encoding.py

This file was deleted.

5 changes: 3 additions & 2 deletions ldfparser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .parser import LDF
from .lin import LinFrame, LinSignal
from .parser import LDF, parseLDF, parseLDFtoDict
from .lin import LinFrame, LinSignal
from .node import LinMaster, LinSlave, LinProductId
Loading

0 comments on commit 345c3fb

Please sign in to comment.