# NGON Status Dashboard - New Implementation

## Overview
This is the new NGON Mining Status Dashboard, a real-time web interface for monitoring mining operations across multiple sites. It displays live data for generators, pods, miners, and various operational metrics.

## Architecture

### Main Files
- **`index.py`** - Main entry point, serves the HTML structure
- **`status_core.js`** - Core application logic, WebSocket handling, page building
- **`styles.css`** - All styling including mobile responsiveness
- **Modal files** - Individual modal implementations for detailed views

### Data Flow
1. **Initial Load**: Fetches from `/api/status` (main status API)
2. **Real-time Updates**: WebSocket connection for live data streaming
3. **Modal Data**: Separate API calls when modals are opened
4. **Pool Data**: Foundry API integration via `pool_data_cgi.py`

## API Endpoints

### Primary Data Source
- **`/api/status`** - Main status API providing:
  - Site and generator data (`.sites`)
  - Summary metrics (`.summary`) 
  - Weather data (`.metadata.weather`)
  - Log data (`.logs.powercontrol[]`, `.logs.miner_monitor[]`)
  - Miner types configuration (`.misc.miner_types`)

### Specialized Endpoints
- **`pool_data_cgi.py`** - Foundry pool hashrate data for Performance modal
- **`/api/all_pods_hashrate`** - Historical hashrate data for charts
- **`/api/all_miners_history`** - Historical miner status data for charts

### Status API Access (Local Development)

For local connections to the status API (HTTP on port 5050):

```bash
# Health check
curl http://localhost:5050/health

# Full status dump
curl http://localhost:5050/api/status

# Get all sites
curl http://localhost:5050/api/query/sites

# Get specific site data
curl http://localhost:5050/api/query/sites/Alpha

# Get generator data for a site
curl http://localhost:5050/api/query/sites/Alpha/generator_groups

# Get specific generator group
curl http://localhost:5050/api/query/sites/Alpha/generator_groups/Alpha\ 1-2

# Get generator field
curl http://localhost:5050/api/query/sites/Alpha/generator_groups/Alpha\ 1-2/generators/22-24-229/power_avg

# Get metadata (weather, etc.)
curl http://localhost:5050/api/query/metadata

# Get peplinks
curl http://localhost:5050/api/peplinks
```

**Examples with JSON parsing:**
```bash
# Get all site names
curl -s http://localhost:5050/api/query/sites | jq '.value | keys'

# Get Alpha site generator group data
curl -s http://localhost:5050/api/query/sites/Alpha | jq '.value.generator_groups'

# Check specific generator
curl -s http://localhost:5050/api/query/sites/Alpha | jq '.value.generator_groups["Alpha 1-2"].generators["22-24-229"]'
```

**Important Connection Notes:**
- **Local CLI access**: Use HTTP (`http://localhost:5050`)
- **Browser/web access**: Must use HTTPS (`https://localhost:5050`) due to security restrictions
- **External access**: HTTPS on the same port for remote connections

## Layout Structure

### Column Layout (Desktop)
1. **Peps/Pods** (15% width) - Pod status, hashrates, sleep targets
2. **Generators-TX** (flexible) - Texas generators  
3. **Generators-ND** (flexible) - North Dakota generators
4. **Generators-GW** (flexible) - GN/Will generators
5. **Summary** (20% width) - Metrics and special sections

### Sites Overview
Top section displaying site cards with generator/pod status icons

### Mobile Responsiveness
- Columns stack vertically on screens ≤768px
- Each column becomes full width (100%)
- Optimized spacing and font sizes

## Special Sections (Summary Column)

### 1. Hashrate Summary
- Clickable to open Performance modal
- Shows total hashrate with progress bar
- Displays TX/ND breakdown

### 2. Power Summary  
- Clickable to open Power modal
- Shows total power consumption
- Displays available capacity (unused MW and miner count)
- Shows efficiency calculation (J/TH) - watts per terahashes

### 3. Miners Summary
- Clickable to open Miners modal
- Shows hashing/total miners with breakdown
- Includes Zero Hash, Sleeping, Offline counts

### 4. Miner Control
- **3-column layout**: Sleeping | Reboot Off | Sleep Off
- Reads live pod data from status API
- Shows pods with sleeping miners (miners_sleeping > 0) and disabled auto-features

### 5. Weather
- Reads from `.metadata.weather` in status API
- Displays temp, high/low, conditions, humidity for each location
- Formatted display with location names in green

### 6. OOS / Spares
- **2-column layout**: Out of Service | Spares
- Reads from special sites: "Out of Service" and "Spares"
- Shows generators in each category

### 7. Power Control Log
- Reads from `.logs.powercontrol[]`
- Format: `• date time pod count user reason`
- Color-coded actions: Green (wake), Red (sleep), Yellow (reboot)
- Displays newest entries at bottom

### 8. Miner Monitor Log  
- Reads from `.logs.miner_monitor[]`
- Same format as Power Control Log
- Color-coded: Yellow (reboot), Purple (fix pools)
- Displays newest entries at bottom

## Site Configuration

### Generator Column Assignment
```javascript
this.siteConfig = {
    'Generators-ND': ['Nate', 'Dan'],
    'Generators-GW': ['GN', 'Will'], 
    'Generators-TX': [] // Everything else (default)
};
```

### Excluded Sites
```javascript
this.excludedSites = ['Out of Service', 'Spares'];
```
These sites are excluded from normal operational views but accessible for OOS/Spares section.

## Generator Group Capacity Display

### Pod Capacity Calculations
Each generator group header shows capacity information on the right side in grey text:
- **Unused Capacity**: Available power capacity and estimated miner count that could be added
- **Over Capacity**: Amount generators are exceeding their 320kW target
- **Format**: `"Unused Capacity: 45.2 kW (13 miners)"` or `"Over Capacity: 12.3 kW (3 miners)"`

### Calculation Logic
- Uses 320kW as target capacity per generator
- Only includes non-stuck generators (generators with recent data updates)
- Determines predominant miner type in the group's pods
- Uses actual spec_wattage from miner types configuration
- Calculates: `Available Capacity = (Running Gens × 320kW) - Current Power Output`
- Estimates miners: `Miner Count = Available Capacity ÷ Spec Wattage per Miner`

### Stuck Generator Detection
- Generators are considered "stuck" if status shows "Running" but data is >30 minutes old
- Stuck generators are excluded from capacity calculations to ensure accuracy
- Generator status icons show: Green (online), Red (offline), Yellow/Orange (stuck)

## Miner Types Configuration

### Data Structure
```javascript
{
    "M60": {
        "spec_hashrate": 180,  // TH/s
        "spec_wattage": 3400   // Watts
    },
    "JPro": {
        "spec_hashrate": 100,
        "spec_wattage": 3100
    },
    "XP": {
        "spec_hashrate": 140,
        "spec_wattage": 3200
    }
}
```

### Braiins Firmware Support
- Miners with Braiins firmware are identified with `_B` suffix (e.g., `JPro_B`, `XP_B`)
- Braiins miners report sleep state directly via API for more reliable tracking
- The display uses base type for capacity calculations (strips `_B` suffix)

### Configuration Management
- **Source**: `/opt/ngon/config/master_config.json` under `misc.miner_types`
- **Site Manager**: Allows editing both spec_hashrate and spec_wattage
- **Status API**: Loads and serves miner types configuration in `/api/status` response
- **Usage**: Pod capacity calculations and efficiency metrics

## Data Structure Examples

### Pod Data Structure
```javascript
{
    "stats": {
        "hashrate": 4250000000000000,  // TH/s (convert to PH/s by /1000)
        "miners_hashing": 150,
        "miners_installed": 200,
        "miners_sleeping": 25,  // Count of miners with mining_state == 'sleeping'
        "miners_offline": 20,
        "miners_zero_hash": 5
    },
    "auto_reboot_enabled": true,
    "auto_sleep_enabled": false,
    "miner_type": "M60"
}
```

### Weather Data Structure
```javascript
{
    "North Dakota": {
        "temp": 5.0,
        "high": 21,
        "low": 12, 
        "humidity": 71.5,
        "weather": "Clear",
        "last_updated": "2025-12-10T19:22:18.195369+00:00"
    }
}
```

### Log Entry Structure
```javascript
{
    "action": "stop_mining",  // resume_mining, stop_mining, reboot, fix_pools
    "count": 75,
    "pod": "Ellyson 1",
    "reason": "Low gas", 
    "timestamp": "2025-12-09 17:40:46",
    "user": "KB"
}
```

## Modal System

### Performance Modal (`status_performance_modal.js`)
- Shows current hashrate overview with progress bar
- Site hashrate grid with Foundry pool data comparison
- 24-hour historical hashrate charts by site
- Fetches pool data from `pool_data_cgi.py` when opened

### Power Modal (`status_power_modal.js`) 
- Power consumption overview and charts
- Generator power details and historical data

### Miners Modal (`status_miners_modal.js`)
- Current miner status breakdown (Hashing, Sleeping, Zero Hash, Offline)
- 4 historical charts: Miners Hashing, Sleeping, Zero Hash, Offline
- Summary stats below progress bar for consistency

### Individual Modals
- Pod hashrate modal for individual pod details
- Generator modal for individual generator details  
- Site modal for site-level overview

## Styling System

### CSS Organization
- **Base styles** - Typography, colors, layout
- **Component styles** - Status dots, progress bars, modals
- **Special sections** - Log entries, weather display
- **Mobile responsive** - Media queries for stacking

### Color Scheme
- **Green (#00ff00)** - Online status, positive metrics, wake actions
- **Red (#ff4444/#ff6666)** - Offline status, errors, sleep actions, zero hash
- **Yellow (#ffff00)** - Warning status, reboot actions
- **Blue (#4a9eff)** - Sleep targets, low power indicators
- **Purple (#aa66ff)** - Fix pools actions
- **Grey (#888)** - Secondary text, disabled items

### Status Colors
```css
.online { background-color: green; }
.offline { background-color: red; }
.stuck { background-color: orange; }
.zero-hash { color: #ff4444; }
.sleep-target { color: #4a9eff; }
```

### Building a new page so it matches the others

Four traps have each cost real debugging time. Copy `gen_manager.py` or
`gen_service.py` rather than hand-rolling a page; if you do hand-roll, read this.

**1. `generate_dropdown_css()` contains its own `.header` rule** — background
`#1a1a1a`, padding `20px`, border-bottom `2px solid #2a2a2a`. It is normally
injected *after* your own `<style>` content, and at equal specificity the later
rule wins. Your header styling is silently overwritten and the floating box
flattens into a flush bar. **Mark every `.header` property `!important`**, which
is why `gen_manager.py` does — that is the load-bearing part of that file, not
noise. Symptom: edits to the header appear to do nothing at all.

**2. `generate_dropdown_html()` returns only the inner links.** They must sit
inside the wrapper, and the page title is the hover trigger:

    <div class="dropdown">
      <h1 class="dropdown-title">Page Title</h1>
      <div class="dropdown-content">  ...generate_dropdown_html(access)...  </div>
    </div>

Without the wrapper (and `generate_dropdown_css()`), all ~32 nav links render
inline across the header.

**2b. `generate_dropdown_css()` ALSO returns bare CSS with no `<style>` tags.**
It must be printed *inside* your `<style>` block (that is why `gen_manager.py`
opens `<style>`, prints its own rules, then `print(generate_dropdown_css())`,
then continues). Placed in `<head>` on its own it styles nothing — so
`.dropdown-content` never gets its `display: none` and all ~32 nav links show
as a wall of text — and the stylesheet itself renders visibly on the page.
Symptom is identical to trap 2, so check this one first: if the links are
inside the wrapper and *still* visible, the CSS never applied.

**3. `generate_dropdown_js()` returns BARE JavaScript with no `<script>` tags.**
Emit it inside a `<script>` block or the page displays
`// Mobile dropdown functionality ...` as visible text at the bottom.

**4. Do not set `font-size` on `.header h1`.** `.dropdown-title` styles it
(`2.2em`, `600`, `#00ff00`) but `.header h1` out-specifies it and silently
shrinks the heading.

**Base palette** (from `gen_manager.py` / `gen_service.py`, which match the
status page):

    body    font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto
            background:#1a1a1a; color:#e0e0e0; line-height:1.4
    th      background:#2a2a2a; color:#00ff00; border-bottom:2px solid #3a3a3a
    td      border-bottom:1px solid #2a2a2a;  tr:hover rgba(255,255,255,0.03)
    tfoot   border-top:2px solid #3a3a3a; font-weight:bold; color:#00ff00; background:#222
    buttons background:#2a2a2a; border:1px solid #3a3a3a; hover #333

**Python trap, unrelated to CSS but adjacent:** these pages print their HTML from
an f-string, so every literal CSS brace must be doubled — including braces inside
*comments*. A `/* ... { background:#111 } ... */` comment inside the f-string
raises `NameError: name 'background' is not defined` and the page serves zero
bytes with an HTTP 200.

Worth noting the duplication: each page re-declares the same base CSS. If a
shared `report_base.css` ever gets written, these rules belong in it.

## Real-time Data Handling

### WebSocket Connection
- Connects to status API WebSocket endpoint
- Receives incremental updates for efficiency
- Automatically reconnects on connection loss
- Applies updates to current data and rebuilds affected UI

### Data Rate Tracking
- Monitors incoming data volume (KB/s)
- Displays connection status in header
- Tracks data over 10-second window

### Update Strategy
- **Full rebuild** on initial load and major updates
- **Incremental updates** for real-time changes:
  - Pod updates (hashrate, miners, power) → Update pod display + summary
  - Generator updates (power, status) → Update generator display + summary  
  - Peplink updates → Update connectivity status
  - Log updates → Refresh log sections
  - Weather updates → Refresh weather section only
- **Modal refresh** when opening modals for latest data

### Update Categories Handled
- **pod**: Miner statistics (including miners_sleeping), hashrate
- **generator**: Power output, status changes
- **peplink**: Network connectivity status
- **logs**: Power control and miner monitor actions
- **weather**: Temperature and weather condition updates

## Display Formats

### Pods Column Display
```
<icon> Pod Name - hashing/installed (zero_hash)(sleeping) - hashrate
```
- Zero hash count in red (if > 0)
- Sleeping count in blue (if > 0) - miners with mining_state == 'sleeping'
- Hashrate in PH/s with 2 decimals

### Log Entry Display
```
• 12/10 14:18 Pod Name 75 User Reason
```
- Date as MM/DD, time as HH:MM
- Count (action) color-coded based on action type
- Chronological order (newest at bottom)

## Development Notes

### Key Functions
- **`buildPage()`** - Main page builder, calls all sub-builders
- **`buildSpecialSections()`** - Builds all special sections in summary column
- **`buildGeneratorColumns()`** - Builds all three generator columns with capacity info
- **`calculatePodCapacityInfo()`** - Calculates unused/over capacity for generator groups
- **`getGeneratorStatus()`** - Determines generator status including stuck detection
- **`updateMinerControl()`** - Reads live pod data for miner control settings
- **`updateWeather()`** - Formats weather data display (real-time updates)
- **`updateLogs()`** - Formats both log sections with color coding

### Mobile Considerations
- Uses `@media (max-width: 768px)` breakpoint
- Columns stack with `flex-wrap: wrap` and `flex: 0 0 100%`
- Reduced padding and font sizes for mobile optimization
- Maintains all functionality on mobile devices

### Future Maintenance
- **Lint/Typecheck**: Run linting before commits (commands in package.json if available)
- **API Changes**: Update data structure examples if API responses change
- **New Sites**: Add to `siteConfig` as needed for column assignment
- **Color Consistency**: Use existing CSS classes rather than inline styles
- **Modal Data**: Consider caching strategies for frequently opened modals

## Foundry Integration

### Pool Data Fetching
- **Endpoint**: `pool_data_cgi.py` 
- **Credentials**: Stored in CGI script (see `pool_sub_accounts` array)
- **API**: Uses Foundry's `subaccount_hashrate_hour` endpoint
- **Conversion**: Converts MH/s to PH/s (`/ 1000000`)
- **Display**: Shows as "Pool: X.XX PH/s" in grey under site hashrates

### Site Mapping
Pool data maps to sites using account names and site mappings in the CGI script.

## Testing
- **Real-time**: Test WebSocket reconnection by restarting status API
- **Mobile**: Test responsive design on various screen sizes
- **Modals**: Verify all modals load data and charts correctly
- **Sleeping Display**: Verify sleeping counts display in blue when miners_sleeping > 0
- **Logs**: Test that newest entries appear at bottom with correct colors
- **Capacity Info**: Verify capacity calculations appear when miner types are loaded

## Troubleshooting

### Common Issues

#### No Capacity Information in Generator Headers
- **Cause**: Miner types not loaded in status API
- **Check**: Browser console for "Miner types not available" warnings
- **Fix**: Restart status API service to reload miner types configuration
- **Verification**: Check `/api/status` endpoint includes `.misc.miner_types`

#### Efficiency Calculation Shows 0 J/TH
- **Cause**: No hashrate data or power data available
- **Check**: Verify pods have hashrate > 0 and generators show power output
- **Fix**: Wait for miner data collection or check field server connectivity

#### WebSocket Connection Issues
- **Symptoms**: "🔴 Connecting..." status, no real-time updates
- **Causes**: Status API not running, network connectivity, browser security
- **Fix**: Check status API service status, verify port 5050 accessibility
- **Browser**: Must use HTTPS for WebSocket connections in production

#### Generator Status Shows Incorrect Colors
- **Green**: Generator online and reporting recent data
- **Red**: Generator offline or status not "Running"
- **Yellow/Orange**: Generator stuck (shows "Running" but >30min old data)
- **Check**: Generator stats.last_update timestamp in API response

### Performance Optimization
- **Data Rate**: Monitor KB/s in header, high rates indicate frequent updates
- **Memory**: Page automatically refreshes every 5 minutes to prevent memory leaks
- **Updates**: Incremental updates preferred over full rebuilds
- **Debug Mode**: Set `this.debugMode = true` in StatusCore for detailed logging

### Configuration Dependencies
- **Status API**: Must be running and serving `/api/status` endpoint
- **Master Config**: Must include `misc.miner_types` with spec_wattage values
- **Site Manager**: Used to edit miner type specifications
- **Field Servers**: Provide miner data for capacity calculations