Added weather stuff and start of server tidyup

This commit is contained in:
Martin Donnelly 2020-02-03 14:45:22 +00:00
parent e0d8922c04
commit 378de8b4e4
12 changed files with 952 additions and 46 deletions

55
.eslintrc.json Normal file
View File

@ -0,0 +1,55 @@
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": false
}
},
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"arrow-spacing": "error",
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": ["error", "stroustrup", {}],
"camelcase": "error",
"comma-dangle": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"comma-style": [1, "last"],
"consistent-this": [1, "_this"],
"curly": [1, "multi"],
"eol-last": 1,
"eqeqeq": 1,
"func-names": 1,
"indent": ["error", 2, { "SwitchCase": 1 }],
"lines-around-comment": ["error", { "beforeBlockComment": true, "allowArrayStart": true }],
"max-len": [1, 120, 2], // 2 spaces per tab, max 80 chars per line
"new-cap": 1,
"newline-before-return": "error",
"no-array-constructor": 1,
"no-inner-declarations": [1, "both"],
"no-mixed-spaces-and-tabs": 1,
"no-multi-spaces": 2,
"no-new-object": 1,
"no-shadow-restricted-names": 1,
"object-curly-spacing": ["error", "always"],
"padded-blocks": ["error", { "blocks": "never", "switches": "always" }],
"prefer-const": "error",
"prefer-template": "error",
"one-var": 0,
"quote-props": ["error", "always"],
"quotes": [1, "single"],
"radix": 1,
"semi": [1, "always"],
"space-before-blocks": [1, "always"],
"space-infix-ops": 1,
"vars-on-top": 1,
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
"spaced-comment": ["error", "always", { "markers": ["/"] }]
}
}

152
.gitignore vendored Normal file
View File

@ -0,0 +1,152 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml
/src/bundle.js
/src/bundle.js.map
/src/react/bundle.js
/src/backbone/bundle.js
/src/react/bundle.js.map
/src/es2016/bundle.js
/src/es2016/bundle.js.map
/src/backbone/bundle.js.map

152
.ignore Normal file
View File

@ -0,0 +1,152 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml
/src/bundle.js
/src/bundle.js.map
/src/react/bundle.js
/src/backbone/bundle.js
/src/react/bundle.js.map
/src/es2016/bundle.js
/src/es2016/bundle.js.map
/src/backbone/bundle.js.map

View File

@ -1,47 +1,56 @@
var express = require('express'), path = require('path'), http = require('http'),
require('dotenv').config();
const express = require('express');
const path = require('path');
const http = require('http');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const routes = require('./routes/index');
const users = require('./routes/users');
const timeroute = require('./routes/time');
const btcroute = require('./routes/btc');
const temproute = require('./routes/temp');
const weightroute = require('./routes/weight');
const weatherRoute = require('./server/routes/weather');
favicon = require('serve-favicon'),
logger = require('morgan'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
const app = express();
GLOBAL.lastcheck = { 'btc': 0, 'fx': 0 };
routes = require('./routes/index'),
users = require('./routes/users'),
app.set('port', process.env.PORT || 8030);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ 'extended': true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
timeroute = require('./routes/time'),
btcroute = require('./routes/btc'),
temproute = require('./routes/temp'),
weightroute = require('./routes/weight')
//train = require('lib/train')
/* ,submit = require('./routes/mongo/submit') */
;
var app = express();
GLOBAL.lastcheck = {"btc": 0, "fx": 0};
app.use('/', routes);
// app.use('/users', users);
app.use('/time', timeroute);
app.use('/btc', btcroute);
app.use('/temp', temproute);
app.use('/weight', weightroute);
app.use('/weather', weatherRoute);
app.set('port', process.env.PORT || 8030);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
//app.use('/users', users);
app.use('/time', timeroute);
app.use('/btc', btcroute);
app.use('/temp',temproute);
app.use('/weight',weightroute);
// Handle 404
app.use((req, res) => {
res.status(404).send('404: Page not Found');
});
// Handle 500
app.use((error, req, res, next) => {
console.log(error);
res.status(500).send('500: Internal Server Error');
});
/**
* create the server
*/
app.listen(app.get('port'), function () {
console.log('APIServer listening on ' + app.get('port'));
});
app.listen(app.get('port'), function() {
console.log(`APIServer listening on ${ app.get('port')}`);
});

View File

@ -6,19 +6,27 @@
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "~2.3.3",
"events": "^1.1.0",
"express": "~4.13.1",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.4",
"debug": "^4.1.1",
"dotenv": "^8.2.0",
"ejs": "^2.7.1",
"eslint": "^6.8.0",
"events": "^3.0.0",
"express": "^4.17.1",
"express-promise-router": "^3.0.3",
"fecha": "^4.0.0",
"lodash": "^4.17.15",
"morgan": "^1.9.1",
"node-geocoder": "^3.25.0",
"openweather-apis": "^4.1.0",
"request-json": "^0.6.4",
"serve-favicon": "^2.5.0",
"websocket": "^1.0.22",
"ws": "^1.0.1"
"ws": "^7.1.2"
},
"devDependencies": {
"log4js": "^0.6.31",
"sqlite3": "~3.1.1"
"log4js": "^5.2.1",
"sqlite3": "^4.1.0"
}
}

View File

@ -1,5 +1,6 @@
var express = require('express');
var router = express.Router();
var debug = require('debug')('silvrapi:time');
/* GET users listing. */
router.get('/', function(req, res, next) {
@ -20,6 +21,8 @@ router.get('/', function(req, res, next) {
var t = {"zulu":now, "utc":now.toUTCString(),"date":date, "time":time};
debug(t);
res.writeHead(200, {"ContentType": "application/json"});
//res.send(JSON.stringify(t));
res.end(JSON.stringify(t));

0
routes/trains.js Normal file
View File

96
server/lib/geocode.js Normal file
View File

@ -0,0 +1,96 @@
const NodeGeocoder = require('node-geocoder');
const logger = require('log4js').getLogger('GeoCode');
const { reduceOpencage } = require('../reducers/opencage');
logger.level = 'debug';
const options = {
'provider': 'opencage',
// Optional depending on the providers
'httpAdapter': 'https', // Default
'apiKey': '893ab539eca84b5ca7a54cb03ef23443', // for Mapquest, OpenCage, Google Premier
'formatter': null // 'gpx', 'string', ...
};
const geocoder = NodeGeocoder(options);
function doGetGeocode(ll) {
return new Promise((resolve, reject) => {
const [lat, lon ] = ll.split(',');
const latlong = { lat, lon };
logger.debug(latlong);
geocoder.reverse(latlong)
.then(function(res) {
if (res.hasOwnProperty('raw')) {
const result = reduceOpencage(res.raw);
return resolve(result[0]);
}
else
return resolve(res[0]);
})
.catch(function(err) {
logger.error(err);
return reject(err);
});
});
}
module.exports = { doGetGeocode };
/*
opencage
{
"latitude": 51.508751,
"longitude": -0.067457,
"country": "United Kingdom",
"city": "London",
"state": "England",
"zipcode": "SE15",
"streetName": "Vaughan Way",
"countryCode": "gb",
"suburb": "St.George in the East",
"extra": {
"flag": "🇬🇧",
"confidence": 9,
"confidenceKM": 0.5,
"map": "https://www.openstreetmap.org/?mlat=51.50875&mlon=-0.06746#map=17/51.50875/-0.06746"
}
}
google
[
{
"administrativeLevels": {
"level1long": "England",
"level1short": "England",
"level2long": "Northamptonshire",
"level2short": "Northamptonshire"
},
"city": "Northampton",
"country": "United Kingdom",
"countryCode": "GB",
"extra": {
"confidence": 0.7,
"establishment": "Daventy depot",
"googlePlaceId": "ChIJI8H0WFUVd0gRIIFzNwDQAuM",
"neighborhood": "Kilsby",
"premise": null,
"subpremise": null
},
"formattedAddress": "Daventy depot, Kilsby, Northampton NN6 7GY, UK",
"latitude": 52.3546726,
"longitude": -1.1741823,
"provider": "google",
"zipcode": "NN6 7GY"
}
]
*/

118
server/lib/weather.js Normal file
View File

@ -0,0 +1,118 @@
const Client = require('request-json');
const logger = require('log4js').getLogger('Weather');
const weather = require('openweather-apis');
const { reduceWeather } = require('../reducers/weather');
const request = require('request');
logger.level = 'debug';
logger.label = 'Weather';
const openWeatherApiKey = process.env.openweatherAPI || '';
const darkskyApiKey = process.env.darkskyApiKey || '';
const dsURL = `https://api.darksky.net/forecast/${ darkskyApiKey }/`;
const DSclient = Client.createClient(`https://api.darksky.net/forecast/${ darkskyApiKey }/`);
weather.setAPPID(openWeatherApiKey);
weather.setLang('en');
// weather.setCity('Glasgow City');
function doGetOpenWeather(ll) {
const [lat, long ] = ll.split(',');
return new Promise((resolve, reject) => {
weather.setCoordinate(lat, long);
weather.getWeatherForecast( function(err, wData) {
if (err)
return reject(err);
else
return resolve(wData);
});
});
}
function doGetOpenWeatherForecast(ll) {
const [lat, long ] = ll.split(',');
return new Promise((resolve, reject) => {
weather.setCoordinate(lat, long);
weather.getWeatherForecastForDays(5, function(err, wData) {
if (err)
return reject(err);
else
return resolve(wData);
});
});
}
function doGetDarkSkyWeather(ll) {
const query = `${ll}?units=uk2&exclude=daily,flags,minutely,hourly`;
logger.debug(`https://api.darksky.net/forecast/${ darkskyApiKey }/${query}`);
return new Promise((resolve, reject) => {
DSclient.get(query, function(err, res, body) {
if (err || !body || !body.currently)
return reject(err);
return resolve(body);
});
});
}
function doGetFullForcast(ll) {
const query = `${ll}?units=uk2&exclude=flags,minutely`;
logger.debug('doGetFullForcast');
logger.debug(query);
return new Promise((resolve, reject) => {
DSclient.get(query, function(err, res, body) {
if (err || !body || !body.currently)
return reject(err);
const output = reduceWeather(body);
return resolve(output);
});
});
}
function doGetFullForcastV2(ll) {
const query = `${ll}?units=uk2&exclude=flags,minutely`;
logger.debug('doGetFullForcastV2');
const url = `${dsURL}${query}`;
logger.debug(url);
return new Promise(function(resolve, reject) {
request.get({ 'url':url }, function(err, resp, body) {
if (err) {
logger.error(err);
return reject(err);
}
// Logger.error(err);
// return reject(err);
// Throw err;
console.log;
const output = reduceWeather(body);
output.fullBody = JSON.parse(body);
output.timestamp = new Date().getTime();
console.log(output);
return resolve(output);
}, function(error, response, body) {
console.log(response);
if (response.statusCode !== 200) {
logger.error(response.statusCode);
logger.error(body);
return reject(error);
}
});
});
}
module.exports = { doGetOpenWeather, doGetOpenWeatherForecast, doGetDarkSkyWeather, doGetFullForcast, doGetFullForcastV2 };

View File

@ -0,0 +1,62 @@
const logger = require('log4js').getLogger('GeoCode 🔧');
const { get, isEmpty, has, uniq } = require('lodash');
logger.level = 'debug';
var ConfidenceInKM = {
'10': 0.25,
'9': 0.5,
'8': 1,
'7': 5,
'6': 7.5,
'5': 10,
'4': 15,
'3': 20,
'2': 25,
'1': Number.POSITIVE_INFINITY,
'0': Number.NaN
};
function formatResult (result) {
var confidence = result.confidence || 0;
return {
'latitude': result.geometry.lat,
'longitude': result.geometry.lng,
'country': result.components.country,
'city': result.components.city,
'town': result.components.town,
'state': result.components.state,
'zipcode': result.components.postcode,
'streetName': result.components.road,
'streetNumber': result.components.house_number,
'countryCode': result.components.country_code,
'county': result.components.county,
'suburb': result.components.suburb,
'neighbourhood' : result.components.neighbourhood,
'village' : result.components.village,
'formatted' : result.formatted,
'target' : result.components.village || result.components.town || result.components.city,
'extra': {
'flag' : result.annotations.flag,
'confidence': confidence,
'confidenceKM': ConfidenceInKM[result.confidence] || Number.NaN,
'map' : result.annotations.OSM.url
}
};
}
function reduceOpencage(result) {
logger.debug(JSON.stringify(result));
const results = [];
if (result && result.results instanceof Array)
for (let i = 0; i < result.results.length; i++)
results.push(formatResult(result.results[i]));
return results;
}
module.exports = { reduceOpencage };

154
server/reducers/weather.js Normal file
View File

@ -0,0 +1,154 @@
const logger = require('log4js').getLogger('Weather 🔧');
const fecha = require('fecha');
const { get } = require('lodash');
logger.level = 'debug';
function getTodaysForcast(hourlyData) {
const data = get(hourlyData, 'data', []);
const output = [];
const now = new Date().getTime();
const nowToHour = now - (now % 3600000);
const tomorrow = nowToHour + (60 * 1000 * 60 * 24);
for (const item of data) {
const time = item.time * 1000;
if (!(time < nowToHour || time > tomorrow)) {
// logger.debug(item);
const newItem = { 'time': fecha.format(time, 'h A'), 'icon': item.icon, 'temp': item.temperature, 'precip': item.precipProbability };
output.push(newItem);
}
}
return output;
}
function getDailyForcast(dailyData) {
const data = get(dailyData, 'data', []);
const output = [];
const h24 = (60 * 1000 * 60 * 24);
const now = new Date().getTime();
const startODBase = new Date();
startODBase.setHours(0, 0, 0, 0);
const startOD = startODBase.getTime();
const endOD = startOD + h24 - 1;
logger.debug('startOD', fecha.format(new Date(startOD), 'default'));
logger.debug('endOD', fecha.format(new Date(endOD), 'default'));
for (const item of data) {
const time = item.time * 1000;
if (!(time < endOD)) {
// logger.debug(item);
const newItem = {
'time': fecha.format(time, 'dddd'),
'icon': item.icon,
'tempHigh': item.temperatureHigh,
'tempLow': item.temperatureLow,
'precip': item.precipProbability,
'precipType': item.precipType
};
output.push(newItem);
}
}
return output;
}
function toCompass(degrees) {
return ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'][Math.round(degrees / 11.25 / 2)];
}
function moonCalc(moonPhase) {
let output = '';
if (moonPhase === 0.0)
output = '🌕 New moon';
else if (moonPhase >= 0.1 && moonPhase < 0.25)
output = '🌔 waxing crescent';
else if (moonPhase === 0.25)
output = '🌓 First Quarter';
else if (moonPhase > 0.25 && moonPhase < 0.5)
output = '🌒 waxing gibbous';
else if (moonPhase === 0.5)
output = '🌑 Full moon';
else if (moonPhase > 0.5 && moonPhase < 0.75)
output = '🌘 Waning gibbous';
else if (moonPhase === 0.5)
output = '🌗 Third quarter';
else if (moonPhase > 0.75)
output = '🌖 Waning crescent';
return output;
// ['🌑', '🌘', '🌗', '🌖', '🌕', '🌔', '🌓', '🌒']
// a value of 0 corresponds to a new moon, 0.25 to a first quarter moon, 0.5 to a full moon, and 0.75 to a last quarter moon. (The ranges
// in between these represent waxing crescent, waxing gibbous, waning gibbous, and waning crescent moons, respectively.)
}
function getDetails(dailyData) {
const data = get(dailyData, 'data', []);
const today = data[0];
const output = {};
output.summary = dailyData.summary;
output.icon = dailyData.icon;
output.humidity = today.humidity;
output.visibility = today.visibility;
output.uvIndex = today.uvIndex;
output.sunriseTime = fecha.format(today.sunriseTime * 1000, 'shortTime');
output.sunsetTime = fecha.format(today.sunsetTime * 1000, 'shortTime');
output.moonphase = moonCalc(today.moonPhase);
output.moonPhaseVal = today.moonPhase;
output.windSpeed = today.windSpeed;
output.pressure = today.pressure;
return output;
}
function reduceWeather(body = '') {
if (body === '') return {};
const obj = {};
const { currently, daily, hourly } = body;
const today = daily.data[0];
const outCurrent = {};
outCurrent.icon = get(currently, 'icon');
outCurrent.temperature = get(currently, 'temperature');
outCurrent.summary = get(currently, 'summary');
outCurrent.precip = get(currently, 'precipProbability');
outCurrent.precipType = get(currently, 'precipType');
outCurrent.tempMax = get(today, 'temperatureMax');
outCurrent.tempMin = get(today, 'temperatureMin');
outCurrent.windBearing = get(today, 'windBearing');
outCurrent.windBearingRead = toCompass(get(today, 'windBearing'));
const forcastToday = getTodaysForcast(hourly);
const dailyForecast = getDailyForcast(daily);
const details = getDetails(daily);
obj.currently = outCurrent;
obj.forcastToday = forcastToday;
obj.dailyForecast = dailyForecast;
obj.details = details;
obj.time = get(currently, 'time');
return obj;
}
module.exports = { reduceWeather };
//
/*
moonPhase optional, only on daily
The fractional part of the lunation number during the given day: a value of 0 corresponds to a new moon, 0.25 to a first quarter
moon, 0.5 to a full moon, and 0.75 to a last quarter moon. (The ranges in between these represent waxing crescent, waxing gibbous,
waning gibbous, and waning crescent moons, respectively.)
*/

97
server/routes/weather.js Normal file
View File

@ -0,0 +1,97 @@
var router = require('express-promise-router')();
const weather = require('../lib/weather');
const logger = require('log4js').getLogger('simpleWeather');
logger.level = 'debug';
/*
OpenWeather:
/ow/forecast
/ow/fullforecast
DarkSkies
/ds/forecast
/ds/fullforecast
*/
router.get('/ow/forecast', async (req, res, next) => {
if (req.query.hasOwnProperty('ll')) {
const ll = req.query.ll;
const weatherData = await weather.doGetOpenWeather(ll);
res.send(weatherData);
}
else {
// throw new Error('Weather: LL missing');
logger.warn('FS: LL missing');
res.status(500).send('LL Missing');
}
});
router.get('/ow/fullforecast', async (req, res, next) => {
if (req.query.hasOwnProperty('ll')) {
const ll = req.query.ll;
const weatherData = await weather.doGetOpenWeatherForecast(ll);
res.send(weatherData);
}
else {
// throw new Error('Weather: LL missing');
logger.warn('FS: LL missing');
res.status(500).send('LL Missing');
}
});
router.get('/ds/forecast', async (req, res, next) => {
if (req.query.hasOwnProperty('ll')) {
const ll = req.query.ll;
const weatherData = await weather.doGetDarkSkyWeather(ll);
res.send(weatherData);
}
else {
// throw new Error('Weather: LL missing');
logger.warn('FS: LL missing');
res.status(500).send('LL Missing');
}
});
router.get('/ds/fullforecast', async (req, res, next) => {
if (req.query.hasOwnProperty('ll')) {
const ll = req.query.ll;
const weatherData = await weather.doGetFullForcast(ll);
res.send(weatherData);
}
else {
// throw new Error('Weather: LL missing');
logger.warn('FS: LL missing');
res.status(500).send('LL Missing');
}
});
module.exports = router;