Initial commit: Alfred Mobile - AI Assistant Android App
- OAuth authentication via Authentik - WebSocket connection to OpenClaw gateway - Configurable gateway URL with first-run setup - User preferences sync across devices - Multi-user support with custom assistant names - ElevenLabs TTS integration (local + remote) - FCM push notifications for alarms - Voice input via Google Speech API - No hardcoded secrets or internal IPs in tracked files
This commit is contained in:
199
CROSS_DEVICE_ALARMS.md
Normal file
199
CROSS_DEVICE_ALARMS.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Cross-Device Alarm Dismissal
|
||||
|
||||
## Overview
|
||||
|
||||
When an alarm is dismissed on one device, it automatically dismisses on all other connected devices. This prevents the same alarm from ringing on multiple devices.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
Device A (dismisses alarm)
|
||||
↓
|
||||
AlarmManager detects dismissal
|
||||
↓
|
||||
Calls onAlarmDismissed callback
|
||||
↓
|
||||
GatewayClient sends {"type":"alarm.dismiss","alarmId":"..."}
|
||||
↓
|
||||
OAuth Proxy receives message
|
||||
↓
|
||||
Proxy broadcasts {"type":"event","event":"mobile.alarm.dismissed","payload":{...}} to ALL clients
|
||||
↓
|
||||
Device B, C, D... receive broadcast
|
||||
↓
|
||||
Each device silently dismisses that alarm ID
|
||||
```
|
||||
|
||||
### Implementation Details
|
||||
|
||||
**Mobile App (Alfred Mobile):**
|
||||
|
||||
1. **AlarmManager.kt** - Singleton with `onAlarmDismissed` callback
|
||||
- When `dismissAlarm(alarmId)` is called, triggers callback
|
||||
- Callback is set by MainScreen to notify GatewayClient
|
||||
|
||||
2. **GatewayClient.kt** - Added `dismissAlarm(alarmId)` method
|
||||
- Sends `{"type":"alarm.dismiss","alarmId":"..."}` via WebSocket
|
||||
- Receives `mobile.alarm.dismissed` events
|
||||
- Calls `listener.onAlarmDismissed(alarmId)`
|
||||
|
||||
3. **GatewayListener interface** - Added `onAlarmDismissed(alarmId)` callback
|
||||
|
||||
4. **MainScreen.kt** - Wires everything together
|
||||
- Sets `alarmManager.onAlarmDismissed` callback to call `gatewayClient.dismissAlarm()`
|
||||
- Implements `onAlarmDismissed()` to dismiss alarm locally without re-broadcasting
|
||||
|
||||
**Proxy Server (alfred-proxy):**
|
||||
|
||||
1. **Message Interception** - Checks for `alarm.dismiss` messages from clients
|
||||
2. **Broadcasting** - Creates `mobile.alarm.dismissed` event and sends to all connected clients
|
||||
3. **No OpenClaw Forwarding** - Dismiss events are handled internally, not sent to OpenClaw
|
||||
|
||||
### Message Format
|
||||
|
||||
**Client → Proxy (dismiss):**
|
||||
```json
|
||||
{
|
||||
"type": "alarm.dismiss",
|
||||
"alarmId": "alarm-1770148325914",
|
||||
"timestamp": 1770148325914
|
||||
}
|
||||
```
|
||||
|
||||
**Proxy → All Clients (broadcast):**
|
||||
```json
|
||||
{
|
||||
"type": "event",
|
||||
"event": "mobile.alarm.dismissed",
|
||||
"payload": {
|
||||
"alarmId": "alarm-1770148325914",
|
||||
"timestamp": 1770148325914
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Prerequisites
|
||||
- Alfred Mobile app installed on 2+ devices
|
||||
- All devices connected to the same proxy (alfred-app.dnspegasus.net)
|
||||
- All devices authenticated with the same user account
|
||||
|
||||
### Test Procedure
|
||||
|
||||
1. **Set an alarm:**
|
||||
```bash
|
||||
# Via Alfred or directly:
|
||||
curl -X POST http://localhost:18790/api/notify \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"notificationType":"alarm","title":"Cross-Device Test","message":"Testing sync","priority":"high","sound":true,"vibrate":true}'
|
||||
```
|
||||
|
||||
2. **Verify alarm triggers on all devices**
|
||||
- Sound and vibration should start on all devices
|
||||
- Full-screen AlarmActivity should appear on all devices
|
||||
|
||||
3. **Dismiss on ONE device**
|
||||
- Use either the notification dismiss button OR the full-screen dismiss button
|
||||
- Watch the other devices
|
||||
|
||||
4. **Expected behavior:**
|
||||
- ✅ Alarm stops immediately on the device you dismissed
|
||||
- ✅ Alarm automatically stops on all other devices within 1-2 seconds
|
||||
- ✅ Notifications clear on all devices
|
||||
- ✅ No re-triggering or duplicate dismissals
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**Alarm doesn't dismiss on other devices:**
|
||||
- Check proxy logs: `tail -f /tmp/alfred-proxy-new.log`
|
||||
- Look for: `[proxy] Alarm dismiss received:` and `Broadcasted alarm dismiss to X client(s)`
|
||||
- Verify all devices are connected: broadcast count should match device count
|
||||
|
||||
**Alarm dismisses multiple times:**
|
||||
- Check for infinite loops in logs
|
||||
- Verify the `onAlarmDismissed` callback is properly cleared before local dismissal in broadcast handler
|
||||
|
||||
**Delay in dismissal:**
|
||||
- Normal: 1-2 second delay is expected (network latency)
|
||||
- Check WebSocket connection health on all devices
|
||||
- Verify proxy is not rate-limiting or buffering messages
|
||||
|
||||
## Logging
|
||||
|
||||
**Mobile App (adb logcat):**
|
||||
```bash
|
||||
# Watch for alarm dismissal events
|
||||
adb logcat | grep -E "AlarmManager.*Dismiss|onAlarmDismissed|alarm.dismiss"
|
||||
|
||||
# Example output:
|
||||
# AlarmManager: Dismissing alarm: alarm-1770148325914
|
||||
# MainScreen: Alarm dismissed locally, broadcasting: alarm-1770148325914
|
||||
# GatewayClient: Sending alarm dismiss: alarm-1770148325914
|
||||
# MainScreen: Received alarm dismiss broadcast: alarm-1770148325914
|
||||
```
|
||||
|
||||
**Proxy Server:**
|
||||
```bash
|
||||
tail -f /tmp/alfred-proxy-new.log | grep -i alarm
|
||||
|
||||
# Example output:
|
||||
# [proxy] Alarm dismiss received: alarm-1770148325914
|
||||
# [proxy] Broadcasted alarm dismiss to 2 client(s)
|
||||
```
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### Same Device Dismissal
|
||||
- Device dismisses alarm → triggers broadcast → receives own broadcast
|
||||
- **Handled:** Callback is temporarily cleared before processing broadcast to avoid re-dismissal
|
||||
|
||||
### Partial Network Failure
|
||||
- One device offline when alarm is dismissed
|
||||
- **Behavior:** Alarm continues ringing on offline device until manually dismissed
|
||||
- **No persistence:** Dismiss events are not queued or stored
|
||||
|
||||
### Multiple Simultaneous Dismissals
|
||||
- Two devices dismiss the same alarm within milliseconds
|
||||
- **Behavior:** Each sends dismiss event, proxy broadcasts both
|
||||
- **Handled:** AlarmManager is idempotent - dismissing already-dismissed alarm is safe
|
||||
|
||||
### Connection During Active Alarm
|
||||
- Device connects while alarm is already ringing on other devices
|
||||
- **Behavior:** Newly connected device starts alarm (receives notification)
|
||||
- **No state sync:** Active alarm state is not synchronized on connect
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Possible Improvements:
|
||||
1. **State sync on connect** - Send active alarm list when device connects
|
||||
2. **Dismiss persistence** - Store recent dismissals (last 5 minutes) and send to new connections
|
||||
3. **Snooze sync** - Extend cross-device sync to snooze actions
|
||||
4. **Offline queue** - Queue dismiss events when offline, send when reconnected
|
||||
|
||||
### Not Implemented:
|
||||
- Alarm creation sync (alarms created via Alfred cron, not device-local)
|
||||
- Snooze functionality
|
||||
- Custom alarm sounds per device
|
||||
- Volume control sync
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Authentication:** All clients must be authenticated via OAuth to connect to proxy
|
||||
- **Authorization:** Same user account across devices (enforced by OAuth)
|
||||
- **No spoofing:** Alarm IDs include timestamp - difficult to forge
|
||||
- **Rate limiting:** Consider adding if dismiss spam becomes an issue
|
||||
|
||||
## Version History
|
||||
|
||||
- **v1.0.1** (2026-02-03) - Initial cross-device alarm dismissal implementation
|
||||
- **v1.0.0** (2026-02-03) - Basic alarm system with single-device dismissal
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- `ALARMS.md` - Full alarm system documentation
|
||||
- `ARCHITECTURE.md` - Overall system architecture
|
||||
- `AGENT_TOOLS.md` - Mobile-notify and alarms skill integration
|
||||
- `~/.openclaw/workspace/skills/alarms/SKILL.md` - Alarm scheduling skill
|
||||
Reference in New Issue
Block a user