mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-06-13 21:53:32 +00:00
Compare commits
3 Commits
baebe4f5f7
...
b7295129b5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7295129b5 | ||
|
|
3e94bb9664 | ||
|
|
44316d3bae |
@@ -1,4 +1,4 @@
|
||||
requests>=2.28.0
|
||||
Pillow>=9.1.0
|
||||
Pillow>=10.2.0
|
||||
pytz>=2022.1
|
||||
numpy>=1.24.0
|
||||
|
||||
@@ -132,7 +132,7 @@ class WiFiMonitorDaemon:
|
||||
# AP-enable trigger clean and avoid false-positive AP enables from
|
||||
# transient packet loss on otherwise working WiFi.
|
||||
if updated_status.connected and not updated_status.ap_mode_active:
|
||||
if not self.wifi_manager._check_internet_connectivity():
|
||||
if not self.wifi_manager.check_internet_connectivity():
|
||||
self._consecutive_internet_failures += 1
|
||||
logger.warning(
|
||||
f"Internet unreachable despite nmcli connection "
|
||||
@@ -140,10 +140,18 @@ class WiFiMonitorDaemon:
|
||||
)
|
||||
if self._consecutive_internet_failures >= self._nm_restart_threshold:
|
||||
logger.warning("Restarting NetworkManager to recover internet connectivity")
|
||||
import subprocess as _sp
|
||||
_sp.run(["sudo", "systemctl", "restart", "NetworkManager"],
|
||||
capture_output=True, timeout=20)
|
||||
self._consecutive_internet_failures = 0
|
||||
try:
|
||||
subprocess.run(
|
||||
["/usr/bin/systemctl", "restart", "NetworkManager"],
|
||||
capture_output=True, timeout=20, check=True
|
||||
)
|
||||
self._consecutive_internet_failures = 0
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"NetworkManager restart failed (rc={e.returncode}); "
|
||||
"keeping failure counter unchanged")
|
||||
except Exception as e:
|
||||
logger.error(f"NetworkManager restart error: {e}; "
|
||||
"keeping failure counter unchanged")
|
||||
else:
|
||||
self._consecutive_internet_failures = 0
|
||||
else:
|
||||
|
||||
@@ -948,6 +948,10 @@ class WiFiManager:
|
||||
logger.debug("Internet connectivity check failed (both ping and HTTP)")
|
||||
return False
|
||||
|
||||
def check_internet_connectivity(self, timeout: int = 5) -> bool:
|
||||
"""Public wrapper around _check_internet_connectivity for use by the daemon."""
|
||||
return self._check_internet_connectivity(timeout=timeout)
|
||||
|
||||
def _has_ap_clients(self) -> bool:
|
||||
"""
|
||||
Return True if at least one client is associated with the AP.
|
||||
|
||||
@@ -129,7 +129,15 @@ def test_nmcli_ap_profile_has_no_security_params(manager: WiFiManager) -> None:
|
||||
assert "psk" not in add_str, "AP profile must not include a PSK/password"
|
||||
assert "wpa" not in add_str.lower(), "AP profile must not reference WPA"
|
||||
assert "802-11-wireless.mode" in add_str, "AP profile must declare wireless mode"
|
||||
assert "ap" in add_calls[0], "Wireless mode value must be 'ap'"
|
||||
# Verify the value for 802-11-wireless.mode is exactly "ap" — check the element
|
||||
# that immediately follows the key in the command list, not a loose substring match.
|
||||
cmd = add_calls[0]
|
||||
try:
|
||||
mode_idx = cmd.index("802-11-wireless.mode")
|
||||
assert cmd[mode_idx + 1] == "ap", \
|
||||
f"802-11-wireless.mode value must be exactly 'ap', got {cmd[mode_idx + 1]!r}"
|
||||
except ValueError:
|
||||
pytest.fail("802-11-wireless.mode not found as a list element in nmcli command")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
||||
import json
|
||||
import logging
|
||||
from html import escape as html_escape
|
||||
from pathlib import Path
|
||||
from src.web_interface.secret_helpers import mask_secret_fields
|
||||
|
||||
@@ -354,7 +355,7 @@ def _load_plugin_config_partial(plugin_id):
|
||||
plugin_info = pages_v3.plugin_manager.get_plugin_info(plugin_id)
|
||||
|
||||
if not plugin_info:
|
||||
return f'<div class="text-red-500 p-4">Plugin "{plugin_id}" not found</div>', 404
|
||||
return f'<div class="text-red-500 p-4">Plugin "{html_escape(plugin_id)}" not found</div>', 404
|
||||
|
||||
# Get plugin instance (may be None if not loaded)
|
||||
plugin_instance = pages_v3.plugin_manager.get_plugin(plugin_id)
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
const xOptions = config['x-options'] || config['x_options'] || {};
|
||||
const requestedFormat = xOptions.format || 'long';
|
||||
// Validate format exists in DAY_LABELS, default to 'long' if not
|
||||
const format = DAY_LABELS.hasOwnProperty(requestedFormat) ? requestedFormat : 'long';
|
||||
const format = Object.prototype.hasOwnProperty.call(DAY_LABELS, requestedFormat) ? requestedFormat : 'long';
|
||||
const layout = xOptions.layout || 'horizontal';
|
||||
const showSelectAll = xOptions.selectAll !== false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user