Add support for fallback WeatherProviders
This commit is contained in:
@@ -7,7 +7,11 @@ import * as geoTZ from "geo-tz";
|
|||||||
|
|
||||||
import * as local from "./local";
|
import * as local from "./local";
|
||||||
import { AdjustmentOptions, GeoCoordinates, TimeData, WateringData, WeatherData, WeatherProvider } from "../types";
|
import { AdjustmentOptions, GeoCoordinates, TimeData, WateringData, WeatherData, WeatherProvider } from "../types";
|
||||||
const weatherProvider: WeatherProvider = require("./weatherProviders/" + ( process.env.WEATHER_PROVIDER || "OWM" ) ).default;
|
import CompositeWeatherProvider from "./weatherProviders/CompositeWeatherProvider";
|
||||||
|
|
||||||
|
const weatherProvider: WeatherProvider = new CompositeWeatherProvider(
|
||||||
|
( process.env.WEATHER_PROVIDER || "OWM" ).split( "," ).map( ( id ) => require( "./weatherProviders/" + id ).default )
|
||||||
|
);
|
||||||
|
|
||||||
// Define regex filters to match against location
|
// Define regex filters to match against location
|
||||||
const filters = {
|
const filters = {
|
||||||
|
|||||||
45
routes/weatherProviders/CompositeWeatherProvider.ts
Normal file
45
routes/weatherProviders/CompositeWeatherProvider.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { GeoCoordinates, WateringData, WeatherData, WeatherProvider } from "../../types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WeatherProvider calls other WeatherProviders until one successfully returns a value.
|
||||||
|
* This is a special utility WeatherProvider, and should NOT be selected with the WEATHER_PROVIDER environment variable.
|
||||||
|
*/
|
||||||
|
export default class CompositeWeatherProvider implements WeatherProvider {
|
||||||
|
|
||||||
|
private readonly weatherProviders: WeatherProvider[];
|
||||||
|
|
||||||
|
public constructor( weatherProviders: WeatherProvider[] ) {
|
||||||
|
this.weatherProviders = weatherProviders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getWateringData( coordinates : GeoCoordinates ): Promise< WateringData > {
|
||||||
|
return await this.callMethod( "getWateringData", coordinates ) as WateringData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getWeatherData( coordinates : GeoCoordinates ): Promise< WeatherData > {
|
||||||
|
return await this.callMethod( "getWeatherData", coordinates ) as WeatherData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a specified function in each WeatherProvider until one returns a non-undefined value. If the function is
|
||||||
|
* not defined for a WeatherProvider, it will be skipped.
|
||||||
|
* @param func The name of the function to call.
|
||||||
|
* @param args The arguments to pass to the function.
|
||||||
|
* @return A promise that will be resolved with the first non-undefined value returned by a WeatherProvider, or
|
||||||
|
* resolved with undefined if none of the WeatherProviders returned a value.
|
||||||
|
*/
|
||||||
|
private async callMethod( func: "getWateringData" | "getWeatherData", ...args: any ): Promise< unknown > {
|
||||||
|
for ( const weatherProvider of this.weatherProviders ) {
|
||||||
|
if ( !weatherProvider[ func ] ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const result = await weatherProvider[ func ]( ...args );
|
||||||
|
if ( result ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user