MagicMirror/modules/default/weather/weatherutils.js
Veeck 39a614e0de
Release 2.31.0 (#3758)
Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel,
@KristjanESPERANTO, @MagMar94, @mixasgr, @n8many, @OWL4C, @rejas,
@savvadam, @sdetweil.

> ⚠️ This release needs nodejs version `v22.14.0 or higher`

### Added

- Add CSS support to the digital clock hour/minute/second through the
use of the classes `clock-hour-digital`, `clock-minute-digital`, and
`clock-second-digital`.
- Add Arabic (#3719) and Esperanto translation.
- Mark option `secondsColor` as deprecated in clock module.
- Add Greek translation to Alerts module.
- [newsfeed] Add specific ignoreOlderThan value (override) per feed
(#3360)
- [weather] Added option Humidity to hourly View
- [weather] Added option to hide hourly entries that are Zero, hiding
the entire column if empty.
- [updatenotification] Added option to iterate over modules directory
instead using modules defined in `config.js` (#3739)

### Changed

- [core] starting clientonly now checks for needed env var
`WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed
parameters (if both are set wayland is used) (#3677)
- [core] Optimize systeminformation calls and output (#3689)
- [core] Add issue templates for feature requests and bug reports
(#3695)
- [core] Adapt `start:x11:dev` script
- [weather/yr] The Yr weather provider now enforces a minimum
`updateInterval` of 600 000 ms (10 minutes) to comply with the terms of
service. If a lower value is set, it will be automatically increased to
this minimum.
- [weather/weatherflow] Fixed icons and added hourly support as well as
UV, precipitation, and location name support.
- [workflow] Run `sudo apt-get update` before installing packages to
avoid install errors
- [workflow] Exclude issues with label `ready (coming with next
release)` from stale job

### Removed

### Updated

- [core] Update requirements and dependencies including electron to v35
and formatting (#3593, #3693, #3717)
- [core] Update prettier, ESLint and simplify config
- Update Greek translation

### Fixed

- [calendar] Fix clipping events being broadcast (#3678)
- [tests] Fix Electron tests by running them under new github image
ubuntu-24.04, replace xserver with labwc, running under xserver and
labwc depending on env variable WAYLAND_DISPLAY is set (#3676)
- [calendar] Fix arrayed symbols, #3267, again, add testcase, add
testcase for #3678
- [weather] Fix wrong weatherCondition name in openmeteo provider which
lead to n/a icon (#3691)
- [core] Fix wrong port in log message when starting server only (#3696)
- [calendar] Fix NewYork event processed on system in Central timezone
shows wrong time #3701
- [weather/yr] The Yr weather provider is now able to recover from bad
API responses instead of freezing (#3296)
- [compliments] Fix evening events being shown during the day (#3727)
- [weather] Fixed minor spacing issues when using UV Index in Hourly
- [workflow] Fix command to run spellcheck

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Michael Teeuw <michael@xonaymedia.nl>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Karsten Hassel <hassel@gmx.de>
Co-authored-by: Ross Younger <crazyscot@gmail.com>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: jkriegshauser <joshuakr@nvidia.com>
Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com>
Co-authored-by: sam detweiler <sdetweil@gmail.com>
Co-authored-by: vppencilsharpener <tim.pray@gmail.com>
Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com>
Co-authored-by: Brian O'Connor <btoconnor@users.noreply.github.com>
Co-authored-by: WallysWellies <59727507+WallysWellies@users.noreply.github.com>
Co-authored-by: Jason Stieber <jrstieber@gmail.com>
Co-authored-by: jargordon <50050429+jargordon@users.noreply.github.com>
Co-authored-by: Daniel <32464403+dkallen78@users.noreply.github.com>
Co-authored-by: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com>
Co-authored-by: Panagiotis Skias <panagiotis.skias@gmail.com>
Co-authored-by: Marc Landis <dirk.rettschlag@gmail.com>
Co-authored-by: HeikoGr <20295490+HeikoGr@users.noreply.github.com>
Co-authored-by: Pedro Lamas <pedrolamas@gmail.com>
Co-authored-by: veeck <gitkraken@veeck.de>
Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com>
Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>
Co-authored-by: DevIncomin <56730075+Developer-Incoming@users.noreply.github.com>
Co-authored-by: Nathan <n8nyoung@gmail.com>
Co-authored-by: mixasgr <mixasgr@users.noreply.github.com>
Co-authored-by: Savvas Adamtziloglou <savvas-gr@greeklug.gr>
Co-authored-by: Konstantinos <geraki@gmail.com>
Co-authored-by: OWL4C <124401812+OWL4C@users.noreply.github.com>
2025-04-01 20:11:02 +02:00

169 lines
5.5 KiB
JavaScript

const WeatherUtils = {
/**
* Convert wind (from m/s) to beaufort scale
* @param {number} speedInMS the windspeed you want to convert
* @returns {number} the speed in beaufort
*/
beaufortWindSpeed (speedInMS) {
const windInKmh = this.convertWind(speedInMS, "kmh");
const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
for (const [index, speed] of speeds.entries()) {
if (speed > windInKmh) {
return index;
}
}
return 12;
},
/**
* Convert a value in a given unit to a string with a converted
* value and a postfix matching the output unit system.
* @param {number} value - The value to convert.
* @param {string} valueUnit - The unit the values has. Default is mm.
* @param {string} outputUnit - The unit system (imperial/metric) the return value should have.
* @returns {string} - A string with tha value and a unit postfix.
*/
convertPrecipitationUnit (value, valueUnit, outputUnit) {
if (valueUnit === "%") return `${value.toFixed(0)} ${valueUnit}`;
let convertedValue = value;
let conversionUnit = valueUnit;
if (outputUnit === "imperial") {
convertedValue = this.convertPrecipitationToInch(value, valueUnit);
conversionUnit = "in";
} else {
conversionUnit = valueUnit ? valueUnit : "mm";
}
return `${convertedValue.toFixed(2)} ${conversionUnit}`;
},
/**
* Convert precipitation value into inch
* @param {number} value the precipitation value for convert
* @param {string} valueUnit can be 'mm' or 'cm'
* @returns {number} the converted precipitation value
*/
convertPrecipitationToInch (value, valueUnit) {
if (valueUnit && valueUnit.toLowerCase() === "cm") return value * 0.3937007874;
else return value * 0.03937007874;
},
/**
* Convert temp (from degrees C) into imperial or metric unit depending on
* your config
* @param {number} tempInC the temperature in celsius you want to convert
* @param {string} unit can be 'imperial' or 'metric'
* @returns {number} the converted temperature
*/
convertTemp (tempInC, unit) {
return unit === "imperial" ? tempInC * 1.8 + 32 : tempInC;
},
/**
* Convert wind speed into another unit.
* @param {number} windInMS the windspeed in meter/sec you want to convert
* @param {string} unit can be 'beaufort', 'kmh', 'knots, 'imperial' (mph)
* or 'metric' (mps)
* @returns {number} the converted windspeed
*/
convertWind (windInMS, unit) {
switch (unit) {
case "beaufort":
return this.beaufortWindSpeed(windInMS);
case "kmh":
return (windInMS * 3600) / 1000;
case "knots":
return windInMS * 1.943844;
case "imperial":
return windInMS * 2.2369362920544;
case "metric":
default:
return windInMS;
}
},
/*
* Convert the wind direction cardinal to value
*/
convertWindDirection (windDirection) {
const windCardinals = {
N: 0,
NNE: 22,
NE: 45,
ENE: 67,
E: 90,
ESE: 112,
SE: 135,
SSE: 157,
S: 180,
SSW: 202,
SW: 225,
WSW: 247,
W: 270,
WNW: 292,
NW: 315,
NNW: 337
};
return windCardinals.hasOwnProperty(windDirection) ? windCardinals[windDirection] : null;
},
convertWindToMetric (mph) {
return mph / 2.2369362920544;
},
convertWindToMs (kmh) {
return kmh * 0.27777777777778;
},
calculateFeelsLike (temperature, windSpeed, humidity) {
const windInMph = this.convertWind(windSpeed, "imperial");
const tempInF = this.convertTemp(temperature, "imperial");
let feelsLike = tempInF;
if (windInMph > 3 && tempInF < 50) {
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
} else if (tempInF > 80 && humidity > 40) {
feelsLike
= -42.379
+ 2.04901523 * tempInF
+ 10.14333127 * humidity
- 0.22475541 * tempInF * humidity
- 6.83783 * Math.pow(10, -3) * tempInF * tempInF
- 5.481717 * Math.pow(10, -2) * humidity * humidity
+ 1.22874 * Math.pow(10, -3) * tempInF * tempInF * humidity
+ 8.5282 * Math.pow(10, -4) * tempInF * humidity * humidity
- 1.99 * Math.pow(10, -6) * tempInF * tempInF * humidity * humidity;
}
return ((feelsLike - 32) * 5) / 9;
},
/**
* Converts the Weather Object's values into imperial unit
* @param {object} weatherObject the weather object
* @returns {object} the weather object with converted values to imperial
*/
convertWeatherObjectToImperial (weatherObject) {
if (!weatherObject || Object.keys(weatherObject).length === 0) return null;
let imperialWeatherObject = { ...weatherObject };
if (imperialWeatherObject) {
if (imperialWeatherObject.feelsLikeTemp) imperialWeatherObject.feelsLikeTemp = this.convertTemp(imperialWeatherObject.feelsLikeTemp, "imperial");
if (imperialWeatherObject.maxTemperature) imperialWeatherObject.maxTemperature = this.convertTemp(imperialWeatherObject.maxTemperature, "imperial");
if (imperialWeatherObject.minTemperature) imperialWeatherObject.minTemperature = this.convertTemp(imperialWeatherObject.minTemperature, "imperial");
if (imperialWeatherObject.precipitationAmount) imperialWeatherObject.precipitationAmount = this.convertPrecipitationToInch(imperialWeatherObject.precipitationAmount, imperialWeatherObject.precipitationUnits);
if (imperialWeatherObject.temperature) imperialWeatherObject.temperature = this.convertTemp(imperialWeatherObject.temperature, "imperial");
if (imperialWeatherObject.windSpeed) imperialWeatherObject.windSpeed = this.convertWind(imperialWeatherObject.windSpeed, "imperial");
}
return imperialWeatherObject;
}
};
if (typeof module !== "undefined") {
module.exports = WeatherUtils;
}