Skip to content

Commit

Permalink
Update grammars
Browse files Browse the repository at this point in the history
  • Loading branch information
christoph2 committed Jan 29, 2019
1 parent 301401a commit 04b0f8c
Show file tree
Hide file tree
Showing 20 changed files with 1,277 additions and 676 deletions.
2 changes: 2 additions & 0 deletions pydbc/buildGrammars.cmd
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
java org.antlr.v4.Tool -Dlanguage=Python3 -long-messages -visitor dbc.g4 -o ./py3/
java org.antlr.v4.Tool -Dlanguage=Python3 -long-messages -visitor ncf.g4 -o ./py3/
java org.antlr.v4.Tool -Dlanguage=Python3 -long-messages -visitor ldf.g4 -o ./py3/
245 changes: 245 additions & 0 deletions pydbc/db/load/ldf.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,263 @@
__author__ = 'Christoph Schueler'
__version__ = '0.1.0'


import itertools

from pydbc.types import AttributeType, ValueType, CategoryType
from .base import BaseLoader

from pprint import pprint


"""
LIN-Attributes
==============
Network
-------
LIN_protocol_version stringValue
LIN_language_version stringValue
LIN_speed number
LIN_channel_name stringValue
Node
----
ismaster number
isslave number
time_base [MASTER] number
jitter [MASTER] number
LIN_protocol stringValue
configured_NAD intValue
initial_NAD intValue
(product_id)
supplier_id intValue
function_id intValue
variant intValue
response_error identifierValue [SIGNAL]
fault_state_signals* identifierValue [SIGNAL]
P2_min number
ST_min number
N_As_timeout number
N_Cr_timeout number
Signal
------
"""

# fbxFrame_Triggering
# fbxSchedule_Table
# fbxSchedule_Table_Entry

class AttributeContainer:

def __init__(self, name, objType, valueType, minimum = None, maximum = None):
self.name = name
self.objType = objType
self.valueType = valueType
self.minimum = minimum
self.maximum = maximum


LDF_ATTRS = {
# Network
"LIN_protocol_version": AttributeContainer("LIN_protocol_version", AttributeType.NETWORK, ValueType.STRING),
"LIN_language_version": AttributeContainer("LIN_language_version", AttributeType.NETWORK, ValueType.STRING),
"LIN_file_revision": AttributeContainer("LIN_file_revision", AttributeType.NETWORK, ValueType.STRING),
"LIN_speed": AttributeContainer("LIN_speed", AttributeType.NETWORK, ValueType.FLOAT),
"LIN_channel_name": AttributeContainer("LIN_channel_name", AttributeType.NETWORK, ValueType.STRING),
"LIN_include_diag": AttributeContainer("LIN_channel_name", AttributeType.NETWORK, ValueType.INT),
# Nodes
"LIN_is_master": AttributeContainer("LIN_is_master", AttributeType.NODE, ValueType.INT),
"LIN_is_slave": AttributeContainer("LIN_is_slave", AttributeType.NODE, ValueType.INT),
"LIN_time_base": AttributeContainer("LIN_time_base", AttributeType.NODE, ValueType.FLOAT),
"LIN_jitter": AttributeContainer("LIN_jitter", AttributeType.NODE, ValueType.FLOAT),
"LIN_protocol": AttributeContainer("LIN_protocol", AttributeType.NODE, ValueType.STRING),
"LIN_configured_NAD": AttributeContainer("LIN_configured_NAD", AttributeType.NODE, ValueType.INT),
"LIN_initial_NAD": AttributeContainer("LIN_initial_NAD", AttributeType.NODE, ValueType.INT),
"LIN_supplier_id": AttributeContainer("LIN_supplier_id", AttributeType.NODE, ValueType.INT),
"LIN_function_id": AttributeContainer("LIN_function_id", AttributeType.NODE, ValueType.INT),
"LIN_variant": AttributeContainer("LIN_variant", AttributeType.NODE, ValueType.INT),
"LIN_response_error": AttributeContainer("LIN_response_error", AttributeType.NODE, ValueType.STRING),
#fault_state_signals* identifierValue [SIGNAL]
"LIN_P2_min": AttributeContainer("LIN_P2_min", AttributeType.NODE, ValueType.FLOAT),
"LIN_ST_min": AttributeContainer("LIN_ST_min", AttributeType.NODE, ValueType.FLOAT),
"LIN_N_As_timeout": AttributeContainer("LIN_N_As_timeout", AttributeType.NODE, ValueType.FLOAT),
"LIN_N_Cr_timeout": AttributeContainer("LIN_N_Cr_timeout", AttributeType.NODE, ValueType.FLOAT),
}

class LdfLoader(BaseLoader):

def __init__(self, db, queryClass):
super(LdfLoader, self).__init__(db, queryClass)
self.nodes = {}
self.signals = {}
self.frames = {}

def _insertValues(self, cur, tree):
pprint(tree)
pprint(tree.keys())
self.insertAttributeDefinitions(cur)
self.insertNetworkAttributes(cur, tree)
"""
dict_keys([
'diagnosticSignals',
'signals',
'sporadicFrames',
'nodeAttributes',
'channelName',
'nodes',
'eventTriggeredFrames',
'signalGroups',
'signalRepresentations',
'nodeCompositions',
'scheduleTables',
'signalEncodings',
'diagnosticFrames',
'frames'])
"""
self.insertNetwork(cur)
self.insertNodes(cur, tree['nodes'])
self.insertNodeAttributes(cur, tree['nodeAttributes'])
self.insertSignals(cur, tree['signals'])
self.insertFrames(cur, tree['frames'])
self.insertFrameSignalRelationships(cur)

def insertAttributeDefinitions(self, cur):
for key, attr in LDF_ATTRS.items():
self.db.insertStatement(
cur, "linAttribute_Definition", "Name, Objecttype, Valuetype", attr.name, attr.objType, attr.valueType
)
rid = cur.lastrowid
attr.attrDef = rid

def insertNetworkAttributes(self, cur, tree):
KEY_MAP = {
'languageVersion': "LIN_language_version",
'protocolVersion': "LIN_protocol_version",
'fileRevision': "LIN_file_revision",
'speed': "LIN_speed",
'channelName': 'LIN_channel_name',
}
objID = 0
for key, mappedKey in KEY_MAP.items():
value = tree[key]
self.setAttributeValue(cur, objID, mappedKey, value)

def insertNetwork(self, cur):
self.db.insertStatement(cur, "Network", "Name", self.db.name)

def insertNodes(self, cur, nodes):
nodeIDs = {}
masterNode = nodes['master']
self.db.insertStatement(cur, "Node", "Name", masterNode)
mrid = cur.lastrowid
self.nodes[masterNode] = mrid
self.master = masterNode
self.setAttributeValue(cur, mrid, "LIN_is_master", 1)
self.setAttributeValue(cur, mrid, "LIN_time_base", nodes['timeBase'])
self.setAttributeValue(cur, mrid, "LIN_jitter", nodes['jitter'])
for name in nodes['slaves']:
self.db.insertStatement(cur, "Node", "Name", name)
srid = cur.lastrowid
self.setAttributeValue(cur, srid, "LIN_is_slave", 1)
self.nodes[name] = srid
print("SlaveNode:", name, srid)

def insertNodeAttributes(self, cur, attrs):
KEY_MAP = {
'initialNAD': "LIN_initial_NAD",
'configuredNAD': "LIN_configured_NAD",
'version': "LIN_protocol",
'nAs': "LIN_N_As_timeout",
'supplierID': "LIN_supplier_id",
'functionID': "LIN_function_id",
'variant': "LIN_variant",
'p2Min': "LIN_P2_min",
'nCr': "LIN_N_Cr_timeout",
'stMin': "LIN_ST_min",
'responseErrorSignal': 'LIN_response_error',
#'faultStateSignals': ""
}
for attr in attrs:
name = attr['name']
nid = self.nodes.get(name)
for key, mappedKey in KEY_MAP.items():
value = attr[key]
self.setAttributeValue(cur, nid, mappedKey, value)

def insertSignals(self, cur, signals):
"""
{'initValue': {'array': None, 'scalar': 0},
'name': 'LockingSystem',
'publishedBy': 'Gateway',
'size': 1,
'subscribedBy': ['Motor_back', 'Motor_head', 'Motor_horizontal', 'Motor_vertical']
},
"""
for signal in signals:
initValue = signal['initValue']
name = signal['name']
size = signal['size']
publishedBy = signal['publishedBy']
subscribedBy = signal['subscribedBy']
self.db.insertStatement(cur, "Signal", "Name, Bitsize", name, size)
signal['rid'] = cur.lastrowid
self.signals[name] = signal

def insertFrames(self, cur, frames):
"""
{'frameID': 21,
'frameName': 'Seatheating',
'frameSize': 1,
'publishedBy': 'Gateway',
'signals': [{'signalName': 'Heating', 'signalOffset': 0}]},
"""
for frame in frames:
frid = frame['frameID']
name = frame['frameName']
size = frame['frameSize']
publishedBy = frame['publishedBy']
sender = self.nodes.get(publishedBy)
self.db.insertStatement(cur, "Message", "Name, Message_ID, DLC, Sender", name, frid, size, sender)
frame['rid'] = cur.lastrowid
self.frames[name] = frame

def insertFrameSignalRelationships(self, cur):
for sigName, signal in self.signals.items():
sgrid = signal['rid']
for frameName in self.sendingFrameNames(sigName):
frame = self.frames.get(frameName)
frid = frame['rid']
for nodeName in signal['subscribedBy']:
nid = self.nodes.get(nodeName)
self.db.insertStatement(cur, "Node_RxSignal", "Message, Signal, Node", frid, sgrid, nid)

def setAttributeValue(self, cur, objID, attribute, value):
attr = LDF_ATTRS.get(attribute)
if attr is None:
raise KeyError("Invalid attribute '{}'".format(attribute))
numValue = None
stringValue = None
if attr.valueType in (ValueType.FLOAT, ValueType.INT):
numValue = value
elif attr.valueType == ValueType.STRING:
stringValue = value

self.db.insertStatement(
cur, "linAttribute_Value", "Object_ID, Attribute_Definition, Num_Value, String_Value",
objID, attr.attrDef, numValue, stringValue
)

def sendingFrameNames(self, signal):
result = []
for _, frame in self.frames.items():
frameSignals = (s['signalName'] for s in frame['signals'])
frameName = frame['frameName']
if signal in frameSignals:
result.append(frameName)
return result
23 changes: 18 additions & 5 deletions pydbc/dbcListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,18 @@

DIGITS = re.compile(r'(\d+)')

CO_MPX = re.compile(r"^m(\d+)M$")

def validateMultiplexerIndicatior(value):
if value == "M" or (value[0] == 'm' and value[1 : ].isdigit()):
return True
else:
print("Invalid multiplex indicator: '{}'".format(value))
return False
match = CO_MPX.match(value)
if not match:
print("Invalid multiplex indicator: '{}'".format(value))
return False
else:
return True


def extractAccessType(value):
Expand Down Expand Up @@ -102,21 +108,28 @@ def exitSignalExtendedValueTypeList(self, ctx):
def exitSignalExtendedValueType(self, ctx):
messageID = ctx.messageID.value
signalName = ctx.signalName.value
valType = ctx.valType.value # TODO: Validate ('0' | '1' | '2' | '3')
valType = ctx.valType.value
if not valType in (0, 1, 2, 3):
pass
#self.logger.error("ValueType must be in range [0..3]")
ctx.value = dict(messageID = messageID, signalName = signalName, valueType = valType)

def exitMessages(self, ctx):
ctx.value = [x.value for x in ctx.items]

def exitMessage(self, ctx):
# TODO: Check signals for multiple multiplexors!
ctx.value = dict(messageID = ctx.messageID.value, name = ctx.messageName.value, dlc = ctx.messageSize.value,
transmitter = ctx.transmt.text if ctx.transmt else None, signals = [x.value for x in ctx.sgs]
)

def exitSignal(self, ctx):
# TODO: Check signals for multiple multiplexors!
byteOrder = ctx.byteOrder.value
if not byteOrder in (0, 1):
pass
#self.logger.error("Byteorder must be either 0 or 1")
ctx.value = dict(name = ctx.signalName.value, startBit = ctx.startBit.value, signalSize = ctx.signalSize.value,
byteOrder = ctx.byteOrder.value, sign = -1 if ctx.sign.text == '-' else +1, factor = ctx.factor.value, offset = ctx.offset.value,
byteOrder = byteOrder, sign = -1 if ctx.sign.text == '-' else +1, factor = ctx.factor.value, offset = ctx.offset.value,
minimum = ctx.minimum.value, maximum = ctx.maximum.value, unit = ctx.unit.value, receiver = ctx.rcv.value,
multiplexerIndicator = ctx.mind.value if ctx.mind else None
)
Expand Down
4 changes: 2 additions & 2 deletions pydbc/ldfListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ def exitLin_protocol_version_def(self, ctx):

def exitLin_language_version_def(self, ctx):
ctx.value = ctx.s.value
print("Language-Ver:", ctx.value)

def exitLin_file_revision_def(self, ctx):
ctx.value = ctx.s.value
print("File_Revision:", ctx.value)

def exitLin_speed_def(self, ctx):
#print("SPEED:", dir(ctx.n))
print("SPEED:", ctx.n.start.line, ctx.n.start.column)
ctx.value = ctx.n.value if ctx.n else None

def exitChannel_name_def(self, ctx):
Expand Down
16 changes: 7 additions & 9 deletions pydbc/py3/dbc.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,13 @@ T__45=46
T__46=47
T__47=48
T__48=49
T__49=50
DUMMY_NODE_VECTOR=51
C_IDENTIFIER=52
FLOAT=53
INT=54
WS=55
STRING=56
SIGN=57
DUMMY_NODE_VECTOR=50
C_IDENTIFIER=51
FLOAT=52
INT=53
WS=54
STRING=55
SIGN=56
'BO_TX_BU_'=1
':'=2
';'=3
Expand Down Expand Up @@ -104,4 +103,3 @@ SIGN=57
'FLOAT'=47
'STRING'=48
'ENUM'=49
'BA_REL'=50
5 changes: 2 additions & 3 deletions pydbc/py3/dbcLexer.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Generated from dbc.g4 by ANTLR 4.7.2
# Generated from dbc.g4 by ANTLR 4.7
from antlr4 import *
from io import StringIO
from typing.io import TextIO
import sys



def serializedATN():
with StringIO() as buf:
buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2:")
Expand Down Expand Up @@ -356,7 +355,7 @@ class dbcLexer(Lexer):

def __init__(self, input=None, output:TextIO = sys.stdout):
super().__init__(input, output)
self.checkVersion("4.7.2")
self.checkVersion("4.7")
self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
self._actions = None
self._predicates = None
Expand Down
Loading

0 comments on commit 04b0f8c

Please sign in to comment.