Download the PHP package drakelid/librenms-weather-risk-map-widget without Composer

On this page you can find all versions of the php package drakelid/librenms-weather-risk-map-widget. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package librenms-weather-risk-map-widget

Weather Risk Map

A LibreNMS dashboard widget that shows which network sites are about to be hit by bad weather.

It reads the GPS coordinates already stored on your LibreNMS devices, correlates them with forecasts and official severe-weather warnings, and reports an infrastructure risk level — not a weather report.

LibreNMS 26.7.0-68-g1dfe1994d
PHP ^8.2
Laravel ^12.10
Core files modified none
Database changes none
JS dependencies none (Leaflet ships with LibreNMS)
Licence GPL-3.0-or-later

Contents

  1. Quick start
  2. Risk levels
  3. How it works
  4. Weather data sources
  5. Installation
  6. Configuration
  7. The risk algorithm
  8. Map and UI behaviour
  9. Testing
  10. Troubleshooting
  11. Files created and modified
  12. Known limitations
  13. Future improvements
  14. Verification status

1. Quick start

[!IMPORTANT] Run every command as the librenms user (sudo su - librenms first). LibreNMS refuses artisan as anyone else, and running it as root or your own account leaves cache files the web server cannot write — which surfaces later as an unrelated-looking 500.

There is usually no composer on PATH. Use LibreNMS's own wrapper: php scripts/composer_wrapper.php …

First get the package onto the server, beside the LibreNMS directory:

Then, as librenms, from /opt/librenms:

Add one required line to .env:

Then clear caches and verify:

Add it to a dashboard: Overview → edit (pencil) → Add Widget → Weather Risk Map.

[!IMPORTANT] The .env line is not optional. MET Norway answers 403 to any request whose User-Agent lacks a real contact email. weather-risk-map:diagnose fails loudly while the shipped placeholder is still in place.

[!CAUTION] A LibreNMS core update will uninstall this plugin. daily.sh runs git checkout -- composer.json composer.lock, which destroys the path repository above. See §5 before putting this into production — it is not optional operational trivia, the widget silently disappears.

Full details in §5 Installation.

[!TIP] Deploying to a live LibreNMS server? Follow docs/PRODUCTION-INSTALL.md instead — a step-by-step guide including backups, verification, the persistence guard and a rollback procedure.


2. Risk levels

Level Meaning
🟢 Normal No significant risk
🔵 Info Informational / minor weather
🟡 Moderate Yellow-warning territory
🟠 High Orange-warning territory
🔴 Severe Red-warning territory
🟣 Extreme Two or more hazards at Severe

[!NOTE] Marker fill is weather risk. LibreNMS operational status is drawn separately — a device that is down keeps its weather colour and gains a dark border. The two are never conflated.


3. How it works

The widget renders before its data

The dashboard requests each widget over AJAX and swaps in the returned HTML. If the widget controller waited on the weather APIs, a slow provider would visibly stall it.

So the widget controller performs no weather I/O at all. The shell paints immediately and fetches its payload separately.

Device count does not drive API traffic

Three collapses happen in sequence:

# Collapse Effect
1 Devices → LibreNMS locations rows A POP with 40 switches is one coordinate
2 Locations → geographic grid cells Sites a forecast cannot distinguish share one lookup
3 Warnings → one national request Matched to devices locally, point-in-polygon

A 2,000-device Norwegian ISP across ~150 sites typically resolves to 30–60 forecast requests per 15 minutes, plus one warnings request per 5 minutes. Both are cached, so a NOC wall with eight browsers open generates the same traffic as one.

A hard max_cells_per_refresh ceiling bounds the worst case. Cells beyond it reuse cached data rather than being dropped.

The cache has two tiers

Every entry is written twice:

A single-tier cache loses its data exactly when the provider goes down and you need it most. On failure the widget serves the stale copy and labels it with its age. A failure marker additionally stops a dead provider being retried by every dashboard refresh from every logged-in operator.


4. Weather data sources

MET Norway — primary (met-norway)

Product Endpoint Used for
Locationforecast 2.0 …/locationforecast/2.0/compact Point forecast, per geo cell
MetAlerts 2.0 …/metalerts/2.0/current.json Every active Norwegian warning as GeoJSON polygons, in one request

Chosen because it is authoritative for Norway, it is the only candidate publishing official warning polygons with severity, and MetAlerts' single-request national coverage is what makes local polygon matching possible.

Terms-of-service compliance is implemented, not just intended:

Open-Meteo — secondary (open-meteo)

Kept behind the same interface for two reasons:

It publishes no official warnings, so supportsWarnings() returns false and warnings keep coming from MET Norway.

Lightning — an honest limitation

[!WARNING] No free, reliable public API provides real-time lightning strike data.

Lightning is modelled as risk from thunder indications in the forecast — probability_of_thunder where available, otherwise the …andthunder symbol suffix. It is flagged inferred in the payload and rendered as "(risk, not detected strikes)" in the UI. Nothing is presented as a detected strike.


5. Installation

Leaflet and Leaflet.markercluster are already bundled with LibreNMS (html/js/leaflet.js, html/js/leaflet.markercluster.js), and the widget reuses core's init_map() / get_map() / destroy_map() helpers. There are no JavaScript dependencies and no asset build step.

Prerequisites that are easy to get wrong

User Every artisan / lnms / composer command runs as librenms. Start with sudo su - librenms.
Composer Usually not on PATH. Use php /opt/librenms/scripts/composer_wrapper.php (it downloads composer.phar if the system has no Composer).
Location The package must exist on the server. ../weather-risk-map-widget resolves relative to the LibreNMS directory, i.e. /opt/weather-risk-map-widget.
Ownership sudo chown -R librenms:librenms /opt/weather-risk-map-widget, or git refuses with "detected dubious ownership" and pulls silently fail.

Steps

Set the contact email — required, see §1:

Then: Overview → dashboard → edit (pencil) → Add Widget → Weather Risk Map.

Verify the route registered — this is the single best health check, because a missing route renders as core's generic "Problem with backend":

Surviving a LibreNMS core update

[!CAUTION] Installed this way, the plugin will be removed by the next nightly update.

daily.sh does the following, in order:

composer.json is tracked in LibreNMS's git, so the checkout destroys the path repository. LibreNMS then re-requires the plugin by name from composer.plugins.json — but composer_get_plugins in daily.php reads only the require block and ignores any repositories you add there. With no repository, the package cannot resolve and is dropped.

The same pass runs --update-no-dev, which strips LibreNMS's dev dependencies. That removes PHPUnit and breaks the flare log driver in the default logging stack, so subsequent errors are not written to laravel.log at all — which makes the failure considerably harder to diagnose than it should be.

Three ways to handle it:

1. Publish the package (the real fix). If drakelid/librenms-weather-risk-map-widget resolves from Packagist, daily.sh's composer require works untouched and no repository entry is needed anywhere. A path repository is a development arrangement; this is what LibreNMS's plugin system expects.

2. Re-apply automatically. Idempotent, so it is safe hourly regardless of when daily.sh runs:

3. Disable automatic updates — arguably correct for a NOC system anyway:

[!NOTE] Defining the repository in Composer's global config does not work. Composer documents only disabling a repository globally; there is no supported way to define one that applies to another project. This was tested and failed.

Notes

Optional: pre-warm the cache

Worth it only for a permanently displayed NOC dashboard. Deliberately not scheduled by default, so an installation that never opens the widget generates no API traffic:


6. Configuration

Widget settings

Per widget, per user — edited in the widget's own settings panel.

Group Setting Options Default
General Widget title free text Weather Risk Map
Device groups multi-select, empty = all All
Risk period Current / 3 / 6 / 12 / 24 / 48 h 24 h
Minimum displayed severity All / Moderate+ / High+ / Severe+ All
Refresh interval seconds 600
Map Default map mode Auto-fit devices / Remember last position Auto-fit
Weather risk radius 1 / 5 / 10 / 25 / 50 km 10 km
Marker clustering on / off on
Show warning polygons on / off on
Hazards Wind, Storm, Lightning, Rain, Flood, Snow, Icing, Heat, Cold on / off each all on
Thresholds numeric, per hazard × moderate/high/severe blank = installation default see §7

[!NOTE] On the refresh field. The spec suggested a 5/10/15/30/60-minute dropdown. The panel instead inherits LibreNMS's own numeric refresh input from widgets.settings.base, because that is the convention every other widget follows and what core's save path validates. The default is 600 s (10 min) as specified; any value is accepted.

Installation config

config/weather-risk-map.php — provider selection, User-Agent, language, cache TTLs, HTTP timeout, request budget, default thresholds and sensitivity profiles. Every value is overridable by environment variable.

Infrastructure sensitivity

Shifts individual hazards up or down for devices in a given LibreNMS device group. Ships empty, so nothing changes until you opt in.

Profiles reference device groups by numeric id, never by name:

Find your group ids with:

Offsets shift the hazard on the 0–5 scale and are clamped at both ends. When a device belongs to several profiled groups the largest offset wins — erring toward showing more risk, never less.


7. The risk algorithm

Fully documented in the class docblock of src/Services/WeatherRiskService.php. In summary:

1 — Calculated risk. Every forecast hour in the window is scored against configurable thresholds per hazard. The result is the worst hour and the time it occurs. Wind scores sustained speed and gusts on separate scales, because a 25 m/s gust in a 12 m/s wind is a different engineering problem from steady 25 m/s.

2 — Official warning risk. Warnings whose polygon contains the device, and whose validity overlaps the window, contribute their published severity: yellow → Moderate, orange → High, red → Severe.

3 — Combination.

Official warnings raise but never lower a calculated risk — a genuinely dangerous local value is not suppressed just because no warning was issued. When calculated risk wins, the assessment is still flagged official so the operator sees a warning exists.

4 — Sensitivity. Device-group offsets applied.

5 — Escalation. Two or more hazards at Severe promote the device to Extreme 🟣. Compound events are what actually take sites off the air.

Default thresholds

All overridable per widget.

Hazard 🟡 Moderate 🟠 High 🔴 Severe
Wind, sustained (m/s) 12 18 25
Wind gusts (m/s) 17 24 32
Rain (mm/h) 4 8 15
Rain, accumulated (mm) 20 40 70
Snow (mm water eq.) 5 12 25
Thunder probability (%) 15 40 70
Heat (°C, at or above) 30 35 40
Cold (°C, at or below) −10 −20 −30

Icing is derived from the physical precondition — precipitation while air temperature sits in the −6 °C … +1 °C band — and is flagged inferred.


8. Map and UI behaviour


9. Testing

Automated

The package keeps its own vendor/, so the suite is unaffected when a LibreNMS update strips core's dev dependencies:

Expected: OK (110 tests, 264 assertions).

The suite is pure — no database, no Laravel application, no network — so it runs anywhere PHP 8.2+ is available. vendor/bin/pint --test checks style.

[!NOTE] composer is usually not on PATH on a LibreNMS host, and scripts/composer_wrapper.php always chdirs to /opt/librenms, so it cannot be used for this package. Invoke composer.phar directly as above.

Coverage against the specification's test matrix | Area | Covered by | | --- | --- | | Valid / missing / invalid / duplicate coordinates, `0,0`, out-of-range, NaN | `CoordinateTest` | | Polygon containment, holes, concave shapes, MultiPolygon, malformed geometry, simplification | `PolygonTest`, `WeatherGeoServiceTest` | | No warnings / yellow / orange / red / multiple simultaneous | `WeatherRiskServiceTest`, `MetNorwayParsingTest` | | `max(calculated, official)` in both directions | `WeatherRiskServiceTest` | | Thresholds, gusts, peak-hour selection, null ≠ zero | `WeatherRiskServiceTest` | | Sensitivity offsets, positive and negative | `WeatherRiskServiceTest` | | Device grouping, 1000 devices → few cells | `WeatherGeoServiceTest` | | Malformed response, missing fields, unparseable times | `MetNorwayParsingTest` | | Cached fallback, provider throw, provider null, failure backoff | `WeatherCacheServiceTest` | | Settings validation, XSS in title, injection in group ids, range clamping | `WidgetSettingsTest` |

Static and syntax checks

Run on the LibreNMS host, where PHP is available:

Manual NOC checks

# Check Expected
1 php artisan weather-risk-map:diagnose Forecast OK, warning count reported
2 Block api.met.no at the firewall, refresh Devices still shown + "cached data N minutes old" badge — never an empty widget or a Laravel error page
3 Set WEATHER_RISK_MAP_TIMEOUT=1 Widget degrades, does not hang
4 Hit the data endpoint > 60×/min Throttled message, not a stack trace
5 Take a device down Keeps its weather colour, gains the dark border
6 Set a device-group filter Only that group's members appear
7 Toggle light / dark theme Popups, table, controls, polygons, overlays all legible
8 Resize widget and browser Map calls invalidateSize() via the resize event
9 Zoom out Cluster colour reflects its worst member
10 Hundreds of devices cells in the footer stays small relative to device count

10. Troubleshooting

Logs go to storage/logs/weather-risk-map.log — a separate channel, so weather noise stays out of the main LibreNMS log.

Symptom Likely cause Fix
"Problem with backend" in the widget tile Core's generic AJAX failure. Usually the package is not installed, so the route 404s php artisan route:list --path=ajax/dash \| grep weather. If absent, reinstall — see §5
Widget vanished after a LibreNMS update daily.sh reverted composer.json and dropped the plugin Reinstall, then apply one of the three mitigations in §5
Widget missing from Add Widget Route not registered php artisan route:clear, then php artisan route:list --path=ajax/dash — weather-risk-map must appear
Errors appear nowhere in laravel.log The default log stack references a flare driver removed by --update-no-dev Set LOG_CHANNEL=single in .env, then php artisan config:clear
"artisan must be run as the user librenms" Ran as root or your own account sudo su - librenms first. If caches were already written with wrong ownership: sudo chown -R librenms:librenms /opt/librenms/storage /opt/librenms/bootstrap/cache
"detected dubious ownership" on git pull Package directory not owned by the invoking user sudo chown -R librenms:librenms /opt/weather-risk-map-widget
Blade parse error after editing the view A doubled opening brace anywhere in the file — including inside a JavaScript comment — is compiled as a PHP echo Never write JSDoc brace-type annotations in .blade.php. Check with php artisan view:cache
"No devices with valid GPS coordinates" No lat/lng on locations Run weather-risk-map:diagnose; set coordinates or enable LibreNMS geolocation lookup
403 from MET Norway Placeholder User-Agent, or >4-decimal coordinates Set WEATHER_RISK_MAP_USER_AGENT to include a real contact email
429 from a provider Too many cells, TTL too short Increase the widget's radius, raise forecast_ttl, or lower max_cells_per_refresh
"Weather data temporarily unavailable" persists Provider unreachable from the server Check egress to api.met.no:443 — the widget is working as designed by showing cached data
Warnings never appear providers.warnings set to a provider without warnings, or devices outside Norway Set it to met-norway; check diagnose output
Polygons missing, warnings still listed Source published a warning without geometry Expected — such a warning cannot be matched to a device, so it is listed only
Map blank white/black Leaflet failed to load Check the browser console; confirm html/js/leaflet.js is served
Settings do not persist Dashboard not writable by this user Core requires update permission on the dashboard
Everything stale after a config edit Config cached php artisan config:clear

Raise verbosity temporarily with WEATHER_RISK_MAP_LOG_LEVEL=debug. Normal operation logs only aggregate lines — e.g. one "skipped N devices for unusable coordinates" per refresh — never one line per device.


11. Files created and modified

Modified: none

LibreNMS builds its widget catalogue in DashboardController::listWidgets() by scanning the route table for routes prefixed exactly ajax/dash — the widgets database table was dropped in 2022. Registering a route with that prefix from this package's own service provider is therefore enough to make Weather Risk Map appear in the Add Widget menu.

No core controller, view, route file, language file or migration is touched, so a LibreNMS upgrade cannot overwrite the feature.

Two details make it behave like a built-in widget rather than a bolted-on approximation:

Database changes: none

No migrations, no new tables, no new columns. Widget settings use LibreNMS's existing per-user users_widgets.settings JSON column; coordinates are read from the existing locations table. This package stores no device coordinates of its own.

Created

Full file inventory (37 files) #### Package root | File | Purpose | | --- | --- | | `composer.json` | Package definition, PSR-4, Laravel provider discovery | | `phpunit.xml` | Test configuration | | `README.md` | This document | | `config/weather-risk-map.php` | Installation defaults: providers, User-Agent, TTLs, thresholds, sensitivity | | `routes/web.php` | Widget route (`ajax/dash` prefix) + data endpoint | | `lang/en/widget.php` | All user-facing strings | #### Domain | File | Purpose | | --- | --- | | `src/WeatherRiskMapServiceProvider.php` | Registration, log channel, bindings | | `src/Contracts/WeatherProviderInterface.php` | Provider contract | | `src/Enums/RiskLevel.php` | 0–5 risk scale, colours, labels | | `src/Enums/HazardType.php` | Hazard classes and ISP impact notes | | `src/DTO/Coordinate.php` | Validated WGS84 coordinate — the single place validity is decided | | `src/DTO/ForecastPoint.php` | One forecast hour | | `src/DTO/Forecast.php` | Time series + windowing | | `src/DTO/WeatherWarning.php` | Official warning + geometry | | `src/DTO/HazardAssessment.php` | Peak of one hazard, official/inferred flags | | `src/DTO/WidgetSettings.php` | Validation and normalisation of untrusted widget settings | | `src/Support/Polygon.php` | Ray-casting point-in-polygon, bbox fast path, holes, simplification | | `src/Support/GeoMath.php` | Haversine distance, degree/km conversion | #### Providers and services | File | Purpose | | --- | --- | | `src/Providers/MetNorwayWeatherProvider.php` | MET Norway forecast + MetAlerts | | `src/Providers/OpenMeteoWeatherProvider.php` | Open-Meteo batched forecast | | `src/Services/WeatherCacheService.php` | Two-tier cache, stale fallback, failure backoff | | `src/Services/WeatherGeoService.php` | Cell grouping, warning matching, bounds | | `src/Services/WeatherRiskService.php` | **The documented risk algorithm** | | `src/Services/SensitivityProfileService.php` | Per-device-group hazard offsets | | `src/Services/DeviceLocationService.php` | Device + coordinate retrieval (no N+1) | | `src/Services/WeatherRiskMapBuilder.php` | Orchestration, degradation handling | | `src/Services/WeatherRiskMapFactory.php` | Per-widget service wiring | #### HTTP, console and views | File | Purpose | | --- | --- | | `src/Http/Controllers/WeatherRiskMapWidgetController.php` | The widget (extends core `WidgetController`) | | `src/Http/Controllers/WeatherRiskDataController.php` | Async data endpoint | | `src/Console/DiagnoseCommand.php` | End-to-end health check | | `src/Console/WarmCacheCommand.php` | Optional cache pre-warming | | `resources/views/widgets/weather-risk-map.blade.php` | Map, summary header, risk table, dark-mode CSS | | `resources/views/widgets/settings/weather-risk-map.blade.php` | Settings panel | #### Tests | File | Purpose | | --- | --- | | `tests/Support/ArrayCacheStub.php` | In-memory cache for unit tests | | `tests/Unit/CoordinateTest.php` | Coordinate validation | | `tests/Unit/PolygonTest.php` | Point-in-polygon geometry | | `tests/Unit/WeatherGeoServiceTest.php` | Cell grouping, warning matching, bounds | | `tests/Unit/WeatherRiskServiceTest.php` | The risk algorithm | | `tests/Unit/WeatherCacheServiceTest.php` | Degradation and fallback | | `tests/Unit/MetNorwayParsingTest.php` | Provider response parsing | | `tests/Unit/WidgetSettingsTest.php` | Settings validation and sanitisation |

12. Known limitations

  1. Lightning is risk, not strikes. No free public API provides real-time strike data. Labelled as such everywhere it appears.
  2. Official warnings are Norway-only. MetAlerts covers Norway and its waters. Devices elsewhere still get forecast-based calculated risk — MET's forecast model is global. There is no equivalent single-request pan-European warning feed with polygons.
  3. Icing and snow are inferred from temperature, precipitation and symbol codes rather than a dedicated icing product. Flagged inferred.
  4. Snow amounts are water-equivalent millimetres, not snow depth — that is what the providers publish.
  5. No antimeridian handling in point-in-polygon. MET Norway issues no warnings crossing 180°; the failure mode would be a missed match, never a false one.
  6. Warning polygons are simplified to ~0.01° for transmission. Device matching always uses full-resolution geometry server-side; only the drawn outline is thinned.
  7. The per-refresh cell budget means a pathological inventory (thousands of distinct sites at 1 km radius) will show some devices from cached rather than current data. The footer reports cell count, so this is visible.
  8. Sensitivity is a flat offset table, not a rules engine — by design for v1. SensitivityProfileService::adjust() is the seam where a richer engine slots in.
  9. Cluster "worst member" derives from zIndexOffset. Compact, but it couples two concerns; a dedicated marker option would be cleaner if the marker code grows.
  10. A LibreNMS core update uninstalls the plugin unless mitigated — daily.sh reverts composer.json, destroying the path repository. See §5. Publishing to a Composer repository is the only fix that needs no ongoing maintenance.

13. Future improvements

The architecture was chosen so none of these require a rewrite:

Feature What it needs
Lightning strike overlay Add getStrikes() to WeatherProviderInterface + a map layer. The risk engine already distinguishes detected from inferred via HazardAssessment::$inferred.
Weather radar overlay A Leaflet tile layer; mapConfig already flows from controller to view.
Historical correlation The payload is already keyed by device_id and timestamped. Joining against eventlog / alert_log for "8 network incidents occurred during this storm" needs no data-layer change.
Predictive risk WeatherRiskService::assess() returns structured HazardAssessment objects rather than strings — the shape a scoring model would consume.
Additional providers Implement WeatherProviderInterface, add one match arm in WeatherRiskMapFactory::makeProvider(). Nothing else changes.
Per-hazard sensitivity in the UI Move the config-file profiles into the settings panel.
Acknowledged risk Persist a mute flag so a NOC can silence a known-exposed site.

14. Verification status

The unit suite has been run on the target host and passes:

The widget is confirmed rendering in a live LibreNMS dashboard.

What was authored without a local runtime, and is therefore covered only by the run above plus manual checking:

Still not exercised: §9's manual NOC checks — provider failure and cached fallback, timeout, rate limiting, and the light/dark and clustering passes. Run those before relying on the widget operationally.


Attribution

Weather data from MET Norway and Open-Meteo, both licensed CC BY 4.0. Attribution is rendered in the widget footer at runtime, as their licences require.


All versions of librenms-weather-risk-map-widget with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
ext-json Version *
illuminate/contracts Version ^12.10
illuminate/support Version ^12.10
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package drakelid/librenms-weather-risk-map-widget contains the following files

Loading the files please wait ...