Skip to content

Commit

Permalink
Replace non-functional NOAA API with reading data from a text file
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertMParker committed Jul 24, 2023
1 parent c39a369 commit 3c8f605
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 26 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ <h2><a target="_blank" href='https://ambientweather.net/dashboard/0e02feb4d3f58c

<h2><a target="_blank" href='https://www.ndbc.noaa.gov/station_page.php?station=46026'>Farallones Buoy</a></h2>
<p>This buoy 20 miles off the coast of San Francisco can indicate future conditions.</p>
<canvas id="urn:ioos:station:wmo:46026" class="NOAAWind" timezone="PST8PDT" height="120"></canvas>
<canvas id="46026" class="NOAAWind" timezone="PST8PDT" height="120"></canvas>

<h1>Webcams</h1>

Expand Down
60 changes: 35 additions & 25 deletions noaa-wind.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Class for getting measurements from sdf.ndbc.noaa.gov
// Class for getting measurements from https://www.ndbc.noaa.gov/data/5day2/<station_id>_5day.txt

class NOAAWind extends Wind {
constructor(stationId, timezone) {
Expand All @@ -8,44 +8,54 @@ class NOAAWind extends Wind {
}

makeRequest() {
var startTime = moment().subtract(24, 'hours').format('YYYY-MM-DDTHH:mm[Z]');
var endTime = moment().format('YYYY-MM-DDTHH:mm[Z]');

// Make request to get JSON weather data for stationId
this.xmlhttp = new XMLHttpRequest();
this.xmlhttp.onreadystatechange = this.onResponseReceived.bind(this);
this.xmlhttp.open('GET', 'https://sdf.ndbc.noaa.gov/sos/server.php?request=GetObservation&service=SOS&version=1.0.0&offering=' + this.stationId + '&observedproperty=Winds&responseformat=text/csv&eventtime=' + startTime + '/' + endTime, true);
// Found this cors proxy randomly on Google, not sure if it's trustworthy
const url = 'https://corsproxy.io/?' + encodeURIComponent('https://www.ndbc.noaa.gov/data/5day2/' + this.stationId + '_5day.txt');
this.xmlhttp.open('GET', url, true);
this.xmlhttp.send();

// fields:
// - 0 station_id
// - 1 sensor_id
// - 2 latitude (degree)
// - 3 longitude (degree)
// - 4 date_time
// - 5 depth (m)
// - 6 wind_from_direction (degree)
// - 7 wind_speed (m/s)
// - 8 wind_speed_of_gust (m/s)
// - 9 upward_air_velocity (m/s)
}

parseData() {
var response = Papa.parse(this.xmlhttp.responseText, { header: true });
/* Example response:
#YY MM DD hh mm WDIR WSPD GST WVHT DPD APD MWD PRES ATMP WTMP DEWP VIS PTDY TIDE
#yr mo dy hr mn degT m/s m/s m sec sec degT hPa degC degC degC nmi hPa ft
2023 07 24 20 10 300 6.0 7.0 MM MM MM MM 1020.2 MM 12.9 MM MM MM MM
2023 07 24 20 00 300 5.0 7.0 MM MM MM MM 1020.3 MM 12.9 MM MM +1.0 MM
2023 07 24 19 50 300 5.0 7.0 1.4 7 5.2 304 1020.2 MM 12.9 MM MM MM MM
2023 07 24 19 40 310 6.0 8.0 MM MM MM MM 1020.1 MM 12.8 MM MM MM MM
2023 07 24 19 30 310 6.0 8.0 MM MM MM MM 1020.1 MM 12.7 MM MM MM MM
2023 07 24 19 20 310 7.0 9.0 1.5 MM 5.1 302 1019.9 MM 12.7 MM MM MM MM
*/

// Since thie uses a 3rd party CORS proxy, do not execute/parse JSON. The data isn't even JSON, but still worth a warning.
var lines = this.xmlhttp.responseText.split('\n');
var windDir = [];
var windSpeed = [];
var windGust = [];
var minMoment = moment().subtract(3, 'hours');
for (var i=0; i<response.data.length; i++) {
var observation = response.data[i];
var observationMoment = moment.parseZone(observation.date_time).add(this.tzOffset, 'hours');
for (var i=0; i<lines.length; i++) {
var cols = lines[i].split(' ')
if (cols[0].startsWith('#')) continue;

var year = parseInt(cols[0]);
var month = parseInt(cols[1]);
var day = parseInt(cols[2]);
var hour = parseInt(cols[3]);
var minute = parseInt(cols[4]);
var wind_direction = parseInt(cols[5]);
var wind_speed_meters_per_second = parseInt(cols[6]);
var wind_gust_meters_per_second = parseInt(cols[7]);

// Month is 0-indexed
var observationMoment = moment.utc([year, month-1, day, hour, minute]);

// Filter out data that is not within the last three hours
if (!observationMoment.isAfter(minMoment)) continue;

windDir.push({x: observationMoment, y: observation['wind_from_direction (degree)']});
windSpeed.push({x: observationMoment, y: Math.round(observation['wind_speed (m/s)'] * 2.23694)});
windGust.push({x: observationMoment, y: Math.round(observation['wind_speed_of_gust (m/s)'] * 2.23694)});
windDir.push({x: observationMoment, y: wind_direction});
windSpeed.push({x: observationMoment, y: Math.round(wind_speed_meters_per_second * 2.23694)});
windGust.push({x: observationMoment, y: Math.round(wind_gust_meters_per_second * 2.23694)});
}
this.createChart(windSpeed, windGust, windDir);
}
Expand Down

0 comments on commit 3c8f605

Please sign in to comment.