forked from MagicMirrorOrg/MagicMirror
-
Notifications
You must be signed in to change notification settings - Fork 0
[weather] refactor: migrate to server-side providers with centralized HTTPFetcher #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
KristjanESPERANTO
wants to merge
107
commits into
develop
Choose a base branch
from
weather
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
107 commits
Select commit
Hold shift + click to select a range
4544bdc
refactor(weather): migrate OpenMeteo provider to server-side with HTT…
KristjanESPERANTO 162c9d8
refactor(weather): migrate OpenWeatherMap provider to server-side
KristjanESPERANTO 07dfd96
refactor(weather): migrate WeatherGov provider to server-side
KristjanESPERANTO 94d52f5
refactor(weather): migrate Yr.no provider to server-side
KristjanESPERANTO 74e47a2
refactor(weather): migrate SMHI provider to server-side
KristjanESPERANTO d59b5d5
refactor(weather): migrate EnvCanada provider to server-side
KristjanESPERANTO efd69e4
chore(weather): improve authentication error message for clarity
KristjanESPERANTO 16d6689
refactor(weather): migrate Pirateweather provider to server-side
KristjanESPERANTO a6c6b80
refactor(weather): migrate UkMetOfficeDataHub provider to server-side
KristjanESPERANTO 031ea10
refactor(weather): add logContext to HTTPFetcher options for better l…
KristjanESPERANTO df59ad5
refactor(weather): migrate Weatherbit provider to server-side
KristjanESPERANTO 7e07e36
refactor(weather): migrate WeatherFlow provider to server-side
KristjanESPERANTO 2510972
refactor(weather): integrate override logic into weather.js
KristjanESPERANTO d168d79
docs(weather): update link to MagicMirror² weather provider documenta…
KristjanESPERANTO c054b8e
refactor(weather): complete server-side migration cleanup
KristjanESPERANTO 060b9d1
refactor(weather): remove unnecessary log prefixes in node_helper.js
KristjanESPERANTO ca1a0de
fix(weather): update EnvCanada provider for API structure change
KristjanESPERANTO 60e22f2
test(weather): Add weather provider smoke tests
KristjanESPERANTO cb1bca3
feat(weather): add stopWeatherProvider functionality to manage weathe…
KristjanESPERANTO 8a90f4c
fix(weather): Fix timezone handling in OpenMeteo and Weatherbit
KristjanESPERANTO e357732
refactor(tests): clean up weather E2E tests with socket injection
KristjanESPERANTO 6cf800c
refactor(tests): migrate Electron weather tests to socket injection
KristjanESPERANTO a3643fe
refactor(weather): enhance JSDoc comments for callback parameters in …
KristjanESPERANTO 5aaebda
refactor(tests): improve weather module initialization and rendering …
KristjanESPERANTO 1f82392
fix(weather): add switch default cases to prevent undefined callbacks
KristjanESPERANTO 255fd78
fix(openmeteo): use API timezone instead of server timezone for hourl…
KristjanESPERANTO b62d698
fix(weathergov): convert wind direction from string to degrees
KristjanESPERANTO 7a938a1
fix(yr): use local timezone instead of hardcoded CET for sunrise API
KristjanESPERANTO 4abc975
refactor(openweathermap): validate callbacks before initialize
KristjanESPERANTO c404a79
refactor(weather): extract shared utilities to reduce code duplication
KristjanESPERANTO 99b8954
test(weather): restore global fetch mock after tests
KristjanESPERANTO a65346d
fix(envcanada): replace magic number 999 with null for temperature cache
KristjanESPERANTO 25f1338
fix(yr): await stellar data fetch when using cached weather data
KristjanESPERANTO 11dc77b
refactor(weather): centralize limitDecimals utility
KristjanESPERANTO 718ac8c
refactor(ukmetofficedatahub): make internal methods private
KristjanESPERANTO 9d72d17
refactor(openmeteo): simplify property checks
KristjanESPERANTO e71b835
fix(weather): prevent invalid moment objects from null dates
KristjanESPERANTO 18dc9d8
refactor(weather): rename utils.js to provider-utils.js
KristjanESPERANTO c0c85d5
fix(weather): handle missing sunrise/sunset data gracefully
KristjanESPERANTO 58cdaa5
test(weather): add unit tests for provider-utils
KristjanESPERANTO 8a4498d
fix(weather): use local time in getDateString instead of UTC
KristjanESPERANTO ebecaac
fix(weatherbit): use data timestamp for sunrise/sunset date
KristjanESPERANTO 8f48c43
fix(envcanada): prevent double timezone shift in date parsing
KristjanESPERANTO cdb12ff
fix(openmeteo): handle both hourly data shapes in current weather
KristjanESPERANTO 53582ee
chore(eslint): allow loose equality for null checks
KristjanESPERANTO b80b1e8
fix(smhi): correct gap-filling algorithm to preserve data
KristjanESPERANTO 7d70370
fix(ukmetofficedatahub): use precipitationAmount instead of precipita…
KristjanESPERANTO b70e49a
fix(weathergov): remove incorrect wind conversion for observations
KristjanESPERANTO e176854
fix(yr): add default case to weather type switch
KristjanESPERANTO 7fab859
test(weather): add validation for mock weather data fixtures
KristjanESPERANTO 0c9a7c1
test(server_functions): restore global.config after test
KristjanESPERANTO c1a9ab4
refactor(weather): centralize common utility functions
KristjanESPERANTO 869be0a
fix(weather): add default cases to all provider switch statements
KristjanESPERANTO 06a5234
fix(weather): add error handling to smhi initialize
KristjanESPERANTO 0c80359
fix(weather): add defensive null checks to weatherflow provider
KristjanESPERANTO 8f8cad2
refactor(weather): code quality improvements from nitpick review
KristjanESPERANTO 34137df
fix(weather): additional nitpick improvements
KristjanESPERANTO 46179d9
fix(weather): correct WeatherFlow provider event handling and data st…
KristjanESPERANTO 2d0f89f
fix(weather): improve Yr.no daily forecast data aggregation
KristjanESPERANTO 960bee6
fix(weather): EnvCanada hourly timestamps and null value handling
KristjanESPERANTO 3f342ca
fix(weather): change log level from warn to debug for missing hourly …
KristjanESPERANTO 2389502
fix(weather): improve null value handling and error logging
KristjanESPERANTO 245dc8f
fix(weather): increase Weather.gov timeout for reliability
KristjanESPERANTO 54f85d2
chore(weather): simplify log prefixes for weather providers
KristjanESPERANTO 8b2fd36
fix(weather): transform Yr.no stellar data into expected array format
KristjanESPERANTO 409d907
fix(weather): correct OpenMeteo daily data access after transpose
KristjanESPERANTO c280d67
fix(weather): preserve 0% precipitation probability in OpenWeatherMap
KristjanESPERANTO 5941092
fix(weather): use config values for units and lang in Pirateweather
KristjanESPERANTO 3295851
fix(weather): prevent undefined data callback in SMHI default case
KristjanESPERANTO 570833f
fix(weather): use correct property name precipitationAmount in Weathe…
KristjanESPERANTO e15ea06
fix(weather): add null-check for wind_avg in WeatherFlow
KristjanESPERANTO cae1fe8
fix(weather): add error callbacks for unknown weather types
KristjanESPERANTO 1674363
fix(weather): use timestamp comparison in OpenMeteo time matching
KristjanESPERANTO c6483f6
style(tests): fix formatting in hourlyweather_default config
KristjanESPERANTO 488501e
feat(weather): add retry logic and prevent parallel DNS lookups
KristjanESPERANTO f73fca3
fix(weather): reduce log noise in EnvCanada during hour transitions
KristjanESPERANTO 8bcbd76
test: add comprehensive unit tests for weather providers
KristjanESPERANTO 2a77aef
fix(weather): handle null values in OpenMeteo provider
KristjanESPERANTO 3508e01
fix(weather): add missing icon code 40 to EnvCanada provider
KristjanESPERANTO 189a2f7
refactor(weather): use #http_fetcher alias in WeatherFlow provider
KristjanESPERANTO 0d57cd8
fix(weather): fix provider bugs from CodeRabbit review
KristjanESPERANTO fe0161e
fix(core): improve error handling and remove dead code
KristjanESPERANTO 7b5bd65
fix(tests): preserve 0 values in test helpers
KristjanESPERANTO f300949
chore(tests): clean up test specs
KristjanESPERANTO 9d27f04
style(weather): split multi-statement lines in OpenWeatherMap
KristjanESPERANTO 6284897
fix(weather): rename windDirection to windFromDirection
KristjanESPERANTO d05aff1
chore: remove unused imports
KristjanESPERANTO 56a20a8
refactor(tests): simplify EnvCanada error test
KristjanESPERANTO 5ee079c
fix(server): restore /version endpoint
KristjanESPERANTO 9fa9995
fix(weather): increase OpenMeteo geocoding timeout and reduce log noise
KristjanESPERANTO 1c760b5
fix(envcanada): restore complete weatherType map (codes 0-48)
KristjanESPERANTO 29b9b75
fix(pirateweather): use correct WeatherObject field names
KristjanESPERANTO f349991
fix(weatherflow): compare full date instead of day-of-month
KristjanESPERANTO 02b0c05
refactor(tests): replace waitForTimeout with deterministic waits
KristjanESPERANTO c6c9439
style(tests): break multi-statement line in ukmetoffice test
KristjanESPERANTO bb50cad
fix(envcanada): set temperature to null when unavailable
KristjanESPERANTO 9eed95e
fix(envcanada): handle empty currentConditions element
KristjanESPERANTO 9c0c06b
revert: restore CORS proxy for newsfeed and 3rd-party module compatib…
KristjanESPERANTO f6ae5c7
tests(weather): fix EnvCanada provider to read current weather from c…
KristjanESPERANTO 33e8eaa
refactor: use hasOwnProperty for precipAccumulation check
KristjanESPERANTO 2807859
feat(ukmetofficedatahub): add withFutureDailyTimes function to shift …
KristjanESPERANTO 6945854
refactor(weather): change method visibility to private
KristjanESPERANTO 7ee5d42
refactor(pirateweather): change default units from 'us' to 'si' in ge…
KristjanESPERANTO 0b041d9
feat(http_fetcher): improve network error handling with exponential b…
KristjanESPERANTO 88c49b4
fix(weatherbit): fix weather icon mappings
KristjanESPERANTO d54caa6
feat(weatherapi): implement WeatherAPIProvider for current, daily, an…
KristjanESPERANTO be9c24a
refactor(weather): extract cardinalToDegrees() to provider-utils.js
KristjanESPERANTO File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| const path = require("node:path"); | ||
| const NodeHelper = require("node_helper"); | ||
| const Log = require("logger"); | ||
|
|
||
| module.exports = NodeHelper.create({ | ||
| providers: {}, | ||
|
|
||
| start () { | ||
| Log.log(`Starting node helper for: ${this.name}`); | ||
| }, | ||
|
|
||
| socketNotificationReceived (notification, payload) { | ||
| if (notification === "INIT_WEATHER") { | ||
| Log.log(`Received INIT_WEATHER for instance ${payload.instanceId}`); | ||
| this.initWeatherProvider(payload); | ||
| } else if (notification === "STOP_WEATHER") { | ||
| Log.log(`Received STOP_WEATHER for instance ${payload.instanceId}`); | ||
| this.stopWeatherProvider(payload.instanceId); | ||
| } | ||
| // FETCH_WEATHER is no longer needed - HTTPFetcher handles periodic fetching | ||
| }, | ||
|
|
||
| /** | ||
| * Initialize a weather provider | ||
| * @param {object} config The configuration object | ||
| */ | ||
| async initWeatherProvider (config) { | ||
| const identifier = config.weatherProvider.toLowerCase(); | ||
| const instanceId = config.instanceId; | ||
|
|
||
| Log.log(`Attempting to initialize provider ${identifier} for instance ${instanceId}`); | ||
|
|
||
| if (this.providers[instanceId]) { | ||
| Log.log(`Weather provider ${identifier} already initialized for instance ${instanceId}`); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| // Dynamically load the provider module | ||
| const providerPath = path.join(__dirname, "providers", `${identifier}.js`); | ||
| Log.log(`Loading provider from: ${providerPath}`); | ||
| const ProviderClass = require(providerPath); | ||
|
|
||
| // Create provider instance | ||
| const provider = new ProviderClass(config); | ||
|
|
||
| // Set up callbacks before initializing | ||
| provider.setCallbacks( | ||
| (data) => { | ||
| // On data received | ||
| this.sendSocketNotification("WEATHER_DATA", { | ||
| instanceId, | ||
| type: config.type, | ||
| data | ||
| }); | ||
| }, | ||
| (errorInfo) => { | ||
| // On error | ||
| this.sendSocketNotification("WEATHER_ERROR", { | ||
| instanceId, | ||
| error: errorInfo.message || "Unknown error", | ||
| translationKey: errorInfo.translationKey | ||
| }); | ||
| } | ||
| ); | ||
|
|
||
| await provider.initialize(); | ||
| this.providers[instanceId] = provider; | ||
|
|
||
| this.sendSocketNotification("WEATHER_INITIALIZED", { | ||
| instanceId, | ||
| locationName: provider.locationName | ||
KristjanESPERANTO marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| // Start periodic fetching | ||
| provider.start(); | ||
KristjanESPERANTO marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Log.log(`Weather provider ${identifier} initialized for instance ${instanceId}`); | ||
| } catch (error) { | ||
| Log.error(`Failed to initialize weather provider ${identifier}:`, error); | ||
| this.sendSocketNotification("WEATHER_ERROR", { | ||
| instanceId, | ||
| error: error.message | ||
| }); | ||
| } | ||
| }, | ||
|
|
||
| /** | ||
| * Stop and cleanup a weather provider | ||
| * @param {string} instanceId The instance identifier | ||
| */ | ||
| stopWeatherProvider (instanceId) { | ||
| const provider = this.providers[instanceId]; | ||
|
|
||
| if (provider) { | ||
| Log.log(`Stopping weather provider for instance ${instanceId}`); | ||
| provider.stop(); | ||
| delete this.providers[instanceId]; | ||
| } else { | ||
| Log.warn(`No provider found for instance ${instanceId}`); | ||
| } | ||
| } | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.