320 lines
8.3 KiB
Markdown
320 lines
8.3 KiB
Markdown
|
|
# Alarm System
|
||
|
|
|
||
|
|
**Critical alarms with repeating sound until dismissed**
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The Alfred mobile app now supports alarms - notifications that play a sound on repeat and require explicit dismissal. Unlike regular notifications that auto-dismiss, alarms are designed for time-critical events you cannot miss.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
### 🔔 Repeating Sound
|
||
|
|
- Uses system alarm ringtone (same sound as your device's alarm clock)
|
||
|
|
- Loops continuously until dismissed
|
||
|
|
- Full volume (respects system alarm volume)
|
||
|
|
|
||
|
|
### 📳 Repeating Vibration
|
||
|
|
- Vibration pattern: 500ms on, 500ms off, repeating
|
||
|
|
- Loops continuously until dismissed
|
||
|
|
- Can be disabled with `--no-vibrate` flag
|
||
|
|
|
||
|
|
### 🔒 Persistent Notification
|
||
|
|
- System notification stays visible until dismissed
|
||
|
|
- Cannot auto-dismiss (requires user action)
|
||
|
|
- Marked with ⏰ icon and "ALARM" prefix
|
||
|
|
|
||
|
|
### ✅ Manual Dismissal
|
||
|
|
- Say "dismiss alarm" or "dismiss alert" in chat
|
||
|
|
- Alarm stops immediately
|
||
|
|
- Notification clears
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Scheduled Alarms
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Morning medication at 8am
|
||
|
|
mobile-notify alarm "08:00" "Take morning medication" --title "Health"
|
||
|
|
|
||
|
|
# Doctor appointment tomorrow
|
||
|
|
mobile-notify alarm "tomorrow 14:30" "Doctor appointment in 10 minutes"
|
||
|
|
|
||
|
|
# Critical meeting
|
||
|
|
mobile-notify alarm "2026-02-10 09:00" "Team standup starts now!"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Instant Alarms
|
||
|
|
|
||
|
|
For immediate alarms (rare), use the `--alarm` flag with `alert`:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
mobile-notify alert "Emergency alert!" --alarm --title "URGENT"
|
||
|
|
```
|
||
|
|
|
||
|
|
### From Alfred
|
||
|
|
|
||
|
|
When you ask Alfred to set a reminder, I'll ask if you want a notification or alarm if it's not clear:
|
||
|
|
|
||
|
|
**User:** "Remind me to take my medication at 8am tomorrow"
|
||
|
|
|
||
|
|
**Alfred:** "Would you like a regular notification, or an alarm (repeating sound until dismissed)?"
|
||
|
|
|
||
|
|
**User:** "Alarm please, I can't miss this"
|
||
|
|
|
||
|
|
**Alfred:** ✅ *Sets alarm*
|
||
|
|
|
||
|
|
```bash
|
||
|
|
exec(['mobile-notify', 'alarm', 'tomorrow 08:00', 'Take morning medication', '--title', 'Health'])
|
||
|
|
```
|
||
|
|
|
||
|
|
## When to Use Alarms vs Notifications
|
||
|
|
|
||
|
|
### Use Alarms For:
|
||
|
|
- ✅ Medication reminders
|
||
|
|
- ✅ Critical appointments (doctor, dentist, etc.)
|
||
|
|
- ✅ Important meetings you can't miss
|
||
|
|
- ✅ Wake-up alarms
|
||
|
|
- ✅ Time-sensitive tasks
|
||
|
|
- ✅ Emergency alerts
|
||
|
|
|
||
|
|
### Use Notifications For:
|
||
|
|
- ✅ General reminders
|
||
|
|
- ✅ Informational alerts
|
||
|
|
- ✅ Task completion notices
|
||
|
|
- ✅ Non-urgent events
|
||
|
|
- ✅ Daily routines
|
||
|
|
|
||
|
|
## Dismissing Alarms
|
||
|
|
|
||
|
|
### In-App Dismissal
|
||
|
|
|
||
|
|
Type or say any of these:
|
||
|
|
- "dismiss alarm"
|
||
|
|
- "dismiss alert"
|
||
|
|
- "dismiss the alarm"
|
||
|
|
- "stop alarm"
|
||
|
|
- "stop the alarm"
|
||
|
|
|
||
|
|
The app automatically detects these phrases and dismisses all active alarms.
|
||
|
|
|
||
|
|
### Notification Dismissal
|
||
|
|
|
||
|
|
Currently, you can only dismiss alarms via the app (by saying "dismiss alarm"). Future updates will add a dismiss button in the notification itself.
|
||
|
|
|
||
|
|
## Technical Details
|
||
|
|
|
||
|
|
### AlarmManager Component
|
||
|
|
|
||
|
|
Located at `app/src/main/java/com/openclaw/alfred/alarm/AlarmManager.kt`
|
||
|
|
|
||
|
|
**Key methods:**
|
||
|
|
- `startAlarm()` - Begin alarm with repeating sound/vibration
|
||
|
|
- `dismissAlarm()` - Stop specific alarm
|
||
|
|
- `dismissAll()` - Stop all active alarms
|
||
|
|
- `destroy()` - Cleanup on app close
|
||
|
|
|
||
|
|
**Sound playback:**
|
||
|
|
- Uses `MediaPlayer` with alarm audio attributes
|
||
|
|
- Loops via `isLooping = true`
|
||
|
|
- Uses `RingtoneManager.TYPE_ALARM` sound
|
||
|
|
|
||
|
|
**Vibration:**
|
||
|
|
- Uses `VibrationEffect.createWaveform()` with repeating pattern
|
||
|
|
- Pattern: [0ms delay, 500ms vibrate, 500ms pause, repeat]
|
||
|
|
- Requires `android.permission.VIBRATE`
|
||
|
|
|
||
|
|
### CLI Tool Updates
|
||
|
|
|
||
|
|
**New command:**
|
||
|
|
```bash
|
||
|
|
mobile-notify alarm "TIME" "MESSAGE" [options]
|
||
|
|
```
|
||
|
|
|
||
|
|
**New flag:**
|
||
|
|
```bash
|
||
|
|
mobile-notify alert "MESSAGE" --alarm [options]
|
||
|
|
```
|
||
|
|
|
||
|
|
### Event Format
|
||
|
|
|
||
|
|
WebSocket events for alarms:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "event",
|
||
|
|
"event": "mobile.notification",
|
||
|
|
"payload": {
|
||
|
|
"notificationType": "alarm",
|
||
|
|
"title": "Health",
|
||
|
|
"message": "Take morning medication",
|
||
|
|
"priority": "default",
|
||
|
|
"sound": true,
|
||
|
|
"vibrate": true,
|
||
|
|
"timestamp": 1706918400000
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### UI Behavior
|
||
|
|
|
||
|
|
**When alarm is received:**
|
||
|
|
|
||
|
|
1. **Foreground:**
|
||
|
|
- Alarm sound starts looping
|
||
|
|
- Vibration starts looping
|
||
|
|
- Message added to chat: "🔔 ALARM: [message] (Say 'dismiss alarm' to stop)"
|
||
|
|
- Persistent notification shown
|
||
|
|
|
||
|
|
2. **Background:**
|
||
|
|
- Alarm sound starts looping
|
||
|
|
- Vibration starts looping
|
||
|
|
- Persistent notification shown
|
||
|
|
- User must open app to dismiss
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
|
||
|
|
### Medication Reminder
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Set alarm for 8am daily medication
|
||
|
|
mobile-notify alarm "08:00" "Take your morning medication" --title "Health"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:**
|
||
|
|
- At 8:00 AM, alarm sound plays on repeat
|
||
|
|
- Persistent notification: "⏰ ALARM: Health - Take your morning medication"
|
||
|
|
- User must say "dismiss alarm" to stop
|
||
|
|
|
||
|
|
### Important Meeting
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Alarm 5 minutes before critical meeting
|
||
|
|
mobile-notify alarm "14:55" "Sprint planning starts in 5 minutes" --title "Calendar"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Wake-Up Alarm
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Wake up alarm for tomorrow
|
||
|
|
mobile-notify alarm "tomorrow 07:00" "Good morning! Time to wake up" --title "Wake Up"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Emergency Alert
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Immediate emergency alarm
|
||
|
|
mobile-notify alert "Server is down! Check immediately!" --alarm --title "EMERGENCY" --priority high
|
||
|
|
```
|
||
|
|
|
||
|
|
## Configuration
|
||
|
|
|
||
|
|
### Custom Alarm Sound
|
||
|
|
|
||
|
|
Currently uses the system's default alarm sound. To customize in the future, modify `AlarmManager.kt`:
|
||
|
|
|
||
|
|
```kotlin
|
||
|
|
val alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
|
||
|
|
// Replace with: Uri.parse("android.resource://" + context.packageName + "/" + R.raw.custom_alarm)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Volume
|
||
|
|
|
||
|
|
Alarms respect the system's alarm volume setting (not media volume). Users control volume via:
|
||
|
|
- Volume buttons (when on alarm screen)
|
||
|
|
- Settings → Sound → Alarm volume
|
||
|
|
|
||
|
|
### Vibration Pattern
|
||
|
|
|
||
|
|
Default pattern: 500ms on, 500ms off
|
||
|
|
|
||
|
|
To customize, edit `AlarmManager.kt`:
|
||
|
|
|
||
|
|
```kotlin
|
||
|
|
val pattern = longArrayOf(0, 500, 500) // [delay, vibrate, pause]
|
||
|
|
```
|
||
|
|
|
||
|
|
## Permissions
|
||
|
|
|
||
|
|
Required permissions (already declared in `AndroidManifest.xml`):
|
||
|
|
|
||
|
|
- `android.permission.VIBRATE` - For alarm vibration
|
||
|
|
- `android.permission.POST_NOTIFICATIONS` - For showing notifications (Android 13+)
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Alarm sound not playing
|
||
|
|
|
||
|
|
**Possible causes:**
|
||
|
|
- Alarm volume is muted (check Settings → Sound)
|
||
|
|
- Do Not Disturb mode is enabled
|
||
|
|
- Device is in silent mode
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
- Check system alarm volume
|
||
|
|
- Disable Do Not Disturb
|
||
|
|
- Ensure alarm volume is not muted
|
||
|
|
|
||
|
|
### Alarm not stopping
|
||
|
|
|
||
|
|
**Symptom:** Alarm keeps playing after saying "dismiss alarm"
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
- Make sure text is sent (not just voice input canceled)
|
||
|
|
- Try typing "dismiss alarm" manually
|
||
|
|
- Force-close and reopen app if stuck
|
||
|
|
|
||
|
|
### Vibration not working
|
||
|
|
|
||
|
|
**Possible causes:**
|
||
|
|
- Device doesn't support vibration (emulators)
|
||
|
|
- Vibration disabled in settings
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
- Test on physical device
|
||
|
|
- Check Settings → Accessibility → Vibration
|
||
|
|
|
||
|
|
### Notification not showing
|
||
|
|
|
||
|
|
**Possible causes:**
|
||
|
|
- Notification permissions denied (Android 13+)
|
||
|
|
- App notifications disabled in system settings
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
- Settings → Apps → Alfred → Notifications → Allow
|
||
|
|
- Grant notification permission when prompted
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
Planned improvements:
|
||
|
|
|
||
|
|
- [ ] **Dismiss button in notification** - Tap to dismiss without opening app
|
||
|
|
- [ ] **Snooze functionality** - Delay alarm by X minutes
|
||
|
|
- [ ] **Custom alarm sounds** - Choose from device sounds or upload custom
|
||
|
|
- [ ] **Escalating volume** - Start quiet, gradually increase
|
||
|
|
- [ ] **Smart silence** - Auto-stop after X minutes (safety)
|
||
|
|
- [ ] **Multiple alarms** - Track and dismiss individually
|
||
|
|
- [ ] **Alarm history** - See past alarms and when dismissed
|
||
|
|
- [ ] **Quick alarm presets** - Common alarms with one tap
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
### For Users
|
||
|
|
|
||
|
|
1. **Use alarms sparingly** - Reserve for truly important events
|
||
|
|
2. **Dismiss promptly** - Don't let alarms loop unnecessarily
|
||
|
|
3. **Test first** - Try a test alarm to ensure sound/vibration work
|
||
|
|
4. **Check volume** - Verify alarm volume is audible before critical alarms
|
||
|
|
5. **Battery considerations** - Alarms drain battery if left running
|
||
|
|
|
||
|
|
### For Alfred
|
||
|
|
|
||
|
|
1. **Ask when uncertain** - If user doesn't specify, ask "notification or alarm?"
|
||
|
|
2. **Default to notifications** - Only use alarms when appropriate
|
||
|
|
3. **Be explicit** - Tell user it's an alarm ("I've set an alarm...")
|
||
|
|
4. **Mention dismissal** - Remind user how to dismiss ("Say 'dismiss alarm' to stop")
|
||
|
|
5. **Confirm critical alarms** - "I've set an alarm for your medication at 8am tomorrow. It will repeat until you dismiss it."
|
||
|
|
|
||
|
|
## Version
|
||
|
|
|
||
|
|
1.0.0 - Initial alarm system (February 2026)
|