day-summ – kamera, puls va lokal LLM bilan belgilangan kun
Noutbuk kamerasi daqiqalarni fokus, telefon va charchoqqa ajratadi, Whoop bilaguzugi BLE orqali pulsni uzatadi, lokal model esa kechki xulosani yozadi. To'liq oflayn: kadrlar saqlanmaydi, bazada faqat daqiqalik raqamlar.
Whoop puls, uyqu va recovery'ni ko'rsatadi, lekin o'sha daqiqalarda nima qilganim haqida jim. Ekran vaqti trekerlari esa aksincha: ilovani biladi, ammo umuman ekranga qaraganimni bilmaydi. Fiziologiya va xatti-harakat bitta vaqt o'qida yotadigan yagona kun manzarasini xohladim – va buning uchun hech narsani bulutga bermaslikni.
Eng foydali signal kameradan emas, uning yo'qligidan chiqdi. Kadrda yuz yo'q, lekin BLE orqali puls kelib turibdi – demak men yaqindaman, bu qisqa tanaffus. Puls ham yo'qolgan bo'lsa – xonadan chiqib ketganman. Bitta `hr_avg is not None` tekshiruvi butun bir evristikalar sinfini almashtirdi. Yana: MediaPipe blendshape'larni (ko'z pirillashi, esnash, pastga qarash) tayyor raqam sifatida beradi, shuning uchun PERCLOS va pirillash chastotasi bir necha qatorda, model o'qitmasdan hisoblanadi.
Batareya uchun kamera bo'laklab suratga oladi: har 5 daqiqada ~10 soniya. Yigirma daqiqalik yo'qlik esa taymlaynda to'rtta bir daqiqalik dog'ga aylanardi – chunki faqat kadr bo'lgan daqiqalar belgilanardi. Yechim sample-and-hold bo'ldi: har bo'lak o'z kategoriyasini keyingisiga qadar ushlab turadi, lekin cheklov bilan – aks holda yopiq qopqoq butun oqshomga yoyilib ketardi.
Bitta kun, bitta o'q
Tanam haqidagi ma'lumot allaqachon bor edi: Whoop puls, uyqu va recovery'ni halol yozadi. Ammo u "o'sha payt nima qilayotgan eding" degan savolga javob bermaydi. Ekran vaqti trekerlari esa buning teskarisi: ilovani biladi, lekin ekranga qaraganimni yoki noutbuk yonida telefonga tikilganimni bilmaydi.
day-summ ikkala oqimni bitta kechki hisobotga jamlaydi: daqiqama-daqiqa taymlayn, charchoq oynalari, fokusdagi puls va telefondagi puls – ustiga shu noutbukda ishlaydigan model yozgan matnli xulosa.
Daqiqa o'z belgisini qanday oladi
Kadrlar birma-bir tahlil qilinmaydi: hammasi daqiqalik yozuvga yig'iladi (kadrdagi mavjudlik ulushi, ekranga qarash ulushi, telefonli kadrlar ulushi, pirillashlar, PERCLOS, o'rtacha puls), keyin daqiqa toza funksiya orqali aynan bitta kategoriya oladi:
def minute_category(rec, cfg, workout_spans):
if not rec.data_ok:
return "nodata"
if overlaps_workout(rec, workout_spans):
return "workout"
if rec.presence_ratio < cfg.break_presence_max:
# yuz yo'q: puls kelyapti → yaqinman, puls yo'q → chiqib ketganman
return "break" if rec.hr_avg is not None else "left"
if rec.phone_detected_ratio > cfg.phone_minute_ratio:
return "phone"
if (rec.presence_ratio >= cfg.focus_presence
and rec.gaze_on_screen_ratio >= cfg.focus_gaze
and rec.phone_detected_ratio < cfg.focus_phone_max):
return "focus"
if rec.gaze_on_screen_ratio < cfg.away_gaze_max:
return "away"
return "idle"Yuz va qarashni MediaPipe Face Landmarker hisoblaydi: u blendshape'larni (eyeBlinkLeft, jawOpen, eyeLookDown, browDown) va boshning burilish matritsasini beradi, undan pitch va yaw olinadi. Shu yerdan daqiqadagi pirillashlar va PERCLOS – ko'z yumuq o'tgan vaqt ulushi, uyquchanlikning klassik ko'rsatkichi – chiqadi.
Kadrdagi telefonni YOLO11-nano COCO klassi cell phone bo'yicha ushlaydi va faqat har o'ninchi kadrda, chunki detektor yuz modelidan og'irroq.
Tanaffusmi yoki ketganmi – pulsga bog'liq
Loyihaning eng yoqimli topilmasi. Kamera bir xil narsani – bo'sh kadrni – mutlaqo boshqa ikki holatda ko'radi: men kresloga suyanib o'ylayapman yoki xonadan chiqib ketdim. Ularni BLE ajratadi: Broadcast Heart Rate yoqilganda Whoop bilaguzugi standart Heart Rate Service orqali uzatadi va bir necha metr radiusda bo'lsam, puls kelaverdi. Puls yo'qolsa – demak men ketganman, yuz o'girganim emas.
Batareya: uzluksiz suratga olish o'rniga bo'laklar
Kamerani kun bo'yi yoqib qo'yish – qiziyotgan noutbuk va bir necha soat avtonomlikning yo'qolishi. Shuning uchun sukut bo'yicha kamera har 5 daqiqada 10 soniyaga uyg'onadi (konfigda sample_duration_sec / sample_interval_sec), BLE-puls esa doim ulanib turadi – u deyarli energiya yemaydi. macOS'da qopqoq ioreg orqali tekshiriladi (AppleClamshellState): yopiq bo'lsa, kamera umuman qo'zg'atilmaydi.
Matnni model yozadi, raqamlarni kod hisoblaydi
Hisobot tepasidagi xulosani lokal ollama orqali qwen3:8b generatsiya qiladi. Muhim tamoyil: model hisoblamaydi – u faqat so'zlab beradi. Barcha faktlarni (fokus daqiqalari, charchoq oynalari, kategoriyalar bo'yicha puls, Whoop API'dan recovery va uyqu) kod hisoblaydi va tayyor JSON qilib beradi, prompt esa to'g'ridan-to'g'ri "qayta hisoblama" deydi.
Agar ollama ishlamayotgan bo'lsa, hisobot buzilmaydi: f-satrlardan shablon xulosa yig'iladi. qwen3'da mulohaza rejimi ham bor – <think>…</think> bloki regulyar ifoda bilan kesib tashlanadi, hisobotga faqat toza matn boradi.
uv run daysumm calibrate # bir marta: ish joyingizga moslangan chegaralar
uv run daysumm start # ertalab: yig'ish + localhost:9683 da jonli dashboard
uv run daysumm report # kechqurun: HTML-hisobotni yig'ish va ochishMaxfiylik – va'da emas, arxitektura
Bunday narsani "deyarli maxfiy" qilib bo'lmaydi. Yo kadrlar umuman saqlanmaydi, yo bir kuni yarim yillik o'z yuzing turgan papkani topasan. Shuning uchun loyihada kadr diskka yetib boradigan bironta ham kod yo'li yo'q.