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()
class SerialDisplay: def __init__(self, width, height): self.width = width self.height = height self.codebook = SerialDisplay.create_codebook() self.xcors = [] self.ycors = [] self.pcors = [] for y in range(height): for x in range(width): for p in range(8): self.xcors.append(x if not (y & 1) else (width - 1 - x)) self.ycors.append(y) self.pcors.append(p) self.dev = Device() self.dev.baudrate = 3010000 self.dev.ftdi_fn.ftdi_set_line_property(7, 0, 0) def display(self, image): data = np.zeros([self.width * self.height * 8], dtype=np.uint8) data[:] = 0xFF image = np.array(np.clip(image * 255, 0, 255), dtype=np.uint8) for c in range(3): data &= self.codebook[c, image[self.xcors, self.ycors, c], self.pcors] self.dev.write(bytes(data.data)) @staticmethod def format_byte(b0, b1, b2): return [(not b0) | (1 << 1) | ((not b1) << 3) | (1 << 4) | ((not b2) << 6)] @staticmethod def format_color(r, g, b): color = ((g & 0xFF) << 16) | ((r & 0xFF) << 8) | (b & 0xFF) result = [] for i in range(8): trip = (color >> (24 - 3 * (i + 1))) & 7 result += SerialDisplay.format_byte(trip & 4, trip & 2, trip & 1) return bytes(result) @staticmethod def create_codebook(): codebook = np.zeros([3, 256, 8], dtype=np.uint8) for c in range(3): for p in range(8): for v in range(256): m = [0, 0, 0] m[c] = v codebook[c, v, p] = SerialDisplay.format_color(*m)[p] return codebook
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()
def __init__(self, device_index=0): """Initialise the driver.""" try: Device.__init__(self, mode="b", device_index=device_index) except LibraryMissingError: raise Exception( "Dependency libftdi not found. Check the README for driver dependencies." ) self.baudrate = 250000 self.ftdi_fn.ftdi_set_line_property(FT232R._BITS_8, FT232R._STOP_BITS_2, FT232R._PARITY_NONE)
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 write(self, data: List[int]): """Write 512 bytes or less of DMX data.""" try: byte_data = bytes(data) except TypeError: byte_data = self.encoder.encode(data) # Break self._set_break_on() wait_ms(10) # Mark after break self._set_break_off() wait_us(8) # Frame body Device.write(self, b"\x00" + byte_data) # Idle wait_ms(15)
def __init__(self, port, baud=115200): """ Initializes SCPI slave device from a given port. Port can either be an already initialized pyserial port or may be a string, specifiying the port to be used. Special name: hamegusb, this uses the HM2008 USB interface """ if ( type(port) is str): if (port == "hamegusb"): USB_PID_LIST.append(0xED72); self.__ser = Device(mode='b') else: # configure the serial connections (the parameters differs from device # to device you are connecting to) self.__ser = serial.Serial( port=port, baudrate=baud, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS ) else: self.__ser = port # Try at least an *IDN? command, if this fails # most likely nothing will work on the device at all. self.__device_id = self.query_string("*IDN?", 1); print "Found >>"+self.__device_id
def __init__(self, int_select): self.dev = Device(mode='b', interface_select = int_select, auto_detach=False, device_id = 'Dual RS232-HS' ) self.write_port_l = 0x80 self.read_port_l = 0x81 self.write_port_h = 0x82 self.read_port_h = 0x83 self.port_l = port(self.dev,self.write_port_l, self.read_port_l) self.port_h = port(self.dev,self.write_port_h, self.read_port_h)
def __init__(self, queue): """Initialize the communication worker""" # call constructor of super class threading.Thread.__init__(self) # set queue self.queue = queue # set FTDI device for communication with iCEstick try: self.dev = Device(mode='b', interface_select=INTERFACE_B) # set baudrate self.dev.baudrate = self.BAUD_RATE except: global exit_flag print(fg.li_red + "[-] Could not connect to FTDI serial interface" + fg.rs) exit(1)
def __init__(self,deviceId=""): ''' Constructor ''' self._ID = None self._HWID = None self._Cluster = None self._firstCmd = True self._errorFlag = False self._errorMSg = "" self._stick = None if deviceId == "": log_trace('C', '0067', "No deviceID provided", traceback=traceback.print_stack()) pass #self.stick = Device(mode = "t") else: try: self._stick = Device(device_id=deviceId,mode = "t") self._stick.open() #one call of the baudrate setter does not always work self._stick.baudrate = 3000000 except: log_trace('E', '0068', "Error when opening new device", ID=deviceId, exception=', '.join(sys.exc_info()[0])) if self._stick: self._stick.close() self._stick = None #ERR408 return self._HWID = deviceId self._ID = self.GETID() if self._ID: self._ID = self._ID.split()[0] else: log_trace('E', '0069', "GETID() returned no data", HWID=deviceId) self._stick.close() self._stick = None # ERR405 return self._Cluster = self.GETCLUSTER() if self._Cluster: self._Cluster = self._Cluster.split()[0] else: log_trace('E', '0070', "GETCLUSTER() returned no data", HWID=deviceId) self._stick.close() self._stick = None #ERR406 return if (self._ID[:3]=="ERR") or (self._Cluster[:3]=="ERR"): log_trace('E', '0071', "Device initialisation returned an error (GETID or GETCLUSTER)", HWID=deviceId, ID=self._ID, cluster=self._Cluster) self._stick.close() self._stick = None
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')
def compute(threadname): """ Compute the force """ dev = Device() dev.baudrate = 230400 lastupdate = pg.ptime.time() i = 0 while True: taille = HAPTICDEV.incommingsize() #FIFO.qsize() if taille >= 3: rec = HAPTICDEV.readarray(3)#bytearray(extract(FIFO, 3)) taille = taille - 3 if rec[0] != 5: while rec[0] != 5: rec = HAPTICDEV.readarray(1)#bytearray(extract(FIFO, 1)) taille = taille - 1 rec[1:2] = HAPTICDEV.readarray(2)#bytearray(extract(FIFO, 2)) taille = taille - 2 if rec[0] == 5: i += 1 angle = rec[1] + rec[2] * 256 if angle > 32767: angle -= 65536 degre = angle*360/20000 data = SHARED['data'] data[:-1] = data[1:] data[-1] = degre SHARED['data'] = data indexf = max(min(int((ANGLEMAX+degre)*RESANG), ANGLEMAX*RESANG*2-1), 0) forcenow = FORCE[indexf] forcenow = max(min(forcenow, 130), -130) HAPTICDEV.write(forcenow) SHARED['degre'] = degre SHARED['forcenow'] = forcenow if i >= COUNT: i = 0 now = pg.ptime.time() SHARED['fps'] = COUNT / (now - lastupdate) SHARED['taille'] = taille lastupdate = now
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 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
def __init__(self, fps, velocity_scale=200, dry_run=False, verbose=False): """ fps: the frames per second that set_multi_velocity must be called to keep smooth motion. velocity_scale: convert unitless range (-1, 1) to velocity in microseconds / second """ if not dry_run: self.dev = Device(mode='t') self.dev.baudrate = 9600 self.default_speed = 600 self.positions = self._home_position() self.fps = fps self.velocity_scale = velocity_scale # position scale is the velocity in (microseconds / second) / FPS to get # microseconds per frame self.position_scale = velocity_scale / self.fps self.dry_run = dry_run self.verbose = verbose
def __init__(self, start_offset=0, end_offset=5000, offset_step=1, duration_step=1, start_duration=1, end_duration=30, retries=2): """Initialize the glitcher""" # set FTDI device for communication with iCEstick self.dev = Device(mode='b', interface_select=INTERFACE_B) # set baudrate self.dev.baudrate = 115200 # set offset and duration steps self.offset_step = offset_step self.duration_step = duration_step self.start_offset = start_offset self.end_offset = end_offset self.start_duration = start_duration self.end_duration = end_duration self.retries = retries
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 __init__(self, width, height): self.width = width self.height = height self.codebook = SerialDisplay.create_codebook() self.xcors = [] self.ycors = [] self.pcors = [] for y in range(height): for x in range(width): for p in range(8): self.xcors.append(x if not (y & 1) else (width - 1 - x)) self.ycors.append(y) self.pcors.append(p) self.dev = Device() self.dev.baudrate = 3010000 self.dev.ftdi_fn.ftdi_set_line_property(7, 0, 0)
def _connect(self): try: # Attempt to construct an FTDI Device self._dev = Device('MON001') # Reset the mode, then switch into serial FIFO self._dev.ftdi_fn.ftdi_set_bitmode(0xFF, 0x00) time.sleep(0.01) self._dev.ftdi_fn.ftdi_set_bitmode(0xFF, 0x40) # Set communication params self._dev.ftdi_fn.ftdi_set_latency_timer(5) self._dev.ftdi_fn.ftdi_setflowctrl(0) self._dev.ftdi_fn.ftdi_usb_purge_buffers() # Mark ourselves connected self.connected.emit(True) except FtdiError: pass
def __init__( self, name: str, device_id: str, sensor: common.sensor.BaseSensor, callback_func: Callable, log: logging.Logger, ) -> None: super().__init__( name=name, device_id=device_id, sensor=sensor, callback_func=callback_func, log=log, ) self.vcp: Device = Device( self.device_id, mode="t", encoding="ASCII", lazy_open=True, auto_detach=False, )
class CommunicationThread(threading.Thread): """Thread for fast serial communication""" BAUD_RATE = 2000000 # baud rate for serial communication BUFFER_SIZE = 64 # read buffer size in bytes def __init__(self, queue): """Initialize the communication worker""" # call constructor of super class threading.Thread.__init__(self) # set queue self.queue = queue # set FTDI device for communication with iCEstick try: self.dev = Device(mode='b', interface_select=INTERFACE_B) # set baudrate self.dev.baudrate = self.BAUD_RATE except: global exit_flag print(fg.li_red + "[-] Could not connect to FTDI serial interface" + fg.rs) exit(1) def run(self): """Receive data""" global exit_flag while not exit_flag: if not self.queue.full(): item = self.dev.read(self.BUFFER_SIZE) if item != b'': self.queue.put(item)
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
class Arm(object): def __init__(self, fps, velocity_scale=200, dry_run=False, verbose=False): """ fps: the frames per second that set_multi_velocity must be called to keep smooth motion. velocity_scale: convert unitless range (-1, 1) to velocity in microseconds / second """ if not dry_run: self.dev = Device(mode='t') self.dev.baudrate = 9600 self.default_speed = 600 self.positions = self._home_position() self.fps = fps self.velocity_scale = velocity_scale # position scale is the velocity in (microseconds / second) / FPS to get # microseconds per frame self.position_scale = velocity_scale / self.fps self.dry_run = dry_run self.verbose = verbose def _home_position(self): return {i: BOUNDS[i][2] for i in BOUNDS} def _bound_position(self, axis, position): if position > BOUNDS[axis][1]: return BOUNDS[axis][1] if position < BOUNDS[axis][0]: return BOUNDS[axis][0] return position def set_position(self, axis, position, speed=None, time=None): """ pos: position pulse width in microseconds speed: microseconds per second time: time in milliseconds to execute motion to `pos` """ self.positions[axis] = self._bound_position(axis, position) if speed is None and time is None: speed = self.default_speed if self.verbose: print('axis=', axis) print('position=', position) print('speed=', speed) print('time=', time) if self.dry_run: return if speed: self.dev.write( '#{axis}P{position}S{speed}\r'.format( axis=axis, position=position, speed=speed ) ) else: self.dev.write( '#{axis}P{position}T{time}\r'.format( axis=axis, position=position, time=time ) ) def set_positions(self, positions, speeds=None, scaled=False): if scaled: positions = { axis: self._scaled_to_absoltuion_position(axis, position) for axis, position in positions.items() } for axis in positions: positions[axis] = self._bound_position(axis, positions[axis]) self.positions[axis] = positions[axis] if speeds is None: speeds = {axis: self.default_speed for axis in positions} if self.verbose: print('positions', positions) print('speeds ', speeds) if self.dry_run: return self.dev.write( ''.join( '#{axis}P{pos}S{speed}'.format( axis=axis, pos=positions[axis], speed=speeds[axis], ) for axis in positions ) + '\r' ) def _scaled_position(self, axis, position): return (position - BOUNDS[axis][0]) / ( BOUNDS[axis][1] - BOUNDS[axis][0] ) def scaled_positions(self): return [ self._scaled_position(axis, position) for axis, position in self.positions.items() ] def _scaled_to_absoltuion_position(self, axis, position): if position < 0 or position > 1: raise ValueError(( 'position expected to be within 0 and 1. found: {}' ).format(position)) return BOUNDS[axis][0] + position * (BOUNDS[axis][1] - BOUNDS[axis][0]) def set_scaled_position(self, axis, position, speed=None): self.set_position( axis, self._scaled_to_absoltuion_position(axis, position), speed=speed ) def set_relative_position(self, axis, position_delta, speed=None): self.positions[axis] += position_delta self.set_position(axis, self.positions[axis], speed=speed) def set_velocities(self, velocities): """ Set velocity of all servos in arm. set_multi_velocity must be called once every self.fps """ if set(velocities.keys()) != set(self.positions.keys()): raise ValueError(( 'velocities.keys must match self.positions.keys:\n' ' velocities.keys(): {}\n' ' self.position.keys(): {}\n' ).format(velocities.keys(), self.positions.keys())) if not any(v != 0 for v in velocities.values()): return self.set_positions( { axis: self.positions[axis] + (velocity * self.position_scale) for axis, velocity in velocities.items() }, { axis: max(abs(velocity * self.velocity_scale), 100) for axis, velocity in velocities.items() }, ) def set_velocity(self, axis, velocity): velocity *= 10 self.set_position( axis, self.positions[axis] + velocity * self.position_scale, speed=max(abs(velocity) * self.velocity_scale, 5) ) def go_home(self): self.set_positions(self._home_position()) def go_random(self): for axis in BOUNDS: self.set_position( axis, random.randrange(BOUNDS[axis][0], BOUNDS[axis][1], 1) )
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)
import paho.mqtt.client as mqtt import json from pylibftdi import Device, USB_PID_LIST, USB_VID_LIST from config import MQTT_HOST USB_VID_LIST.append(0x1321) USB_PID_LIST.append(0x1001) dev = Device(mode='t') dev.baudrate = 57600 dev.open() def run_command(cmd): if cmd != '': dev.flush() print('TX: ' + cmd) dev.writelines(cmd + '\r') out = '' while out == '': out = dev.readline() print('RX: ' + out) def to_command(obj): cmds = [] for input in obj: cmd = 'xpgn(' + input + ',*)=' # print('Input: ' + input) # print(obj[input])
def __init__(self): self.ser = Device(mode='b', lazy_open=True)
def __init__(self): self.device = Device(device_id="64drive USB device")
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)
#! /usr/bin/python import sys, os #import pylibftdi from pylibftdi import Driver, Device try: dev_list = Driver().list_devices() if len(dev_list) != 0: print "\n\nFollowing devices found: \n" for device_ in dev_list: print device_ dev = Device(device_id="FTZ17IRO", mode='b', interface_select=2) dev.open() tx_data = bytearray(range(0, 256)) dev.write(tx_data) rx_data = bytearray(dev.read(257))#, timeout = 0)) if len(rx_data) == 256 : print "\n\n[Test] Test 1 Passed: Sent 256 bytes of data, received 256 bytes of data" failed = False for i in range(256): if ((tx_data[i]+1)%256) != rx_data[i]: print "[Test] Test 2: Data verification failed! , tx_data : ", tx_data[i], " =/= rx_data : ", rx_data[i] failed = True
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()
#!/usr/bin/env python import pygame from math import floor from pylibftdi import Device # I2C over USB import time # import servo dev = Device(mode="b") dev.baudrate = 9600 # allow multiple joysticks joy = [] def fix(bits): if bits & 0b00100000: return 63 - bits else: return bits # handle joystick event def handleJoyEvent(e): if e.type == pygame.JOYAXISMOTION: axis = "unknown" if e.dict["axis"] == 0: axis = "X" bits = 0b10000000 # Throw away; don't change anything if e.dict["axis"] == 1: axis = "Y"
from pylibftdi import Device with Device(mode='t') as dev: dev.baudrate = 115200 dev.write('Hello World')
class Dongle(object): ''' For full description visit: http://docs.s-crib.com/doku.php/scramble_scrib_-_api_specification Management commands GETINITKEY host computer can request initialisation key, it will be typed after a button is pressed; GETPASSWD requests one of the device's passwords. Status commands GETID host computer requests the device's ID ENGETID request the device's ID, the response is encrypted GETCOUNTER returns the number of SCRAMBLE requests served Execution commands SCRAMBLE protect a password; ENSCRAMBLE protect a password that is sent encrypted General Rules and Security Policy 1. Passwords contain characters in ASCII encoding. 2. Management commands can only be executed before the first execution command is served. 3. The maximum length of commands is 160 characters, including <new line>. 4. All letters must be sent as capitals (with the exception of passwords), the device replies with capital letters only as well. 5. Commands must start immediately after newline, command and parameters must be separated with exactly one space. 6. The device does only necessary checks of commands and parameters to protect itself against malformed commands. 7. The device uses 3 passwords, each is 32 characters long: a, Password 2 for scrambling; b, Password 3 computes -time- to EXOR with salt before scrambling; and c, Password 4 encryption of parameters for commands with prefix EN. ''' _BLOCK_SIZE = 16 _READ_TIMEOUT = 2 # in seconds space = 1 operationCounterLen = 8 + space # length of the postfix - appended to all non encrypted command responses scrambleLength = 64 ''' GETID command returns the device's ID. This is required to recover passwords from the initialisation key - online service is available here: https://my.s-crib.com/ ''' getIdText = "GETID\n" getIdTextLen = 16 +operationCounterLen ''' GETCLUSTER allows the host computer to request the device's cluster ID - identifies its set of passwords. ''' getClusterText = "GETCLUSTER\n" getClusterTextLen = 10 +operationCounterLen ''' GETLOCKED command returns whether the device is locked - protects keys/passwords. ''' getLockedText = "GETLOCKED\n" getLockedTextLen = 1 +operationCounterLen ''' GETINITKEY allows the host computer to request the device's initialisation key. This can be printed out and used for pas < missing text on web site ;0) ''' getInitKeyText = "GETINITKEY\n" getInitKeyTextLen = 48 +operationCounterLen ''' GETPASSWD allows the host computer to request the device's passwords (2/3/4) for backup. ''' getPasswordText = "GETPASSWD %d\n" getPasswordTextLen = 32 +operationCounterLen ''' GETCOUNTER command returns the order number of the last command. This counter is incremented with each command sent to the device. It is kept in volatile memory and reset to nought each time the device loses power supply. ''' getCounterText = "GETCOUNTER\n" getCounterTextLen = 16 ''' GETDELAY allows the host computer to set the current delay set on the device. This delay may increase protection against brute-force attacks. The delay is between 0 and 99. You need to experiment to get the delay length in milliseconds. ''' getDelayText = "GETDELAY\n" getDelayTextLen = 2 +operationCounterLen ''' ENGETID is the encrypted variant of the GETID command. This can be used when the device is on another physical server and some kind of encryption is required. ''' enGetIdText = "ENGETID %s\n" enGetIdTextLen = 64 +operationCounterLen ''' ENSCRAMBLE is the encrypted variant of the SCRAMBLE command. All parameters of SCRAMBLE are prefixed with a hexadecimal counter of 16 digits and padded with spaces to create 96 characters' string that is encrypted. Encryption used to protect parameters is AES256-CBC and it uses Password 4 ''' enScrambleText = "ENSCRAMBLE %s\n" enScrambleTextLen = 128 +operationCounterLen ''' This is the actual operation command. Password must not contain space or new line. The salt_length is between 0 and 32 and denotes the length of the returned string. The string is of hexadecimal digits and each digit gives 4 bits of entropy. The salt is an optional parameter with the minimum length of <salt_length>. If the <salt> is missing and <salt_length> is non-zero, the device will generate a new random <salt>. ''' scrambleText = "SCRAMBLE %s %02d %s\n" scrambleTextLen =operationCounterLen # Length will need to adjusted at time of call def __init__(self,deviceId=""): ''' Constructor ''' self._ID = None self._HWID = None self._Cluster = None self._firstCmd = True self._errorFlag = False self._errorMSg = "" self._stick = None if deviceId == "": log_trace('C', '0067', "No deviceID provided", traceback=traceback.print_stack()) pass #self.stick = Device(mode = "t") else: try: self._stick = Device(device_id=deviceId,mode = "t") self._stick.open() #one call of the baudrate setter does not always work self._stick.baudrate = 3000000 except: log_trace('E', '0068', "Error when opening new device", ID=deviceId, exception=', '.join(sys.exc_info()[0])) if self._stick: self._stick.close() self._stick = None #ERR408 return self._HWID = deviceId self._ID = self.GETID() if self._ID: self._ID = self._ID.split()[0] else: log_trace('E', '0069', "GETID() returned no data", HWID=deviceId) self._stick.close() self._stick = None # ERR405 return self._Cluster = self.GETCLUSTER() if self._Cluster: self._Cluster = self._Cluster.split()[0] else: log_trace('E', '0070', "GETCLUSTER() returned no data", HWID=deviceId) self._stick.close() self._stick = None #ERR406 return if (self._ID[:3]=="ERR") or (self._Cluster[:3]=="ERR"): log_trace('E', '0071', "Device initialisation returned an error (GETID or GETCLUSTER)", HWID=deviceId, ID=self._ID, cluster=self._Cluster) self._stick.close() self._stick = None def exists(self): log_trace('D', '0072', "exists() called", ID=self._ID) if self._stick: return True else: return False ''' Returns a list of tuples: - first item: a colon-separated vendor:product:serial summary of detected devices - second item: serial number - HWID ''' @staticmethod def listDevices(): log_trace('D', '0073', "listDevices() called", detail="n/a") dev_list = [] dev_dict = {} devices = None try: #FTDI returns a list of triplets - (vendor, name, HWID) devices = Driver().list_devices() except AttributeError, e: # ERR_ENUMERATE ERR403 log_trace('E', '0074', "Error when enumerating devices - Attribute Error", exception=e) if not devices: return None except :
from pylibftdi import Device, USB_PID_LIST, USB_VID_LIST USB_VID_LIST.append(0x1321) USB_PID_LIST.append(0x1001) dev = Device(mode='t') dev.baudrate = 57600 dev.open() cmd = 'serial?' while cmd != 'quit': if cmd != '': dev.flush_input() dev.writelines(cmd + '\r') out = '' while out == '': out = dev.readline() print(out) cmd = input('Type command: ')
def reset(self): if self.dev != None: del self.dev self.dev = None self.dev = Device(self.device_id)
class Py64drive: def __init__(self): self.device = Device(device_id="64drive USB device") def _send_cmd(self, cmd, params): txbuf = struct.pack(">B3s",cmd,b"CMD") if len(params) >= 1: txbuf += struct.pack(">L",params[0]) if len(params) >= 2: txbuf += struct.pack(">L",params[1]) self.device.write(txbuf) def _recv_resp(self): rxbuf = self.device.read(4) return struct.unpack(">L", rxbuf) def _recv_ver_resp(self): rxbuf = self.device.read(8) return struct.unpack(">L4s", rxbuf) def _recv_success(self,command): while True: rxbuf = self.device.read(4) if rxbuf: break if rxbuf != b"CMP" + bytes([command]): #print("Got {}, expected CMP{}",rxbuf,command,file=sys.stderr) return False return True def load_image(self, data, bank, ram_addr=0): length = len(data) if length % 512: #print("File was truncated during loading.", file=sys.stderr) length -= length % 512 for offset in range(0, length, CHUNK_SIZE): size = min(CHUNK_SIZE, length - offset) block = data[offset:offset+size] self._send_cmd(0x20, (ram_addr + offset, (bank << 24) | (size & 0xffffff))) self.device.write(block) self._recv_success(0x20) def dump_image(self, length, bank, ram_addr=0): data = b"" if length % 512: #print("File was truncated during dumping.", file=sys.stderr) length -= length % 512 for offset in range(0, length, CHUNK_SIZE): size = min(CHUNK_SIZE, length - offset) self._send_cmd(0x30, (ram_addr + offset, (bank << 24) | (size & 0xffffff))) data += self.device.read(size) self._recv_success(0x30) return data def set_save(self, save_type): self._send_cmd(0x70, (save_type,)) self._recv_success(0x70) def read_version(self): self._send_cmd(0x80,()) val,magic = self._recv_ver_resp() if val == 0 or magic != b"UDEV": #print("Incorrect 64drive version reported.", file=sys.stderr) return False self._recv_success(0x80) return True def pi_write_block(self,*args): raise NotImplementedError("Not implemented yet") def pi_write_block_long(self,*args): raise NotImplementedError("Not implemented yet") def pi_read_int32(self): raise NotImplementedError("Not implemented yet") def pi_write_int32(self,num): raise NotImplementedError("Not implemented yet")
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) ])
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)])
if (len(bytes) > 0): break time.sleep(0.1) print("Received", bytes) while (len(bytes) > 0): print(len(bytes)) msg, bytes = get_msg(bytes) if (msg): print(msg) translate(msg) if INPUT: input() with Device() as dev: dev.ftdi_fn.ftdi_set_bitmode(0xFF, 0x00) time.sleep(0.01) dev.ftdi_fn.ftdi_set_bitmode(0xFF, 0x40) dev.ftdi_fn.ftdi_set_latency_timer(5) dev.ftdi_fn.ftdi_setflowctrl(0) dev.ftdi_fn.ftdi_usb_purge_buffers() i1 = 0 if RANDOM: while True: i2 = random.randint(0, 255) i3 = random.randint(0, 255) print(i1, i2, i3)
def midi_ftdi_dev(): from pylibftdi import Device d = Device() d.baudrate = 31250 return d
def __init__(self): self.device = Device()
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
# Steve Phillips / elimisteve # 2011.05.11 from pylibftdi import Device import asterisk.manager, binascii, time #'\x01\xe7\x6e' USER_DATA = { '\x01\xe7l\x02': {'nick': 'swiss', 'song': 'custom/youngbuk2'}, '\x01\xe7_Y': {'nick': 'Joule_Thief', 'song': 'custom/smokeonwater'}, '\x01\xe7ma': {'nick': 'elimisteve', 'song': 'custom/loop'}, '\x01\xe7f\x8d': {'nick': 'luckyaba', 'song': 'custom/goodfoot'} } KEY_LENGTH = 6 dev = Device(mode='b') dev.baudrate = 9600 while 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')
def __init__(self, *o, **k): Device.__init__(self, *o, **k) self.baudrate = 31250
#! /usr/bin/python import sys, os import time import random from pylibftdi import Driver, Device dev_list = Driver().list_devices() if len(dev_list) != 0: print "Following devices found:" for device_ in dev_list: print device_ dev = Device(device_id="FTZ17IRO", mode='b', interface_select=2) dev.open() epochs = 1024 * 10 BLOCK_LEN = 2048 tx_data = bytearray([random.randrange(0, 256) for i in range(BLOCK_LEN)]) ts = time.time() while epochs: dev.write(tx_data) rx_data = bytearray(dev.read(BLOCK_LEN)) #print "Epoch: {}".format(epochs) failed = False for i in range(BLOCK_LEN): if ((tx_data[i] + 1) % 256) != rx_data[i]: print "Epoch: {}".format(epochs)
""" Script to test serial devices """ from pylibftdi import Device, Driver, INTERFACE_B #print Driver().list_devices() with Device(mode='t', interface_select=INTERFACE_B) as dev: dev.baudrate = 115200 # Send a read command to the board dev.write('R 0 4\r\n') result = "" while 1: # This is a non-blocking read (!!!) result += dev.read(1) print(repr(result))