Added weather stuff and start of server tidyup
This commit is contained in:
parent
e0d8922c04
commit
378de8b4e4
55
.eslintrc.json
Normal file
55
.eslintrc.json
Normal 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
152
.gitignore
vendored
Normal 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
152
.ignore
Normal 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
|
79
newapp.js
79
newapp.js
@ -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')}`);
|
||||
});
|
||||
|
30
package.json
30
package.json
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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
0
routes/trains.js
Normal file
96
server/lib/geocode.js
Normal file
96
server/lib/geocode.js
Normal 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
118
server/lib/weather.js
Normal 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 };
|
62
server/reducers/opencage.js
Normal file
62
server/reducers/opencage.js
Normal 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
154
server/reducers/weather.js
Normal 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
97
server/routes/weather.js
Normal 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;
|
Loading…
Reference in New Issue
Block a user