fix(settings): stale env vars survived bridge restart, reverting saved changes
_restart_bridge() cleared a hardcoded, manually-maintained list of env keys before restarting — every setting added since (vibration_compensation, host_ip, poll_interval, verbose_http_log) was missing from it. The old process's env var therefore survived into the new process and silently overrode the freshly written config.ini value, making toggles appear to revert right after saving. Fixed at the root: config_loader.CONFIG_ENV_MAPPING is now the single source of truth for which env keys back which config.ini options, and _restart_bridge() derives its cleanup list from it. A newly added setting can't be forgotten here again.
This commit is contained in:
@@ -47,32 +47,39 @@ def _load_env_file(path: pathlib.Path):
|
||||
os.environ[key] = val
|
||||
|
||||
|
||||
# Single source of truth for env-var <-> config.ini mapping. _restart_bridge()
|
||||
# in kobrax_moonraker_bridge.py clears exactly these keys from os.environ
|
||||
# before restarting, so a value removed here or in the UI settings save can
|
||||
# never survive as a stale env var read by the new process. Add new settings
|
||||
# here ONLY - no second list to keep in sync.
|
||||
CONFIG_ENV_MAPPING = {
|
||||
"PRINTER_IP": (CONFIG_SECTION_CONNECTION, "printer_ip"),
|
||||
"MQTT_PORT": (CONFIG_SECTION_CONNECTION, "mqtt_port"),
|
||||
"MQTT_USERNAME": (CONFIG_SECTION_CONNECTION, "username"),
|
||||
"MQTT_PASSWORD": (CONFIG_SECTION_CONNECTION, "password"),
|
||||
"MODE_ID": (CONFIG_SECTION_CONNECTION, "mode_id"),
|
||||
"DEVICE_ID": (CONFIG_SECTION_CONNECTION, "device_id"),
|
||||
"DEFAULT_AMS_SLOT": (CONFIG_SECTION_PRINT, "default_ams_slot"),
|
||||
"AUTO_LEVELING": (CONFIG_SECTION_PRINT, "auto_leveling"),
|
||||
"VIBRATION_COMPENSATION": (CONFIG_SECTION_PRINT, "vibration_compensation"),
|
||||
"CAMERA_ON_PRINT": (CONFIG_SECTION_PRINT, "camera_on_print"),
|
||||
"WEB_UPLOAD_WARNING": (CONFIG_SECTION_PRINT, "web_upload_warning"),
|
||||
"PRINT_START_DIALOG": (CONFIG_SECTION_PRINT, "print_start_dialog"),
|
||||
"BRIDGE_PRINTER_NAME": (CONFIG_SECTION_BRIDGE, "printer_name"),
|
||||
"BRIDGE_HOST_IP": (CONFIG_SECTION_BRIDGE, "host_ip"),
|
||||
"POLL_INTERVAL": (CONFIG_SECTION_BRIDGE, "poll_interval"),
|
||||
"VERBOSE_HTTP_LOG": (CONFIG_SECTION_BRIDGE, "verbose_http_log"),
|
||||
"SPOOLMAN_SERVER": (CONFIG_SECTION_SPOOLMAN, "server"),
|
||||
"SPOOLMAN_SYNC_RATE": (CONFIG_SECTION_SPOOLMAN, "sync_rate"),
|
||||
}
|
||||
|
||||
|
||||
def _load_config_file(path: pathlib.Path):
|
||||
"""Loads config.ini and sets keys in os.environ (only if not already set)."""
|
||||
cfg = configparser.ConfigParser()
|
||||
cfg.read(path, encoding="utf-8")
|
||||
|
||||
mapping = {
|
||||
"PRINTER_IP": (CONFIG_SECTION_CONNECTION, "printer_ip"),
|
||||
"MQTT_PORT": (CONFIG_SECTION_CONNECTION, "mqtt_port"),
|
||||
"MQTT_USERNAME": (CONFIG_SECTION_CONNECTION, "username"),
|
||||
"MQTT_PASSWORD": (CONFIG_SECTION_CONNECTION, "password"),
|
||||
"MODE_ID": (CONFIG_SECTION_CONNECTION, "mode_id"),
|
||||
"DEVICE_ID": (CONFIG_SECTION_CONNECTION, "device_id"),
|
||||
"DEFAULT_AMS_SLOT": (CONFIG_SECTION_PRINT, "default_ams_slot"),
|
||||
"AUTO_LEVELING": (CONFIG_SECTION_PRINT, "auto_leveling"),
|
||||
"VIBRATION_COMPENSATION": (CONFIG_SECTION_PRINT, "vibration_compensation"),
|
||||
"CAMERA_ON_PRINT": (CONFIG_SECTION_PRINT, "camera_on_print"),
|
||||
"WEB_UPLOAD_WARNING": (CONFIG_SECTION_PRINT, "web_upload_warning"),
|
||||
"PRINT_START_DIALOG": (CONFIG_SECTION_PRINT, "print_start_dialog"),
|
||||
"BRIDGE_PRINTER_NAME": (CONFIG_SECTION_BRIDGE, "printer_name"),
|
||||
"BRIDGE_HOST_IP": (CONFIG_SECTION_BRIDGE, "host_ip"),
|
||||
"POLL_INTERVAL": (CONFIG_SECTION_BRIDGE, "poll_interval"),
|
||||
"VERBOSE_HTTP_LOG": (CONFIG_SECTION_BRIDGE, "verbose_http_log"),
|
||||
"SPOOLMAN_SERVER": (CONFIG_SECTION_SPOOLMAN, "server"),
|
||||
"SPOOLMAN_SYNC_RATE": (CONFIG_SECTION_SPOOLMAN, "sync_rate"),
|
||||
}
|
||||
for env_key, (section, option) in mapping.items():
|
||||
for env_key, (section, option) in CONFIG_ENV_MAPPING.items():
|
||||
if env_key not in os.environ:
|
||||
try:
|
||||
val = cfg.get(section, option)
|
||||
|
||||
@@ -4644,12 +4644,15 @@ class KobraXBridge:
|
||||
log.info("Restarting bridge...")
|
||||
# config_loader caches config.ini values in os.environ ("only if not set").
|
||||
# On restart, environ must be cleaned, otherwise the new process reads
|
||||
# the old values instead of the modified config.ini.
|
||||
for _k in ("PRINTER_IP", "MQTT_PORT", "MQTT_USERNAME", "MQTT_PASSWORD",
|
||||
"MODE_ID", "DEVICE_ID", "DEFAULT_AMS_SLOT", "AUTO_LEVELING",
|
||||
"CAMERA_ON_PRINT", "WEB_UPLOAD_WARNING", "PRINT_START_DIALOG",
|
||||
"FILE_READY_DIALOG", "BRIDGE_PRINTER_NAME",
|
||||
"SPOOLMAN_SERVER", "SPOOLMAN_SYNC_RATE"):
|
||||
# the old values instead of the modified config.ini. Keys are derived
|
||||
# from config_loader.CONFIG_ENV_MAPPING (single source of truth) so a
|
||||
# newly added setting can never be forgotten here again.
|
||||
try:
|
||||
import config_loader as _cl
|
||||
_restart_env_keys = set(_cl.CONFIG_ENV_MAPPING.keys()) | {"FILE_READY_DIALOG"}
|
||||
except Exception:
|
||||
_restart_env_keys = ()
|
||||
for _k in _restart_env_keys:
|
||||
os.environ.pop(_k, None)
|
||||
|
||||
in_docker = os.path.exists("/.dockerenv") or os.environ.get("KX_IN_DOCKER")
|
||||
|
||||
Reference in New Issue
Block a user