2020-09-04 18:02:20 +00:00
|
|
|
// current weather conditions display
|
|
|
|
/* globals WeatherDisplay, utils, STATUS, icons, UNITS, draw, navigation */
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
class CurrentWeather extends WeatherDisplay {
|
2020-09-08 19:39:17 +00:00
|
|
|
constructor(navId,elemId) {
|
2020-09-08 15:05:46 +00:00
|
|
|
super(navId,elemId,'Current Conditions');
|
2020-09-04 18:02:20 +00:00
|
|
|
// pre-load background image (returns promise)
|
|
|
|
this.backgroundImage = utils.image.load('images/BackGround1_1.png');
|
|
|
|
}
|
|
|
|
|
|
|
|
async getData(weatherParameters) {
|
2020-09-25 14:55:29 +00:00
|
|
|
super.getData(weatherParameters);
|
|
|
|
if (!weatherParameters) weatherParameters = this.weatherParameters;
|
|
|
|
|
2020-09-04 18:02:20 +00:00
|
|
|
// Load the observations
|
|
|
|
let observations, station;
|
2020-10-16 20:16:46 +00:00
|
|
|
// station number counter
|
|
|
|
let stationNum = 0;
|
|
|
|
while (!observations && stationNum < weatherParameters.stations.length) {
|
|
|
|
// get the station
|
|
|
|
station = weatherParameters.stations[stationNum];
|
|
|
|
stationNum++;
|
|
|
|
try {
|
|
|
|
// station observations
|
|
|
|
observations = await utils.fetch.json(`${station.id}/observations`,{
|
|
|
|
cors: true,
|
|
|
|
data: {
|
|
|
|
limit: 2,
|
|
|
|
},
|
|
|
|
});
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-10-16 20:16:46 +00:00
|
|
|
// test data quality
|
|
|
|
if (observations.features[0].properties.temperature.value === null ||
|
|
|
|
observations.features[0].properties.windSpeed.value === null ||
|
|
|
|
observations.features[0].properties.textDescription === null) {
|
|
|
|
observations = undefined;
|
|
|
|
throw new Error(`Unable to get observations: ${station.properties.stationIdentifier}, trying next station`);
|
|
|
|
}
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
// TODO: add retry for further stations if observations are unavailable
|
2020-10-16 20:16:46 +00:00
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// test for data received
|
|
|
|
if (!observations) {
|
|
|
|
console.error('All current weather stations exhausted');
|
2020-09-09 19:29:03 +00:00
|
|
|
this.setStatus(STATUS.failed);
|
2020-09-04 18:02:20 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-09-23 16:49:15 +00:00
|
|
|
// preload the icon
|
2020-09-23 19:10:25 +00:00
|
|
|
utils.image.preload(icons.getWeatherIconFromIconLink(observations.features[0].properties.icon));
|
2020-09-23 16:49:15 +00:00
|
|
|
|
2020-09-04 18:02:20 +00:00
|
|
|
// we only get here if there was no error above
|
|
|
|
this.data = Object.assign({}, observations, {station: station});
|
2020-09-17 21:34:38 +00:00
|
|
|
this.setStatus(STATUS.loaded);
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
// format the data for use outside this function
|
|
|
|
parseData() {
|
|
|
|
if (!this.data) return false;
|
|
|
|
const data = {};
|
2020-09-04 18:02:20 +00:00
|
|
|
const observations = this.data.features[0].properties;
|
|
|
|
// values from api are provided in metric
|
2020-09-25 03:44:51 +00:00
|
|
|
data.observations = observations;
|
|
|
|
data.Temperature = Math.round(observations.temperature.value);
|
2020-09-25 14:55:29 +00:00
|
|
|
data.TemperatureUnit = 'C';
|
2020-09-25 03:44:51 +00:00
|
|
|
data.DewPoint = Math.round(observations.dewpoint.value);
|
|
|
|
data.Ceiling = Math.round(observations.cloudLayers[0].base.value);
|
|
|
|
data.CeilingUnit = 'm.';
|
|
|
|
data.Visibility = Math.round(observations.visibility.value/1000);
|
|
|
|
data.VisibilityUnit = ' km.';
|
|
|
|
data.WindSpeed = Math.round(observations.windSpeed.value);
|
|
|
|
data.WindDirection = utils.calc.directionToNSEW(observations.windDirection.value);
|
|
|
|
data.Pressure = Math.round(observations.barometricPressure.value);
|
|
|
|
data.HeatIndex = Math.round(observations.heatIndex.value);
|
|
|
|
data.WindChill = Math.round(observations.windChill.value);
|
|
|
|
data.WindGust = Math.round(observations.windGust.value);
|
2020-09-25 14:55:29 +00:00
|
|
|
data.WindUnit = 'KPH';
|
2020-09-25 03:44:51 +00:00
|
|
|
data.Humidity = Math.round(observations.relativeHumidity.value);
|
|
|
|
data.Icon = icons.getWeatherIconFromIconLink(observations.icon);
|
|
|
|
data.PressureDirection = '';
|
|
|
|
data.TextConditions = observations.textDescription;
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
// difference since last measurement (pascals, looking for difference of more than 150)
|
|
|
|
const pressureDiff = (observations.barometricPressure.value - this.data.features[1].properties.barometricPressure.value);
|
2020-09-25 03:44:51 +00:00
|
|
|
if (pressureDiff > 150) data.PressureDirection = 'R';
|
|
|
|
if (pressureDiff < -150) data.PressureDirection = 'F';
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
if (navigation.units() === UNITS.english) {
|
2020-09-25 03:44:51 +00:00
|
|
|
data.Temperature = utils.units.celsiusToFahrenheit(data.Temperature);
|
2020-09-25 14:55:29 +00:00
|
|
|
data.TemperatureUnit = 'F';
|
2020-09-25 03:44:51 +00:00
|
|
|
data.DewPoint = utils.units.celsiusToFahrenheit(data.DewPoint);
|
|
|
|
data.Ceiling = Math.round(utils.units.metersToFeet(data.Ceiling)/100)*100;
|
|
|
|
data.CeilingUnit = 'ft.';
|
|
|
|
data.Visibility = utils.units.kilometersToMiles(observations.visibility.value/1000);
|
|
|
|
data.VisibilityUnit = ' mi.';
|
|
|
|
data.WindSpeed = utils.units.kphToMph(data.WindSpeed);
|
2020-09-25 14:55:29 +00:00
|
|
|
data.WindUnit = 'MPH';
|
2020-09-25 21:36:43 +00:00
|
|
|
data.Pressure = utils.units.pascalToInHg(data.Pressure).toFixed(2);
|
2020-09-25 03:44:51 +00:00
|
|
|
data.HeatIndex = utils.units.celsiusToFahrenheit(data.HeatIndex);
|
|
|
|
data.WindChill = utils.units.celsiusToFahrenheit(data.WindChill);
|
|
|
|
data.WindGust = utils.units.kphToMph(data.WindGust);
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
2020-09-25 03:44:51 +00:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
async drawCanvas () {
|
|
|
|
super.drawCanvas();
|
|
|
|
// parse each time to deal with a change in units if necessary
|
|
|
|
const data = this.parseData();
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
this.context.drawImage(await this.backgroundImage, 0, 0);
|
|
|
|
draw.horizontalGradientSingle(this.context, 0, 30, 500, 90, draw.topColor1, draw.topColor2);
|
|
|
|
draw.triangle(this.context, 'rgb(28, 10, 87)', 500, 30, 450, 90, 500, 90);
|
|
|
|
draw.horizontalGradientSingle(this.context, 0, 90, 52, 399, draw.sideColor1, draw.sideColor2);
|
|
|
|
draw.horizontalGradientSingle(this.context, 584, 90, 640, 399, draw.sideColor1, draw.sideColor2);
|
|
|
|
|
|
|
|
draw.titleText(this.context, 'Current', 'Conditions');
|
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', '24pt', '#FFFFFF', 170, 135, data.Temperature + String.fromCharCode(176), 2);
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
let Conditions = data.observations.textDescription;
|
|
|
|
if (Conditions.length > 15) {
|
2020-09-04 18:02:20 +00:00
|
|
|
Conditions = this.shortConditions(Conditions);
|
|
|
|
}
|
|
|
|
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 195, 170, Conditions, 2, 'center');
|
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 80, 330, 'Wind:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 300, 330, data.WindDirection + ' ' + data.WindSpeed, 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
if (data.WindGust) draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 80, 375, 'Gusts to ' + data.WindGust, 2);
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFF00', 315, 120, this.data.station.properties.name.substr(0, 20), 2);
|
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 165, 'Humidity:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 165, data.Humidity + '%', 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 205, 'Dewpoint:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 205, data.DewPoint + String.fromCharCode(176), 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 245, 'Ceiling:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 245, (data.Ceiling === '' ? 'Unlimited' : data.Ceiling + data.CeilingUnit), 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 285, 'Visibility:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 285, data.Visibility + data.VisibilityUnit, 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 325, 'Pressure:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 535, 325, data.Pressure, 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
switch (data.PressureDirection) {
|
2020-09-04 18:02:20 +00:00
|
|
|
case 'R':
|
|
|
|
// Shadow
|
|
|
|
draw.triangle(this.context, '#000000', 552, 302, 542, 312, 562, 312);
|
|
|
|
draw.box(this.context, '#000000', 549, 312, 6, 15);
|
|
|
|
|
|
|
|
// Border
|
|
|
|
draw.triangle(this.context, '#000000', 550, 300, 540, 310, 560, 310);
|
|
|
|
draw.box(this.context, '#000000', 547, 310, 6, 15);
|
|
|
|
|
|
|
|
// Fill
|
|
|
|
draw.triangle(this.context, '#FFFF00', 550, 301, 541, 309, 559, 309);
|
|
|
|
draw.box(this.context, '#FFFF00', 548, 309, 4, 15);
|
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
// Shadow
|
|
|
|
draw.triangle(this.context, '#000000', 552, 327, 542, 317, 562, 317);
|
|
|
|
draw.box(this.context, '#000000', 549, 302, 6, 15);
|
|
|
|
|
|
|
|
// Border
|
|
|
|
draw.triangle(this.context, '#000000', 550, 325, 540, 315, 560, 315);
|
|
|
|
draw.box(this.context, '#000000', 547, 300, 6, 15);
|
|
|
|
|
|
|
|
// Fill
|
|
|
|
draw.triangle(this.context, '#FFFF00', 550, 324, 541, 314, 559, 314);
|
|
|
|
draw.box(this.context, '#FFFF00', 548, 301, 4, 15);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
if (data.observations.heatIndex.value && data.HeatIndex !== data.Temperature) {
|
2020-09-04 18:02:20 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 365, 'Heat Index:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 365, data.HeatIndex + String.fromCharCode(176), 2, 'right');
|
|
|
|
} else if (data.observations.windChill.value && data.WindChill !== '' && data.WindChill < data.Temperature) {
|
2020-09-04 18:02:20 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 365, 'Wind Chill:', 2);
|
2020-09-25 03:44:51 +00:00
|
|
|
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 365, data.WindChill + String.fromCharCode(176), 2, 'right');
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
2020-09-04 18:38:58 +00:00
|
|
|
|
|
|
|
// get main icon
|
|
|
|
this.gifs.push(await utils.image.superGifAsync({
|
2020-09-25 03:44:51 +00:00
|
|
|
src: data.Icon,
|
2020-09-04 18:38:58 +00:00
|
|
|
auto_play: true,
|
|
|
|
canvas: this.canvas,
|
|
|
|
x: 140,
|
|
|
|
y: 175,
|
|
|
|
max_width: 126,
|
|
|
|
}));
|
|
|
|
|
2020-09-04 18:02:20 +00:00
|
|
|
this.finishDraw();
|
|
|
|
}
|
|
|
|
|
2020-09-25 03:44:51 +00:00
|
|
|
// return the latest gathered information if available
|
|
|
|
getCurrentWeather() {
|
|
|
|
return this.parseData();
|
|
|
|
}
|
|
|
|
|
2020-09-04 18:02:20 +00:00
|
|
|
shortConditions(condition) {
|
|
|
|
condition = condition.replace(/Light/g, 'L');
|
|
|
|
condition = condition.replace(/Heavy/g, 'H');
|
|
|
|
condition = condition.replace(/Partly/g, 'P');
|
|
|
|
condition = condition.replace(/Mostly/g, 'M');
|
|
|
|
condition = condition.replace(/Few/g, 'F');
|
|
|
|
condition = condition.replace(/Thunderstorm/g, 'T\'storm');
|
|
|
|
condition = condition.replace(/ in /g, '');
|
|
|
|
condition = condition.replace(/Vicinity/g, '');
|
|
|
|
condition = condition.replace(/ and /g, ' ');
|
|
|
|
condition = condition.replace(/Freezing Rain/g, 'Frz Rn');
|
|
|
|
condition = condition.replace(/Freezing/g, 'Frz');
|
|
|
|
condition = condition.replace(/Unknown Precip/g, '');
|
|
|
|
condition = condition.replace(/L Snow Fog/g, 'L Snw/Fog');
|
|
|
|
condition = condition.replace(/ with /g, '/');
|
|
|
|
return condition;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|