# Eldercare Sleep Tracker

> Theo dõi giấc ngủ người cao tuổi từ cảm biến mmWave (không cần wearable). Phân tích: giờ ngủ, giờ thức, số lần thức giữa đêm, tổng thời gian ngủ. Kết quả gửi vào daily report mỗi sáng. Data source: HA sensor presence + motion history. Không yêu cầu phần cứng thêm.

- Skill: `nclamvn/eldercare-sleep-tracker` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add nclamvn/eldercare-sleep-tracker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nclamvn/eldercare-sleep-tracker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: nclamvn (https://skillmd.com/u/nclamvn)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nclamvn/eldercare-sleep-tracker

---


# Eldercare Sleep Tracker — Theo dõi giấc ngủ

Skill phân tích giấc ngủ bà từ motion sensor data. Không cần thiết bị đeo — dùng FP2 mmWave presence + motion đã có sẵn.

## Nguyên lý

mmWave sensor (Aqara FP2) detect presence + motion liên tục.
Khi bà ngủ: presence=ON (vẫn trong phòng), motion=rất ít/không có.
Khi bà thức: motion tăng (trở mình, ngồi dậy, đi WC).

Skill phân tích motion history từ 22:00 → 06:30 để suy ra sleep pattern.

## Cron 6:30 sáng — Phân tích đêm qua

### Bước 1: Query HA history

Dùng tool `home_assistant` với action `get_history`:

```
action: get_history
entity_id: binary_sensor.grandma_room_presence
start_time: {22:00 hôm qua ISO}
end_time: {06:30 hôm nay ISO}
```

```
action: get_history
entity_id: sensor.grandma_room_motion_minutes
start_time: {22:00 hôm qua ISO}
end_time: {06:30 hôm nay ISO}
```

Nếu entity motion_minutes không available, fallback sang:
```
action: get_history
entity_id: binary_sensor.grandma_room_camera_motion
start_time: {22:00 hôm qua ISO}
end_time: {06:30 hôm nay ISO}
```

### Bước 2: Phân tích pattern

Từ motion history, xác định:

**Giờ ngủ (sleep_time):**
- Tìm thời điểm đầu tiên sau 21:00 mà motion dừng > 15 phút liên tục
- Cụ thể: `motion_minutes` tăng dần liên tục (bà không cử động) HOẶC `camera_motion` = off > 15 phút
- Ví dụ: motion cuối lúc 22:15 → sleep_time ≈ 22:15

**Giờ thức (wake_time):**
- Tìm thời điểm cuối cùng trong buổi sáng mà motion bắt đầu sustained > 5 phút
- Cụ thể: `motion_minutes` reset về 0 VÀ tiếp tục có activity
- Ví dụ: motion bắt đầu lúc 5:45 và tiếp tục → wake_time ≈ 5:45

**Số lần thức giữa đêm (wake_events):**
- Mỗi lần motion ON > 2 phút giữa sleep_time và wake_time
- Thường: đi WC, trở mình lâu, khó ngủ
- Format: `[{time: "02:30", duration_min: 8}, ...]`
- Lọc: motion < 2 phút = trở mình bình thường, KHÔNG count

**Tổng giờ ngủ (total_sleep_hours):**
- = (wake_time - sleep_time) - tổng thời gian wake_events
- Ví dụ: 22:15 → 5:45 = 7.5h - 15min thức = ~7.25h

**Chất lượng (quality):**
- **TỐT (good):** ≥7h ngủ, ≤1 lần thức, mỗi lần thức <10 phút
- **BÌNH THƯỜNG (normal):** 5-7h ngủ, ≤3 lần thức
- **KÉM (poor):** <5h ngủ, HOẶC >3 lần thức, HOẶC 1 lần thức >30 phút

### Bước 3: So sánh với 7 ngày trước

Query memory: tìm keys `eldercare_sleep_*` trong 7 ngày gần nhất.

Tính:
- Trung bình giờ ngủ 7 ngày (avg_7day)
- Trend: so sánh 3 ngày gần nhất
  - Giảm đều → "declining"
  - Tăng đều → "improving"
  - Dao động → "stable"

### Bước 4: Lưu memory

Key: `eldercare_sleep_{YYYY-MM-DD}`

```json
{
  "date": "2026-02-19",
  "sleep_time": "22:15",
  "wake_time": "05:45",
  "total_hours": 7.25,
  "wake_events": [
    { "time": "02:30", "duration_min": 8 }
  ],
  "quality": "good",
  "avg_7day": 6.8,
  "trend": "stable"
}
```

### Bước 5: Cảnh báo (nếu cần)

**Ngủ ít:**
- Ngủ < 4 giờ → Zalo gia đình: "⚠️ Bà chỉ ngủ ~{X} tiếng đêm qua. Thức {Y} lần."

**Thức giữa đêm lâu:**
- 1 lần thức > 30 phút → "⚠️ Bà thức lúc {giờ}, {X} phút. Có thể cần kiểm tra."

**Trend giảm:**
- 3 ngày liên tiếp giảm → "📊 Bà ngủ ít hơn 3 ngày liên tiếp ({X}h → {Y}h → {Z}h). Theo dõi thêm."

**KHÔNG cảnh báo** nếu chất lượng tốt hoặc bình thường.

## Tích hợp daily report

Skill `eldercare-daily-report` query key `eldercare_sleep_{today}`:

```
😴 Giấc ngủ:
  Ngủ lúc 22:15, thức lúc 5:45 (~7 tiếng)
  Thức 1 lần lúc 2:30 (8 phút)
  Chất lượng: Tốt ✅
  TB 7 ngày: 6.8 tiếng (→ ổn định)
```

## Xem lịch sử qua chat

Gia đình hỏi:
- "bà ngủ có ngon không" → report đêm qua
- "giấc ngủ bà tuần này" → bảng 7 ngày
- "bà thức mấy lần đêm qua" → chi tiết wake_events

## Giới hạn

- **Không chính xác 100%** — suy luận từ motion, không phải wearable sensor
- Nếu bà trở mình nhiều nhưng vẫn ngủ → có thể count sai wake_event
- Nếu ông ngủ cùng phòng → presence/motion có thể bị ảnh hưởng bởi ông
- Skill ghi rõ trong mọi report: "Ước tính dựa trên cảm biến phòng, tham khảo"
- Không phải chẩn đoán y khoa — nếu nghi ngờ vấn đề giấc ngủ → hỏi bác sĩ

## Multi-Elder Support

Skill này hỗ trợ nhiều người thân:

1. Đọc `eldercare_profiles` từ memory
2. Nếu không tồn tại → auto-migrate default profile "ba_noi" (xem skill eldercare-profiles)
3. Loop qua tất cả active elders
4. Với mỗi elder:
   - Dùng `elder.ha_entities.*` thay vì hardcoded entity names
   - Dùng `eldercare_{elder.id}_*` làm memory key prefix
   - Dùng `elder.name` trong messages/TTS
   - Dùng `elder.contacts` cho alert recipients (fallback global contacts)
   - Dùng `elder.tts.*` cho TTS settings

### Thay đổi cụ thể

- `binary_sensor.grandma_room_presence` → `elder.ha_entities.presence`
- `sensor.grandma_room_motion_minutes` → `elder.ha_entities.motion`
- `binary_sensor.grandma_room_camera_motion` → `elder.ha_entities.camera` + `_motion`
- Memory: `eldercare_sleep_*` → `eldercare_{elder.id}_sleep_*`
- Memory: `eldercare_sleep_{date}` → `eldercare_{elder.id}_sleep_{date}`
- Reports: Include `elder.name` in sleep reports

