diff --git a/@noaa/datacategories.m b/@noaa/datacategories.m new file mode 100644 index 0000000..1637f77 --- /dev/null +++ b/@noaa/datacategories.m @@ -0,0 +1,62 @@ +function [d,response] = datacategories(c,id,varargin) +%DATACATEGORIES NOAA data category name and identifiers. +% [DATA,RESPONSE] = DATACATEGORIES(C) returns up to 25 category names +% and identifiers. C is the NOAA object. +% +% [DATA,RESPONSE] = DATACATEGORIES(C,ID) returns the category name +% and identifier for a given category identifier, ID. C is the NOAA +% object. +% +% [DATA,RESPONSE] = DATACATEGORIES(C,ID,VARARGIN) returns category names +% and identifiers. C is the NOAA object, ID is a category identifier and +% VARARGIN is name and value parameters supported by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +datacatagoriesUrl = strcat(c.URL,"datacategories"); +if exist('id','var') && ~isempty(id) + datacatagoriesUrl = strcat(datacatagoriesUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + datacatagoriesUrl = strcat(datacatagoriesUrl,"?"); + + for i = 1:2:length(varargin) + datacatagoriesUrl = strcat(datacatagoriesUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(datacatagoriesUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +% Convert output to table +if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); +else + d = struct2table(response.Body.Data); +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"name","id"} + d.(varNames{i}) = string(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/@noaa/datasets.m b/@noaa/datasets.m new file mode 100644 index 0000000..6baa010 --- /dev/null +++ b/@noaa/datasets.m @@ -0,0 +1,63 @@ +function [d,response] = datasets(c,id,varargin) +%DATASETS NOAA dataset information. +% [DATA,RESPONSE] = DATASETS(C) returns up to 25 records containing +% information pertaining to the available NOAA datasets +% +% [DATA,RESPONSE] = DATASETS(C,ID) returns the dataset information for a +% given dataset identifier, ID. C is the NOAA +% object. +% +% [DATA,RESPONSE] = DATASETS(C,ID,VARARGIN) returns dataset information. +% C is the NOAA object, ID is a dataset identifier and VARARGIN is name +% and value parameters supported by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +datasetsUrl = strcat(c.URL,"datasets"); +if exist('id','var') && ~isempty(id) + datasetsUrl = strcat(datasetsUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + datasetsUrl = strcat(datasetsUrl,"?"); + + for i = 1:2:length(varargin) + datasetsUrl = strcat(datasetsUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(datasetsUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); +else + d = struct2table(response.Body.Data); +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"uid","name","id"} + d.(varNames{i}) = string(d.(varNames{i})); + case {"mindate","maxdate"} + d.(varNames{i}) = datetime(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/@noaa/datatypes.m b/@noaa/datatypes.m new file mode 100644 index 0000000..0a30b2f --- /dev/null +++ b/@noaa/datatypes.m @@ -0,0 +1,68 @@ +function [d,response] = datatypes(c,id,varargin) +%DATATYPES NOAA data types information. +% [DATA,RESPONSE] = DATATYPES(C) returns up to 25 records containing +% information pertaining to the available NOAA data types. +% +% [DATA,RESPONSE] = DATATYPES(C,ID) returns the data type information for a +% given data type identifier, ID. C is the NOAA +% object. +% +% [DATA,RESPONSE] = DATATYPES(C,ID,VARARGIN) returns data type information. +% C is the NOAA object, ID is a data type identifier and VARARGIN is name +% and value parameters supported by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. +% Set request parameters +method = "GET"; + +% Create URL +datatypesUrl = strcat(c.URL,"datatypes"); +if exist('id','var') && ~isempty(id) + datatypesUrl = strcat(datatypesUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + datatypesUrl = strcat(datatypesUrl,"?"); + + for i = 1:2:length(varargin) + datatypesUrl = strcat(datatypesUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(datatypesUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +try + if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); + else + d = struct2table(response.Body.Data); + end +catch + % Unstructured data return + d = response; + return +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"name","id"} + d.(varNames{i}) = string(d.(varNames{i})); + case {"mindate","maxdate"} + d.(varNames{i}) = datetime(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/@noaa/getdata.m b/@noaa/getdata.m new file mode 100644 index 0000000..4ebf960 --- /dev/null +++ b/@noaa/getdata.m @@ -0,0 +1,79 @@ +function [d,response] = getdata(c,id,startdate,enddate,varargin) +%GETDATA NOAA dataset data. +% [DAT,RESPONSE] = GETDATA(C,ID,STARTDATE,ENDDATE) returns the data for a +% given NOAA object C and dataset identifier ID for the date range +% defined by STARTDATE and ENDDATE. +% +% [DAT,RESPONSE] = GETDATA(C,ID,STARTDATE,ENDDATE,VARARGIN) returns the data for a +% given NOAA object C and dataset identifier ID for the date range +% defined by STARTDATE and ENDDATE. VARARGIN is name and value parameters +% supported by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +dataUrl = strcat(c.URL,"data"); + +% Add datasetid +if exist("id","var") && ~isempty(id) + varargin = [{"datasetid" id} varargin]; +else + error("datafeed:noaa:missingDataSetId","Dataset identifier required.") +end + +% Add startdate +if exist("startdate","var") && ~isempty(startdate) + startdate = matlab.datetime.compatibility.convertDatenum(startdate); + startdate.Format = "yyyy-MM-dd"; + varargin{end+1} = "startdate"; + varargin{end+1} = string(startdate); +else + error("datafeed:noaa:missingStartDate","Start date required.") +end + +% Add enddate +if exist("enddate","var") && ~isempty(enddate) + enddate = matlab.datetime.compatibility.convertDatenum(enddate); + enddate.Format = "yyyy-MM-dd"; + varargin{end+1} = "enddate"; + varargin{end+1} = string(enddate); +else + error("datafeed:noaa:missingEndDate","End date required.") +end + +% Add name value pairs +if nargin > 1 + dataUrl = strcat(dataUrl,"?"); + + for i = 1:2:length(varargin) + dataUrl = strcat(dataUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end +dataUrl{end}(end) = []; + +HttpURI = matlab.net.URI(dataUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); +else + try + d = struct2table(response.Body.Data); + catch + d = response; + end +end \ No newline at end of file diff --git a/@noaa/locationcategories.m b/@noaa/locationcategories.m new file mode 100644 index 0000000..c9b420a --- /dev/null +++ b/@noaa/locationcategories.m @@ -0,0 +1,62 @@ +function [d,response] = locationcategories(c,id,varargin) +%LOCATIONCATEGORIES NOAA location category name and identifiers. +% [DATA,RESPONSE] = LOCATIONCATEGORIES(C) returns up to 25 location +% category names and identifiers. C is the NOAA object. +% +% [DATA,RESPONSE] = LOCATIONCATEGORIES(C,ID) returns the location +% category name and identifier for a given category identifier, ID. C is +% the NOAA object. +% +% [DATA,RESPONSE] = LOCATIONCATEGORIES(C,ID,VARARGIN) returns location +% category names and identifiers. C is the NOAA object, ID is a location +% category identifier and VARARGIN is name and value parameters supported +% by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +locationcatagoriesUrl = strcat(c.URL,"locationcategories"); +if exist('id','var') && ~isempty(id) + locationcatagoriesUrl = strcat(locationcatagoriesUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + locationcatagoriesUrl = strcat(locationcatagoriesUrl,"?"); + + for i = 1:2:length(varargin) + locationcatagoriesUrl = strcat(locationcatagoriesUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(locationcatagoriesUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); +else + d = struct2table(response.Body.Data); +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"name","id"} + d.(varNames{i}) = string(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/@noaa/locations.m b/@noaa/locations.m new file mode 100644 index 0000000..c585046 --- /dev/null +++ b/@noaa/locations.m @@ -0,0 +1,64 @@ +function [d,response] = locations(c,id,varargin) +%LOCATIONS NOAA location name and identifiers. +% [DATA,RESPONSE] = LOCATIONS(C) returns up to 25 geographic location +% names and identifiers. C is the NOAA object. +% +% [DATA,RESPONSE] = LOCATIONS(C,ID) returns the geographic location +% name and identifier for a given geographic location identifier, ID. C +% is the NOAA object. +% +% [DATA,RESPONSE] = LOCATIONS(C,ID,VARARGIN) returns geographic location +% names and identifiers. C is the NOAA object, ID is a geographic location +% identifier and VARARGIN is name and value parameters supported +% by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +locationsUrl = strcat(c.URL,"locations"); +if exist('id','var') && ~isempty(id) + locationsUrl = strcat(locationsUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + locationsUrl = strcat(locationsUrl,"?"); + + for i = 1:2:length(varargin) + locationsUrl = strcat(locationsUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(locationsUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); +else + d = struct2table(response.Body.Data); +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"name","id"} + d.(varNames{i}) = string(d.(varNames{i})); + case {"mindate","maxdate"} + d.(varNames{i}) = datetime(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/@noaa/noaa.m b/@noaa/noaa.m new file mode 100644 index 0000000..b79e6d5 --- /dev/null +++ b/@noaa/noaa.m @@ -0,0 +1,118 @@ +classdef noaa < handle +%NOAA National Oceanic and Atmospheric Administration connection. +% C = NOAA(TOKEN,TIMEOUT) creates a NOAA connection object using the +% TOKEN. TOKEN can be input as a string scalar or character vector. +% TIMEOUT is the request value in milliseconds and input as a numeric +% value. The default value is 200 milliseconds. C is an noaa object. +% +% For example, +% +% c = noaa("tokenstring") +% +% returns +% +% c = +% +% noaa with properties: +% +% TimeOut: 200.00 + +% Copyright 2022 The MathWorks, Inc. + + properties + TimeOut + end + + properties (Hidden = true) + DebugModeValue + MediaType + URL + end + + properties (Access = 'private') + Token + end + + methods (Access = 'public') + + function c = noaa(apiToken,timeout,url,mediatype,debugmodevalue) + + % Registered noaa users will have an authentication token + if nargin < 1 + error("datafeed:noaa:missingToken","NOAA token required for data requests."); + end + + % Timeout value for requests + if exist("timeout","var") && ~isempty(timeout) + c.TimeOut = timeout; + else + c.TimeOut = 200; + end + + % Set URL + if exist("url","var") && ~isempty(url) + c.URL = url; + else + c.URL = "https://www.ncdc.noaa.gov/cdo-web/api/v2/"; + end + + % Specify HTTP media type i.e. application content to deal with + if nargin < 4 || isempty(mediatype) + HttpMediaType = matlab.net.http.MediaType("application/json; charset=UTF-8"); + else + HttpMediaType = matlab.net.http.MediaType(mediatype); + end + c.MediaType = string(HttpMediaType.MediaInfo); + + % Debug value for requests + if exist("debugmodevalue","var") && ~isempty(debugmodevalue) + c.DebugModeValue = debugmodevalue; + else + c.DebugModeValue = 0; + end + + % Check valid + % Set request parameters + method = "GET"; + + HttpURI = matlab.net.URI(c.URL); + + HttpHeader = matlab.net.http.HeaderField("token",apiToken,"Content-Type",c.MediaType); + + RequestMethod = matlab.net.http.RequestMethod(method); + Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + + options = matlab.net.http.HTTPOptions('ConnectTimeout',c.TimeOut,'Debug',c.DebugModeValue); + + % Send Request + response = send(Request,HttpURI,options); + + % Check for response error + switch response.StatusCode + + case "NotFound" + + error("datafeed:noaa:invalidURL",strcat("URL not found. Status code: ", string(response.StatusCode))) + + case "OK" + + % Valid connection response + + otherwise + responseError = response.Body.Data; + error("datafeed:noaa:connectFailure",strcat(responseError.message," Status code: ",responseError.status)) + + end + + % Store token in object + c.Token = apiToken; + + end + + end + + methods (Static) + + end + +end \ No newline at end of file diff --git a/@noaa/stations.m b/@noaa/stations.m new file mode 100644 index 0000000..673b1b9 --- /dev/null +++ b/@noaa/stations.m @@ -0,0 +1,68 @@ +function [d,response] = stations(c,id,varargin) +%STATIONS NOAA station name and identifiers. +% [DATA,RESPONSE] = STATIONS(C) returns up to 25 geographic station +% names and identifiers. C is the NOAA object. +% +% [DATA,RESPONSE] = STATIONS(C,ID) returns the geographic station +% name and identifier for a given station identifier, ID. C is +% the NOAA object. +% +% [DATA,RESPONSE] = STATIONS(C,ID,VARARGIN) returns geographic station +% names and identifiers. C is the NOAA object, ID is a geographic station +% identifier and VARARGIN is name and value parameters supported +% by the NOAA REST API. +% +% See also NOAA. + +% Copyright 2022 The MathWorks, Inc. + +% Set request parameters +method = "GET"; + +% Create URL +stationsUrl = strcat(c.URL,"stations"); +if exist('id','var') && ~isempty(id) + stationsUrl = strcat(stationsUrl,"/",id); +end + +% Add name value pairs +if nargin > 2 + stationsUrl = strcat(stationsUrl,"?"); + + for i = 1:2:length(varargin) + stationsUrl = strcat(stationsUrl,varargin{i},"=",string(varargin{i+1}),"&"); + end +end + +HttpURI = matlab.net.URI(stationsUrl); + +HttpHeader = matlab.net.http.HeaderField("token",c.Token,"Content-Type","application/json; charset=UTF-8"); + +RequestMethod = matlab.net.http.RequestMethod(method); +Request = matlab.net.http.RequestMessage(RequestMethod,HttpHeader); + +options = matlab.net.http.HTTPOptions('ConnectTimeout',200,'Debug',c.DebugModeValue); + +% Send Request +response = send(Request,HttpURI,options); + +try + if isfield(response.Body.Data,"results") + d = struct2table(response.Body.Data.results); + else + d = struct2table(response.Body.Data); + end +catch + d = response.Body.Data; +end + +% Convert cell arrays to string arrays +varNames = d.Properties.VariableNames; +for i = 1:length(varNames) + switch varNames{i} + case {"name","id","elevationUnit"} + d.(varNames{i}) = string(d.(varNames{i})); + case {"mindate","maxdate"} + d.(varNames{i}) = datetime(d.(varNames{i})); + end +end \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d772fd0 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# noaa + Access NOAA from MATLAB diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..221952e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,6 @@ +# Reporting Security Vulnerabilities + +If you believe you have discovered a security vulnerability, please report it to +[security@mathworks.com](mailto:security@mathworks.com). Please see +[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html) +for additional information. \ No newline at end of file diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..3bea778 --- /dev/null +++ b/license.txt @@ -0,0 +1,11 @@ +Copyright (c) 2022, The MathWorks, Inc. +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +