Compare commits

..

6 Commits

Author SHA1 Message Date
Matt Walsh
c6af9a2913 5.26.2 2025-06-27 22:30:05 -05:00
Matt Walsh
11eba84cdb fix for calm/0mph wind close #121 2025-06-27 22:29:56 -05:00
Matt Walsh
b9ead38015 5.26.1 2025-06-27 22:17:00 -05:00
Matt Walsh
3d0178faa1 radar scrolling fix for ios 2025-06-27 22:16:51 -05:00
Matt Walsh
8a2907e02c fix display of null wind speed 2025-06-27 15:35:15 -05:00
Matt Walsh
b870ce1c01 store already processed radar images for reuse on silent reload 2025-06-27 15:29:20 -05:00
4 changed files with 46 additions and 10 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ws4kp",
"version": "5.26.0",
"version": "5.26.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ws4kp",
"version": "5.26.0",
"version": "5.26.2",
"license": "MIT",
"dependencies": {
"dotenv": "^16.5.0",

View File

@@ -1,6 +1,6 @@
{
"name": "ws4kp",
"version": "5.26.0",
"version": "5.26.2",
"description": "Welcome to the WeatherStar 4000+ project page!",
"main": "index.mjs",
"type": "module",

View File

@@ -112,10 +112,12 @@ class CurrentWeather extends WeatherDisplay {
condition = shortConditions(condition);
}
const wind = (typeof this.data.WindSpeed === 'number') ? this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' ') : this.data.WindSpeed;
const fill = {
temp: this.data.Temperature + String.fromCharCode(176),
condition,
wind: this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' '),
wind,
location: locationCleanup(this.data.station.properties.name).substr(0, 20),
humidity: `${this.data.Humidity}%`,
dewpoint: this.data.DewPoint + String.fromCharCode(176),
@@ -202,13 +204,15 @@ const parseData = (data) => {
data.WindSpeed = windConverter(observations.windSpeed.value);
data.WindDirection = directionToNSEW(observations.windDirection.value);
data.WindGust = windConverter(observations.windGust.value);
data.WindSpeed = windConverter(data.WindSpeed);
data.WindUnit = windConverter.units;
data.Humidity = Math.round(observations.relativeHumidity.value);
data.Icon = getLargeIcon(observations.icon);
data.PressureDirection = '';
data.TextConditions = observations.textDescription;
// set wind speed of 0 as calm
if (data.WindSpeed === 0) data.WindSpeed = 'Calm';
// difference since last measurement (pascals, looking for difference of more than 150)
const pressureDiff = (observations.barometricPressure.value - data.features[1].properties.barometricPressure.value);
if (pressureDiff > 150) data.PressureDirection = 'R';

View File

@@ -8,6 +8,10 @@ import * as utils from './radar-utils.mjs';
import setTiles from './radar-tiles.mjs';
import processRadar from './radar-processor.mjs';
// store processed radar as dataURLs to avoid re-processing frames as they slide backwards in time
// this is cleared upon changing the location displayed
let processedRadars = [];
const RADAR_HOST = 'mesonet.agron.iastate.edu';
class Radar extends WeatherDisplay {
constructor(navId, elemId) {
@@ -110,19 +114,44 @@ class Radar extends WeatherDisplay {
elemId: this.elemId,
});
const radarKey = `${radarSourceXY.x.toFixed(0)}-${radarSourceXY.y.toFixed(0)}`;
// reset the "used" flag on pre-processed radars
// items that were not used during this process are deleted (either expired via time or change of location)
processedRadars.forEach((radar) => { radar.used = false; });
// remove any radars that aren't
// Load the most recent doppler radar images.
const radarInfo = await Promise.all(urls.map(async (url) => {
const processedRadar = await processRadar({
// store the time
const timeMatch = url.match(/_(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)\./);
const [, year, month, day, hour, minute] = timeMatch;
const radarKeyedTimestamp = `${radarKey}:${year}${month}${day}${hour}${minute}`;
// check for a pre-processed radar
const preProcessed = processedRadars.find((radar) => radar.key === radarKeyedTimestamp);
// use the pre-processed radar, or get a new one
const processedRadar = preProcessed?.dataURL ?? await processRadar({
url,
RADAR_HOST,
OVERRIDES,
radarSourceXY,
});
// store the time
const timeMatch = url.match(/_(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)\./);
// store the radar
if (!preProcessed) {
processedRadars.push({
key: radarKeyedTimestamp,
dataURL: processedRadar,
used: true,
});
} else {
// set used flag
preProcessed.used = true;
}
const [, year, month, day, hour, minute] = timeMatch;
const time = DateTime.fromObject({
year,
month,
@@ -150,12 +179,15 @@ class Radar extends WeatherDisplay {
this.times = radarInfo.map((radar) => radar.time);
this.setStatus(STATUS.loaded);
// clean up any unused stored radars
processedRadars = processedRadars.filter((radar) => radar.used);
}
async drawCanvas() {
super.drawCanvas();
const time = this.times[this.screenIndex].toLocaleString(DateTime.TIME_SIMPLE);
const timePadded = time.length >= 8 ? time : ` ${time}`;
const timePadded = time.length >= 8 ? time : ` ${time} `;
this.elem.querySelector('.header .right .time').innerHTML = timePadded;
// get image offset calculation