Index: lib/MsgUtils/scripts/MsgData.py =================================================================== diff -u -rcfc0df719cb5033078d0cac45ce0f6243810f2e7 -rfa691c15183dfe8596de699ef8c3a7fcdb90edab --- lib/MsgUtils/scripts/MsgData.py (.../MsgData.py) (revision cfc0df719cb5033078d0cac45ce0f6243810f2e7) +++ lib/MsgUtils/scripts/MsgData.py (.../MsgData.py) (revision fa691c15183dfe8596de699ef8c3a7fcdb90edab) @@ -5,6 +5,7 @@ import csv import os from pathlib import Path +import re import sys # \brief Class that reads and stores the message data. @@ -65,7 +66,7 @@ # \param[in] clear If true, clear out any already loaded data before processing new data, # otherwise new data will be added to the existing data # \return none - def load(self, filename, clear=True): + def loadCSV(self, filename, clear=True): filename = Path(filename).resolve() def get_field_from_entry(entry, column): if column in self._msg_col and len(entry) > self._msg_col.index(column): @@ -127,6 +128,91 @@ print(f'Loaded {filename} with {entry_count} entries') + # \brief Load a .conf file (Unhandled.conf format) and cache the data. + # \note This will clear any previously cached data. + # \param[in] filename Filename of the .conf to load. + # \param[in] clear If true, clear out any already loaded data before processing new data, + # otherwise new data will be added to the existing data + # \return none + def loadConf(self, filename, clear=True): + name_regex = re.compile(r'[a-zA-Z][a-zA-Z0-9_]*') + filename = Path(filename).resolve() + if clear: + self.data = { } + entry_count = 0 + row_data = None + with open(filename, mode='r', encoding='utf-8') as in_file: + for line in in_file: + line = line.strip() + # blank line and message has been collected, end of message section + if not line and row_data is not None: + # check to see if data has already been collected for this msg_id_value + if row_data['msg_id_value'] in self.data: + print(f"WARNING: found MesgIDs with same value, {self.data[row_data['msg_id_value']]['msg_id']} will be replaced by {row_data['msg_id']} for value {row_data['msg_id_hex_string']}") + for item in self.data.values(): + if item['msg_name'] == row_data['msg_name']: + print(f"WARNING: found MesgIDs with same name, {row_data['msg_name']}, skipping message") + row_data = None + break + if row_data is not None: + if row_data['msg_id'] == '': + print(f"WARNING: message with ID {row_data['msg_id_hex_string']} contains blank msg_id, skipping message") + elif row_data['msg_name'] == '': + print(f"WARNING: message with ID {row_data['msg_id_hex_string']} contains blank msg_name, skipping message") + else: + self.data[row_data['msg_id_value']] = row_data + entry_count += 1 + row_data = None + elif line.startswith('#'): + if row_data is not None: + row_data['raw'] += line + '\n' + continue + # new message section start + elif line.startswith('[') and line.endswith(']') and row_data is None: + id_value = int(line[1:-1], 16) + row_data = { + 'msg_id': '', + 'msg_id_value': id_value, + 'msg_id_hex_string': MsgData.value_to_hex_string(id_value), + 'can_channel': '', + 'can_channel_value': 0, + 'ack_status': False, + 'msg_name': '', + 'payload': [], + 'raw': line + '\n', + } + # message name (first line of message section) + elif row_data is not None and row_data['msg_id'] == '' and re.fullmatch(name_regex, line): + row_data['raw'] += line + '\n' + row_data['msg_id'] = 'MSG_ID_' + '_'.join(word.upper() for word in line.split('_')) + row_data['msg_name'] = self.__message_name(row_data['msg_id']) + # payload parameter + elif row_data is not None and '=' in line: + row_data['raw'] += line + '\n' + result = line.strip().split('=', 1) + field_type = result[0] + field_name = result[1][:1].lower() + result[1][1:] if result[1] else '' + if not re.fullmatch(name_regex, field_name): + print(f"WARNING: {row_data['msg_id']} ({row_data['msg_id_hex_string']}) contains invalid field name \"{result[1]}\", skipping message") + row_data = None + continue + count = 0 + base_name = field_name + while any(field['name'] == field_name for field in row_data['payload']): + if count == 0: + print(f"WARNING: {row_data['msg_id']} ({row_data['msg_id_hex_string']}) contains duplicate field \"{field_name}\"") + count += 1 + field_name = f"{base_name}{count}" + row_data['payload'].append({ + 'raw': line.strip(), + 'name': field_name, + 'type': field_type, + }) + self.data = OrderedDict(sorted(self.data.items(), + key=lambda x: (int(x[1]['msg_id_value'] if x[1]['msg_id_value'] is not None else 99999), x[0]))) + print(f'Loaded {filename} with {entry_count} entries') + + # \brief Sort the cached csv data. # \return none def sort(self):