@ryancardin/noaa-tides-currents-mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +29 -0
- package/CLAUDE.md +71 -0
- package/Dockerfile +14 -0
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -0
- package/dist/interfaces/config.d.ts +6 -0
- package/dist/interfaces/config.js +1 -0
- package/dist/interfaces/moon.d.ts +65 -0
- package/dist/interfaces/moon.js +35 -0
- package/dist/interfaces/noaa.d.ts +334 -0
- package/dist/interfaces/noaa.js +98 -0
- package/dist/interfaces/parameters.d.ts +18 -0
- package/dist/interfaces/parameters.js +5 -0
- package/dist/interfaces/sun.d.ts +103 -0
- package/dist/interfaces/sun.js +45 -0
- package/dist/mcp-server.d.ts +12 -0
- package/dist/mcp-server.js +103 -0
- package/dist/moon-phase-service.d.ts +122 -0
- package/dist/moon-phase-service.js +187 -0
- package/dist/noaa-service.d.ts +60 -0
- package/dist/noaa-service.js +159 -0
- package/dist/schemas/common.d.ts +14 -0
- package/dist/schemas/common.js +18 -0
- package/dist/schemas/dpapi.d.ts +198 -0
- package/dist/schemas/dpapi.js +89 -0
- package/dist/server/config.d.ts +9 -0
- package/dist/server/config.js +40 -0
- package/dist/server/mcp-server.d.ts +12 -0
- package/dist/server/mcp-server.js +103 -0
- package/dist/services/dpapi-service.d.ts +72 -0
- package/dist/services/dpapi-service.js +164 -0
- package/dist/services/moon-phase-service.d.ts +34 -0
- package/dist/services/moon-phase-service.js +147 -0
- package/dist/services/noaa-parameters-service.d.ts +76 -0
- package/dist/services/noaa-parameters-service.js +128 -0
- package/dist/services/noaa-service.d.ts +52 -0
- package/dist/services/noaa-service.js +151 -0
- package/dist/services/sun-service.d.ts +60 -0
- package/dist/services/sun-service.js +234 -0
- package/dist/sun-service.d.ts +184 -0
- package/dist/sun-service.js +218 -0
- package/dist/tools/derived-product-tools.d.ts +6 -0
- package/dist/tools/derived-product-tools.js +168 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.js +36 -0
- package/dist/tools/moon-tools.d.ts +6 -0
- package/dist/tools/moon-tools.js +69 -0
- package/dist/tools/parameter-tools.d.ts +6 -0
- package/dist/tools/parameter-tools.js +77 -0
- package/dist/tools/station-tools.d.ts +6 -0
- package/dist/tools/station-tools.js +51 -0
- package/dist/tools/sun-tools.d.ts +6 -0
- package/dist/tools/sun-tools.js +109 -0
- package/dist/tools/water-tools.d.ts +6 -0
- package/dist/tools/water-tools.js +150 -0
- package/dist/types/moon.d.ts +26 -0
- package/dist/types/moon.js +14 -0
- package/dist/types/sun.d.ts +49 -0
- package/dist/types/sun.js +19 -0
- package/dist/types.d.ts +337 -0
- package/dist/types.js +98 -0
- package/package.json +56 -0
- package/smithery.yaml +16 -0
- package/src/index.ts +13 -0
- package/src/interfaces/moon.ts +44 -0
- package/src/interfaces/noaa.ts +130 -0
- package/src/interfaces/parameters.ts +20 -0
- package/src/interfaces/sun.ts +57 -0
- package/src/schemas/common.ts +23 -0
- package/src/schemas/dpapi.ts +99 -0
- package/src/server/config.ts +43 -0
- package/src/server/mcp-server.ts +135 -0
- package/src/services/dpapi-service.ts +187 -0
- package/src/services/moon-phase-service.ts +167 -0
- package/src/services/noaa-parameters-service.ts +139 -0
- package/src/services/noaa-service.ts +171 -0
- package/src/services/sun-service.ts +275 -0
- package/src/tools/derived-product-tools.ts +180 -0
- package/src/tools/index.ts +40 -0
- package/src/tools/moon-tools.ts +79 -0
- package/src/tools/parameter-tools.ts +82 -0
- package/src/tools/station-tools.ts +57 -0
- package/src/tools/sun-tools.ts +120 -0
- package/src/tools/water-tools.ts +166 -0
- package/src/types/moon.ts +27 -0
- package/src/types/sun.ts +51 -0
- package/src/types/suncalc.d.ts +110 -0
- package/test-dpapi.js +0 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
// Base URL for the NOAA Derived Product API
|
|
3
|
+
const DPAPI_BASE_URL = 'https://api.tidesandcurrents.noaa.gov/dpapi/prod';
|
|
4
|
+
/**
|
|
5
|
+
* Service for interacting with NOAA Derived Product API (DPAPI)
|
|
6
|
+
*/
|
|
7
|
+
export class DpapiService {
|
|
8
|
+
/**
|
|
9
|
+
* Build parameters for the API request
|
|
10
|
+
* @param params Parameters for the request
|
|
11
|
+
* @returns URL-encoded parameters string
|
|
12
|
+
*/
|
|
13
|
+
buildParams(params) {
|
|
14
|
+
// Remove undefined and null values
|
|
15
|
+
const filteredParams = Object.entries(params)
|
|
16
|
+
.filter(([_, value]) => value !== undefined && value !== null)
|
|
17
|
+
.reduce((acc, [key, value]) => {
|
|
18
|
+
acc[key] = value;
|
|
19
|
+
return acc;
|
|
20
|
+
}, {});
|
|
21
|
+
// Convert to URL parameters
|
|
22
|
+
return new URLSearchParams(filteredParams).toString();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Make a request to the DPAPI
|
|
26
|
+
* @param endpoint Endpoint path
|
|
27
|
+
* @param params Parameters for the request
|
|
28
|
+
* @returns Response data
|
|
29
|
+
*/
|
|
30
|
+
async fetchDpapi(endpoint, params = {}) {
|
|
31
|
+
try {
|
|
32
|
+
const queryParams = this.buildParams(params);
|
|
33
|
+
const url = `${DPAPI_BASE_URL}${endpoint}${queryParams ? '?' + queryParams : ''}`;
|
|
34
|
+
const response = await axios.get(url);
|
|
35
|
+
return response.data;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (axios.isAxiosError(error) && error.response) {
|
|
39
|
+
throw new Error(`NOAA DPAPI Error: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get sea level trends for a station
|
|
46
|
+
* @param params Parameters including station ID and affiliation
|
|
47
|
+
* @returns Sea level trend data
|
|
48
|
+
*/
|
|
49
|
+
async getSeaLevelTrends(params) {
|
|
50
|
+
const { station, affil = 'Global', format = 'json', ...rest } = params;
|
|
51
|
+
return this.fetchDpapi('/sltrends', {
|
|
52
|
+
station,
|
|
53
|
+
affil,
|
|
54
|
+
format,
|
|
55
|
+
...rest
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get extreme water levels for a station
|
|
60
|
+
* @param params Parameters including station ID and units
|
|
61
|
+
* @returns Extreme water level data
|
|
62
|
+
*/
|
|
63
|
+
async getExtremeWaterLevels(params) {
|
|
64
|
+
const { station, units = 'english', format = 'json', ...rest } = params;
|
|
65
|
+
return this.fetchDpapi('/ewl', {
|
|
66
|
+
station,
|
|
67
|
+
units,
|
|
68
|
+
format,
|
|
69
|
+
...rest
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get high tide flooding daily count data
|
|
74
|
+
* @param params Parameters including station ID, date range, and thresholds
|
|
75
|
+
* @returns Daily flood count data
|
|
76
|
+
*/
|
|
77
|
+
async getHighTideFloodingDaily(params) {
|
|
78
|
+
const { station, format = 'json', ...rest } = params;
|
|
79
|
+
return this.fetchDpapi('/htf/daily', {
|
|
80
|
+
station,
|
|
81
|
+
format,
|
|
82
|
+
...rest
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get high tide flooding monthly count data
|
|
87
|
+
* @param params Parameters including station ID, date range, and thresholds
|
|
88
|
+
* @returns Monthly flood count data
|
|
89
|
+
*/
|
|
90
|
+
async getHighTideFloodingMonthly(params) {
|
|
91
|
+
const { station, format = 'json', ...rest } = params;
|
|
92
|
+
return this.fetchDpapi('/htf/monthly', {
|
|
93
|
+
station,
|
|
94
|
+
format,
|
|
95
|
+
...rest
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get high tide flooding seasonal count data
|
|
100
|
+
* @param params Parameters including station ID, seasons, and thresholds
|
|
101
|
+
* @returns Seasonal flood count data
|
|
102
|
+
*/
|
|
103
|
+
async getHighTideFloodingSeasonal(params) {
|
|
104
|
+
const { station, format = 'json', ...rest } = params;
|
|
105
|
+
return this.fetchDpapi('/htf/seasonal', {
|
|
106
|
+
station,
|
|
107
|
+
format,
|
|
108
|
+
...rest
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get high tide flooding annual count data
|
|
113
|
+
* @param params Parameters including station ID, year range, and thresholds
|
|
114
|
+
* @returns Annual flood count data
|
|
115
|
+
*/
|
|
116
|
+
async getHighTideFloodingAnnual(params) {
|
|
117
|
+
const { station, format = 'json', ...rest } = params;
|
|
118
|
+
return this.fetchDpapi('/htf/annual', {
|
|
119
|
+
station,
|
|
120
|
+
format,
|
|
121
|
+
...rest
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get high tide flooding decadal projections
|
|
126
|
+
* @param params Parameters including station ID, scenario, and decade
|
|
127
|
+
* @returns Decadal projection data
|
|
128
|
+
*/
|
|
129
|
+
async getHighTideFloodingProjections(params) {
|
|
130
|
+
const { station, scenario = 'all', format = 'json', ...rest } = params;
|
|
131
|
+
return this.fetchDpapi('/htf/projections', {
|
|
132
|
+
station,
|
|
133
|
+
scenario,
|
|
134
|
+
format,
|
|
135
|
+
...rest
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get high tide flooding daily likelihoods
|
|
140
|
+
* @param params Parameters including station ID and date
|
|
141
|
+
* @returns Daily likelihood data
|
|
142
|
+
*/
|
|
143
|
+
async getHighTideFloodingLikelihoods(params) {
|
|
144
|
+
const { station, format = 'json', ...rest } = params;
|
|
145
|
+
return this.fetchDpapi('/htf/likelihoods', {
|
|
146
|
+
station,
|
|
147
|
+
format,
|
|
148
|
+
...rest
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get top ten water levels for a station
|
|
153
|
+
* @param params Parameters including station ID and analysis type
|
|
154
|
+
* @returns Top ten water level data
|
|
155
|
+
*/
|
|
156
|
+
async getTopTenWaterLevels(params) {
|
|
157
|
+
const { station, format = 'json', ...rest } = params;
|
|
158
|
+
return this.fetchDpapi('/topten', {
|
|
159
|
+
station,
|
|
160
|
+
format,
|
|
161
|
+
...rest
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MoonPhaseParams, MoonPhasesRangeParams, NextMoonPhaseParams } from '../interfaces/moon.js';
|
|
2
|
+
import { MoonPhaseInfo } from '../types/moon.js';
|
|
3
|
+
/**
|
|
4
|
+
* Service for moon phase calculations
|
|
5
|
+
*/
|
|
6
|
+
export declare class MoonPhaseService {
|
|
7
|
+
/**
|
|
8
|
+
* Get the moon phase for a specific date
|
|
9
|
+
* @param params Parameters for the request
|
|
10
|
+
* @returns Moon phase information
|
|
11
|
+
*/
|
|
12
|
+
getMoonPhase(params: MoonPhaseParams): MoonPhaseInfo;
|
|
13
|
+
/**
|
|
14
|
+
* Get moon phases for a date range
|
|
15
|
+
* @param params Parameters for the request
|
|
16
|
+
* @returns Array of moon phase information
|
|
17
|
+
*/
|
|
18
|
+
getMoonPhasesRange(params: MoonPhasesRangeParams): MoonPhaseInfo[];
|
|
19
|
+
/**
|
|
20
|
+
* Get the next occurrence(s) of a specific moon phase
|
|
21
|
+
* @param params Parameters for the request
|
|
22
|
+
* @returns Array of dates for the next occurrences of the specified phase
|
|
23
|
+
*/
|
|
24
|
+
getNextMoonPhase(params: NextMoonPhaseParams): {
|
|
25
|
+
date: string;
|
|
26
|
+
phase: string;
|
|
27
|
+
}[];
|
|
28
|
+
/**
|
|
29
|
+
* Get the moon phase name based on the phase value (0-1)
|
|
30
|
+
* @param phase Phase value (0-1)
|
|
31
|
+
* @returns Moon phase name
|
|
32
|
+
*/
|
|
33
|
+
private getMoonPhaseName;
|
|
34
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import SunCalc from 'suncalc';
|
|
2
|
+
import { MoonPhaseName } from '../types/moon.js';
|
|
3
|
+
/**
|
|
4
|
+
* Service for moon phase calculations
|
|
5
|
+
*/
|
|
6
|
+
export class MoonPhaseService {
|
|
7
|
+
/**
|
|
8
|
+
* Get the moon phase for a specific date
|
|
9
|
+
* @param params Parameters for the request
|
|
10
|
+
* @returns Moon phase information
|
|
11
|
+
*/
|
|
12
|
+
getMoonPhase(params) {
|
|
13
|
+
const date = params.date ? new Date(params.date) : new Date();
|
|
14
|
+
// Get moon illumination data
|
|
15
|
+
const illuminationData = SunCalc.getMoonIllumination(date);
|
|
16
|
+
// Get moon position data (requires location)
|
|
17
|
+
const latitude = params.latitude ?? 0;
|
|
18
|
+
const longitude = params.longitude ?? 0;
|
|
19
|
+
const positionData = SunCalc.getMoonPosition(date, latitude, longitude);
|
|
20
|
+
// Calculate moon phase name
|
|
21
|
+
const phaseName = this.getMoonPhaseName(illuminationData.phase);
|
|
22
|
+
// Calculate if the moon is waxing (increasing illumination)
|
|
23
|
+
const isWaxing = illuminationData.phase < 0.5;
|
|
24
|
+
// Calculate approximate moon age (0-29.53 days)
|
|
25
|
+
const lunarMonth = 29.53; // days
|
|
26
|
+
const age = illuminationData.phase * lunarMonth;
|
|
27
|
+
// Calculate apparent diameter (in degrees)
|
|
28
|
+
const diameter = 0.5181 * (384400 / positionData.distance);
|
|
29
|
+
return {
|
|
30
|
+
date: date.toISOString().split('T')[0],
|
|
31
|
+
phase: illuminationData.phase,
|
|
32
|
+
phaseName,
|
|
33
|
+
illumination: illuminationData.fraction,
|
|
34
|
+
age,
|
|
35
|
+
distance: positionData.distance,
|
|
36
|
+
diameter,
|
|
37
|
+
isWaxing
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get moon phases for a date range
|
|
42
|
+
* @param params Parameters for the request
|
|
43
|
+
* @returns Array of moon phase information
|
|
44
|
+
*/
|
|
45
|
+
getMoonPhasesRange(params) {
|
|
46
|
+
const startDate = new Date(params.start_date);
|
|
47
|
+
const endDate = new Date(params.end_date);
|
|
48
|
+
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
|
|
49
|
+
throw new Error('Invalid date format. Please use YYYY-MM-DD format.');
|
|
50
|
+
}
|
|
51
|
+
if (startDate > endDate) {
|
|
52
|
+
throw new Error('Start date must be before end date.');
|
|
53
|
+
}
|
|
54
|
+
const result = [];
|
|
55
|
+
const currentDate = new Date(startDate);
|
|
56
|
+
while (currentDate <= endDate) {
|
|
57
|
+
result.push(this.getMoonPhase({
|
|
58
|
+
date: currentDate.toISOString().split('T')[0],
|
|
59
|
+
latitude: params.latitude,
|
|
60
|
+
longitude: params.longitude
|
|
61
|
+
}));
|
|
62
|
+
// Move to next day
|
|
63
|
+
currentDate.setDate(currentDate.getDate() + 1);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the next occurrence(s) of a specific moon phase
|
|
69
|
+
* @param params Parameters for the request
|
|
70
|
+
* @returns Array of dates for the next occurrences of the specified phase
|
|
71
|
+
*/
|
|
72
|
+
getNextMoonPhase(params) {
|
|
73
|
+
const startDate = params.date ? new Date(params.date) : new Date();
|
|
74
|
+
const count = params.count || 1;
|
|
75
|
+
const targetPhase = params.phase;
|
|
76
|
+
// Map phase names to their approximate values
|
|
77
|
+
const phaseValues = {
|
|
78
|
+
[MoonPhaseName.NEW_MOON]: 0,
|
|
79
|
+
[MoonPhaseName.FIRST_QUARTER]: 0.25,
|
|
80
|
+
[MoonPhaseName.FULL_MOON]: 0.5,
|
|
81
|
+
[MoonPhaseName.LAST_QUARTER]: 0.75
|
|
82
|
+
};
|
|
83
|
+
const targetPhaseValue = phaseValues[targetPhase];
|
|
84
|
+
const results = [];
|
|
85
|
+
let currentDate = new Date(startDate);
|
|
86
|
+
// Find the next occurrences
|
|
87
|
+
while (results.length < count) {
|
|
88
|
+
// Check every day (could be optimized with better algorithms)
|
|
89
|
+
const illuminationData = SunCalc.getMoonIllumination(currentDate);
|
|
90
|
+
const prevDate = new Date(currentDate);
|
|
91
|
+
prevDate.setDate(prevDate.getDate() - 1);
|
|
92
|
+
const prevIlluminationData = SunCalc.getMoonIllumination(prevDate);
|
|
93
|
+
// Check if we've passed the target phase between yesterday and today
|
|
94
|
+
const prevDiff = Math.abs(prevIlluminationData.phase - targetPhaseValue);
|
|
95
|
+
const currentDiff = Math.abs(illuminationData.phase - targetPhaseValue);
|
|
96
|
+
// If we're getting closer to the target phase and then further away, we've passed it
|
|
97
|
+
// Or if we're very close to the target phase (within 0.01)
|
|
98
|
+
if ((prevDiff > currentDiff && currentDiff < 0.01) || currentDiff < 0.005) {
|
|
99
|
+
results.push({
|
|
100
|
+
date: currentDate.toISOString().split('T')[0],
|
|
101
|
+
phase: targetPhase
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// Move to next day
|
|
105
|
+
currentDate.setDate(currentDate.getDate() + 1);
|
|
106
|
+
// Safety check to prevent infinite loops
|
|
107
|
+
if (results.length === 0 && currentDate.getTime() - startDate.getTime() > 366 * 24 * 60 * 60 * 1000) {
|
|
108
|
+
throw new Error('Could not find the specified moon phase within a year.');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return results;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the moon phase name based on the phase value (0-1)
|
|
115
|
+
* @param phase Phase value (0-1)
|
|
116
|
+
* @returns Moon phase name
|
|
117
|
+
*/
|
|
118
|
+
getMoonPhaseName(phase) {
|
|
119
|
+
// Normalize phase to 0-1 range
|
|
120
|
+
const normalizedPhase = phase < 0 ? phase + 1 : phase > 1 ? phase - 1 : phase;
|
|
121
|
+
// Determine moon phase based on the value
|
|
122
|
+
if (normalizedPhase < 0.0625 || normalizedPhase >= 0.9375) {
|
|
123
|
+
return MoonPhaseName.NEW_MOON;
|
|
124
|
+
}
|
|
125
|
+
else if (normalizedPhase < 0.1875) {
|
|
126
|
+
return MoonPhaseName.WAXING_CRESCENT;
|
|
127
|
+
}
|
|
128
|
+
else if (normalizedPhase < 0.3125) {
|
|
129
|
+
return MoonPhaseName.FIRST_QUARTER;
|
|
130
|
+
}
|
|
131
|
+
else if (normalizedPhase < 0.4375) {
|
|
132
|
+
return MoonPhaseName.WAXING_GIBBOUS;
|
|
133
|
+
}
|
|
134
|
+
else if (normalizedPhase < 0.5625) {
|
|
135
|
+
return MoonPhaseName.FULL_MOON;
|
|
136
|
+
}
|
|
137
|
+
else if (normalizedPhase < 0.6875) {
|
|
138
|
+
return MoonPhaseName.WANING_GIBBOUS;
|
|
139
|
+
}
|
|
140
|
+
else if (normalizedPhase < 0.8125) {
|
|
141
|
+
return MoonPhaseName.LAST_QUARTER;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
return MoonPhaseName.WANING_CRESCENT;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides information about valid NOAA Tides and Currents API parameters
|
|
3
|
+
*/
|
|
4
|
+
export declare class NoaaParametersService {
|
|
5
|
+
/**
|
|
6
|
+
* Get valid time zone values
|
|
7
|
+
*/
|
|
8
|
+
getTimeZones(): {
|
|
9
|
+
id: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}[];
|
|
12
|
+
/**
|
|
13
|
+
* Get valid datum values
|
|
14
|
+
*/
|
|
15
|
+
getDatums(): {
|
|
16
|
+
id: string;
|
|
17
|
+
description: string;
|
|
18
|
+
}[];
|
|
19
|
+
/**
|
|
20
|
+
* Get valid units
|
|
21
|
+
*/
|
|
22
|
+
getUnits(): {
|
|
23
|
+
id: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}[];
|
|
26
|
+
/**
|
|
27
|
+
* Get valid intervals for tide predictions
|
|
28
|
+
*/
|
|
29
|
+
getTidePredictionIntervals(): {
|
|
30
|
+
id: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}[];
|
|
33
|
+
/**
|
|
34
|
+
* Get valid intervals for current predictions
|
|
35
|
+
*/
|
|
36
|
+
getCurrentPredictionIntervals(): {
|
|
37
|
+
id: string;
|
|
38
|
+
description: string;
|
|
39
|
+
}[];
|
|
40
|
+
/**
|
|
41
|
+
* Get valid velocity types for current predictions
|
|
42
|
+
*/
|
|
43
|
+
getVelocityTypes(): {
|
|
44
|
+
id: string;
|
|
45
|
+
description: string;
|
|
46
|
+
}[];
|
|
47
|
+
/**
|
|
48
|
+
* Get valid meteorological products
|
|
49
|
+
*/
|
|
50
|
+
getMeteorologicalProducts(): {
|
|
51
|
+
id: string;
|
|
52
|
+
description: string;
|
|
53
|
+
}[];
|
|
54
|
+
/**
|
|
55
|
+
* Get valid station types
|
|
56
|
+
*/
|
|
57
|
+
getStationTypes(): {
|
|
58
|
+
id: string;
|
|
59
|
+
description: string;
|
|
60
|
+
}[];
|
|
61
|
+
/**
|
|
62
|
+
* Get valid date formats
|
|
63
|
+
*/
|
|
64
|
+
getDateFormats(): {
|
|
65
|
+
format: string;
|
|
66
|
+
description: string;
|
|
67
|
+
example: string;
|
|
68
|
+
}[];
|
|
69
|
+
/**
|
|
70
|
+
* Get valid output formats
|
|
71
|
+
*/
|
|
72
|
+
getOutputFormats(): {
|
|
73
|
+
id: string;
|
|
74
|
+
description: string;
|
|
75
|
+
}[];
|
|
76
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides information about valid NOAA Tides and Currents API parameters
|
|
3
|
+
*/
|
|
4
|
+
export class NoaaParametersService {
|
|
5
|
+
/**
|
|
6
|
+
* Get valid time zone values
|
|
7
|
+
*/
|
|
8
|
+
getTimeZones() {
|
|
9
|
+
return [
|
|
10
|
+
{ id: 'gmt', description: 'Greenwich Mean Time' },
|
|
11
|
+
{ id: 'lst', description: 'Local Standard Time' },
|
|
12
|
+
{ id: 'lst_ldt', description: 'Local Standard/Local Daylight Time' }
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get valid datum values
|
|
17
|
+
*/
|
|
18
|
+
getDatums() {
|
|
19
|
+
return [
|
|
20
|
+
{ id: 'MHHW', description: 'Mean Higher High Water' },
|
|
21
|
+
{ id: 'MHW', description: 'Mean High Water' },
|
|
22
|
+
{ id: 'MTL', description: 'Mean Tide Level' },
|
|
23
|
+
{ id: 'MSL', description: 'Mean Sea Level' },
|
|
24
|
+
{ id: 'MLW', description: 'Mean Low Water' },
|
|
25
|
+
{ id: 'MLLW', description: 'Mean Lower Low Water' },
|
|
26
|
+
{ id: 'NAVD', description: 'North American Vertical Datum' },
|
|
27
|
+
{ id: 'STND', description: 'Station Datum' }
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get valid units
|
|
32
|
+
*/
|
|
33
|
+
getUnits() {
|
|
34
|
+
return [
|
|
35
|
+
{ id: 'english', description: 'English units (feet, mph, etc.)' },
|
|
36
|
+
{ id: 'metric', description: 'Metric units (meters, kph, etc.)' }
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get valid intervals for tide predictions
|
|
41
|
+
*/
|
|
42
|
+
getTidePredictionIntervals() {
|
|
43
|
+
return [
|
|
44
|
+
{ id: 'hilo', description: 'High/low tide predictions only' },
|
|
45
|
+
{ id: 'h', description: 'Hourly predictions' },
|
|
46
|
+
{ id: '6', description: '6-minute predictions' },
|
|
47
|
+
{ id: '30', description: '30-minute predictions' },
|
|
48
|
+
{ id: '60', description: '60-minute predictions' }
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get valid intervals for current predictions
|
|
53
|
+
*/
|
|
54
|
+
getCurrentPredictionIntervals() {
|
|
55
|
+
return [
|
|
56
|
+
{ id: 'MAX_SLACK', description: 'Maximum flood/ebb and slack predictions only' },
|
|
57
|
+
{ id: '6', description: '6-minute predictions' },
|
|
58
|
+
{ id: '30', description: '30-minute predictions' },
|
|
59
|
+
{ id: '60', description: '60-minute predictions' }
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get valid velocity types for current predictions
|
|
64
|
+
*/
|
|
65
|
+
getVelocityTypes() {
|
|
66
|
+
return [
|
|
67
|
+
{ id: 'default', description: 'Default velocity reporting (flood/ebb direction)' },
|
|
68
|
+
{ id: 'speed_dir', description: 'Speed and direction format' }
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get valid meteorological products
|
|
73
|
+
*/
|
|
74
|
+
getMeteorologicalProducts() {
|
|
75
|
+
return [
|
|
76
|
+
{ id: 'air_temperature', description: 'Air temperature' },
|
|
77
|
+
{ id: 'water_temperature', description: 'Water temperature' },
|
|
78
|
+
{ id: 'wind', description: 'Wind speed and direction' },
|
|
79
|
+
{ id: 'air_pressure', description: 'Barometric pressure' },
|
|
80
|
+
{ id: 'air_gap', description: 'Air gap (distance between bridge and water surface)' },
|
|
81
|
+
{ id: 'conductivity', description: 'Conductivity' },
|
|
82
|
+
{ id: 'visibility', description: 'Visibility' },
|
|
83
|
+
{ id: 'humidity', description: 'Relative humidity' },
|
|
84
|
+
{ id: 'salinity', description: 'Salinity' },
|
|
85
|
+
{ id: 'hourly_height', description: 'Verified hourly height water level' },
|
|
86
|
+
{ id: 'high_low', description: 'Verified high/low water level' },
|
|
87
|
+
{ id: 'daily_mean', description: 'Verified daily mean water level' },
|
|
88
|
+
{ id: 'monthly_mean', description: 'Verified monthly mean water level' },
|
|
89
|
+
{ id: 'one_minute_water_level', description: 'One-minute water level data' },
|
|
90
|
+
{ id: 'datums', description: 'Datums' }
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get valid station types
|
|
95
|
+
*/
|
|
96
|
+
getStationTypes() {
|
|
97
|
+
return [
|
|
98
|
+
{ id: 'waterlevels', description: 'Water level stations' },
|
|
99
|
+
{ id: 'currentpredictions', description: 'Current prediction stations' },
|
|
100
|
+
{ id: 'currents', description: 'Current observation stations' },
|
|
101
|
+
{ id: 'tidepredictions', description: 'Tide prediction stations' },
|
|
102
|
+
{ id: 'weather', description: 'Weather stations' },
|
|
103
|
+
{ id: 'ports', description: 'Physical Oceanographic Real-Time System (PORTS) stations' }
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get valid date formats
|
|
108
|
+
*/
|
|
109
|
+
getDateFormats() {
|
|
110
|
+
return [
|
|
111
|
+
{ format: 'YYYYMMDD', description: 'Year, month, day without separators', example: '20230401' },
|
|
112
|
+
{ format: 'MM/DD/YYYY', description: 'Month/day/year with separators', example: '04/01/2023' },
|
|
113
|
+
{ format: 'today', description: 'Current date', example: 'today' },
|
|
114
|
+
{ format: 'latest', description: 'Latest available data', example: 'latest' },
|
|
115
|
+
{ format: 'recent', description: 'Most recent data', example: 'recent' }
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get valid output formats
|
|
120
|
+
*/
|
|
121
|
+
getOutputFormats() {
|
|
122
|
+
return [
|
|
123
|
+
{ id: 'json', description: 'JSON format' },
|
|
124
|
+
{ id: 'xml', description: 'XML format' },
|
|
125
|
+
{ id: 'csv', description: 'CSV format (not available for all endpoints)' }
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service for interacting with NOAA Tides and Currents APIs
|
|
3
|
+
*/
|
|
4
|
+
export declare class NoaaService {
|
|
5
|
+
/**
|
|
6
|
+
* Build parameters for the API request
|
|
7
|
+
* @param params Parameters for the request
|
|
8
|
+
* @returns URL-encoded parameters string
|
|
9
|
+
*/
|
|
10
|
+
private buildParams;
|
|
11
|
+
/**
|
|
12
|
+
* Make a request to the Data API
|
|
13
|
+
* @param params Parameters for the request
|
|
14
|
+
* @returns Response data
|
|
15
|
+
*/
|
|
16
|
+
fetchDataApi(params: Record<string, any>): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Make a request to the Metadata API
|
|
19
|
+
* @param endpoint Endpoint path
|
|
20
|
+
* @param params Parameters for the request
|
|
21
|
+
* @returns Response data
|
|
22
|
+
*/
|
|
23
|
+
fetchMetadataApi(endpoint: string, params?: Record<string, any>): Promise<any>;
|
|
24
|
+
/**
|
|
25
|
+
* Get water level data
|
|
26
|
+
*/
|
|
27
|
+
getWaterLevels(params: Record<string, any>): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Get tide predictions
|
|
30
|
+
*/
|
|
31
|
+
getTidePredictions(params: Record<string, any>): Promise<any>;
|
|
32
|
+
/**
|
|
33
|
+
* Get currents data
|
|
34
|
+
*/
|
|
35
|
+
getCurrents(params: Record<string, any>): Promise<any>;
|
|
36
|
+
/**
|
|
37
|
+
* Get current predictions
|
|
38
|
+
*/
|
|
39
|
+
getCurrentPredictions(params: Record<string, any>): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Get meteorological data (air_temperature, wind, etc.)
|
|
42
|
+
*/
|
|
43
|
+
getMeteorologicalData(params: Record<string, any>): Promise<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Get list of stations
|
|
46
|
+
*/
|
|
47
|
+
getStations(params: Record<string, any>): Promise<any>;
|
|
48
|
+
/**
|
|
49
|
+
* Get station details
|
|
50
|
+
*/
|
|
51
|
+
getStationDetails(params: Record<string, any>): Promise<any>;
|
|
52
|
+
}
|