mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-16 16:49:30 -07:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
471d322cde | ||
|
|
8f9be046ac | ||
|
|
c34dc1ff25 | ||
|
|
9b4eed7332 | ||
|
|
ef1477f9eb | ||
|
|
e2876df177 | ||
|
|
d6335b2878 | ||
|
|
781128100e | ||
|
|
56261ded4b |
@@ -16,6 +16,13 @@ This project is based on the work of [Mike Battaglia](https://github.com/vbguyny
|
||||
* [Icon](https://twcclassics.com/downloads.html) sets
|
||||
* Countless photos and videos of WeatherStar 4000 forecasts used as references.
|
||||
|
||||
## Does WeatherStar 4000+ work outside of the USA?
|
||||
|
||||
This project is tightly coupled to [NOAA's Weather API](https://www.weather.gov/documentation/services-web-api), which is exclsuive to the United States. Using NOAA's Weather API is a crucial requirement to provide an authentic WeatherStar 4000+ experience.
|
||||
|
||||
If you would like to display weather information for international locations (outside of the USA), please checkout a fork of this project created by [@mwood77](https://github.com/mwood77):
|
||||
- [`ws4kp-international`](https://github.com/mwood77/ws4kp-international)
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
2
dist/index.html
vendored
2
dist/index.html
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",
|
||||
"version": "5.14.0",
|
||||
"version": "5.14.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ws4kp",
|
||||
"version": "5.14.0",
|
||||
"version": "5.14.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ejs": "^3.1.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ws4kp",
|
||||
"version": "5.14.0",
|
||||
"version": "5.14.3",
|
||||
"description": "Welcome to the WeatherStar 4000+ project page!",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { loadImg, preloadImg } from './utils/image.mjs';
|
||||
import { DateTime } from '../vendor/auto/luxon.mjs';
|
||||
import STATUS from './status.mjs';
|
||||
import WeatherDisplay from './weatherdisplay.mjs';
|
||||
import { registerDisplay } from './navigation.mjs';
|
||||
import { registerDisplay, timeZone } from './navigation.mjs';
|
||||
|
||||
class Almanac extends WeatherDisplay {
|
||||
constructor(navId, elemId) {
|
||||
@@ -123,10 +123,10 @@ class Almanac extends WeatherDisplay {
|
||||
// sun and moon data
|
||||
this.elem.querySelector('.day-1').innerHTML = Today.toLocaleString({ weekday: 'long' });
|
||||
this.elem.querySelector('.day-2').innerHTML = Tomorrow.toLocaleString({ weekday: 'long' });
|
||||
this.elem.querySelector('.rise-1').innerHTML = DateTime.fromJSDate(info.sun[0].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.rise-2').innerHTML = DateTime.fromJSDate(info.sun[1].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.set-1').innerHTML = DateTime.fromJSDate(info.sun[0].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.set-2').innerHTML = DateTime.fromJSDate(info.sun[1].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.rise-1').innerHTML = DateTime.fromJSDate(info.sun[0].sunrise).setZone(timeZone()).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.rise-2').innerHTML = DateTime.fromJSDate(info.sun[1].sunrise).setZone(timeZone()).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.set-1').innerHTML = DateTime.fromJSDate(info.sun[0].sunset).setZone(timeZone()).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
this.elem.querySelector('.set-2').innerHTML = DateTime.fromJSDate(info.sun[1].sunset).setZone(timeZone()).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase();
|
||||
|
||||
const days = info.moon.map((MoonPhase) => {
|
||||
const fill = {};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import STATUS from './status.mjs';
|
||||
import getHourlyData from './hourly.mjs';
|
||||
import WeatherDisplay from './weatherdisplay.mjs';
|
||||
import { registerDisplay } from './navigation.mjs';
|
||||
import { registerDisplay, timeZone } from './navigation.mjs';
|
||||
import { DateTime } from '../vendor/auto/luxon.mjs';
|
||||
|
||||
class HourlyGraph extends WeatherDisplay {
|
||||
@@ -145,7 +145,7 @@ const drawPath = (path, ctx, options) => {
|
||||
};
|
||||
|
||||
// format as 1p, 12a, etc.
|
||||
const formatTime = (time) => time.toFormat('ha').slice(0, -1);
|
||||
const formatTime = (time) => time.setZone(timeZone()).toFormat('ha').slice(0, -1);
|
||||
|
||||
// register display
|
||||
registerDisplay(new HourlyGraph(4, 'hourly-graph'));
|
||||
|
||||
@@ -7,7 +7,7 @@ import { temperature as temperatureUnit, distanceKilometers } from './utils/unit
|
||||
import { getHourlyIcon } from './icons.mjs';
|
||||
import { directionToNSEW } from './utils/calc.mjs';
|
||||
import WeatherDisplay from './weatherdisplay.mjs';
|
||||
import { registerDisplay } from './navigation.mjs';
|
||||
import { registerDisplay, timeZone } from './navigation.mjs';
|
||||
import getSun from './almanac.mjs';
|
||||
|
||||
class Hourly extends WeatherDisplay {
|
||||
@@ -56,10 +56,7 @@ class Hourly extends WeatherDisplay {
|
||||
const list = this.elem.querySelector('.hourly-lines');
|
||||
list.innerHTML = '';
|
||||
|
||||
// get a unit converter
|
||||
const temperatureConverter = temperatureUnit();
|
||||
|
||||
const startingHour = DateTime.local();
|
||||
const startingHour = DateTime.local().setZone(timeZone());
|
||||
|
||||
const lines = this.data.map((data, index) => {
|
||||
const fillValues = {};
|
||||
@@ -69,8 +66,8 @@ class Hourly extends WeatherDisplay {
|
||||
fillValues.hour = formattedHour;
|
||||
|
||||
// temperatures, convert to strings with no decimal
|
||||
const temperature = temperatureConverter(data.temperature).toString().padStart(3);
|
||||
const feelsLike = Math.round(data.apparentTemperature).toString().padStart(3);
|
||||
const temperature = data.temperature.toString().padStart(3);
|
||||
const feelsLike = data.apparentTemperature.toString().padStart(3);
|
||||
fillValues.temp = temperature;
|
||||
// only plot apparent temperature if there is a difference
|
||||
// if (temperature !== feelsLike) line.querySelector('.like').innerHTML = feelsLike;
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { getWeatherRegionalIconFromIconLink } from './icons.mjs';
|
||||
import { preloadImg } from './utils/image.mjs';
|
||||
import { json } from './utils/fetch.mjs';
|
||||
import { temperature as temperatureUnit } from './utils/units.mjs';
|
||||
|
||||
const buildForecast = (forecast, city, cityXY) => ({
|
||||
daytime: forecast.isDaytime,
|
||||
temperature: forecast.temperature || 0,
|
||||
name: formatCity(city.city),
|
||||
icon: forecast.icon,
|
||||
x: cityXY.x,
|
||||
y: cityXY.y,
|
||||
time: forecast.startTime,
|
||||
});
|
||||
const buildForecast = (forecast, city, cityXY) => {
|
||||
// get a unit converter
|
||||
const temperatureConverter = temperatureUnit('us');
|
||||
return {
|
||||
daytime: forecast.isDaytime,
|
||||
temperature: temperatureConverter(forecast.temperature || 0),
|
||||
name: formatCity(city.city),
|
||||
icon: forecast.icon,
|
||||
x: cityXY.x,
|
||||
y: cityXY.y,
|
||||
time: forecast.startTime,
|
||||
};
|
||||
};
|
||||
|
||||
const getRegionalObservation = async (point, city) => {
|
||||
try {
|
||||
|
||||
@@ -7,6 +7,7 @@ const round2 = (value, decimals) => Math.trunc(value * 10 ** decimals) / 10 ** d
|
||||
|
||||
const kphToMph = (Kph) => Math.round(Kph / 1.609_34);
|
||||
const celsiusToFahrenheit = (Celsius) => Math.round((Celsius * 9) / 5 + 32);
|
||||
const fahrenheitToCelsius = (Fahrenheit) => Math.round((Fahrenheit - 32) * 5 / 9);
|
||||
const kilometersToMiles = (Kilometers) => Math.round(Kilometers / 1.609_34);
|
||||
const metersToFeet = (Meters) => Math.round(Meters / 0.3048);
|
||||
const pascalToInHg = (Pascal) => round2(Pascal * 0.000_295_3, 2);
|
||||
@@ -35,7 +36,11 @@ const temperature = (defaultUnit = 'si') => {
|
||||
let converter = (passthru) => Math.round(passthru);
|
||||
// change the converter if there is a mismatch
|
||||
if (defaultUnit !== settings.units.value) {
|
||||
converter = celsiusToFahrenheit;
|
||||
if (defaultUnit === 'us') {
|
||||
converter = fahrenheitToCelsius;
|
||||
} else {
|
||||
converter = celsiusToFahrenheit;
|
||||
}
|
||||
}
|
||||
// append units
|
||||
if (settings.units.value === 'si') {
|
||||
|
||||
Reference in New Issue
Block a user