A library to fetch air quality data from various providers (AQICN, OpenAQ...) and normalizing data into one common format: the openaq-data-format.
Provider | Provider Code | Website | Notes |
---|---|---|---|
AQICN | aqicn |
https://aqicn.org | API token needed, get one for free here |
WAQI | waqi |
https://waqi.info/ | Same institution as AqiCN |
OpenAQ v2 | openaq |
https://openaq.org |
We plan to support more air quality providers in the future see issue #29.
Install the package:
yarn install @shootismoke/dataproviders
The package exposes a couple of data providers (see list above), and for each data provider, there are two main functions:
fetchByGps({ latitude, longitude }, options?)
- Fetch air quality data by GPS coordinates.fetchByStation(stationId, options?)
- Fetch air quality data by station ID.
// Retrieve the providers by provider code.
import { aqicn, openaq } from '@shootismoke/dataproviders';
async function main() {
// Fetch the station 1045 on AQICN.
const data = await aqicn.fetchByStation(1045);
console.log(data.dominentpol); // `dominentpol` is a field specific to AQICN. This logs "pm25".
const results = aqicn.normalizeByStation(data); // `results` is an array of normalized OpenAQResults.
const res = results[0];
console.log(`${res.parameter}: ${res.value} ${res.unit}`); // Logs "pm25: 34.5 µg/m³".
// Note how `data.dominentpol` has been converted to `res.parameter`: this is
// what we call "normalization" in @shootismoke/providers.
}
The codebase uses io-ts
under the hood to perform runtime data validation, the results are functional programming datatypes (Either<E,A>
, Task<E,A>
...). If you are already using io-ts
and fp-ts
](https://github.com/gcanti/fp-ts) in your project, it's recommended to import from the /lib/fp
subfolder directly.
// Retrieve the providers by provider code, using fp-ts.
import { aqicn, openaq } from '@shootismoke/dataproviders/lib/fp';
aqicn.fetchByGps({ latitude: 45, longitude: 23 }); // Returns a TaskEither<Error, AqicnData>
Here's a real-world example:
import { pipe } from 'fp-ts/lib/pipeable';
import * as TE from 'fp-ts/lib/TaskEither';
pipe(
// Fetch data from station 'Coyhaique' on the OpenAQ platform.
openaq.fetchByStation('Coyhaique'),
// Normalize the data.
TE.chain((response) => TE.fromEither(normalize(response))),
// Depending on error/result case, do different stuff
TE.fold(
// Do on error:
(error) => {
console.error(error);
// -- snip --
},
// Do on success:
(results) => {
const res = results[0]; // `results` is an array of normalized OpenAQ objects
console.log(`${res.value} ${res.unit}`); // Logs "34.5 µg/m³"
// -- snip --
}
)
);
If you use the .normalizeByGps
or .normalizeByStation
functions, the output will be normalized, i.e. in the same format no matter which provider you use. We follow the openaq-data-format
, below are some of its most frequently used fields:
/**
* The OpenAQ data format. One such object represents one air quality
* measurement
*/
interface OpenAQResult {
/**
* City (or regional approximation) containing location
*/
city?: string;
/**
* Coordinates where the measurement took place. Note that in the
* openaq-data-format, this field is optional. Using this library, this field
* will **always** be populated
*/
coordinates?: {
latitude: number;
longitude: number;
};
/**
* Country containing location in two letter ISO format
*/
country: string;
/**
* Time of measurement including both local time and UTC time.
*/
date: {
local: string;
utc: string;
};
/**
* A unique ID representing the location of a measurement (can be a station
* ID, a place...)
*/
location: string;
/**
* The pollutant id (pm25, pm10, o3...)
*/
parameter: Pollutant;
/**
* The value of the measurement
*/
value: number;
/**
* The unit the value is measured in (µg/m³, ppm)
*/
unit: Unit;
// -- snip --
// There are some other optional fields, see docs for more details.
}
/**
* The normalized data is an array of OpenAQ results. We ensure there is
* always at least one element in the Normalized array.
*/
type OpenAQResults = OpenAQResult[];
See openaq-data-format
for more information.
See the API reference documentation.
- Fork the repo
- Make your changes in your own fork
- Make sure
yarn lint
andyarn test
pass - Create a Pull Request on this repo
Look out for *.spec.ts
in the codebase. Run:
yarn test
GPL-3.0. See LICENSE file for more information.