Merge branch 'dev' into minor-fixes

This commit is contained in:
Matthew Oslan
2019-06-30 16:40:41 -04:00
committed by GitHub
12 changed files with 165 additions and 68 deletions

View File

@@ -1,6 +1,6 @@
import * as moment from "moment-timezone";
import { GeoCoordinates, WateringData, WeatherData } from "../../types";
import { GeoCoordinates, WeatherData, ZimmermanWateringData } from "../../types";
import { httpJSONRequest } from "../weather";
import { WeatherProvider } from "./WeatherProvider";
@@ -16,7 +16,7 @@ export default class DarkSkyWeatherProvider extends WeatherProvider {
}
}
public async getWateringData( coordinates: GeoCoordinates ): Promise< WateringData > {
public async getWateringData( coordinates: GeoCoordinates ): Promise< ZimmermanWateringData > {
// The Unix timestamp of 24 hours ago.
const yesterdayTimestamp: number = moment().subtract( 1, "day" ).unix();
const todayTimestamp: number = moment().unix();

View File

@@ -1,4 +1,4 @@
import { GeoCoordinates, WateringData, WeatherData } from "../../types";
import { GeoCoordinates, WeatherData, ZimmermanWateringData } from "../../types";
import { httpJSONRequest } from "../weather";
import { WeatherProvider } from "./WeatherProvider";
@@ -14,7 +14,7 @@ export default class OWMWeatherProvider extends WeatherProvider {
}
}
public async getWateringData( coordinates: GeoCoordinates ): Promise< WateringData > {
public async getWateringData( coordinates: GeoCoordinates ): Promise< ZimmermanWateringData > {
const forecastUrl = `http://api.openweathermap.org/data/2.5/forecast?appid=${ this.API_KEY }&units=imperial&lat=${ coordinates[ 0 ] }&lon=${ coordinates[ 1 ] }`;
// Perform the HTTP request to retrieve the weather data

View File

@@ -0,0 +1,44 @@
import { GeoCoordinates, PWS, WeatherData, ZimmermanWateringData } from "../../types";
import { WeatherProvider } from "./WeatherProvider";
import { httpJSONRequest } from "../weather";
export default class WUnderground extends WeatherProvider {
async getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
if ( !pws ) {
throw "WUnderground WeatherProvider requires a PWS to be specified.";
}
const url = `https://api.weather.com/v2/pws/observations/hourly/7day?stationId=${ pws.id }&format=json&units=e&apiKey=${ pws.apiKey }`;
let data;
try {
data = await httpJSONRequest( url );
} catch ( err ) {
console.error( "Error retrieving weather information from WUnderground:", err );
throw "An error occurred while retrieving weather information from WUnderground."
}
// Take the 24 most recent observations.
const samples = data.observations.slice( -24 );
// Fail if not enough data is available.
if ( samples.length !== 24 ) {
throw "Insufficient data was returned by WUnderground.";
}
const totals = { temp: 0, humidity: 0, precip: 0 };
for ( const sample of samples ) {
totals.temp += sample.imperial.tempAvg;
totals.humidity += sample.humidityAvg;
totals.precip += sample.imperial.precipRate;
}
return {
weatherProvider: "WUnderground",
temp: totals.temp / samples.length,
humidity: totals.humidity / samples.length,
precip: totals.precip,
raining: samples[ samples.length - 1 ].imperial.precipRate > 0
}
}
}

View File

@@ -1,14 +1,16 @@
import { GeoCoordinates, WateringData, WeatherData } from "../../types";
import { GeoCoordinates, PWS, WeatherData, ZimmermanWateringData } from "../../types";
export class WeatherProvider {
/**
* Retrieves weather data necessary for watering level calculations.
* Retrieves weather data necessary for Zimmerman watering level calculations.
* @param coordinates The coordinates to retrieve the watering data for.
* @return A Promise that will be resolved with the WateringData if it is successfully retrieved,
* or rejected with an error message if an error occurs while retrieving the WateringData or the WeatherProvider
* @param pws The PWS to retrieve the weather from, or undefined if a PWS should not be used. If the implementation
* of this method does not have PWS support, this parameter may be ignored and coordinates may be used instead.
* @return A Promise that will be resolved with the ZimmermanWateringData if it is successfully retrieved,
* or rejected with an error message if an error occurs while retrieving the ZimmermanWateringData or the WeatherProvider
* does not support this method.
*/
getWateringData( coordinates : GeoCoordinates ): Promise< WateringData > {
getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
throw "Selected WeatherProvider does not support getWateringData";
}

View File

@@ -1,6 +1,6 @@
import * as express from "express";
import { CronJob } from "cron";
import { GeoCoordinates, WateringData } from "../../types";
import { GeoCoordinates, ZimmermanWateringData } from "../../types";
import { WeatherProvider } from "./WeatherProvider";
const count = { temp: 0, humidity: 0 };
@@ -46,9 +46,9 @@ export const captureWUStream = function( req: express.Request, res: express.Resp
export default class LocalWeatherProvider extends WeatherProvider {
public async getWateringData( coordinates: GeoCoordinates ): Promise< WateringData > {
const result: WateringData = {
...yesterday as WateringData,
public async getWateringData( coordinates: GeoCoordinates ): Promise< ZimmermanWateringData > {
const result: ZimmermanWateringData = {
...yesterday as ZimmermanWateringData,
// Use today's weather if we dont have information for yesterday yet (i.e. on startup)
...today,
// PWS report "buckets" so consider it still raining if last bucket was less than an hour ago