From 616a0bda6f438503525b040f08b1fd5599ef4c2a Mon Sep 17 00:00:00 2001 From: Samer Albahra Date: Sun, 22 Jul 2018 19:31:38 -0500 Subject: [PATCH] Fix unit tests and remove unused code --- models/Cache.js | 14 - package-lock.json | 183 ------ package.json | 2 - routes/weather.js | 64 +- server.js | 41 -- test/api.js | 17 +- test/expected.json | 8 +- test/replies.json | 1537 +++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 1551 insertions(+), 315 deletions(-) delete mode 100644 models/Cache.js diff --git a/models/Cache.js b/models/Cache.js deleted file mode 100644 index ef5e107..0000000 --- a/models/Cache.js +++ /dev/null @@ -1,14 +0,0 @@ -var mongoose = require( "mongoose" ); - -var cacheSchema = new mongoose.Schema( { - - // Stores the current GPS location as unique for weather data cache - location: { type: String, unique: true }, - - // This is the end of day value for the humidity yesterday - yesterdayHumidity: Number, - currentHumidityTotal: Number, - currentHumidityCount: Number -} ); - -module.exports = mongoose.model( "Cache", cacheSchema ); diff --git a/package-lock.json b/package-lock.json index 710317a..3f12fb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -170,11 +170,6 @@ "tweetnacl": "^0.14.3" } }, - "bluebird": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" - }, "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", @@ -214,21 +209,11 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "bson": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.6.tgz", - "integrity": "sha512-D8zmlb46xfuK2gGvKmUjIklQEouN2nQ0LEHHeZ/NoHM2LDiMk2EYzZ5Ntw/Urk+bgMDosOZxaRzXxvhI5TcAVQ==" - }, "buffer-from": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -474,14 +459,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cron": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/cron/-/cron-1.3.0.tgz", - "integrity": "sha512-K/SF7JlgMmNjcThWxkKvsHhey2EDB4CeOEWJ9aXWj3fbQJppsvTPIeyLdHfNq5IbbsMUUjRW1nr5dSO95f2E4w==", - "requires": { - "moment-timezone": "^0.5.x" - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1195,11 +1172,6 @@ "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" }, - "hooks-fixed": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", - "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" - }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -1481,11 +1453,6 @@ "verror": "1.10.0" } }, - "kareem": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", - "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -1529,11 +1496,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -1714,132 +1676,11 @@ "moment": ">= 2.9.0" } }, - "mongodb": { - "version": "2.2.34", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz", - "integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=", - "requires": { - "es6-promise": "3.2.1", - "mongodb-core": "2.1.18", - "readable-stream": "2.2.7" - }, - "dependencies": { - "es6-promise": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", - "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "readable-stream": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", - "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", - "requires": { - "buffer-shims": "~1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~1.0.0", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "mongodb-core": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", - "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", - "requires": { - "bson": "~1.0.4", - "require_optional": "~1.0.0" - } - }, - "mongoose": { - "version": "4.13.13", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.13.tgz", - "integrity": "sha512-QBuryf62TVwpbdsaeJS6Ym3/FlrMhp7Xa5MkuomIX+wBeOSkMR8MjIDuiMZVZmQvN8j9/FnL7uZ9DX2wIJifYw==", - "requires": { - "async": "2.6.0", - "bson": "~1.0.4", - "hooks-fixed": "2.0.2", - "kareem": "1.5.0", - "lodash.get": "4.4.2", - "mongodb": "2.2.34", - "mpath": "0.3.0", - "mpromise": "0.5.5", - "mquery": "2.3.3", - "ms": "2.0.0", - "muri": "1.3.0", - "regexp-clone": "0.0.1", - "sliced": "1.0.1" - }, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "requires": { - "lodash": "^4.14.0" - } - } - } - }, - "mpath": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", - "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" - }, - "mpromise": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", - "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" - }, - "mquery": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", - "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", - "requires": { - "bluebird": "3.5.0", - "debug": "2.6.9", - "regexp-clone": "0.0.1", - "sliced": "0.0.5" - }, - "dependencies": { - "sliced": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", - "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" - } - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "muri": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", - "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" - }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -5359,11 +5200,6 @@ "strip-indent": "^1.0.1" } }, - "regexp-clone": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", - "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -5406,25 +5242,11 @@ "uuid": "^3.1.0" } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - } - }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - }, "resolve-protobuf-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", @@ -5539,11 +5361,6 @@ "resolved": "https://registry.npmjs.org/slice-source/-/slice-source-0.4.1.tgz", "integrity": "sha1-QKV6wDxmaLXaIA4FN44AC/KmHXk=" }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" - }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", diff --git a/package.json b/package.json index 7358963..e7b5e83 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,11 @@ "test": "mocha test" }, "dependencies": { - "cron": "^1.3.0", "dotenv": "^2.0.0", "express": "^4.16.3", "geo-tz": "^4.0.1", "grunt": "^1.0.3", "moment-timezone": "^0.5.17", - "mongoose": "^4.13.13", "suncalc": "^1.8.0" }, "devDependencies": { diff --git a/routes/weather.js b/routes/weather.js index 5b3e462..f25d820 100755 --- a/routes/weather.js +++ b/routes/weather.js @@ -1,5 +1,4 @@ var http = require( "http" ), - Cache = require( "../models/Cache" ), SunCalc = require( "suncalc" ), moment = require( "moment-timezone" ), geoTZ = require( "geo-tz" ), @@ -105,14 +104,7 @@ function getOWMWeatherData( location, callback ) { location = location.join( "," ); - getCache( { - key: "yesterdayHumidity", - location: location, - weather: weather, - callback: callback - } ); - - updateCache( location, weather ); + callback( weather ); } ); } ); } @@ -135,58 +127,6 @@ function getTimeData( location, callback ) { } ); } -// Retrieve cached record for a given location -// opt is defined as an object with two required items -// opt.location defines the location for the cache record -// opt.key defines the key to return for the location -function getCache( opt, callback ) { - - // Find the cache entry for the provided location - Cache.findOne( { location: opt.location }, function( err, record ) { - - if ( err ) { - return; - } - - // If a record is found for the provided key, return it - if ( record && record[ opt.key ] !== null ) { - opt.weather[ opt.key ] = record[ opt.key ]; - } - - opt.callback( opt.weather ); - } ); -} - -// Update weather cache record in the local database -function updateCache( location, weather ) { - - // Search for a cache record for the provided location - Cache.findOne( { location: location }, function( err, record ) { - - if ( err ) { - return; - } - - // If a record is found update the data and save it - if ( record ) { - - record.currentHumidityTotal += weather.humidity; - record.currentHumidityCount++; - record.save(); - - } else { - - // If no cache record is found, generate a new one and save it - new Cache( { - location: location, - currentHumidityTotal: weather.humidity, - currentHumidityCount: 1 - } ).save(); - - } - } ); -} - // Calculates the resulting water scale using the provided weather data, adjustment method and options function calculateWeatherScale( adjustmentMethod, adjustmentOptions, weather ) { @@ -394,7 +334,7 @@ exports.getWeather = function( req, res ) { // Attempt to resolve provided location to GPS coordinates when it does not match // a GPS coordinate or Weather Underground location using Weather Underground autocomplete - resolveCoordinates( location, function( result, timezone ) { + resolveCoordinates( location, function( result ) { if ( result === false ) { res.send( "Error: Unable to resolve location" ); return; diff --git a/server.js b/server.js index 122a35d..dd5d39a 100755 --- a/server.js +++ b/server.js @@ -1,8 +1,5 @@ var express = require( "express" ), weather = require( "./routes/weather.js" ), - mongoose = require( "mongoose" ), - Cache = require( "./models/Cache" ), - CronJob = require( "cron" ).CronJob, host = process.env.HOST || "127.0.0.1", port = process.env.PORT || 3000, app = express(); @@ -13,14 +10,6 @@ if ( !process.env.HOST || !process.env.PORT ) { port = process.env.PORT || port; } -// Connect to local MongoDB instance -mongoose.connect( "mongodb://localhost", { useMongoClient: true } ); - -// If the database connection cannot be established, throw an error -mongoose.connection.on( "error", function() { - console.error( "MongoDB Connection Error. Please make sure that MongoDB is running." ); -} ); - // Handle requests matching /weatherID.py where ID corresponds to the // weather adjustment method selector. // This endpoint is considered deprecated and supported for prior firmware @@ -42,34 +31,4 @@ app.listen( port, host, function() { console.log( "OpenSprinkler Weather Service now listening on %s:%s", host, port ); } ); -// Schedule a cronjob daily to consildate the weather cache data, runs daily -new CronJob( "0 0 0 * * *", function() { - - // Find all records in the weather cache - Cache.find( {}, function( err, records ) { - - if ( err ) { - return; - } - - // Cycle through each record - records.forEach( function( record ) { - - // If the record contains any unaveraged data, then process the record - if ( record.currentHumidityCount > 0 ) { - - // Average the humidity by dividing the total over the total data points collected - record.yesterdayHumidity = record.currentHumidityTotal / record.currentHumidityCount; - - // Reset the current humidity data for the new day - record.currentHumidityTotal = 0; - record.currentHumidityCount = 0; - - // Save the record in the database - record.save(); - } - } ); - } ); -}, null, true, "UTC" ); - exports.app = app; diff --git a/test/api.js b/test/api.js index ae81fe6..7fb1185 100644 --- a/test/api.js +++ b/test/api.js @@ -15,7 +15,7 @@ describe( "Weather API", function() { loc: test, key: process.env.WU_API_KEY, expected: expected.WU[test], - callback: function( reply ) { + callback: function() { done(); } } ); @@ -30,7 +30,7 @@ describe( "Weather API", function() { method: 0, loc: test, expected: expected.noWeather[test], - callback: function( reply ) { + callback: function() { done(); } } ); @@ -69,18 +69,19 @@ function setupMocks( location ) { nock.cleanAll(); nock( "http://autocomplete.wunderground.com" ) - .filteringPath( function( path ) { - return "/"; - } ) + .filteringPath( function() { return "/"; } ) .get( "/" ) .reply( 200, replies[location].WUautoComplete ); nock( "http://api.wunderground.com" ) - .filteringPath( function( path ) { - return "/"; - } ) + .filteringPath( function() { return "/"; } ) .get( "/" ) .reply( 200, replies[location].WUyesterday ); + + nock( "http://api.openweathermap.org" ) + .filteringPath( function() { return "/"; } ) + .get( "/" ) + .reply( 200, replies[location].OWMData ); } function extend( target ) { diff --git a/test/expected.json b/test/expected.json index 023292e..3442e2e 100644 --- a/test/expected.json +++ b/test/expected.json @@ -6,7 +6,7 @@ "tz": 32, "sunrise": 324, "sunset": 1228, - "eip": 2130706433 + "eip": null } }, "noWeather": { @@ -14,9 +14,9 @@ "scale": -1, "rd": -1, "tz": 32, - "sunrise": 324, - "sunset": 1226, - "eip": 2130706433 + "sunrise": 333, + "sunset": 1221, + "eip": null } } } diff --git a/test/replies.json b/test/replies.json index 99b347c..f26d04c 100644 --- a/test/replies.json +++ b/test/replies.json @@ -1805,6 +1805,1541 @@ "since1jancoolingdegreedaysnormal": "" }] } - } + }, + "OWMData": { + "cod": "200", + "message": 0.0121, + "cnt": 39, + "list": [ + { + "dt": 1532314800, + "main": + { + "temp": 69.1, + "temp_min": 69.1, + "temp_max": 69.42, + "pressure": 997.48, + "sea_level": 1031.96, + "grnd_level": 997.48, + "humidity": 98, + "temp_kf": -0.18 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.96, + "deg": 131.503 + }, + "rain": + { + "3h": 6.735 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-23 03:00:00" + }, + { + "dt": 1532325600, + "main": + { + "temp": 69.21, + "temp_min": 69.21, + "temp_max": 69.45, + "pressure": 996.78, + "sea_level": 1031.37, + "grnd_level": 996.78, + "humidity": 97, + "temp_kf": -0.13 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.74, + "deg": 158.001 + }, + "rain": + { + "3h": 8.82 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-23 06:00:00" + }, + { + "dt": 1532336400, + "main": + { + "temp": 69.78, + "temp_min": 69.78, + "temp_max": 69.94, + "pressure": 997.33, + "sea_level": 1031.89, + "grnd_level": 997.33, + "humidity": 98, + "temp_kf": -0.09 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.18, + "deg": 142.502 + }, + "rain": + { + "3h": 1.1 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-23 09:00:00" + }, + { + "dt": 1532347200, + "main": + { + "temp": 70.9, + "temp_min": 70.9, + "temp_max": 70.97, + "pressure": 998.32, + "sea_level": 1032.97, + "grnd_level": 998.32, + "humidity": 99, + "temp_kf": -0.04 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 4.38, + "deg": 142.505 + }, + "rain": + { + "3h": 0.99 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-23 12:00:00" + }, + { + "dt": 1532358000, + "main": + { + "temp": 71.22, + "temp_min": 71.22, + "temp_max": 71.22, + "pressure": 999.38, + "sea_level": 1033.93, + "grnd_level": 999.38, + "humidity": 100, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 5.5, + "deg": 151.001 + }, + "rain": + { + "3h": 1.66 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-23 15:00:00" + }, + { + "dt": 1532368800, + "main": + { + "temp": 71.21, + "temp_min": 71.21, + "temp_max": 71.21, + "pressure": 999.52, + "sea_level": 1034.04, + "grnd_level": 999.52, + "humidity": 100, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 4.83, + "deg": 154.504 + }, + "rain": + { + "3h": 4.66 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-23 18:00:00" + }, + { + "dt": 1532379600, + "main": + { + "temp": 72.74, + "temp_min": 72.74, + "temp_max": 72.74, + "pressure": 999.64, + "sea_level": 1034.22, + "grnd_level": 999.64, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 4.85, + "deg": 154 + }, + "rain": + { + "3h": 1.97 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-23 21:00:00" + }, + { + "dt": 1532390400, + "main": + { + "temp": 72.33, + "temp_min": 72.33, + "temp_max": 72.33, + "pressure": 1000.3, + "sea_level": 1034.87, + "grnd_level": 1000.3, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.2, + "deg": 158.002 + }, + "rain": + { + "3h": 1.86 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-24 00:00:00" + }, + { + "dt": 1532401200, + "main": + { + "temp": 71.57, + "temp_min": 71.57, + "temp_max": 71.57, + "pressure": 1000.82, + "sea_level": 1035.43, + "grnd_level": 1000.82, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.72, + "deg": 154.5 + }, + "rain": + { + "3h": 0.91 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-24 03:00:00" + }, + { + "dt": 1532412000, + "main": + { + "temp": 71.29, + "temp_min": 71.29, + "temp_max": 71.29, + "pressure": 1000.59, + "sea_level": 1035.38, + "grnd_level": 1000.59, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.65, + "deg": 160.006 + }, + "rain": + { + "3h": 5.97 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-24 06:00:00" + }, + { + "dt": 1532422800, + "main": + { + "temp": 71.19, + "temp_min": 71.19, + "temp_max": 71.19, + "pressure": 1000.94, + "sea_level": 1035.56, + "grnd_level": 1000.94, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.63, + "deg": 168.006 + }, + "rain": + { + "3h": 6.07 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-24 09:00:00" + }, + { + "dt": 1532433600, + "main": + { + "temp": 71.56, + "temp_min": 71.56, + "temp_max": 71.56, + "pressure": 1001.57, + "sea_level": 1036.23, + "grnd_level": 1001.57, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.49, + "deg": 168.005 + }, + "rain": + { + "3h": 1.79 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-24 12:00:00" + }, + { + "dt": 1532444400, + "main": + { + "temp": 71.8, + "temp_min": 71.8, + "temp_max": 71.8, + "pressure": 1002.09, + "sea_level": 1036.68, + "grnd_level": 1002.09, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.29, + "deg": 171.5 + }, + "rain": + { + "3h": 6.68 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-24 15:00:00" + }, + { + "dt": 1532455200, + "main": + { + "temp": 74.25, + "temp_min": 74.25, + "temp_max": 74.25, + "pressure": 1001.8, + "sea_level": 1036.39, + "grnd_level": 1001.8, + "humidity": 93, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.96, + "deg": 173.007 + }, + "rain": + { + "3h": 0.28 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-24 18:00:00" + }, + { + "dt": 1532466000, + "main": + { + "temp": 73.58, + "temp_min": 73.58, + "temp_max": 73.58, + "pressure": 1001.45, + "sea_level": 1036.04, + "grnd_level": 1001.45, + "humidity": 92, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.18, + "deg": 176.5 + }, + "rain": + { + "3h": 0.23999999999999 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-24 21:00:00" + }, + { + "dt": 1532476800, + "main": + { + "temp": 72.28, + "temp_min": 72.28, + "temp_max": 72.28, + "pressure": 1001.25, + "sea_level": 1035.74, + "grnd_level": 1001.25, + "humidity": 93, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.29, + "deg": 174.001 + }, + "rain": + { + "3h": 0.24 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-25 00:00:00" + }, + { + "dt": 1532487600, + "main": + { + "temp": 71.1, + "temp_min": 71.1, + "temp_max": 71.1, + "pressure": 1001.35, + "sea_level": 1035.86, + "grnd_level": 1001.35, + "humidity": 96, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.8, + "deg": 171.001 + }, + "rain": + { + "3h": 0.52 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-25 03:00:00" + }, + { + "dt": 1532498400, + "main": + { + "temp": 70.36, + "temp_min": 70.36, + "temp_max": 70.36, + "pressure": 1000.02, + "sea_level": 1034.71, + "grnd_level": 1000.02, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.4, + "deg": 167.002 + }, + "rain": + { + "3h": 0.43000000000001 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-25 06:00:00" + }, + { + "dt": 1532509200, + "main": + { + "temp": 70.11, + "temp_min": 70.11, + "temp_max": 70.11, + "pressure": 999.16, + "sea_level": 1033.62, + "grnd_level": 999.16, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.18, + "deg": 169 + }, + "rain": + { + "3h": 0.89 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-25 09:00:00" + }, + { + "dt": 1532520000, + "main": + { + "temp": 70.62, + "temp_min": 70.62, + "temp_max": 70.62, + "pressure": 998.04, + "sea_level": 1032.55, + "grnd_level": 998.04, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.74, + "deg": 165.5 + }, + "rain": + { + "3h": 0.48 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-25 12:00:00" + }, + { + "dt": 1532530800, + "main": + { + "temp": 71.66, + "temp_min": 71.66, + "temp_max": 71.66, + "pressure": 997.6, + "sea_level": 1032.12, + "grnd_level": 997.6, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.96, + "deg": 171.5 + }, + "rain": + { + "3h": 0.83999999999999 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-25 15:00:00" + }, + { + "dt": 1532541600, + "main": + { + "temp": 72.81, + "temp_min": 72.81, + "temp_max": 72.81, + "pressure": 996.88, + "sea_level": 1031.32, + "grnd_level": 996.88, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 88 + }, + "wind": + { + "speed": 8.66, + "deg": 180.501 + }, + "rain": + { + "3h": 2.31 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-25 18:00:00" + }, + { + "dt": 1532552400, + "main": + { + "temp": 72.94, + "temp_min": 72.94, + "temp_max": 72.94, + "pressure": 995.81, + "sea_level": 1030.23, + "grnd_level": 995.81, + "humidity": 91, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.38, + "deg": 184.003 + }, + "rain": + { + "3h": 1.6 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-25 21:00:00" + }, + { + "dt": 1532563200, + "main": + { + "temp": 70.38, + "temp_min": 70.38, + "temp_max": 70.38, + "pressure": 994.37, + "sea_level": 1028.68, + "grnd_level": 994.37, + "humidity": 99, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.15, + "deg": 165.5 + }, + "rain": + { + "3h": 4.18 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-26 00:00:00" + }, + { + "dt": 1532574000, + "main": + { + "temp": 70.03, + "temp_min": 70.03, + "temp_max": 70.03, + "pressure": 993.56, + "sea_level": 1027.92, + "grnd_level": 993.56, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.73, + "deg": 177.5 + }, + "rain": + { + "3h": 7.35 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-26 03:00:00" + }, + { + "dt": 1532584800, + "main": + { + "temp": 70.32, + "temp_min": 70.32, + "temp_max": 70.32, + "pressure": 992.28, + "sea_level": 1026.64, + "grnd_level": 992.28, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 6.85, + "deg": 193.507 + }, + "rain": + { + "3h": 7.91 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-26 06:00:00" + }, + { + "dt": 1532595600, + "main": + { + "temp": 71.33, + "temp_min": 71.33, + "temp_max": 71.33, + "pressure": 990.85, + "sea_level": 1025.17, + "grnd_level": 990.85, + "humidity": 98, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 7.72, + "deg": 185.501 + }, + "rain": + { + "3h": 1.13 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-26 09:00:00" + }, + { + "dt": 1532606400, + "main": + { + "temp": 71.86, + "temp_min": 71.86, + "temp_max": 71.86, + "pressure": 991.04, + "sea_level": 1025.42, + "grnd_level": 991.04, + "humidity": 96, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 8.41, + "deg": 207.001 + }, + "rain": + { + "3h": 1.45 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-26 12:00:00" + }, + { + "dt": 1532617200, + "main": + { + "temp": 74.16, + "temp_min": 74.16, + "temp_max": 74.16, + "pressure": 992.9, + "sea_level": 1027.23, + "grnd_level": 992.9, + "humidity": 86, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 88 + }, + "wind": + { + "speed": 7.05, + "deg": 239.006 + }, + "rain": + { + "3h": 0.030000000000001 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-26 15:00:00" + }, + { + "dt": 1532628000, + "main": + { + "temp": 78.14, + "temp_min": 78.14, + "temp_max": 78.14, + "pressure": 993.56, + "sea_level": 1027.84, + "grnd_level": 993.56, + "humidity": 79, + "temp_kf": 0 + }, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04d" + }], + "clouds": + { + "all": 68 + }, + "wind": + { + "speed": 5.39, + "deg": 236.502 + }, + "rain": + {}, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-26 18:00:00" + }, + { + "dt": 1532638800, + "main": + { + "temp": 77.62, + "temp_min": 77.62, + "temp_max": 77.62, + "pressure": 993.99, + "sea_level": 1028.29, + "grnd_level": 993.99, + "humidity": 80, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 68 + }, + "wind": + { + "speed": 5.06, + "deg": 223.501 + }, + "rain": + { + "3h": 0.0099999999999909 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-26 21:00:00" + }, + { + "dt": 1532649600, + "main": + { + "temp": 75.02, + "temp_min": 75.02, + "temp_max": 75.02, + "pressure": 994.77, + "sea_level": 1029.14, + "grnd_level": 994.77, + "humidity": 86, + "temp_kf": 0 + }, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + }], + "clouds": + { + "all": 88 + }, + "wind": + { + "speed": 4.74, + "deg": 206.002 + }, + "rain": + {}, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-27 00:00:00" + }, + { + "dt": 1532660400, + "main": + { + "temp": 72.56, + "temp_min": 72.56, + "temp_max": 72.56, + "pressure": 995.18, + "sea_level": 1029.78, + "grnd_level": 995.18, + "humidity": 96, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 5.17, + "deg": 185.504 + }, + "rain": + { + "3h": 0.83000000000001 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-27 03:00:00" + }, + { + "dt": 1532671200, + "main": + { + "temp": 70.67, + "temp_min": 70.67, + "temp_max": 70.67, + "pressure": 994.45, + "sea_level": 1028.95, + "grnd_level": 994.45, + "humidity": 97, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 4.72, + "deg": 189.004 + }, + "rain": + { + "3h": 0.17999999999999 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-27 06:00:00" + }, + { + "dt": 1532682000, + "main": + { + "temp": 67.79, + "temp_min": 67.79, + "temp_max": 67.79, + "pressure": 993.48, + "sea_level": 1028.1, + "grnd_level": 993.48, + "humidity": 99, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 2.93, + "deg": 208.003 + }, + "rain": + { + "3h": 10.79 + }, + "sys": + { + "pod": "n" + }, + "dt_txt": "2018-07-27 09:00:00" + }, + { + "dt": 1532692800, + "main": + { + "temp": 68.66, + "temp_min": 68.66, + "temp_max": 68.66, + "pressure": 994.49, + "sea_level": 1029.03, + "grnd_level": 994.49, + "humidity": 99, + "temp_kf": 0 + }, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.4, + "deg": 230.504 + }, + "rain": + { + "3h": 4.68 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-27 12:00:00" + }, + { + "dt": 1532703600, + "main": + { + "temp": 72.18, + "temp_min": 72.18, + "temp_max": 72.18, + "pressure": 995.32, + "sea_level": 1029.81, + "grnd_level": 995.32, + "humidity": 93, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.15, + "deg": 235.508 + }, + "rain": + { + "3h": 0.22 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-27 15:00:00" + }, + { + "dt": 1532714400, + "main": + { + "temp": 73.12, + "temp_min": 73.12, + "temp_max": 73.12, + "pressure": 994.94, + "sea_level": 1029.36, + "grnd_level": 994.94, + "humidity": 91, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 92 + }, + "wind": + { + "speed": 3.15, + "deg": 213.507 + }, + "rain": + { + "3h": 0.56 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-27 18:00:00" + }, + { + "dt": 1532725200, + "main": + { + "temp": 73.63, + "temp_min": 73.63, + "temp_max": 73.63, + "pressure": 994.99, + "sea_level": 1029.36, + "grnd_level": 994.99, + "humidity": 88, + "temp_kf": 0 + }, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + }], + "clouds": + { + "all": 80 + }, + "wind": + { + "speed": 3.15, + "deg": 216.501 + }, + "rain": + { + "3h": 0.030000000000001 + }, + "sys": + { + "pod": "d" + }, + "dt_txt": "2018-07-27 21:00:00" + }], + "city": + { + "id": 4929023, + "name": "Amherst Center", + "coord": + { + "lat": 42.3754, + "lon": -72.5193 + }, + "country": "US", + "population": 19065 + } + } } }