Skip to content

Instantly share code, notes, and snippets.

@maccyber
Last active December 2, 2016 10:52
Show Gist options
  • Save maccyber/2a706be08fb55a5bc2646d7b6c4a32f2 to your computer and use it in GitHub Desktop.
Save maccyber/2a706be08fb55a5bc2646d7b6c4a32f2 to your computer and use it in GitHub Desktop.
/**
* This code is responsible for implementing all methods related to fetching
* and returning data for the Norwegian data sources.
*/
'use strict';
import { REQUEST_TIMEOUT } from '../lib/constants';
import { default as baseRequest } from 'request';
const request = baseRequest.defaults({timeout: REQUEST_TIMEOUT});
import { default as moment } from 'moment-timezone';
import log from '../lib/logger';
exports.name = 'norway';
/**
* Fetches the data for a given source and returns an appropriate object
* @param {object} source A valid source object
* @param {function} cb A callback of the form cb(err, data)
*/
exports.fetchData = function (source, cb) {
request(source.url, function (err, res, body) {
if (err || res.statusCode !== 200) {
log.error(err || res.statusCode);
return cb({message: 'Failure to load data url.'});
}
// Wrap everything in a try/catch in case something goes wrong
try {
// Format the data
const data = formatData(body);
// Make sure the data is valid
if (data === undefined) {
return cb({message: 'Failure to parse data.'});
}
cb(null, data);
} catch (e) {
return cb({message: 'Unknown adapter error.'});
}
});
};
/**
* Given fetched data, turn it into a format our system can use.
* @param {array} results Fetched source data and other metadata
* @return {object} Parsed and standarized data our system can use
*/
const formatData = function (data) {
// Wrap the JSON.parse() in a try/catch in case it fails
try {
data = JSON.parse(data);
} catch (e) {
// Return undefined to be caught elsewhere
return undefined;
}
/**
* Given a json object, convert to aq openaq format
* @param {json object} item coming from source data
* @return {object} a repacked object
*/
const aqRepack = (item) => {
const dateMoment = moment.tz(item.fromTime, 'YYYY-MM-DD HH:mm', 'Europe/Oslo');
const template = {
name: item.station,
measurements: [
{
parameter: item.component,
date: {
utc: dateMoment.toDate(),
local: dateMoment.format()
},
coordinates: {
latitude: item.latitude,
longitude: item.longitude
},
value: item.value,
unit: item.unit
}
]
};
return template;
};
// Maps array to aq-format
const result = [...data.map(aqRepack).reduce((m, o) => {
const name = o.name.toLowerCase();
let obj = m.get(name);
return obj ? m.set(name, {
name: name,
measurements: [...new Set(obj.measurements.concat(o.measurements))]
})
: m.set(name, o);
},
new Map()
).values()
];
return result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment