From 7fad9de331b41e62e8246a97e2e6f6eb52c16d5a Mon Sep 17 00:00:00 2001 From: Ben Allfree Date: Sun, 30 Nov 2025 15:18:00 -0800 Subject: [PATCH] chore: update firmware patch --- firmware-patch.diff | 114 ++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/firmware-patch.diff b/firmware-patch.diff index cca5853..c47e301 100644 --- a/firmware-patch.diff +++ b/firmware-patch.diff @@ -17,10 +17,10 @@ index cc742c6c1..545b0923a 100644 \ No newline at end of file diff --git a/bin/mpm_pio.py b/bin/mpm_pio.py new file mode 100644 -index 000000000..486e7c1cc +index 000000000..bbb251eff --- /dev/null +++ b/bin/mpm_pio.py -@@ -0,0 +1,74 @@ +@@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +""" +Mesh Plugin Manager (MPM) - PlatformIO build integration shim. @@ -37,55 +37,85 @@ index 000000000..486e7c1cc +# Provided by PlatformIO/SCons when used as `pre:` extra_script +Import("env") # type: ignore[name-defined] # noqa: F821 + ++ ++def find_site_packages(venv_dir): ++ """Find site-packages directory in a venv (handles different Python versions).""" ++ if not os.path.isdir(venv_dir): ++ return None ++ lib_dir = os.path.join(venv_dir, "lib") ++ if not os.path.isdir(lib_dir): ++ return None ++ pattern = os.path.join(lib_dir, "python*/site-packages") ++ matches = glob.glob(pattern) ++ return matches[0] if matches else None ++ ++ ++def add_to_path(directory, env_var="PATH", label=""): ++ """Add directory to environment variable if it exists and isn't already present.""" ++ if not directory or not os.path.isdir(directory): ++ return False ++ current = os.environ.get(env_var, "") ++ if directory not in current: ++ os.environ[env_var] = f"{directory}:{current}" if current else directory ++ print(f"MPM: Added {label or directory} to {env_var}") ++ return True ++ return False ++ ++ ++def add_to_sys_path(directory, label=""): ++ """Add directory to sys.path if it exists and isn't already present.""" ++ if not directory or not os.path.isdir(directory): ++ return False ++ if directory not in sys.path: ++ sys.path.insert(0, directory) ++ print(f"MPM: Added {directory} to sys.path") ++ return True ++ return False ++ ++ +# Find Poetry's .venv directory using PROJECT_DIR from PlatformIO env +# (__file__ is not available when exec'd by SCons) +project_dir = env["PROJECT_DIR"] # type: ignore[name-defined] # noqa: F821 -+_venv_dir = os.path.join(project_dir, ".venv") ++print(f"MPM DEBUG: project_dir = {project_dir}") + -+# Add .venv site-packages to sys.path -+_site_packages_dirs = [] -+if os.path.isdir(_venv_dir): -+ # Find site-packages directory (handles different Python versions) -+ _lib_dir = os.path.join(_venv_dir, "lib") -+ if os.path.isdir(_lib_dir): -+ # Look for pythonX.Y/site-packages -+ _site_packages_pattern = os.path.join(_lib_dir, "python*/site-packages") -+ _site_packages_dirs = glob.glob(_site_packages_pattern) -+ if _site_packages_dirs: -+ _site_packages = _site_packages_dirs[0] -+ if _site_packages not in sys.path: -+ sys.path.insert(0, _site_packages) -+ print(f"MPM: Added {_site_packages} to sys.path") ++# First, try to find mpm source and mpm's .venv for local development ++# (mpm is at ../../mpm relative to firmware directory) ++mpm_dir = os.path.join(project_dir, "..", "mpm") ++mpm_dir = os.path.abspath(mpm_dir) # Resolve relative path ++mpm_source_dir = os.path.join(mpm_dir, "src") ++mpm_venv_dir = os.path.join(mpm_dir, ".venv") ++firmware_venv_dir = os.path.join(project_dir, ".venv") + -+ # Add .venv/bin to PATH so console scripts can be found -+ _venv_bin = os.path.join(_venv_dir, "bin") -+ if os.path.isdir(_venv_bin): -+ current_path = os.environ.get("PATH", "") -+ if _venv_bin not in current_path: -+ os.environ["PATH"] = f"{_venv_bin}:{current_path}" if current_path else _venv_bin -+ print(f"MPM: Added {_venv_bin} to PATH") ++print(f"MPM Directories:") ++print(f" mpm_dir: {mpm_dir}") ++print(f" mpm_source_dir: {mpm_source_dir}") ++print(f" mpm_venv_dir: {mpm_venv_dir}") ++print(f" firmware_venv_dir: {firmware_venv_dir}") + -+ # Add .venv site-packages to PYTHONPATH so subprocesses (like nanopb_generator) can find modules -+ if _site_packages_dirs: -+ _site_packages = _site_packages_dirs[0] -+ current_pythonpath = os.environ.get("PYTHONPATH", "") -+ if _site_packages not in current_pythonpath: -+ os.environ["PYTHONPATH"] = f"{_site_packages}:{current_pythonpath}" if current_pythonpath else _site_packages -+ print(f"MPM: Added {_site_packages} to PYTHONPATH") + -+ # Add nanopb/generator to PATH so nanopb generator executables can be found -+ if _site_packages_dirs: -+ _nanopb_generator = os.path.join(_site_packages_dirs[0], "nanopb", "generator") -+ if os.path.isdir(_nanopb_generator): -+ current_path = os.environ.get("PATH", "") -+ if _nanopb_generator not in current_path: -+ os.environ["PATH"] = f"{_nanopb_generator}:{current_path}" if current_path else _nanopb_generator -+ print(f"MPM: Added {_nanopb_generator} to PATH") ++mpm_site_packages = find_site_packages(mpm_venv_dir) ++firmware_site_packages = find_site_packages(firmware_venv_dir) ++ ++# These are in reverse order because they are prepended to sys.path ++add_to_sys_path(firmware_site_packages, "firmware .venv") # Look for this last ++add_to_sys_path(mpm_site_packages, "mpm .venv") # Look for this next ++add_to_sys_path(mpm_source_dir, "mpm source") # Look for this first ++ ++# Add .venv/bin to PATH (prioritize mpm's .venv) ++mpm_venv_bin = os.path.join(mpm_venv_dir, "bin") ++firmware_venv_bin = os.path.join(firmware_venv_dir, "bin") ++add_to_path(firmware_venv_bin, "PATH") ++add_to_path(mpm_venv_bin, "PATH") ++ ++for site_packages in [mpm_site_packages, firmware_site_packages]: ++ add_to_path(site_packages, "PYTHONPATH") ++ nanopb_generator = os.path.join(site_packages, "nanopb", "generator") ++ add_to_path(nanopb_generator, "PATH", "nanopb/generator") + +# Use the installed `mpm` package -+from mpm.build import init_plugins # type: ignore[import] -+from mpm.build_utils import scan_plugins # type: ignore[import] -+from mpm.proto import generate_all_protobuf_files # type: ignore[import] ++from mesh_plugin_manager.build import init_plugins # type: ignore[import] ++from mesh_plugin_manager.build_utils import scan_plugins # type: ignore[import] ++from mesh_plugin_manager.proto import generate_all_protobuf_files # type: ignore[import] + +# Auto-initialize when imported by PlatformIO (not when run as __main__) +if __name__ != "__main__":