예제 #1
0
class LoopbackTester(object):
    def __init__(self):
        self.device = Device()

    def test_loopback(self, lengths):
        self.device.flush()
        time.sleep(0.1)
        for l in lengths:
            test_str = test_string(l)
            if self.device.write(test_str) != len(test_str):
                sys.stdout.write('*')
            time.sleep(0.1)
            result = ''
            for _ in range(3):
                result = self.device.read(l)
                if result:
                    break
            if result != test_str:
                self.device.flush()
                time.sleep(0.25)
            yield result == test_str

    def main(self):
        for bd in [9600, 31250, 115200, 1152000]:
            self.device.baudrate = bd

            for result in self.test_loopback(range(1, 50) + range(100, 500, 100) +
                                             range(1000, 5000, 1000)):
                if result:
                    sys.stdout.write('+')
                else:
                    sys.stdout.write('!')
            sys.stdout.write('\n')
예제 #2
0
class RS485Monitor(object):
    __metaclass__ = abc.ABCMeta

    def __init__(self, a, mode='t', baudrate=1250000,
                 databits=8, stopbits=0, paritymode=2):
        self._single = a.single
        self._count = 0
        self._out = UnbufferedStreamWrapper(stdout)

        try:
            self._d = Device()
            self._d.baudrate = baudrate
            self._d.ftdi_fn.ftdi_set_line_property(databits,
                                                   stopbits,
                                                   paritymode)
            self._d.flush()
        except FtdiError as e:
            self._d = None
            raise FtdiError('could not start FTDI Device "' + e.args[0] + '"')

    def __del__(self):
        try:
            if self._d:
                self._d.flush()
                self._d.close()
        except:
            print 'Destroy failed'
        print normColor + '\nExiting monitor'

    @abc.abstractmethod
    def run(self):
        pass
예제 #3
0
class LoopbackTester(object):
    def __init__(self):
        self.device = Device()

    def test_loopback(self, lengths):
        self.device.flush()
        time.sleep(0.1)
        for l in lengths:
            test_str = test_string(l)
            if self.device.write(test_str) != len(test_str):
                sys.stdout.write('*')
            time.sleep(0.1)
            result = ''
            for _ in range(3):
                result = self.device.read(l)
                if result:
                    break
            if result != test_str:
                self.device.flush()
                time.sleep(0.25)
            yield result == test_str

    def main(self):
        for bd in [9600, 31250, 115200, 1152000]:
            self.device.baudrate = bd

            for result in self.test_loopback(
                    range(1, 50) + range(100, 500, 100) +
                    range(1000, 5000, 1000)):
                if result:
                    sys.stdout.write('+')
                else:
                    sys.stdout.write('!')
            sys.stdout.write('\n')
class FtdiSyncInterface:
    ##################################################################
    # Construction
    ##################################################################
    def __init__(self, iface=None):
        self.interface = iface
        self.target = None
        self.prog_cb = None
        self.CMD_NOP = 0x0
        self.CMD_WR = 0x1
        self.CMD_RD = 0x2
        self.CMD_GP_WR = 0x3
        self.CMD_GP_RD = 0x4
        self.HDR_SIZE = 6
        self.MAX_SIZE = 255
        self.BLOCK_SIZE_WR = 64  # Really 2048
        self.BLOCK_SIZE_RD = 64
        self.MAGIC_ADDR = 0xF0000000

        # User specified (device_id)
        self.dev_id = None
        if iface != None and iface != "":
            self.dev_id = iface

    ##################################################################
    # set_progress_cb: Set progress callback
    ##################################################################
    def set_progress_cb(self, prog_cb):
        self.prog_cb = prog_cb

    ##################################################################
    # connect: Open serial connection
    ##################################################################
    def connect(self):
        self.target = Device(device_id=self.dev_id, interface_select=1)
        self.target.flush()
        time.sleep(0.01)

        BITMODE_SYNCFF = 0x40
        SIO_RTS_CTS_HS = (0x1 << 8)
        self.target.ftdi_fn.ftdi_set_bitmode(0, BITMODE_SYNCFF)
        self.target.ftdi_fn.ftdi_setflowctrl(SIO_RTS_CTS_HS)
        self.target.flush()

    ##################################################################
    # write: Write a block of data to a specified address
    ##################################################################
    def write(self, addr, data, length, addr_incr=True, max_block_size=-1):
        # Connect if required
        if self.target == None:
            self.connect()

        # Write blocks
        idx = 0
        remainder = length

        if self.prog_cb != None:
            self.prog_cb(0, length)

        if max_block_size == -1:
            max_block_size = self.BLOCK_SIZE_WR

        while remainder > 0:
            l = max_block_size
            if l > remainder:
                l = remainder

            cmd = bytearray(2 + 4 + l)
            cmd[0] = (((l >> 8) & 0xF) << 4) | self.CMD_WR
            cmd[1] = l & 0xFF
            cmd[2] = (addr >> 24) & 0xFF
            cmd[3] = (addr >> 16) & 0xFF
            cmd[4] = (addr >> 8) & 0xFF
            cmd[5] = (addr >> 0) & 0xFF

            for i in range(l):
                cmd[6 + i] = data[idx]
                idx += 1

            # Write to interface
            self.target.write(cmd)

            # Update display
            if self.prog_cb != None:
                self.prog_cb(idx, length)

            if addr_incr:
                addr += l
            remainder -= l

    ##################################################################
    # read: Read a block of data from a specified address
    ##################################################################
    def read(self, addr, length, addr_incr=True, max_block_size=-1):
        # Connect if required
        if self.target == None:
            self.connect()

        idx = 0
        remainder = length
        data = bytearray(length)

        if self.prog_cb != None:
            self.prog_cb(0, length)

        if max_block_size == -1:
            max_block_size = self.BLOCK_SIZE_RD

        while remainder > 0:
            l = max_block_size
            if l > remainder:
                l = remainder

            cmd = bytearray(2 + 4)
            cmd[0] = (((l >> 8) & 0xF) << 4) | self.CMD_RD
            cmd[1] = l & 0xFF
            cmd[2] = (addr >> 24) & 0xFF
            cmd[3] = (addr >> 16) & 0xFF
            cmd[4] = (addr >> 8) & 0xFF
            cmd[5] = (addr >> 0) & 0xFF

            # Write to serial port
            self.target.write(cmd)

            # Read block response
            for i in range(l):

                x = bytearray()
                while len(x) == 0:
                    x = self.target.read(1)

                data[idx] = ord(x) & 0xFF
                idx += 1

            # Update display
            if self.prog_cb != None:
                self.prog_cb(idx, length)

            if addr_incr:
                addr += l
            remainder -= l

        return data

    ##################################################################
    # read32: Read a word from a specified address
    ##################################################################
    def read32(self, addr):
        # Connect if required
        if self.target == None:
            self.connect()

        # Send read command
        cmd = bytearray([
            self.CMD_RD, 4, (addr >> 24) & 0xFF, (addr >> 16) & 0xFF,
            (addr >> 8) & 0xFF, (addr >> 0) & 0xFF
        ])
        self.target.write(cmd)

        value = 0
        idx = 0
        while (idx < 4):
            b = self.target.read(1)
            value |= (ord(b) << (idx * 8))
            idx += 1

        return value

    ##################################################################
    # write32: Write a word to a specified address
    ##################################################################
    def write32(self, addr, value):
        # Connect if required
        if self.target == None:
            self.connect()

        # Send write command
        cmd = bytearray([
            self.CMD_WR, 4, (addr >> 24) & 0xFF, (addr >> 16) & 0xFF,
            (addr >> 8) & 0xFF, (addr >> 0) & 0xFF, (value >> 0) & 0xFF,
            (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF
        ])
        self.target.write(cmd)

    ##################################################################
    # read_gpio: Read GPIO bus
    ##################################################################
    def read_gpio(self):
        # Connect if required
        if self.target == None:
            self.connect()

        # Send read command
        cmd = bytearray([self.CMD_GP_RD])
        self.target.write(cmd)

        return ord(self.target.read(1))

    ##################################################################
    # write_gpio: Write a byte to GPIO
    ##################################################################
    def write_gpio(self, value):
        # Connect if required
        if self.target == None:
            self.connect()

        # Send write command
        cmd = bytearray([self.CMD_GP_WR, (value >> 0) & 0xFF])
        self.target.write(cmd)
예제 #5
0
class Ecu:
    def __init__(self):
        self.ser = Device(mode='b', lazy_open=True)

    def slowInit11(self):
        # Take the one-byte address to "bit bang" and bang the port
        self.bbser = BitBangDevice()
        print("beginning slow init")
        self.bbser.open()
        self.bbser.direction = 0x01
        self.bbser.port = 1
        time.sleep(.5)
        self.bbser.port = 0
        time.sleep(.2)
        self.bbser.port = 1
        time.sleep(.2)
        self.bbser.port = 0
        time.sleep(1.4)
        self.bbser.port = 1
        time.sleep(.2)
        self.bbser.close()
        print("slow init sent")

    def initialize(self, connect):
        self.connect = connect
        if self.connect == "SLOW-0x11":
            self.ser.close()
            time.sleep(.5)

            self.ecuconnect = False
            while self.ecuconnect == False:
                print("Attempting ECU connect: " + self.connect)

                # Bit bang the K-line
                self.slowInit11()
                self.ser.open()
                self.ser.ftdi_fn.ftdi_set_line_property(8, 1, 0)
                self.ser.baudrate = 10400
                self.ser.flush()

                # Wait for ECU response to bit bang
                waithex = [0x55, 0xef, 0x8f, 1]
                print("Wating for init response")
                response = self.waitfor(waithex)
                print(f"Init response: {hexlist(response[2])}")
                # Wait a bit
                time.sleep(.026)

                # Send 0x70
                self.send([0x70])

                # 0xee means that we're talking to the ECU
                waithex = [0xfe, 1]
                print("waiting for ECU reponse")
                response = self.waitfor(waithex)
                print(f"ecu connection response: {hexlist(response[2])}")
                if response[0] == True:
                    self.ecuconnect = True
                else:
                    print("ECU Connect Failed.  Retrying.")
                    return
                print("INIT done")

    def waitfor(self, wf):
        # This was used for debugging and really is only used for the init at this point.
        # wf should be a list with the timeout in the last element
        self.wf = wf
        isfound = False
        idx = 0
        foundlist = []
        capturebytes = []
        to = self.wf[-1]
        timecheck = time.time()
        while (time.time() <= (timecheck + to)) & (isfound == False):
            try:
                recvbyte = self.recvraw(1)
                if recvbyte != b"":
                    recvdata = ord(recvbyte)
                    capturebytes = capturebytes + [recvdata]
                    if recvdata == self.wf[idx]:
                        foundlist = foundlist + [recvdata]
                        idx = idx + 1
                    else:
                        foundlist = []
                        idx = 0
                    if idx == len(self.wf) - 1:
                        isfound = True
            except e:
                print([isfound, foundlist, capturebytes])
                print('error', e)
                break
        return [isfound, foundlist, capturebytes]

    def send(self, sendlist):
        self.sendlist = sendlist
        # Puts every byte in the sendlist out the serial port
        for i in self.sendlist:
            self.ser.write(chr(i))

    def recvraw(self, bytes):
        self.bytes = bytes
        recvdata = self.ser.read(self.bytes)
        return recvdata

    def recv(self, bytes):
        self.bytes = bytes
        isread = False
        while isread == False:
            recvbyte = self.ser.read(self.bytes)
            if recvbyte != b"":
                recvdata = recvbyte
                isread = True
        return recvdata

    def sendcommand(self, sendlist):
        # Wraps raw KWP command in a length byte and a checksum byte and hands it to send()
        self.sendlist = sendlist
        csum = 0
        self.sendlist = [len(self.sendlist)] + self.sendlist
        csum = self.checksum(self.sendlist)
        self.sendlist = self.sendlist + [csum]
        self.send(self.sendlist)
        print(f"sendcommand() sent: {hexlist(self.sendlist)}")
        cmdval = self.commandvalidate(self.sendlist)
        return cmdval

    def commandvalidate(self, command):
        # Every KWP command is echoed back.  This clears out these bytes.
        self.command = command
        cv = True
        for i in range(len(self.command)):
            recvdata = self.recv(1)
            if ord(recvdata) != self.command[i]:
                cv = cv & False
        return cv

    def checksum(self, checklist):
        # Calculates the simple checksum for the KWP command bytes.
        self.checklist = checklist
        csum = 0
        for i in self.checklist:
            csum = csum + i
        csum = (csum & 0xFF) % 0xFF
        return csum

    # used exclusivly for the errorhandling section
    def _raise(self, ex):
        raise ex

    def getresponse(self):
        # gets a properly formated KWP response from a command and returns the data.
        debugneeds = 4
        numbytes = 0
        # This is a hack because sometimes responses have leading 0x00's.  Why?  This removes them.
        while numbytes == 0:
            numbytes = ord(self.recv(1))
        gr = [numbytes]
        if debug >= debugneeds:
            print("Get bytes: " + hex(numbytes))
        for i in range(numbytes):
            recvdata = ord(self.recv(1))
            if debug >= debugneeds:
                print("Get byte" + str(i) + ": " + hex(recvdata))
            gr = gr + [recvdata]
        checkbyte = self.recv(1)
        if debug >= debugneeds:
            print(f"getresponse recieved: {hexlist(gr)}")
        if debug >= debugneeds:
            print("GR: " + hex(ord(checkbyte)) + "<-->" +
                  hex(self.checksum(gr)))
        if (gr[1] == 0x7f):
            return {  # returning the result so 0x78 (responsePending) can re-execute
                0x10:
                lambda: self._raise(Exception("generalReject", gr)),
                0x11:
                lambda: self._raise(Exception("busyRepeatRequest", gr)),
                0x12:
                lambda: self._raise(
                    Exception("subFunctionNotSupported / invalidFormat", gr)),
                0x21:
                lambda: self._raise(Exception("busyRepeatRequest", gr)),
                0x22:
                lambda: self._raise(
                    Exception("conditionsNotCorrectOrRequestSequenceError", gr)
                ),
                0x23:
                lambda: self._raise(Exception("routineNotComplete", gr)),
                0x31:
                lambda: self._raise(Exception("requestOutOfRange", gr)),
                0x33:
                lambda: self._raise(
                    Exception("securityAccessDenied / securityAccessRequested",
                              gr)),
                0x35:
                lambda: self._raise(Exception("invalidKey", gr)),
                0x36:
                lambda: self._raise(Exception("exceedNumberOfAttempts", gr)),
                0x37:
                lambda: self._raise(
                    Exception("requiredTimeDelayNotExpired", gr)),
                0x40:
                lambda: self._raise(Exception("downloadNotAccepted")),
                0x41:
                lambda: self._raise(Exception("improperDownloadType")),
                0x42:
                lambda: self._raise(
                    Exception("canNotDownloadToSpecifiedAddress", gr)),
                0x43:
                lambda: self._raise(
                    Exception("canNotDownloadNumberOfBytesRequested", gr)),
                0x50:
                lambda: self._raise(Exception("uploadNotAccepted", gr)),
                0x51:
                lambda: self._raise(Exception("improperUploadType", gr)),
                0x52:
                lambda: self._raise(
                    Exception("canNotUploadFromSpecifiedAddress", gr)),
                0x53:
                lambda: self._raise(
                    Exception("canNotUploadNumberOfBytesRequested", gr)),
                0x71:
                lambda: self._raise(Exception("transferSuspended", gr)),
                0x72:
                lambda: self._raise(Exception("transferAborted", gr)),
                0x74:
                lambda: self._raise(
                    Exception("illegalAddressInBlockTransfer", gr)),
                0x75:
                lambda: self._raise(
                    Exception("illegalByteCountInBlockTransfer", gr)),
                0x76:
                lambda: self._raise(Exception("illegalBlockTransferType", gr)),
                0x77:
                lambda: self._raise(
                    Exception("blockTransferDataChecksumError", gr)),
                0x78:
                self.getresponse,
                0x79:
                lambda: self._raise(
                    Exception("incorrectByteCountDuringBlockTransfer", gr)),
                0x80:
                lambda: self._raise(
                    Exception("serviceNotSupportedInActiveDiagnosticMode", gr)
                ),
                0x90:
                lambda: self._raise(Exception("noProgramm", gr)),
                0x91:
                lambda: self._raise(
                    Exception("requiredTimeDelayNotExpired", gr))
            }.get(
                gr[3], lambda: self._raise(
                    Exception("Generic KWP negative response", gr)))()
        return gr

    def readecuid(self, paramdef):
        #KWP2000 command to pull the ECU ID
        self.paramdef = paramdef
        debugneeds = 3
        response = self.sendcommand([0x10, 0x85])  # setup diag session
        reqserviceid = [0x1A]
        sendlist = reqserviceid + self.paramdef
        if debug >= debugneeds:
            print(f"readecuid sending: {hexlist(sendlist)}")
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds:
            print(f"readecuid got: {hexlist(response)}")
        return response

    def securityAccessL3(self):
        ### Begin - level 3 security
        self.sendcommand([0x27, 0x03])
        response = self.getresponse()
        print(f"Seed: {hexlist(response)}")

        ## highBytes(uint8_t) = value(uint16_t) >> 8
        ## lowBytes(uint8_t) = value(uint16_t) & 0xff
        ## value(uint16_t) = (high << 8) + low

        seed = (response[3] << 24) + (response[4] << 16) + (
            response[5] << 8) + response[6]
        print(f"Seed: {seed}")

        key = seed + 12233  # standard VW access
        keyHex = [
            key >> 24 & 0xff, key >> 16 & 0xff, key >> 8 & 0xff, key & 0xff
        ]
        print(f"Seed: {hexlist(keyHex)}")
        self.sendcommand([0x27, 0x04] + keyHex)
        try:
            response = self.getresponse()  #sometimes this doesn't work
        except:
            response = self.getresponse()
        print(hexlist(response))
        if (response[3] != 0x34):
            raise Exception("failed to get L3 auth")

        print("End security level 3 access")

    # def securityAccessL1(self):
    #     pass
    #     ### Begin - Level 1 key/seed
    #     ## request seed 27 01
    #     self.sendcommand([0x27,0x01])
    #     response = self.getresponse()
    #     print(hexlist(response))
    #     # len? secreq  level    seed h    seed l    checksum
    #     # 0x06  0x67    0x01    0x6D 0x20 0xFC 0xB1   0xA8
    #     seedH = (response[3] << 8) + response[4]
    #     seedL = (response[5] << 8) + response[6]

    #     magicValue = 0x1c60020
    #     for count in range(5):
    #         tempstring = seedH &0x8000
    #         seedH = seedH << 1
    #         if(tempstring&0xFFFF == 0):
    #             temp2 = seedL&0xFFFF
    #             temp3 = tempstring&0xFFFF0000
    #             tempstring = temp2+temp3
    #             seedH = seedH&0xFFFE
    #             temp2 = tempstring&0xFFFF
    #             temp2 = temp2 >> 0x0F
    #             tempstring = tempstring&0xFFFF0000
    #             tempstring = tempstring+temp2
    #             seedH = seedH|tempstring
    #             seedL = seedL << 1
    #         else:
    #             tempstring = seedL+seedL
    #             seedH = seedH & 0xFFFE
    #             temp2 = tempstring & 0xFF #Same as EDC15 until this point
    #             temp3 = magicValue & 0xFFFFFF00
    #             temp2 = temp2 | 1
    #             magicValue = temp2 + temp3
    #             magicValue = magicValue & 0xFFFF00FF
    #             magicValue = magicValue | tempstring
    #             temp2 = seedL & 0xFFFF
    #             temp3 = tempstring & 0xFFFF0000
    #             temp2 = temp2 >> 0x0F
    #             tempstring = temp2 + temp3
    #             tempstring = tempstring | seedH
    #             magicValue = magicValue ^ 0x1289
    #             tempstring = tempstring ^ 0x0A22
    #             seedL = magicValue
    #             seedH = tempstring
    #     print(f"H:{seedH} L:{seedL}")
    #     ## high bytes = value >> 8
    #     ## low bytes = value & 0xff
    #     ## value = (high<<8) + low
    #     self.sendcommand([0x27,0x02, seedH & 0xff, seedH >>8, seedL & 0xff, seedL >> 8])
    #     # self.sendcommand([0x27,0x02, 0xff, 0xff, 0xff, 0xff])
    #     response = self.getresponse()

    def securityAccessL1(self):
        self.sendcommand([0x27, 0x01])
        response = self.getresponse()
        print(hexlist(response))
        seed = (response[3] << 24) + (response[4] << 16) + (
            response[5] << 8) + response[6]
        print(f"L1 seed: {seed}")
        '''
        for (byte i = 0; i < 5; i++) {
            if ((seed & 0x80000000) == 0x80000000) { // Check carry
                seed = (SEED_DATA[ecuID]) ^ ((seed << 1) | (seed >>> 31)); // rotate left and xor
            }
            else {
                seed = ((seed << 1) | (seed >>> 31)); // rotate left only
            }
        }
        return seed;
        '''
        magicValue = 0x1c60020

        def rshift(val, n):
            return (val >> n) & (0x7fffffff >> (n - 1))

        for x in range(5):
            if ((seed & 0x80000000) == 0x80000000):
                seed = magicValue ^ ((seed << 1) | rshift(seed, 31))
            else:
                seed = ((seed << 1) | rshift(seed, 31))
        print(f"L1 key: {seed}")
        keyHex = [
            seed >> 24 & 0xff, seed >> 16 & 0xff, seed >> 8 & 0xff, seed & 0xff
        ]
        self.sendcommand([0x27, 0x02] + keyHex)
        # self.sendcommand([0x27,0x02, 0xff, 0xff, 0xff, 0xff])
        return self.getresponse()

    def stopcomm(self):
        # KWP2000 command to tell the ECU that the communications is finished
        stopcommunication = [0x82]
        self.sendcommand(stopcommunication)
        response = self.getresponse()
        return response

    def startdiagsession(self, bps):
        # KWP2000 setup that sets the baud for the logging session
        self.bps = bps
        startdiagnosticsession = [0x10]
        sessionType = [0x86]
        #   if self.bps == 10400:
        #      bpsout = [ 0x?? ]
        #   if self.bps == 14400:
        #      bpsout = [ 0x?? ]
        if self.bps == 19200:
            bpsout = [0x30]
        if self.bps == 38400:
            bpsout = [0x50]
        if self.bps == 56000:
            bpsout = [0x63]
        if self.bps == 57600:
            bpsout = [0x64]
        if self.bps == 124800:
            bpsout = [0x87]
        if self.bps == 250000:
            bpsout = [0xA7]
        if (self.bps != 0):
            sendlist = startdiagnosticsession + sessionType + bpsout
        else:
            sendlist = startdiagnosticsession + sessionType
        self.sendcommand(sendlist)
        response = self.getresponse()
        self.ser.baudrate = self.bps
        time.sleep(1)
        return response

    def accesstimingparameter(self, params):
        # KWP2000 command to access timing parameters
        self.params = params
        accesstiming_setval = [0x83, 0x03]
        accesstiming = accesstiming_setval + self.params
        sendlist = accesstiming
        self.sendcommand(sendlist)
        response = self.getresponse()
        return response

    def readmembyaddr(self, readvals):
        # Function to read an area of ECU memory.
        debugneeds = 4
        self.readvals = readvals
        rdmembyaddr = [0x23]
        sendlist = rdmembyaddr + self.readvals
        if debug >= debugneeds:
            print("readmembyaddr() sendlist: " + hexlist(sendlist))
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds:
            print("readmembyaddr() response: " + hexlist(response))
        return response

    def writemembyaddr(self, writevals):
        # Function to write to an area of ECU memory.
        debugneeds = 4
        self.writevals = writevals
        wrmembyaddr = [0x3D]
        sendlist = wrmembyaddr + self.writevals
        if debug >= debugneeds:
            print("writemembyaddr() sendlist: " + hexlist(sendlist))
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds:
            print("writemembyaddr() response: " + hexlist(response))
        return response

    def testerpresent(self):
        # KWP2000 TesterPresent command
        tp = [0x3E]
        self.sendcommand(tp)
        response = self.getresponse()
        return response

    def setuplogrecord(self, logline):
        # KWP2000 command to access timing parameters
        self.logline = logline
        response = []
        sendlist = [0xb7]  # is 0xB7 the "locator?"
        sendlist = sendlist + [0x03]  # Number of bytes per field ?
        sendlist = sendlist + self.logline
        self.sendcommand(sendlist)
        response = self.getresponse()
        return response

    def getlogrecord(self):
        # Command to request a logging record
        gr = [0xb7]
        self.sendcommand(gr)
        response = self.getresponse()
        return response

    def sendhexstring(self, dumpstring):
        # Takes a list of characters as a string, turns every two characters into a hex byte and sends it raw.
        # used as needed for dev/test/debug
        self.dumpstring = dumpstring
        for i in range(len(self.dumpstring) / 2):
            self.send([int('0x' + self.dumpstring[i * 2:(i * 2) + 2], 16)])
예제 #6
0
파일: ecu.py 프로젝트: SancheZ911/HondaECU
class HondaECU(object):
    def __init__(self, device_id=None, latency=None, baudrate=10400):
        super(HondaECU, self).__init__()
        self.device_id = device_id
        self.dev = None
        self.error = 0
        self.resets = 0
        self.latency = latency
        self.baudrate = baudrate
        self.reset()

    def reset(self):
        if self.dev != None:
            del self.dev
            self.dev = None

        self.dev = Device(self.device_id,
                          auto_detach=(platform.system() != "Windows"))
        self.setup()

    def setup(self):
        self.dev.ftdi_fn.ftdi_usb_reset()
        self.dev.ftdi_fn.ftdi_usb_purge_buffers()
        self.dev.ftdi_fn.ftdi_set_line_property(8, 1, 0)
        self.dev.baudrate = self.baudrate
        if self.latency:
            self.dev.ftdi_fn.ftdi_set_latency_timer(self.latency)
        latency = c_ubyte()
        self.dev.ftdi_fn.ftdi_get_latency_timer(byref(latency))

    def _break(self, ms):
        self.dev.ftdi_fn.ftdi_set_bitmode(1, 0x01)
        self.dev._write(b'\x00')
        time.sleep(ms)
        self.dev._write(b'\x01')
        self.dev.ftdi_fn.ftdi_set_bitmode(0, 0x00)
        self.dev.flush()

    def wakeup(self):
        self._break(.070)
        time.sleep(.130)

    def ping(self):
        return self.send_command([0xfe], [0x72], retries=0) != None

    def probe_tables(self, tables=None):
        if not tables:
            tables = [
                0x10, 0x11, 0x17, 0x20, 0x21, 0x60, 0x61, 0x67, 0x70, 0x71,
                0xd0, 0xd1
            ]
        ret = {}
        for t in tables:
            info = self.send_command([0x72], [0x71, t])
            if info:
                if info[3] > 2:
                    ret[t] = [info[3], info[2]]
            else:
                return {}
        return ret

    def init(self):
        self.wakeup()
        return self.ping()

    def kline_new(self):
        pin_byte = c_ubyte()
        self.dev.ftdi_fn.ftdi_read_pins(byref(pin_byte))
        return (pin_byte.value == 0xff)

    def kline(self, timeout=.05):
        self.dev.flush()
        self.dev._write(b"\x00")
        to = time.time()
        while time.time() - to < timeout:
            tmp = self.dev._read(1)
            if len(tmp) == 1:
                return tmp == b"\x00"
        return False

    def kline_alt(self):
        self.dev.flush()
        self.dev._write(b"\xff")
        return self.dev._read(1) == b"\xff"

    def kline_old(self):
        b = create_string_buffer(2)
        self.dev.ftdi_fn.ftdi_poll_modem_status(b)
        return b.raw[1] & 16 == 0

    def send(self, buf, ml, timeout=.001):
        self.dev.flush()
        msg = "".join([chr(b) for b in buf]).encode("latin1")
        self.dev._write(msg)
        r = len(msg)
        timeout = .05 + timeout * r
        to = time.time()
        while r > 0:
            r -= len(self.dev._read(r))
            if time.time() - to > timeout: return None
        buf = bytearray()
        r = ml + 1
        while r > 0:
            tmp = self.dev._read(r)
            r -= len(tmp)
            buf.extend(tmp)
            if time.time() - to > timeout: return None
        r = buf[-1] - ml - 1
        while r > 0:
            tmp = self.dev._read(r)
            r -= len(tmp)
            buf.extend(tmp)
            if time.time() - to > timeout: return None
        return buf

    def send_command(self, mtype, data=[], retries=1):
        msg, ml, dl = format_message(mtype, data)
        r = 0
        while r <= retries:
            dispatcher.send(signal="ecu.debug",
                            sender=self,
                            msg="%d > [%s]" %
                            (r, ", ".join(["%02x" % m for m in msg])))
            resp = self.send(msg, ml)
            if resp:
                if checksum8bitHonda(resp[:-1]) == resp[-1]:
                    dispatcher.send(signal="ecu.debug",
                                    sender=self,
                                    msg="%d < [%s]" %
                                    (r, ", ".join(["%02x" % r for r in resp])))
                    rmtype = resp[:ml]
                    valid = False
                    if ml == 3:
                        valid = (rmtype[:2] == bytearray(
                            map(lambda x: x | 0x10, mtype[:2])))
                    elif ml == 1:
                        valid = (rmtype == bytearray(
                            map(lambda x: x & 0xf, mtype)))
                    if valid:
                        rml = resp[ml:(ml + 1)]
                        rdl = ord(rml) - 2 - len(rmtype)
                        rdata = resp[(ml + 1):-1]
                        return (rmtype, rml, rdata, rdl)
                    else:
                        return None
            r += 1

    def detect_ecu_state_new(self):
        t0 = self.send_command([0x72], [0x71, 0x00], retries=0)
        if t0 is None:
            self.wakeup()
            self.ping()
            t0 = self.send_command([0x72], [0x71, 0x00], retries=0)
        if not t0 is None:
            if bytes(t0[2][5:7]) != b"\x00\x00":
                return ECUSTATE.OK
            else:
                if self.send_command([0x7d], [0x01, 0x01, 0x00], retries=0):
                    return ECUSTATE.RECOVER_OLD
                if self.send_command([0x7b], [0x00, 0x01, 0x01], retries=0):
                    return ECUSTATE.RECOVER_NEW
        else:
            writestatus = self.send_command([0x7e], [0x01, 0x01, 0x00],
                                            retries=0)
            if not writestatus is None:
                if writestatus[2][1] == 0x0f:
                    return ECUSTATE.WRITE_GOOD
                elif writestatus[2][1] == 0x10:
                    return ECUSTATE.WRITE_INIT_OLD
                elif writestatus[2][1] == 0x20:
                    return ECUSTATE.WRITE_INIT_NEW
                elif writestatus[2][1] == 0x30:
                    return ECUSTATE.ERASE
                elif writestatus[2][1] == 0x40:
                    return ECUSTATE.WRITE
                elif writestatus[2][1] == 0x0:
                    return ECUSTATE.WRITE_UNKNOWN1
                else:
                    return ECUSTATE.ERROR
            else:
                readinfo = self.send_command([0x82, 0x82, 0x00],
                                             [0x00, 0x00, 0x00, 0x08],
                                             retries=0)
                if not readinfo is None:
                    return ECUSTATE.READ
        return ECUSTATE.OFF if not self.kline() else ECUSTATE.UNKNOWN

    def do_init_recover(self):
        self.send_command([0x7b], [0x00, 0x01, 0x01])
        self.send_command([0x7b], [0x00, 0x01, 0x02])
        self.send_command([0x7b], [0x00, 0x01, 0x03])
        self.send_command([0x7b], [0x00, 0x02, 0x76, 0x03, 0x17])
        self.send_command([0x7b], [0x00, 0x03, 0x75, 0x05, 0x13])

    def do_init_write(self):
        self.send_command([0x7d], [0x01, 0x01, 0x01])
        self.send_command([0x7d], [0x01, 0x01, 0x02])
        self.send_command([0x7d], [0x01, 0x01, 0x03])
        self.send_command([0x7d], [0x01, 0x02, 0x50, 0x47, 0x4d])
        self.send_command([0x7d], [0x01, 0x03, 0x2d, 0x46, 0x49])

    def do_erase(self):
        self.send_command([0x7e], [0x01, 0x02])
        self.send_command([0x7e], [0x01, 0x03, 0x00, 0x00])
        self.send_command([0x7e],
                          [0x01, 0x0b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff])
        self.send_command([0x7e], [0x01, 0x0e, 0x01, 0x90])
        self.send_command([0x7e], [0x01, 0x01, 0x01])
        self.send_command([0x7e], [0x01, 0x04, 0xff])

    def do_erase_wait(self):
        cont = 1
        while cont:
            info = self.send_command([0x7e], [0x01, 0x05])
            if info:
                if info[2][1] == 0x00:
                    cont = 0
            else:
                cont = -1
        if cont == 0:
            into = self.send_command([0x7e], [0x01, 0x01, 0x00])

    def do_post_write(self):
        self.send_command([0x7e], [0x01, 0x09])
        time.sleep(.5)
        self.send_command([0x7e], [0x01, 0x0a])
        time.sleep(.5)
        self.send_command([0x7e], [0x01, 0x0c])
        time.sleep(.5)
        info = self.send_command([0x7e], [0x01, 0x0d])
        if info: return (info[2][1] == 0x0f)

    def get_faults(self):
        faults = {'past': [], 'current': []}
        for i in range(1, 0x0c):
            info_current = self.send_command([0x72], [0x74, i])[2]
            for j in [3, 5, 7]:
                if info_current[j] != 0:
                    faults['current'].append(
                        "%02d-%02d" % (info_current[j], info_current[j + 1]))
            if info_current[2] == 0:
                break
        for i in range(1, 0x0c):
            info_past = self.send_command([0x72], [0x73, i])[2]
            for j in [3, 5, 7]:
                if info_past[j] != 0:
                    faults['past'].append("%02d-%02d" %
                                          (info_past[j], info_past[j + 1]))
            if info_past[2] == 0:
                break
        return faults
예제 #7
0
파일: MDB.py 프로젝트: pc-coholic/pylibmdb
class MDB(object):
  def __init__(self, deviceid):
    self.__deviceid = deviceid
    self.__scaling = 0
    self.__coins = {}
    self.__deposited = 0

  def _ftdisend(self, data, mode):
    data_parity = self._parityOf(int(hexlify(data), 16))

    if data_parity == -1:
      if mode:
        #parity = serial.PARITY_EVEN
        parity = 2
      else:
        #parity = serial.PARITY_ODD
        parity = 1
    else:
      if mode:
        #parity = serial.PARITY_ODD
        parity = 1
      else:
        #parity = serial.PARITY_EVEN
        parity = 2
    try:
        self.__device = Device(self.__deviceid)
        self.__device.ftdi_fn.ftdi_set_line_property(8, 1, parity)
        self.__device.baudrate = 9600
        self.__device.write(data)
        self.__device.flush()
    except pylibftdi.FtdiError:
        print "FtdiError"
        self._ftdisend(data, mode)

  def _parityOf(self, int_type):
      parity = 0
      while (int_type):
          parity = ~parity
          int_type = int_type & (int_type - 1)
      return(parity)

  def _read(self):
    returndata = []
    for i in self.__device.read(100):
      returndata.append(i)

    return returndata

  def _send(self, data):
    mode = 1

    for element in data:
      self._ftdisend(element, mode)
      mode = 0

    self._ftdisend(self._calcchk(data), 0)

    time.sleep(0.1)
    return self._read()

  def _calcchk(self, data):
    sum = 0
    for byte in data:
        sum += int(hexlify(byte), 16)
    return unhexlify('{:02x}'.format(sum % 256))

  def _getbits(self, byte):
    return bin(int(hexlify(byte), 16))[2:].zfill(8)

# CoinChanger
  def reset(self):
    print "OUT: Reset"
    answer = self._send(data = ['\x08'])
    if (len(answer) == 1) and (answer[0] == '\x00'):
      print "IN : OK"
      #self.ack()
    else:
      print "IN: Fail"
      print answer

  def poll(self):
    print "OUT: Poll"
    answer = self._send(data = ['\x0B'])

    i = 0
    while i < len(answer):
      if answer[i] == '\x00':
        message = "ACK"
      elif answer[i] == '\xFF':
        message = "NACK"
      elif '\x01' <= answer[i] <= '\x0D':
        message = {
          '\x01': 'Escrow request - An escrow lever activation has been detected.',
          '\x02': 'Changer Payout Busy - The changer is busy activating payout devices',
          '\x03': 'No Credit - A coin was validated but did not get to the place in the system when credit is given',
          '\x04': 'Defective Tube Sensor - The changer hasdetected one of the tube sensors behaving abnormally',
          '\x05': 'Double Arrival - Two coins were detected too close together to validate either one',
          '\x06': 'Acceptor Unplugged - The changer has detected that the acceptor has been removed',
          '\x07': 'Tube Jam - A tube payout attempt has resulted in jammed condition',
          '\x08': 'ROM checksum error - The changers internal checksum does not match the calculated checksum',
          '\x09': 'Coin Routing Error - A coin has been validated, but did not follow the intended routing',
          '\x0A': 'Changer Busy - The changer is busy and can not answer a detailed command right now',
          '\x0B': 'Changer was Reset - The changer has detected an Reset condition and has returned to its power-on idle condition',
          '\x0C': 'Coin Jam - A coin(s) has jammed in the acceptance path',
          '\x0D': 'Possible Credited Coin Removal - There has been an attempt to remove a credited coin',
        }.get(answer[i])
        print "IN: " + message
      elif '\x20' <= answer[i] <= '\x3F':
        print "IN: Slugs deposited: " + str(int(self._getbits(answer[i])[3:], 2))
      elif '\x40' <= answer[i] <= '\x7F':
        bits = self._getbits(answer[i])

        if bits[2:4] == '00':
          routing = "Cash Box"
        elif bits[2:4] == '01':
          routing = "Tubes"
        elif bits[2:4] == '10':
          routing = "Not used"
        elif bits[2:4] == '11':
          routing = "Rejected"
        else:
          routing = "Unknown"

        cointype = int(bits[4:8], 2)
        coinsinroutingpath = str(int(self._getbits(answer[i+1]), 2))

        print "IN: Coin deposited: Type " + str(cointype) + ", sent to " + routing  + ". Now " + coinsinroutingpath + " coins there"
        self.__deposited += self.__coins[cointype] * self.__scaling
        i += 1
        break;
      elif '\x80' <= answer[i] <= '\xFE':
        bits = self._getbits(answer[i])
        
        number = str(int(bits[1:4], 2))
        cointype = str(int(bits[4:8], 2))
        coinsintube = str(int(self._getbits(answer[i+1]), 2))
        print "IN: Coins dispensed manually: " + number + " coins of type " + cointype  + ". Now " + coinsintube + " coins there"
        i += 1
        break;
      else: #\x0E -> \x1F
        print "IN: Unknown Poll Status reply" + hexlify(answer[i])
      i += 1
    self.ack()

  def setup(self):
    print "OUT: Setup"
    answer = self._send(data = ['\x09'])
    if len(answer) == 24:
      print "IN: Changer Feature Level: " + str(ord(answer[0])) + " (" + hex(ord(answer[0])) + ")"
      print "IN: Country/Currency-Code: " + hex(ord(answer[1])) + " " + hex(ord(answer[2]))
      print "IN: Coin Scaling Factor: " + str(ord(answer[3])) + " (" + hex(ord(answer[3])) + ")"
      self.__scaling = int(ord(answer[3]))
      print "IN: Decimal Places: " + str(ord(answer[4])) + " (" + hex(ord(answer[4])) + ")"
      canberoutedtotube = (self._getbits(answer[5]) + self._getbits(answer[6]))[::-1]
      for i in range(7, 23):
        print "IN: Coin Type: " + str(i-7) + ", Value: " + str(ord(answer[i])) + ", Can be routed to tube: " + canberoutedtotube[i-7]
        self.__coins[(i-7)] = int(ord(answer[i]))
      self.ack()
    else:
      print "IN: Fail - " + answer

  def expansionidentification(self):
    print "OUT: Expansion Identification"
    answer = self._send(data = ['\x0F', '\x00'])
    if len(answer) == 34:
      print "IN: Manufacturer Code: " + str(answer[0]) + str(answer[1]) + str(answer[2]) + " (" + hex(ord(answer[0])) + " " + hex(ord(answer[1])) + " " + hex(ord(answer[2])) + ")"
      print "IN: Serial Number: " + ''.join(answer[i] for i in range(3, 15)) + " (" + " ".join(hex(ord(answer[i])) for i in range(3, 15)) + ")"
      print "IN: Model #/Tuning Revision: " + ''.join(answer[i] for i in range(15, 27)) + " (" + " ".join(hex(ord(answer[i])) for i in range(15, 27)) + ")"
      print "IN: Software Version: " + hex(ord(answer[27])) + " " + hex(ord(answer[28]))
      optionalfeatures = (self._getbits(answer[29]) + self._getbits(answer[30]) + self._getbits(answer[31]) + self._getbits(answer[32]))[::-1]
      print "IN: Optional Feature: Alternative Payout method: " + optionalfeatures[0]
      print "IN: Optional Feature: Extended Diagnostic command supported: " + optionalfeatures[1]
      print "IN: Optional Feature: Controlled Manual Fill and Payout commands supported: " + optionalfeatures[2]
      print "IN: Optional Feature: File Transport Layer (FTL) supported: " + optionalfeatures[3]
      print "IN: Optional Features: Future extensions: " + optionalfeatures[4:]
      self.ack()
      features = []
      for i in range (29, 33):
        features.append(ord(answer[i]))
      return features
    else:
      print "IN: Fail - " + answer

  def expansionfeatureenable(self, features):
    print "OUT: Expansion Feature Enable"
    answer = self._send(data = ['\x0F', '\x01'] + features)
    if (len(answer) == 1) and (answer[0] == '\x00'):
      print "IN : OK"
      self.ack()
    else:
     print "IN: Fail - " + answer

  def expansiondiagnosticstatus(self):
    print "OUT: Expansion Diagnostic Status"
    answer = self._send(data = ['\x0F', '\x05'])
    if len(answer) == 3:
      print "IN: Main-Code: " + hex(ord(answer[0]))
      print "IN: Sub-Code: " + hex(ord(answer[1]))
      message = {
        '\x01': 'Powering up',
        '\x02': 'Powering down',
        '\x03': 'OK',
        '\x04': 'Keypad shifted',
        '\x05': '',
        '\x06': 'Inhibited by VMC',
        '\x10': '',
        '\x11': '',
        '\x12': '',
        '\x13': '',
        '\x14': '',
        '\x15': '',
        'unknown': 'Unknown Main-Code',
      }.get(answer[0], 'unknown')

      if ( (answer[0] == '\x05') and (answer[1] == '\x10') ):
        message = "Manual Fill / Payout active"

      if ( (answer[0] == '\x05') and (answer[1] == '\x20') ):
        message = "New Inventory Information Available"

      if answer[0] == '\x10':
        message = "General changer error: " + {
          '\x00': 'Non specific error',
          '\x01': 'Check sum error #1. A check sum error over a particular data range of configuration field detected.',
          '\x02': 'Check sum error #2. A check sum error over a secondary data range or configuration field detected.',
          '\x03': 'Low line voltage detected. The changer has disabled acceptance or payout due to a low voltage condition',
          'unknown': 'Unknown Sub-Code',
        }.get(answer[1], 'unknown')

      if answer[0] == '\x11':
        message = "Discriminator module error: " + {
          '\x00': 'Non specific discriminator error.',
          '\x10': 'Flight deck open.',
          '\x11': 'Escrow Return stuck open.',
          '\x30': 'Coin jam in sensor.',
          '\x41': 'Discrimination below specified standard.',
          '\x50': 'Validation sensor A out of range. The acceptor detects a problem with sensor A.',
          '\x51': 'Validation sensor B out of range. The acceptor detects a problem with sensor B.',
          '\x52': 'Validation sensor C out of range. The acceptor detects a problem with sensor C.',
          '\x53': 'Operating temperature exceeded. The acceptor detects the ambient temperature has exceeded the changer\'s operating range, thus possibly affecting the acceptance rate.',
          '\x54': 'Sizing optics failure. The acceptor detects an error in the sizing optics.',
          'unknown': 'Unknown Sub-Code',
      }.get(answer[1], 'unknown')

      if answer[0] == '\x12':
        message = "Accept gate module error: " + {
          '\x00': 'Non specific accept gate error',
          '\x30': 'Coins entered gate, but did not exit.',
          '\x31': 'Accept gate alarm active.',
          '\x40': 'Accept gate open, but no coin detected.',
          '\x50': 'Post gate sensor covered before gate opened.',
          'unknown': 'Unknown Sub-Code',
      }.get(answer[1], 'unknown')

      if answer[0] == '\x13':
        message = "Separator module error: " + {
          '\x00': 'Non specific separator error',
          '\x10': 'Sort sensor error. The acceptor detects an error in the sorting sensor',
          'unknown': 'Unknown Sub-Code',
      }.get(answer[1], 'unknown')

      if answer[0] == '\x14':
        message = "Dispenser module error: " + {
          '\x00': 'Non specific dispenser error.',
          'unknown': 'Unknown Sub-Code',
      }.get(answer[1], 'unknown')

      if answer[0] == '\x15':
        message = "Coin Cassette / tube module error: " + {
          '\x00': 'Non specific cassette error.',
          '\x02': 'Cassette removed.',
          '\x03': 'Cash box sensor error. The changer detects an error in a cash box sensor.',
          '\x04': 'Sunlight on tube sensors. The changer detects too much ambient light on one or more of the tube sensors.',
          'unknown': 'Unknown Sub-Code',
      }.get(answer[1], 'unknown')

      print "IN: Message: " + message
      self.ack()
    else:
      print "IN: Fail - " + answer

  def tubestatus(self):
    print "OUT: Tube Status"
    answer = self._send(data = ['\x0A'])
    if len(answer) == 19:
      print "IN: Tube Full Status: " + hex(ord(answer[0])) + " " + hex(ord(answer[1]))
      for i in range(2, 18):
        print "IN: Tube Status: " + str(i-2) + " --> " + str(ord(answer[i])) + " (" + hex(ord(answer[i])) + ")"
      self.ack()
    else:
      print "IN: Fail - " + answer

  def enableall(self, manual = False):
    if manual == True:
      self.cointype('\xFF', '\xFF', '\xFF', '\xFF')
    else:
      self.cointype('\xFF', '\xFF', '\x00', '\x00')

  def disableall(self, manual = False):
    if manual == True:
      self.cointype('\x00', '\x00', '\xFF', '\xFF')
    else:
      self.cointype('\x00', '\x00', '\x00', '\x00')

  def cointype(self, enable1, enable2, manual1, manual2):
    print "OUT: Coin type"
    answer = self._send(data = ['\x0C', enable1, enable2, manual1, manual2])
    if (len(answer) == 1) and (answer[0] == '\x00'):
      print "IN : OK"
      self.ack()
    else:
      print "IN: Fail - " + answer

  def ack(self):
    print "OUT: ACK"
    # ACK, NACK and RET don't take the mode-Bit
    self._ftdisend('\x00', 0)

  def payout(self, value):
    print "OUT: Payout"
    self._send(data = ['\x0F', '\x02', unhexlify('{:02x}'.format(int(value) / self.__scaling)) ])

  def payoutpoll(self):
    print "OUT: Payout Poll"
    self._send(data = ['\x0F', '\x04'])

  def payoutstatus(self):
    print "OUT: Payout Status"
    self._send(data = ['\x0F', '\x03'])

  def getdeposited(self):
    return self.__deposited

  def cleardeposited(self):
    self.__deposited = 0
예제 #8
0
파일: pylibme7.py 프로젝트: gsiepen/mmll
class Ecu:

   def __init__(self):
      self.ser = Device(mode='b', lazy_open=True)


   def bbang(self, bba):
      # Take the one-byte address to "bit bang" and bang the port
      self.bba = bba
      self.bbser = BitBangDevice()
      self.bbser.open()
      self.bbser.direction = 0x01
      self.bbser.port = 1
      time.sleep(.5)
      self.bbser.port = 0
      outstr = "><"
      sys.stdout.write('\r' + outstr)
      sys.stdout.flush()
      time.sleep(.2)
      bbbitmask = 1
      for i in range(8):
         if (self.bba[0] & bbbitmask) > 0:
            outbit = 1
         else:
            outbit = 0   
         self.bbser.port = outbit
         outstr = ">" + str(outbit) + outstr[1:] 
         sys.stdout.write('\r' + outstr)
         sys.stdout.flush()
         bbbitmask = bbbitmask * 2
         time.sleep(.2)
      self.bbser.port = 1
      sys.stdout.write("\n")
      self.bbser.close()

   def initialize(self, connect):
      self.connect = connect
      if self.connect == "SLOW-0x11":
         self.ser.close()
         time.sleep(.5)

         self.ecuconnect = False
         while self.ecuconnect == False:
            print("Attempting ECU connect: " + self.connect )

            # Bit bang the K-line
            bbseq = [ 0x11 ]
            self.bbang(bbseq)
            self.ser.open()
            self.ser.ftdi_fn.ftdi_set_line_property(8, 1, 0)
            self.ser.baudrate = 10400
            self.ser.flush()

            # Wait for ECU response to bit bang
            waithex = [ 0x55, 0xef, 0x8f, 1 ]
            self.waitfor(waithex)
            # Wait a bit
            time.sleep(.026)

            # Send 0x70
            self.send([ 0x70 ])
   
            # 0xee means that we're talking to the ECU
            waithex = [ 0xee, 1 ]
            response = self.waitfor(waithex)
            if response[0] == True:
                self.ecuconnect = True
            else:
                print("ECU Connect Failed.  Retrying.")

   def waitfor(self, wf):
      # This was used for debugging and really is only used for the init at this point.
      # wf should be a list with the timeout in the last element
      self.wf = wf
      isfound = False
      idx = 0
      foundlist = []
      capturebytes = []
      to = self.wf[-1]
      timecheck = time.time()
      while (time.time() <= (timecheck+to)) & (isfound == False): 
         try:
            recvbyte = self.recvraw(1)
            if recvbyte != "":
               recvdata = ord(recvbyte)
               capturebytes = capturebytes + [ recvdata ]
               if recvdata == self.wf[idx]: 
                  foundlist = foundlist + [ recvdata ]
                  idx = idx + 1
               else: 
                  foundlist = []
                  idx = 0
               if idx == len(self.wf)-1:
                  isfound = True
         except:
            print('error')
            break
      return [ isfound, foundlist, capturebytes ]

   def send(self, sendlist):
      self.sendlist = sendlist
      # Puts every byte in the sendlist out the serial port
      for i in self.sendlist:
         self.ser.write(chr(i))

   def recvraw(self, bytes):
      self.bytes = bytes
      recvdata = self.ser.read(self.bytes)
      return recvdata

   def recv(self, bytes):
      self.bytes = bytes
      isread = False
      while isread == False:
         recvbyte = self.ser.read(self.bytes)
         if recvbyte != "":
            recvdata = recvbyte
            isread = True
      return recvdata      

   def sendcommand(self, sendlist):
      # Wraps raw KWP command in a length byte and a checksum byte and hands it to send()
      self.sendlist = sendlist
      csum = 0
      self.sendlist = [len(self.sendlist)] + self.sendlist 
      csum = self.checksum(self.sendlist)
      self.sendlist = self.sendlist + [csum] 
      self.send(self.sendlist)
      cmdval = self.commandvalidate(self.sendlist)
      return cmdval

   def commandvalidate(self, command):
      # Every KWP command is echoed back.  This clears out these bytes.
      self.command = command
      cv = True
      for i in range(len(self.command)):
         recvdata = self.recv(1)
         if ord(recvdata) != self.command[i]:
            cv = cv & False
      return cv   

   def checksum(self, checklist):
      # Calculates the simple checksum for the KWP command bytes.
      self.checklist = checklist
      csum = 0
      for i in self.checklist:
         csum = csum + i
      csum = (csum & 0xFF) % 0xFF
      return csum

   def getresponse(self):
      # gets a properly formated KWP response from a command and returns the data. 
      debugneeds = 4
      numbytes = 0
      while numbytes == 0:     # This is a hack because sometimes responses have leading 0x00's.  Why?  This removes them.
         numbytes = ord(self.recv(1))
      gr = [ numbytes ]
      if debug >= debugneeds: print("Get bytes: " + hex(numbytes))
      for i in range(numbytes):
         recvdata = ord(self.recv(1))
         if debug >= debugneeds: print("Get byte" + str(i) + ": " + hex(recvdata))
         gr = gr + [ recvdata ]
      checkbyte = self.recv(1)
      if debug >= debugneeds: print(gr)
      if debug >= debugneeds: print("GR: " + hex(ord(checkbyte)) + "<-->" + hex(self.checksum(gr))) 
      return (gr + [ ord(checkbyte) ])

   def readecuid(self, paramdef):      
      # KWP2000 command to pull the ECU ID
      self.paramdef = paramdef
      debugneeds = 4
      reqserviceid = [ 0x1A ]
      sendlist = reqserviceid + self.paramdef
      if debug >= debugneeds: print( sendlist )
      self.sendcommand(sendlist)
      response = self.getresponse()
      if debug >= debugneeds: print(response)
      return response

   def stopcomm(self):
      # KWP2000 command to tell the ECU that the communications is finished
      stopcommunication = [ 0x82 ]
      self.sendcommand(stopcommunication)
      response = self.getresponse()
      return response

   def startdiagsession(self, bps):
      # KWP2000 setup that sets the baud for the logging session
      self.bps = bps
      startdiagnosticsession = [ 0x10 ]
      setbaud = [ 0x86 ]  #Is this the actual function of 0x86?
   #   if self.bps == 10400:
   #      bpsout = [ 0x?? ]
   #   if self.bps == 14400:
   #      bpsout = [ 0x?? ]
      if self.bps == 19200:
         bpsout = [ 0x30 ]
      if self.bps == 38400:
         bpsout = [ 0x50 ]
      if self.bps == 56000:
         bpsout = [ 0x63 ]
      if self.bps == 57600:
         bpsout = [ 0x64 ]
   #   if self.bps == 125000:
   #      bpsout = [ 0x?? ]
      sendlist = startdiagnosticsession + setbaud + bpsout
      self.sendcommand(sendlist)
      response = self.getresponse()
      self.ser.baudrate = self.bps
      time.sleep(1)
      return response

   def accesstimingparameter(self, params):
      # KWP2000 command to access timing parameters
      self.params = params
      accesstiming_setval = [ 0x083, 0x03 ]
      accesstiming = accesstiming_setval + self.params
      sendlist = accesstiming
      self.sendcommand(sendlist)
      response = self.getresponse()
      return response
   
   def readmembyaddr(self, readvals):
      # Function to read an area of ECU memory.
      debugneeds = 4
      self.readvals = readvals
      rdmembyaddr = [ 0x23 ]
      sendlist = rdmembyaddr + self.readvals
      if debug >= debugneeds: print("readmembyaddr() sendlist: " + sendlist)
      self.sendcommand(sendlist)
      response = self.getresponse()
      if debug >= debugneeds: print("readmembyaddr() response: " + response)
      return response

   def writemembyaddr(self, writevals):
      # Function to write to an area of ECU memory.
      debugneeds = 4
      self.writevals = writevals
      wrmembyaddr = [ 0x3D ]
      sendlist = wrmembyaddr + self.writevals
      if debug >= debugneeds: print("writemembyaddr() sendlist: " + sendlist)
      self.sendcommand(sendlist)
      response = self.getresponse()
      if debug >= debugneeds: print("writemembyaddr() response: " + response)
      return response

   def testerpresent(self):
      # KWP2000 TesterPresent command
      tp = [ 0x3E ]
      self.sendcommand(tp)
      response = self.getresponse()
      return response

   def setuplogrecord(self, logline):
      # KWP2000 command to access timing parameters
      self.logline = logline
      response = []
      sendlist = [ 0xb7 ]                           # is 0xB7 the "locator?"
      sendlist = sendlist + [ 0x03 ]           # Number of bytes per field ?
      sendlist = sendlist + self.logline                
      self.sendcommand(sendlist)
      response = self.getresponse()
      return response

   def getlogrecord(self):
      # Command to request a logging record
      gr = [ 0xb7 ]
      self.sendcommand(gr)
      response = self.getresponse()
      return response

   def sendhexstring(self, dumpstring):
      # Takes a list of characters as a string, turns every two characters into a hex byte and sends it raw.
      # used as needed for dev/test/debug
      self.dumpstring = dumpstring
      for i in range(len(self.dumpstring)/2):
         self.send([ int('0x'+self.dumpstring[i*2:(i*2)+2],16) ])
예제 #9
0
class HondaECU(object):

	def __init__(self, device_id=None):
		super(HondaECU, self).__init__()
		self.device_id = device_id
		self.dev = None
		self.error = 0
		self.resets = 0
		self.reset()

	def reset(self):
		if self.dev != None:
			del self.dev
			self.dev = None
		self.dev = Device(self.device_id)

	def setup(self):
		self.dev.ftdi_fn.ftdi_usb_reset()
		self.dev.ftdi_fn.ftdi_usb_purge_buffers()
		self.dev.ftdi_fn.ftdi_set_line_property(8, 1, 0)
		self.dev.baudrate = 10400

	def _break(self, ms, debug=False):
		self.dev.ftdi_fn.ftdi_set_bitmode(1, 0x01)
		self.dev._write(b'\x00')
		time.sleep(ms)
		self.dev._write(b'\x01')
		self.dev.ftdi_fn.ftdi_set_bitmode(0, 0x00)
		self.dev.flush()

	def init(self, debug=False):
		ret = False
		self._break(.070)
		time.sleep(.130)
		self.dev.flush()
		info = self.send_command([0xfe],[0x72], debug=debug, retries=0) # 0xfe <- KWP2000 fast init all nodes ?
		if info != None and ord(info[0]) > 0:
			if ord(info[2]) == 0x72:
				ret = True
		return ret

	def kline(self):
		b = create_string_buffer(2)
		self.dev.ftdi_fn.ftdi_poll_modem_status(b)
		return b.raw[1] & 16 == 0

	def send(self, buf, ml, timeout=.5):
		self.dev.flush()
		msg = "".join([chr(b) for b in buf]).encode("latin1")
		self.dev._write(msg)
		r = len(msg)
		to = time.time()
		while r > 0:
			r -= len(self.dev._read(r))
			if time.time() - to > timeout: return None
		buf = bytearray()
		r = ml+1
		while r > 0:
			tmp = self.dev._read(r)
			r -= len(tmp)
			buf.extend(tmp)
			if time.time() - to > timeout: return None
		r = buf[-1]-ml-1
		while r > 0:
			tmp = self.dev._read(r)
			r -= len(tmp)
			buf.extend(tmp)
			if time.time() - to > timeout: return None
		return buf

	def send_command(self, mtype, data=[], retries=10, debug=False):
		msg, ml, dl = format_message(mtype, data)
		first = True
		while first or retries > 0:
			first = False
			if debug:
				sys.stderr.write("> [%s]" % ", ".join(["%02x" % m for m in msg]))
			resp = self.send(msg, ml)
			ret = None
			if resp == None:
				if debug:
					sys.stderr.write(" !%d \n" % (retries))
				retries -= 1
				time.sleep(0)
				continue
			else:
				if debug:
					sys.stderr.write("\n")
			if debug:
				sys.stderr.write("< [%s]" % ", ".join(["%02x" % r for r in resp]))
			invalid = (resp[-1] != checksum8bitHonda([r for r in resp[:-1]]))
			if invalid:
				if debug:
					sys.stderr.write(" !%d \n" % (retries))
				retries -= 1
				time.sleep(0)
				continue
			else:
				if debug:
					sys.stderr.write("\n")
			sys.stderr.flush()
			rmtype = resp[:ml]
			rml = resp[ml:(ml+1)]
			rdl = ord(rml) - 2 - len(rmtype)
			rdata = resp[(ml+1):-1]
			return (rmtype, rml, rdata, rdl)

	def do_init_recover(self, debug=False):
		self.send_command([0x7b], [0x00, 0x01, 0x03], debug=debug)
		self.send_command([0x7b], [0x00, 0x01, 0x01], debug=debug)
		self.send_command([0x7b], [0x00, 0x01, 0x02], debug=debug)
		self.send_command([0x7b], [0x00, 0x01, 0x03], debug=debug)
		self.send_command([0x7b], [0x00, 0x02, 0x76, 0x03, 0x17], debug=debug) # seed/key?
		self.send_command([0x7b], [0x00, 0x03, 0x75, 0x05, 0x13], debug=debug) # seed/key?

	def do_init_write(self, debug=False):
		# is this the command to erase the ECU?
		self.send_command([0x7d], [0x01, 0x01, 0x00], debug=debug)
		self.send_command([0x7d], [0x01, 0x01, 0x01], debug=debug)
		self.send_command([0x7d], [0x01, 0x01, 0x02], debug=debug)
		self.send_command([0x7d], [0x01, 0x01, 0x03], debug=debug)
		self.send_command([0x7d], [0x01, 0x02, 0x50, 0x47, 0x4d], debug=debug) # seed/key?
		self.send_command([0x7d], [0x01, 0x03, 0x2d, 0x46, 0x49], debug=debug) # seed/key?

	def do_pre_write(self, debug=False):
		self.send_command([0x7e], [0x01, 0x01, 0x00], debug=debug)
		time.sleep(11)
		self.send_command([0x7e], [0x01, 0x02], debug=debug)
		self.send_command([0x7e], [0x01, 0x03, 0x00, 0x00], debug=debug)
		self.send_command([0x7e], [0x01, 0x01, 0x00], debug=debug)
		self.send_command([0x7e], [0x01, 0x0b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff], debug=debug) # password?
		self.send_command([0x7e], [0x01, 0x01, 0x00], debug=debug)
		self.send_command([0x7e], [0x01, 0x0e, 0x01, 0x90], debug=debug)
		self.send_command([0x7e], [0x01, 0x01, 0x01], debug=debug)
		self.send_command([0x7e], [0x01, 0x04, 0xff], debug=debug)
		self.send_command([0x7e], [0x01, 0x01, 0x00], debug=debug)

	def do_pre_write_wait(self, debug=False):
		while True:
			info = self.send_command([0x7e], [0x01, 0x05], debug=debug)
			if info[2][1] == 0x00:
				break
		self.send_command([0x7e], [0x01, 0x01, 0x00], debug=debug)
			toSend = 'S%s+' % msg['S']
			print '>> %s' % toSend.encode('string_escape')
			self.tellstick.write(toSend)
		time.sleep(2) # Make sure you sleep or else it won't like getting another command so soon!

	def go(self):
		self.threatellStick = threading.Thread(target=self.writer)
		self.threatellStick.daemon = True
		self.threatellStick.start()

		# We wait for the writer to be actually running (but not yet
		# writing anything) before we start the reader.
		self.running.wait()
		self.thread2 = threading.Thread(target=self.reader)
		self.thread2.daemon = True
		self.thread2.start()

	def join(self):
		# Use of a timeout allows Ctrl-C interruption
		self.threatellStick.join(timeout=1e6)
		self.thread2.join(timeout=1e6)

if __name__ == '__main__':

	tellStick = TellStick(mode='t')
	tellStick.flush()
	app = Application(tellStick)
	app.go()
	app.join()
	tellStick.flush()
예제 #11
0
def main():
    d1 = Device(device_index=0)
    d2 = Device(device_index=1)

    for b in 9600, 38400, 115200:
        print("Testing {} baud".format(b))
        d1.flush()
        d2.flush()
        print("Half duplex d1->d2...")
        test_half_duplex_transfer(d1, d2, baudrate=b)
        d1.flush()
        d2.flush()
        print("Half duplex d2->d1...")
        test_half_duplex_transfer(d2, d1, baudrate=b)
        d1.flush()
        d2.flush()
        print("Full duplex d1<=>d2...")
        test_full_duplex_transfer(d1, d2, baudrate=b)
예제 #12
0
파일: ecu.py 프로젝트: macsboost/HondaECU
class HondaECU(object):
    def __init__(self,
                 device_id=None,
                 dprint=None,
                 latency=None,
                 baudrate=10400):
        super(HondaECU, self).__init__()
        self.device_id = device_id
        self.dev = None
        self.error = 0
        self.resets = 0
        self.latency = latency
        self.baudrate = baudrate
        if not dprint:
            self.dprint = self.__dprint
        else:
            self.dprint = dprint
        self.reset()

    def __dprint(self, msg):
        sys.stderr.write(msg)
        sys.stderr.write("\n")
        sys.stderr.flush()

    def reset(self):
        if self.dev != None:
            del self.dev
            self.dev = None

        self.dev = Device(self.device_id,
                          auto_detach=(platform.system() != "Windows"))
        self.setup()
        self.starttime = time.time()

    def time(self):
        return time.time() - self.starttime

    def setup(self):
        self.dev.ftdi_fn.ftdi_usb_reset()
        self.dev.ftdi_fn.ftdi_usb_purge_buffers()
        self.dev.ftdi_fn.ftdi_set_line_property(8, 1, 0)
        self.dev.baudrate = self.baudrate
        if self.latency:
            self.dev.ftdi_fn.ftdi_set_latency_timer(self.latency)
        latency = c_ubyte()
        self.dev.ftdi_fn.ftdi_get_latency_timer(byref(latency))

    def _break(self, ms, debug=False):
        self.dev.ftdi_fn.ftdi_set_bitmode(1, 0x01)
        self.dev._write(b'\x00')
        time.sleep(ms)
        self.dev._write(b'\x01')
        self.dev.ftdi_fn.ftdi_set_bitmode(0, 0x00)
        self.dev.flush()

    def wakeup(self):
        self._break(.070)
        time.sleep(.130)

    def ping(self, debug=False):
        return self.send_command([0xfe], [0x72]) != None

    def probe_tables(self, tables=None):
        if not tables:
            tables = [
                0x10, 0x11, 0x17, 0x20, 0x21, 0x60, 0x61, 0x67, 0x70, 0x71,
                0xd0, 0xd1
            ]
        ret = {}
        for t in tables:
            info = self.send_command([0x72], [0x71, t])
            if info:
                if info[3] > 2:
                    ret[t] = [info[3], info[2]]
            else:
                return {}
        return ret

    def init(self, debug=False):
        self.wakeup()
        return self.ping(debug)

    def kline_new(self):
        pin_byte = c_ubyte()
        self.dev.ftdi_fn.ftdi_read_pins(byref(pin_byte))
        return (pin_byte.value == 0xff)

    def kline(self, timeout=.05):
        self.dev.flush()
        self.dev._write(b"\x00")
        to = time.time()
        while time.time() - to < timeout:
            tmp = self.dev._read(1)
            if len(tmp) == 1:
                return tmp == b"\x00"
        return False

    def kline_alt(self):
        self.dev.flush()
        self.dev._write(b"\xff")
        return self.dev._read(1) == b"\xff"

    def kline_old(self):
        b = create_string_buffer(2)
        self.dev.ftdi_fn.ftdi_poll_modem_status(b)
        return b.raw[1] & 16 == 0

    def send(self, buf, ml, timeout=.001):
        self.dev.flush()
        msg = "".join([chr(b) for b in buf]).encode("latin1")
        self.dev._write(msg)
        r = len(msg)
        timeout = .05 + timeout * r
        to = time.time()
        while r > 0:
            r -= len(self.dev._read(r))
            if time.time() - to > timeout: return None
        buf = bytearray()
        r = ml + 1
        while r > 0:
            tmp = self.dev._read(r)
            r -= len(tmp)
            buf.extend(tmp)
            if time.time() - to > timeout: return None
        r = buf[-1] - ml - 1
        while r > 0:
            tmp = self.dev._read(r)
            r -= len(tmp)
            buf.extend(tmp)
            if time.time() - to > timeout: return None
        return buf

    def send_command(self, mtype, data=[], debug=False, retries=1):
        msg, ml, dl = format_message(mtype, data)
        r = 0
        while r <= retries:
            self.dprint("%d > [%s]" % (r, ", ".join(["%02x" % m
                                                     for m in msg])))
            resp = self.send(msg, ml)
            if resp:
                if checksum8bitHonda(resp[:-1]) == resp[-1]:
                    self.dprint("%d < [%s]" %
                                (r, ", ".join(["%02x" % r for r in resp])))
                    rmtype = resp[:ml]
                    valid = False
                    if ml == 3:
                        valid = (rmtype[:2] == bytearray(
                            map(lambda x: x | 0x10, mtype[:2])))
                    elif ml == 1:
                        valid = (rmtype == bytearray(
                            map(lambda x: x & 0xf, mtype)))
                    if valid:
                        rml = resp[ml:(ml + 1)]
                        rdl = ord(rml) - 2 - len(rmtype)
                        rdata = resp[(ml + 1):-1]
                        return (rmtype, rml, rdata, rdl)
                    else:
                        print("shit")
            r += 1

    def detect_ecu_state(self, wakeup=False):
        states = [
            "unknown",  # 0
            "ok",  # 1
            "recover",  # 2
            "recover (old)",  # 3
            "init",  # 4
            "unlock",  # 5
            "erase",  # 6
            "write",  # 7
            "finalize",  # 8
            "incomplete",  # 9
            "reset",  # 10
            "error",  # 11
            "read",  # 12
            "off",  # 13
        ]
        state = 0
        if wakeup:
            self.wakeup()
        if self.ping():
            rinfo = self.send_command([0x7b], [0x00, 0x01, 0x01])
            winfo = self.send_command([0x7d], [0x01, 0x01, 0x01])
            if winfo:
                state = 1
            else:
                state = 2
        else:
            einfo = self.send_command([0x7e], [0x01, 0x01, 0x00])
            if einfo:
                if einfo[2][1] == 0x00:
                    state = 3
                elif einfo[2][1] == 0x10:
                    state = 4
                elif einfo[2][1] == 0x20:
                    state = 5
                elif einfo[2][1] == 0x30:
                    state = 6
                elif einfo[2][1] == 0x40:
                    state = 7
                elif einfo[2][1] == 0x50:
                    state = 8
                elif einfo[2][1] == 0x0d:
                    state = 9
                elif einfo[2][1] == 0x0f:
                    state = 10
                elif einfo[2][1] == 0xfa:
                    state = 11
                else:
                    print(hex(einfo[2][1]))
            else:
                dinfo = self.send_command([0x82, 0x82, 0x00],
                                          [0x00, 0x00, 0x00, 0x08])
                if dinfo:
                    state = 12
        if state == 0:
            if not wakeup:
                state, _ = self.detect_ecu_state(wakeup=True)
            elif not self.kline():
                state = 13
        return state, states[state]

    def do_init_recover(self, debug=False):
        self.send_command([0x7b], [0x00, 0x01, 0x01])
        self.send_command([0x7b], [0x00, 0x01, 0x02])
        self.send_command([0x7b], [0x00, 0x01, 0x03])
        self.send_command([0x7b], [0x00, 0x02, 0x76, 0x03, 0x17])
        self.send_command([0x7b], [0x00, 0x03, 0x75, 0x05, 0x13])

    def do_init_write(self, debug=False):
        self.send_command([0x7d], [0x01, 0x01, 0x01])
        self.send_command([0x7d], [0x01, 0x01, 0x02])
        self.send_command([0x7d], [0x01, 0x01, 0x03])
        self.send_command([0x7d], [0x01, 0x02, 0x50, 0x47, 0x4d])
        self.send_command([0x7d], [0x01, 0x03, 0x2d, 0x46, 0x49])

    def do_erase(self, debug=False):
        self.send_command([0x7e], [0x01, 0x02])
        self.send_command([0x7e], [0x01, 0x03, 0x00, 0x00])
        self.send_command([0x7e],
                          [0x01, 0x0b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff])
        self.send_command([0x7e], [0x01, 0x0e, 0x01, 0x90])
        self.send_command([0x7e], [0x01, 0x01, 0x01])
        self.send_command([0x7e], [0x01, 0x04, 0xff])

    def do_erase_wait(self, debug=False):
        cont = 1
        while cont:
            info = self.send_command([0x7e], [0x01, 0x05])
            if info:
                if info[2][1] == 0x00:
                    cont = 0
            else:
                cont = -1
        if cont == 0:
            into = self.send_command([0x7e], [0x01, 0x01, 0x00])

    def do_post_write(self, debug=False):
        self.send_command([0x7e], [0x01, 0x09])
        time.sleep(.5)
        self.send_command([0x7e], [0x01, 0x0a])
        time.sleep(.5)
        self.send_command([0x7e], [0x01, 0x0c])
        time.sleep(.5)
        info = self.send_command([0x7e], [0x01, 0x0d])
        if info: return (info[2][1] == 0x0f)

    def get_faults(self, debug=False):
        faults = {'past': [], 'current': []}
        for i in range(1, 0x0c):
            info_current = self.send_command([0x72], [0x74, i])[2]
            for j in [3, 5, 7]:
                if info_current[j] != 0:
                    faults['current'].append(
                        "%02d-%02d" % (info_current[j], info_current[j + 1]))
            if info_current[2] == 0:
                break
        for i in range(1, 0x0c):
            info_past = self.send_command([0x72], [0x73, i])[2]
            for j in [3, 5, 7]:
                if info_past[j] != 0:
                    faults['past'].append("%02d-%02d" %
                                          (info_past[j], info_past[j + 1]))
            if info_past[2] == 0:
                break
        return faults

    def do_read_flash(self, binfile):
        readsize = 12
        location = 0
        nl = False
        with open(binfile, "wb") as fbin:
            while True:
                info = self.send_command([0x82, 0x82, 0x00],
                                         format_read(location) + [readsize])
                if not info:
                    readsize -= 1
                    if readsize < 1:
                        break
                else:
                    fbin.write(info[2])
                    fbin.flush()
                    location += readsize
        with open(binfile, "rb") as fbin:
            nbyts = os.path.getsize(binfile)
            byts = bytearray(fbin.read(nbyts))
            _, status = do_validation(byts)
            return status == "good"

    def do_write_flash(self, byts, offset=0):
        print("write start")
        writesize = 128
        maxi = len(byts) / 128
        i = 0
        while i < maxi:
            w = (i * writesize)
            bytstart = [s for s in struct.pack(">H", offset + (8 * i))]
            if i + 1 == maxi:
                bytend = [s for s in struct.pack(">H", offset)]
            else:
                bytend = [s for s in struct.pack(">H", offset + (8 * (i + 1)))]
            d = list(byts[((i + 0) * 128):((i + 1) * 128)])
            x = bytstart + d + bytend
            c1 = checksum8bit(x)
            c2 = checksum8bitHonda(x)
            x = [0x01, 0x06] + x + [c1, c2]
            info = self.send_command([0x7e], x)
            if not info or ord(info[1]) != 5:
                return False
            i += 1
            if i % 2 == 0:
                self.send_command([0x7e], [0x01, 0x08])
        return True
    string = dev.read(KEY_LENGTH).strip()
    old_string = '' # Not yet used to compare string and old_string

    if string != "":
        if string in USER_DATA:
            print "Hex:", binascii.b2a_hex(string)
            dev.write('U')

            # Play ringtone/theme song
            manager = asterisk.manager.Manager()
            manager.connect('192.168.1.200')
            manager.login('steve', 'amp111')

            # manager.originate('', '')
            data = {"Action": "Originate",
                    "Channel": "SIP/180",
                    "Application": "Playback",
                    "Data": USER_DATA[string]['song']
                    }

            manager.send_action(data)
            response = manager.status()
            #print response
            manager.logoff()
            old_string = string

            time.sleep(4)
            dev.flush()
        else:
            print binascii.hexlify(string), "DENIED"
예제 #14
0
class Ecu:
    def __init__(self):
        self.ser = Device(mode='b', lazy_open=True)

    def bbang(self, bba):
        # Take the one-byte address to "bit bang" and bang the port
        self.bba = bba
        self.bbser = BitBangDevice()
        self.bbser.open()
        self.bbser.direction = 0x01
        self.bbser.port = 1
        time.sleep(.5)
        self.bbser.port = 0
        outstr = "><"
        sys.stdout.write('\r' + outstr)
        sys.stdout.flush()
        time.sleep(.2)
        bbbitmask = 1
        for i in range(8):
            if (self.bba[0] & bbbitmask) > 0:
                outbit = 1
            else:
                outbit = 0
            self.bbser.port = outbit
            outstr = ">" + str(outbit) + outstr[1:]
            sys.stdout.write('\r' + outstr)
            sys.stdout.flush()
            bbbitmask = bbbitmask * 2
            time.sleep(.2)
        self.bbser.port = 1
        sys.stdout.write("\n")
        self.bbser.close()

    def initialize(self, connect):
        self.connect = connect
        if self.connect == "SLOW-0x11":
            self.ser.close()
            time.sleep(.5)

            self.ecuconnect = False
            while self.ecuconnect == False:
                print("Attempting ECU connect: " + self.connect)

                # Bit bang the K-line
                bbseq = [0x11]
                self.bbang(bbseq)
                self.ser.open()
                self.ser.ftdi_fn.ftdi_set_line_property(8, 1, 0)
                self.ser.baudrate = 10400
                self.ser.flush()

                # Wait for ECU response to bit bang
                waithex = [0x55, 0xef, 0x8f, 1]
                self.waitfor(waithex)
                # Wait a bit
                time.sleep(.026)

                # Send 0x70
                self.send([0x70])

                # 0xee means that we're talking to the ECU
                waithex = [0xee, 1]
                response = self.waitfor(waithex)
                if response[0] == True:
                    self.ecuconnect = True
                else:
                    print("ECU Connect Failed.  Retrying.")

    def waitfor(self, wf):
        # This was used for debugging and really is only used for the init at this point.
        # wf should be a list with the timeout in the last element
        self.wf = wf
        isfound = False
        idx = 0
        foundlist = []
        capturebytes = []
        to = self.wf[-1]
        timecheck = time.time()
        while (time.time() <= (timecheck + to)) & (isfound == False):
            try:
                recvbyte = self.recvraw(1)
                if recvbyte != "":
                    recvdata = ord(recvbyte)
                    capturebytes = capturebytes + [recvdata]
                    if recvdata == self.wf[idx]:
                        foundlist = foundlist + [recvdata]
                        idx = idx + 1
                    else:
                        foundlist = []
                        idx = 0
                    if idx == len(self.wf) - 1:
                        isfound = True
            except:
                print('error')
                break
        return [isfound, foundlist, capturebytes]

    def send(self, sendlist):
        self.sendlist = sendlist
        # Puts every byte in the sendlist out the serial port
        for i in self.sendlist:
            self.ser.write(chr(i))

    def recvraw(self, bytes):
        self.bytes = bytes
        recvdata = self.ser.read(self.bytes)
        return recvdata

    def recv(self, bytes):
        self.bytes = bytes
        isread = False
        while isread == False:
            recvbyte = self.ser.read(self.bytes)
            if recvbyte != "":
                recvdata = recvbyte
                isread = True
        return recvdata

    def sendcommand(self, sendlist):
        # Wraps raw KWP command in a length byte and a checksum byte and hands it to send()
        self.sendlist = sendlist
        csum = 0
        self.sendlist = [len(self.sendlist)] + self.sendlist
        csum = self.checksum(self.sendlist)
        self.sendlist = self.sendlist + [csum]
        self.send(self.sendlist)
        cmdval = self.commandvalidate(self.sendlist)
        return cmdval

    def commandvalidate(self, command):
        # Every KWP command is echoed back.  This clears out these bytes.
        self.command = command
        cv = True
        for i in range(len(self.command)):
            recvdata = self.recv(1)
            if ord(recvdata) != self.command[i]:
                cv = cv & False
        return cv

    def checksum(self, checklist):
        # Calculates the simple checksum for the KWP command bytes.
        self.checklist = checklist
        csum = 0
        for i in self.checklist:
            csum = csum + i
        csum = (csum & 0xFF) % 0xFF
        return csum

    def getresponse(self):
        # gets a properly formated KWP response from a command and returns the data.
        debugneeds = 4
        numbytes = 0
        while numbytes == 0:  # This is a hack because sometimes responses have leading 0x00's.  Why?  This removes them.
            numbytes = ord(self.recv(1))
        gr = [numbytes]
        if debug >= debugneeds: print("Get bytes: " + hex(numbytes))
        for i in range(numbytes):
            recvdata = ord(self.recv(1))
            if debug >= debugneeds:
                print("Get byte" + str(i) + ": " + hex(recvdata))
            gr = gr + [recvdata]
        checkbyte = self.recv(1)
        if debug >= debugneeds: print(gr)
        if debug >= debugneeds:
            print("GR: " + hex(ord(checkbyte)) + "<-->" +
                  hex(self.checksum(gr)))
        return (gr + [ord(checkbyte)])

    def readecuid(self, paramdef):
        # KWP2000 command to pull the ECU ID
        self.paramdef = paramdef
        debugneeds = 4
        reqserviceid = [0x1A]
        sendlist = reqserviceid + self.paramdef
        if debug >= debugneeds: print(sendlist)
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds: print(response)
        return response

    def stopcomm(self):
        # KWP2000 command to tell the ECU that the communications is finished
        stopcommunication = [0x82]
        self.sendcommand(stopcommunication)
        response = self.getresponse()
        return response

    def startdiagsession(self, bps):
        # KWP2000 setup that sets the baud for the logging session
        self.bps = bps
        startdiagnosticsession = [0x10]
        setbaud = [0x86]  #Is this the actual function of 0x86?
        #   if self.bps == 10400:
        #      bpsout = [ 0x?? ]
        #   if self.bps == 14400:
        #      bpsout = [ 0x?? ]
        if self.bps == 19200:
            bpsout = [0x30]
        if self.bps == 38400:
            bpsout = [0x50]
        if self.bps == 56000:
            bpsout = [0x63]
        if self.bps == 57600:
            bpsout = [0x64]

    #   if self.bps == 125000:
    #      bpsout = [ 0x?? ]
        sendlist = startdiagnosticsession + setbaud + bpsout
        self.sendcommand(sendlist)
        response = self.getresponse()
        self.ser.baudrate = self.bps
        time.sleep(1)
        return response

    def accesstimingparameter(self, params):
        # KWP2000 command to access timing parameters
        self.params = params
        accesstiming_setval = [0x083, 0x03]
        accesstiming = accesstiming_setval + self.params
        sendlist = accesstiming
        self.sendcommand(sendlist)
        response = self.getresponse()
        return response

    def readmembyaddr(self, readvals):
        # Function to read an area of ECU memory.
        debugneeds = 4
        self.readvals = readvals
        rdmembyaddr = [0x23]
        sendlist = rdmembyaddr + self.readvals
        if debug >= debugneeds: print("readmembyaddr() sendlist: " + sendlist)
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds: print("readmembyaddr() response: " + response)
        return response

    def writemembyaddr(self, writevals):
        # Function to write to an area of ECU memory.
        debugneeds = 4
        self.writevals = writevals
        wrmembyaddr = [0x3D]
        sendlist = wrmembyaddr + self.writevals
        if debug >= debugneeds: print("writemembyaddr() sendlist: " + sendlist)
        self.sendcommand(sendlist)
        response = self.getresponse()
        if debug >= debugneeds: print("writemembyaddr() response: " + response)
        return response

    def testerpresent(self):
        # KWP2000 TesterPresent command
        tp = [0x3E]
        self.sendcommand(tp)
        response = self.getresponse()
        return response

    def setuplogrecord(self, logline):
        # KWP2000 command to access timing parameters
        self.logline = logline
        response = []
        sendlist = [0xb7]  # is 0xB7 the "locator?"
        sendlist = sendlist + [0x03]  # Number of bytes per field ?
        sendlist = sendlist + self.logline
        self.sendcommand(sendlist)
        response = self.getresponse()
        return response

    def getlogrecord(self):
        # Command to request a logging record
        gr = [0xb7]
        self.sendcommand(gr)
        response = self.getresponse()
        return response

    def sendhexstring(self, dumpstring):
        # Takes a list of characters as a string, turns every two characters into a hex byte and sends it raw.
        # used as needed for dev/test/debug
        self.dumpstring = dumpstring
        for i in range(len(self.dumpstring) / 2):
            self.send([int('0x' + self.dumpstring[i * 2:(i * 2) + 2], 16)])