sg-gov-nea
Version:
API to access the Singaporean Government National Environment Agency's Dataset
145 lines (110 loc) • 4.7 kB
text/typescript
/// <reference path='typings/tsd.d.ts' />
import _ = require('lodash');
export module sg.gov.nea {
import EventEmitter = NodeJS.EventEmitter;
export interface IAPIConfig {
key?:string;
baseUrl?:string;
}
export class APIConfig implements IAPIConfig {
public key:string;
public baseUrl:string;
constructor(config:IAPIConfig) {
_.extend(this, config);
}
static defaults:IAPIConfig = {
key: '[insert_your_own_API_key]',
baseUrl: 'http://www.nea.gov.sg/api/WebAPI'
}
}
export class APIEvent {
static DATA:string = 'data';
static ERROR:string = 'error';
}
export interface IDataSet {
name:string;
on(event:string, callback:Function) : void;
}
export class DataSet implements IDataSet {
private emitter:EventEmitter;
constructor(public name:string, private config:IAPIConfig) {
this.config = _.extend({}, APIConfig.defaults, config);
var events = require('events');
this.emitter = new events.EventEmitter();
this.refresh();
}
public on(event:string, callback:Function):void {
this.emitter.addListener(event, callback);
}
public off(event:string, callback:Function):void {
this.emitter.removeListener(event, callback);
}
private refresh():void {
var context:DataSet = this;
var transport:DataSetTransport = new DataSetTransport(this.config.baseUrl + '?dataset=' + this.name + '&keyref=' + this.config.key);
transport.fetch(function (err:Error, result:any):void {
if (err) {
context.emitter.emit(APIEvent.ERROR, err);
return;
}
switch (context.name) {
case DataSet.PSI_UPDATE:
result = _.map(result.channel.item.region, function(region:any) : any {
var result:any = {
region: region.id,
latitude: parseFloat(region.latitude),
longitude: parseFloat(region.longitude),
timestamp: parseInt(region.record.timestamp),
readings: {}
};
_.each(region.record.reading, function(reading:any) : any {
_.set(result.readings, reading.type.toLowerCase(), parseFloat(reading.value));
})
return result;
})
break;
case DataSet.NOWCAST:
result = {
datentime: result.channel.item.issue_datentime,
forecasts: _.map(result.channel.item.weatherForecast.area, function(forecast:any) : any {
var result:any = {
name: _.get(forecast, 'name'),
forecast: _.trim(_.get(forecast, 'forecast').toString()),
icon: _.get(forecast, 'icon'),
zone: _.get(forecast, 'zone'),
latitude: parseFloat(_.get(forecast, 'lat').toString()),
longitude: parseFloat(_.get(forecast, 'lon').toString()),
};
return result;
})
}
break;
default:
// ignore for now
break;
}
context.emitter.emit(APIEvent.DATA, result);
})
}
static PSI_UPDATE:string = 'psi_update'
static NOWCAST:string = 'nowcast'
}
export class DataSetTransport {
constructor(private url:string) {
}
public fetch(callback:Function):void {
var request = require('request');
request(this.url, function (err:Error, response:any, body:string):void {
if (err) {
return callback(err);
}
var parser = require('xml2json');
var result = parser.toJson(body);
result = JSON.parse(result);
callback(null, result);
})
}
static END:string = 'end';
static DATA:string = 'data';
}
}