mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-18 09:39:30 -07:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd4ffa48c | ||
|
|
2c9e15bed0 | ||
|
|
2c31484e99 | ||
|
|
0e457881c7 | ||
|
|
56d6a68e9a | ||
|
|
6b5ac04498 | ||
|
|
465fa5a99b | ||
|
|
9c0d42c5c4 | ||
|
|
07ad5141a4 | ||
|
|
2c010a9a32 | ||
|
|
3b050073ed | ||
|
|
2953dc993c | ||
|
|
f481c5cfeb | ||
|
|
5da4a50a96 | ||
|
|
d5cce14fc2 | ||
|
|
d850165752 | ||
|
|
2d0af7a143 | ||
|
|
146a3fda76 | ||
|
|
e1083c83ae |
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.git/
|
||||||
|
Dockerfile
|
||||||
|
.vscode/
|
||||||
47
.github/workflows/build-docker.yaml
vendored
Normal file
47
.github/workflows/build-docker.yaml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: build-docker
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build Image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- id: short-sha
|
||||||
|
uses: benjlevesque/short-sha@v1.2
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/netbymatt/ws4kp
|
||||||
|
tags: |
|
||||||
|
type=raw,priority=1000,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
|
||||||
|
type=ref,event=branch
|
||||||
|
${{ steps.short-sha.outputs.sha }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and Push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
pull: true
|
||||||
|
push: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FROM node:18-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json .
|
||||||
|
COPY package-lock.json .
|
||||||
|
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
CMD ["node", "index.js"]
|
||||||
@@ -19,12 +19,18 @@ This project is based on the work of [Mike Battaglia](https://github.com/vbguyny
|
|||||||
## Run Your WeatherStar
|
## Run Your WeatherStar
|
||||||
There are a lot of CORS considerations and issues with api.weather.gov that are easiest to deal with by running a local server to see this in action (or use the live link above). You'll need Node.js >12.0 to run the local server.
|
There are a lot of CORS considerations and issues with api.weather.gov that are easiest to deal with by running a local server to see this in action (or use the live link above). You'll need Node.js >12.0 to run the local server.
|
||||||
|
|
||||||
|
To run via Node locally:
|
||||||
```
|
```
|
||||||
git clone https://github.com/netbymatt/ws4kp.git
|
git clone https://github.com/netbymatt/ws4kp.git
|
||||||
cd ws4kp
|
cd ws4kp
|
||||||
npm i
|
npm i
|
||||||
node index.js
|
node index.js
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To run via Docker:
|
||||||
|
```
|
||||||
|
docker run -p 8080:8080 ghcr.io/netbymatt/ws4kp
|
||||||
|
```
|
||||||
Open your web browser: http://localhost:8080/
|
Open your web browser: http://localhost:8080/
|
||||||
|
|
||||||
## Updates in 5.0
|
## Updates in 5.0
|
||||||
|
|||||||
2
dist/index.html
vendored
2
dist/index.html
vendored
File diff suppressed because one or more lines are too long
2
dist/resources/vendor.min.js
vendored
2
dist/resources/vendor.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/resources/ws.min.css
vendored
2
dist/resources/ws.min.css
vendored
File diff suppressed because one or more lines are too long
2
dist/resources/ws.min.js
vendored
2
dist/resources/ws.min.js
vendored
File diff suppressed because one or more lines are too long
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ws4kp",
|
"name": "ws4kp",
|
||||||
"version": "5.9.8",
|
"version": "5.9.11",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ws4kp",
|
"name": "ws4kp",
|
||||||
"version": "5.9.8",
|
"version": "5.9.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"del": "^6.0.0",
|
"del": "^6.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ws4kp",
|
"name": "ws4kp",
|
||||||
"version": "5.9.8",
|
"version": "5.9.11",
|
||||||
"description": "Welcome to the WeatherStar 4000+ project page!",
|
"description": "Welcome to the WeatherStar 4000+ project page!",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -274,9 +274,9 @@ const resize = () => {
|
|||||||
|
|
||||||
const scale = Math.min(widthZoomPercent, heightZoomPercent);
|
const scale = Math.min(widthZoomPercent, heightZoomPercent);
|
||||||
if (scale < 1.0 || document.fullscreenElement) {
|
if (scale < 1.0 || document.fullscreenElement) {
|
||||||
document.querySelector('#container').style.zoom = scale;
|
document.querySelector('#container').style.transform = `scale(${scale})`;
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('#container').style.zoom = 1;
|
document.querySelector('#container').style.transform = 'unset';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class Radar extends WeatherDisplay {
|
|||||||
const anchors = xmlDoc.querySelectorAll('a');
|
const anchors = xmlDoc.querySelectorAll('a');
|
||||||
const urls = [];
|
const urls = [];
|
||||||
Array.from(anchors).forEach((elem) => {
|
Array.from(anchors).forEach((elem) => {
|
||||||
if (elem.innerHTML?.includes('.png') && elem.innerHTML?.includes('n0r_')) {
|
if (elem.innerHTML?.match(/n0r_\d{12}\.png/)) {
|
||||||
urls.push(elem.href);
|
urls.push(elem.href);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -99,7 +99,8 @@ class Radar extends WeatherDisplay {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// get the last few images
|
// get the last few images
|
||||||
const sortedPngs = pngs.sort((a, b) => (Date(a) < Date(b) ? -1 : 1));
|
const timestampRegex = /_(\d{12})\.png/;
|
||||||
|
const sortedPngs = pngs.sort((a, b) => (a.match(timestampRegex)[1] < b.match(timestampRegex)[1] ? -1 : 1));
|
||||||
const urls = sortedPngs.slice(-(this.dopplerRadarImageMax));
|
const urls = sortedPngs.slice(-(this.dopplerRadarImageMax));
|
||||||
|
|
||||||
// calculate offsets and sizes
|
// calculate offsets and sizes
|
||||||
@@ -215,7 +216,7 @@ class Radar extends WeatherDisplay {
|
|||||||
|
|
||||||
// get image offset calculation
|
// get image offset calculation
|
||||||
// is slides slightly because of scaling so we have to take a measurement from the rendered page
|
// is slides slightly because of scaling so we have to take a measurement from the rendered page
|
||||||
const actualFrameHeight = this.elem.querySelector('.frame').getBoundingClientRect().height;
|
const actualFrameHeight = this.elem.querySelector('.frame').scrollHeight;
|
||||||
|
|
||||||
// scroll to image
|
// scroll to image
|
||||||
this.elem.querySelector('.scroll-area').style.top = `${-this.screenIndex * actualFrameHeight}px`;
|
this.elem.querySelector('.scroll-area').style.top = `${-this.screenIndex * actualFrameHeight}px`;
|
||||||
|
|||||||
@@ -167,9 +167,7 @@ class RegionalForecast extends WeatherDisplay {
|
|||||||
// draw the map
|
// draw the map
|
||||||
const scale = 640 / (offsetXY.x * 2);
|
const scale = 640 / (offsetXY.x * 2);
|
||||||
const map = this.elem.querySelector('.map');
|
const map = this.elem.querySelector('.map');
|
||||||
map.style.zoom = scale;
|
map.style.transform = `scale(${scale}) translate(-${sourceXY.x}px, -${sourceXY.y}px)`;
|
||||||
map.style.top = `-${sourceXY.y}px`;
|
|
||||||
map.style.left = `-${sourceXY.x}px`;
|
|
||||||
|
|
||||||
const cities = data.map((city) => {
|
const cities = data.map((city) => {
|
||||||
const fill = {};
|
const fill = {};
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ class WeatherDisplay {
|
|||||||
drawCanvas() {
|
drawCanvas() {
|
||||||
// clean up the first-run flag in screen index
|
// clean up the first-run flag in screen index
|
||||||
if (this.screenIndex < 0) this.screenIndex = 0;
|
if (this.screenIndex < 0) this.screenIndex = 0;
|
||||||
|
if (this.okToDrawCurrentDateTime) this.drawCurrentDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
finishDraw() {
|
finishDraw() {
|
||||||
@@ -159,14 +160,13 @@ class WeatherDisplay {
|
|||||||
this.drawCurrentDateTime();
|
this.drawCurrentDateTime();
|
||||||
// auto clock refresh
|
// auto clock refresh
|
||||||
if (!this.dateTimeInterval) {
|
if (!this.dateTimeInterval) {
|
||||||
setInterval(() => this.drawCurrentDateTime(), 100);
|
// only draw if canvas is active to conserve battery
|
||||||
|
setInterval(() => this.active && this.drawCurrentDateTime(), 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawCurrentDateTime() {
|
drawCurrentDateTime() {
|
||||||
// only draw if canvas is active to conserve battery
|
|
||||||
if (!this.active) return;
|
|
||||||
// Get the current date and time.
|
// Get the current date and time.
|
||||||
const now = DateTime.local().setZone(timeZone());
|
const now = DateTime.local().setZone(timeZone());
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -95,8 +95,9 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete-suggestions {
|
.autocomplete-suggestions {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border: 1px solid #000000;
|
border: 1px solid #000000;
|
||||||
@@ -282,8 +283,9 @@ body {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 640px;
|
width: 640px;
|
||||||
height: 480px;
|
height: 480px;
|
||||||
overflow: hidden;
|
// overflow: hidden;
|
||||||
background-image: url(../images/BackGround1_1.png);
|
background-image: url(../images/BackGround1_1.png);
|
||||||
|
transform-origin: 0 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +293,7 @@ body {
|
|||||||
background-image: none;
|
background-image: none;
|
||||||
width: unset;
|
width: unset;
|
||||||
height: unset;
|
height: unset;
|
||||||
|
transform-origin: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loading {
|
#loading {
|
||||||
@@ -373,7 +376,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#divTwcBottom img {
|
#divTwcBottom img {
|
||||||
zoom: 75%;
|
transform: scale(0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
#divTwc:fullscreen {
|
#divTwc:fullscreen {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
.map {
|
.map {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
transform-origin: 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.location {
|
.location {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<div id="radar-html" class="weather-display">
|
<div id="radar-html" class="weather-display">
|
||||||
<%- include('partials/radar.ejs') %>
|
<%- include('partials/radar.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="hazards-html" class="weather-display show">
|
<div id="hazards-html" class="weather-display">
|
||||||
<%- include('partials/hazards.ejs') %>
|
<%- include('partials/hazards.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user