diff --git a/can/io/asc.py b/can/io/asc.py index 2e25e5c2c..5bc19c0b0 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,8 +19,15 @@ 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 +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") @@ -38,15 +46,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 _ 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") + if base not in BASES: + raise ValueError("Support for base %s not implemented" % base) + self.base = BASES[base] + self.absolute_timestamps = m.group("timestamps") == "absolute" + + 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): @@ -108,7 +133,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)