# coding=utf-8 import codecs import sys sys.path.append('..') import canmatrix # # create target Matrix # db = canmatrix.CanMatrix() db.boardUnits.add(canmatrix.BoardUnit("testBU")) db.boardUnits.add(canmatrix.BoardUnit("recBU")) myFrame1 = canmatrix.Frame("canFdStandard1",Id=1, dlc=24, is_fd = True, transmitter=["testBU"]) myFrame2 = canmatrix.Frame("CanFdExtended2",Id=2, dlc=16, extended = True, is_fd = True, transmitter=["testBU"]) myFrame3 = canmatrix.Frame("CanExtended3", Id=3, dlc=8, extended = True, transmitter=["testBU"]) myFrame4 = canmatrix.Frame("CanStandard4", Id=4, dlc=8) mySignal1 = canmatrix.Signal("signal1", signalSize=64, startBit=0, is_little_endian=True, min=0, max=0, is_signed=True, receiver=["recBU"]) mySignal2 = canmatrix.Signal("signal2", signalSize=64, startBit=64, is_little_endian=True, min=0, max=0, is_signed=True, receiver=["recBU"]) mySignal3 = canmatrix.Signal("signal3", signalSize=64, startBit=128, is_little_endian=True, min=0, max=0, is_signed=True) myFrame1.addSignal(mySignal3) myFrame1.addSignal(mySignal2) myFrame1.addSignal(mySignal1) myFrame2.addSignal(mySignal2) myFrame2.addSignal(mySignal1)
def load(f, **options): # type: (typing.IO, **typing.Any) -> canmatrix.CanMatrix dbc_import_encoding = options.get("dbcImportEncoding", 'iso-8859-1') dbc_comment_encoding = options.get("dbcImportCommentEncoding", dbc_import_encoding) float_factory = options.get('float_factory', default_float_factory) i = 0 follow_up = _FollowUps.NOTHING comment = "" signal = None # type: typing.Optional[canmatrix.Signal] frame = None board_unit = None db = canmatrix.CanMatrix() frames_by_id = {} # type: typing.Dict[int, canmatrix.Frame] def hash_arbitration_id(arbitration_id): # type: (canmatrix.ArbitrationId) -> int return hash((arbitration_id.id, arbitration_id.extended)) def get_frame_by_id(arbitration_id): # type: (canmatrix.ArbitrationId) -> typing.Optional[canmatrix.Frame] try: return frames_by_id[hash_arbitration_id(arbitration_id)] except KeyError: return None def add_frame_by_id(new_frame): # type: (canmatrix.Frame) -> None frames_by_id[hash_arbitration_id(new_frame.arbitration_id)] = new_frame for line in f: i = i + 1 l = line.strip() if len(l) == 0: continue try: # if 1==1: if follow_up == _FollowUps.SIGNAL_COMMENT: try: comment += "\n" + l.decode(dbc_comment_encoding).replace('\\"', '"') except: logger.error("Error decoding line: %d (%s)" % (i, line)) if re.match(r'.*" *;\Z',l.decode(dbc_import_encoding).strip()) is not None: follow_up = _FollowUps.NOTHING if signal is not None: signal.add_comment(comment[:-1].strip()[:-1]) continue elif follow_up == _FollowUps.FRAME_COMMENT: try: comment += "\n" + l.decode(dbc_comment_encoding).replace('\\"', '"') except: logger.error("Error decoding line: %d (%s)" % (i, line)) if re.match(r'.*" *;\Z',l.decode(dbc_import_encoding).strip()) is not None: follow_up = _FollowUps.NOTHING if frame is not None: frame.add_comment(comment[:-1].strip()[:-1]) continue elif follow_up == _FollowUps.BOARD_UNIT_COMMENT: try: comment += "\n" + \ l.decode(dbc_comment_encoding).replace('\\"', '"') except: logger.error("Error decoding line: %d (%s)" % (i, line)) if re.match(r'.*" *;\Z',l.decode(dbc_import_encoding).strip()) is not None: follow_up = _FollowUps.NOTHING if board_unit is not None: board_unit.add_comment(comment[:-1].strip()[:-1]) continue decoded = l.decode(dbc_import_encoding).strip() if decoded.startswith("BO_ "): regexp = re.compile(r"^BO_ ([^\ ]+) ([^\ ]+) *: ([^\ ]+) ([^\ ]+)") temp = regexp.match(decoded) # db.frames.addFrame(Frame(temp.group(1), temp.group(2), temp.group(3), temp.group(4))) frame = canmatrix.Frame(temp.group(2), arbitration_id=int(temp.group(1)), size=int(temp.group(3)), transmitters=temp.group(4).split()) db.frames.append(frame) add_frame_by_id(frame) elif decoded.startswith("SG_ "): pattern = r"^SG_ +(\w+) *: *(\d+)\|(\d+)@(\d+)([\+|\-]) *\(([0-9.+\-eE]+), *([0-9.+\-eE]+)\) *\[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] +\"(.*)\" +(.*)" regexp = re.compile(pattern) temp = regexp.match(decoded) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp_raw = regexp_raw.match(l) if temp: receiver = [b.strip() for b in temp.group(11).split(',')] extras = {} # type: typing.Dict[typing.Any, typing.Any] # if float_factory is not None: # extras['float_factory'] = float_factory temp_signal = canmatrix.Signal( temp.group(1), start_bit=int(temp.group(2)), size=int(temp.group(3)), is_little_endian=(int(temp.group(4)) == 1), is_signed=(temp.group(5) == '-'), factor=temp.group(6), offset=temp.group(7), min=temp.group(8), max=temp.group(9), unit=temp_raw.group(10).decode(dbc_import_encoding), receivers=receiver, **extras ) if not temp_signal.is_little_endian: # startbit of motorola coded signals are MSB in dbc temp_signal.set_startbit(int(temp.group(2)), bitNumbering=1) frame.add_signal(temp_signal) # db.frames.addSignalToLastFrame(tempSig) else: pattern = r"^SG_ +(.+?) +(.+?) *: *(\d+)\|(\d+)@(\d+)([\+|\-]) *\(([0-9.+\-eE]+),([0-9.+\-eE]+)\) *\[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] +\"(.*)\" +(.*)" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) receiver = [b.strip() for b in temp.group(12).split(',')] multiplex = temp.group(2) # type: str is_complex_multiplexed = False if multiplex == 'M': multiplex = 'Multiplexor' elif multiplex.endswith('M'): is_complex_multiplexed = True multiplex = multiplex[:-1] if multiplex != 'Multiplexor': try: multiplex = int(multiplex[1:]) except: raise Exception('error decoding line', line) extras = {} # if float_factory is not None: # extras['float_factory'] = float_factory temp_signal = canmatrix.Signal( temp.group(1), start_bit=int(temp.group(3)), size=int(temp.group(4)), is_little_endian=(int(temp.group(5)) == 1), is_signed=(temp.group(6) == '-'), factor=temp.group(7), offset=temp.group(8), min=temp.group(9), max=temp.group(10), unit=temp_raw.group(11).decode(dbc_import_encoding), receivers=receiver, multiplex=multiplex, **extras ) if is_complex_multiplexed: temp_signal.is_multiplexer = True temp_signal.multiplex = 'Multiplexor' if not temp_signal.is_little_endian: # startbit of motorola coded signals are MSB in dbc temp_signal.set_startbit(int(temp.group(3)), bitNumbering=1) frame.add_signal(temp_signal) if is_complex_multiplexed: frame.is_complex_multiplexed = True elif decoded.startswith("BO_TX_BU_ "): regexp = re.compile(r"^BO_TX_BU_ ([0-9]+) *: *(.+) *;") temp = regexp.match(decoded) frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) for ecu_name in temp.group(2).split(','): frame.add_transmitter(ecu_name) elif decoded.startswith("CM_ SG_ "): pattern = r"^CM_ +SG_ +(\w+) +(\w+) +\"(.*)\" *;" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) signal = frame.signal_by_name(temp.group(2)) if signal: try: signal.add_comment(temp_raw.group(3).decode( dbc_comment_encoding).replace('\\"', '"')) except: logger.error( "Error decoding line: %d (%s)" % (i, line)) else: pattern = r"^CM_ +SG_ +(\w+) +(\w+) +\"(.*)" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) signal = frame.signal_by_name(temp.group(2)) try: comment = temp_raw.group(3).decode( dbc_comment_encoding).replace('\\"', '"') except: logger.error( "Error decoding line: %d (%s)" % (i, line)) follow_up = _FollowUps.SIGNAL_COMMENT elif decoded.startswith("CM_ BO_ "): pattern = r"^CM_ +BO_ +(\w+) +\"(.*)\" *;" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) if frame: try: frame.add_comment(temp_raw.group(2).decode( dbc_comment_encoding).replace('\\"', '"')) except: logger.error( "Error decoding line: %d (%s)" % (i, line)) else: pattern = r"^CM_ +BO_ +(\w+) +\"(.*)" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) try: comment = temp_raw.group(2).decode( dbc_comment_encoding).replace('\\"', '"') except: logger.error( "Error decoding line: %d (%s)" % (i, line)) follow_up = _FollowUps.FRAME_COMMENT elif decoded.startswith("CM_ BU_ "): pattern = r"^CM_ +BU_ +(\w+) +\"(.*)\" *;" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: board_unit = db.ecu_by_name(temp.group(1)) if board_unit: try: board_unit.add_comment(temp_raw.group(2).decode( dbc_comment_encoding).replace('\\"', '"')) except: logger.error("Error decoding line: %d (%s)" % (i, line)) else: pattern = r"^CM_ +BU_ +(\w+) +\"(.*)" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: board_unit = db.ecu_by_name(temp.group(1)) if board_unit: try: comment = temp_raw.group(2).decode( dbc_comment_encoding).replace('\\"', '"') except: logger.error( "Error decoding line: %d (%s)" % (i, line)) follow_up = _FollowUps.BOARD_UNIT_COMMENT elif decoded.startswith("BU_:"): pattern = r"^BU_\:(.*)" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) if temp: my_temp_list = temp.group(1).split(' ') for ele in my_temp_list: if len(ele.strip()) > 1: db.ecus.append(canmatrix.Ecu(ele)) elif decoded.startswith("VAL_ "): regexp = re.compile(r"^VAL_ +(\w+) +(\w+) +(.*) *;") temp = regexp.match(decoded) if temp: frame_id = temp.group(1) signal_name = temp.group(2) temp_list = list(canmatrix.utils.escape_aware_split(temp.group(3), '"')) if frame_id.isnumeric(): # value for Frame try: frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(frame_id))) sg = frame.signal_by_name(signal_name) for i in range(math.floor(len(temp_list) / 2)): val = temp_list[i * 2 + 1] val = val.replace('\\"', '"') if sg: sg.add_values(temp_list[i * 2], val) except: logger.error("Error with Line: " + str(temp_list)) else: logger.info("Warning: environment variables currently not supported") elif decoded.startswith("VAL_TABLE_ "): regexp = re.compile(r"^VAL_TABLE_ +(\w+) +(.*) *;") temp = regexp.match(decoded) if temp: table_name = temp.group(1) temp_list = temp.group(2).split('"') value_hash = {} try: for i in range(math.floor(len(temp_list) / 2)): val = temp_list[i * 2 + 1] value_hash[temp_list[i * 2].strip()] = val.strip() except: logger.error("Error with Line: " + str(temp_list)) db.add_value_table(table_name, value_hash) else: logger.debug(l) elif decoded.startswith("BA_DEF_") and decoded[7:].strip()[:3] in ["SG_", "BO_", "BU_", "EV_"]: substring = decoded[7:].strip() define_type = substring[:3] substring = substring[3:].strip() pattern = r"^\"(.+?)\" +(.+); *" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(substring) substring_line = l[7:].strip()[3:].strip() temp_raw = regexp_raw.match(substring_line) if temp: if define_type == "SG_": db.add_signal_defines(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif define_type == "BO_": db.add_frame_defines(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif define_type == "BU_": db.add_ecu_defines(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif define_type == "EV_": db.add_env_defines(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif decoded.startswith("BA_DEF_ "): pattern = r"^BA_DEF_ +\"(.+?)\" +(.+) *;" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: db.add_global_defines(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif decoded.startswith("BA_ "): regexp = re.compile(r"^BA_ +\".+?\" +(.+)") tempba = regexp.match(decoded) if tempba.group(1).strip().startswith("BO_ "): regexp = re.compile(r"^BA_ +\"(.+?)\" +BO_ +(\d+) +(.+) *; *") temp = regexp.match(decoded) get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(2)))).add_attribute( temp.group(1), temp.group(3)) elif tempba.group(1).strip().startswith("SG_ "): regexp = re.compile(r"^BA_ +\"(.+?)\" +SG_ +(\d+) +(\w+) +(.+) *; *") temp = regexp.match(decoded) if temp is not None: get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(2)))).signal_by_name( temp.group(3)).add_attribute(temp.group(1), temp.group(4)) elif tempba.group(1).strip().startswith("EV_ "): regexp = re.compile(r"^BA_ +\"(.+?)\" +EV_ +(\w+) +(.*) *; *") temp = regexp.match(decoded) if temp is not None: db.add_env_attribute(temp.group(2), temp.group(1), temp.group(3)) elif tempba.group(1).strip().startswith("BU_ "): regexp = re.compile(r"^BA_ +\"(.*?)\" +BU_ +(\w+) +(.+) *; *") temp = regexp.match(decoded) db.ecu_by_name( temp.group(2)).add_attribute( temp.group(1), temp.group(3)) else: regexp = re.compile( r"^BA_ +\"([A-Za-z0-9\-_]+)\" +([\"\w\-\.]+) *; *") temp = regexp.match(decoded) if temp: db.add_attribute(temp.group(1), temp.group(2)) elif decoded.startswith("SIG_GROUP_ "): regexp = re.compile(r"^SIG_GROUP_ +(\w+) +(\w+) +(\w+) +\:(.*) *; *") temp = regexp.match(decoded) frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) if frame is not None: signal_array = temp.group(4).split(' ') frame.add_signal_group(temp.group(2), temp.group(3), signal_array) # todo wrong annotation in canmatrix? Id is a string? elif decoded.startswith("SIG_VALTYPE_ "): regexp = re.compile(r"^SIG_VALTYPE_ +(\w+) +(\w+)\s*\:(.*) *; *") temp = regexp.match(decoded) frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(temp.group(1)))) if frame: signal = frame.signal_by_name(temp.group(2)) signal.is_float = True # SIG_VALTYPE_ 0 float : 1; elif decoded.startswith("BA_DEF_DEF_ "): pattern = r"^BA_DEF_DEF_ +\"(.+?)\" +(.+?) *;" regexp = re.compile(pattern) regexp_raw = re.compile(pattern.encode(dbc_import_encoding)) temp = regexp.match(decoded) temp_raw = regexp_raw.match(l) if temp: db.add_define_default(temp.group(1), temp_raw.group(2).decode(dbc_import_encoding)) elif decoded.startswith("SG_MUL_VAL_ "): pattern = r"^SG_MUL_VAL_ +([0-9]+) +([\w\-]+) +([\w\-]+) +(.*) *; *" regexp = re.compile(pattern) temp = regexp.match(decoded) if temp: frame_id = temp.group(1) signal_name = temp.group(2) muxer_for_signal = temp.group(3) mux_val_groups = temp.group(4).split(',') frame = get_frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(frame_id))) if frame is not None: signal = frame.signal_by_name(signal_name) frame.is_complex_multiplexed = True signal.muxer_for_signal = muxer_for_signal for muxVal in mux_val_groups: mux_val_min, mux_val_max = muxVal.split("-") mux_val_min_number = int(mux_val_min) mux_val_max_number = int(mux_val_max) signal.mux_val_grp.append([mux_val_min_number, mux_val_max_number]) elif decoded.startswith("EV_ "): pattern = r"^EV_ +([\w\-\_]+?) *\: +([0-9]+) +\[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] +\"(.*?)\" +([0-9.+\-eE]+) +([0-9.+\-eE]+) +([\w\-]+?) +(.*); *" regexp = re.compile(pattern) temp = regexp.match(decoded) var_name = temp.group(1) var_type = temp.group(2) min_value = temp.group(3) max_value = temp.group(4) unit = temp.group(5) initial_value = temp.group(6) ev_id = temp.group(7) access_type = temp.group(8) access_nodes = temp.group(9).split(",") db.add_env_var(var_name, {"varType": var_type, "min": min_value, "max": max_value, "unit": unit, "initialValue": initial_value, "evId": ev_id, "accessType": access_type, "accessNodes": access_nodes}) # else: except: print("error with line no: %d" % i) print(line) # Backtracking env_var_names = list(db.env_vars.keys()) for env_var_name in env_var_names: env_var = db.env_vars[env_var_name] if 'SystemEnvVarLongSymbol' in env_var.get("attributes", ""): long_name = env_var["attributes"]["SystemEnvVarLongSymbol"][1:-1] del(env_var["attributes"]["SystemEnvVarLongSymbol"]) db.env_vars[long_name] = db.env_vars.pop(env_var_name) for ecu in db.ecus: if ecu.attributes.get("SystemNodeLongSymbol", None) is not None: ecu.name = ecu.attributes.get("SystemNodeLongSymbol")[1:-1] ecu.del_attribute("SystemNodeLongSymbol") for frame in db.frames: frame.cycle_time = int(float(frame.attributes.get("GenMsgCycleTime", 0))) if frame.attributes.get("SystemMessageLongSymbol", None) is not None: frame.name = frame.attributes.get("SystemMessageLongSymbol")[1:-1] frame.del_attribute("SystemMessageLongSymbol") # receiver is only given in the signals, so do propagate the receiver # to the frame: frame.update_receiver() # extended-flag is implicit in can id, thus repair this: # if frame.id > 0x80000000: # frame.id -= 0x80000000 # frame.extended = 1 for signal in frame.signals: signal.initial_value = float_factory(signal.attributes.get("GenSigStartValue", "0")) signal.cycle_time = int(signal.attributes.get("GenSigCycleTime", 0)) if signal.attribute("SystemSignalLongSymbol") is not None: signal.name = signal.attribute("SystemSignalLongSymbol")[1:-1] signal.del_attribute("SystemSignalLongSymbol") for define in db.global_defines: if db.global_defines[define].type == "STRING": if define in db.attributes: db.attributes[define] = db.attributes[define][1:-1] for define in db.ecu_defines: if db.ecu_defines[define].type == "STRING": for ecu in db.ecus: if define in ecu.attributes: ecu.attributes[define] = ecu.attributes[define][1:-1] for define in db.frame_defines: if db.frame_defines[define].type == "STRING": for frame in db.frames: if define in frame.attributes: frame.attributes[define] = frame.attributes[define][1:-1] for define in db.signal_defines: if db.signal_defines[define].type == "STRING": for frame in db.frames: for signal in frame.signals: if define in signal.attributes: signal.attributes[define] = signal.attributes[define][1:-1] db.enum_attribs_to_values() for frame in db.frames: if "_FD" in frame.attributes.get("VFrameFormat", ""): frame.is_fd = True if "J1939PG" in frame.attributes.get("VFrameFormat", ""): frame.is_j1939 = True db.update_ecu_list() db.del_ecu("Vector__XXX") # db.del_frame_attributes(["GenMsgCycleTime"]) # db.del_signal_attributes(["GenSigCycleTime"]) # db.del_signal_attributes(["GenSigStartValue"]) # if "GenMsgCycleTime" in db.frame_defines: # del (db.frame_defines["GenMsgCycleTime"]) # if "GenSigCycleTime" in db.signal_defines: # del (db.signal_defines["GenSigCycleTime"]) # if "GenSigStartValue" in db.signal_defines: # del (db.signal_defines["GenSigStartValue"]) free_signals_dummy_frame = db.frame_by_name("VECTOR__INDEPENDENT_SIG_MSG") if free_signals_dummy_frame is not None and free_signals_dummy_frame.arbitration_id.id == 0x40000000: db.signals = free_signals_dummy_frame.signals db.del_frame(free_signals_dummy_frame) return db
def load(f, **_options): # type: (typing.BinaryIO, **str) -> canmatrix.CanMatrix db = canmatrix.CanMatrix() if sys.version_info > (3, 0): import io json_data = json.load(io.TextIOWrapper(f, encoding='UTF-8')) else: json_data = json.load(f) if "messages" in json_data: for frame in json_data["messages"]: # new_frame = Frame(frame["id"],frame["name"],8,None) new_frame = canmatrix.Frame(frame["name"], arbitration_id=frame["id"], size=8) if "length" in frame: new_frame.size = frame["length"] new_frame.arbitration_id.extended = frame.get( "is_extended_frame", False) for signal in frame["signals"]: is_little_endian = not signal.get("is_big_endian", False) is_float = signal.get("is_float", False) is_signed = signal.get("is_signed", False) new_signal = canmatrix.Signal( signal["name"], start_bit=signal["start_bit"], size=signal["bit_length"], is_little_endian=is_little_endian, is_signed=is_signed, is_float=is_float, factor=signal["factor"], offset=signal["offset"]) if signal.get("min") is not None: new_signal.min = new_signal.float_factory(signal["min"]) if signal.get("max", False): new_signal.max = new_signal.float_factory(signal["max"]) if signal.get("unit", False): new_signal.unit = signal["unit"] if signal.get("multiplex", False): new_signal.multiplex = signal["multiplex"] if signal.get("values", False): for key in signal["values"]: new_signal.add_values(key, signal["values"][key]) if new_signal.is_little_endian is False: new_signal.set_startbit(new_signal.start_bit, bitNumbering=1, startLittle=True) new_frame.add_signal(new_signal) db.add_frame(new_frame) f.close() return db
def load(f, **options): # type: (typing.IO, **typing.Any) -> canmatrix.CanMatrix dbf_import_encoding = options.get("dbfImportEncoding", 'iso-8859-1') float_factory = options.get('float_factory', default_float_factory) is_j1939 = False db = canmatrix.CanMatrix() mode = '' for line in f: line = line.decode(dbf_import_encoding).strip() if mode == 'SignalDescription': if line.startswith("[END_DESC_SIG]") or line.startswith( "[END_DESC]"): mode = '' else: (bo_id, tem_s, signal_name, comment) = line.split(' ', 3) comment = comment.replace('"', '').replace(';', '') db.frame_by_id( canmatrix.ArbitrationId.from_compound_integer( int(bo_id))).signal_by_name(signal_name).add_comment( comment) if mode == 'BUDescription': if line.startswith("[END_DESC_NODE]") or line.startswith( "[END_DESC]"): mode = '' else: (bu_name, comment) = line.split(' ', 1) comment = comment.replace('"', '').replace(';', '') db.ecu_by_name(bu_name).add_comment(comment) if mode == 'FrameDescription': if line.startswith("[END_DESC_MSG]") or line.startswith( "[END_DESC]"): mode = '' else: (bo_id, tem_s, comment) = line.split(' ', 2) comment = comment.replace('"', '').replace(';', '') frame = db.frame_by_id( canmatrix.ArbitrationId.from_compound_integer(int(bo_id))) if frame: frame.add_comment(comment) elif mode == 'ParamMsgVal': if line.startswith("[END_PARAM_MSG_VAL]"): mode = '' else: (bo_id, tem_s, attrib, value) = line.split(',', 3) db.frame_by_id( canmatrix.ArbitrationId.from_compound_integer( int(bo_id))).add_attribute(attrib.replace('"', ''), value.replace('"', '')) elif mode == 'ParamNodeVal': if line.startswith("[END_PARAM_NODE_VAL]"): mode = '' else: (bu, attrib, value) = line.split(',', 2) db.ecu_by_name(bu).add_attribute(attrib.replace('"', ''), value[1:-1]) elif mode == 'ParamNetVal': if line.startswith("[END_PARAM_NET_VAL]"): mode = '' else: (attrib, value) = line.split(',', 1) db.add_attribute(attrib.replace('"', ''), value[1:-1]) elif mode == 'ParamSigVal': if line.startswith("[END_PARAM_SIG_VAL]"): mode = '' else: (bo_id, tem_s, signal_name, attrib, value) = line.split(',', 4) db.frame_by_id(canmatrix.ArbitrationId.from_compound_integer(int(bo_id)))\ .signal_by_name(signal_name)\ .add_attribute(attrib.replace('"', ''), value[1:-1]) elif mode == 'ParamSig': if line.startswith("[END_PARAM_SIG]"): mode = '' else: (name, define, default) = decode_define(line) db.add_signal_defines(name, define) db.add_define_default(name, default) elif mode == 'ParamMsg': if line.startswith("[END_PARAM_MSG]"): mode = '' else: (name, define, default) = decode_define(line) db.add_frame_defines(name, define) db.add_define_default(name, default) elif mode == 'ParamNode': if line.startswith("[END_PARAM_NODE]"): mode = '' else: (name, define, default) = decode_define(line) db.add_ecu_defines(name, define) db.add_define_default(name, default) elif mode == 'ParamNet': if line.startswith("[END_PARAM_NET]"): mode = '' else: (name, define, default) = decode_define(line) db.add_global_defines(name, define) db.add_define_default(name, default) else: if line.startswith("[PROTOCOL]") and "J1939" in line: is_j1939 = True if line.startswith("[START_DESC_SIG]"): mode = 'SignalDescription' if line.startswith("[START_DESC_MSG]"): mode = 'FrameDescription' if line.startswith("[START_DESC_NODE]"): mode = 'BUDescription' if line.startswith("[START_PARAM_NODE_VAL]"): mode = 'ParamNodeVal' if line.startswith("[START_PARAM_NET_VAL]"): mode = 'ParamNetVal' if line.startswith("[START_PARAM_MSG_VAL]"): mode = 'ParamMsgVal' if line.startswith("[START_PARAM_SIG_VAL]"): mode = 'ParamSigVal' if line.startswith("[START_PARAM_SIG]"): mode = 'ParamSig' if line.startswith("[START_PARAM_MSG]"): mode = 'ParamMsg' if line.startswith("[START_PARAM_NODE]"): mode = 'ParamNode' if line.startswith("[START_PARAM_NET]"): mode = 'ParamNet' if line.startswith("[START_MSG]"): temp_str = line.strip()[11:].strip() temp_array = temp_str.split(',') (name, arb_id, size, n_signals, dummy) = temp_array[0:5] if len(temp_array) > 5: extended = temp_array[5] else: extended = None if len(temp_array) > 6: transmitters = temp_array[6].split() else: transmitters = list() new_frame = db.add_frame( canmatrix.Frame(name, size=int(size), transmitters=transmitters)) if is_j1939: new_frame.arbitration_id.pgn = int(arb_id) else: new_frame.arbitration_id = canmatrix.ArbitrationId.from_compound_integer( int(arb_id)) # Frame(int(Id), name, size, transmitter)) if extended == 'X': logger.debug("Extended") new_frame.arbitration_id.extended = True if line.startswith("[NODE]"): temp_str = line.strip()[6:].strip() bo_list = temp_str.split(',') for bo in bo_list: db.add_ecu(canmatrix.Ecu(bo)) if line.startswith("[START_SIGNALS]"): temp_str = line.strip()[15:].strip() temp_array = temp_str.split(',') (name, size, start_byte, start_bit, sign, max_val, min_val, byteorder, offset, factor, unit, multiplex) = temp_array[0:12] min_val = float_factory(min_val) max_val = float_factory(max_val) factor = float_factory(factor) offset = float_factory(offset) if len(temp_array) > 12: receiver = temp_array[12].split(',') else: receiver = [] if multiplex == 'M': multiplex = 'Multiplexor' elif len(multiplex.strip()) > 0: multiplex = int(multiplex[1:]) else: multiplex = None is_float = False is_signed = False if sign == "U": is_signed = False elif sign == "F" or sign == "D": is_float = True else: is_signed = True start_bit = int(start_bit) start_bit += (int(start_byte) - 1) * 8 new_signal = new_frame.add_signal( canmatrix.Signal(name, start_bit=int(start_bit), size=int(size), is_little_endian=(int(byteorder) == 1), is_signed=is_signed, factor=factor, offset=offset, min=min_val * factor, max=max_val * factor, unit=unit, receivers=receiver, is_float=is_float, multiplex=multiplex)) if int(byteorder) == 0: # this is dummy here, because internal lsb is default - for now new_signal.set_startbit(start_bit, bitNumbering=1, startLittle=True) if line.startswith("[VALUE_DESCRIPTION]"): temp_str = line.strip()[19:].strip() regexp = re.compile("\"(.+)\" *, *(.+)") temp = regexp.match(temp_str) if temp: new_signal.add_values(value=temp.group(2), valueName=temp.group(1)) for frame in db.frames: # receiver is only given in the signals, so do propagate the receiver to the frame: frame.update_receiver() db.enum_attribs_to_values() free_signals_dummy_frame = db.frame_by_name("VECTOR__INDEPENDENT_SIG_MSG") if free_signals_dummy_frame is not None and free_signals_dummy_frame.arbitration_id == 0x40000000: db.signals = free_signals_dummy_frame.signals db.del_frame(free_signals_dummy_frame) return db
def dump(in_db, f, **options): # type: (canmatrix.CanMatrix, typing.IO, **typing.Any) -> None # create copy because export changes database db = copy.deepcopy(in_db) dbc_export_encoding = options.get("dbcExportEncoding", 'iso-8859-1') dbc_export_comment_encoding = options.get("dbcExportCommentEncoding", dbc_export_encoding) compatibility = options.get('compatibility', True) dbc_unique_signal_names_per_frame = options.get("dbcUniqueSignalNames", compatibility) ignore_encoding_errors= options.get("ignoreEncodingErrors", "ignore") write_val_table = options.get("writeValTable", True) whitespace_replacement = options.get("whitespaceReplacement", '_') if whitespace_replacement in ['', None] or {' ', '\t'}.intersection(whitespace_replacement): logger.warning("Settings may result in whitespace in DBC variable names. This is not supported by the DBC format.") if db.contains_fd and db.contains_j1939: db.add_frame_defines("VFrameFormat", 'ENUM "StandardCAN","ExtendedCAN","reserved","J1939PG","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","StandardCAN_FD","ExtendedCAN_FD"') logger.warning("dbc export not fully compatible to candb, because both J1939 and CAN_FD frames are defined") elif db.contains_fd: db.add_global_defines("BusType", "STRING") db.add_attribute("BusType", "CAN FD") db.add_frame_defines("VFrameFormat", 'ENUM "StandardCAN","ExtendedCAN","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","StandardCAN_FD","ExtendedCAN_FD"') elif db.contains_j1939: db.add_global_defines("ProtocolType", "STRING") db.add_attribute("ProtocolType", "J1939") db.add_frame_defines("VFrameFormat", 'ENUM "StandardCAN","ExtendedCAN","reserved","J1939PG"') if db.contains_fd or db.contains_j1939: for frame in db.frames: if frame.is_fd: if frame.arbitration_id.extended: frame.add_attribute("VFrameFormat", "ExtendedCAN_FD") else: frame.add_attribute("VFrameFormat", "StandardCAN_FD") elif frame.is_j1939: frame.add_attribute("VFrameFormat", "J1939PG") else: if frame.arbitration_id.extended: frame.add_attribute("VFrameFormat", "ExtendedCAN") else: frame.add_attribute("VFrameFormat", "StandardCAN") db.enum_attribs_to_keys() # free signals are in special frame in dbc... if len(db.signals) > 0: free_signals_dummy_frame = canmatrix.Frame("VECTOR__INDEPENDENT_SIG_MSG") # set arbitration id manualy, constructor would not allow this special id free_signals_dummy_frame.arbitration_id.extended = True free_signals_dummy_frame.arbitration_id.id = 0x40000000 free_signals_dummy_frame.signals = db.signals db.add_frame(free_signals_dummy_frame) # shorten long environment variable names for env_var_name in copy.deepcopy(db.env_vars): if len(env_var_name) > 32: db.add_env_attribute(env_var_name, "SystemEnvVarLongSymbol", env_var_name) db.env_vars[env_var_name[:32]] = db.env_vars.pop(env_var_name) db.add_env_defines("SystemEnvVarLongSymbol", "STRING") header = "VERSION \"created by canmatrix\"\n\n\nNS_ :\n\nBS_:\n\n" f.write(header.encode(dbc_export_encoding, ignore_encoding_errors)) # ECUs f.write("BU_: ".encode(dbc_export_encoding, ignore_encoding_errors)) for ecu in db.ecus: # fix long ecu names: if len(ecu.name) > 32: ecu.add_attribute("SystemNodeLongSymbol", ecu.name) ecu.name = ecu.name[0:32] db.add_ecu_defines("SystemNodeLongSymbol", "STRING") f.write((ecu.name + " ").encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n\n".encode(dbc_export_encoding, ignore_encoding_errors)) if write_val_table: # ValueTables for table in sorted(db.value_tables): f.write(("VAL_TABLE_ " + table).encode(dbc_export_encoding, ignore_encoding_errors)) for row in db.value_tables[table]: f.write(' {} "{}"'.format(str(row), db.value_tables[table][row]).encode(dbc_export_encoding, ignore_encoding_errors)) f.write(";\n".encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) output_names = collections.defaultdict(dict) # type: typing.Dict[canmatrix.Frame, typing.Dict[canmatrix.Signal, str]] for frame in db.frames: # fix long frame names if len(frame.name) > 32: frame.add_attribute("SystemMessageLongSymbol", frame.name) frame.name = frame.name[0:32] db.add_frame_defines("SystemMessageLongSymbol", "STRING") # fix long signal names for s in frame.signals: if len(s.name) > 32: s.add_attribute("SystemSignalLongSymbol", s.name) s.name = s.name[0:32] db.add_signal_defines("SystemSignalLongSymbol", "STRING") normalized_names = collections.OrderedDict(( (s, normalize_name(s.name, whitespace_replacement)) for s in frame.signals )) # remove "-" from frame names if compatibility: frame.name = re.sub("[^A-Za-z0-9]", whitespace_replacement, frame.name) duplicate_signal_totals = collections.Counter(normalized_names.values()) duplicate_signal_counter = collections.Counter() # type: typing.Counter[str] numbered_names = collections.OrderedDict() # type: ignore if frame.cycle_time != 0: frame.add_attribute("GenMsgCycleTime", frame.cycle_time) for signal in frame.signals: if signal.cycle_time != 0: signal.add_attribute("GenSigCycleTime", signal.cycle_time) if signal.initial_value != 0: signal.add_attribute("GenSigStartValue", signal.initial_value) name = normalized_names[signal] if compatibility: name = re.sub("[^A-Za-z0-9]", whitespace_replacement, name) if name[0].isdigit(): name = whitespace_replacement + name duplicate_signal_counter[name] += 1 if dbc_unique_signal_names_per_frame and duplicate_signal_totals[name] > 1: # TODO: pad to 01 in case of 10+ instances, for example? name += str(duplicate_signal_counter[name] - 1) output_names[frame][signal] = name if len(db.frames) > 0: if max([x.cycle_time for x in db.frames]) > 0: db.add_frame_defines("GenMsgCycleTime", 'INT 0 65535') if len([s for fr in db.frames for s in fr.signals]) > 0: if max([x.cycle_time for y in db.frames for x in y.signals]) > 0: db.add_signal_defines("GenSigCycleTime", 'INT 0 65535') if max([x.initial_value for y in db.frames for x in y.signals]) > 0 or min([x.initial_value for y in db.frames for x in y.signals]) < 0: db.add_signal_defines("GenSigStartValue", 'FLOAT 0 100000000000') # Frames for frame in db.frames: multiplex_written = False if len(frame.transmitters) == 0: frame.add_transmitter("Vector__XXX") f.write( ("BO_ %d " % frame.arbitration_id.to_compound_integer() + frame.name + ": %d " % frame.size + frame.transmitters[0] + "\n").encode(dbc_export_encoding, ignore_encoding_errors)) duplicate_signal_totals = collections.Counter( normalize_name(s.name, whitespace_replacement) for s in frame.signals ) duplicate_signal_counter = collections.Counter() for signal in frame.signals: if signal.multiplex == 'Multiplexor' and multiplex_written and not frame.is_complex_multiplexed: continue signal_line = " SG_ " + output_names[frame][signal] + " " if signal.mux_val is not None: signal_line += "m{}".format(int(signal.mux_val)) if signal.multiplex != 'Multiplexor': signal_line += " " if signal.multiplex == 'Multiplexor': signal_line += "M " multiplex_written = True start_bit = signal.get_startbit(bit_numbering=1) if signal.is_signed: sign = '-' else: sign = '+' signal_line += (": %d|%d@%d%c" % (start_bit, signal.size, signal.is_little_endian, sign)) signal_line += " (%s,%s)" % (format_float(signal.factor), format_float(signal.offset)) signal_line += " [{}|{}]".format(format_float(signal.min), format_float(signal.max)) signal_line += ' "' if signal.unit is None: signal.unit = "" signal_line += signal.unit signal_line += '" ' if len(signal.receivers) == 0: signal.add_receiver('Vector__XXX') signal_line += ','.join(signal.receivers) + "\n" f.write(signal_line.encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # second Sender: for frame in db.frames: if len(frame.transmitters) > 1: f.write(("BO_TX_BU_ %d : %s;\n" % (frame.arbitration_id.to_compound_integer(), ','.join(frame.transmitters))).encode(dbc_export_encoding, ignore_encoding_errors)) # frame comments # wow, there are dbcs where comments are encoded with other coding than rest of dbc... for frame in db.frames: f.write(create_comment_string("BO_", "%d " % frame.arbitration_id.to_compound_integer(), frame.comment, dbc_export_encoding, dbc_export_comment_encoding, dbc_export_encoding)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # signal comments for frame in db.frames: for signal in frame.signals: if signal.comment: name = output_names[frame][signal] f.write(create_comment_string( "SG_", "%d " % frame.arbitration_id.to_compound_integer() + name, signal.comment, dbc_export_encoding, dbc_export_comment_encoding, dbc_export_encoding)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # ecu comments for ecu in db.ecus: if ecu.comment: f.write(create_comment_string("BU_", ecu.name, ecu.comment, dbc_export_encoding, dbc_export_comment_encoding, dbc_export_encoding)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) defaults = {} # type: typing.Dict[str, str] # write defines for (data_type, define) in sorted(list(db.frame_defines.items())): f.write(create_define(data_type, define, "BO_", defaults).encode(dbc_export_encoding, 'replace')) for (data_type, define) in sorted(list(db.signal_defines.items())): f.write(create_define(data_type, define, "SG_", defaults).encode(dbc_export_encoding, 'replace')) for (data_type, define) in sorted(list(db.ecu_defines.items())): f.write(create_define(data_type, define, "BU_", defaults).encode(dbc_export_encoding, 'replace')) for (data_type, define) in sorted(list(db.env_defines.items())): f.write(create_define(data_type, define, "EV_", defaults).encode(dbc_export_encoding, 'replace')) for (data_type, define) in sorted(list(db.global_defines.items())): f.write(create_define(data_type, define, "", defaults).encode(dbc_export_encoding, 'replace')) for define_name in sorted(defaults): f.write(('BA_DEF_DEF_ "' + define_name + '" ').encode(dbc_export_encoding, ignore_encoding_errors) + defaults[define_name].encode(dbc_export_encoding, 'replace') + ';\n'.encode(dbc_export_encoding, ignore_encoding_errors)) # ecu-attributes: for ecu in db.ecus: for attrib, val in sorted(ecu.attributes.items()): f.write(create_attribute_string(attrib, "BU_", ecu.name, val, db.ecu_defines[attrib].type == "STRING").encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # global-attributes: for attrib, val in sorted(db.attributes.items()): f.write(create_attribute_string(attrib, "", "", val, db.global_defines[attrib].type == "STRING").encode( dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # messages-attributes: for frame in db.frames: for attrib, val in sorted(frame.attributes.items()): f.write(create_attribute_string(attrib, "BO_", str(frame.arbitration_id.to_compound_integer()), val, db.frame_defines[attrib].type == "STRING").encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) # signal-attributes: for frame in db.frames: for signal in frame.signals: for attrib, val in sorted(signal.attributes.items()): name = output_names[frame][signal] if isinstance(val, float): val = format_float(val) f.write(create_attribute_string(attrib, "SG_", '%d ' % frame.arbitration_id.to_compound_integer() + name, val, db.signal_defines[attrib].type == "STRING").encode(dbc_export_encoding, ignore_encoding_errors)) f.write("\n".encode(dbc_export_encoding, ignore_encoding_errors)) for env_var_name, env_var in db.env_vars.items(): if "attributes" in env_var: for attribute, value in env_var["attributes"].items(): f.write(create_attribute_string(attribute, "EV_", "", value, db.env_defines[attribute].type == "STRING").encode(dbc_export_encoding, ignore_encoding_errors)) # signal-values: for frame in db.frames: multiplex_written = False for signal in frame.signals: if signal.multiplex == 'Multiplexor' and multiplex_written: continue multiplex_written = True if signal.values: f.write( ('VAL_ %d ' % frame.arbitration_id.to_compound_integer() + output_names[frame][signal]).encode(dbc_export_encoding, ignore_encoding_errors)) for attr_name, val in sorted(signal.values.items(), key=lambda x: int(x[0])): if '"' in val: val = val.replace('"', '\\"') f.write( (' ' + str(attr_name) + ' "' + val + '"').encode(dbc_export_encoding, ignore_encoding_errors)) f.write(";\n".encode(dbc_export_encoding, ignore_encoding_errors)) # SIG_VALTYPE for frame in db.frames: for signal in frame.signals: if signal.is_float: if int(signal.size) > 32: f.write(('SIG_VALTYPE_ %d %s : 2;\n' % (frame.arbitration_id.to_compound_integer(), output_names[frame][signal])).encode( dbc_export_encoding, ignore_encoding_errors)) else: f.write(('SIG_VALTYPE_ %d %s : 1;\n' % (frame.arbitration_id.to_compound_integer(), output_names[frame][signal])).encode( dbc_export_encoding, ignore_encoding_errors)) # signal-groups: for frame in db.frames: for sigGroup in frame.signalGroups: f.write(("SIG_GROUP_ " + str(frame.arbitration_id.to_compound_integer()) + " " + sigGroup.name + " " + str(sigGroup.id) + " :").encode(dbc_export_encoding, ignore_encoding_errors)) for signal in sigGroup.signals: f.write((" " + output_names[frame][signal]).encode(dbc_export_encoding, ignore_encoding_errors)) f.write(";\n".encode(dbc_export_encoding, ignore_encoding_errors)) for frame in db.frames: if frame.is_complex_multiplexed: for signal in frame.signals: if signal.muxer_for_signal is not None: f.write(("SG_MUL_VAL_ %d %s %s " % (frame.arbitration_id.to_compound_integer(), signal.name, signal.muxer_for_signal)).encode(dbc_export_encoding, ignore_encoding_errors)) f.write((", ".join(["%d-%d" % (a, b) for a, b in signal.mux_val_grp])).encode(dbc_export_encoding, ignore_encoding_errors)) f.write(";\n".encode(dbc_export_encoding, ignore_encoding_errors)) for env_var_name in db.env_vars: env_var = db.env_vars[env_var_name] f.write(("EV_ {0} : {1} [{2}|{3}] \"{4}\" {5} {6} {7} {8};\n".format( env_var_name, env_var["varType"], env_var["min"], env_var["max"], env_var["unit"], env_var["initialValue"], env_var["evId"], env_var["accessType"], ",".join(env_var["accessNodes"]))).encode(dbc_export_encoding, ignore_encoding_errors))
def load(f, **options): # type: (typing.IO, **typing.Any) -> canmatrix.CanMatrix if 'symImportEncoding' in options: sym_import_encoding = options["symImportEncoding"] else: sym_import_encoding = 'iso-8859-1' calc_min_for_none = options.get('calc_min_for_none') calc_max_for_none = options.get('calc_max_for_none') float_factory = options.get('float_factory', default_float_factory) class Mode(object): glob, enums, send, sendReceive, receive = list(range(5)) mode = Mode.glob frame_name = "" frame = None db = canmatrix.CanMatrix() db.add_frame_defines("Receivable", 'BOOL False True') db.add_frame_defines("Sendable", 'BOOL False True') db.add_signal_defines("HexadecimalOutput", 'BOOL False True') db.add_signal_defines("DisplayDecimalPlaces", 'INT 0 65535') db.add_signal_defines("LongName", 'STR') for line_count, line in enumerate(f, 1): try: line = line.decode(sym_import_encoding).strip() # ignore empty line: if line.__len__() == 0: continue # switch mode: if line[0:7] == "{ENUMS}": mode = Mode.enums continue if line[0:6] == "{SEND}": mode = Mode.send continue if line[0:13] == "{SENDRECEIVE}": mode = Mode.sendReceive continue if line[0:9] == "{RECEIVE}": mode = Mode.receive continue if mode == Mode.glob: # just ignore headers... continue elif mode == Mode.enums: line = line.strip() if line.startswith('enum'): while not line[5:].strip().endswith(')'): line = line.split('//')[0] if sys.version_info > ( 3, 0): # is there a clean way to to it? line += ' ' + f.readline().decode( sym_import_encoding).strip() else: line += ' ' + next(f).decode( sym_import_encoding).strip() line = line.split('//')[0] temp_array = line[5:].strip().rstrip(')').split('(', 1) val_table_name = temp_array[0] split = canmatrix.utils.quote_aware_space_split( temp_array[1]) temp_array = [s.rstrip(',') for s in split] temp_val_table = {} for entry in temp_array: temp_val_table[entry.split( '=')[0].strip()] = entry.split('=')[1].replace( '"', '').strip() db.add_value_table(val_table_name, temp_val_table) elif mode in {Mode.send, Mode.sendReceive, Mode.receive}: if line.startswith('['): multiplexor = None # found new frame: if frame_name != line.replace('[', '').replace( ']', '').replace('"', '').strip(): frame_name = line.replace('[', '').replace(']', '').replace( '"', '').strip() # TODO: CAMPid 939921818394902983238 if frame is not None: if len(frame.mux_names) > 0: frame.signal_by_name( frame.name + "_MUX").values = frame.mux_names db.add_frame(frame) frame = canmatrix.Frame(frame_name) frame.add_attribute( 'Receivable', mode in {Mode.receive, Mode.sendReceive}) frame.add_attribute( 'Sendable', mode in {Mode.send, Mode.sendReceive}) # key value: elif line.startswith('Var') or line.startswith('Mux'): tmp_mux = line[:3] line = line[4:] # comment = "" index_offset = 1 if tmp_mux == "Mux": index_offset = 0 comment = "" if '//' in line: split = line.split('//', 1) comment = split[1].strip() line = split[0].strip() line = line.replace(' ', ' "" ') temp_array = canmatrix.utils.quote_aware_space_split(line) sig_name = temp_array[0] is_float = False if index_offset != 1: is_signed = True else: is_signed = False if temp_array[1] == 'unsigned': pass elif temp_array[1] == 'bit': # TODO: actually support bit instead of interpreting as # an unsigned pass elif temp_array[1] == 'signed': is_signed = True elif temp_array[1] in ['float', 'double']: is_float = True elif temp_array[1] in ['string']: # TODO: actually support these variable types instead # of skipping print('Variable type \'{}\' found and skipped'. format(temp_array[1])) continue else: raise ValueError( 'Unknown type \'{}\' found'.format( temp_array[1])) start_bit = int(temp_array[index_offset + 1].split(',')[0]) signal_length = int(temp_array[index_offset + 1].split(',')[1]) intel = True unit = "" factor = 1 max_value = None min_value = None long_name = None start_value = None offset = 0 value_table_name = None hexadecimal_output = False display_decimal_places = None if tmp_mux == "Mux": multiplexor = temp_array[2] if multiplexor[-1] == 'h': multiplexor = int(multiplexor[:-1], 16) else: multiplexor = int(multiplexor) if multiplexor in frame.mux_names: raise DuplicateMuxIdError( id=multiplexor, old=frame.mux_names[multiplexor], new=sig_name, line_number=line_count, line=line, ) frame.mux_names[multiplexor] = sig_name index_offset = 2 for switch in temp_array[index_offset + 2:]: if switch == "-m": intel = False elif switch == "-h": hexadecimal_output = True elif switch.startswith('/'): s = switch[1:].split(':', 1) if s[0] == 'u': unit = s[1] elif s[0] == 'f': factor = s[1] elif s[0] == 'd': start_value = s[1] elif s[0] == 'p': display_decimal_places = s[1] elif s[0] == 'o': offset = s[1] elif s[0] == 'e': value_table_name = s[1] elif s[0] == 'max': max_value = s[1] elif s[0] == 'min': min_value = s[1] elif s[0] == 'ln': long_name = s[1] # else: # print switch # else: # print switch if tmp_mux == "Mux": signal = frame.signal_by_name(frame_name + "_MUX") if signal is None: extras = {} if calc_min_for_none is not None: extras['calc_min_for_none'] = calc_min_for_none if calc_max_for_none is not None: extras['calc_max_for_none'] = calc_max_for_none # if float_factory is not None: # extras['float_factory'] = float_factory signal = canmatrix.Signal(frame_name + "_MUX", start_bit=int(start_bit), size=int(signal_length), is_little_endian=intel, is_signed=is_signed, is_float=is_float, factor=factor, offset=offset, unit=unit, multiplex='Multiplexor', comment=comment, **extras) if min_value is not None: signal.min = float_factory(min_value) if max_value is not None: signal.max = float_factory(max_value) # signal.add_comment(comment) if intel is False: # motorola set/convert start bit signal.set_startbit(start_bit) frame.add_signal(signal) signal.comments[multiplexor] = comment else: # signal = Signal(sigName, startBit, signalLength, intel, is_signed, factor, offset, min, max, unit, "", multiplexor) extras = {} if calc_min_for_none is not None: extras['calc_min_for_none'] = calc_min_for_none if calc_max_for_none is not None: extras['calc_max_for_none'] = calc_max_for_none # if float_factory is not None: # extras['float_factory'] = float_factory signal = canmatrix.Signal(sig_name, start_bit=int(start_bit), size=int(signal_length), is_little_endian=intel, is_signed=is_signed, is_float=is_float, factor=factor, offset=offset, unit=unit, multiplex=multiplexor, comment=comment, **extras) if min_value is not None: signal.min = float_factory(min_value) if max_value is not None: signal.max = float_factory(max_value) if intel is False: # motorola set/convert start bit signal.set_startbit(start_bit) if value_table_name is not None: signal.values = db.value_tables[value_table_name] signal.enumeration = value_table_name # signal.add_comment(comment) # ... (1 / ...) because this somehow made 59.8/0.1 be 598.0 rather than 597.9999999999999 if start_value is not None: signal.initial_value = float_factory(start_value) frame.add_signal(signal) if long_name is not None: signal.add_attribute("LongName", long_name) if hexadecimal_output: signal.add_attribute("HexadecimalOutput", str(True)) if display_decimal_places is not None: signal.add_attribute("DisplayDecimalPlaces", display_decimal_places) # variable processing elif line.startswith('ID'): comment = "" if '//' in line: split = line.split('//', 1) comment = split[1].strip() line = split[0].strip() frame.arbitration_id.id = int( line.split('=')[1].strip()[:-1], 16) frame.add_comment(comment) elif line.startswith('Type'): if line.split('=')[1][:8] == "Extended": frame.arbitration_id.extended = 1 elif line.startswith('DLC'): frame.size = int(line.split('=')[1]) elif line.startswith('CycleTime'): frame.cycle_time = int(line.split('=')[1].strip()) # else: # print line # else: # print "Unrecognized line: " + l + " (%d) " % i except Exception as e: if not isinstance(e, ParsingError): ParsingError( message=str(e), line_number=line_count, line=line, original=e, ) db.load_errors.append(e) logger.error("Error decoding line %d" % line_count) logger.error(line) # TODO: CAMPid 939921818394902983238 if frame is not None: if len(frame.mux_names) > 0: frame.signal_by_name(frame.name + "_MUX").values = frame.mux_names db.add_frame(frame) return db
def dump(mydb, f, **options): # type: (canmatrix.CanMatrix, typing.IO, **typing.Any) -> None # create copy because export changes database db = copy.deepcopy(mydb) dbf_export_encoding = options.get("dbfExportEncoding", 'iso-8859-1') ignore_encoding_errors = options.get("ignoreEncodingErrors", "strict") db.enum_attribs_to_keys() if len(db.signals) > 0: free_signals_dummy_frame = canmatrix.Frame( "VECTOR__INDEPENDENT_SIG_MSG") free_signals_dummy_frame.arbitration_id = canmatrix.ArbitrationId( id=0x40000000, extended=True) free_signals_dummy_frame.signals = db.signals db.add_frame(free_signals_dummy_frame) out_str = """//******************************BUSMASTER Messages and signals Database ******************************// [DATABASE_VERSION] 1.3 [PROTOCOL] CAN [BUSMASTER_VERSION] [1.7.2] [NUMBER_OF_MESSAGES] """ out_str += str(len(db.frames)) + "\n" cycle_times_of_all_frames = [x.cycle_time for x in db.frames] if len(cycle_times_of_all_frames) > 0 and max( cycle_times_of_all_frames) > 0: db.add_frame_defines("GenMsgCycleTime", 'INT 0 65535') cycle_times_of_all_singals = [ x.cycle_time for y in db.frames for x in y.signals ] if len(cycle_times_of_all_singals) > 0 and max( cycle_times_of_all_singals) > 0: db.add_signal_defines("GenSigCycleTime", 'INT 0 65535') initial_values_of_all_singals = [ x.initial_value for y in db.frames for x in y.signals ] if len(initial_values_of_all_singals) > 0 and ( max(initial_values_of_all_singals) > 0 or min(initial_values_of_all_singals)) < 0: db.add_signal_defines("GenSigStartValue", 'FLOAT 0 100000000000') # Frames for frame in db.frames: if frame.is_complex_multiplexed: logger.error( "export complex multiplexers is not supported - ignoring frame " + frame.name) continue # Name unMsgId m_ucLength m_ucNumOfSignals m_cDataFormat m_cFrameFormat? m_txNode # m_cDataFormat Data format: 1-Intel, 0-Motorola -- always 1 original converter decides based on signal count. # cFrameFormat Standard 'S' Extended 'X' extended = 'X' if frame.arbitration_id.extended == 1 else 'S' out_str += "[START_MSG] " + frame.name + \ ",%d,%d,%d,1,%c," % (frame.arbitration_id.id, frame.size, len(frame.signals), extended) if not frame.transmitters: frame.add_transmitter("Vector__XXX") # DBF does not support multiple Transmitters out_str += frame.transmitters[0] + "\n" for signal in frame.signals: # m_acName ucLength m_ucWhichByte m_ucStartBit # m_ucDataFormat m_fOffset m_fScaleFactor m_acUnit m_acMultiplex m_rxNode # m_ucDataFormat which_byte = int( math.floor( signal.get_startbit(bit_numbering=1, start_little=True) / 8) + 1) sign = 'I' if not signal.is_signed: sign = 'U' if signal.is_float: if signal.size > 32: sign = 'D' else: sign = 'F' if signal.factor == 0: signal.factor = 1 out_str += "[START_SIGNALS] " + signal.name \ + ",%d,%d,%d,%c," % (signal.size, which_byte, int(signal.get_startbit(bit_numbering=1, start_little=True)) % 8, sign) + '{},{}'.format(float(signal.max) / float(signal.factor), float(signal.min) / float(signal.factor)) out_str += ",%d,%s,%s" % (signal.is_little_endian, signal.offset, signal.factor) multiplex = "" if signal.multiplex is not None: if signal.multiplex == 'Multiplexor': multiplex = 'M' else: multiplex = 'm' + str(signal.multiplex) out_str += "," + signal.unit + ",%s," % multiplex + \ ','.join(signal.receivers) + "\n" if len(signal.values) > 0: for value, name in sorted(list(signal.values.items())): out_str += '[VALUE_DESCRIPTION] "' + \ name + '",' + str(value) + '\n' out_str += "[END_MSG]\n\n" # Board units out_str += "[NODE] " count = 1 for ecu in db.ecus: out_str += ecu.name if count < len(db.ecus): out_str += "," count += 1 out_str += "\n" out_str += "[START_DESC]\n\n" # BU-descriptions out_str += "[START_DESC_MSG]\n" for frame in db.frames: if frame.comment is not None: comment = frame.comment.replace("\n", " ") out_str += str(frame.arbitration_id.id) + ' S "' + comment + '";\n' out_str += "[END_DESC_MSG]\n" # Frame descriptions out_str += "[START_DESC_NODE]\n" for ecu in db.ecus: if ecu.comment is not None: comment = ecu.comment.replace("\n", " ") out_str += ecu.name + ' "' + comment + '";\n' out_str += "[END_DESC_NODE]\n" # signal descriptions out_str += "[START_DESC_SIG]\n" for frame in db.frames: if frame.is_complex_multiplexed: continue for signal in frame.signals: if signal.comment is not None: comment = signal.comment.replace("\n", " ") out_str += "%d S " % frame.arbitration_id.id + signal.name + ' "' + comment + '";\n' out_str += "[END_DESC_SIG]\n" out_str += "[END_DESC]\n\n" out_str += "[START_PARAM]\n" # db-parameter out_str += "[START_PARAM_NET]\n" for (data_type, define) in sorted(list(db.global_defines.items())): default_val = define.defaultValue if default_val is None: default_val = "0" out_str += '"' + data_type + '",' + define.definition.replace( ' ', ',') + ',' + default_val + '\n' out_str += "[END_PARAM_NET]\n" # bu-parameter out_str += "[START_PARAM_NODE]\n" for (data_type, define) in sorted(list(db.ecu_defines.items())): default_val = define.defaultValue if default_val is None: default_val = "0" out_str += '"' + data_type + '",' + define.definition.replace( ' ', ',') + ',' + default_val + '\n' out_str += "[END_PARAM_NODE]\n" # frame-parameter out_str += "[START_PARAM_MSG]\n" for (data_type, define) in sorted(list(db.frame_defines.items())): default_val = define.defaultValue if default_val is None: default_val = "0" out_str += '"' + data_type + '",' + define.definition.replace( ' ', ',') + '\n' # + ',' + default_val + '\n' out_str += "[END_PARAM_MSG]\n" # signal-parameter out_str += "[START_PARAM_SIG]\n" for (data_type, define) in list(db.signal_defines.items()): default_val = define.defaultValue if default_val is None: default_val = "0" out_str += '"' + data_type + '",' + define.definition.replace( ' ', ',') + ',' + default_val + '\n' out_str += "[END_PARAM_SIG]\n" out_str += "[START_PARAM_VAL]\n" # board unit attributes: out_str += "[START_PARAM_NODE_VAL]\n" for ecu in db.ecus: for attrib, val in sorted(list(ecu.attributes.items())): out_str += ecu.name + ',"' + attrib + '","' + val + '"\n' out_str += "[END_PARAM_NODE_VAL]\n" # messages-attributes: out_str += "[START_PARAM_MSG_VAL]\n" for frame in db.frames: if frame.is_complex_multiplexed: continue for attrib, val in sorted(list(frame.attributes.items())): out_str += str(frame.arbitration_id.id ) + ',S,"' + attrib + '","' + val + '"\n' out_str += "[END_PARAM_MSG_VAL]\n" # signal-attributes: out_str += "[START_PARAM_SIG_VAL]\n" for frame in db.frames: if frame.is_complex_multiplexed: continue for signal in frame.signals: for attrib, val in sorted(list(signal.attributes.items())): out_str += str(frame.arbitration_id.id) + ',S,' + signal.name + \ ',"' + attrib + '","' + val + '"\n' out_str += "[END_PARAM_SIG_VAL]\n" out_str += "[END_PARAM_VAL]\n" f.write(out_str.encode(dbf_export_encoding, ignore_encoding_errors))
import math dbc = canmatrix.CanMatrix() dbc.add_frame( canmatrix.Frame( name="Panic", arbitration_id=0, transmitters=["air_ctrl", "bms_core", "throttle", "brakelight_bspd"], comment="This is bad. Liek really bad", signals=[ canmatrix.Signal( name="Panic", start_bit=0, size=2, is_float=False, is_little_endian=False, is_signed=False, factor=1, offset=1, min=0, max=1, receivers=[ "air_ctrl", "bms_core", "throttle", "brakelight_bspd" ], ) ], )) for file in os.listdir('./mini_yamls'): with open(f"./mini_yamls/{file}", 'r') as yaml_file: data = yaml.load(yaml_file) data = data["MessagesTX"]
def load(f, **options): # type: (typing.IO, **typing.Any) -> typing.Dict[str, canmatrix.CanMatrix] float_factory = options.get("float_factory", default_float_factory) # type: typing.Callable dbs = {} # type: typing.Dict[str, canmatrix.CanMatrix] tree = etree.parse(f) root = tree.getroot() namespace = "{" + tree.xpath('namespace-uri(.)') + "}" node_list = {} nodes = root.findall('./' + namespace + 'Node') buses = root.findall('./' + namespace + 'Bus') counter = 0 for bus in buses: db = canmatrix.CanMatrix() db.add_frame_defines("GenMsgCycleTime", 'INT 0 65535') for node in nodes: db.ecus.append(canmatrix.Ecu(node.get('name'))) node_list[node.get('id')] = node.get('name') messages = bus.findall('./' + namespace + 'Message') for message in messages: dlc = None # new_frame = Frame(int(message.get('id'), 16), message.get('name'), 1, None) new_frame = canmatrix.Frame(message.get('name')) if 'triggered' in message.attrib: new_frame.add_attribute("GenMsgCycleTime", message.get('interval')) if 'length' in message.attrib: dlc = int(message.get('length')) new_frame.size = dlc if 'format' in message.attrib and message.get( 'format') == "extended": new_frame.arbitration_id = canmatrix.ArbitrationId( int(message.get('id'), 16), extended=True) else: new_frame.arbitration_id = canmatrix.ArbitrationId( int(message.get('id'), 16), extended=False) multiplex = message.find('./' + namespace + 'Multiplex') if multiplex is not None: start_bit = 0 if 'offset' in multiplex.attrib: start_bit = int(multiplex.get('offset')) signal_size = 1 if 'length' in multiplex.attrib: signal_size = int(multiplex.get('length')) is_little_endian = True min_value = None max_value = None values = multiplex.find('./' + namespace + 'Value') if values is not None: if 'min' in values.attrib: min_value = float_factory(values.get('min')) if 'max' in values.attrib: max_value = float_factory(values.get('max')) unit = "" offset = float_factory('0') factor = float_factory('1') is_signed = False if 'type' in multiplex.attrib: if multiplex.get('type') == 'signed': is_signed = True receiver_names = [] # type: typing.List[str] consumers = multiplex.findall('./' + namespace + 'Consumer') for consumer in consumers: node_refs = consumer.findall('./' + namespace + 'NodeRef') for node_ref in node_refs: receiver_names.append(node_list[node_ref.get('id')]) new_signal = canmatrix.Signal( multiplex.get('name'), start_bit=int(start_bit), size=int(signal_size), is_little_endian=is_little_endian, is_signed=is_signed, factor=factor, offset=offset, unit=unit, receivers=receiver_names, multiplex='Multiplexor') if min_value is not None: new_signal.min = min_value if max_value is not None: new_signal.max = max_value if is_little_endian is False: # motorola/big_endian set/convert startbit new_signal.set_startbit(start_bit) notes = multiplex.findall('./' + namespace + 'Notes') comment = "" for note in notes: comment += note.text new_signal.add_comment(comment) label_sets = multiplex.findall('./' + namespace + 'LabelSet') for label_set in label_sets: labels = label_set.findall('./' + namespace + 'Label') for label in labels: name = label.get('name') value = label.get('value') new_signal.add_values(value, name) new_frame.add_signal(new_signal) mux_groups = multiplex.findall('./' + namespace + 'MuxGroup') for mux_group in mux_groups: mux = mux_group.get('count') signals = mux_group.findall('./' + namespace + 'Signal') for signal in signals: new_signal = parse_signal(signal, mux, namespace, node_list, float_factory) new_frame.add_signal(new_signal) signals = message.findall('./' + namespace + 'Signal') producers = message.findall('./' + namespace + 'Producer') for producer in producers: node_refs = producer.findall('./' + namespace + 'NodeRef') for node_ref in node_refs: new_frame.add_transmitter(node_list[node_ref.get('id')]) for signal in signals: new_signal = parse_signal(signal, None, namespace, node_list, float_factory) new_frame.add_signal(new_signal) notes = message.findall('./' + namespace + 'Notes') comment = "" for note in notes: if note.text is not None: comment += note.text new_frame.add_comment(comment) if dlc is None: new_frame.calc_dlc() else: new_frame.size = dlc new_frame.update_receiver() db.add_frame(new_frame) name = bus.get('name') if not name: name = "CAN%d" % counter counter += 1 dbs[name] = db return dbs
import string dbc = canmatrix.CanMatrix() #import pdb #pdb.set_trace() dbc.add_frame( canmatrix.Frame( name="Panic", arbitration_id=0, comment="This is bad. Liek really bad", signals=[ canmatrix.Signal( name="Panic", start_bit=0, size=2, is_float=False, is_little_endian=False, is_signed=False, factor=1, offset=1, min=0, max=1, ) ], )) for file in os.listdir('./mini_yamls'): with open(f"./mini_yamls/{file}", 'r') as yaml_file: data = yaml.load(yaml_file) data_tx = data["MessagesTX"] data_rx = data["MessagesRX"]
def load(filename, **options): # type: (typing.BinaryIO, **str) -> canmatrix.CanMatrix # use xlrd excel reader if available, because its more robust if options.get('xlsxLegacy', False) is True: logger.error("xlsx: using legacy xlsx-reader - please get xlrd working for better results!") else: import canmatrix.formats.xls as xls_loader # we need alias, otherwise we hide the globally imported canmatrix return xls_loader.load(filename, **options) # else use this hack to read xlsx motorola_bit_format = options.get("xlsMotorolaBitFormat", "msbreverse") sheet = read_xlsx(filename, sheet=1, header=True) db = canmatrix.CanMatrix() all_letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' letter_index = list(all_letters) letter_index += ["%s%s" % (a, b) for a in all_letters for b in all_letters] # Defines not imported... db.add_frame_defines("GenMsgDelayTime", 'INT 0 65535') db.add_frame_defines("GenMsgCycleTimeActive", 'INT 0 65535') db.add_frame_defines("GenMsgNrOfRepetitions", 'INT 0 65535') launch_types = [] # type: typing.List[str] db.add_signal_defines("GenSigSNA", 'STRING') ecu_start = ecu_end = 0 if 'Byteorder' in list(sheet[0].values()): for key in sheet[0]: if sheet[0][key].strip() == 'Byteorder': ecu_start = letter_index.index(key) + 1 break else: for key in sheet[0]: if sheet[0][key].strip() == 'Signal Not Available': ecu_start = letter_index.index(key) + 1 for key in sheet[0]: if sheet[0][key].strip() == 'Value': ecu_end = letter_index.index(key) # ECUs: for x in range(ecu_start, ecu_end): db.add_ecu(canmatrix.Ecu(sheet[0][letter_index[x]])) # initialize: frame_id = None signal_name = "" signal_length = 8 new_frame = None # type: typing.Optional[canmatrix.Frame] new_signal = None # type: typing.Optional[canmatrix.Signal] for row in sheet[1]: # ignore empty row if 'ID' not in row: continue # new frame detected if row['ID'] != frame_id: # new Frame frame_id = row['ID'] frame_name = row['Frame Name'] cycle_time = get_if_possible(row, 'Cycle Time [ms]', '0') launch_type = get_if_possible(row, 'Launch Type') dlc = 8 # launch_param = get_if_possible(row, 'Launch Parameter', '0') # launch_param = str(int(launch_param)) if frame_id.endswith("xh"): new_frame = canmatrix.Frame(frame_name, arbitration_id=int(frame_id[:-2], 16), size=dlc) new_frame.arbitration_id.extended = True else: new_frame = canmatrix.Frame(frame_name, arbitration_id=int(frame_id[:-1], 16), size=dlc) db.add_frame(new_frame) # eval launch_type if launch_type is not None: new_frame.add_attribute("GenMsgSendType", launch_type) if launch_type not in launch_types: launch_types.append(launch_type) new_frame.cycle_time = cycle_time # new signal detected if 'Signal Name' in row and row['Signal Name'] != signal_name: receiver = [] # type: typing.List[str] start_byte = int(row["Signal Byte No."]) start_bit = int(row['Signal Bit No.']) signal_name = row['Signal Name'] signal_comment = get_if_possible(row, 'Signal Function') signal_length = int(row['Signal Length [Bit]']) # signal_default = get_if_possible(row, 'Signal Default') # signal_sna = get_if_possible(row, 'Signal Not Available') multiplex = None # type: typing.Union[str, int, None] if signal_comment is not None and signal_comment.startswith('Mode Signal:'): multiplex = 'Multiplexor' signal_comment = signal_comment[12:] elif signal_comment is not None and signal_comment.startswith('Mode '): mux, signal_comment = signal_comment[4:].split(':', 1) multiplex = int(mux.strip()) signal_byte_order = get_if_possible(row, 'Byteorder') if signal_byte_order is not None: if 'i' in signal_byte_order: is_little_endian = True else: is_little_endian = False else: is_little_endian = True # Default Intel is_signed = False if signal_name != "-": for x in range(ecu_start, ecu_end): ecu_name = sheet[0][letter_index[x]].strip() ecu_sender_receiver = get_if_possible(row, ecu_name) if ecu_sender_receiver is not None: if 's' in ecu_sender_receiver: new_frame.add_transmitter(ecu_name) if 'r' in ecu_sender_receiver: receiver.append(ecu_name) new_signal = canmatrix.Signal(signal_name, start_bit=(start_byte - 1) * 8 + start_bit, size=signal_length, is_little_endian=is_little_endian, is_signed=is_signed, receivers=receiver, multiplex=multiplex) if not is_little_endian: # motorola if motorola_bit_format == "msb": new_signal.set_startbit( (start_byte - 1) * 8 + start_bit, bitNumbering=1) elif motorola_bit_format == "msbreverse": new_signal.set_startbit((start_byte - 1) * 8 + start_bit) else: # motorola_bit_format == "lsb" new_signal.set_startbit( (start_byte - 1) * 8 + start_bit, bitNumbering=1, startLittle=True ) new_frame.add_signal(new_signal) new_signal.add_comment(signal_comment) # function = get_if_possible(row, 'Function / Increment Unit') value = get_if_possible(row, 'Value') value_name = get_if_possible(row, 'Name / Phys. Range') if value_name == 0 or value_name is None: value_name = "0" elif value_name == 1: value_name = "1" test = value_name # .encode('utf-8') factor = get_if_possible(row, 'Function / Increment Unit') if factor is not None: factor = factor.strip() if " " in factor and factor[0].isdigit(): (factor, unit) = factor.split(" ", 1) factor = factor.strip() unit = unit.strip() new_signal.unit = unit new_signal.factor = float(factor) else: unit = factor.strip() new_signal.unit = unit new_signal.factor = 1 if ".." in test: (mini, maxi) = test.strip().split("..", 2) try: new_signal.offset = new_signal.float_factory(mini) new_signal.min = new_signal.float_factory(mini) new_signal.max = new_signal.float_factory(maxi) except ValueError: new_signal.offset = 0 new_signal.min = None new_signal.max = None elif len(value_name) > 0: if value is not None and value.strip(): value_int = int(float(value)) new_signal.add_values(value_int, value_name) maxi = pow(2, signal_length) - 1 new_signal.max = float(maxi) else: new_signal.offset = 0 new_signal.min = None new_signal.max = None # dlc-estimation / dlc is not in xls, thus calculate a minimum-dlc: for frame in db.frames: frame.update_receiver() frame.calc_dlc() launch_type_enum = "ENUM" for launch_type in launch_types: if len(launch_type) > 0: launch_type_enum += ' "' + launch_type + '",' db.add_frame_defines("GenMsgSendType", launch_type_enum[:-1]) db.set_fd_type() return db
def load(file, **options): # type: (typing.IO, **typing.Any) -> canmatrix.CanMatrix motorola_bit_format = options.get("xlsMotorolaBitFormat", "msbreverse") float_factory = options.get("float_factory", default_float_factory) additional_inputs = dict() wb = xlrd.open_workbook(file_contents=file.read()) sh = wb.sheet_by_index(0) db = canmatrix.CanMatrix() # Defines not imported... # db.add_ecu_defines("NWM-Stationsadresse", 'HEX 0 63') # db.add_ecu_defines("NWM-Knoten", 'ENUM "nein","ja"') db.add_frame_defines("GenMsgCycleTime", 'INT 0 65535') db.add_frame_defines("GenMsgDelayTime", 'INT 0 65535') db.add_frame_defines("GenMsgCycleTimeActive", 'INT 0 65535') db.add_frame_defines("GenMsgNrOfRepetitions", 'INT 0 65535') # db.addFrameDefines("GenMsgStartValue", 'STRING') launch_types = [] # type: typing.List[str] # db.addSignalDefines("GenSigStartValue", 'HEX 0 4294967295') db.add_signal_defines("GenSigSNA", 'STRING') # eval search for correct columns: index = {} for i in range(sh.ncols): value = sh.cell(0, i).value if value == "ID": index['ID'] = i elif "Frame Name" in value: index['frameName'] = i elif "Cycle" in value: index['cycle'] = i elif "Launch Type" in value: index['launchType'] = i elif "Launch Parameter" in value: index['launchParam'] = i elif "Signal Byte No." in value: index['startbyte'] = i elif "Signal Bit No." in value: index['startbit'] = i elif "Signal Name" in value: index['signalName'] = i elif "Signal Function" in value: index['signalComment'] = i elif "Signal Length" in value: index['signalLength'] = i elif "Signal Default" in value: index['signalDefault'] = i elif "Signal Not Ava" in value: index['signalSNA'] = i elif "Value" in value: index['Value'] = i elif "Name / Phys" in value: index['ValueName'] = i elif "Function /" in value: index['function'] = i elif "Byteorder" in value: index['byteorder'] = i else: if 'Value' in index and i > index['Value']: additional_inputs[i] = value if "byteorder" in index: index['ECUstart'] = index['byteorder'] + 1 else: index['ECUstart'] = index['signalSNA'] + 1 index['ECUend'] = index['Value'] # ECUs: for x in range(index['ECUstart'], index['ECUend']): db.add_ecu(canmatrix.Ecu(sh.cell(0, x).value)) # initialize: frame_id = None signal_name = "" new_frame = None for row_num in range(1, sh.nrows): # ignore empty row if len(sh.cell(row_num, index['ID']).value) == 0: break # new frame detected if sh.cell(row_num, index['ID']).value != frame_id: # new Frame frame_id = sh.cell(row_num, index['ID']).value frame_name = sh.cell(row_num, index['frameName']).value cycle_time = sh.cell(row_num, index['cycle']).value launch_type = sh.cell(row_num, index['launchType']).value dlc = 8 launch_param = sh.cell(row_num, index['launchParam']).value try: launch_param = str(int(launch_param)) except: launch_param = "0" new_frame = canmatrix.Frame(frame_name, size=dlc) if frame_id.endswith("xh"): new_frame.arbitration_id = canmatrix.ArbitrationId( int(frame_id[:-2], 16), extended=True) else: new_frame.arbitration_id = canmatrix.ArbitrationId( int(frame_id[:-2], 16), extended=False) db.add_frame(new_frame) # eval launch_type if launch_type is not None: new_frame.add_attribute("GenMsgSendType", launch_type) if launch_type not in launch_types: launch_types.append(launch_type) # eval cycle time try: cycle_time = int(cycle_time) except: cycle_time = 0 new_frame.add_attribute("GenMsgCycleTime", str(int(cycle_time))) for additional_index in additional_inputs: if "frame" in additional_inputs[additional_index]: command_str = additional_inputs[additional_index].replace( "frame", "new_frame") command_str += "=" command_str += str( sh.cell(row_num, additional_index).value) exec(command_str) # new signal detected if sh.cell(row_num, index['signalName']).value != signal_name \ and len(sh.cell(row_num, index['signalName']).value) > 0: # new Signal receiver = [] start_byte = int(sh.cell(row_num, index['startbyte']).value) start_bit = int(sh.cell(row_num, index['startbit']).value) signal_name = sh.cell(row_num, index['signalName']).value signal_comment = sh.cell(row_num, index['signalComment']).value.strip() signal_length = int(sh.cell(row_num, index['signalLength']).value) signal_default = sh.cell(row_num, index['signalDefault']).value signal_sna = sh.cell(row_num, index['signalSNA']).value multiplex = None # type: typing.Union[str, int, None] if signal_comment.startswith('Mode Signal:'): multiplex = 'Multiplexor' signal_comment = signal_comment[12:] elif signal_comment.startswith('Mode '): mux, signal_comment = signal_comment[4:].split(':', 1) multiplex = int(mux.strip()) if index.get("byteorder", False): signal_byte_order = sh.cell(row_num, index['byteorder']).value if 'i' in signal_byte_order: is_little_endian = True else: is_little_endian = False else: is_little_endian = True # Default Intel is_signed = False if signal_name != "-": for x in range(index['ECUstart'], index['ECUend']): if 's' in sh.cell(row_num, x).value: new_frame.add_transmitter(sh.cell(0, x).value.strip()) if 'r' in sh.cell(row_num, x).value: receiver.append(sh.cell(0, x).value.strip()) new_signal = canmatrix.Signal( signal_name, start_bit=(start_byte - 1) * 8 + start_bit, size=int(signal_length), is_little_endian=is_little_endian, is_signed=is_signed, receivers=receiver, multiplex=multiplex) if not is_little_endian: # motorola if motorola_bit_format == "msb": new_signal.set_startbit( (start_byte - 1) * 8 + start_bit, bitNumbering=1) elif motorola_bit_format == "msbreverse": new_signal.set_startbit((start_byte - 1) * 8 + start_bit) else: # motorola_bit_format == "lsb" new_signal.set_startbit( (start_byte - 1) * 8 + start_bit, bitNumbering=1, startLittle=True) for additional_index in additional_inputs: # todo explain this possibly dangerous code with eval if "signal" in additional_inputs[additional_index]: command_str = additional_inputs[ additional_index].replace("signal", "new_signal") command_str += "=" command_str += str( sh.cell(row_num, additional_index).value) if len(str(sh.cell(row_num, additional_index).value)) > 0: exec(command_str) new_frame.add_signal(new_signal) new_signal.add_comment(signal_comment) function = sh.cell(row_num, index['function']).value value = str(sh.cell(row_num, index['Value']).value) value_name = sh.cell(row_num, index['ValueName']).value if value_name == 0: value_name = "0" elif value_name == 1: value_name = "1" # .encode('utf-8') unit = "" factor = sh.cell(row_num, index['function']).value if isinstance(factor, past.builtins.basestring): factor = factor.strip() if " " in factor and factor[0].isdigit(): (factor, unit) = factor.strip().split(" ", 1) factor = factor.strip() unit = unit.strip() new_signal.unit = unit try: new_signal.factor = float_factory(factor) except: logger.warning( "Some error occurred while decoding scale of Signal %s: '%s'", signal_name, sh.cell(row_num, index['function']).value) else: unit = factor.strip() new_signal.unit = unit new_signal.factor = 1 (mini, maxi, offset, value_table) = parse_value_name_column(value_name, value, new_signal.size, float_factory) if new_signal.min is None: new_signal.min = mini if new_signal.max is None: new_signal.max = maxi if new_signal.offset is None: new_signal.offset = offset if value_table is not None: for value, name in value_table.items(): new_signal.add_values(value, name) for frame in db.frames: frame.update_receiver() frame.calc_dlc() launch_type_enum = "ENUM" launch_type_enum += ",".join([ ' "{}"'.format(launch_type) for launch_type in launch_types if launch_type ]) db.add_frame_defines("GenMsgSendType", launch_type_enum) db.set_fd_type() return db