bs_seg_analyze.py 2.19 KB
#!/usr/bin/env python3
# 解析 batterystats --history,算「20h 待机耗电段」各电源状态 ON 时长 + 睡眠估计
import re

PATH = '/data/data/com.termux/files/home/tmp/bs_hist_1012.txt'
DAY0 = '10-11'

def tsec(day, hms):
    h, m, s = hms.split(':')
    base = 0 if day == DAY0 else 86400
    return base + int(h)*3600 + int(m)*60 + float(s)

rows = []
pat = re.compile(r'^\s+(\d\d-\d\d) (\d\d:\d\d:\d\d\.\d\d\d) (.*)$')
for ln in open(PATH, errors='replace'):
    m = pat.match(ln)
    if not m:
        continue
    day, hms, rest = m.groups()
    if not (day == '10-11' or day == '10-12'):
        continue
    t = tsec(day, hms)
    rows.append((t, rest))

T0 = tsec('10-11', '19:43:52.154')
T1 = tsec('10-12', '15:59:16.425')
seg = [(t, r) for t, r in rows if T0 <= t <= T1]
total = T1 - T0
print(f'段: 10-11 19:43:52 → 10-12 15:59:16  共 {total/3600:.2f} h, 记录 {len(seg)} 行')
print(f'平均记录间隔 {total/len(seg):.2f} s')

# flag ON 时长
state = {}
acc = {}
last_t = {}
flag_tok = re.compile(r'([+-])([a-z_][a-z_0-9]*)')
for t, rest in seg:
    seen_on = set()
    seen_off = set()
    for sign, flag in flag_tok.findall(rest):
        if sign == '+':
            seen_on.add(flag)
        else:
            seen_off.add(flag)
    for flag in seen_off:
        if state.get(flag):
            acc[flag] = acc.get(flag, 0.0) + (t - last_t[flag])
            state[flag] = False
    for flag in seen_on:
        if not state.get(flag):
            last_t[flag] = t
            state[flag] = True
# 收尾
for flag, on in state.items():
    if on:
        acc[flag] = acc.get(flag, 0.0) + (T1 - last_t[flag])
rows_out = sorted(((v, k) for k, v in acc.items()), reverse=True)[:18]
print('\n== 各状态累计 ON 时长(占 20.26h 的百分比) ==')
for v, k in rows_out:
    print(f'  {k:28s} {v/3600:6.2f} h  {100*v/total:5.1f}%')

# 睡眠估计:相邻记录时间差
gaps = [(seg[i+1][0]-seg[i][0]) for i in range(len(seg)-1)]
big = sum(g for g in gaps if g >= 30)
print(f'\n== 休眠线索 ==')
print(f'  相邻记录间隔 >=30s 的累计时长: {big/3600:.2f} h ({100*big/total:.1f}%)  -> 疑似深睡/低活动')
print(f'  间隔 <5s 的记录数: {sum(1 for g in gaps if g < 5)} / {len(gaps)}')