Remove errMessage
This commit is contained in:
@@ -59,9 +59,8 @@ export class CodedError {
|
|||||||
public readonly errCode: ErrorCode;
|
public readonly errCode: ErrorCode;
|
||||||
public readonly message: string;
|
public readonly message: string;
|
||||||
|
|
||||||
public constructor( errCode: ErrorCode, message: string ) {
|
public constructor( errCode: ErrorCode ) {
|
||||||
this.errCode = errCode;
|
this.errCode = errCode;
|
||||||
this.message = message;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +78,6 @@ export function makeCodedError( err: any ): CodedError {
|
|||||||
if ( err instanceof CodedError ) {
|
if ( err instanceof CodedError ) {
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
// Include the current timestamp in the error message so the full error can easily be found in the logs.
|
return new CodedError( ErrorCode.UnexpectedError );
|
||||||
return new CodedError( ErrorCode.UnexpectedError, "Unexpected error occurred at timestamp " + Date.now() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,14 +44,6 @@ export interface AdjustmentMethodResponse {
|
|||||||
* watering.
|
* watering.
|
||||||
*/
|
*/
|
||||||
rainDelay?: number;
|
rainDelay?: number;
|
||||||
/**
|
|
||||||
* An message to send to the OS firmware to indicate that an error occurred while calculating the watering
|
|
||||||
* scale and the returned scale either defaulted to some reasonable value or was calculated with incomplete data.
|
|
||||||
* Older firmware versions will ignore this field (they will silently swallow the error and use the returned scale),
|
|
||||||
* but newer firmware versions may be able to alert the user that an error occurred and/or default to a
|
|
||||||
* user-configured watering scale instead of using the one returned by the AdjustmentMethod.
|
|
||||||
*/
|
|
||||||
errMessage?: string;
|
|
||||||
/** A code describing the type of error that occurred (if one occurred). */
|
/** A code describing the type of error that occurred (if one occurred). */
|
||||||
errCode?: ErrorCode;
|
errCode?: ErrorCode;
|
||||||
/** The data that was used to calculate the watering scale, or undefined if no data was used. */
|
/** The data that was used to calculate the watering scale, or undefined if no data was used. */
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ async function calculateEToWateringScale(
|
|||||||
): Promise< AdjustmentMethodResponse > {
|
): Promise< AdjustmentMethodResponse > {
|
||||||
|
|
||||||
if ( pws ) {
|
if ( pws ) {
|
||||||
throw new CodedError( ErrorCode.PwsNotSupported, "ETo adjustment method does not support personal weather stations through WUnderground." );
|
throw new CodedError( ErrorCode.PwsNotSupported );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporarily disabled since OWM forecast data is checking if rain is forecasted for 3 hours in the future.
|
// Temporarily disabled since OWM forecast data is checking if rain is forecasted for 3 hours in the future.
|
||||||
@@ -41,7 +41,7 @@ async function calculateEToWateringScale(
|
|||||||
if ( adjustmentOptions && "baseETo" in adjustmentOptions ) {
|
if ( adjustmentOptions && "baseETo" in adjustmentOptions ) {
|
||||||
baseETo = adjustmentOptions.baseETo
|
baseETo = adjustmentOptions.baseETo
|
||||||
} else {
|
} else {
|
||||||
throw new CodedError( ErrorCode.MissingAdjustmentOption, "A baseline potential ETo must be provided." );
|
throw new CodedError( ErrorCode.MissingAdjustmentOption );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( adjustmentOptions && "elevation" in adjustmentOptions ) {
|
if ( adjustmentOptions && "elevation" in adjustmentOptions ) {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ async function calculateZimmermanWateringScale(
|
|||||||
scale: 100,
|
scale: 100,
|
||||||
rawData: rawData,
|
rawData: rawData,
|
||||||
errCode: ErrorCode.MissingWeatherField,
|
errCode: ErrorCode.MissingWeatherField,
|
||||||
errMessage: "Necessary field(s) were missing from ZimmermanWateringData.",
|
|
||||||
wateringData: wateringData
|
wateringData: wateringData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ const cache = new WateringScaleCache();
|
|||||||
export async function resolveCoordinates( location: string ): Promise< GeoCoordinates > {
|
export async function resolveCoordinates( location: string ): Promise< GeoCoordinates > {
|
||||||
|
|
||||||
if ( !location ) {
|
if ( !location ) {
|
||||||
throw new CodedError( ErrorCode.InvalidLocationFormat, "No location specified" );
|
throw new CodedError( ErrorCode.InvalidLocationFormat );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( filters.pws.test( location ) ) {
|
if ( filters.pws.test( location ) ) {
|
||||||
throw new CodedError( ErrorCode.InvalidLocationFormat, "PWS ID must be specified in the pws adjustment option." );
|
throw new CodedError( ErrorCode.InvalidLocationFormat );
|
||||||
} else if ( filters.gps.test( location ) ) {
|
} else if ( filters.gps.test( location ) ) {
|
||||||
const split: string[] = location.split( "," );
|
const split: string[] = location.split( "," );
|
||||||
return [ parseFloat( split[ 0 ] ), parseFloat( split[ 1 ] ) ];
|
return [ parseFloat( split[ 0 ] ), parseFloat( split[ 1 ] ) ];
|
||||||
@@ -64,7 +64,7 @@ export async function resolveCoordinates( location: string ): Promise< GeoCoordi
|
|||||||
data = await httpJSONRequest( url );
|
data = await httpJSONRequest( url );
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// If the request fails, indicate no data was found.
|
// If the request fails, indicate no data was found.
|
||||||
throw new CodedError( ErrorCode.LocationServiceApiError, "An API error occurred while attempting to resolve location" );
|
throw new CodedError( ErrorCode.LocationServiceApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the data is valid
|
// Check if the data is valid
|
||||||
@@ -75,7 +75,7 @@ export async function resolveCoordinates( location: string ): Promise< GeoCoordi
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Otherwise, indicate no data was found
|
// Otherwise, indicate no data was found
|
||||||
throw new CodedError( ErrorCode.NoLocationFound, "No match found for specified location" );
|
throw new CodedError( ErrorCode.NoLocationFound );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
remoteAddress = remoteAddress.split( "," )[ 0 ];
|
remoteAddress = remoteAddress.split( "," )[ 0 ];
|
||||||
|
|
||||||
if ( !adjustmentMethod ) {
|
if ( !adjustmentMethod ) {
|
||||||
sendWateringData( res, { errCode: ErrorCode.InvalidAdjustmentMethod, errMessage: "Invalid AdjustmentMethod ID" } );
|
sendWateringData( res, { errCode: ErrorCode.InvalidAdjustmentMethod } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
adjustmentOptions = JSON.parse( "{" + adjustmentOptionsString + "}" );
|
adjustmentOptions = JSON.parse( "{" + adjustmentOptionsString + "}" );
|
||||||
} catch ( err ) {
|
} catch ( err ) {
|
||||||
// If the JSON is not valid then abort the calculation
|
// If the JSON is not valid then abort the calculation
|
||||||
sendWateringData( res, { errCode: ErrorCode.MalformedAdjustmentOptions, errMessage: `Unable to parse options (${ err })` } );
|
sendWateringData( res, { errCode: ErrorCode.MalformedAdjustmentOptions } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
console.error( `An unexpected error occurred during location resolution for "${ req.url }": `, err );
|
console.error( `An unexpected error occurred during location resolution for "${ req.url }": `, err );
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWateringData( res, { errCode: codedError.errCode, errMessage: `Unable to resolve location "${ location }" (${ codedError.message })` } );
|
sendWateringData( res, { errCode: codedError.errCode } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,11 +241,11 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
|
|
||||||
// Make sure that the PWS ID and API key look valid.
|
// Make sure that the PWS ID and API key look valid.
|
||||||
if ( !pwsId ) {
|
if ( !pwsId ) {
|
||||||
sendWateringData( res, { errCode: ErrorCode.InvalidPwsId, errMessage: "PWS ID does not appear to be valid" } );
|
sendWateringData( res, { errCode: ErrorCode.InvalidPwsId } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !apiKey ) {
|
if ( !apiKey ) {
|
||||||
sendWateringData( res, { errCode: ErrorCode.InvalidPwsApiKey, errMessage: "PWS API key does not appear to be valid" } );
|
sendWateringData( res, { errCode: ErrorCode.InvalidPwsApiKey } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +262,6 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
sunset: timeData.sunset,
|
sunset: timeData.sunset,
|
||||||
eip: ipToInt( remoteAddress ),
|
eip: ipToInt( remoteAddress ),
|
||||||
rawData: undefined,
|
rawData: undefined,
|
||||||
errMessage: undefined,
|
|
||||||
errCode: 0
|
errCode: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -289,13 +288,12 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
console.error( `An unexpected error occurred during watering scale calculation for "${ req.url }": `, err );
|
console.error( `An unexpected error occurred during watering scale calculation for "${ req.url }": `, err );
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWateringData( res, { errCode: codedError.errCode, errMessage: codedError.message } );
|
sendWateringData( res, { errCode: codedError.errCode } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.scale = adjustmentMethodResponse.scale;
|
data.scale = adjustmentMethodResponse.scale;
|
||||||
data.errCode = adjustmentMethodResponse.errCode || 0;
|
data.errCode = adjustmentMethodResponse.errCode || 0;
|
||||||
data.errMessage = adjustmentMethodResponse.errMessage;
|
|
||||||
data.rd = adjustmentMethodResponse.rainDelay;
|
data.rd = adjustmentMethodResponse.rainDelay;
|
||||||
data.rawData = adjustmentMethodResponse.rawData;
|
data.rawData = adjustmentMethodResponse.rawData;
|
||||||
|
|
||||||
@@ -311,7 +309,7 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
console.error( `An unexpected error occurred during restriction checks for "${ req.url }": `, err );
|
console.error( `An unexpected error occurred during restriction checks for "${ req.url }": `, err );
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWateringData( res, { errCode: codedError.errCode, errMessage: codedError.message } );
|
sendWateringData( res, { errCode: codedError.errCode } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +321,7 @@ export const getWateringData = async function( req: express.Request, res: expres
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache the watering scale if caching is enabled and no error occurred.
|
// Cache the watering scale if caching is enabled and no error occurred.
|
||||||
if ( weatherProvider.shouldCacheWateringScale() && !data.errMessage ) {
|
if ( weatherProvider.shouldCacheWateringScale() ) {
|
||||||
cache.storeWateringScale( req.params[ 0 ], coordinates, pws, adjustmentOptions, {
|
cache.storeWateringScale( req.params[ 0 ], coordinates, pws, adjustmentOptions, {
|
||||||
scale: data.scale,
|
scale: data.scale,
|
||||||
rawData: data.rawData,
|
rawData: data.rawData,
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ export default class DarkSkyWeatherProvider extends WeatherProvider {
|
|||||||
yesterdayData = await httpJSONRequest( yesterdayUrl );
|
yesterdayData = await httpJSONRequest( yesterdayUrl );
|
||||||
} catch ( err ) {
|
} catch ( err ) {
|
||||||
console.error( "Error retrieving weather information from Dark Sky:", err );
|
console.error( "Error retrieving weather information from Dark Sky:", err );
|
||||||
throw new CodedError( ErrorCode.WeatherApiError, "An error occurred while retrieving weather information from Dark Sky." );
|
throw new CodedError( ErrorCode.WeatherApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !yesterdayData.hourly || !yesterdayData.hourly.data ) {
|
if ( !yesterdayData.hourly || !yesterdayData.hourly.data ) {
|
||||||
throw new CodedError( ErrorCode.MissingWeatherField, "Necessary field(s) were missing from weather information returned by Dark Sky." );
|
throw new CodedError( ErrorCode.MissingWeatherField );
|
||||||
}
|
}
|
||||||
|
|
||||||
const samples = [
|
const samples = [
|
||||||
@@ -42,7 +42,7 @@ export default class DarkSkyWeatherProvider extends WeatherProvider {
|
|||||||
|
|
||||||
// Fail if not enough data is available.
|
// Fail if not enough data is available.
|
||||||
if ( samples.length !== 24 ) {
|
if ( samples.length !== 24 ) {
|
||||||
throw new CodedError( ErrorCode.InsufficientWeatherData, "Insufficient data was returned by Dark Sky." );
|
throw new CodedError( ErrorCode.InsufficientWeatherData );
|
||||||
}
|
}
|
||||||
|
|
||||||
const totals = { temp: 0, humidity: 0, precip: 0 };
|
const totals = { temp: 0, humidity: 0, precip: 0 };
|
||||||
@@ -123,7 +123,7 @@ export default class DarkSkyWeatherProvider extends WeatherProvider {
|
|||||||
try {
|
try {
|
||||||
historicData = await httpJSONRequest( historicUrl );
|
historicData = await httpJSONRequest( historicUrl );
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new CodedError( ErrorCode.WeatherApiError, "An error occurred while retrieving weather information from Dark Sky." );
|
throw new CodedError( ErrorCode.WeatherApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
const cloudCoverInfo: CloudCoverInfo[] = historicData.hourly.data.map( ( hour ): CloudCoverInfo => {
|
const cloudCoverInfo: CloudCoverInfo[] = historicData.hourly.data.map( ( hour ): CloudCoverInfo => {
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ export default class OWMWeatherProvider extends WeatherProvider {
|
|||||||
forecast = await httpJSONRequest( forecastUrl );
|
forecast = await httpJSONRequest( forecastUrl );
|
||||||
} catch ( err ) {
|
} catch ( err ) {
|
||||||
console.error( "Error retrieving weather information from OWM:", err );
|
console.error( "Error retrieving weather information from OWM:", err );
|
||||||
throw new CodedError( ErrorCode.WeatherApiError, "An error occurred while retrieving weather information from OWM." );
|
throw new CodedError( ErrorCode.WeatherApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicate watering data could not be retrieved if the forecast data is incomplete.
|
// Indicate watering data could not be retrieved if the forecast data is incomplete.
|
||||||
if ( !forecast || !forecast.list ) {
|
if ( !forecast || !forecast.list ) {
|
||||||
throw new CodedError( ErrorCode.MissingWeatherField, "Necessary field(s) were missing from weather information returned by OWM." );
|
throw new CodedError( ErrorCode.MissingWeatherField );
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalTemp = 0,
|
let totalTemp = 0,
|
||||||
@@ -112,12 +112,12 @@ export default class OWMWeatherProvider extends WeatherProvider {
|
|||||||
forecast = await httpJSONRequest( forecastUrl );
|
forecast = await httpJSONRequest( forecastUrl );
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error( "Error retrieving ETo information from OWM:", err );
|
console.error( "Error retrieving ETo information from OWM:", err );
|
||||||
throw new CodedError( ErrorCode.WeatherApiError, "An error occurred while retrieving ETo information from OWM." );
|
throw new CodedError( ErrorCode.WeatherApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicate ETo data could not be retrieved if the forecast data is incomplete.
|
// Indicate ETo data could not be retrieved if the forecast data is incomplete.
|
||||||
if ( !forecast || !forecast.list || forecast.list.length < 8 ) {
|
if ( !forecast || !forecast.list || forecast.list.length < 8 ) {
|
||||||
throw new CodedError( ErrorCode.InsufficientWeatherData, "Insufficient data available from OWM." );
|
throw new CodedError( ErrorCode.InsufficientWeatherData );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a sample over 24 hours.
|
// Take a sample over 24 hours.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default class WUnderground extends WeatherProvider {
|
|||||||
|
|
||||||
async getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
|
async getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
|
||||||
if ( !pws ) {
|
if ( !pws ) {
|
||||||
throw new CodedError( ErrorCode.NoPwsProvided, "WUnderground WeatherProvider requires a PWS to be specified." );
|
throw new CodedError( ErrorCode.NoPwsProvided );
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `https://api.weather.com/v2/pws/observations/hourly/7day?stationId=${ pws.id }&format=json&units=e&apiKey=${ pws.apiKey }`;
|
const url = `https://api.weather.com/v2/pws/observations/hourly/7day?stationId=${ pws.id }&format=json&units=e&apiKey=${ pws.apiKey }`;
|
||||||
@@ -16,7 +16,7 @@ export default class WUnderground extends WeatherProvider {
|
|||||||
data = await httpJSONRequest( url );
|
data = await httpJSONRequest( url );
|
||||||
} catch ( err ) {
|
} catch ( err ) {
|
||||||
console.error( "Error retrieving weather information from WUnderground:", err );
|
console.error( "Error retrieving weather information from WUnderground:", err );
|
||||||
throw new CodedError( ErrorCode.WeatherApiError, "An error occurred while retrieving weather information from WUnderground." );
|
throw new CodedError( ErrorCode.WeatherApiError );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take the 24 most recent observations.
|
// Take the 24 most recent observations.
|
||||||
@@ -24,7 +24,7 @@ export default class WUnderground extends WeatherProvider {
|
|||||||
|
|
||||||
// Fail if not enough data is available.
|
// Fail if not enough data is available.
|
||||||
if ( samples.length !== 24 ) {
|
if ( samples.length !== 24 ) {
|
||||||
throw new CodedError( ErrorCode.InsufficientWeatherData, "Insufficient data was returned by WUnderground." );
|
throw new CodedError( ErrorCode.InsufficientWeatherData );
|
||||||
}
|
}
|
||||||
|
|
||||||
const totals = { temp: 0, humidity: 0, precip: 0 };
|
const totals = { temp: 0, humidity: 0, precip: 0 };
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class WeatherProvider {
|
|||||||
* does not support this method).
|
* does not support this method).
|
||||||
*/
|
*/
|
||||||
getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
|
getWateringData( coordinates: GeoCoordinates, pws?: PWS ): Promise< ZimmermanWateringData > {
|
||||||
throw new CodedError( ErrorCode.UnsupportedAdjustmentMethod, "Selected WeatherProvider does not support getWateringData" );
|
throw new CodedError( ErrorCode.UnsupportedAdjustmentMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +34,7 @@ export class WeatherProvider {
|
|||||||
* CodedError if an error occurs while retrieving the EToData (or the WeatherProvider does not support this method).
|
* CodedError if an error occurs while retrieving the EToData (or the WeatherProvider does not support this method).
|
||||||
*/
|
*/
|
||||||
getEToData( coordinates: GeoCoordinates ): Promise< EToData > {
|
getEToData( coordinates: GeoCoordinates ): Promise< EToData > {
|
||||||
throw new CodedError( ErrorCode.UnsupportedAdjustmentMethod, "Selected WeatherProvider does not support getEToData" );
|
throw new CodedError( ErrorCode.UnsupportedAdjustmentMethod );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user