技术博客

14/03/2017 作者 Mikkel

特殊转换情况

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

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

本博文系列的第二篇中,我们创建了一个将kme50日志文件转换为纯文本的简单程序。现在我们将继续查看转换日志文件时可能出现的三种特殊情况:溢出,数据截断和输出文件名更改:

溢出 如果总线负载超过记录容量,则在使用Memorator记录期间会发生溢出。可以通过调用kvlcIsOverrunActive()函数来检测此情况。一旦注意到超载,我们需要使用函数kvlcResetOverrunActive()手动重置状态。

数据截断 当所选择的输出转换器不能将数据帧中的所有字节写入输出文件时,会发生数据截断。如果将CAN FD数据提取为仅支持最多8个数据字节的格式,则可能发生这种情况,例如KVLC_FILE_FORMAT_KME40。通过调用kvlcResetStatusTruncated()函数可重置此情况。

新输出文件名 新的输出文件名的产生,是当转换器创建新文件时输出文件名发生变化,这可能是拆分输出文件所导致的结果(稍后我们将作简要介绍)[1] 当最后一次转换的事件导致创建新的输出文件时,对kvlcIsOutputFilenameNew()函数的调用将返回true。在下一次调用kvlcConvertEvent()时,此情况将自动重置。发生拆分时,可以通过调用kvlcGetOutputFilename()函数来获取新的输出文件名。

现在让我们创建一个功能,除了可进行实际转换之外,还要查找上述情况,并向用户输出一些含有信息的报文。

def convertEvents(kc):
# Get estimated number of remaining events in the input file. This can be 
# useful for displaying progress during conversion.
total = kc.eventCount()
print("Converting about %d events..." % total)
while True:
    try:
        # Convert events from input file one by one until EOF is reached
        kc.convertEvent()
        if kc.IsOutputFilenameNew():
            print("New output filename: %s" % kc.getOutputFilename())
            print("About %d events left to convert..." % kc.eventCount()) 
    except kvlc.KvlcEndOfFile:
        if kc.IsOverrunActive():
            print("NOTE! The extracted data contained overrun.")
            kc.resetOverrunActive() 
        if kc.IsDataTruncated():
            print("NOTE! The extracted data was truncated.")
            kc.resetStatusTruncated()
        break

列表8:定义执行转换的函数,并检查特殊情况。

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']))


def convertEvents(kc):
    # Get estimated number of remaining events in the input file. This can be
    # useful for displaying progress during conversion.
    total = kc.eventCount()
    print("Converting about %d events..." % total)
    while True:
        try:
            # Convert events from input file one by one until EOF is reached
            kc.convertEvent()
            if kc.IsOutputFilenameNew():
                print("New output filename: %s" % kc.getOutputFilename())
                print("About %d events left to convert..." % kc.eventCount())
        except kvlc.KvlcEndOfFile:
            if kc.IsOverrunActive():
                print("NOTE! The extracted data contained overrun.")
                kc.resetOverrunActive()
            if kc.IsDataTruncated():
                print("NOTE! The extracted data was truncated.")
                kc.resetStatusTruncated()
            break


# 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)

convertEvents(kc)

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

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

运行列表9的程序输出以下结果:

Output format is ’Plain text’
Output filename is ’myresult.txt’
Input filename is ’mylog.kme50’
  PROPERTY_OVERWRITE is supported (Default: 0)
    Current value: 1
  PROPERTY_WRITE_HEADER is supported (Default: 0)
    Current value: 1
  PROPERTY_LIMIT_DATA_BYTES is supported (Default: 64)
    Current value: 8
Converting about 71253 events...
New output filename: myresult.txt 
About 71252 events left to convert...
NOTE! The extracted data contained overrun.

从输出文件中可以看出,我们的输入文件包含7000多个事件,因此创建的输出文件超过4MB。 现在让我们通过设置属性KVLC_PROPERTY_SIZE_LIMIT拆分输出文件。

# split output files into max 2 MB files 
trySetProperty(kc, kvlc.PROPERTY_SIZE_LIMIT, 2)

我们的最终运行的输出结果如下所示,我们现在有三个输出文件,前两个是大约2MB。

Output format is ’Plain text’
Output filename is ’myresult.txt’
Input filename is ’mylog.kme50’
  PROPERTY_OVERWRITE is supported (Default: 0)
    Current value: 1
  PROPERTY_WRITE_HEADER is supported (Default: 0)
    Current value: 1
  PROPERTY_LIMIT_DATA_BYTES is supported (Default: 64)
    Current value: 8
Converting about 71253 events...
New output filename: myresult.txt 
About 71252 events left to convert...
NOTE! The extracted data contained overrun.

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

脚注

[1] 输出文件的拆分由编辑器属性KVLC_PROPERTY_SIZE_LIMITKVLC_PROPERTY_TIME_LIMIT控制。

Author Image

Mikkel Gerdes