ScooterCam Wave Height – Layered Views

Version: 3.0
Author: ScooterCam
For: ScooterCam.net

Clean, discrete layers for buoy observations and forecast models – no more mixing yesterday’s data!

🎯 Why Layered Views?

The Problem with Hybrid

  • Forecast data was bleeding into yesterday
  • Timezone confusion between data sources
  • Hard to see which data is which
  • Mixed data = messy debugging

The Solution: Separate Layers

Buoy layer = Past 48 hours of real observations
Forecast layer = Next 48 hours of predictions
No mixing = No timezone confusion
Clear data source = Easy debugging


🌊 Three Shortcodes, Three Use Cases

1.
Loading buoy data...
– Buoy Observations Only

Shows: Past 48 hours of real buoy measurements
When to use: Historical data, validation, actual conditions
Data source: NDBC Buoy 45168 (South Haven)

Loading buoy data...

24

Loading buoy data...

72

Loading buoy data...
[wave_buoy]
[wave_buoy hours="24"]  // Last 24 hours only
[wave_buoy hours="72"]  // Last 3 days

Features:

  • ✅ Real measurements from 12 miles offshore
  • ✅ Current wave stats (height, period, direction)
  • ✅ Solid blue line
  • ✅ Seasonal (April-October)

2.
Loading forecast data...
– Forecast Only

Shows: Next 48 hours of wave predictions
When to use: Planning, future conditions
Data source: Open-Meteo marine model

Loading forecast data...
Loading forecast data...
Loading forecast data...
[wave_forecast]
[wave_forecast hours="24"]  // Next 24 hours
[wave_forecast hours="72"]  // Next 3 days

Features:

  • ✅ Future predictions from now forward
  • ✅ No historical/yesterday data
  • ✅ Dashed orange line
  • ✅ Year-round availability

3.
Loading buoy data...
Loading forecast data...
– Tabbed Interface

Shows: Both views with tab switcher
When to use: Complete conditions page
Data sources: Both buoy + forecast

Loading buoy data...
Loading forecast data...
[wave_layered]

Features:

  • ✅ Tab 1: Buoy Observations (real data)
  • ✅ Tab 2: Forecast Model (predictions)
  • ✅ Single shortcode, both views
  • ✅ Easy switching between layers

📦 Installation

File Structure

/wp-content/plugins/scootercam-wave-layered/
├── wave-height-layered.php
├── js/
│   └── wave-layered-chart.js
└── README.md

Upload & Activate

  1. Upload to /wp-content/plugins/scootercam-wave-layered/
  2. WordPress Admin → Plugins → Activate
  3. Use any of the three shortcodes!

🎨 Visual Examples

Buoy Layer (Past Data)

Yesterday ←──────────────────── Now
        48h of observations
        Solid blue line
        Real measurements

Forecast Layer (Future Data)

        Now ────────────────────→ +48h
        48h of predictions
        Dashed orange line
        Model forecasts

Layered View (Both)

┌─────────────────────────┐
│ 🌊 Buoy | 📊 Forecast  │ ← Tabs
├─────────────────────────┤
│                         │
│   [Active layer here]   │
│                         │
└─────────────────────────┘

🔧 How It Works

Separate AJAX Endpoints

Buoy Endpoint:

wp_ajax_get_buoy_data
→ Fetches NDBC 45168
→ Returns past X hours
→ Cached 30 minutes

Forecast Endpoint:

wp_ajax_get_forecast_data  
→ Fetches Open-Meteo
→ Returns ONLY future data
→ Cached 1 hour

No More Timezone Issues!

Old hybrid approach:

// Mixed buoy (UTC) + forecast (Chicago)
// Comparison: time() vs strtotime()
// Result: Yesterday bleeds through ❌

New layered approach:

// Buoy: Shows past only
// Forecast: Shows future only
// No comparison needed ✅

🎯 Usage Examples

Main Conditions Page

<h1>Lake Michigan Wave Conditions</h1>

<h2>Current Observations</h2>
Loading buoy data...

<h2>48-Hour Forecast</h2>

Loading forecast data...

Tabbed Interface

<h1>Wave Data</h1>
Loading buoy data...
Loading forecast data...

Sidebar Widget

<h3>Current Waves</h3>
Loading buoy data...

Blog Post Embed

<p>Check today's wave forecast:</p>
Loading forecast data...

Comparison View

<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
  <div>
    <h3>What Just Happened</h3>
Loading buoy data...

</div> <div> <h3>What’s Coming</h3>

Loading forecast data...

</div> </div>


📊 Data Specifications

Buoy Layer (45168)

Location: 42.397°N, 86.331°W
Distance: 12 miles west of South Haven
Active: April – October
Update: Hourly

Returns:

  • Wave height (meters)
  • Wave period (seconds)
  • Wave direction (degrees)
  • Timestamps in Chicago timezone

Behavior when offline:

  • Shows friendly message
  • Explains seasonal deployment
  • No chart displayed

Forecast Layer

Location: 42.5593°N, 86.2359°W (South Haven)
Source: Open-Meteo marine model
Active: Year-round
Update: Every 6 hours

Returns:

  • Wave height forecast (meters)
  • Wave period forecast (seconds)
  • Wave direction forecast (degrees)
  • ONLY future timestamps

Filtering:

// Server-side filter
if ($timestamp <= $nowTimestamp) {
    continue; // Skip past data
}

// Guaranteed: Only shows future

🐛 Troubleshooting

Issue: Forecast Still Shows Yesterday

This shouldn’t happen anymore! But if it does:

  1. Clear transients:
wp transient delete openmeteo_forecast
  1. Check server time:
echo date('Y-m-d H:i:s T');  // Should match reality
  1. Verify timezone:
WordPress Admin → Settings → General
Timezone: America/Chicago
  1. Hard refresh:
Ctrl+Shift+R (Windows/Linux)
Cmd+Shift+R (Mac)

Issue: Buoy Shows “Seasonal” Message

This is normal November-April!

The South Haven buoy is physically removed from the water in fall and redeployed in spring. This is expected behavior.

To verify it’s actually off-season:

  • Check: https://www.ndbc.noaa.gov/station_page.php?station=45168
  • Look for recent data (should be none)

Issue: Charts Not Loading

  1. Check browser console (F12):
// Look for errors like:
"Failed to fetch"
"Chart is not a constructor"
"waveLayeredData is not defined"
  1. Verify AJAX endpoints:
# Test buoy endpoint
curl -X POST https://scootercam.net/wp-admin/admin-ajax.php \
  -d "action=get_buoy_data&nonce=..."

# Test forecast endpoint  
curl -X POST https://scootercam.net/wp-admin/admin-ajax.php \
  -d "action=get_forecast_data&nonce=..."
  1. Clear ALL caches:
wp transient delete --all
wp cache flush

🔄 Migration from Hybrid

If Currently Using Hybrid Plugin

Option 1: Run Both (Recommended)

  • Keep hybrid plugin active
  • Install layered plugin
  • Test layered on separate page
  • Gradually migrate

Option 2: Replace Entirely

Old: [wave_hybrid_chart]
New: [wave_layered]

Option 3: Separate Displays

Old: [wave_hybrid_chart]
New: [wave_buoy] + [wave_forecast]

Shortcode Conversion

Old HybridNew Layered
[wave_hybrid_chart]
Loading buoy data...
Loading forecast data...
[wave_hybrid_chart show_buoy="true" show_forecast="false"]
Loading buoy data...
[wave_hybrid_chart show_buoy="false" show_forecast="true"]
Loading forecast data...

🎨 Customization

Tab Colors

.wave-tab.active {
    background: #10b981; /* Green instead of blue */
}

.wave-tab-badge {
    background: rgba(255,255,255,0.3);
}

Chart Heights

.wave-chart-wrapper {
    height: 500px !important; /* Taller charts */
}

Buoy Chart Color

// In wave-layered-chart.js
borderColor: '#0ea5e9',  // Sky blue instead of blue

Forecast Chart Color

// In wave-layered-chart.js
borderColor: '#8b5cf6',  // Purple instead of orange

📈 Performance

Cache Strategy

Buoy data: 30 minutes

  • Real-time not critical
  • Reduces NDBC server load
  • Balances freshness vs performance

Forecast data: 1 hour

  • Model updates every 6 hours
  • No need for frequent checks
  • Significant performance gain

Load Times

Single layer (buoy or forecast):

  • Initial load: <1 second
  • AJAX call: 1-2 seconds
  • Chart render: <100ms
  • Total: 2-3 seconds

Layered view (tabs):

  • Both layers load on page load
  • Slightly slower: 3-4 seconds
  • But switching tabs is instant

✅ Advantages Over Hybrid

Data Integrity

  • ✅ No mixed timeframes
  • ✅ No timezone confusion
  • ✅ Clear data boundaries
  • ✅ Easy validation

Debugging

  • ✅ Simple data flow
  • ✅ Separate endpoints
  • ✅ Clear error messages
  • ✅ Isolated failures

User Experience

  • ✅ Choose what to see
  • ✅ Understand data source
  • ✅ No confusing overlaps
  • ✅ Clean visual separation

Maintenance

  • ✅ Easier to update
  • ✅ Independent caching
  • ✅ Clearer code
  • ✅ Better testability

🆚 When to Use Which

Use
Loading buoy data...
when:

  • ✅ Want actual observed data
  • ✅ Validating forecast accuracy
  • ✅ Showing recent trends
  • ✅ It’s buoy season (Apr-Oct)

Use
Loading forecast data...
when:

  • ✅ Planning future activities
  • ✅ Need predictions
  • ✅ It’s off-season (Nov-Mar)
  • ✅ Want clean forward-looking data

Use
Loading buoy data...
Loading forecast data...
when:

  • ✅ Want complete picture
  • ✅ Professional display
  • ✅ Main conditions page
  • ✅ Let users choose view

📝 Best Practices

Page Layout

Good:

<h1>Wave Conditions</h1>
Loading buoy data...
Loading forecast data...

<!– Single comprehensive view –>

Also Good:

<h2>Recent Observations</h2>
Loading buoy data...

<h2>Upcoming Forecast</h2>

Loading forecast data...

<!– Clear separation –>

Avoid:

[wave_layered]
Loading buoy data...

Loading forecast data...
<!– Too much! Pick one approach –>

Cache Management

During testing:

# Clear before each test
wp transient delete openmeteo_forecast
wp transient delete ndbc_buoy_45168

In production:

# Let caches work normally
# 30min/1hr is good balance

Seasonal Messaging

April-October (Active):

  • Promote buoy data
  • Show observed stats
  • Highlight “real” measurements

November-March (Inactive):

  • Default to forecast
  • Explain seasonal nature
  • Show “next deployment” date

🎉 Success Checklist

After deploying layered views:

  • [ ] All three shortcodes work
  • [ ] Buoy shows past data only
  • [ ] Forecast shows future data only
  • [ ] No “yesterday” in forecast
  • [ ] Tabs switch properly (layered view)
  • [ ] Current stats update (buoy view)
  • [ ] Seasonal message shows correctly
  • [ ] Mobile responsive
  • [ ] No console errors
  • [ ] Caching works

📞 Support

Quick Diagnostics

Test buoy data:

curl https://www.ndbc.noaa.gov/data/realtime2/45168.txt | head -5

Test forecast API:

curl "https://marine-api.open-meteo.com/v1/marine?latitude=42.5593&longitude=-86.2359&hourly=wave_height&timezone=America/Chicago&forecast_days=2" | jq

Check WordPress transients:

wp transient list | grep -E 'buoy|forecast'

🏆 Summary

Layered = Better than Hybrid because:

  1. Cleaner separation – No data mixing
  2. No timezone issues – Each layer independent
  3. Easier debugging – Isolated data flows
  4. Better UX – Users choose what to see
  5. More reliable – Simpler = fewer bugs

Three shortcodes for every use case:

  • Loading buoy data...
    → Past observations
  • Loading forecast data...
    → Future predictions
  • Loading buoy data...
    Loading forecast data...
    → Both in tabs

The forecast layer guarantees future-only data! 🎯


Made with 🌊 for accurate wave forecasting