From 16e913caf368faad5f5159e47fb2ccaf6b222d1a Mon Sep 17 00:00:00 2001 From: Matthew Oslan Date: Mon, 13 May 2019 15:14:06 -0400 Subject: [PATCH] Add support for DarkSky API --- routes/weather.ts | 2 +- routes/weatherProviders/DarkSky.ts | 83 ++++++++++++++++++++++++++++++ types.ts | 12 +++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 routes/weatherProviders/DarkSky.ts diff --git a/routes/weather.ts b/routes/weather.ts index ac9a91f..ab966c8 100644 --- a/routes/weather.ts +++ b/routes/weather.ts @@ -337,7 +337,7 @@ export const getWateringData = async function( req: express.Request, res: expres eip: ipToInt( remoteAddress ), // TODO this may need to be changed (https://github.com/OpenSprinkler/OpenSprinkler-Weather/pull/11#issuecomment-491037948) rawData: { - h: wateringData ? wateringData.humidity : null, + h: wateringData ? Math.round( wateringData.humidity * 100) / 100 : null, p: wateringData ? Math.round( wateringData.precip * 100 ) / 100 : null, t: wateringData ? Math.round( wateringData.temp * 10 ) / 10 : null, raining: wateringData ? ( wateringData.raining ? 1 : 0 ) : null diff --git a/routes/weatherProviders/DarkSky.ts b/routes/weatherProviders/DarkSky.ts new file mode 100644 index 0000000..4f1b19a --- /dev/null +++ b/routes/weatherProviders/DarkSky.ts @@ -0,0 +1,83 @@ +import { GeoCoordinates, WateringData, WeatherData, WeatherProvider } from "../../types"; +import { httpJSONRequest } from "../weather"; + +async function getDarkSkyWateringData( coordinates: GeoCoordinates ): Promise< WateringData > { + const DARKSKY_API_KEY = process.env.DARKSKY_API_KEY, + forecastUrl = `https://api.darksky.net/forecast/${DARKSKY_API_KEY}/${coordinates[0]},${coordinates[1]}`; + + let forecast; + try { + forecast = await httpJSONRequest( forecastUrl ); + } catch (err) { + // Indicate watering data could not be retrieved if an API error occurs. + return undefined; + } + + + let totalTemp = 0, + totalHumidity = 0, + totalPrecip = 0; + + const periods = Math.min( forecast.hourly.data.length, 30 ); + for ( let index = 0; index < periods; index++ ) { + totalTemp += forecast.hourly.data[ index ].temperature; + totalHumidity += forecast.hourly.data[ index ].humidity * 100; + totalPrecip += forecast.hourly.data[ index ].precipIntensity; + } + + return { + temp: totalTemp / periods, + humidity: totalHumidity / periods, + precip: totalPrecip, + raining: forecast.currently.precipType === "rain" + }; +} + +async function getDarkSkyWeatherData( coordinates: GeoCoordinates ): Promise< WeatherData > { + const DARKSKY_API_KEY = process.env.DARKSKY_API_KEY, + forecastUrl = `https://api.darksky.net/forecast/${DARKSKY_API_KEY}/${coordinates[0]},${coordinates[1]}`; + + let forecast; + try { + forecast = await httpJSONRequest( forecastUrl ); + } catch (err) { + // Indicate watering data could not be retrieved if an API error occurs. + return undefined; + } + + const weather: WeatherData = { + temp: Math.floor( forecast.currently.temperature ), + humidity: Math.floor( forecast.currently.humidity * 100 ), + wind: Math.floor( forecast.currently.windSpeed ), + description: forecast.currently.summary, + // TODO set this + icon: "", + + region: "", + city: "", + minTemp: Math.floor( forecast.daily.data[ 0 ].temperatureLow ), + maxTemp: Math.floor( forecast.daily.data[ 0 ].temperatureHigh ), + precip: forecast.daily.data[ 0 ].precipIntensity * 24, + forecast: [] + }; + + for ( let index = 0; index < forecast.daily.data.length; index++ ) { + weather.forecast.push( { + temp_min: Math.floor( forecast.daily.data[ index ].temperatureLow ), + temp_max: Math.floor( forecast.daily.data[ index ].temperatureHigh ), + date: forecast.daily.data[ index ].time, + // TODO set this + icon: "", + description: forecast.daily.data[ index ].summary + } ); + } + + return weather; +} + + +const DarkSkyWeatherProvider: WeatherProvider = { + getWateringData: getDarkSkyWateringData, + getWeatherData: getDarkSkyWeatherData +}; +export default DarkSkyWeatherProvider; diff --git a/types.ts b/types.ts index b9493f9..ba856ea 100644 --- a/types.ts +++ b/types.ts @@ -17,22 +17,34 @@ export interface WeatherData { temp: number; /** The current humidity (as a percentage). */ humidity: number; + /** The current wind speed (in miles per hour). */ wind: number; + /** A human-readable description of the weather. */ description: string; + /** An icon ID that represents the current weather. This will be used in http://openweathermap.org/img/w/.png */ icon: string; region: string; city: string; + /** The forecasted minimum temperature for the current day (in Fahrenheit). */ minTemp: number; + /** The forecasted minimum temperature for the current day (in Fahrenheit). */ maxTemp: number; + /** The forecasted total precipitation for the current day (in inches). */ precip: number; forecast: WeatherDataForecast[] } +/** The forecasted weather for a specific day in the future. */ export interface WeatherDataForecast { + /** The forecasted minimum temperature for this day (in Fahrenheit). */ temp_min: number; + /** The forecasted maximum temperature for this day (in Fahrenheit). */ temp_max: number; + /** The timestamp of the day this forecast is for (in Unix epoch seconds). */ date: number; + /** An icon ID that represents the weather at this forecast window. This will be used in http://openweathermap.org/img/w/.png */ icon: string; + /** A human-readable description of the weather. */ description: string; }