Skip to content

Commit c03fe70

Browse files
committed
Allow permissive DBC parsing
If multiple frames have the same name, add the frame ID as a suffix
1 parent a0bc7ef commit c03fe70

File tree

2 files changed

+101
-31
lines changed

2 files changed

+101
-31
lines changed

tools/cloud/dbc-to-decoders.py

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,70 @@
22
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
import argparse
56
import json
67
import sys
78

89
import cantools
910

10-
if len(sys.argv) < 2:
11-
print("Usage: python3 " + sys.argv[0] + " <INPUT_DBC_FILE> [<OUTPUT_JSON_FILE>]")
12-
exit(-1)
11+
default_interface_id = "1"
12+
parser = argparse.ArgumentParser(
13+
description=(
14+
"Converts a DBC file to AWS IoT FleetWise 'decoders' format for use with "
15+
"CreateDecoderManifest"
16+
)
17+
)
18+
parser.add_argument(
19+
"-p",
20+
"--permissive",
21+
action="store_true",
22+
help="Apply the cantools strict=False option when loading the DBC file",
23+
)
24+
parser.add_argument(
25+
"-i",
26+
"--interface-id",
27+
default=default_interface_id,
28+
help=(
29+
f'Network interface ID, default "{default_interface_id}". This must match the ID used in '
30+
"the static config file."
31+
),
32+
)
33+
parser.add_argument(
34+
"infile",
35+
nargs="?",
36+
type=argparse.FileType("r"),
37+
default=sys.stdin,
38+
help="Input DBC file, default stdin",
39+
)
40+
parser.add_argument(
41+
"outfile",
42+
nargs="?",
43+
type=argparse.FileType("w"),
44+
default=sys.stdout,
45+
help="Output filename, default stdout",
46+
)
47+
args = parser.parse_args()
1348

14-
db = cantools.database.load_file(sys.argv[1])
15-
16-
with open("network-interfaces.json") as f:
17-
network_interfaces = json.load(f)
18-
for interface in network_interfaces:
19-
if interface["type"] == "CAN_INTERFACE":
20-
interface_id = interface["interfaceId"]
49+
db = cantools.database.load(args.infile, strict=not args.permissive)
2150

2251
signal_decoders_to_add = []
2352

53+
processed_messages = set()
2454
for message in db.messages:
55+
message_text = message.name if message.name else message.frame_id
56+
if message_text in processed_messages:
57+
message_text = f"{message_text}_{message.frame_id}"
58+
processed_messages.add(message_text)
59+
processed_signals = set()
2560
for signal in message.signals:
61+
if signal.name in processed_signals:
62+
print(
63+
f"Signal {signal.name} occurs multiple times in the message {message_text}, only"
64+
" the first occurrence will be used",
65+
file=sys.stderr,
66+
)
67+
continue
68+
processed_signals.add(signal.name)
2669
signal_to_add = {}
2770
signal_to_add["name"] = signal.name
2871
signal_to_add["factor"] = signal.scale
@@ -52,14 +95,10 @@
5295
"type": "CAN_SIGNAL",
5396
"canSignal": signal_to_add,
5497
"fullyQualifiedName": f"Vehicle.{message.name}.{signal.name}",
55-
"interfaceId": interface_id,
98+
"interfaceId": args.interface_id,
5699
}
57100
)
58101

59102
out = json.dumps(signal_decoders_to_add, indent=4, sort_keys=True)
60103

61-
if len(sys.argv) < 3:
62-
print(out)
63-
else:
64-
with open(sys.argv[2], "w") as fp:
65-
fp.write(out)
104+
args.outfile.write(out)

tools/cloud/dbc-to-nodes.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,72 @@
22
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
import argparse
56
import json
67
import sys
78

89
import cantools
910

1011
FQN_KEY = "fullyQualifiedName"
1112

12-
if len(sys.argv) < 2:
13-
print("Usage: python3 " + sys.argv[0] + " <INPUT_DBC_FILE> [<OUTPUT_JSON_FILE>]")
14-
exit(-1)
13+
parser = argparse.ArgumentParser(
14+
description=(
15+
"Converts a DBC file to AWS IoT FleetWise 'nodes' format for use with "
16+
"CreateSignalCatalog"
17+
)
18+
)
19+
parser.add_argument(
20+
"-p",
21+
"--permissive",
22+
action="store_true",
23+
help="Apply the cantools strict=False option when loading the DBC file",
24+
)
25+
parser.add_argument(
26+
"infile",
27+
nargs="?",
28+
type=argparse.FileType("r"),
29+
default=sys.stdin,
30+
help="Input DBC file, default stdin",
31+
)
32+
parser.add_argument(
33+
"outfile",
34+
nargs="?",
35+
type=argparse.FileType("w"),
36+
default=sys.stdout,
37+
help="Output filename, default stdout",
38+
)
39+
args = parser.parse_args()
1540

16-
db = cantools.database.load_file(sys.argv[1])
41+
db = cantools.database.load(args.infile, strict=not args.permissive)
1742

1843
vehicle_branch = {FQN_KEY: "Vehicle"}
1944
nodes = []
2045

21-
signals = {}
46+
processed_messages = set()
2247
for message in db.messages:
2348
message_text = message.name if message.name else message.frame_id
49+
if message_text in processed_messages:
50+
message_text = f"{message_text}_{message.frame_id}"
51+
if message_text in processed_messages:
52+
print(
53+
f"Message {message.frame_id} occurs multiple times, only the first occurrence "
54+
"will be used",
55+
file=sys.stderr,
56+
)
57+
continue
58+
processed_messages.add(message_text)
2459
message_branch = {FQN_KEY: f"{vehicle_branch[FQN_KEY]}.{message_text}"}
2560
nodes.append({"branch": message_branch})
61+
processed_signals = set()
2662
for signal in message.signals:
27-
if message_text not in signals:
28-
signals[message_text] = set()
29-
if signal.name in signals[message_text]:
63+
if signal.name in processed_signals:
3064
print(
3165
f"Signal {signal.name} occurs multiple times in the message {message_text}, only"
32-
" the first occurrence will be used"
66+
" the first occurrence will be used",
67+
file=sys.stderr,
3368
)
3469
continue
35-
signals[message_text].add(signal.name)
70+
processed_signals.add(signal.name)
3671
if (
3772
signal.choices
3873
and len(signal.choices) <= 2
@@ -70,8 +105,4 @@
70105

71106
out = json.dumps(nodes, indent=4, sort_keys=True)
72107

73-
if len(sys.argv) < 3:
74-
print(out)
75-
else:
76-
with open(sys.argv[2], "w") as fp:
77-
fp.write(out)
108+
args.outfile.write(out)

0 commit comments

Comments
 (0)