tao_z
2022-06-06 20cc603922983f154d10b7d56c6b49e5e02997bd
dbc.py
@@ -22,8 +22,10 @@
UNSIGNED = 0
SIGNED = 1
def normalizeValueTable(table):
    return {int(k): v for k, v in table.items()}
@attr.s(cmp=False)
class Frame:
@@ -73,7 +75,7 @@
            if sig.getStartbit() + int(sig.size) > maxBit:
                maxBit = sig.getStartbit() + int(sig.size)
        self.size = max(self.size, int(math.ceil(maxBit / 8)))
    def setFdType(self):
        """Try to guess and set the CAN type for every frame.
        If a Frame is longer than 8 bytes, it must be Flexible Data Rate frame (CAN-FD).
@@ -92,7 +94,7 @@
        bitfieldLe = []
        bitfieldBe = []
        for i in range(0,64):
        for i in range(0, 64):
            bitfieldBe.append(0)
            bitfieldLe.append(0)
            bitfield.append(0)
@@ -100,21 +102,21 @@
        for sig in self.signals:
            i += 1
            for bit in range(sig.getStartbit(),  sig.getStartbit() + int(sig.size)):
            for bit in range(sig.getStartbit(),
                             sig.getStartbit() + int(sig.size)):
                if sig.is_little_endian:
                    bitfieldLe[bit] = i
                else:
                    bitfieldBe[bit] = i
        for i in range(0,8):
            for j in range(0,8):
                bitfield[i*8+j] = bitfieldLe[i*8+(7-j)]
        for i in range(0, 8):
            for j in range(0, 8):
                bitfield[i * 8 + j] = bitfieldLe[i * 8 + (7 - j)]
        for i in range(0,8):
            for j in range(0,8):
                if bitfield[i*8+j] == 0:
                    bitfield[i*8+j] = bitfieldBe[i*8+j]
        for i in range(0, 8):
            for j in range(0, 8):
                if bitfield[i * 8 + j] == 0:
                    bitfield[i * 8 + j] = bitfieldBe[i * 8 + j]
        return bitfield
@@ -143,48 +145,51 @@
    * _multiplex ('Multiplexor' or Number of Multiplex)
    """
    name = attr.ib(default = "")
    name = attr.ib(default="")
    #    float_factory = attr.ib(default=defaultFloatFactory)
    float_factory = defaultFloatFactory
    startBit = attr.ib(type=int, default=0)
    size = attr.ib(type=int, default = 0)
    is_little_endian = attr.ib(type=bool, default = True)
    is_signed = attr.ib(type=bool, default = True)
    offset = attr.ib(converter = float_factory, default = float_factory(0.0))
    factor = attr.ib(converter = float_factory, default = float_factory(1.0))
    size = attr.ib(type=int, default=0)
    is_little_endian = attr.ib(type=bool, default=True)
    is_signed = attr.ib(type=bool, default=True)
    offset = attr.ib(converter=float_factory, default=float_factory(0.0))
    factor = attr.ib(converter=float_factory, default=float_factory(1.0))
    #    offset = attr.ib(converter = float_factory, default = 0.0)
    min  = attr.ib(converter=float_factory)
    min = attr.ib(converter=float_factory)
    @min.default
    def setDefaultMin(self):
        return  self.calcMin()
        return self.calcMin()
    max =  attr.ib(converter = float_factory)
    max = attr.ib(converter=float_factory)
    @max.default
    def setDefaultMax(self):
        return  self.calcMax()
        return self.calcMax()
    unit = attr.ib(type=str, default ="")
    receiver = attr.ib(default = attr.Factory(list))
    comment = attr.ib(default = None)
    multiplex  = attr.ib(default = None)
    unit = attr.ib(type=str, default="")
    receiver = attr.ib(default=attr.Factory(list))
    comment = attr.ib(default=None)
    multiplex = attr.ib(default=None)
    mux_value = attr.ib(default = None)
    mux_value = attr.ib(default=None)
    is_float = attr.ib(type=bool, default=False)
    enumeration = attr.ib(type=str, default = None)
    comments = attr.ib(type=dict, default = attr.Factory(dict))
    attributes = attr.ib(type=dict, default = attr.Factory(dict))
    values = attr.ib(type=dict, converter=normalizeValueTable, default = attr.Factory(dict))
    calc_min_for_none = attr.ib(type=bool, default = True)
    calc_max_for_none = attr.ib(type=bool, default = True)
    muxValMax = attr.ib(default = 0)
    muxValMin = attr.ib(default = 0)
    muxerForSignal= attr.ib(type=str, default = None)
    enumeration = attr.ib(type=str, default=None)
    comments = attr.ib(type=dict, default=attr.Factory(dict))
    attributes = attr.ib(type=dict, default=attr.Factory(dict))
    values = attr.ib(type=dict,
                     converter=normalizeValueTable,
                     default=attr.Factory(dict))
    calc_min_for_none = attr.ib(type=bool, default=True)
    calc_max_for_none = attr.ib(type=bool, default=True)
    muxValMax = attr.ib(default=0)
    muxValMin = attr.ib(default=0)
    muxerForSignal = attr.ib(type=str, default=None)
    def __attrs_post_init__(self):
        self.multiplex = self.multiplexSetter(self.multiplex)
    @property
    def spn(self):
@@ -253,7 +258,8 @@
            startBitInternal = startBitInternal + self.size - 1
        # bit numbering not consistent with byte order. reverse
        if bitNumbering is not None and bitNumbering != self.is_little_endian:
            startBitInternal = startBitInternal - (startBitInternal % 8) + 7 - (startBitInternal % 8)
            startBitInternal = startBitInternal - (
                startBitInternal % 8) + 7 - (startBitInternal % 8)
        return int(startBitInternal)
    def calculateRawRange(self):
@@ -261,7 +267,7 @@
        :return: Signal range, i.e. (0, 15) for unsigned 4 bit Signal or (-8, 7) for signed one.
        :rtype: tuple
        """
        rawRange = 2 ** (self.size - (1 if self.is_signed else 0))
        rawRange = 2**(self.size - (1 if self.is_signed else 0))
        return (self.float_factory(-rawRange if self.is_signed else 0),
                self.float_factory(rawRange - 1))
@@ -304,15 +310,12 @@
                    value = value_key
                    break
            else:
                raise ValueError(
                        "{} is invalid value choice for {}".format(value, self)
                )
                raise ValueError("{} is invalid value choice for {}".format(
                    value, self))
        if not (self.min <= value <= self.max):
            print(
                "Value {} is not valid for {}. Min={} and Max={}".format(
                    value, self, self.min, self.max)
                )
            print("Value {} is not valid for {}. Min={} and Max={}".format(
                value, self, self.min, self.max))
        raw_value = (value - self.offset) / self.factor
        if not self.is_float:
@@ -338,7 +341,9 @@
    def __str__(self):
        return self.name
class DBC:
    def __init__(self, dbcfile=None):
        self.filePath = dbcfile
        self.frames = self.__load()
@@ -349,7 +354,7 @@
        frameList = []
        i = 0
        frame = None
        with open(self.filePath, mode='r', encoding='gb2312') as f:
        with open(self.filePath, mode='r', encoding=dbcImportEncoding) as f:
            for line in f.readlines():
                i = i + 1
                l = line.strip()
@@ -358,14 +363,14 @@
                # logging.info(l)
                if l.startswith('BO_ '):
                    # frames
                    regexp = re.compile("^BO\_ ([^\ ]+) ([^\ ]+) *: ([^\ ]+) ([^\ ]+)")
                    regexp = re.compile(
                        "^BO\_ ([^\ ]+) ([^\ ]+) *: ([^\ ]+) ([^\ ]+)")
                    temp = regexp.match(l)
                    # name, id, dlc, transmitters
                    frame = Frame(
                        temp.group(2),
                        id=int(temp.group(1)),
                        size=int(temp.group(3)),
                        transmitters=temp.group(4).split())
                    frame = Frame(temp.group(2),
                                  id=int(temp.group(1)),
                                  size=int(temp.group(3)),
                                  transmitters=temp.group(4).split())
                    frameList.append(frame)
                    pass
                elif l.startswith('SG_ '):
@@ -375,30 +380,34 @@
                    temp = regexp.match(l)
                    if temp:
                        extras = {}
                        receiver = list(map(str.strip, temp.group(11).split(',')))
                        tempSig = Signal(
                            temp.group(1),
                            startBit=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.group(10),
                            receiver=receiver,
                            **extras
                        )
                        receiver = list(
                            map(str.strip,
                                temp.group(11).split(',')))
                        tempSig = Signal(temp.group(1),
                                         startBit=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.group(10),
                                         receiver=receiver,
                                         **extras)
                        if not tempSig.is_little_endian:
                            # startbit of motorola coded signals are MSB in dbc
                            tempSig.setStartbit(int(temp.group(2)), bitNumbering=1)
                            tempSig.setStartbit(int(temp.group(2)),
                                                bitNumbering=1)
                        frame.signals.append(tempSig)
                    else:
                        pattern = "^SG\_ +(\w+) +(\w+) *: *(\d+)\|(\d+)@(\d+)([\+|\-]) +\(([0-9.+\-eE]+),([0-9.+\-eE]+)\) +\[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] +\"(.*)\" +(.*)"
                        regexp = re.compile(pattern)
                        temp = regexp.match(l)
                        receiver = list(map(str.strip, temp.group(12).split(',')))
                        receiver = list(
                            map(str.strip,
                                temp.group(12).split(',')))
                        multiplex = temp.group(2)
                        is_complex_multiplexed = False
@@ -413,25 +422,24 @@
                            try:
                                multiplex = int(multiplex[1:])
                            except:
                                raise Exception('error decoding line',line)
                                raise Exception('error decoding line', line)
                        extras = {}
                        tempSig = Signal(
                            temp.group(1),
                            startBit=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(11),
                            receiver=receiver,
                            multiplex=multiplex,
                            **extras
                        )
                        tempSig = Signal(temp.group(1),
                                         startBit=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(11),
                                         receiver=receiver,
                                         multiplex=multiplex,
                                         **extras)
                        if is_complex_multiplexed:
                            tempSig.is_multiplexer = True
@@ -439,7 +447,8 @@
                        if not tempSig.is_little_endian:
                            # startbit of motorola coded signals are MSB in dbc
                            tempSig.setStartbit(int(temp.group(3)), bitNumbering=1)
                            tempSig.setStartbit(int(temp.group(3)),
                                                bitNumbering=1)
                        frame.addSignal(tempSig)
                        if is_complex_multiplexed:
@@ -468,8 +477,10 @@
                        if testF.id == int(tmpId):
                            for signal in testF.signals:
                                if signal.name == signalName:
                                    for i in range(math.floor(len(tempList) / 2)):
                                        signal.values[tempList[i * 2].strip()] = tempList[i * 2 + 1].strip()
                                    for i in range(
                                            math.floor(len(tempList) / 2)):
                                        signal.values[tempList[i * 2].strip(
                                        )] = tempList[i * 2 + 1].strip()
                                    break
                            break
                elif l.startswith("VAL_TABLE_ "):
@@ -491,7 +502,8 @@
                    regexp = re.compile("^BA\_ +\"[A-Za-z0-9[\-_ .]+\" +(.+)")
                    tempba = regexp.match(l)
                    if tempba.group(1).strip().startswith("BO_ "):
                        regexp = re.compile(r"^BA_ +\"(.*)\" +BO_ +(\w+) +(.+);")
                        regexp = re.compile(
                            r"^BA_ +\"(.*)\" +BO_ +(\w+) +(.+);")
                        temp = regexp.match(l)
                        tempId = temp.group(2)
                        for testF in frameList:
@@ -501,10 +513,12 @@
                            tempCys = temp.group(3)
                            frame.cycle = int(tempCys)
                elif l.startswith("SIG_GROUP_ "):
                    regexp = re.compile("^SIG\_GROUP\_ +(\w+) +(\w+) +(\w+) +\:(.*);")
                    regexp = re.compile(
                        "^SIG\_GROUP\_ +(\w+) +(\w+) +(\w+) +\:(.*);")
                    temp = regexp.match(l)
                elif l.startswith("SIG_VALTYPE_ "):
                    regexp = re.compile("^SIG\_VALTYPE\_ +(\w+) +(\w+)\s*\:(.*);")
                    regexp = re.compile(
                        "^SIG\_VALTYPE\_ +(\w+) +(\w+)\s*\:(.*);")
                    temp = regexp.match(l)
                elif l.startswith("BA_DEF_DEF_ "):
                    pattern = "^BA\_DEF\_DEF\_ +\"([A-Za-z0-9\-_\.]+)\" +(.+)\;"
@@ -516,7 +530,7 @@
                    pattern = "^EV_ +([A-Za-z0-9\-_]+) *\: +([0-9]+) +\[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] +\"(\w*)\" +([0-9.+\-eE]+) +([0-9.+\-eE]+) +([A-Za-z0-9\-_]+) +(.*);"
                    regexp = re.compile(pattern)
                    temp = regexp.match(l)
        return frameList
    def __setFdType(self):
@@ -527,13 +541,13 @@
        for frame in self.frames:
            # if frame.size == 0:
            frame.calcDLC()
            print(frame.id, frame.size)
            # print(frame.id, frame.size)
            if frame.size > 8:
                frame.is_fd = True
    def __setExtended(self):
        for frame in self.frames:
        # extended-flag is implicite in canid, thus repair this:
            # extended-flag is implicite in canid, thus repair this:
            if frame.id > 0x80000000:
                frame.id -= 0x80000000
                frame.extended = 1
@@ -565,37 +579,37 @@
                            return test
        return None
    def __getSignalVal(self, signal:Signal, data='00 01 02 03 04 05 06 07'):
    def __getSignalVal(self, signal: Signal, data='00 01 02 03 04 05 06 07'):
        dataList = data.strip().split(' ')
        _startbit = signal.startBit
        _bitsize = signal.size
        _little = signal.is_little_endian # (1: Intel, 0: Motorola)
        _byteSize = math.ceil((signal.size + _startbit%8)/8)
        _startByte = math.floor(_startbit/8)
        _little = signal.is_little_endian  # (1: Intel, 0: Motorola)
        _byteSize = math.ceil((signal.size + _startbit % 8) / 8)
        _startByte = math.floor(_startbit / 8)
        phyvalue = 0
        rawvalue = ''
        base = int('{0:0>8}'.format('1'*_bitsize+'0'*(_startbit%8)), 2)
        base = int('{0:0>8}'.format('1' * _bitsize + '0' * (_startbit % 8)), 2)
        _byteNum = 0
        _byteList= []
        _byteList = []
        while _byteNum < _byteSize:
            # tmpbase = (base >> (8*_byteNum)) & 0xff
            _byteList.append(dataList[_startByte+_byteNum])
            _byteList.append(dataList[_startByte + _byteNum])
            _byteNum += 1
        if _little == 1:
            _byteList.reverse()
        for _byte in _byteList:
            rawvalue += _byte
        rawvalue = ((int(rawvalue,16) & base) >> (_startbit%8))
        rawvalue = ((int(rawvalue, 16) & base) >> (_startbit % 8))
        return {"phy": signal.raw2phys(rawvalue), "raw": rawvalue}
        # print(_startByte, _byteSize, _bitsize, int(dataList[_startByte], 16), int('{0:0>8}'.format('1'*_bitsize+'0'*(_startbit%8)), 2))
    def analyzer(self, msgid=None, data='00 01 02 03 04 05 06 07'):
        '''analysis given data
        '''analysis given data
        Keyword Arguments:
            msgid {int} -- msg id (base 10) (default: {None})
            data {str} -- given data (default: {'00 01 02 03 04 05 06 07'})
        Returns:
            dict -- key sorted by signal index
        '''
@@ -615,7 +629,11 @@
                break
        return ret
if __name__ == '__main__':
    testDbc = DBC("data/SX7H.dbc")
    abc=testDbc.analyzer(msgid=1056, data='40 01 C8 00 FF 00 00 00')
    print(abc)
    testDbc = DBC("DBC/DFLZM.dbc")
    abc = testDbc.analyzer(msgid=1056, data='40 01 C8 00 FF 00 00 00')
    print(abc)
    print(abc[5]["name"])
    print(abc[6]["name"])
    print(abc[4]["name"])