Compare commits

..

9 Commits

Author SHA1 Message Date
Matt Walsh
4903b95fec 6.1.7 2025-09-09 20:26:37 -05:00
Matt Walsh
b43fb32820 Merge branch 'ios-metar-regex' 2025-09-09 20:26:29 -05:00
Matt Walsh
0d0c4ec452 fix Dockerfile.server build close #142 2025-09-09 20:06:54 -05:00
Matt Walsh
49d18c2fbe 6.1.6 2025-09-09 19:36:33 -05:00
Matt Walsh
1732a3381f fix hazards displaying when disabled (sometimes) close #140 2025-09-09 19:36:23 -05:00
Matt Walsh
093b6ac239 unique version numbers for staging uploads 2025-09-04 21:57:12 -05:00
Matt Walsh
12d068d740 playlist info in readme close #138 2025-09-04 21:26:01 -05:00
Matt Walsh
517c560ef6 don't parse metar for old ios versions 2025-09-03 21:46:48 -05:00
Matt Walsh
3eb571bed4 update community notes in readme close #135 2025-08-23 16:28:02 -05:00
7 changed files with 2520 additions and 43 deletions

View File

@@ -2,7 +2,7 @@ FROM node:24-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --legacy-peer-deps
RUN npm ci --legacy-peer-deps
COPY . .
RUN npm run build

View File

@@ -309,11 +309,13 @@ If you're unable to pre-set the play state before entering kiosk mode (such as w
## Community Notes
Thanks to the WeatherStar community for providing these discussions to further extend your retro forecasts!
Thanks to the WeatherStar+ community for providing these discussions to further extend your retro forecasts!
* [Stream as FFMPEG](https://github.com/netbymatt/ws4kp/issues/37#issuecomment-2008491948)
* [Weather like it's 1999](https://blog.scottlabs.io/2024/02/weather-like-its-1999/) Raspberry pi, streaming, music and CRT all combined into a complete solution.
* [ws4channels](https://github.com/rice9797/ws4channels) A Dockerized Node.js application to stream WeatherStar 4000 data into Channels DVR using Puppeteer and FFmpeg.
* [SSL Certificates](https://github.com/netbymatt/ws4kp/issues/135) Discussion about how to host with an SSL certificate (enables geolocation).
* [Changing playlists](https://github.com/netbymatt/ws4kp/issues/138) Possible ways to automatically change the playlist on a schedule.
## Customization

View File

@@ -97,23 +97,27 @@ const copyCss = () => src(cssSources)
const htmlSources = [
'views/*.ejs',
];
const compressHtml = async () => {
const packageJson = await readFile('package.json');
const { version } = JSON.parse(packageJson);
return src(htmlSources)
.pipe(ejs({
production: version,
serverAvailable: false,
version,
OVERRIDES,
query: {},
}))
.pipe(rename({ extname: '.html' }))
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(dest('./dist'));
const packageJson = await readFile('package.json');
let { version } = JSON.parse(packageJson);
const previewVersion = async () => {
// generate a relatively unique timestamp for cache invalidation of the preview site
const now = new Date();
const msNow = now.getTime() % 1_000_000;
version = msNow.toString();
};
const compressHtml = async () => src(htmlSources)
.pipe(ejs({
production: version,
serverAvailable: false,
version,
OVERRIDES,
query: {},
}))
.pipe(rename({ extname: '.html' }))
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(dest('./dist'));
const otherFiles = [
'server/robots.txt',
'server/manifest.json',
@@ -205,7 +209,7 @@ const buildDist = series(clean, parallel(buildJs, compressJsVendor, copyCss, com
// upload_images could be in parallel with upload, but _images logs a lot and has little changes
// by running upload last the majority of the changes will be at the bottom of the log for easy viewing
const publishFrontend = series(buildDist, uploadImages, upload, invalidate);
const stageFrontend = series(buildDist, uploadImagesPreview, uploadPreview, invalidatePreview);
const stageFrontend = series(previewVersion, buildDist, uploadImagesPreview, uploadPreview, invalidatePreview);
export default publishFrontend;

2488
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ws4kp",
"version": "6.1.5",
"version": "6.1.7",
"description": "Welcome to the WeatherStar 4000+ project page!",
"main": "index.mjs",
"type": "module",
@@ -56,6 +56,7 @@
"dotenv": "^17.0.1",
"ejs": "^3.1.5",
"express": "^5.1.0",
"metar-taf-parser": "^9.0.0"
"metar-taf-parser": "^9.0.0",
"npm": "^11.6.0"
}
}

View File

@@ -103,7 +103,10 @@ class Hazards extends WeatherDisplay {
// show alert indicator
if (unViewed > 0) alert.classList.add('show');
// draw the canvas to calculate the new timings and activate hazards in the slide deck again
this.drawLongCanvas();
// unless this has been disabled
if (this.isEnabled) {
this.drawLongCanvas();
}
} catch (error) {
console.error(`Unexpected Active Alerts error: ${error.message}`);
if (this.isEnabled) this.setStatus(STATUS.failed);
@@ -115,7 +118,7 @@ class Hazards extends WeatherDisplay {
this.getDataCallback();
if (!superResult) {
this.setStatus(STATUS.loaded);
// Don't override status - super.getData() already set it to STATUS.disabled
return;
}
this.drawLongCanvas();

View File

@@ -3,13 +3,32 @@ import { parseMetar } from '../../vendor/auto/metar-taf-parser.mjs';
// eslint-disable-next-line import/extensions
import en from '../../vendor/auto/locale/en.js';
// metar-taf-parser requires regex lookbehind
// this does not work in iOS < 16.4
// this is a detection algorithm for iOS versions
const isIos = /iP(ad|od|hone)/i.test(window.navigator.userAgent);
let iosVersionOk = false;
if (isIos) {
// regex match the version string
const iosVersionRaw = /OS (\d+)_(\d+)/.exec(window.navigator.userAgent);
// check for match
if (iosVersionRaw) {
// break into parts
const iosVersionMajor = parseInt(iosVersionRaw[1], 10);
const iosVersionMinor = parseInt(iosVersionRaw[2], 10);
if (iosVersionMajor > 16) iosVersionOk = true;
if (iosVersionMajor === 16 && iosVersionMinor >= 4) iosVersionOk = true;
}
}
/**
* Augment observation data by parsing METAR when API fields are missing
* @param {Object} observation - The observation object from the API
* @returns {Object} - Augmented observation with parsed METAR data filled in
*/
const augmentObservationWithMetar = (observation) => {
if (!observation?.rawMessage) {
// check for a metar message and for unusable ios versions
if (!observation?.rawMessage || (isIos && !iosVersionOk)) {
return observation;
}