ws-dottie
Version:
Your friendly TypeScript companion for Washington State transportation APIs - WSDOT and WSF data with smart caching and React Query integration
554 lines (469 loc) • 21.6 kB
Markdown
# Weather APIs
This guide covers all weather-related APIs in WS-Dottie, providing comprehensive access to Washington State weather information, road conditions, and mountain pass status.
> **📚 Documentation Navigation**: [Documentation Index](../../INDEX.md) • [Getting Started](../../getting-started.md) • [API Guide](../api-guide.md)
## 🌤️ Overview
WS-Dottie provides access to three weather APIs that cover all aspects of Washington State weather and road condition information:
| API | Description | Key Features | Update Frequency |
|------|-------------|---------------|------------------|
| **WSDOT Weather Information** | Current weather conditions at monitoring stations | Temperature, precipitation, road conditions | Frequent (15m) |
| **WSDOT Weather Readings** | Detailed weather with surface/subsurface measurements | Advanced weather data, scientific measurements | Frequent (15m) |
| **WSDOT Weather Stations** | Weather station locations and metadata | Station locations, equipment information, coverage map | Static (weekly) |
## 🌡️ WSDOT Weather Information API
### API Overview
The WSDOT Weather Information API provides current weather conditions from monitoring stations throughout Washington State, including temperature, precipitation, visibility, and road conditions.
### Endpoint Groups
| Endpoint Group | Description | Cache Strategy |
|----------------|-------------|----------------|
| **weather-info** | Current atmospheric conditions from road weather stations | FREQUENT |
### Key Endpoints
#### Weather Information
- **getWeatherInformation**: Returns current weather conditions for all stations
- **Input**: No parameters required
- **Output**: Array of weather station information
- **Key Fields**:
- `StationID`: Unique station identifier
- `StationName`: Human-readable station name
- `Latitude`, `Longitude`: GPS coordinates
- `Temperature`: Current temperature in Fahrenheit
- `RelativeHumidity`: Humidity percentage
- `WindSpeed`: Wind speed in mph
- `WindDirection`: Wind direction in degrees
- `BarometricPressure`: Atmospheric pressure
- `Precipitation`: Precipitation measurement
- `Visibility`: Visibility distance in miles
- `RoadCondition`: Current road condition status
- `LastUpdated`: Timestamp of last update
- **getWeatherInformationByStationId**: Returns weather information for a specific station
- **Input**: `StationID` (integer) - Unique station identifier
- **Output**: Single weather station object with all fields above
- **getCurrentWeatherForStations**: Returns weather information for multiple specified stations
- **Input**: `StationList` (string) - Comma-separated list of station IDs
- **Output**: Array of weather station information for specified stations
- **searchWeatherInformation**: Returns historical weather information for a time range
- **Input**:
- `StationID` (integer) - Station identifier
- `SearchStartTime` (datetime) - Start of search range
- `SearchEndTime` (datetime) - End of search range
- **Output**: Array of historical weather information
### Common Use Cases
#### Weather Dashboard
```javascript
import { useWeatherInformation } from 'ws-dottie/wsdot-weather-information';
function WeatherDashboard() {
const { data: weather, isLoading, error } = useWeatherInformation();
// Group weather stations by region
const westernStations = weather?.filter(s => s.Latitude < 47.5);
const easternStations = weather?.filter(s => s.Latitude >= 47.5);
// Find stations with adverse conditions
const adverseConditions = weather?.filter(s =>
s.RoadCondition !== 'Clear' || s.Temperature < 32 || s.Visibility < 1
) || [];
return (
<div>
<h1>Washington Weather Conditions</h1>
{isLoading && <div>Loading weather data...</div>}
{error && <div>Error loading weather data: {error.message}</div>}
<div className="weather-summary">
<div className="region-summary">
<h2>Western Washington</h2>
<p>Stations: {westernStations?.length || 0}</p>
<p>Avg Temperature: {calculateAverage(westernStations, 'Temperature')?.toFixed(1)}°F</p>
</div>
<div className="region-summary">
<h2>Eastern Washington</h2>
<p>Stations: {easternStations?.length || 0}</p>
<p>Avg Temperature: {calculateAverage(easternStations, 'Temperature')?.toFixed(1)}°F</p>
</div>
</div>
<div className="adverse-conditions">
<h2>Adverse Conditions ({adverseConditions.length || 0})</h2>
{adverseConditions.map(station => (
<div key={station.StationID} className="adverse-station">
<h3>{station.StationName}</h3>
<p>Temperature: {station.Temperature}°F</p>
<p>Condition: {station.RoadCondition}</p>
<p>Visibility: {station.Visibility} miles</p>
</div>
))}
</div>
<div className="weather-regions">
<div className="weather-region">
<h2>Western Washington</h2>
{westernStations?.map(station => (
<div key={station.StationID} className="weather-station">
<h3>{station.StationName}</h3>
<p>Temperature: {station.Temperature}°F</p>
<p>Conditions: {station.RoadCondition}</p>
<p>Visibility: {station.Visibility} miles</p>
</div>
))}
</div>
<div className="weather-region">
<h2>Eastern Washington</h2>
{easternStations?.map(station => (
<div key={station.StationID} className="weather-station">
<h3>{station.StationName}</h3>
<p>Temperature: {station.Temperature}°F</p>
<p>Conditions: {station.RoadCondition}</p>
<p>Visibility: {station.Visibility} miles</p>
</div>
))}
</div>
</div>
</div>
);
}
// Helper function to calculate average values
function calculateAverage(stations, field) {
if (!stations || stations.length === 0) return 0;
const sum = stations.reduce((acc, station) => acc + (station[field] || 0), 0);
return sum / stations.length;
}
```
#### Travel Weather Map
```javascript
import { useWeatherInformation } from 'ws-dottie/wsdot-weather-information';
function TravelWeatherMap() {
const { data: weather, isLoading, error } = useWeatherInformation();
// Process data for map visualization
const weatherMapData = weather?.map(station => ({
id: station.StationID,
name: station.StationName,
location: [station.Latitude, station.Longitude],
temperature: station.Temperature,
conditions: station.RoadCondition,
icon: getWeatherIcon(station.RoadCondition)
})) || [];
// Group stations by road condition for map layers
const conditionGroups = weatherMapData.reduce((acc, station) => {
const condition = station.conditions;
if (!acc[condition]) acc[condition] = [];
acc[condition].push(station);
return acc;
}, {});
return (
<div>
<h1>Washington Weather Map</h1>
{isLoading && <div>Loading weather data...</div>}
{error && <div>Error loading weather data: {error.message}</div>}
<div className="weather-legend">
<h2>Road Conditions</h2>
{Object.keys(conditionGroups).map(condition => (
<div key={condition} className="legend-item">
<span className={`icon ${condition}`}></span>
<span>{condition}</span>
</div>
))}
</div>
<div className="weather-map">
{/* Render map with weather station markers */}
{weatherMapData.map(station => (
<div key={station.id} className="weather-marker">
<h3>{station.name}</h3>
<p>{station.temperature}°F</p>
<p>{station.conditions}</p>
</div>
))}
</div>
</div>
);
}
// Helper function to get weather icon based on condition
function getWeatherIcon(condition) {
const iconMap = {
'Clear': '☀️',
'Wet': '🌧',
'Snow': '❄️',
'Ice': '🧊',
'Fog': '🌫'
};
return iconMap[condition] || '🌡️';
}
```
## 🌡️ WSDOT Weather Readings API
### API Overview
The WSDOT Weather Readings API provides detailed weather measurements including surface and subsurface data from monitoring stations throughout Washington State.
### Endpoint Groups
| Endpoint Group | Description | Cache Strategy |
|----------------|-------------|----------------|
| **surface-measurements** | Pavement and surface weather measurements | FREQUENT |
| **subsurface-measurements** | Subsurface temperature and moisture measurements | FREQUENT |
| **weather-readings** | Combined surface and subsurface measurements | FREQUENT |
### Key Endpoints
#### Surface Measurements
- **getSurfaceMeasurements**: Returns surface weather measurements for all stations
- **Input**: No parameters required
- **Output**: Array of surface measurement data
- **Key Fields**:
- `StationID`: Unique station identifier
- `StationName`: Human-readable station name
- `PavementTemperature`: Road surface temperature in Fahrenheit
- `SurfaceCondition`: Road surface condition status
- `Friction`: Surface friction measurement
- `LastUpdated`: Timestamp of last update
#### Subsurface Measurements
- **getSubsurfaceMeasurements**: Returns subsurface measurements for all stations
- **Input**: No parameters required
- **Output**: Array of subsurface measurement data
- **Key Fields**:
- `StationID`: Unique station identifier
- `StationName`: Human-readable station name
- `SubsurfaceTemperature`: Temperature below road surface in Fahrenheit
- `SubsurfaceCondition`: Subsurface condition status
- `MoistureContent`: Moisture content percentage
- `LastUpdated`: Timestamp of last update
### Common Use Cases
#### Scientific Weather Dashboard
```javascript
import { useSurfaceMeasurements, useSubsurfaceMeasurements } from 'ws-dottie/wsdot-weather-readings';
function ScientificWeatherDashboard() {
const { data: surfaceData, isLoading: surfaceLoading } = useSurfaceMeasurements();
const { data: subsurfaceData, isLoading: subsurfaceLoading } = useSubsurfaceMeasurements();
// Combine surface and subsurface data by station
const combinedData = surfaceData?.map(surface => {
const subsurface = subsurfaceData?.find(s => s.StationID === surface.StationID);
return {
...surface,
subsurface
};
}) || [];
return (
<div>
<h1>Advanced Weather Information</h1>
{surfaceLoading && subsurfaceLoading && <div>Loading weather data...</div>}
<div className="weather-grid">
{combinedData.map(station => (
<div key={station.StationID} className="weather-station">
<h3>{station.StationName}</h3>
<div className="weather-basic">
<p>Temperature: {station.Temperature}°F</p>
<p>Humidity: {station.RelativeHumidity}%</p>
<p>Wind Speed: {station.WindSpeed} mph</p>
</div>
<div className="weather-advanced">
<h4>Surface Conditions</h4>
<p>Pavement Temperature: {station.PavementTemperature}°F</p>
<p>Surface Condition: {station.SurfaceCondition}</p>
<p>Friction: {station.Friction}</p>
</div>
{station.subsurface && (
<div className="weather-advanced">
<h4>Subsurface Conditions</h4>
<p>Subsurface Temperature: {station.subsurface.SubsurfaceTemperature}°F</p>
<p>Subsurface Condition: {station.subsurface.SubsurfaceCondition}</p>
<p>Moisture Content: {station.subsurface.MoistureContent}%</p>
</div>
)}
</div>
))}
</div>
</div>
);
}
```
## 🏔️ WSDOT Weather Stations API
### API Overview
The WSDOT Weather Stations API provides information about weather station locations throughout Washington State, including coordinates, equipment, and coverage information.
### Endpoint Groups
| Endpoint Group | Description | Cache Strategy |
|----------------|-------------|----------------|
| **weather-stations** | Weather station locations and metadata | FREQUENT |
### Key Endpoints
#### Weather Stations
- **getWeatherStations**: Returns location information for all weather stations
- **Input**: No parameters required
- **Output**: Array of weather station location information
- **Key Fields**:
- `StationID`: Unique station identifier
- `StationName`: Human-readable station name
- `Latitude`, `Longitude`: GPS coordinates
- `Elevation`: Station elevation in feet
- `County`: County where station is located
- `Equipment`: Equipment information
- `Coverage`: Coverage area description
### Common Use Cases
#### Weather Station Locator
```javascript
import { useWeatherStations } from 'ws-dottie/wsdot-weather-stations';
import { useWeatherInformation } from 'ws-dottie/wsdot-weather-information';
function WeatherStationLocator() {
const { data: stations, isLoading: stationsLoading } = useWeatherStations();
const { data: weather, isLoading: weatherLoading } = useWeatherInformation();
const [selectedStation, setSelectedStation] = useState(null);
// Group stations by region
const stationsByRegion = stations?.reduce((acc, station) => {
const region = station.County || 'Unknown';
if (!acc[region]) acc[region] = [];
acc[region].push(station);
return acc;
}, {});
// Find closest station to user location (simulated)
const findClosestStation = (userLat, userLon) => {
return stations?.reduce((closest, station) => {
const distance = calculateDistance(userLat, userLon, station.Latitude, station.Longitude);
const closestDistance = calculateDistance(userLat, userLon, closest.Latitude, closest.Longitude);
return distance < closestDistance ? station : closest;
});
};
return (
<div>
<h1>Washington Weather Stations</h1>
{stationsLoading && <div>Loading weather stations...</div>}
{weatherLoading && <div>Loading weather data...</div>}
<div className="station-locator">
<div className="station-list">
{Object.entries(stationsByRegion).map(([region, regionStations]) => (
<div key={region} className="station-region">
<h3>{region} Region</h3>
{regionStations.map(station => (
<div
key={station.StationID}
className={`station-item ${selectedStation?.StationID === station.StationID ? 'selected' : ''}`}
onClick={() => setSelectedStation(station)}
>
<h4>{station.StationName}</h4>
<p>Elevation: {station.Elevation} feet</p>
<p>Location: {station.Latitude.toFixed(4)}, {station.Longitude.toFixed(4)}</p>
<p>Equipment: {station.Equipment}</p>
</div>
))}
</div>
))}
</div>
{selectedStation && (
<div className="station-details">
<h2>{selectedStation.StationName}</h2>
<p>Station ID: {selectedStation.StationID}</p>
<p>Elevation: {selectedStation.Elevation} feet</p>
<p>Location: {selectedStation.Latitude.toFixed(4)}, {selectedStation.Longitude.toFixed(4)}</p>
<p>County: {selectedStation.County}</p>
<p>Equipment: {selectedStation.Equipment}</p>
<p>Coverage: {selectedStation.Coverage}</p>
{/* Display current weather for selected station */}
{weather && (
<div className="current-weather">
<h3>Current Conditions</h3>
{(() => {
const stationWeather = weather.find(w => w.StationID === selectedStation.StationID);
return stationWeather ? (
<div>
<p>Temperature: {stationWeather.Temperature}°F</p>
<p>Humidity: {stationWeather.RelativeHumidity}%</p>
<p>Wind Speed: {stationWeather.WindSpeed} mph</p>
<p>Road Condition: {stationWeather.RoadCondition}</p>
</div>
) : <p>No weather data available</p>;
})()}
</div>
)}
</div>
)}
</div>
</div>
);
}
// Helper function to calculate distance between two points
function calculateDistance(lat1, lon1, lat2, lon2) {
const R = 3959; // Earth's radius in miles
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
```
## 🔗 API Relationships
Weather APIs work together to provide comprehensive weather and road condition information:
### Weather Stations + Weather Information Integration
```javascript
import { useWeatherInformation } from 'ws-dottie/wsdot-weather-information';
import { useWeatherStations } from 'ws-dottie/wsdot-weather-stations';
function ComprehensiveWeatherDashboard() {
const { data: weather, isLoading: weatherLoading } = useWeatherInformation();
const { data: stations, isLoading: stationsLoading } = useWeatherStations();
// Combine station metadata with current weather
const stationsWithWeather = stations?.map(station => {
const currentWeather = weather?.find(w => w.StationID === station.StationID);
return {
...station,
currentWeather,
lastUpdated: currentWeather?.LastUpdated || null
};
}) || [];
// Group stations by temperature range for visualization
const tempGroups = stationsWithWeather.reduce((acc, station) => {
if (!station.currentWeather) return acc;
const temp = station.currentWeather.Temperature;
if (temp < 32) acc.freezing = [...(acc.freezing || []), station];
else if (temp < 50) acc.cold = [...(acc.cold || []), station];
else if (temp < 70) acc.mild = [...(acc.mild || []), station];
else acc.warm = [...(acc.warm || []), station];
return acc;
}, {});
return (
<div>
<h1>Comprehensive Weather Dashboard</h1>
{weatherLoading && stationsLoading && <div>Loading weather data...</div>}
<div className="weather-summary">
<div className="temp-group">
<h3>Freezing (< 32°F)</h3>
<p>{tempGroups.freezing?.length || 0} stations</p>
</div>
<div className="temp-group">
<h3>Cold (32-50°F)</h3>
<p>{tempGroups.cold?.length || 0} stations</p>
</div>
<div className="temp-group">
<h3>Mild (50-70°F)</h3>
<p>{tempGroups.mild?.length || 0} stations</p>
</div>
<div className="temp-group">
<h3>Warm (> 70°F)</h3>
<p>{tempGroups.warm?.length || 0} stations</p>
</div>
</div>
<div className="weather-grid">
{stationsWithWeather.map(station => (
<div key={station.StationID} className="weather-station">
<h3>{station.StationName}</h3>
<p>Elevation: {station.Elevation} feet</p>
<p>Location: {station.Latitude.toFixed(4)}, {station.Longitude.toFixed(4)}</p>
{station.currentWeather ? (
<div className="current-weather">
<p>Temperature: {station.currentWeather.Temperature}°F</p>
<p>Conditions: {station.currentWeather.RoadCondition}</p>
<p>Last Updated: {new Date(station.lastUpdated).toLocaleString()}</p>
</div>
) : (
<div className="no-weather-data">
<p>No current weather data available</p>
</div>
)}
</div>
))}
</div>
</div>
);
}
```
## 📊 Performance Considerations
### Caching Strategies
- **Weather Information**: `HOURLY_UPDATES` (15-minute refresh)
- **Weather Readings**: `HOURLY_UPDATES` (15-minute refresh)
- **Weather Stations**: `STATIC` (daily refresh)
### Optimization Tips
- **Regional Filtering**: Use geographic filtering to reduce data volume
- **Station Selection**: Prioritize stations closest to user location
## 🔗 Detailed Documentation
For detailed endpoint documentation, interactive examples, and schema definitions, see our generated documentation:
- **[WSDOT Weather Information HTML](../../../redoc/wsdot-weather-information.html)** - Interactive weather documentation
- **[WSDOT Weather Readings HTML](../../../api-reference/wsdot-weather-readings.html)** - Interactive weather readings documentation
- **[WSDOT Weather Stations HTML](../../../redoc/wsdot-weather-stations.html)** - Interactive station documentation
## 📚 Next Steps
- **[TanStack Query Guide](../advanced/tanstack-query.md)** - React patterns with TanStack Query
- **[Fetching Data Guide](../advanced/fetching-data.md)** - Server-side and client-side usage patterns
- **[Performance Guide](../advanced/performance-guide.md)** - Performance optimization strategies
- **[Error Handling Guide](../advanced/error-handling.md)** - Error recovery patterns