Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DBC: write cycle time #351

Merged
merged 3 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 63 additions & 37 deletions cantools/database/can/formats/dbc.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,14 +606,27 @@ def _dump_signal_types(database):

return valtype

def _create_GenMsgCycleTime_definition():
return AttributeDefinition('GenMsgCycleTime',
default_value=0,
kind='BO_',
type_name='INT',
minimum=0,
maximum=2**16-1)

def _dump_attribute_definitions(database):
ba_def = []

if database.dbc is None:
return ba_def
definitions = odict()
else:
definitions = database.dbc.attribute_definitions

definitions = database.dbc.attribute_definitions
# define "GenMsgCycleTime" attribute for specifying the cycle
# times of messages if it has not been explicitly defined
if 'GenMsgCycleTime' not in definitions:
definitions['GenMsgCycleTime'] = \
_create_GenMsgCycleTime_definition()

def get_value(definition, value):
if definition.minimum is None:
Expand Down Expand Up @@ -664,9 +677,15 @@ def _dump_attribute_definition_defaults(database):
ba_def_def = []

if database.dbc is None:
return ba_def_def
definitions = odict()
else:
definitions = database.dbc.attribute_definitions

definitions = database.dbc.attribute_definitions
# define "GenMsgCycleTime" attribute for specifying the cycle
# times of messages if it has not been explicitly defined
if 'GenMsgCycleTime' not in definitions:
definitions['GenMsgCycleTime'] = \
_create_GenMsgCycleTime_definition()

for definition in definitions.values():
if definition.default_value is not None:
Expand All @@ -680,7 +699,6 @@ def _dump_attribute_definition_defaults(database):

return ba_def_def


def _dump_attributes(database):
ba = []

Expand All @@ -695,43 +713,49 @@ def get_value(attribute):
if database.dbc is not None:
if database.dbc.attributes is not None:
for attribute in database.dbc.attributes.values():
ba.append(
'BA_ "{name}" {value};'.format(name=attribute.definition.name,
value=get_value(attribute)))
ba.append(f'BA_ "{attribute.definition.name}" '
f'{get_value(attribute)};')

for node in database.nodes:
if node.dbc is not None:
if node.dbc.attributes is not None:
for attribute in node.dbc.attributes.values():
ba.append(
'BA_ "{name}" {kind} {node_name} {value};'.format(
name=attribute.definition.name,
kind=attribute.definition.kind,
node_name=node.name,
value=get_value(attribute)))
ba.append(f'BA_ "{attribute.definition.name}" '
f'{attribute.definition.kind} '
f'{node.name} '
f'{get_value(attribute)};')

for message in database.messages:
if message.dbc is not None:
if message.dbc.attributes is not None:
for attribute in message.dbc.attributes.values():
ba.append(
'BA_ "{name}" {kind} {frame_id} {value};'.format(
name=attribute.definition.name,
kind=attribute.definition.kind,
frame_id=get_dbc_frame_id(message),
value=get_value(attribute)))

# retrieve the ordered dictionary of message attributes
msg_attributes = odict()
if message.dbc is not None and message.dbc.attributes is not None:
msg_attributes = message.dbc.attributes

# synchronize the attribute for the message cycle time with
# the cycle time specified by the message object
if message.cycle_time is None and 'GenMsgCycleTime' in msg_attributes:
del msg_attributes['GenMsgCycleTime']
elif message.cycle_time is not None:
msg_attributes['GenMsgCycleTime'] = \
Attribute(value=message.cycle_time,
definition=_create_GenMsgCycleTime_definition())

# output all message attributes
for attribute in msg_attributes.values():
ba.append(f'BA_ "{attribute.definition.name}" '
f'{attribute.definition.kind} '
f'{get_dbc_frame_id(message)} '
f'{get_value(attribute)};')

# handle the signals contained in the message
for signal in message.signals[::-1]:
if signal.dbc is not None:
if signal.dbc.attributes is not None:
for attribute in signal.dbc.attributes.values():
ba.append(
'BA_ "{name}" {kind} {frame_id} {signal_name} {value};'.format(
name=attribute.definition.name,
kind=attribute.definition.kind,
frame_id=get_dbc_frame_id(message),
signal_name=signal.name,
value=get_value(attribute)))
if signal.dbc is not None and signal.dbc.attributes is not None:
for attribute in signal.dbc.attributes.values():
ba.append(f'BA_ "{attribute.definition.name}" '
f'{attribute.definition.kind} '
f'{get_dbc_frame_id(message)} '
f'{signal.name} '
f'{get_value(attribute)};')

return ba

Expand Down Expand Up @@ -1247,7 +1271,7 @@ def get_signal_initial_value(frame_id_dbc, name):

def get_signal_spn(frame_id_dbc, name):
signal_attributes = get_attributes(frame_id_dbc, name)

try:
return signal_attributes['SPN'].value
except (KeyError, TypeError):
Expand Down Expand Up @@ -1357,10 +1381,12 @@ def get_cycle_time(frame_id_dbc):
message_attributes = get_attributes(frame_id_dbc)

try:
return int(message_attributes['GenMsgCycleTime'].value)
result = int(message_attributes['GenMsgCycleTime'].value)
return None if result == 0 else result
except (KeyError, TypeError):
try:
return int(definitions['GenMsgCycleTime'].default_value)
result = int(definitions['GenMsgCycleTime'].default_value)
return None if result == 0 else result
except (KeyError, TypeError):
return None

Expand Down
3 changes: 3 additions & 0 deletions cantools/subparsers/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ def _print_message(message):
print(f' Size: {message.length} bytes')
print(f' Is extended frame: {message.is_extended_frame}')

if message.cycle_time is not None:
print(f' Cycle time: {message.cycle_time} ms')

if message.signals:
print(f' Signals:')

Expand Down
2 changes: 1 addition & 1 deletion tests/files/c_source/multiplex.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern "C" {
#define MULTIPLEX_MESSAGE1_IS_EXTENDED (1)

/* Frame cycle times in milliseconds. */
#define MULTIPLEX_MESSAGE1_CYCLE_TIME_MS (0u)


/* Signal choices. */

Expand Down
5 changes: 1 addition & 4 deletions tests/files/c_source/multiplex_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ extern "C" {
#define MULTIPLEX_2_EXTENDED_TYPES_IS_EXTENDED (1)

/* Frame cycle times in milliseconds. */
#define MULTIPLEX_2_SHARED_CYCLE_TIME_MS (0u)
#define MULTIPLEX_2_NORMAL_CYCLE_TIME_MS (0u)
#define MULTIPLEX_2_EXTENDED_CYCLE_TIME_MS (0u)
#define MULTIPLEX_2_EXTENDED_TYPES_CYCLE_TIME_MS (0u)


/* Signal choices. */

Expand Down
4 changes: 2 additions & 2 deletions tests/files/dbc/floating_point.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ BO_ 1025 Message2: 8 TestNode


CM_ BU_ TestNode "";


BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "GenMsgCycleTime" 0;


SIG_VALTYPE_ 1024 Signal1 : 2;
Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/mod_name_len_dest.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ CM_ BU_ node_now_short "";
BA_DEF_ BU_ "SystemNodeLongSymbol" STRING ;
BA_DEF_ BO_ "SystemMessageLongSymbol" STRING ;
BA_DEF_ SG_ "SystemSignalLongSymbol" STRING ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "SystemNodeLongSymbol" "";
BA_DEF_DEF_ "SystemMessageLongSymbol" "";
BA_DEF_DEF_ "SystemSignalLongSymbol" "";
BA_DEF_DEF_ "GenMsgCycleTime" 0;



Expand Down
4 changes: 2 additions & 2 deletions tests/files/dbc/motohawk.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ BO_ 496 ExampleMessage: 8 PCM1


CM_ BO_ 496 "Example message used as template in MotoHawk models.";


BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "GenMsgCycleTime" 0;

VAL_ 496 Enable 0 "Disabled" 1 "Enabled" ;

Expand Down
4 changes: 2 additions & 2 deletions tests/files/dbc/multiple_senders.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ BO_TX_BU_ 1 : FOO,BAR,FIE;





BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "GenMsgCycleTime" 0;



Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/sig_groups.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ BO_ 0 NormalMsg: 8 Vector__XXX


BA_DEF_ "BusType" STRING ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "BusType" "CAN";
BA_DEF_DEF_ "GenMsgCycleTime" 0;



Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/sig_groups_del.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ BO_ 0 NormalMsg: 8 Vector__XXX


BA_DEF_ "BusType" STRING ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "BusType" "CAN";
BA_DEF_DEF_ "GenMsgCycleTime" 0;



Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/sig_groups_out.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ BO_ 0 NormalMsg: 8 Vector__XXX


BA_DEF_ "BusType" STRING ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "BusType" "CAN";
BA_DEF_DEF_ "GenMsgCycleTime" 0;



Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/val_table.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ BO_ 0 Message1: 8 Vector__XXX


BA_DEF_ "BusType" STRING ;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "BusType" "";
BA_DEF_DEF_ "GenMsgCycleTime" 0;

VAL_ 0 Signal1 1 "One" 0 "Zero" ;

Expand Down
2 changes: 2 additions & 0 deletions tests/files/dbc/vehicle.dbc
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,9 @@ CM_ SG_ 2303356194 Validity_Gyro_Rate_Roll "Valid when bit is set, invalid when
CM_ SG_ 2303356194 Validity_Gyro_Rate_Pitch "Valid when bit is set, invalid when bit is clear.";
CM_ SG_ 2303356194 Validity_Gyro_Rate_Yaw "Valid when bit is set, invalid when bit is clear.";
BA_DEF_ SG_ "GenSigStartValue" INT -2147483648 2147483647;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65535;
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_ "GenSigStartValue" SG_ 2304279330 Validity_INS_Vel_Forwards 0;
BA_ "GenSigStartValue" SG_ 2303355937 Accel_Vertical 16120;
BA_ "GenSigStartValue" SG_ 2303355937 Accel_Lateral -30000;
Expand Down
6 changes: 3 additions & 3 deletions tests/test_command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ def test_dump_with_comments_mux(self):
Destination: 0x34
Format: PDU 1
Length: 8 bytes
Cycle time: 0 ms
Cycle time: - ms
Senders: -
Layout:

Expand Down Expand Up @@ -1102,7 +1102,7 @@ def test_dump_j1939(self):
Destination: 0x02
Format: PDU 1
Length: 8 bytes
Cycle time: 0 ms
Cycle time: - ms
Senders: Node1
Layout:

Expand Down Expand Up @@ -1144,7 +1144,7 @@ def test_dump_j1939(self):
Destination: All
Format: PDU 2
Length: 8 bytes
Cycle time: 0 ms
Cycle time: - ms
Senders: Node2
Layout:

Expand Down
9 changes: 5 additions & 4 deletions tests/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from cantools.database.can.formats import dbc
from cantools.database import UnsupportedDatabaseFormatError
from cantools.database.can.signal import NamedSignalValue

class CanToolsDatabaseTest(unittest.TestCase):

maxDiff = None
Expand Down Expand Up @@ -2042,9 +2042,10 @@ def test_timing(self):
self.assertEqual(message.cycle_time, 200)
self.assertEqual(message.send_type, 'Cyclic')

# Default message cycle time is 0, as given by BA_DEF_DEF_.
# Default message cycle time is None which is defined in the
# DBC as 0 (as given by BA_DEF_DEF_)
message = db.get_message_by_frame_id(2)
self.assertEqual(message.cycle_time, 0)
self.assertEqual(message.cycle_time, None)
self.assertEqual(message.send_type, 'NoMsgSendType')

self.assert_dbc_dump(db, filename)
Expand Down Expand Up @@ -4709,7 +4710,7 @@ def test_bus_comment(self):

# This file is not '__main__' when executed via 'python setup.py3
# test'.
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.WARNING)

if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion tests/test_diagnostics_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ def test_unknown_byteorder(self):

# This file is not '__main__' when executed via 'python setup.py3
# test'.
logging.basicConfig()
logging.basicConfig(level=logging.WARNING)

if __name__ == '__main__':
unittest.main()
2 changes: 2 additions & 0 deletions tests/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def test_arxml4(self):
Frame ID: 0x6 (6)
Size: 7 bytes
Is extended frame: True
Cycle time: 200 ms
Signals:
signal3:
Type: Integer
Expand Down Expand Up @@ -283,6 +284,7 @@ def test_kcd(self):
Frame ID: 0x2 (2)
Size: 4 bytes
Is extended frame: False
Cycle time: 100 ms
Signals:
Signal1:
Type: Integer
Expand Down
2 changes: 2 additions & 0 deletions tests/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from io import StringIO
import cantools
import matplotlib.pyplot
import logging

logging.basicConfig(level=logging.WARNING)

class PyplotMock:

Expand Down