diff --git a/pio-scripts/load_usermods.py b/pio-scripts/load_usermods.py index ab3c6476a6..146cb1f870 100644 --- a/pio-scripts/load_usermods.py +++ b/pio-scripts/load_usermods.py @@ -1,17 +1,14 @@ Import('env') -import os.path from collections import deque from pathlib import Path # For OS-agnostic path manipulation -from platformio.package.manager.library import LibraryPackageManager +from click import secho +from SCons.Script import Exit +from platformio.builder.tools.piolib import LibBuilderBase -usermod_dir = Path(env["PROJECT_DIR"]) / "usermods" -all_usermods = [f for f in usermod_dir.iterdir() if f.is_dir() and f.joinpath('library.json').exists()] +usermod_dir = Path(env["PROJECT_DIR"]).resolve() / "usermods" -if env['PIOENV'] == "usermods": - # Add all usermods - env.GetProjectConfig().set(f"env:usermods", 'custom_usermods', " ".join([f.name for f in all_usermods])) - -def find_usermod(mod: str): +# Utility functions +def find_usermod(mod: str) -> Path: """Locate this library in the usermods folder. We do this to avoid needing to rename a bunch of folders; this could be removed later @@ -22,51 +19,36 @@ def find_usermod(mod: str): return mp mp = usermod_dir / f"{mod}_v2" if mp.exists(): - return mp + return mp mp = usermod_dir / f"usermod_v2_{mod}" if mp.exists(): return mp raise RuntimeError(f"Couldn't locate module {mod} in usermods directory!") +def is_wled_module(dep: LibBuilderBase) -> bool: + """Returns true if the specified library is a wled module + """ + return usermod_dir in Path(dep.src_dir).parents or str(dep.name).startswith("wled-") + +## Script starts here +# Process usermod option usermods = env.GetProjectOption("custom_usermods","") + +# Handle "all usermods" case +if usermods == '*': + usermods = [f.name for f in usermod_dir.iterdir() if f.is_dir() and f.joinpath('library.json').exists()] +else: + usermods = usermods.split() + if usermods: # Inject usermods in to project lib_deps - proj = env.GetProjectConfig() - deps = env.GetProjectOption('lib_deps') - src_dir = proj.get("platformio", "src_dir") - src_dir = src_dir.replace('\\','/') - mod_paths = {mod: find_usermod(mod) for mod in usermods.split()} - usermods = [f"{mod} = symlink://{path}" for mod, path in mod_paths.items()] - proj.set("env:" + env['PIOENV'], 'lib_deps', deps + usermods) - # Force usermods to be installed in to the environment build state before the LDF runs - # Otherwise we won't be able to see them until it's too late to change their paths for LDF - # Logic is largely borrowed from PlaformIO internals - not_found_specs = [] - for spec in usermods: - found = False - for storage_dir in env.GetLibSourceDirs(): - #print(f"Checking {storage_dir} for {spec}") - lm = LibraryPackageManager(storage_dir) - if lm.get_package(spec): - #print("Found!") - found = True - break - if not found: - #print("Missing!") - not_found_specs.append(spec) - if not_found_specs: - lm = LibraryPackageManager( - env.subst(os.path.join("$PROJECT_LIBDEPS_DIR", "$PIOENV")) - ) - for spec in not_found_specs: - #print(f"LU: forcing install of {spec}") - lm.install(spec) - + symlinks = [f"symlink://{find_usermod(mod).resolve()}" for mod in usermods] + env.GetProjectConfig().set("env:" + env['PIOENV'], 'lib_deps', env.GetProjectOption('lib_deps') + symlinks) # Utility function for assembling usermod include paths def cached_add_includes(dep, dep_cache: set, includes: deque): """ Add dep's include paths to includes if it's not in the cache """ - if dep not in dep_cache: + if dep not in dep_cache: dep_cache.add(dep) for include in dep.get_include_dirs(): if include not in includes: @@ -82,13 +64,6 @@ def cached_add_includes(dep, dep_cache: set, includes: deque): # Our new wrapper def wrapped_ConfigureProjectLibBuilder(xenv): - # Update usermod properties - # Set libArchive before build actions are added - for um in (um for um in xenv.GetLibBuilders() if usermod_dir in Path(um.src_dir).parents): - build = um._manifest.get("build", {}) - build["libArchive"] = False - um._manifest["build"] = build - # Call the wrapped function result = old_ConfigureProjectLibBuilder.clone(xenv)() @@ -102,12 +77,25 @@ def wrapped_ConfigureProjectLibBuilder(xenv): for dep in result.depbuilders: cached_add_includes(dep, processed_deps, extra_include_dirs) - for um in [dep for dep in result.depbuilders if usermod_dir in Path(dep.src_dir).parents]: - # Add the wled folder to the include path - um.env.PrependUnique(CPPPATH=wled_dir) - # Add WLED's own dependencies - for dir in extra_include_dirs: - um.env.PrependUnique(CPPPATH=dir) + broken_usermods = [] + for dep in result.depbuilders: + if is_wled_module(dep): + # Add the wled folder to the include path + dep.env.PrependUnique(CPPPATH=str(wled_dir)) + # Add WLED's own dependencies + for dir in extra_include_dirs: + dep.env.PrependUnique(CPPPATH=str(dir)) + # Enforce that libArchive is not set; we must link them directly to the executable + if dep.lib_archive: + broken_usermods.append(dep) + + if broken_usermods: + broken_usermods = [usermod.name for usermod in broken_usermods] + secho( + f"ERROR: libArchive=false is missing on usermod(s) {' '.join(broken_usermods)} -- modules will not compile in correctly", + fg="red", + err=True) + Exit(1) return result diff --git a/pio-scripts/validate_modules.py b/pio-scripts/validate_modules.py new file mode 100644 index 0000000000..f8c9a599d9 --- /dev/null +++ b/pio-scripts/validate_modules.py @@ -0,0 +1,92 @@ +import re +from pathlib import Path # For OS-agnostic path manipulation +from typing import Iterable +from click import secho +from SCons.Script import Action, Exit +from platformio.builder.tools.piolib import LibBuilderBase + + +def is_wled_module(env, dep: LibBuilderBase) -> bool: + """Returns true if the specified library is a wled module + """ + usermod_dir = Path(env["PROJECT_DIR"]).resolve() / "usermods" + return usermod_dir in Path(dep.src_dir).parents or str(dep.name).startswith("wled-") + + +def read_lines(p: Path): + """ Read in the contents of a file for analysis """ + with p.open("r", encoding="utf-8", errors="ignore") as f: + return f.readlines() + + +def check_map_file_objects(map_file: list[str], dirs: Iterable[str]) -> set[str]: + """ Identify which dirs contributed to the final build + + Returns the (sub)set of dirs that are found in the output ELF + """ + # Pattern to match symbols in object directories + # Join directories into alternation + usermod_dir_regex = "|".join([re.escape(dir) for dir in dirs]) + # Matches nonzero address, any size, and any path in a matching directory + object_path_regex = re.compile(r"0x0*[1-9a-f][0-9a-f]*\s+0x[0-9a-f]+\s+\S+[/\\](" + usermod_dir_regex + r")[/\\]\S+\.o") + + found = set() + for line in map_file: + matches = object_path_regex.findall(line) + for m in matches: + found.add(m) + return found + + +def count_usermod_objects(map_file: list[str]) -> int: + """ Returns the number of usermod objects in the usermod list """ + # Count the number of entries in the usermods table section + return len([x for x in map_file if ".dtors.tbl.usermods.1" in x]) + + +def validate_map_file(source, target, env): + """ Validate that all modules appear in the output build """ + build_dir = Path(env.subst("$BUILD_DIR")) + map_file_path = build_dir / env.subst("${PROGNAME}.map") + + if not map_file_path.exists(): + secho(f"ERROR: Map file not found: {map_file_path}", fg="red", err=True) + Exit(1) + + # Identify the WLED module source directories + module_lib_builders = [builder for builder in env.GetLibBuilders() if is_wled_module(env, builder)] + + if env.GetProjectOption("custom_usermods","") == "*": + # All usermods build; filter non-platform-OK modules + module_lib_builders = [builder for builder in module_lib_builders if env.IsCompatibleLibBuilder(builder)] + else: + incompatible_builders = [builder for builder in module_lib_builders if not env.IsCompatibleLibBuilder(builder)] + if incompatible_builders: + secho( + f"ERROR: Modules {[b.name for b in incompatible_builders]} are not compatible with this platform!", + fg="red", + err=True) + Exit(1) + + # Extract the values we care about + modules = {Path(builder.build_dir).name: builder.name for builder in module_lib_builders} + secho(f"INFO: {len(modules)} libraries linked as WLED optional/user modules") + + # Now parse the map file + map_file_contents = read_lines(map_file_path) + usermod_object_count = count_usermod_objects(map_file_contents) + secho(f"INFO: {usermod_object_count} usermod object entries") + + confirmed_modules = check_map_file_objects(map_file_contents, modules.keys()) + missing_modules = [modname for mdir, modname in modules.items() if mdir not in confirmed_modules] + if missing_modules: + secho( + f"ERROR: No object files from {missing_modules} found in linked output!", + fg="red", + err=True) + Exit(1) + return None + +Import("env") +env.Append(LINKFLAGS=[env.subst("-Wl,--Map=${BUILD_DIR}/${PROGNAME}.map")]) +env.AddPostAction("$BUILD_DIR/${PROGNAME}.elf", Action(validate_map_file, cmdstr='Checking linked optional modules (usermods) in map file')) diff --git a/platformio.ini b/platformio.ini index a7485244cd..9bdf58d341 100644 --- a/platformio.ini +++ b/platformio.ini @@ -116,6 +116,7 @@ extra_scripts = pre:pio-scripts/user_config_copy.py pre:pio-scripts/load_usermods.py pre:pio-scripts/build_ui.py + post:pio-scripts/validate_modules.py ;; double-check the build output usermods ; post:pio-scripts/obj-dump.py ;; convenience script to create a disassembly dump of the firmware (hardcore debugging) # ------------------------------------------------------------------------------ @@ -659,5 +660,5 @@ build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_ lib_deps = ${esp32_idf_V4.lib_deps} monitor_filters = esp32_exception_decoder board_build.flash_mode = dio -; custom_usermods = *every folder with library.json* -- injected by pio-scripts/load_usermods.py +custom_usermods = * ; Expands to all usermods in usermods folder board_build.partitions = ${esp32.extreme_partitions} ; We're gonna need a bigger boat diff --git a/usermods/ADS1115_v2/library.json b/usermods/ADS1115_v2/library.json index 9f0c021ce4..5e5d7e450a 100644 --- a/usermods/ADS1115_v2/library.json +++ b/usermods/ADS1115_v2/library.json @@ -1,5 +1,6 @@ { "name": "ADS1115_v2", + "build": { "libArchive": false }, "dependencies": { "Adafruit BusIO": "https://github.com/adafruit/Adafruit_BusIO#1.13.2", "Adafruit ADS1X15": "https://github.com/adafruit/Adafruit_ADS1X15#2.4.0" diff --git a/usermods/AHT10_v2/library.json b/usermods/AHT10_v2/library.json index 54f8c1715d..fa6c2a6fee 100644 --- a/usermods/AHT10_v2/library.json +++ b/usermods/AHT10_v2/library.json @@ -1,5 +1,6 @@ { "name": "AHT10_v2", + "build": { "libArchive": false }, "dependencies": { "enjoyneering/AHT10":"~1.1.0" } diff --git a/usermods/Analog_Clock/library.json b/usermods/Analog_Clock/library.json index 3ed596dc79..f76cf42681 100644 --- a/usermods/Analog_Clock/library.json +++ b/usermods/Analog_Clock/library.json @@ -1,3 +1,4 @@ { - "name": "Analog_Clock" + "name": "Analog_Clock", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/Animated_Staircase/library.json b/usermods/Animated_Staircase/library.json index a2c50ea4c1..015b15cef5 100644 --- a/usermods/Animated_Staircase/library.json +++ b/usermods/Animated_Staircase/library.json @@ -1,3 +1,4 @@ { - "name": "Animated_Staircase" + "name": "Animated_Staircase", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/BH1750_v2/library.json b/usermods/BH1750_v2/library.json index 13740e6c92..4e32099b0c 100644 --- a/usermods/BH1750_v2/library.json +++ b/usermods/BH1750_v2/library.json @@ -1,5 +1,6 @@ { "name": "BH1750_v2", + "build": { "libArchive": false }, "dependencies": { "claws/BH1750":"^1.2.0" } diff --git a/usermods/BME280_v2/library.json b/usermods/BME280_v2/library.json index 626fb8b2bc..cfdfe1ba1a 100644 --- a/usermods/BME280_v2/library.json +++ b/usermods/BME280_v2/library.json @@ -1,5 +1,6 @@ { "name": "BME280_v2", + "build": { "libArchive": false }, "dependencies": { "finitespace/BME280":"~3.0.0" } diff --git a/usermods/BME68X_v2/library.json b/usermods/BME68X_v2/library.json index 2f1e1a310f..b315aa5d4b 100644 --- a/usermods/BME68X_v2/library.json +++ b/usermods/BME68X_v2/library.json @@ -1,5 +1,6 @@ { "name": "BME68X", + "build": { "libArchive": false }, "dependencies": { "boschsensortec/BSEC Software Library":"^1.8.1492" } diff --git a/usermods/Battery/library.json b/usermods/Battery/library.json index d6b8ad38a9..8e71c60a77 100644 --- a/usermods/Battery/library.json +++ b/usermods/Battery/library.json @@ -1,3 +1,4 @@ { - "name": "Battery" + "name": "Battery", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/Cronixie/library.json b/usermods/Cronixie/library.json index a1454a79a7..4a1b6988e2 100644 --- a/usermods/Cronixie/library.json +++ b/usermods/Cronixie/library.json @@ -1,3 +1,4 @@ { - "name": "Cronixie" + "name": "Cronixie", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/EXAMPLE/library.json b/usermods/EXAMPLE/library.json index dd8a7e5dd4..d0dc2f88e6 100644 --- a/usermods/EXAMPLE/library.json +++ b/usermods/EXAMPLE/library.json @@ -1,4 +1,5 @@ { "name": "EXAMPLE", + "build": { "libArchive": false }, "dependencies": {} } diff --git a/usermods/EleksTube_IPS/library.json.disabled b/usermods/EleksTube_IPS/library.json.disabled index eddd12b88e..d143638e47 100644 --- a/usermods/EleksTube_IPS/library.json.disabled +++ b/usermods/EleksTube_IPS/library.json.disabled @@ -1,5 +1,6 @@ { "name:": "EleksTube_IPS", + "build": { "libArchive": false }, "dependencies": { "TFT_eSPI" : "2.5.33" } diff --git a/usermods/INA226_v2/library.json b/usermods/INA226_v2/library.json index ab6c81fbde..34fcd36830 100644 --- a/usermods/INA226_v2/library.json +++ b/usermods/INA226_v2/library.json @@ -1,5 +1,6 @@ { "name": "INA226_v2", + "build": { "libArchive": false }, "dependencies": { "wollewald/INA226_WE":"~1.2.9" } diff --git a/usermods/Internal_Temperature_v2/library.json b/usermods/Internal_Temperature_v2/library.json index 571176f452..b1826ab458 100644 --- a/usermods/Internal_Temperature_v2/library.json +++ b/usermods/Internal_Temperature_v2/library.json @@ -1,3 +1,4 @@ { - "name": "Internal_Temperature_v2" + "name": "Internal_Temperature_v2", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/LD2410_v2/library.json b/usermods/LD2410_v2/library.json index 92ad54da72..757ec40477 100644 --- a/usermods/LD2410_v2/library.json +++ b/usermods/LD2410_v2/library.json @@ -1,5 +1,6 @@ { "name": "LD2410_v2", + "build": { "libArchive": false }, "dependencies": { "ncmreynolds/ld2410":"^0.1.3" } diff --git a/usermods/LDR_Dusk_Dawn_v2/library.json b/usermods/LDR_Dusk_Dawn_v2/library.json index be06c3a3a0..709967ea70 100644 --- a/usermods/LDR_Dusk_Dawn_v2/library.json +++ b/usermods/LDR_Dusk_Dawn_v2/library.json @@ -1,3 +1,4 @@ { - "name": "LDR_Dusk_Dawn_v2" + "name": "LDR_Dusk_Dawn_v2", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/MY9291/library.json b/usermods/MY9291/library.json index e4c63eaf50..9c3a33d43e 100644 --- a/usermods/MY9291/library.json +++ b/usermods/MY9291/library.json @@ -1,4 +1,5 @@ { "name": "MY9291", + "build": { "libArchive": false }, "platforms": ["espressif8266"] } \ No newline at end of file diff --git a/usermods/PIR_sensor_switch/library.json b/usermods/PIR_sensor_switch/library.json index d5ebb7689c..b3cbcbbff6 100644 --- a/usermods/PIR_sensor_switch/library.json +++ b/usermods/PIR_sensor_switch/library.json @@ -1,3 +1,4 @@ { - "name": "PIR_sensor_switch" + "name": "PIR_sensor_switch", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/PWM_fan/library.json b/usermods/PWM_fan/library.json index a8f7a94461..8ae3d7fd6e 100644 --- a/usermods/PWM_fan/library.json +++ b/usermods/PWM_fan/library.json @@ -1,6 +1,7 @@ { "name": "PWM_fan", "build": { + "libArchive": false, "extraScript": "setup_deps.py" } } \ No newline at end of file diff --git a/usermods/PWM_fan/setup_deps.py b/usermods/PWM_fan/setup_deps.py index b8f7276c5d..11879079a6 100644 --- a/usermods/PWM_fan/setup_deps.py +++ b/usermods/PWM_fan/setup_deps.py @@ -1,11 +1,12 @@ +from platformio.package.meta import PackageSpec Import('env') -usermods = env.GetProjectOption("custom_usermods","").split() +libs = [PackageSpec(lib).name for lib in env.GetProjectOption("lib_deps",[])] # Check for dependencies -if "Temperature" in usermods: +if "Temperature" in libs: env.Append(CPPDEFINES=[("USERMOD_DALLASTEMPERATURE")]) -elif "sht" in usermods: +elif "sht" in libs: env.Append(CPPDEFINES=[("USERMOD_SHT")]) -elif "PWM_fan" in usermods: # The script can be run if this module was previously selected +elif "PWM_fan" in libs: # The script can be run if this module was previously selected raise RuntimeError("PWM_fan usermod requires Temperature or sht to be enabled") diff --git a/usermods/RTC/library.json b/usermods/RTC/library.json index 8c103e06d5..688dfc2d0c 100644 --- a/usermods/RTC/library.json +++ b/usermods/RTC/library.json @@ -1,3 +1,4 @@ { - "name": "RTC" + "name": "RTC", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/SN_Photoresistor/library.json b/usermods/SN_Photoresistor/library.json index 45519dfa63..c896644f71 100644 --- a/usermods/SN_Photoresistor/library.json +++ b/usermods/SN_Photoresistor/library.json @@ -1,3 +1,4 @@ { - "name": "SN_Photoresistor" + "name": "SN_Photoresistor", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/ST7789_display/library.json.disabled b/usermods/ST7789_display/library.json.disabled index abcd4635c3..725e20a65a 100644 --- a/usermods/ST7789_display/library.json.disabled +++ b/usermods/ST7789_display/library.json.disabled @@ -1,3 +1,4 @@ { - "name:": "ST7789_display" + "name:": "ST7789_display", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/Si7021_MQTT_HA/library.json b/usermods/Si7021_MQTT_HA/library.json index cec2edfb10..e3d7635e35 100644 --- a/usermods/Si7021_MQTT_HA/library.json +++ b/usermods/Si7021_MQTT_HA/library.json @@ -1,5 +1,6 @@ { "name": "Si7021_MQTT_HA", + "build": { "libArchive": false }, "dependencies": { "finitespace/BME280":"3.0.0", "adafruit/Adafruit Si7021 Library" : "1.5.3" diff --git a/usermods/TetrisAI_v2/library.json b/usermods/TetrisAI_v2/library.json index bfff1aa4d4..54aa22d35b 100644 --- a/usermods/TetrisAI_v2/library.json +++ b/usermods/TetrisAI_v2/library.json @@ -1,3 +1,4 @@ { - "name": "TetrisAI_v2" + "name": "TetrisAI_v2", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/boblight/library.json b/usermods/boblight/library.json index 12debccf55..b54fb35058 100644 --- a/usermods/boblight/library.json +++ b/usermods/boblight/library.json @@ -1,3 +1,4 @@ { - "name": "boblight" + "name": "boblight", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/buzzer/library.json b/usermods/buzzer/library.json index c6af3158b2..0dbb547e34 100644 --- a/usermods/buzzer/library.json +++ b/usermods/buzzer/library.json @@ -1,3 +1,4 @@ { - "name": "buzzer" + "name": "buzzer", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/deep_sleep/library.json b/usermods/deep_sleep/library.json index 8b39b2eedb..82e32c9947 100644 --- a/usermods/deep_sleep/library.json +++ b/usermods/deep_sleep/library.json @@ -1,3 +1,4 @@ { - "name": "deep_sleep" + "name": "deep_sleep", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/multi_relay/library.json b/usermods/multi_relay/library.json index f1caf7d42b..a5e5c6934b 100644 --- a/usermods/multi_relay/library.json +++ b/usermods/multi_relay/library.json @@ -1,3 +1,4 @@ { - "name": "multi_relay" + "name": "multi_relay", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/pwm_outputs/library.json b/usermods/pwm_outputs/library.json index bcdb8d5a64..a01068bd43 100644 --- a/usermods/pwm_outputs/library.json +++ b/usermods/pwm_outputs/library.json @@ -1,3 +1,4 @@ { - "name": "pwm_outputs" + "name": "pwm_outputs", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/sd_card/library.json b/usermods/sd_card/library.json index 44d3e3495e..33e8f98f27 100644 --- a/usermods/sd_card/library.json +++ b/usermods/sd_card/library.json @@ -1,3 +1,4 @@ { - "name": "sd_card" + "name": "sd_card", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/seven_segment_display/library.json b/usermods/seven_segment_display/library.json index 653c3d7ff2..f78aad87b9 100644 --- a/usermods/seven_segment_display/library.json +++ b/usermods/seven_segment_display/library.json @@ -1,3 +1,4 @@ { - "name": "seven_segment_display" + "name": "seven_segment_display", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/library.json b/usermods/seven_segment_display_reloaded/library.json index 4e84e38ed4..1b7d0687f2 100644 --- a/usermods/seven_segment_display_reloaded/library.json +++ b/usermods/seven_segment_display_reloaded/library.json @@ -1,6 +1,7 @@ { "name": "seven_segment_display_reloaded", "build": { + "libArchive": false, "extraScript": "setup_deps.py" - } + } } \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/setup_deps.py b/usermods/seven_segment_display_reloaded/setup_deps.py index dd28f5fe9c..1c51acccec 100644 --- a/usermods/seven_segment_display_reloaded/setup_deps.py +++ b/usermods/seven_segment_display_reloaded/setup_deps.py @@ -1,9 +1,10 @@ +from platformio.package.meta import PackageSpec Import('env') -usermods = env.GetProjectOption("custom_usermods","").split() +libs = [PackageSpec(lib).name for lib in env.GetProjectOption("lib_deps",[])] # Check for partner usermods -if "SN_Photoresistor" in usermods: +if "SN_Photoresistor" in libs: env.Append(CPPDEFINES=[("USERMOD_SN_PHOTORESISTOR")]) -if any(mod in ("BH1750_v2", "BH1750") for mod in usermods): +if any(mod in ("BH1750_v2", "BH1750") for mod in libs): env.Append(CPPDEFINES=[("USERMOD_BH1750")]) diff --git a/usermods/sht/library.json b/usermods/sht/library.json index 6849628ca0..0916e9a378 100644 --- a/usermods/sht/library.json +++ b/usermods/sht/library.json @@ -1,5 +1,6 @@ { "name": "sht", + "build": { "libArchive": false }, "dependencies": { "robtillaart/SHT85": "~0.3.3" } diff --git a/usermods/smartnest/library.json b/usermods/smartnest/library.json index 9b428f6b17..3e9ea63a9b 100644 --- a/usermods/smartnest/library.json +++ b/usermods/smartnest/library.json @@ -1,3 +1,4 @@ { - "name": "smartnest" + "name": "smartnest", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/stairway_wipe_basic/library.json b/usermods/stairway_wipe_basic/library.json index b75baef6bd..f7d353b596 100644 --- a/usermods/stairway_wipe_basic/library.json +++ b/usermods/stairway_wipe_basic/library.json @@ -1,3 +1,4 @@ { - "name": "stairway_wipe_basic" + "name": "stairway_wipe_basic", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_rotary_brightness_color/library.json b/usermods/usermod_rotary_brightness_color/library.json index ecf73c0f99..4f7a146a0b 100644 --- a/usermods/usermod_rotary_brightness_color/library.json +++ b/usermods/usermod_rotary_brightness_color/library.json @@ -1,3 +1,4 @@ { - "name": "usermod_rotary_brightness_color" + "name": "usermod_rotary_brightness_color", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_HttpPullLightControl/library.json b/usermods/usermod_v2_HttpPullLightControl/library.json index a9252fc0cf..870753b994 100644 --- a/usermods/usermod_v2_HttpPullLightControl/library.json +++ b/usermods/usermod_v2_HttpPullLightControl/library.json @@ -1,3 +1,4 @@ { - "name": "usermod_v2_HttpPullLightControl" + "name": "usermod_v2_HttpPullLightControl", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_HttpPullLightControl/usermod_v2_HttpPullLightControl.cpp b/usermods/usermod_v2_HttpPullLightControl/usermod_v2_HttpPullLightControl.cpp index b908b057c5..44a2726ed6 100644 --- a/usermods/usermod_v2_HttpPullLightControl/usermod_v2_HttpPullLightControl.cpp +++ b/usermods/usermod_v2_HttpPullLightControl/usermod_v2_HttpPullLightControl.cpp @@ -4,6 +4,9 @@ const char HttpPullLightControl::_name[] PROGMEM = "HttpPullLightControl"; const char HttpPullLightControl::_enabled[] PROGMEM = "Enable"; +static HttpPullLightControl http_pull_usermod; +REGISTER_USERMOD(http_pull_usermod); + void HttpPullLightControl::setup() { //Serial.begin(115200); diff --git a/usermods/usermod_v2_RF433/library.json b/usermods/usermod_v2_RF433/library.json index d809d3a0da..d8de29b8a5 100644 --- a/usermods/usermod_v2_RF433/library.json +++ b/usermods/usermod_v2_RF433/library.json @@ -1,5 +1,6 @@ { "name": "usermod_v2_RF433", + "build": { "libArchive": false }, "dependencies": { "sui77/rc-switch":"2.6.4" } diff --git a/usermods/usermod_v2_animartrix/library.json b/usermods/usermod_v2_animartrix/library.json index 4552be3301..667572bad9 100644 --- a/usermods/usermod_v2_animartrix/library.json +++ b/usermods/usermod_v2_animartrix/library.json @@ -1,5 +1,6 @@ { "name": "animartrix", + "build": { "libArchive": false }, "dependencies": { "Animartrix": "https://github.com/netmindz/animartrix.git#b172586" } diff --git a/usermods/usermod_v2_auto_save/library.json b/usermods/usermod_v2_auto_save/library.json index d703487a75..127767eb07 100644 --- a/usermods/usermod_v2_auto_save/library.json +++ b/usermods/usermod_v2_auto_save/library.json @@ -1,3 +1,4 @@ { - "name": "auto_save" + "name": "auto_save", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_brightness_follow_sun/library.json b/usermods/usermod_v2_brightness_follow_sun/library.json index 6120d873e3..dec00e55b6 100644 --- a/usermods/usermod_v2_brightness_follow_sun/library.json +++ b/usermods/usermod_v2_brightness_follow_sun/library.json @@ -1,3 +1,4 @@ { - "name": "brightness_follow_sun" + "name": "brightness_follow_sun", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_four_line_display_ALT/library.json b/usermods/usermod_v2_four_line_display_ALT/library.json index 87a690f03f..b164482234 100644 --- a/usermods/usermod_v2_four_line_display_ALT/library.json +++ b/usermods/usermod_v2_four_line_display_ALT/library.json @@ -1,5 +1,6 @@ { "name": "four_line_display_ALT", + "build": { "libArchive": false }, "dependencies": { "U8g2": "~2.34.4", "Wire": "" diff --git a/usermods/usermod_v2_klipper_percentage/library.json b/usermods/usermod_v2_klipper_percentage/library.json index 7a2df6b23f..962dda14e7 100644 --- a/usermods/usermod_v2_klipper_percentage/library.json +++ b/usermods/usermod_v2_klipper_percentage/library.json @@ -1,3 +1,4 @@ { - "name": "usermod_v2_klipper_percentage" + "name": "usermod_v2_klipper_percentage", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_ping_pong_clock/library.json b/usermods/usermod_v2_ping_pong_clock/library.json index d6c079e589..4b272eca47 100644 --- a/usermods/usermod_v2_ping_pong_clock/library.json +++ b/usermods/usermod_v2_ping_pong_clock/library.json @@ -1,3 +1,4 @@ { - "name": "usermod_v2_ping_pong_clock" + "name": "usermod_v2_ping_pong_clock", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/library.json b/usermods/usermod_v2_rotary_encoder_ui_ALT/library.json index ddb6334b16..7c828d087c 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/library.json +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/library.json @@ -1,6 +1,7 @@ { "name": "rotary_encoder_ui_ALT", "build": { + "libArchive": false, "extraScript": "setup_deps.py" } } \ No newline at end of file diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py b/usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py index a6b5659513..ed579bc125 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py @@ -1,8 +1,8 @@ +from platformio.package.meta import PackageSpec Import('env') - -usermods = env.GetProjectOption("custom_usermods","").split() +libs = [PackageSpec(lib).name for lib in env.GetProjectOption("lib_deps",[])] # Check for partner usermod # Allow both "usermod_v2" and unqualified syntax -if any(mod in ("four_line_display_ALT", "usermod_v2_four_line_display_ALT") for mod in usermods): +if any(mod in ("four_line_display_ALT", "usermod_v2_four_line_display_ALT") for mod in libs): env.Append(CPPDEFINES=[("USERMOD_FOUR_LINE_DISPLAY")]) diff --git a/usermods/usermod_v2_word_clock/library.json b/usermods/usermod_v2_word_clock/library.json index b0dcebc6eb..0ea99d8102 100644 --- a/usermods/usermod_v2_word_clock/library.json +++ b/usermods/usermod_v2_word_clock/library.json @@ -1,3 +1,4 @@ { - "name": "usermod_v2_word_clock" + "name": "usermod_v2_word_clock", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/wizlights/library.json b/usermods/wizlights/library.json index 114424e5d0..0bfc097c78 100644 --- a/usermods/wizlights/library.json +++ b/usermods/wizlights/library.json @@ -1,3 +1,4 @@ { - "name": "wizlights" + "name": "wizlights", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/usermods/word-clock-matrix/library.json b/usermods/word-clock-matrix/library.json index afeae5025f..7bc3919de0 100644 --- a/usermods/word-clock-matrix/library.json +++ b/usermods/word-clock-matrix/library.json @@ -1,3 +1,4 @@ { - "name": "word-clock-matrix" + "name": "word-clock-matrix", + "build": { "libArchive": false } } \ No newline at end of file diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 9bfb7e7372..1a7cc22694 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -39,7 +39,13 @@ bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) { return false; } void UsermodManager::addToJsonState(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToJsonState(obj); } -void UsermodManager::addToJsonInfo(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToJsonInfo(obj); } +void UsermodManager::addToJsonInfo(JsonObject& obj) { + auto um_id_list = obj.createNestedArray("um"); + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) { + um_id_list.add((*mod)->getId()); + (*mod)->addToJsonInfo(obj); + } +} void UsermodManager::readFromJsonState(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->readFromJsonState(obj); } void UsermodManager::addToConfig(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToConfig(obj); } bool UsermodManager::readFromConfig(JsonObject& obj) {