import gradio as gr import matplotlib.pyplot as plt import pandas as pd import io import tempfile import os # 直接複製 main.py 的處理邏輯 def parse_accel_hex(tokens): if len(tokens) < 6: return None, None, None acc_x = int(tokens[0], 16) << 8 | int(tokens[1], 16) acc_y = int(tokens[2], 16) << 8 | int(tokens[3], 16) acc_z = int(tokens[4], 16) << 8 | int(tokens[5], 16) def to_int16(val): return val - 0x10000 if val & 0x8000 else val return to_int16(acc_x), to_int16(acc_y), to_int16(acc_z) def process_file(file_obj, acc_sensitivity): # 支援 gradio 3.x/4.x: file_obj 可能是檔案物件或路徑字串或 NamedString if hasattr(file_obj, 'read'): # 檔案物件 file_obj.seek(0) lines = file_obj.read().decode('utf-8').splitlines() else: # 路徑字串或 NamedString with open(str(file_obj), 'r', encoding='utf-8') as f: lines = f.read().splitlines() output = io.StringIO() output.write('Timestamp,AccelX,AccelY,AccelZ\n') data = [] for line in lines: if 'INFO' not in line: continue parts = line.split() if not parts: continue timestamp = parts[0] idx = line.find('value (0x):') if idx == -1: continue hex_str = line[idx + len('value (0x):'):].strip() tokens = [tok for tok in hex_str.split('-') if tok] acc_x, acc_y, acc_z = parse_accel_hex(tokens) if acc_x is None: continue f_acc_x = acc_x / acc_sensitivity f_acc_y = acc_y / acc_sensitivity f_acc_z = acc_z / acc_sensitivity output.write(f"{timestamp},{f_acc_x:.4f},{f_acc_y:.4f},{f_acc_z:.4f}\n") data.append((timestamp, f_acc_x, f_acc_y, f_acc_z)) # 刪除第一筆資料 if data: data.pop(0) output.seek(0) return output, data def gradio_interface(file, acc_sensitivity): if file is None: return None, None, None csv_io, data = process_file(file, acc_sensitivity) # 下載用:寫入臨時檔案,回傳路徑 with tempfile.NamedTemporaryFile(delete=False, suffix='.csv', mode='w', encoding='utf-8') as tmp: tmp.write(csv_io.getvalue()) tmp_path = tmp.name # 視覺化 if not data: return tmp_path, None, "No valid data." df = pd.DataFrame(data, columns=['Timestamp', 'AccelX', 'AccelY', 'AccelZ']) # 將 Timestamp 轉為 datetime df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce') fig, ax = plt.subplots(figsize=(10,6)) ax.plot(df['Timestamp'], df['AccelX'], label='Ax') ax.plot(df['Timestamp'], df['AccelY'], label='Ay') ax.plot(df['Timestamp'], df['AccelZ'], label='Az') ax.set_xlabel('Time') ax.set_ylabel('Acceleration (g)') ax.set_title('Accelerometer Data') ax.legend() fig.autofmt_xdate() plt.tight_layout() return tmp_path, fig, None demo = gr.Blocks() with demo: gr.Markdown(""" # 加速度資料轉換與視覺化 上傳原始檔案(如 data.txt),調整 ACC_SENSITIVITY,下載轉換後的 csv,並預覽加速度圖表。 """) with gr.Row(): file_input = gr.File(label="上傳原始檔案(txt)") acc_input = gr.Number(value=4096.0, label="ACC_SENSITIVITY (例如 4096.0)") with gr.Row(): csv_output = gr.File(label="下載轉換後的 CSV") plot_output = gr.Plot(label="加速度圖表") msg_output = gr.Textbox(label="訊息", interactive=False) btn = gr.Button("執行轉換與繪圖") btn.click(fn=gradio_interface, inputs=[file_input, acc_input], outputs=[csv_output, plot_output, msg_output]) demo.launch()