技术博客

12/02/2017 作者 Mikkel

转换为纯SCII码

这是关于在CANlib SDK中使用转换库(kvlclib)3篇系列文章中的第2篇:

  1. 编辑器格式和属性(1/3)
  2. 转换为纯SCII码(2/3)
  3. 特殊转换情况(3/3)

该系列文章的第1篇介绍了转换器的格式和属性,现在我们继续并转换给定日志文件中的事件。

我们假设一个日志文件mylog.kme50,我们要转换为纯文本(.txt)格式。日志文件是通过使用Kvaser Memorator配置工具或使用kvmlib创建的,如前面的博文所述。[1]

从本博文系列第1篇中我们所写的最新代码示例开始,我们现在将在最后添加一些代码来设置输入文件的格式和文件名。

import canlib.kvlclib as kvlc

# set output format
fmt = kvlc.WriterFormat(kvlc.FILE_FORMAT_PLAIN_ASC)
# the name of the formatter is fetched using kvlcGetWriterName() internally
print("Output format is '%s'" % fmt.name)

# set resulting output filename taking advantage of the extension defined in
# the format. (Uses kvlcGetWriterExtension() under the hood.)
outfile = "myresult." + fmt.extension
print("Output filename is '%s'" % outfile)

# create converter
kc = kvlc.Kvlclib(outfile, fmt)

# Set input filename and format
inputfile = "mylog.kme50"
print("Input filename is '%s'" % inputfile)
kc.setInputFile(inputfile, file_format=kvlc.FILE_FORMAT_KME50)

现在让我们添加一个逐个转换事件的循环,直到我们到达输入文件的末尾。

# Convert events from input file one by one until EOF is reached 
while True:
    try:
        kc.convertEvent()
    except kvlc.KvlcEndOfFile:
        break

我们需要做的最后一件事就是调用kvlcDeleteConverter() 来刷新输出到磁盘和可用内存。

# Delete converter, flush result to disk and free memory
kc.deleteConverter()

运行上述代码一次,文件myresult.txt就会被创建。但是再次运行相同的代码会导致错误:

File "c:\dev\python\pycanlib\src\canlib\kvlclib.py", line 459, in convertEvent 
    self.dll.kvlcConvertEvent(self.handle)
  File "c:\dev\python\pycanlib\src\canlib\kvlclib.py", line 408, in _kvlc_err_check 
    raise KvlcError(self, result)
canlib.kvlclib.KvlcError: [KvlcError] convertEvent: Output file already exists (-6)

每个转换器都有许多影响其内部运作的属性。这些属性之一是KVLC_PROPERTY_OVERWRITE ,默认为“0”,这是第二次运行代码失败的原因——生成的文件已存在,转换器不允许覆盖现有文件。

正如我们在上篇博文中所述,我们可以询问某一属性是否可被特定格式支持。所以让我们创建一个函数来检查给定的属性是否受支持。如果属性被支持,并且一个值被提供给函数,该函数将该属性设置为给定值。我们也借此机会将属性的默认值输出到控制台。

def trySetProperty(converter, property, value=None):
    # Check if the format supports the given property
    if converter.format.isPropertySupported(property):

        # If a value was specified, set the property to this value
        if value is not None:
            converter.setProperty(property, value)

        # get the property's default value
        default = converter.getPropertyDefault(property)
        print(" PROPERTY_%s is supported (Default: %s)" %
              (property['name'], default))

        # get the property's current value
        value = converter.getProperty(property)
        print("	Current value: %s" % value)
    else:
        print(" PROPERTY %s is not supported" %
              (property['name']))

列表4:定义尝试设置给定属性的函数

现在让我们使用列表4中定义的trySetProperty()函数,并将KVLC_PROPERTY_OVERWRITE设置为’1’。纯文本格式的第二个有用属性是KVLC_PROPERTY_WRITE_HEADER,它为输出文件添加规范的标头,因此我们也可以设置该属性。我们设置的最后属性是KVLC_PROPERTY_LIMIT_DATA_BYTES,它控制要输出的数据字节数。在ASCII格式中,这直接影响我们的数据表的宽度,由于我们的输入日志中没有任何CAN FD[2]报文,我们将此属性设置为8(字节)。

# allow output file to overwrite existing files
trySetProperty(kc, kvlc.PROPERTY_OVERWRITE, 1) 

# add nice header to the output file
trySetProperty(kc, kvlc.PROPERTY_WRITE_HEADER, 1) 

# we are converting CAN traffic with max 8 bytes, so we can minimize the width
# of the data output to 8 bytes
trySetProperty(kc, kvlc.PROPERTY_LIMIT_DATA_BYTES, 8)

列表5:使用纯文本编辑器设置一些简单的属性

集合我们迄今为止所有的改进,最终生成列表6所示的程序。

import canlib.kvlclib as kvlc


def trySetProperty(converter, property, value=None):
    # Check if the format supports the given property
    if converter.format.isPropertySupported(property):

        # If a value was specified, set the property to this value
        if value is not None:
            converter.setProperty(property, value)

        # get the property's default value
        default = converter.getPropertyDefault(property)
        print(" PROPERTY_%s is supported (Default: %s)" %
              (property['name'], default))

        # get the property's current value
        value = converter.getProperty(property)
        print("	Current value: %s" % value)
    else:
        print(" PROPERTY %s is not supported" %
              (property['name']))
 

# set output format
fmt = kvlc.WriterFormat(kvlc.FILE_FORMAT_PLAIN_ASC)
# the name of the formatter is fetched using kvlcGetWriterName() internally
print("Output format is '%s'" % fmt.name)

# set resulting output filename taking advantage of the extension defined in
# the format. (Uses kvlcGetWriterExtension() under the hood.)
outfile = "myresult." + fmt.extension
print("Output filename is '%s'" % outfile)

# create converter
kc = kvlc.Kvlclib(outfile, fmt)

# Set input filename and format
inputfile = "mylog.kme50"
print("Input filename is '%s'" % inputfile)
kc.setInputFile(inputfile, file_format=kvlc.FILE_FORMAT_KME50)

# allow output file to overwrite existing files
trySetProperty(kc, kvlc.PROPERTY_OVERWRITE, 1)

# add nice header to the output file
trySetProperty(kc, kvlc.PROPERTY_WRITE_HEADER, 1)

# we are converting CAN traffic with max 8 bytes, so we can minimize the width
# of the data output to 8 bytes
trySetProperty(kc, kvlc.PROPERTY_LIMIT_DATA_BYTES, 8)

# Convert events from input file one by one until EOF is reached
while True:
    try:
        kc.convertEvent()
    except kvlc.KvlcEndOfFile:
        break

# Delete converter, flush result to disk and free memory
kc.deleteConverter()

列表6:将kme50日志文件转换为纯文本输出的简单程序

列表6所示的第二次尝试可以运行多次,生成的文件myresult.txt的最上部分如列表7所示。

                               Kvaser Memorator Log
                               ====================

 Converted from Memorator Binary format at: 1/11/2017 15:54:02


Settings:
    Format of data field: DEC
    Format of id field:   DEC
    Timestamp Offset:     0.000000000 s
    CAN channel:          1 2

        Time Chan  Identifier Flags	   DLC   Data	                                  Counter
=============================================================================================
 0.247909525 Trigger (type=0x1, active=0x00, pre-trigger=0, post-trigger=-1)
10.648166375 1	        55    Rx	    1	2	                                    1
10.648166375 2    	55    Rx	    1	2	                                    2
12.464742375 1         340    Rx	    8	0   0   0   0   0   0   0   0	            3
12.464742375 2	       340    Rx	    8	0   0   0   0   0   0   0   0	            4

列表7:转换的纯文本输出结果的最上部分行

在本文中,我们创建了一个将kme50日志文件转换为纯文本的简单程序。在本系列的最后一篇文章中,我们将介绍转换日志文件时可能出现的特殊情况。

如果您对博文发布有任何问题,意见或建议,可以直接通过support@kvaser.com与我们联系。


脚注

[1] 从Kvaser Memorator读取并使用kvmlib保存记录的数据见 www.kvaser.cn/developer-blog/digging-deeper-into-kvmlib

[2] CAN FD允许每帧最多64字节的数据字段。有关CAN FD的更多信息,请参阅博文 www.kvaser.cn/developer-blog/can-fd

Author Image

Mikkel Gerdes