UNPKG

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
# 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 (&lt; 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 (&gt; 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