技术博客
转换为纯SCII码
这是关于在CANlib SDK中使用转换库(kvlclib)3篇系列文章中的第2篇:
- 编辑器格式和属性(1/3)
- 转换为纯SCII码(2/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