File size: 3,907 Bytes
54daa8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
066c4f5
30b319d
 
 
 
54daa8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dde6407
b979284
 
 
54daa8d
b979284
54daa8d
 
 
 
 
 
 
 
 
 
30b319d
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
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("""
    <img src="https://custom-images.strikinglycdn.com/res/hrscywv4p/image/upload/c_limit,fl_lossy,h_300,w_300,f_auto,q_auto/4493206/132971_72411.png" width="100" />
    
    # 加速度資料轉換與視覺化
    上傳原始檔案(如 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()