Examine the Contents of a Database¶
# examine_db.py
"""
This script uses canlib.kvadblib to parse a database and print its contents.
"""
import argparse
import sys
from canlib import kvadblib
INDENT = ' ' * 4
def print_db(db):
print('DATABASE')
print(db.name)
for line in db_lines(db):
print(INDENT + line)
def adef_lines(adef):
yield 'type: ' + type(adef).__name__
yield 'definition: ' + str(adef.definition)
yield 'owner: ' + str(adef.owner)
def attr_lines(attrib):
yield str(attrib.name) + ' = ' + str(attrib.value)
def db_lines(db):
yield 'flags: ' + str(db.flags)
yield 'protocol: ' + str(db.protocol)
yield ''
yield 'ATTRIBUTE DEFINITIONS'
for adef in db.attribute_definitions():
yield str(adef.name)
for line in adef_lines(adef):
yield INDENT + line
yield ''
yield 'MESSAGES'
for message in db:
yield str(message.name)
for line in msg_lines(message):
yield INDENT + line
yield ''
def enum_lines(enums):
for name, val in enums.items():
yield str(name) + ' = ' + str(val)
def msg_lines(message):
yield 'id: ' + str(message.id)
yield 'flags: ' + str(message.flags)
yield 'dlc: ' + str(message.dlc)
yield 'comment: ' + str(message.comment)
yield ''
yield 'ATTRIBUTES'
for attr in message.attributes():
for line in attr_lines(attr):
yield line
yield ''
yield 'SIGNALS'
for signal in message:
yield str(signal.name)
for line in sig_lines(signal):
yield INDENT + line
yield ''
def sig_lines(signal):
for name in ('type', 'byte_order', 'mode', 'size', 'scaling', 'limits', 'unit', 'comment'):
yield name + ': ' + str(getattr(signal, name))
yield ''
try:
enums = signal.enums
except AttributeError:
pass
else:
yield 'ENUMERATIONS'
for line in enum_lines(enums):
yield line
yield ''
yield 'ATTRIBUTES'
for attr in signal.attributes():
for line in attr_lines(attr):
yield line
yield ''
def examine_database(db_name):
with kvadblib.Dbc(filename=db_name) as db:
print_db(db)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
parser.add_argument(
'db', type=str, metavar='<database.dbc>', help='The dbc database file to examine.'
)
args = parser.parse_args()
examine_database(args.db)
Description¶
The script is structured into several generator functions that take a
canlib.kvadblib
object and yield lines of information about it. This allows
one function to add indentation to any other functions it uses.
Generally each function first yields information in the following order:
Any information about the object itself (e.g.
db.flags
anddb.protocol
)An empty string
For each type of sub-object (e.g. attribute definitions):
A heading (e.g.
'ATTRIBUTE_DEFINTIONS'
)For each object of that type (e.g. iterating through
canlib.kvadblib.Dbc.attribute_definitions
):The objects name
All lines from the
*_lines
function for the object type (e.g.adef_lines
), with added indentation
An empty string
Sample Output¶
Running this script on the database created by Create a Database gives the following:
DATABASE
engine_example
flags: 0
protocol: ProtocolType.CAN
ATTRIBUTE DEFINITIONS
BusType
type: StringDefinition
definition: DefaultDefinition(default='')
owner: AttributeOwner.DB
MESSAGES
EngineData
id: 100
flags: MessageFlag.0
dlc: 8
comment:
ATTRIBUTES
SIGNALS
PetrolLevel
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=24, length=8)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=255.0)
unit: l
comment:
ATTRIBUTES
EngPower
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=48, length=16)
scaling: ValueScaling(factor=0.01, offset=0.0)
limits: ValueLimits(min=0.0, max=150.0)
unit: kW
comment:
ATTRIBUTES
EngForce
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=32, length=16)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=0.0)
unit: N
comment:
ATTRIBUTES
IdleRunning
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: 0
size: ValueSize(startbit=23, length=1)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=0.0)
unit:
comment:
ENUMERATIONS
Running = 0
Idle = 1
ATTRIBUTES
EngTemp
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=16, length=7)
scaling: ValueScaling(factor=2.0, offset=-50.0)
limits: ValueLimits(min=-50.0, max=150.0)
unit: °C
comment:
ATTRIBUTES
EngSpeed
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=0, length=16)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=8000.0)
unit: rpm
comment:
ATTRIBUTES
GearBoxInfo
id: 1020
flags: MessageFlag.0
dlc: 1
comment:
ATTRIBUTES
SIGNALS
EcoMode
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: -1
size: ValueSize(startbit=6, length=2)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=1.0)
unit:
comment:
ATTRIBUTES
ShiftRequest
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: 0
size: ValueSize(startbit=3, length=1)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=0.0)
unit:
comment:
ENUMERATIONS
Shift_Request_On = 1
Shift_Request_Off = 0
ATTRIBUTES
Gear
type: SignalType.UNSIGNED
byte_order: SignalByteOrder.INTEL
mode: 0
size: ValueSize(startbit=0, length=3)
scaling: ValueScaling(factor=1.0, offset=0.0)
limits: ValueLimits(min=0.0, max=5.0)
unit:
comment:
ENUMERATIONS
Gear_5 = 5
Gear_1 = 1
Gear_3 = 3
Idle = 0
Gear_4 = 4
Gear_2 = 2
ATTRIBUTES