Skip to content

Commit d1290ff

Browse files
data_download
1 parent 61e3269 commit d1290ff

1 file changed

Lines changed: 199 additions & 0 deletions

File tree

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import serial
2+
import serial.tools.list_ports
3+
import time
4+
import os
5+
import pandas as pd
6+
7+
# Configuration
8+
BAUD_RATE = 115200
9+
OUTPUT_DIR = os.path.expanduser("~/sd_card_downloads")
10+
PARSED_FOLDER = os.path.join(OUTPUT_DIR, "parsed_files")
11+
SKIP_FILES = {"_ACTIV~1.CSV"}
12+
13+
def should_skip(filename):
14+
normalized = filename.strip().lstrip("/").upper()
15+
return normalized in SKIP_FILES
16+
17+
def find_serial_port():
18+
ports = serial.tools.list_ports.comports()
19+
if not ports:
20+
raise Exception("No serial devices found!")
21+
print("Available serial ports:")
22+
for i, port in enumerate(ports, 1):
23+
print(f"{i}. {port.device} - {port.description}")
24+
selection = input("Enter the number of the port to use: ")
25+
index = int(selection) - 1
26+
if 0 <= index < len(ports):
27+
return ports[index].device
28+
raise Exception("Invalid selection!")
29+
30+
def get_file_list(ser):
31+
print("Sending LIST command...")
32+
ser.write(b"LIST\n")
33+
files = []
34+
start_time = time.time()
35+
while True:
36+
if time.time() - start_time > 10:
37+
print("ERROR: Timeout waiting for LIST_START")
38+
return []
39+
line = ser.readline().decode(errors="ignore").strip()
40+
if line == "LIST_START":
41+
break
42+
while True:
43+
line = ser.readline().decode(errors="ignore").strip()
44+
if line == "LIST_END":
45+
break
46+
if line:
47+
files.append(line)
48+
return files
49+
50+
def download_file(ser, file_name):
51+
ser.write(f"READ:{file_name}\n".encode())
52+
file_content = b""
53+
start_time = time.time()
54+
while True:
55+
if time.time() - start_time > 10:
56+
raise Exception(f"Timeout waiting for FILE_START of {file_name}")
57+
line = ser.readline().decode(errors="ignore").strip()
58+
if line.startswith("FILE_START:"):
59+
print(f"Downloading {file_name}...")
60+
break
61+
start_time = time.time()
62+
while True:
63+
if time.time() - start_time > 30:
64+
raise Exception(f"Timeout while reading content of {file_name}")
65+
line = ser.readline()
66+
if line.startswith(b"FILE_END:"):
67+
break
68+
file_content += line
69+
output_path = os.path.join(OUTPUT_DIR, os.path.basename(file_name))
70+
with open(output_path, "wb") as f:
71+
f.write(file_content)
72+
print(f"Saved: {output_path} ({len(file_content)} bytes)")
73+
74+
def parse_csv_file(filepath, parsed_output_folder):
75+
expected_column_count = 22
76+
new_column_names = [f'col{i+1}' for i in range(expected_column_count)]
77+
78+
try:
79+
rows = []
80+
with open(filepath, 'r') as f:
81+
for line in f:
82+
parts = line.strip().split(',')
83+
if len(parts) == expected_column_count:
84+
rows.append(parts)
85+
86+
if not rows:
87+
print(f"No valid rows in {os.path.basename(filepath)}.")
88+
return
89+
90+
df = pd.DataFrame(rows, columns=new_column_names)
91+
92+
# Drop unwanted columns
93+
#columns_to_delete = [0, 1, 9, 10, 11, 12, 13, 14, 22, 23]
94+
columns_to_delete = [0, 1, 9, 10, 11, 12, 13, 14]
95+
df.drop(df.columns[columns_to_delete], axis=1, inplace=True)
96+
97+
# Rename columns
98+
df.columns = [
99+
'timestamp', 'latitude', 'longitude', 'PM1_0', 'PM2_5', 'PM4',
100+
'PM10', 'temperature', 'humidity', 'gas_op1_w', 'gas_op1_r',
101+
'gas_op2_w', 'gas_op2_r', 'noise'
102+
]
103+
104+
os.makedirs(parsed_output_folder, exist_ok=True)
105+
name, ext = os.path.splitext(os.path.basename(filepath))
106+
output_path = os.path.join(parsed_output_folder, f"{name}_parsed.csv")
107+
df.to_csv(output_path, index=False)
108+
print(f"Parsed and saved: {output_path}")
109+
110+
except Exception as e:
111+
print(f"Error parsing {filepath}: {e}")
112+
113+
def parse_downloaded_files():
114+
downloaded_files = sorted([
115+
f for f in os.listdir(OUTPUT_DIR)
116+
if f.lower().endswith(".csv") and not f.startswith(".")
117+
])
118+
119+
if not downloaded_files:
120+
print("No CSV files found to parse.")
121+
return
122+
123+
print("\nDownloaded files:")
124+
for i, f in enumerate(downloaded_files, 1):
125+
print(f"{i}. {f}")
126+
127+
selections = input("\nEnter file numbers to parse (comma-separated, or 'all'): ").strip().lower()
128+
129+
if selections == 'all':
130+
selected_files = downloaded_files
131+
else:
132+
selected_files = []
133+
for num in selections.split(','):
134+
try:
135+
index = int(num.strip()) - 1
136+
if 0 <= index < len(downloaded_files):
137+
selected_files.append(downloaded_files[index])
138+
except ValueError:
139+
continue
140+
141+
for file in selected_files:
142+
input_path = os.path.join(OUTPUT_DIR, file)
143+
parse_csv_file(input_path, PARSED_FOLDER)
144+
145+
def main():
146+
os.makedirs(OUTPUT_DIR, exist_ok=True)
147+
try:
148+
port = find_serial_port()
149+
print(f"Using device at {port}")
150+
ser = serial.Serial(port, BAUD_RATE, timeout=2)
151+
time.sleep(2)
152+
files = get_file_list(ser)
153+
154+
if not files:
155+
print("No files found on SD card!")
156+
return
157+
158+
print("\nAvailable files:")
159+
for i, file in enumerate(files, 1):
160+
print(f"{i}. {file}")
161+
162+
selections = input("\nEnter file numbers to download (comma-separated, or 'all'): ")
163+
164+
if selections.lower() == 'all':
165+
selected_files = [f for f in files if not should_skip(f)]
166+
else:
167+
selected_files = []
168+
for num in selections.split(','):
169+
try:
170+
index = int(num.strip()) - 1
171+
if 0 <= index < len(files):
172+
file_to_add = files[index]
173+
if not should_skip(file_to_add):
174+
selected_files.append(file_to_add)
175+
except ValueError:
176+
pass
177+
178+
if not selected_files:
179+
print("No valid files selected.")
180+
return
181+
182+
for file in selected_files:
183+
try:
184+
print(f"\n>>> Downloading {file}")
185+
download_file(ser, file)
186+
except Exception as e:
187+
print(f"Failed to download {file}: {str(e)}")
188+
189+
except Exception as e:
190+
print(f"Error: {str(e)}")
191+
finally:
192+
if 'ser' in locals():
193+
ser.close()
194+
195+
# Parse after download
196+
parse_downloaded_files()
197+
198+
if __name__ == "__main__":
199+
main()

0 commit comments

Comments
 (0)