Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function makeCodedError( err: any ): CodedError {
if ( err instanceof CodedError ) {
return err;
} else {
console.error("Unexpected error:", err);
console.error("Unexpected error:", err);
return new CodedError( ErrorCode.UnexpectedError );
}
}
2 changes: 1 addition & 1 deletion src/routes/weatherProviders/AccuWeather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default class AccuWeatherWeatherProvider extends WeatherProvider {

const cloudCoverInfo: CloudCoverInfo[] = historicData.map( ( hour ): CloudCoverInfo => {
//return empty interval if measurement does not exist
const time = fromUnixTime( hour.EpochTime, {in: tz(getTZ(coordinates))} );
const time = fromUnixTime( hour.EpochTime, {in: tz(getTZ(coordinates))} );
if(hour.CloudCover === undefined ){
return {
startTime: time,
Expand Down
96 changes: 48 additions & 48 deletions src/routes/weatherProviders/Apple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,38 @@ interface Metadata {
}

interface CurrentWeather {
name: string,
metadata: Metadata,
asOf: string; // Required; ISO 8601 date-time
cloudCover?: number; // Optional; 0 to 1
conditionCode: string; // Required; enumeration of weather condition
daylight?: boolean; // Optional; indicates daylight
humidity: number; // Required; 0 to 1
precipitationIntensity: number; // Required; in mm/h
pressure: number; // Required; in millibars
pressureTrend: PressureTrend; // Required; direction of pressure change
temperature: number; // Required; in °C
temperatureApparent: number; // Required; feels-like temperature in °C
temperatureDewPoint: number; // Required; in °C
uvIndex: number; // Required; UV radiation level
visibility: number; // Required; in meters
windDirection?: number; // Optional; in degrees
windGust?: number; // Optional; max wind gust speed in km/h
windSpeed: number; // Required; in km/h
name: string,
metadata: Metadata,
asOf: string; // Required; ISO 8601 date-time
cloudCover?: number; // Optional; 0 to 1
conditionCode: string; // Required; enumeration of weather condition
daylight?: boolean; // Optional; indicates daylight
humidity: number; // Required; 0 to 1
precipitationIntensity: number; // Required; in mm/h
pressure: number; // Required; in millibars
pressureTrend: PressureTrend; // Required; direction of pressure change
temperature: number; // Required; in °C
temperatureApparent: number; // Required; feels-like temperature in °C
temperatureDewPoint: number; // Required; in °C
uvIndex: number; // Required; UV radiation level
visibility: number; // Required; in meters
windDirection?: number; // Optional; in degrees
windGust?: number; // Optional; max wind gust speed in km/h
windSpeed: number; // Required; in km/h
}

interface DayPartForecast {
cloudCover: number; // Required; 0 to 1
conditionCode: string; // Required; enumeration of weather condition
forecastEnd: string; // Required; ISO 8601 date-time
forecastStart: string; // Required; ISO 8601 date-time
humidity: number; // Required; 0 to 1
precipitationAmount: number; // Required; in millimeters
precipitationChance: number; // Required; as a percentage
precipitationType: PrecipitationType; // Required
snowfallAmount: number; // Required; in millimeters
windDirection?: number; // Optional; in degrees
windSpeed: number; // Required; in km/h
cloudCover: number; // Required; 0 to 1
conditionCode: string; // Required; enumeration of weather condition
forecastEnd: string; // Required; ISO 8601 date-time
forecastStart: string; // Required; ISO 8601 date-time
humidity: number; // Required; 0 to 1
precipitationAmount: number; // Required; in millimeters
precipitationChance: number; // Required; as a percentage
precipitationType: PrecipitationType; // Required
snowfallAmount: number; // Required; in millimeters
windDirection?: number; // Optional; in degrees
windSpeed: number; // Required; in km/h
}

interface DailyForecastData {
Expand Down Expand Up @@ -99,9 +99,9 @@ interface DailyForecastData {
}

interface DailyForecast {
name: string,
metadata: Metadata,
days: DailyForecastData[];
name: string,
metadata: Metadata,
days: DailyForecastData[];
}

interface HourWeatherConditions {
Expand All @@ -127,9 +127,9 @@ interface HourWeatherConditions {
}

interface HourlyForecast {
name: string,
metadata: Metadata,
hours: HourWeatherConditions[];
name: string,
metadata: Metadata,
hours: HourWeatherConditions[];
}

interface ForecastMinute {
Expand All @@ -147,16 +147,16 @@ interface ForecastPeriodSummary {
}

interface NextHourForecast {
name: string,
metadata: Metadata,
forecastEnd?: string; // ISO 8601 date-time
forecastStart?: string; // ISO 8601 date-time
minutes: ForecastMinute[]; // Required; array of forecast minutes
summary: ForecastPeriodSummary[]; // Required; array of forecast summaries
name: string,
metadata: Metadata,
forecastEnd?: string; // ISO 8601 date-time
forecastStart?: string; // ISO 8601 date-time
minutes: ForecastMinute[]; // Required; array of forecast minutes
summary: ForecastPeriodSummary[]; // Required; array of forecast summaries
}

interface WeatherAlertSummary {
areaId?: string; // Official designation of the affected area
areaId?: string; // Official designation of the affected area
areaName?: string; // Human-readable name of the affected area
certainty: Certainty; // Required; likelihood of the event
countryCode: string; // Required; ISO country code
Expand All @@ -175,9 +175,9 @@ interface WeatherAlertSummary {
}

interface WeatherAlertCollection {
name: string,
metadata: Metadata,
alerts: WeatherAlertSummary[];
name: string,
metadata: Metadata,
alerts: WeatherAlertSummary[];
}

interface AppleWeather {
Expand Down Expand Up @@ -225,7 +225,7 @@ export default class AppleWeatherProvider extends WeatherProvider {
): Promise<WateringData[]> {
const currentDay = startOfDay(localTime(coordinates));

const tz = getTZ(coordinates);
const tz = getTZ(coordinates);

const startTimestamp = new Date(+subDays(currentDay, 10)).toISOString();
const endTimestamp = new Date(+currentDay).toISOString();
Expand Down Expand Up @@ -280,7 +280,7 @@ export default class AppleWeatherProvider extends WeatherProvider {

const cloudCoverInfo: CloudCoverInfo[] = daysInHours[i].map(
(hour): CloudCoverInfo => {
const startTime = new TZDate(hour.forecastStart, tz);
const startTime = new TZDate(hour.forecastStart, tz);

return {
startTime,
Expand Down Expand Up @@ -347,7 +347,7 @@ export default class AppleWeatherProvider extends WeatherProvider {
coordinates: GeoCoordinates,
pws: PWS | undefined
): Promise<WeatherData> {
const tz = getTZ(coordinates);
const tz = getTZ(coordinates);

const forecastUrl = `https://weatherkit.apple.com/api/v1/weather/en/${coordinates[0]}/${coordinates[1]}?dataSets=currentWeather,forecastDaily&timezone=${tz}`;

Expand Down
10 changes: 5 additions & 5 deletions src/routes/weatherProviders/DWD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ export default class DWDWeatherProvider extends WeatherProvider {
}

protected async getWateringDataInternal( coordinates: GeoCoordinates, pws: PWS | undefined ): Promise< WateringData[] > {
const tz = getTZ(coordinates);
const tz = getTZ(coordinates);
const currentDay = startOfDay(localTime(coordinates));

const startTimestamp = subDays(currentDay, 7).toISOString();
const endTimestamp = currentDay.toISOString();
const startTimestamp = subDays(currentDay, 7).toISOString();
const endTimestamp = currentDay.toISOString();

const historicUrl = `https://api.brightsky.dev/weather?lat=${ coordinates[ 0 ] }&lon=${ coordinates[ 1 ] }&date=${ startTimestamp }&last_date=${ endTimestamp }&tz=${tz}`

Expand Down Expand Up @@ -52,7 +52,7 @@ export default class DWDWeatherProvider extends WeatherProvider {

for(let i = 0; i < daysInHours.length; i++){
const cloudCoverInfo: CloudCoverInfo[] = daysInHours[i].map( ( hour ): CloudCoverInfo => {
const startTime = new TZDate(hour.timestamp, tz);
const startTime = new TZDate(hour.timestamp, tz);
const result : CloudCoverInfo = {
startTime,
endTime: addHours(startTime, 1),
Expand Down Expand Up @@ -151,7 +151,7 @@ export default class DWDWeatherProvider extends WeatherProvider {
forecast: [],
};

const local = localTime(coordinates);
const local = localTime(coordinates);

for ( let day = 0; day < 7; day++ ) {

Expand Down
4 changes: 2 additions & 2 deletions src/routes/weatherProviders/OWM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class OWMWeatherProvider extends WeatherProvider {
const localKey = keyToUse(this.API_KEY, pws);

//Get previous date by using UTC
const yesterday = subDays(startOfDay(localTime(coordinates)), 1);
const yesterday = subDays(startOfDay(localTime(coordinates)), 1);

const yesterdayUrl = `https://api.openweathermap.org/data/3.0/onecall/day_summary?units=imperial&appid=${ localKey }&lat=${ coordinates[ 0 ] }&lon=${ coordinates[ 1 ] }&date=${format(yesterday, "yyyy-MM-dd")}&tz=${format(yesterday, "xxx")}`;

Expand All @@ -41,7 +41,7 @@ export default class OWMWeatherProvider extends WeatherProvider {
let clouds = (new Array(24)).fill(historicData.cloud_cover.afternoon);

const cloudCoverInfo: CloudCoverInfo[] = clouds.map( ( sample, i ): CloudCoverInfo => {
const start = addHours(yesterday, i);
const start = addHours(yesterday, i);
if( sample === undefined ) {
return {
startTime: start,
Expand Down
6 changes: 3 additions & 3 deletions src/routes/weatherProviders/OpenMeteo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export default class OpenMeteoWeatherProvider extends WeatherProvider {
protected async getWateringDataInternal( coordinates: GeoCoordinates, pws: PWS | undefined ): Promise< WateringData[] > {
const tz = getTZ(coordinates);

const currentDay = startOfDay(localTime(coordinates));
const currentDay = startOfDay(localTime(coordinates));

const startTimestamp = format(subDays(currentDay, 7), "yyyy-MM-dd");
const endTimestamp = format(currentDay, "yyyy-MM-dd");
const startTimestamp = format(subDays(currentDay, 7), "yyyy-MM-dd");
const endTimestamp = format(currentDay, "yyyy-MM-dd");


const historicUrl = `https://api.open-meteo.com/v1/forecast?latitude=${ coordinates[ 0 ] }&longitude=${ coordinates[ 1 ] }&hourly=temperature_2m,relativehumidity_2m,precipitation,direct_radiation,windspeed_10m&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch&start_date=${startTimestamp}&end_date=${endTimestamp}&timezone=${tz}&timeformat=unixtime`;
Expand Down
50 changes: 25 additions & 25 deletions src/routes/weatherProviders/PirateWeather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class PirateWeatherWeatherProvider extends WeatherProvider {

protected async getWateringDataInternal( coordinates: GeoCoordinates, pws: PWS | undefined ): Promise< WateringData[] > {
// The Unix timestamp of 24 hours ago.
const yesterday = subDays(startOfDay(localTime(coordinates)), 1);
const yesterday = subDays(startOfDay(localTime(coordinates)), 1);

const localKey = keyToUse(this.API_KEY, pws);

Expand Down Expand Up @@ -49,7 +49,7 @@ export default class PirateWeatherWeatherProvider extends WeatherProvider {
samples = samples.slice(0,24);

const cloudCoverInfo: CloudCoverInfo[] = samples.map( ( hour ): CloudCoverInfo => {
const startTime = fromUnixTime(hour.time);
const startTime = fromUnixTime(hour.time);
return {
startTime,
endTime: addDays(startTime, 1),
Expand All @@ -68,7 +68,7 @@ export default class PirateWeatherWeatherProvider extends WeatherProvider {
*/

temp += hour.temperature;
const currentHumidity = hour.humidity || this.humidityFromDewPoint(hour.temperature, hour.dewPoint);
const currentHumidity = hour.humidity || this.humidityFromDewPoint(hour.temperature, hour.dewPoint);
humidity += currentHumidity;
// This field may be missing from the response if it is snowing.
precip += hour.precipAccumulation || 0;
Expand Down Expand Up @@ -173,7 +173,7 @@ export default class PirateWeatherWeatherProvider extends WeatherProvider {
}
}

private celsiusToFahrenheit(celsius: number): number {
private celsiusToFahrenheit(celsius: number): number {
return (celsius * 9) / 5 + 32;
}

Expand All @@ -185,30 +185,30 @@ export default class PirateWeatherWeatherProvider extends WeatherProvider {
return kph * 0.621371;
}

//https://www.npl.co.uk/resources/q-a/dew-point-and-relative-humidity
private eLn(temperature: number, a: number, b: number): number {
return Math.log(611.2) + ((a * temperature) / (b + temperature));
}
//https://www.npl.co.uk/resources/q-a/dew-point-and-relative-humidity
private eLn(temperature: number, a: number, b: number): number {
return Math.log(611.2) + ((a * temperature) / (b + temperature));
}

private eWaterLn(temperature: number): number {
return this.eLn(temperature, 17.62, 243.12);
}
private eIceLn(temperature: number): number {
return this.eLn(temperature, 22.46, 272.62);
}
private eWaterLn(temperature: number): number {
return this.eLn(temperature, 17.62, 243.12);
}
private eIceLn(temperature: number): number {
return this.eLn(temperature, 22.46, 272.62);
}

private humidityFromDewPoint(temperature: number, dewPoint: number): number {
if (isNaN(temperature)) return temperature;
if (isNaN(dewPoint)) return dewPoint;
private humidityFromDewPoint(temperature: number, dewPoint: number): number {
if (isNaN(temperature)) return temperature;
if (isNaN(dewPoint)) return dewPoint;

let eFn: (temp: number) => number;
let eFn: (temp: number) => number;

if (temperature > 0) {
eFn = (temp: number) => this.eWaterLn(temp);
} else {
eFn = (temp: number) => this.eIceLn(temp);
}
if (temperature > 0) {
eFn = (temp: number) => this.eWaterLn(temp);
} else {
eFn = (temp: number) => this.eIceLn(temp);
}

return 100 * Math.exp(eFn(dewPoint) - eFn(temperature));
}
return 100 * Math.exp(eFn(dewPoint) - eFn(temperature));
}
}
24 changes: 12 additions & 12 deletions src/routes/weatherProviders/WeatherProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,22 @@ export class WeatherProvider {
return pws?.id || `${coordinates[0]};s${coordinates[1]}`
}

/**
* Internal command to get the weather data from an API, will be cached when anything outside calls it
* @param coordinates Coordinates of requested data
* @param pws PWS data which includes the apikey
* @returns Returns weather data (should not be mutated)
*/
/**
* Internal command to get the weather data from an API, will be cached when anything outside calls it
* @param coordinates Coordinates of requested data
* @param pws PWS data which includes the apikey
* @returns Returns weather data (should not be mutated)
*/
protected async getWeatherDataInternal(coordinates: GeoCoordinates, pws: PWS | undefined): Promise<WeatherData> {
throw "Selected WeatherProvider does not support getWeatherData";
}

/**
* Internal command to get the watering data from an API, will be cached when anything outside calls it
* @param coordinates Coordinates of requested data
* @param pws PWS data which includes the apikey
* @returns Returns watering data array in reverse chronological order (array should not be mutated)
*/
/**
* Internal command to get the watering data from an API, will be cached when anything outside calls it
* @param coordinates Coordinates of requested data
* @param pws PWS data which includes the apikey
* @returns Returns watering data array in reverse chronological order (array should not be mutated)
*/
protected async getWateringDataInternal(coordinates: GeoCoordinates, pws: PWS | undefined): Promise<readonly WateringData[]> {
throw new CodedError( ErrorCode.UnsupportedAdjustmentMethod );
}
Expand Down
Loading