Appia의 IT세상

파이썬[Python] Project01-02 DBC_Base Message/Siganl Class 본문

Python/Python 응용

파이썬[Python] Project01-02 DBC_Base Message/Siganl Class

Appia 2020. 1. 9. 22:13
반응형

앞서 포스팅에서 언급한 바와 같이 이번 포스팅에서는 DBC_Base부분으로 구성을 해볼까 합니다. DBC 파일을 읽어와서, Message, Signal 부분으로 나누어 저장하는 부분으로 구성이 됩니다. 전체적인 구성은 다음과 같이 이루어 집니다.

 

그럼 먼저 Class 구성에 대해서 많은 고민을 했습니다. 부분에 대해서 Class 만들어서 것인지 아니면, Message Class 생성하고, Signal 부분은 Dictionary 형태로 저장할 것인지 고민했습니다. 저의 코드에서는 후자를 선택하기로 했습니다.

 

 

메시지 클래스

먼저, CAN Message를 저장하기 위한 Class를 살펴 보겠습니다. 

class Msg :
    def __init__(self,data):
        data.replace('\n','')
        data = data.split(' ')
        data[3].replace(':','')
        self._,self.MessageID,self.MessageName,self.SignalCount,self.TxNode = data
        self.signals=[]

    def insert_signal(self, i ):
        print(i)
        _,singalName,_,Temp0, Temp1,Temp2,Temp3, recevieNode = i.split()
        value_type = 'unsigned' if Temp0[-1] == '-' else 'signed'
        byte_order = 'little_endian' if Temp0[-2] == '0' else 'big_endian'
        Temp0 = re.split('\W+',Temp0)
        Temp1 = re.split('\W+', Temp1)
        Temp2 = re.split('\W+', Temp2)
        """
        start_bit = Temp0[0]
        signal_size = Temp0[1]
        factor = Temp1[1]
        offset = Temp1[2]
        minValue = Temp2[1]
        manValue = Temp2[2]
        unit = Temp3
        recevieNode = recevieNode
        """
        self.signals.append({"singalName":singalName,"value_type":value_type ,
                             "byte_order":byte_order,"start_bit":Temp0[0],
                             "signal_size":Temp0[1],"factor":Temp1[1],
                             "offset":Temp1[2],"minValue":Temp2[1], 
                             "maxValue" : Temp2[2], "unit":Temp3, 
                             "recevieNode":recevieNode})

 

먼저, 최초에 값을 받아서, Message ID, Message Name, Tx Node에 대해서 unPacking했습니다. 그리고 class 내에 isert_signal이라는 함수를 하나 사용하여 Signal 정보들을 위에 포함시키도록 했습니다. 

 

 

load_raw_file 

DBC 파일을 읽어와서 List형태로 변환하는 기능을 수행합니다. 

def load_raw_file(File):
    DBCFile = []
    f = open(File,'r')
    Data = f.readlines()
    for i in Data :
        DBCFile.append(i)
    f.close()
    return DBCFile

 

Organize_Data

앞서, load_raw_file함수에서 읽어온 List를 바탕으로 Message Class 바탕으로 저장하여 전체 List로 저장하는 기능입니다. 

def Organize_Data(DBCFile):
    Total = []
    eMsg = None
    for i in DBCFile :
        if "BO_ " == i[:4]:
            if eMsg != None :
                Total.append(eMsg)
                eMsg = None
            eMsg = Msg(i)
        elif " SG_ " == i[:5]:
            eMsg.insert_signal(i)
    return Total

 

Load_DBC

그닥 큰 기능은 없는데 .. 코드 만들다 보니 이렇게 되었습니다. 위의 구성도까지 수정하기 싫어서 그냥 넣었습니다. 

def Load_DBC(File):
    return Organize_Data(load_raw_file(File))

 

전체 코드 

import re

class Msg :
    def __init__(self,data):
        data.replace('\n','')
        data = data.split(' ')
        data[3].replace(':','')
        self._,self.MessageID,self.MessageName,self.SignalCount,self.TxNode = data
        self.signals=[]

    def insert_signal(self, i ):
        print(i)
        _,singalName,_,Temp0, Temp1,Temp2,Temp3, recevieNode = i.split()
        value_type = 'unsigned' if Temp0[-1] == '-' else 'signed'
        byte_order = 'little_endian' if Temp0[-2] == '0' else 'big_endian'
        Temp0 = re.split('\W+',Temp0)
        Temp1 = re.split('\W+', Temp1)
        Temp2 = re.split('\W+', Temp2)
        """
        start_bit = Temp0[0]
        signal_size = Temp0[1]
        factor = Temp1[1]
        offset = Temp1[2]
        minValue = Temp2[1]
        manValue = Temp2[2]
        unit = Temp3
        recevieNode = recevieNode
        """
        self.signals.append({"singalName":singalName,"value_type":value_type ,
                             "byte_order":byte_order,"start_bit":Temp0[0],
                             "signal_size":Temp0[1],"factor":Temp1[1],
                             "offset":Temp1[2],"minValue":Temp2[1],
                             "maxValue" : Temp2[2], "unit":Temp3,
                             "recevieNode":recevieNode})

def Load_DBC(File):
    return Organize_Data(load_raw_file(File))

def load_raw_file(File):
    DBCFile = []
    f = open(File,'r')
    Data = f.readlines()
    for i in Data :
        DBCFile.append(i)
    f.close()
    return DBCFile

def Organize_Data(DBCFile):
    Total = []
    eMsg = None
    for i in DBCFile :
        if "BO_ " == i[:4]:
            if eMsg != None :
                Total.append(eMsg)
                eMsg = None
            eMsg = Msg(i)
        elif " SG_ " == i[:5]:
            eMsg.insert_signal(i)
    return Total

DBCFile = r'D:\Test\chassis.dbc'
Value = Load_DBC(DBCFile)
pass

 

가장 마지막에 있는 pass 문에 breakpoint를 걸어 놓고 나오는 값의 형태를 살펴봤습니다. 

 

물론, User Defined 속성과 Mumultiplexer관련 항목들을 지원하지 않고 있습니다. 이 부분들을 필요하신 분들이 위의 코드에서 수정하여 사용해보심이 어떨까요? 

(향후 업데이트 예정이긴 합니다. ) 

일정 부분 버그도 있음을 알고 있지만, 상용으로 만드는 것이 아니라 포스팅에 연관되어 있는 부분들과 함께 모두에게 공유할 수 있는 부분으로 만들다 보니 일정 속성은 배제할 수 밖에 없음을 양해 부탁드립니다. 그대신 질문이나 궁금하신 사항들은 언제든지 댓글 및 방명록에 글 남겨주세요. 

반응형
Comments