Skip to content

jsprague84/coffee-roaster-dashboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Coffee Roaster Dashboard (Rust)

A real-time web dashboard for monitoring and controlling ESP32-based coffee roaster systems. Built with Rust, Axum, and modern web technologies, this dashboard provides live telemetry visualization, historical data analysis, and roaster control capabilities.

🌟 Features

Real-time Monitoring

  • Live temperature charts with Bean Temperature, Environment Temperature, and Rate of Rise
  • WebSocket-based updates for sub-second latency
  • Real-time telemetry cards with visual trend indicators
  • System status monitoring with service health checks

Historical Data Analysis

  • Historical telemetry storage with 1000+ data points
  • Chart time range controls (5min, 10min, 30min, 1hour)
  • Data export functionality (CSV/JSON formats)
  • Roast session analysis and profiling

Control Interface

  • Manual heater control with PWM percentage
  • Variable fan speed control (0-255 PWM)
  • Control mode switching (Manual/Auto PID)
  • Emergency stop functionality
  • Keyboard shortcuts for quick control

Advanced Features

  • Responsive design for desktop and mobile
  • Toast notifications for alerts and status updates
  • Connection resilience with automatic reconnection
  • Performance optimized for high-frequency data

πŸ†• Recent Updates

v1.0.0 - Latest (September 2024)

  • πŸ› Fixed: Refresh button functionality in status section - resolved JavaScript showToast reference error
  • πŸ“Š Improved: Chart.js time axis display - fixed year range issue (1975-2025) with proper timestamp handling
  • πŸŽ›οΈ Enhanced: Auto mode setpoint controls - added input field and set button for PID temperature control
  • πŸ“± Responsive: Fixed "Latest Readings" section layout - improved grid width for better readability
  • βœ… Verified: End-to-end control system working - dashboard β†’ bridge β†’ ESP32 confirmed functional
  • 🧹 Cleaned: Removed test files and fixed all compilation warnings for production readiness

πŸ—οΈ Architecture

Hybrid Communication Strategy

  • Primary: WebSocket connection to bridge for real-time data
  • Secondary: REST API calls for historical data and status
  • Fallback: HTTP polling when WebSocket unavailable

Technology Stack

  • Backend: Rust with Axum web framework
  • Templates: Askama HTML templating
  • WebSocket: Tokio-tungstenite for real-time communication
  • Frontend: Vanilla JavaScript with Chart.js
  • Styling: Custom CSS with responsive design
  • HTTP Client: Reqwest for bridge API integration

πŸ“‹ Prerequisites

  • Rust 1.70+ with Cargo
  • Coffee Roaster Bridge running and accessible
  • Modern web browser with WebSocket support

πŸš€ Quick Start

1. Clone and Build

git clone https://github.com/yourusername/coffee-roaster-dashboard
cd coffee-roaster-dashboard

# Build in release mode for best performance
cargo build --release

2. Run the Dashboard

# Run with default settings (connects to localhost:8080 bridge)
cargo run --release

# Or run with custom bridge connection
cargo run --release -- \
  --bridge-api-url "http://192.168.1.100:8080" \
  --bridge-websocket-url "ws://192.168.1.100:8081" \
  --port 3000

3. Access the Dashboard

Open your web browser and navigate to:

  • Dashboard: http://localhost:3000
  • System Status: http://localhost:3000/api/status

βš™οΈ Configuration

Command Line Options

Option Default Description
--port 3000 Dashboard web server port
--bridge-api-url http://localhost:8080 Bridge REST API base URL
--bridge-websocket-url ws://localhost:8081 Bridge WebSocket URL
--debug false Enable debug logging

Example Configurations

Local Development

cargo run -- --debug --port 3000

Production Deployment

cargo run --release -- \
  --port 80 \
  --bridge-api-url "https://roaster-api.example.com" \
  --bridge-websocket-url "wss://roaster-ws.example.com"

Multiple Roaster Setup

# Roaster 1
cargo run --release -- --port 3001 --bridge-websocket-url "ws://roaster1:8081"

# Roaster 2  
cargo run --release -- --port 3002 --bridge-websocket-url "ws://roaster2:8081"

πŸŽ›οΈ Dashboard Interface

Main Dashboard Layout

Temperature Cards

  • Bean Temperature: Primary roasting temperature with trend indicator
  • Environment Temperature: Chamber air temperature
  • Setpoint: Target temperature for PID control
  • Rate of Rise: Temperature change velocity with status indicator

Live Charts

  • Temperature Profile: Real-time temperature curves with time range controls
  • Rate of Rise Chart: ROR visualization with fill area

Control Panel

  • Heater Control: Enable/disable and PWM percentage control
  • Fan Control: Variable speed control (0-255 PWM)
  • Control Mode: Manual vs Auto (PID) mode selection
  • Emergency Stop: Immediate safety shutdown

System Status

  • Bridge Status: Connection health and version info
  • Service Status: MQTT, Modbus, WebSocket, Serial service states
  • Performance Metrics: Message counts and system statistics
  • Optimization Status: Performance feature indicators

Keyboard Shortcuts

Key Action
M Switch to Manual mode
A Switch to Auto (PID) mode
H Toggle heater enable
Space Pause/Resume data updates
Esc (2x) Emergency stop (double-tap protection)

πŸ“Š Data Visualization

Chart Features

  • Real-time updates via WebSocket
  • Historical data loading for context
  • Interactive tooltips with precise values
  • Time range controls for zoom levels
  • Responsive scaling for different screen sizes

Chart Configuration

// Update chart time range (seconds)
dashboard.charts.updateTimeRange(1800); // 30 minutes

// Get chart statistics
const rorStats = dashboard.charts.getRORStatistics();
console.log('Current ROR:', rorStats.current);
console.log('Average ROR:', rorStats.average);

Data Export

  • CSV format for spreadsheet analysis
  • JSON format for programmatic processing
  • Configurable data points (1-10,000 entries)
  • Timestamp-based exports for specific time ranges

πŸ”Œ Integration

WebSocket API

The dashboard connects to the bridge WebSocket for real-time data:

Outgoing Messages (Dashboard β†’ Bridge)

// Request current telemetry data
{ "type": "request_current_data" }

// Heartbeat ping
{ "type": "ping", "timestamp": 1699123456 }

Incoming Messages (Bridge β†’ Dashboard)

// Real-time telemetry update
{
  "type": "telemetry",
  "data": {
    "beanTemp": 185.5,
    "envTemp": 145.2,
    "rateOfRise": 12.5,
    // ... full telemetry object
  },
  "timestamp": 1699123456
}

// Heartbeat response
{ "type": "pong", "timestamp": 1699123456 }

REST API Integration

The dashboard uses the bridge REST API for:

  • Initial data loading: /api/data, /api/status
  • Historical data: /api/history?limit=300
  • System information: /api/metrics, /api/registers

Custom Integration Example

// Access dashboard components programmatically
const dashboard = window.dashboard;

// Add custom telemetry handler
dashboard.websocket.onmessage = (data) => {
  if (data.type === 'telemetry') {
    // Custom processing
    console.log('Bean temp:', data.data.beanTemp);
  }
};

// Send custom control commands
dashboard.sendWebSocketMessage({
  type: 'custom_command',
  parameter: 'setpoint',
  value: 200
});

πŸ”§ Development

Project Structure

coffee-roaster-dashboard/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs              # Main application and routing
β”‚   β”œβ”€β”€ models.rs            # Data structures and types
β”‚   β”œβ”€β”€ bridge_client.rs     # HTTP client for bridge API
β”‚   └── websocket.rs         # WebSocket client management
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ dashboard.html       # Main dashboard template
β”‚   └── api_status.html      # Status page template
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ css/dashboard.css    # Dashboard styling
β”‚   └── js/
β”‚       β”œβ”€β”€ dashboard.js     # Main dashboard controller
β”‚       β”œβ”€β”€ charts.js        # Chart management
β”‚       β”œβ”€β”€ controls.js      # Control interface
β”‚       └── websocket.js     # WebSocket connection handling
└── Cargo.toml              # Rust dependencies

Building from Source

# Development build
cargo build

# Release build with optimizations
cargo build --release

# Run tests
cargo test

# Check code formatting
cargo fmt --check

# Run clippy linter
cargo clippy

Adding Custom Features

Custom Chart Types

// Add new chart data structure
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CustomChartData {
    pub timestamp: u64,
    pub custom_metric: f64,
}

// Add route handler
async fn custom_chart_handler(State(state): State<AppState>) -> impl IntoResponse {
    // Implementation
}

Custom WebSocket Messages

// Handle custom message types
dashboard.handleWebSocketMessage = (data) => {
  switch (data.type) {
    case 'custom_data':
      this.handleCustomData(data);
      break;
    // ... existing cases
  }
};

πŸ“± Mobile Support

Responsive Design

  • Adaptive layouts for phones and tablets
  • Touch-friendly controls with proper sizing
  • Optimized charts for small screens
  • Collapsible sections for better mobile UX

Mobile-Specific Features

  • Swipe gestures for chart navigation
  • Haptic feedback for control interactions
  • Landscape mode optimization
  • PWA capabilities for app-like experience

πŸš€ Deployment

Standalone Deployment

# Build optimized release
cargo build --release

# Run on production port
./target/release/coffee-roaster-dashboard --port 80

Docker Deployment

FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/coffee-roaster-dashboard /usr/local/bin/
COPY --from=builder /app/templates /app/templates
COPY --from=builder /app/static /app/static
WORKDIR /app
EXPOSE 3000
CMD ["coffee-roaster-dashboard"]

Reverse Proxy Configuration

Nginx

server {
    listen 80;
    server_name roaster-dashboard.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket upgrade handling
    location /ws {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 86400;
    }
}

πŸ” Monitoring & Debugging

Debug Mode

# Enable debug logging
cargo run -- --debug

# View detailed WebSocket messages
RUST_LOG=debug cargo run

Browser Console Commands

// WebSocket connection info
wsDebug.getState()

// Force WebSocket reconnection
wsDebug.reconnect()

// Send test ping
wsDebug.ping()

// Get chart data
dashboard.charts.exportChartData('json')

Performance Monitoring

// Dashboard performance metrics
console.log('Chart update rate:', dashboard.charts.updateCount);
console.log('WebSocket latency:', dashboard.websocket.lastPongTime - dashboard.websocket.lastPingTime);

πŸ› οΈ Troubleshooting

Common Issues

Dashboard Won't Connect to Bridge

# Check bridge connectivity
curl http://localhost:8080/api/status

# Verify WebSocket endpoint
wscat -c ws://localhost:8081

# Check dashboard logs
cargo run -- --debug

Charts Not Updating

  1. Check WebSocket connection status in browser console
  2. Verify bridge is publishing telemetry data
  3. Check for JavaScript errors in browser dev tools
  4. Confirm dashboard is not paused

High Memory Usage

  1. Reduce chart history points: dashboard.charts.maxDataPoints = 100
  2. Clear chart data: dashboard.charts.clearCharts()
  3. Check for memory leaks in browser dev tools
  4. Restart dashboard application

Performance Optimization

Client-Side

  • Reduce chart update frequency for slower devices
  • Limit historical data points loaded
  • Use chart animation: none for better performance
  • Enable chart data decimation for large datasets

Server-Side

  • Increase WebSocket buffer sizes
  • Use release build for production
  • Monitor memory usage with htop
  • Consider connection pooling for multiple clients

πŸ“ API Reference

Dashboard Internal API

DashboardCharts Class

// Create charts instance
const charts = new DashboardCharts();

// Add telemetry data point
charts.addTelemetryPoint(telemetryData);

// Load historical data
charts.loadHistoricalData(historyArray);

// Get chart statistics
const stats = charts.getRORStatistics();

DashboardControls Class

// Create controls instance
const controls = new DashboardControls();

// Set heater PWM (0-100%)
controls.setHeaterPWM(75);

// Set fan speed (0-255)
controls.setFanPWM(180);

// Change control mode (0=manual, 1=auto)
controls.setControlMode(1);

WebSocket Message Types

Dashboard β†’ Bridge

{
  "type": "request_current_data"  // Request latest telemetry
}

{
  "type": "ping",                 // Heartbeat ping
  "timestamp": 1699123456
}

Bridge β†’ Dashboard

{
  "type": "telemetry",            // Real-time data update
  "data": { /* TelemetryData */ },
  "timestamp": 1699123456
}

{
  "type": "pong",                 // Heartbeat response
  "timestamp": 1699123456
}

🀝 Contributing

Development Setup

  1. Clone the repository
  2. Install Rust 1.70+
  3. Run cargo build to install dependencies
  4. Start development server: cargo run -- --debug
  5. Access dashboard at http://localhost:3000

Code Style

  • Follow Rust standard formatting: cargo fmt
  • Lint with Clippy: cargo clippy
  • Write tests for new features: cargo test
  • Document public APIs with rustdoc comments

Feature Requests

  • Real-time alerts and notifications
  • Roast profile templates and automation
  • Data analytics and machine learning integration
  • Multi-roaster fleet management
  • Mobile app companion

πŸ“„ License

This project is licensed under MIT OR Apache-2.0. See LICENSE files for details.

πŸ†˜ Support

  • Issues: Report bugs and feature requests via GitHub issues
  • Documentation: Check this README and inline code comments
  • Performance: Use browser dev tools and Rust profiling tools
  • Integration: Refer to bridge API documentation

Version: 1.0.0
Rust Version: 1.70+
Real-time Updates: βœ…
Mobile Responsive: βœ…
Production Ready: βœ…

About

A dashboard to control fluid-bed coffee roaster. The backend is Rust.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors