This repository was archived by the owner on Jun 2, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtransactions.py
More file actions
134 lines (134 loc) · 6.45 KB
/
transactions.py
File metadata and controls
134 lines (134 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import serial
import time
import csv
from datetime import datetime
# Configure the serial port (adjust 'COM14' to your Arduino's port)
ser = serial.Serial('COM10', 9600, timeout=1)
time.sleep(2) # Wait for serial to initialize
def print_boxed_message(message, border_char="=", width=50):
"""Helper function to print a message in a boxed format."""
border = border_char * width
padding = " " * ((width - len(message) - 2) // 2)
print(border)
print(f"|{padding}{message}{padding}{' ' if len(message) % 2 else ''}|")
print(border)
def get_timestamp():
"""Return the current timestamp in a formatted string."""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def read_last_unpaid_entry(plate):
"""Read the last unpaid entry (Payment Status = 0) for a given plate from plates_log.csv."""
try:
with open('plates_log.csv', 'r') as file:
reader = csv.DictReader(file)
entries = [row for row in reader if row['Plate Number'] == plate and row['Payment Status'] == '0']
if not entries:
return None
return entries[-1] # Return the last unpaid entry
except FileNotFoundError:
print_boxed_message("Error: File Not Found", "!")
print(f"[{get_timestamp()}] plates_log.csv not found. Creating a new one.\n")
with open('plates_log.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['Plate Number', 'Payment Status', 'Timestamp', 'Payment Timestamp'])
return None
except Exception as e:
print_boxed_message("Error: CSV Read Failed", "!")
print(f"[{get_timestamp()}] {e}\n")
return None
def update_payment_status(plate, entry_timestamp):
"""Update the Payment Status to 1 and log the payment timestamp."""
try:
rows = []
payment_time = get_timestamp() # Exact time of payment
with open('plates_log.csv', 'r') as file:
reader = csv.DictReader(file)
for row in reader:
if row['Plate Number'] == plate and row['Timestamp'] == entry_timestamp and row['Payment Status'] == '0':
row['Payment Status'] = '1'
row['Payment Timestamp'] = payment_time
rows.append(row)
with open('plates_log.csv', 'w', newline='') as file:
writer = csv.DictWriter(file, fieldnames=['Plate Number', 'Payment Status', 'Timestamp', 'Payment Timestamp'])
writer.writeheader()
writer.writerows(rows)
return payment_time
except Exception as e:
print_boxed_message("Error: CSV Update Failed", "!")
print(f"[{get_timestamp()}] {e}\n")
return None
try:
print_boxed_message("Python Parking System Ready", "=")
print(f"[{get_timestamp()}] Waiting for Arduino data...\n")
while True:
if ser.in_waiting > 0:
line = ser.readline().decode('utf-8').strip()
if line.startswith("DATA:"):
print(line)
# Parse the data
plate, cash = line[5:].split(',')
cash = int(cash)
# Display received data
print_boxed_message("Data Received from Arduino", "-")
print(f"[{get_timestamp()}] Details:")
print(f" License Plate: {plate}")
print(f" Current Balance: {cash} units\n")
# Check if cash is more than 200
if cash <= 200:
print_boxed_message("Error: Insufficient Balance", "!")
print(f"[{get_timestamp()}] Balance ({cash} units) must be > 200 units.\n")
continue
# Read the last unpaid entry for the plate
last_entry = read_last_unpaid_entry(plate)
if last_entry is None:
print_boxed_message("Warning: No Unpaid Entry Found", "!")
print(f"[{get_timestamp()}] No unpaid entry for plate {plate}. Assuming 0 hours.\n")
hours = 0
else:
entry_time = datetime.strptime(last_entry['Timestamp'], "%Y-%m-%d %H:%M:%S")
current_time = datetime.now()
time_diff = current_time - entry_time
hours = time_diff.total_seconds() / 3600 # Convert to hours
# Calculate charge (100 units per 30 min after first 30 min)
minutes = hours * 60
charge = 0
if minutes > 30:
charge = ((minutes - 30 + 29) // 30) * 100
if charge > cash:
print_boxed_message("Error: Charge Exceeds Balance", "!")
print(f"[{get_timestamp()}] Charge ({charge} units) exceeds balance ({cash} units).\n")
continue
# Send charge to Arduino
ser.write(f"CHARGE:{charge}\n".encode())
print_boxed_message("Data Sent to Arduino", "-")
print(f"[{get_timestamp()}] Transaction Details:")
print(f" License Plate: {plate}")
print(f" Parking Duration: {hours:.2f} hours")
print(f" Charge Amount: {charge} units\n")
# Wait for DONE signal
response = ser.readline().decode('utf-8').strip()
if response == "DONE":
if last_entry:
payment_time = update_payment_status(plate, last_entry['Timestamp'])
if payment_time:
print_boxed_message("Payment Processed", "-")
print(f"[{get_timestamp()}] Payment Details:")
print(f" Payment Timestamp: {payment_time}")
print(f" Updated Balance: {cash - charge} units\n")
print_boxed_message("Transaction Successful", "=")
print(f"[{get_timestamp()}] Gate is opening...\n")
else:
print_boxed_message("Error: Arduino Response", "!")
print(f"[{get_timestamp()}] Unexpected response: {response}\n")
time.sleep(0.1) # Small delay to prevent overwhelming the loop
except KeyboardInterrupt:
print("\n" + "=" * 50)
print(f"[{get_timestamp()}] Program terminated by user.")
print("=" * 50)
ser.close()
except Exception as e:
print("\n" + "=" * 50)
print(f"[{get_timestamp()}] An error occurred: {e}")
print("=" * 50)
ser.close()
finally:
ser.close()