Beispiel #1
0
 def setBitrate(self, bitrate):
     print('Setting bitrate ' + str(bitrate))
     setBitrateResult = self._dll.icsneoSetBitRate(self._neoObject, bitrate,
                                                   self._icsNetId)
     if setBitrateResult != 1:
         raise CANInterface.Error('Setting bitrate failed')
     else:
         self._cfgdBitrate = bitrate
Beispiel #2
0
    def transmitTo(self, data, ident):
        assert self._cfgdBitrate != None

        if self._dumpTraffic:
            print('TX ' + CANInterface.ID(ident).getString() + ' ' +
                  CANInterface.getDataHexString(data))
        frame = self._build_frame(data, ident)
        res = self._dll.icsneoTxMessages(self._neoObject, ctypes.byref(frame),
                                         self._icsNetId, 1)
        if res != 1:
            raise CANInterface.Error()
Beispiel #3
0
    def receive(self, timeout):
        assert self._cfgdBitrate != None

        if self._slaveAddr.resId.raw == 0xFFFFFFFF:
            return []

        packets = []

        if timeout != 0:
            endTime = time.time() + timeout
        else:
            endTime = None

        while 1:
            if endTime != None:
                newTimeout = int((endTime - time.time()) * 1000)
                if newTimeout > 0:
                    self._dll.icsneoWaitForRxMessagesWithTimeOut(
                        self._neoObject, newTimeout)
                else:
                    break
            else:
                endTime = 0  # allow one pass, then return on the next

            icsMsgs = (_ICSSpyMessage * 20000)()
            icsNMsgs = ctypes.c_int()
            icsNErrors = ctypes.c_int()

            res = self._dll.icsneoGetMessages(self._neoObject, icsMsgs,
                                              ctypes.byref(icsNMsgs),
                                              ctypes.byref(icsNErrors))
            if res != 1:
                raise CANInterface.Error()

            for iMsg in range(icsNMsgs.value):
                if icsMsgs[iMsg].NetworkID == self._icsNetId:
                    ident, data = self._decode_frame(icsMsgs[iMsg])
                    if len(data
                           ) > 0 and ident == self._slaveAddr.resId.raw and (
                               data[0] == 0xFF or data[0] == 0xFE):
                        if self._dumpTraffic:
                            print('RX ' + self._slaveAddr.resId.getString() +
                                  ' ' + CANInterface.getDataHexString(data))
                        packets.append(data)

            if len(packets) != 0:
                break
        return packets
    def __init__(self, parsedURL):
        self._slaveAddr = None
        self._port = None
        self._bitrate = None
        self._txAddrStd = False
        self._cfgdBitrate = None
        self._cfgdTxAddrStd = False
        self._baudDivisor = None
        self._baud87Mult = None
        self._hasSetCSM0 = False
        self._tcpTimeout = 1.0
        self._serialTimeout = 0.2
        self._dumpTraffic = False
        self._cfgdHeaderIdent = None
        self._filter = None
        self._cfgdFilter = None
        self._noCsmQuirk = False
        self._isSt = False

        self._io = None

        urlQueryDict = urllib.parse.parse_qs(parsedURL.query)

        debugLogfile = None
        if 'debuglog' in urlQueryDict:
            if urlQueryDict['debuglog'][0] == 'stdout':
                debugLogfile = sys.stdout
            else:
                debugLogfile = open(urlQueryDict['debuglog'][0], 'w')

        if len(parsedURL.netloc):
            # If netloc is present, we're using a TCP connection
            addr = parsedURL.netloc.split(':')
            if len(addr) == 1:
                addr.append(35000)  # use default port
            elif len(addr) != 2:
                raise CANInterface.Error('Interface address invalid')
            s = socket.socket()
            s.create_connection(addr, 0)
            self._port = SocketAsPort(s)
            self._intfcTimeout = self._tcpTimeout
        else:
            if debugLogfile != None:
                port = LoggingPort(debugLogfile)
            else:
                port = serial.Serial()
            port.port = parsedURL.path
            port.open()
            foundBaud = False
            for baudRate in self._POSSIBLE_BAUDRATES:
                if DEBUG:
                    print('Trying ' + str(baudRate))
                port.baudrate = baudRate
                port.interCharTimeout = min(10 / baudRate, 0.0001)
                port.timeout = 0.05

                # Try sending a CR, if we get a prompt then it's probably the right baudrate
                port.flushInput()
                port.write(b'\r')
                response = port.read(16384)
                if len(response) == 0 or response[-1:] != b'>':
                    port.write(b'\r')
                    response = port.read(16384)
                    if len(response) == 0 or response[-1:] != b'>':
                        continue

                # Turn off echo, this also serves as a test to make sure we didn't randomly get a > at the end of some gibberish
                port.flushInput()
                port.write(b'ATE0\r')
                response = port.read(16)
                if not b'OK' in response:
                    continue

                # If we made contact at baudrate 500k, we're done
                if baudRate == 500000:
                    foundBaud = True
                    break

                # Not at 500k, try to change ELM to that
                port.timeout = 1.28  # Maximum possible timeout for ELM327
                port.flushInput()
                port.write(b'ATBRD08\r')
                response = port.read(2)
                if response == b'?\r':
                    # Device does not allow baudrate change, but we found its operating baudrate
                    foundBaud = True
                    break
                elif response == b'OK':
                    # Device allows baudrate change, try to switch to 500k
                    port.baudrate = 500000
                    port.flushInput()
                    response = port.read(11)
                    if response[0:6] != b'ELM327':
                        # Baudrate switch unsuccessful, try to recover
                        port.baudrate = baudRate
                        port.write(b'\r')
                        port.flushInput()
                        response = port.read(1024)
                        if len(response) == 0 or response[-1:] != b'>':
                            raise UnexpectedResponse('switching baudrate')

                    # Baudrate switched, send a CR to confirm we're on board
                    port.flushInput()
                    port.write(b'\r')
                    response = port.read(2)
                    if response != b'OK':
                        raise UnexpectedResponse('switching baudrate')
                    foundBaud = True
                    if response == b'ELM327 v1.5':
                        self._noCsmQuirk = True
                    break

            if not foundBaud:
                raise SerialError('could not find baudrate')
            port.timeout = 0

            self._port = port
            self._intfcTimeout = self._serialTimeout

        self._port.flushInput()

        # Start the I/O thread, which takes over control of the port
        self._io = ELM327IO(port)

        self._runCmdWithCheck(b'ATWS', checkOK=False,
                              closeOnFail=True)  # Software reset
        self._runCmdWithCheck(b'ATE0', closeOnFail=True)  # Turn off echo
        self._runCmdWithCheck(b'ATL0', closeOnFail=True)  # Turn off newlines
        self._runCmdWithCheck(b'ATS0', closeOnFail=True)  # Turn off spaces
        self._runCmdWithCheck(b'ATH1', closeOnFail=True)  # Turn on headers
        self._runCmdWithCheck(b'ATAL',
                              closeOnFail=True)  # Allow full length messages
        try:
            self._runCmdWithCheck(
                b'STFCP', closeOnFail=False)  # See if this is an ST device
            self._isSt = True
        except UnexpectedResponse:
            pass

        self.setBitrate(CANInterface.URLBitrate(parsedURL))

        self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)