Alert System UI Implementation Guide
This document provides everything needed to implement the frontend UI for the Fermentrack alert system.
Overview
The alert system monitors FermentLogs and triggers alerts when certain conditions are met (e.g., cooling not working, fermentation stalled, device disconnected). Each FermentLog can have multiple alert configurations, and each configuration tracks its own state (active/inactive).
Key Concepts:
- Alert Evaluator: A type of alert (defined in code). Examples: "Cooling Not Effective", "Gravity Stall"
- Alert Configuration: User's settings for a specific alert on a specific FermentLog
- Alert State: Whether an alert is currently triggered (active) or not
API Endpoints
All endpoints require authentication. Base URL: /api/
1. List Alert Configurations for a FermentLog
GET /api/ferment_logs/log/{ferment_log_id}/alerts/configs/
Response:
[
{
"id": "uuid",
"ferment_log": "uuid",
"alert_code": "cooling_ineffective",
"enabled": true,
"custom_thresholds": {"duration_minutes": 45},
"trigger_control_off": false,
"current_state": {
"is_active": false,
"became_active_at": null,
"last_evaluated_at": "2024-01-15T10:30:00Z",
"trigger_context": {},
"control_action_taken": false
},
"evaluator_name": "Cooling Not Effective",
"evaluator_description": "Triggers when cooling runs too long without sufficient temperature drop",
"evaluator_category": "temperature",
"evaluator_severity": "warning",
"is_applicable": true,
"threshold_definitions": [
{
"key": "duration_minutes",
"label": "Duration threshold",
"type": "duration_minutes",
"default": 30,
"min_value": 10,
"max_value": 120,
"help_text": "How long cooling must run without effect",
"units": "minutes"
}
],
"effective_thresholds": {"duration_minutes": 45, "min_temp_drop": 0.5},
"created": "2024-01-10T08:00:00Z",
"modified": "2024-01-15T09:00:00Z"
}
]
2. Get Available Alerts for a FermentLog
Returns ALL alert types with their applicability and configuration status.
GET /api/ferment_logs/log/{ferment_log_id}/alerts/available/
Response:
[
{
"code": "cooling_ineffective",
"name": "Cooling Not Effective",
"description": "Triggers when cooling runs too long without sufficient temperature drop",
"category": "temperature",
"default_severity": "warning",
"is_applicable": true,
"enabled_by_default": true,
"can_trigger_control_action": true,
"threshold_definitions": [...],
"is_configured": true,
"configuration": {
"id": "uuid",
"enabled": true,
"custom_thresholds": {},
"effective_thresholds": {"duration_minutes": 30},
"trigger_control_off": false,
"current_state": {...}
}
},
{
"code": "gravity_stall",
"name": "Gravity Stall",
"description": "Triggers when gravity hasn't changed significantly",
"category": "fermentation",
"default_severity": "warning",
"is_applicable": false,
"enabled_by_default": true,
"can_trigger_control_action": false,
"threshold_definitions": [...],
"is_configured": false,
"configuration": null
}
]
3. Create Alert Configuration
POST /api/ferment_logs/log/{ferment_log_id}/alerts/configs/
Content-Type: application/json
{
"alert_code": "cooling_ineffective",
"enabled": true,
"custom_thresholds": {"duration_minutes": 45},
"trigger_control_off": false
}
4. Update Alert Configuration
PATCH /api/ferment_logs/log/{ferment_log_id}/alerts/configs/{config_id}/
Content-Type: application/json
{
"enabled": false,
"custom_thresholds": {"duration_minutes": 60}
}
5. Delete Alert Configuration
DELETE /api/ferment_logs/log/{ferment_log_id}/alerts/configs/{config_id}/
6. Create Default Configurations
Creates configurations for all applicable alerts with enabled_by_default=true.
POST /api/ferment_logs/log/{ferment_log_id}/alerts/create-defaults/
Response:
{
"created_count": 3,
"configurations": [...]
}
7. Manually Evaluate Alerts for a FermentLog
Triggers immediate evaluation (useful for testing or refresh).
POST /api/ferment_logs/log/{ferment_log_id}/alerts/evaluate/
Response:
{
"evaluated_count": 5,
"triggered_count": 1,
"alerts": [...]
}
8. Get All Active Alerts (Brewhouse-wide)
Returns all currently triggered alerts across all FermentLogs.
GET /api/alerts/active/
Response:
[
{
"alert_code": "temp_controller_disconnected",
"alert_name": "Temperature Controller Disconnected",
"severity": "critical",
"ferment_log_id": "uuid",
"ferment_log_name": "IPA Batch #42",
"became_active_at": "2024-01-15T10:00:00Z",
"trigger_context": {
"message": "Temperature controller hasn't reported data for 25.3 minutes",
"disconnected_minutes": 25.3,
"threshold_minutes": 15
}
}
]
Important: Alert Lifecycle
Automatic Deletion When Log is Stopped
When a FermentLog is "stopped" (both temperature controller AND gravity sensor are removed), all alert configurations for that log are automatically deleted.
This happens automatically via a Django signal - the UI does not need to call any API endpoint. However, the UI should be aware of this behavior:
- After stopping a log, any cached alert data for that log is stale
- The alert configuration page should handle the case where configs no longer exist
- Active alert banners should refresh after a log is stopped
// After stopping a log, clear any cached alert data
async function stopFermentLog(logId) {
await api.post(`/ferment_logs/log/${logId}/stop/`);
// Clear cached alerts for this log - they've been deleted server-side
clearAlertCache(logId);
// Refresh the active alerts list
await refreshActiveAlerts();
}
When to Call the API
On FermentLog Creation
After creating a new FermentLog, call the create-defaults endpoint to set up initial alert configurations:
// After creating a new FermentLog
const response = await api.post(`/ferment_logs/log/${newLogId}/alerts/create-defaults/`);
console.log(`Created ${response.data.created_count} default alert configurations`);
On FermentLog Detail Page Load
Fetch the configured alerts to display their status:
const configs = await api.get(`/ferment_logs/log/${logId}/alerts/configs/`);
On Alert Settings Page
Fetch all available alerts to show which ones can be configured:
const available = await api.get(`/ferment_logs/log/${logId}/alerts/available/`);
On Dashboard/Home Page
Fetch active alerts to show a notification banner:
const activeAlerts = await api.get('/alerts/active/');
if (activeAlerts.data.length > 0) {
showAlertBanner(activeAlerts.data);
}
Polling for Alert Updates
Poll periodically (every 30-60 seconds) on pages where alert status matters:
setInterval(async () => {
const activeAlerts = await api.get('/alerts/active/');
updateAlertIndicators(activeAlerts.data);
}, 30000);
Alert Categories and Severity
Categories
| Category | Description |
|---|---|
temperature | Temperature control issues |
connectivity | Device connection issues |
fermentation | Fermentation process issues |
device | Hardware/firmware issues |
Severity Levels
| Severity | Color Suggestion | Description |
|---|---|---|
critical | Red | Immediate attention required |
warning | Orange/Yellow | Potential problem |
info | Blue | Informational notification |
Available Alert Types
| Code | Name | Category | Severity | Requires |
|---|---|---|---|---|
cooling_ineffective | Cooling Not Effective | temperature | warning | Temp Controller |
heating_ineffective | Heating Not Effective | temperature | warning | Temp Controller |
temp_controller_disconnected | Temperature Controller Disconnected | connectivity | critical | Temp Controller |
gravity_sensor_disconnected | Gravity Sensor Disconnected | connectivity | warning | Gravity Sensor |
gravity_stall | Gravity Stall | fermentation | warning | Gravity Sensor |
fermentation_not_started | Fermentation Not Started | fermentation | warning | Gravity Sensor |
fermentation_complete | Fermentation Complete | fermentation | info | Gravity Sensor |
profile_complete | Temperature Profile Complete | temperature | info | Temp Controller |
firmware_update_available | Firmware Update Available | device | info | Temp Controller |
UI Component Suggestions
1. Active Alerts Banner (Dashboard/Header)
Display prominently when there are active alerts.
┌─────────────────────────────────────────────────────────────────┐
│ ⚠️ 2 Active Alerts [View All]│
│ ────────────────────────────────────────────────────────────────│
│ 🔴 CRITICAL: Temperature Controller Disconnected - IPA Batch #42│
│ 🟠 WARNING: Gravity Stall detected - Hefeweizen │
└─────────────────────────────────────────────────────────────────┘
2. FermentLog Detail - Alert Status Card
Show on the FermentLog detail page.
┌─────────────────────────────────────────────────────────────────┐
│ Alerts [⚙️ Configure] │
│ ────────────────────────────────────────────────────────────────│
│ ✅ Cooling Monitor OK Last checked: 2 min ago │
│ ✅ Heating Monitor OK Last checked: 2 min ago │
│ 🔴 Controller Connection TRIGGERED Since: 10:00 AM │
│ ✅ Fermentation Progress OK Last checked: 2 min ago │
│ ────────────────────────────────────────────────────────────────│
│ 4 alerts configured • 1 triggered │
└─────────────────────────────────────────────────────────────────┘
3. Alert Configuration Page
Allow users to enable/disable alerts and customize thresholds.
┌─────────────────────────────────────────────────────────────────┐
│ Alert Configuration - IPA Batch #42 │
│ ════════════════════════════════════════════════════════════════│
│ │
│ TEMPERATURE ALERTS │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ [✓] Cooling Not Effective WARNING │ │
│ │ Triggers when cooling runs too long without effect │ │
│ │ │ │
│ │ Duration threshold: [30 ] minutes (10-120) │ │
│ │ Min temp drop: [0.5 ] °F (0.1-2.0) │ │
│ │ │ │
│ │ [✓] Turn off controller when triggered │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ [✓] Heating Not Effective WARNING │ │
│ │ Triggers when heating runs too long without effect │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ CONNECTIVITY ALERTS │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ [✓] Controller Disconnected CRITICAL │ │
│ │ Triggers when no data received for too long │ │
│ │ │ │
│ │ Disconnection threshold: [15 ] minutes (5-60) │ │
│ └──────────────────────────────────────────────────── ─────────┘ │
│ │
│ FERMENTATION ALERTS │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ [ ] Gravity Stall NOT APPLICABLE │ │
│ │ ⚠️ Requires a gravity sensor to be attached │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [Cancel] [Save Changes]│
└─────────────────────────────────────────────────────────────────┘
4. Triggered Alert Detail Modal
Show when user clicks on an active alert.
┌─────────────────────────────────────────────────────────────────┐
│ 🔴 Temperature Controller Disconnected [X] │
│ ════════════════════════════════════════════════════════════════│
│ │
│ FermentLog: IPA Batch #42 │
│ Triggered: January 15, 2024 at 10:00 AM (25 minutes ago) │
│ │
│ ────────────────────────────────────────────────────────────────│
│ DETAILS │
│ │
│ Temperature controller hasn't reported data for 25.3 minutes │
│ (threshold: 15 minutes) │
│ │
│ Last check-in: January 15, 2024 at 9:35 AM │
│ │
│ ────────────────────────────────────────────────────────────────│
│ SUGGESTED ACTIONS │
│ │
│ • Check if the controller is powered on │
│ • Verify network connectivity │
│ • Check the controller's web interface │
│ │
│ [View FermentLog] [Dismiss] │
└─────────────────────────────────────────────────────────────────┘
5. Alert History (Future Enhancement)
┌─────────────────────────────────────────────────────────────────┐
│ Alert History - IPA Batch #42 │
│ ────────────────────────────────────────────────────────────────│
│ Jan 15, 10:00 AM 🔴 Controller Disconnected ACTIVE │
│ Jan 14, 3:30 PM 🟢 Cooling Not Effective Resolved (45m) │
│ Jan 13, 8:15 AM 🟢 Controller Disconnected Resolved (5m) │
│ Jan 10, 2:00 PM ℹ️ Fermentation Complete Acknowledged │
└─────────────────────────────────────────────────────────────────┘
Threshold Input Types
When rendering threshold configuration inputs, use the type field:
| Type | Input Type | Notes |
|---|---|---|
duration_minutes | Number input | Show "minutes" label |
duration_hours | Number input | Show "hours" label |
decimal | Number input | Allow decimal values, step="0.001" |
integer | Number input | Whole numbers only |
Always respect min_value and max_value for validation.
Error Handling
Common Error Responses
400 Bad Request - Invalid data:
{
"alert_code": ["Unknown alert code: invalid_code"],
"custom_thresholds": ["Duration threshold: value must be at least 10"]
}
404 Not Found - FermentLog doesn't exist or doesn't belong to user's brewhouse.
403 Forbidden - User not authenticated.
State Management Recommendations
-
Cache active alerts at the app level and update via polling
-
Invalidate cache when:
- User modifies alert configurations
- User manually triggers evaluation
- WebSocket notification received (future)
-
Optimistic updates for enable/disable toggles
Future Considerations
The following features are planned but not yet implemented:
- Notifications - Email/push notifications when alerts trigger
- Alert History - Historical record of past alerts
- Acknowledgment - Allow users to acknowledge/dismiss alerts
- Snooze - Temporarily disable alerts
The API is designed to accommodate these features without breaking changes.