From 71bdeee9365abc278d52c02ce1438e8515fd0f9c Mon Sep 17 00:00:00 2001 From: Tomas Johansson Date: Wed, 14 Aug 2019 10:42:53 +0200 Subject: [PATCH 1/2] Add support for base 10 in CANReader Change-Id: I61a04c53276ea5b74e81d77267ef5e063a211d8a --- can/io/asc.py | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/can/io/asc.py b/can/io/asc.py index 2e25e5c2c..5f077cd2e 100644 --- a/can/io/asc.py +++ b/can/io/asc.py @@ -9,6 +9,7 @@ """ from datetime import datetime +import re import time import logging @@ -18,6 +19,11 @@ from .generic import BaseIOHandler +class ASCParseError(Exception): + """ASC file could not be parsed correctly.""" + + +BASES = {'dec': 10, 'hex': 16} CAN_MSG_EXT = 0x80000000 CAN_ID_MASK = 0x1FFFFFFF @@ -38,15 +44,32 @@ def __init__(self, file): read mode, not binary read mode. """ super().__init__(file, mode="r") - - @staticmethod - def _extract_can_id(str_can_id): + self.base = 16 + self.absolute_timestamps = False + self._parse_header() + + def _parse_header(self): + """Parse the header for information about base and timestamps.""" + base_regex = r"base\s+(?P\w+)\s+timestamps\s+(?P\w+)" + for i in range(10): + line = self.file.readline() + m = re.search(base_regex, line) + if m: + base = m.group('base') + if base not in BASES: + raise ASCParseError("Support for base %s not implemented" % base) + self.base = BASES[base] + self.absolute_timestamps = m.group('timestamps') == 'absolute' + break + self.file.seek(0) + + def _extract_can_id(self, str_can_id): if str_can_id[-1:].lower() == "x": is_extended = True - can_id = int(str_can_id[0:-1], 16) + can_id = int(str_can_id[0:-1], self.base) else: is_extended = False - can_id = int(str_can_id, 16) + can_id = int(str_can_id, self.base) return can_id, is_extended def __iter__(self): @@ -77,8 +100,8 @@ def __iter__(self): yield msg elif ( - not isinstance(channel, int) - or dummy.strip()[0:10].lower() == "statistic:" + not isinstance(channel, int) + or dummy.strip()[0:10].lower() == "statistic:" ): pass @@ -108,7 +131,7 @@ def __iter__(self): frame = bytearray() data = data.split() for byte in data[0:dlc]: - frame.append(int(byte, 16)) + frame.append(int(byte, self.base)) can_id_num, is_extended_id = self._extract_can_id(can_id_str) From d446e628d38dcbc15f850c686d3cd362424edba1 Mon Sep 17 00:00:00 2001 From: Tomas Johansson Date: Wed, 21 Aug 2019 10:37:21 +0200 Subject: [PATCH 2/2] fix PR comments Change-Id: I31169574892448f5df52da21fe563272244d8634 --- can/io/asc.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/can/io/asc.py b/can/io/asc.py index 5f077cd2e..5bc19c0b0 100644 --- a/can/io/asc.py +++ b/can/io/asc.py @@ -23,9 +23,11 @@ class ASCParseError(Exception): """ASC file could not be parsed correctly.""" -BASES = {'dec': 10, 'hex': 16} +BASES = {"dec": 10, "hex": 16} CAN_MSG_EXT = 0x80000000 CAN_ID_MASK = 0x1FFFFFFF +BEGIN_TRIGGERBLOCK = "Begin Triggerblock" +MAX_HEADER_ROW_LENGTH = 10 # TODO Just guessing here, is there an actual max row length of asc header? logger = logging.getLogger("can.io.asc") @@ -51,17 +53,17 @@ def __init__(self, file): def _parse_header(self): """Parse the header for information about base and timestamps.""" base_regex = r"base\s+(?P\w+)\s+timestamps\s+(?P\w+)" - for i in range(10): + for _ in range(MAX_HEADER_ROW_LENGTH): line = self.file.readline() + if line.startswith(BEGIN_TRIGGERBLOCK): + break # Header end m = re.search(base_regex, line) if m: - base = m.group('base') + base = m.group("base") if base not in BASES: - raise ASCParseError("Support for base %s not implemented" % base) + raise ValueError("Support for base %s not implemented" % base) self.base = BASES[base] - self.absolute_timestamps = m.group('timestamps') == 'absolute' - break - self.file.seek(0) + self.absolute_timestamps = m.group("timestamps") == "absolute" def _extract_can_id(self, str_can_id): if str_can_id[-1:].lower() == "x": @@ -100,8 +102,8 @@ def __iter__(self): yield msg elif ( - not isinstance(channel, int) - or dummy.strip()[0:10].lower() == "statistic:" + not isinstance(channel, int) + or dummy.strip()[0:10].lower() == "statistic:" ): pass