diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2bac314f3..3de08ff7b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,6 +57,7 @@ jobs: cache: 'pip' - name: Install PlatformIO run: pip install -r requirements.txt + - name: Build firmware run: pio run -e ${{ matrix.environment }} - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/pr-merge.yaml b/.github/workflows/pr-merge.yaml index df8ae2253..9ef843dd4 100644 --- a/.github/workflows/pr-merge.yaml +++ b/.github/workflows/pr-merge.yaml @@ -8,6 +8,9 @@ runs-on: ubuntu-latest steps: - name: Send Discord notification + shell: bash + env: + DISCORD_WEBHOOK_BETA_TESTERS: ${{ secrets.DISCORD_WEBHOOK_BETA_TESTERS }} if: github.event.pull_request.merged == true run: | - curl -H "Content-Type: application/json" -d '{"content": "Pull Request #{{ github.event.pull_request.number }} merged by {{ github.actor }}"}' ${{ secrets.DISCORD_WEBHOOK_BETA_TESTERS }} + curl -H "Content-Type: application/json" -d '{"content": "Pull Request #{{ github.event.pull_request.number }} merged by {{ github.actor }}"}' $DISCORD_WEBHOOK_BETA_TESTERS diff --git a/package-lock.json b/package-lock.json index 0afeeaafd..b5e14158d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,28 @@ { "name": "wled", - "version": "0.16.0-dev", + "version": "0.16.0-alpha", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wled", - "version": "0.16.0-dev", + "version": "0.16.0-alpha", "license": "ISC", "dependencies": { "clean-css": "^5.3.3", "html-minifier-terser": "^7.2.0", - "inliner": "^1.13.1", - "nodemon": "^3.1.7" + "nodemon": "^3.1.9", + "web-resource-inliner": "^7.0.0" }, "engines": { "node": ">=20.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -35,6 +36,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -43,6 +45,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -51,6 +54,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -59,21 +63,24 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -81,62 +88,20 @@ "node": ">=0.4.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", - "dependencies": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha512-wiXutNjDUlNEDWHcYH3jtZUhd3c4/VojassD8zHdHCY13xbZy2XbW+NKQwA0tWGBVzDA9qEzYwfoSsWmviidhw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -145,70 +110,17 @@ "node": ">= 8" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -216,15 +128,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -234,6 +142,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -244,89 +153,24 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/camel-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", - "dependencies": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/charset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", - "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/cheerio": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", - "integrity": "sha512-Fwcm3zkR37STnPC8FepSHeSYJM5Rd596TZOcfDUdojR4Q735aK1Xn+M+ISagNneuCwMjK28w4kX+ETILGNT/UQ==", - "dependencies": { - "css-select": "~1.0.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "lodash": "^3.2.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cheerio/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -346,21 +190,11 @@ "fsevents": "~2.3.2" } }, - "node_modules/clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "dependencies": { - "chalk": "^1.1.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", "dependencies": { "source-map": "~0.6.0" }, @@ -368,50 +202,11 @@ "node": ">= 10.0" } }, - "node_modules/cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", - "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "node_modules/coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha512-KAGck/eNAmCL0dcT3BiuYwLbExK6lduR8DxM3C1TyDzaXhZHyZ8ooX5I5+na2e3dPFuibfxrGdorr0/Lr7RYCQ==", - "dependencies": { - "q": "^1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", "engines": { "node": ">=14" } @@ -419,230 +214,135 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/configstore": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-1.4.0.tgz", - "integrity": "sha512-Zcx2SVdZC06IuRHd2MhkVYFNJBkZBj166LGdsJXRcqNC8Gs5Bwh8mosStNeCBBmtIm4wNii2uarD50qztjKOjw==", - "dependencies": { - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.1", - "os-tmpdir": "^1.0.0", - "osenv": "^0.1.0", - "uuid": "^2.0.1", - "write-file-atomic": "^1.1.2", - "xdg-basedir": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/configstore/node_modules/uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details." - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/css-select": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", - "integrity": "sha512-/xPlD7betkfd7ChGkLGGWx5HWyiHDOSn7aACLzdH0nwucPvB0EAm8hMBm7Xn7vGfAeRRN7KZ8wumGm8NoNcMRw==", - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "1.0", - "domutils": "1.4", - "nth-check": "~1.0.0" - } - }, - "node_modules/css-what": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", - "integrity": "sha512-60SUMPBreXrLXgvpM8kYpO0AOyMRhdRlXFX5BMQbZq1SIJCyNE56nqFQhmvREQdUJpedbGRYZ5wOyq3/F6q5Zw==", - "engines": { - "node": "*" - } - }, - "node_modules/csso": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.0.0.tgz", - "integrity": "sha512-tckZA0LhyEnToPoQDmncCA+TUS3aoIVl/MsSaoipR52Sfa+H83fJvIHRVOHMFn9zW6kIV1L0D7tUDFFjvN28lg==", - "dependencies": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - }, - "bin": { - "csso": "bin/csso" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "ms": "^2.1.3" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/dom-serializer/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", + "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "license": "BSD-2-Clause", "dependencies": { - "domelementtype": "1" + "domelementtype": "^2.0.1" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/domutils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", - "integrity": "sha512-ZkVgS/PpxjyJMb+S2iVHHEZjVnOUtjGp0/zstqKGTE9lrZtNHlNQmLwP/lhLMEApYbzc08BKMx9IFpKhaSbW1w==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", "dependencies": { - "domelementtype": "1" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/domutils/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/duplexify/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexify/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/duplexify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -650,58 +350,23 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/es6-promise": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz", - "integrity": "sha512-oyOjMhyKMLEjOOtvkwg0G4pAzLQ9WdbbeX7WdqKzvYXu+UFgD0Zo/Brq5Q49zNmnGPPzV5rmYvrr0jz1zWx8Iw==" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", + "license": "MIT", "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "node": ">=10" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -709,32 +374,12 @@ "node": ">=8" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -743,18 +388,11 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -762,75 +400,11 @@ "node": ">= 6" } }, - "node_modules/got": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/got/-/got-3.3.1.tgz", - "integrity": "sha512-7chPlc0pWHjvq7B6dEEXz4GphoDupOvBSSl6AwRsAJX7GPTZ+bturaZiIigX4Dp6KrAP67nvzuKkNc0SLA0DKg==", - "dependencies": { - "duplexify": "^3.2.0", - "infinity-agent": "^2.0.0", - "is-redirect": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "nested-error-stacks": "^1.0.0", - "object-assign": "^3.0.0", - "prepend-http": "^1.0.0", - "read-all-stream": "^3.0.0", - "timed-out": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/got/node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", "engines": { "node": ">=4" } @@ -839,6 +413,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", "dependencies": { "camel-case": "^4.1.2", "clean-css": "~5.3.2", @@ -856,117 +431,40 @@ } }, "node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz", + "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==", + "license": "MIT", "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "node_modules/htmlparser2/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "domelementtype": "^2.0.1", + "domhandler": "^3.3.0", + "domutils": "^2.4.2", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/fb55/htmlparser2?sponsor=1" } }, "node_modules/htmlparser2/node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/infinity-agent": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/infinity-agent/-/infinity-agent-2.0.3.tgz", - "integrity": "sha512-CnfUJe5o2S9aAQWXGMhDZI4UL39MAJV3guOTfHHIdos4tuVHkl1j/J+1XLQn+CLIvqcpgQR/p+xXYXzcrhCe5w==" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/inliner": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/inliner/-/inliner-1.13.1.tgz", - "integrity": "sha512-yoS+56puOu+Ug8FBRtxtTFnEn2NHqFs8BNQgSOvzh3J0ommbwNw8VKiaVNYjWK6fgPuByq95KyV0LC+qV9IwLw==", - "dependencies": { - "ansi-escapes": "^1.4.0", - "ansi-styles": "^2.2.1", - "chalk": "^1.1.3", - "charset": "^1.0.0", - "cheerio": "^0.19.0", - "debug": "^2.2.0", - "es6-promise": "^2.3.0", - "iconv-lite": "^0.4.11", - "jschardet": "^1.3.0", - "lodash.assign": "^3.2.0", - "lodash.defaults": "^3.1.2", - "lodash.foreach": "^3.0.3", - "mime": "^1.3.4", - "minimist": "^1.1.3", - "request": "^2.74.0", - "svgo": "^0.6.6", - "then-fs": "^2.0.0", - "uglify-js": "^2.8.0", - "update-notifier": "^0.5.0" - }, - "bin": { - "inliner": "cli/index.js" - } + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "license": "ISC" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -974,34 +472,20 @@ "node": ">=8" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -1009,310 +493,41 @@ "node": ">=0.10.0" } }, - "node_modules/is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } }, - "node_modules/is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha512-BLv3oxhfET+w5fjPwq3PsAsxzi9i3qzU//HMpWVz0A6KplF86HdR9x2TGnv9DXhSUrO7LO8czUiTd3yb3mLSvg==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/jschardet": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", - "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/latest-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-1.0.1.tgz", - "integrity": "sha512-HERbxp4SBlmI380+eM0B0u4nxjfTaPeydIMzl9+9UQ4nSu3xMWKlX9WoT34e4wy7VWe67c53Nv9qPVjS8fHKgg==", - "dependencies": { - "package-json": "^1.0.0" - }, - "bin": { - "latest-version": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==" - }, - "node_modules/lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha512-Mn7HidOVcl3mkQtbPsuKR0Fj0N6Q6DQB77CtYncZcJc0bx5qv2q4Gl6a0LC1AN+GSxpnBDNnK3CKEm9XNA4zqQ==" - }, - "node_modules/lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==", - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==" - }, - "node_modules/lodash._baseeach": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash._baseeach/-/lodash._baseeach-3.0.4.tgz", - "integrity": "sha512-IqUZ9MQo2UT1XPGuBntInqTOlc+oV+bCo0kMp+yuKGsfvRSNgUW0YjWVZUrG/gs+8z/Eyuc0jkJjOBESt9BXxg==", - "dependencies": { - "lodash.keys": "^3.0.0" - } - }, - "node_modules/lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==" - }, - "node_modules/lodash._createassigner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", - "integrity": "sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw==", - "dependencies": { - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash.restparam": "^3.0.0" - } - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==" - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==" - }, - "node_modules/lodash.assign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", - "integrity": "sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA==", - "dependencies": { - "lodash._baseassign": "^3.0.0", - "lodash._createassigner": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "node_modules/lodash.defaults": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", - "integrity": "sha512-X7135IXFQt5JDFnYxOVAzVz+kFvwDn3N8DJYf+nrz/mMWEuSu7+OL6rWqsk3+VR1T4TejFCSu5isBJOLSID2bg==", - "dependencies": { - "lodash.assign": "^3.0.0", - "lodash.restparam": "^3.0.0" - } - }, - "node_modules/lodash.foreach": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-3.0.3.tgz", - "integrity": "sha512-PA7Lp7pe2HMJBoB1vELegEIF3waUFnM0fWDKJVYolwZ4zHh6WTmnq0xmzfQksD66gx2quhDNyBdyaE2T8/DP3Q==", - "dependencies": { - "lodash._arrayeach": "^3.0.0", - "lodash._baseeach": "^3.0.0", - "lodash._bindcallback": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==" - }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", - "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==" - }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", "bin": { "mime": "cli.js" }, "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" + "node": ">=4.0.0" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1320,51 +535,27 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/nested-error-stacks": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz", - "integrity": "sha512-o32anp9JA7oezPOFSfG2BBXSdHepOm5FpJvwxHWDtfJ3Bg3xdi68S6ijPlEOfUg6quxZWyvJM+8fHk1yMDKspA==", - "dependencies": { - "inherits": "~2.0.1" - } + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "node_modules/nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -1388,112 +579,11 @@ "url": "https://opencollective.com/nodemon" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-1.2.0.tgz", - "integrity": "sha512-knDtirWWqKVJrLY3gEBLflVvueTMpyjbAwX/9j/EKi2DsjNemp5voS8cyKyGh57SNaMJNhNRZbIaWdneOcLU1g==", - "dependencies": { - "got": "^3.2.0", - "registry-url": "^3.0.0" - }, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1502,6 +592,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -1511,20 +602,17 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -1532,155 +620,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dependencies": { - "asap": "~2.0.3" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/read-all-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", - "integrity": "sha512-DI1drPHbmBcUDWrJ7ull/F2Qb8HkwBncVx8/RpKYFSIACYaVRQReISYPdZz/mt1y1+qMCOrfReTopERmaxtP6w==", - "dependencies": { - "pinkie-promise": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-all-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/read-all-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/read-all-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/read-all-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "license": "MIT" }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -1688,122 +638,20 @@ "node": ">=8.10.0" } }, - "node_modules/registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", - "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", - "integrity": "sha512-Nh30JLeMHdoI+AsQ5eblhZ7YlTsM9wiJQe/AHIunlK3KWzvXhXb36IJ7K1IOeRjIOtzMjdUHjwXUFxKJoPTSOg==", - "dependencies": { - "is-finite": "^1.0.0" - }, - "bin": { - "repeating": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", - "dependencies": { - "align-text": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1811,29 +659,11 @@ "node": ">=10" } }, - "node_modules/semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw==", - "dependencies": { - "semver": "^5.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -1841,18 +671,11 @@ "node": ">=10" } }, - "node_modules/slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", - "engines": { - "node": "*" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -1861,113 +684,29 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/string-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", - "integrity": "sha512-MNCACnufWUf3pQ57O5WTBMkKhzYIaKEcUioO0XHrTMafrbBaNk4IyDOLHBv5xbXO0jLLdsYWeFjpjG2hVHRDtw==", - "dependencies": { - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/svgo": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.6.6.tgz", - "integrity": "sha512-C5A1r5SjFesNoKsmc+kWBxmB04iBGH2D/nFy8HJaME9+SyZKcmqcN8QG+GwxIc7D2+JWhaaW7uaM9+XwfplTEQ==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", "dependencies": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.0.0", - "js-yaml": "~3.6.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - }, - "bin": { - "svgo": "bin/svgo" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/terser": { - "version": "5.34.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.0.tgz", - "integrity": "sha512-y5NUX+U9HhVsK/zihZwoq4r9dICLyV2jXGOriDAVOeKhq3LKVjgJbGO90FisozXLlJfvjHqgckGmJFBb9KYoWQ==", + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -1984,28 +723,14 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/then-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/then-fs/-/then-fs-2.0.0.tgz", - "integrity": "sha512-5ffcBcU+vFUCYDNi/o507IqjqrTkuGsLVZ1Fp50hwgZRY7ufVFa9jFfTy5uZ2QnSKacKigWKeaXkOqLa4DsjLw==", - "dependencies": { - "promise": ">=3.2 <8" - } - }, - "node_modules/timed-out": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", - "integrity": "sha512-pqqJOi1rF5zNs/ps4vmbE4SFCrM4iR7LW+GHAsHqO/EumqbIWceioevYLM5xZRgQSH6gFgL9J/uB7EcJhQ9niQ==", - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -2017,196 +742,46 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "license": "ISC", "bin": { "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", - "dependencies": { - "source-map": "~0.5.1", - "yargs": "~3.10.0" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - }, - "optionalDependencies": { - "uglify-to-browserify": "~1.0.0" - } - }, - "node_modules/uglify-js/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", - "optional": true + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "license": "MIT" }, - "node_modules/update-notifier": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.5.0.tgz", - "integrity": "sha512-zOGOlUKDAgDlLHLv7Oiszz3pSj8fKlSJ3i0u49sEakjXUEVJ6DMjo/Mh/B6mg2eOALvRTJkd0kbChcipQoYCng==", + "node_modules/valid-data-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", + "integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/web-resource-inliner": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-7.0.0.tgz", + "integrity": "sha512-NlfnGF8MY9ZUwFjyq3vOUBx7KwF8bmE+ywR781SB0nWB6MoMxN4BA8gtgP1KGTZo/O/AyWJz7HZpR704eaj4mg==", + "license": "MIT", "dependencies": { - "chalk": "^1.0.0", - "configstore": "^1.0.0", - "is-npm": "^1.0.0", - "latest-version": "^1.0.0", - "repeating": "^1.1.2", - "semver-diff": "^2.0.0", - "string-length": "^1.0.0" + "ansi-colors": "^4.1.1", + "escape-goat": "^3.0.0", + "htmlparser2": "^5.0.0", + "mime": "^2.4.6", + "valid-data-url": "^3.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "node_modules/whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", - "integrity": "sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw==", - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" - } - }, - "node_modules/xdg-basedir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", - "integrity": "sha512-NF1pPn594TaRSUO/HARoB4jK8I+rWgcpVlpQCK6/6o5PHyLUt2CSiDrpUZbQ6rROck+W2EwF8mBJcTs+W98J9w==", - "dependencies": { - "os-homedir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", - "dependencies": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "node": ">=10.0.0" } } } diff --git a/package.json b/package.json index 26d24127c..2d7ad2de4 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,10 @@ "dependencies": { "clean-css": "^5.3.3", "html-minifier-terser": "^7.2.0", - "inliner": "^1.13.1", - "nodemon": "^3.1.7" + "web-resource-inliner": "^7.0.0", + "nodemon": "^3.1.9" }, "engines": { "node": ">=20.0.0" } -} +} \ No newline at end of file diff --git a/pio-scripts/load_usermods.py b/pio-scripts/load_usermods.py new file mode 100644 index 000000000..ab3c6476a --- /dev/null +++ b/pio-scripts/load_usermods.py @@ -0,0 +1,115 @@ +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 + +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()] + +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): + """Locate this library in the usermods folder. + We do this to avoid needing to rename a bunch of folders; + this could be removed later + """ + # Check name match + mp = usermod_dir / mod + if mp.exists(): + return mp + mp = usermod_dir / f"{mod}_v2" + if mp.exists(): + 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!") + +usermods = env.GetProjectOption("custom_usermods","") +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) + + +# 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: + dep_cache.add(dep) + for include in dep.get_include_dirs(): + if include not in includes: + includes.appendleft(include) + if usermod_dir not in Path(dep.src_dir).parents: + # Recurse, but only for NON-usermods + for subdep in dep.depbuilders: + cached_add_includes(subdep, dep_cache, includes) + +# Monkey-patch ConfigureProjectLibBuilder to mark up the dependencies +# Save the old value +old_ConfigureProjectLibBuilder = env.ConfigureProjectLibBuilder + +# 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)() + + # Fix up include paths + # In PlatformIO >=6.1.17, this could be done prior to ConfigureProjectLibBuilder + wled_dir = xenv["PROJECT_SRC_DIR"] + # Build a list of dependency include dirs + # TODO: Find out if this is the order that PlatformIO/SCons puts them in?? + processed_deps = set() + extra_include_dirs = deque() # Deque used for fast prepend + 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) + + return result + +# Apply the wrapper +env.AddMethod(wrapped_ConfigureProjectLibBuilder, "ConfigureProjectLibBuilder") diff --git a/platformio.ini b/platformio.ini index 5b1b21265..a7485244c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,7 +10,7 @@ # ------------------------------------------------------------------------------ # CI/release binaries -default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, nodemcuv2_compat, esp8266_2m_compat, esp01_1m_full_compat, esp32dev, esp32dev_V4, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_16MB_opi, esp32s3dev_8MB_opi, esp32s3_4M_qspi, esp32_wrover +default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, nodemcuv2_160, esp8266_2m_160, esp01_1m_full_160, nodemcuv2_compat, esp8266_2m_compat, esp01_1m_full_compat, esp32dev, esp32dev_V4, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_16MB_opi, esp32s3dev_8MB_opi, esp32s3_4M_qspi, esp32_wrover, usermods src_dir = ./wled00 data_dir = ./wled00/data @@ -114,6 +114,7 @@ extra_scripts = post:pio-scripts/output_bins.py post:pio-scripts/strip-floats.py pre:pio-scripts/user_config_copy.py + pre:pio-scripts/load_usermods.py pre:pio-scripts/build_ui.py ; post:pio-scripts/obj-dump.py ;; convenience script to create a disassembly dump of the firmware (hardcore debugging) @@ -157,21 +158,13 @@ lib_deps = ;adafruit/Adafruit BMP280 Library @ 2.1.0 ;adafruit/Adafruit CCS811 Library @ 1.0.4 ;adafruit/Adafruit Si7021 Library @ 1.4.0 - #For ADS1115 sensor uncomment following - ;adafruit/Adafruit BusIO @ 1.13.2 - ;adafruit/Adafruit ADS1X15 @ 2.4.0 #For MAX1704x Lipo Monitor / Fuel Gauge uncomment following ; https://github.com/adafruit/Adafruit_BusIO @ 1.14.5 ; https://github.com/adafruit/Adafruit_MAX1704X @ 1.0.2 #For MPU6050 IMU uncomment follwoing ;electroniccats/MPU6050 @1.0.1 - # For -D USERMOD_ANIMARTRIX - # CC BY-NC 3.0 licensed effects by Stefan Petrick, include this usermod only if you accept the terms! - ;https://github.com/netmindz/animartrix.git#18bf17389e57c69f11bc8d04ebe1d215422c7fb7 # SHT85 ;robtillaart/SHT85@~0.3.3 - # Audioreactive usermod - ;kosme/arduinoFFT @ 2.0.1 extra_scripts = ${scripts_defaults.extra_scripts} @@ -270,11 +263,11 @@ lib_deps = https://github.com/lorol/LITTLEFS.git ${esp32_all_variants.lib_deps} ${env.lib_deps} -# additional build flags for audioreactive -AR_build_flags = -D USERMOD_AUDIOREACTIVE - -D sqrt_internal=sqrtf ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster) -AR_lib_deps = kosme/arduinoFFT @ 2.0.1 board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs +# additional build flags for audioreactive - must be applied globally +AR_build_flags = ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster) +AR_lib_deps = ;; for pre-usermod-library platformio_override compatibility + [esp32_idf_V4] ;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5 @@ -384,8 +377,8 @@ build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEAS extends = env:nodemcuv2 board_build.f_cpu = 160000000L build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_160\" #-DWLED_DISABLE_2D - -D USERMOD_AUDIOREACTIVE -D WLED_DISABLE_PARTICLESYSTEM2D +custom_usermods = audioreactive [env:esp8266_2m] board = esp_wroom_02 @@ -411,9 +404,9 @@ build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEAS extends = env:esp8266_2m board_build.f_cpu = 160000000L build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02_160\" - -D USERMOD_AUDIOREACTIVE -D WLED_DISABLE_PARTICLESYSTEM1D -D WLED_DISABLE_PARTICLESYSTEM2D +custom_usermods = audioreactive [env:esp01_1m_full] board = esp01_1m @@ -440,20 +433,19 @@ build_flags = ${common.build_flags} ${esp8266.build_flags_compat} -D WLED_RELEAS extends = env:esp01_1m_full board_build.f_cpu = 160000000L build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01_160\" -D WLED_DISABLE_OTA - -D USERMOD_AUDIOREACTIVE ; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM -D WLED_DISABLE_PARTICLESYSTEM1D -D WLED_DISABLE_PARTICLESYSTEM2D +custom_usermods = audioreactive [env:esp32dev] board = esp32dev platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET - ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} - ${esp32.AR_lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.default_partitions} @@ -461,10 +453,9 @@ board_build.partitions = ${esp32.default_partitions} board = esp32dev platform = ${esp32_idf_V4.platform} build_unflags = ${common.build_unflags} +custom_usermods = audioreactive build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_V4\" #-D WLED_DISABLE_BROWNOUT_DET - ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} - ${esp32.AR_lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.default_partitions} board_build.flash_mode = dio @@ -472,11 +463,10 @@ board_build.flash_mode = dio [env:esp32dev_8M] board = esp32dev platform = ${esp32_idf_V4.platform} +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET - ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} - ${esp32.AR_lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.large_partitions} board_upload.flash_size = 8MB @@ -487,11 +477,10 @@ board_upload.maximum_size = 8388608 [env:esp32dev_16M] board = esp32dev platform = ${esp32_idf_V4.platform} +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET - ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} - ${esp32.AR_lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.extreme_partitions} board_upload.flash_size = 16MB @@ -503,11 +492,10 @@ board_build.flash_mode = dio ;board = esp32dev ;platform = ${esp32.platform} ;platform_packages = ${esp32.platform_packages} +;custom_usermods = audioreactive ;build_unflags = ${common.build_unflags} ;build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_audioreactive\" #-D WLED_DISABLE_BROWNOUT_DET -; ${esp32.AR_build_flags} ;lib_deps = ${esp32.lib_deps} -; ${esp32.AR_lib_deps} ;monitor_filters = esp32_exception_decoder ;board_build.partitions = ${esp32.default_partitions} ;; board_build.f_flash = 80000000L @@ -518,12 +506,11 @@ board = esp32-poe platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} upload_speed = 921600 +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 ; -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only - ${esp32.AR_build_flags} lib_deps = ${esp32.lib_deps} - ${esp32.AR_lib_deps} board_build.partitions = ${esp32.default_partitions} [env:esp32_wrover] @@ -533,14 +520,13 @@ board = ttgo-t7-v14-mini32 board_build.f_flash = 80000000L board_build.flash_mode = qio board_build.partitions = ${esp32.extended_partitions} +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\" -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html -D DATA_PINS=25 - ${esp32.AR_build_flags} lib_deps = ${esp32_idf_V4.lib_deps} - ${esp32.AR_lib_deps} - + [env:esp32c3dev] extends = esp32c3 platform = ${esp32c3.platform} @@ -562,15 +548,14 @@ board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM suppor board_build.arduino.memory_type = qio_opi ;; use with PSRAM: 8MB or 16MB platform = ${esp32s3.platform} upload_speed = 921600 +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_16MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM - ${esp32.AR_build_flags} lib_deps = ${esp32s3.lib_deps} - ${esp32.AR_lib_deps} board_build.partitions = ${esp32.extreme_partitions} board_upload.flash_size = 16MB board_upload.maximum_size = 16777216 @@ -584,15 +569,14 @@ board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM suppor board_build.arduino.memory_type = qio_opi ;; use with PSRAM: 8MB or 16MB platform = ${esp32s3.platform} upload_speed = 921600 +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_opi\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM - ${esp32.AR_build_flags} lib_deps = ${esp32s3.lib_deps} - ${esp32.AR_lib_deps} board_build.partitions = ${esp32.large_partitions} board_build.f_flash = 80000000L board_build.flash_mode = qio @@ -605,6 +589,7 @@ platform = ${esp32s3.platform} board = esp32s3camlcd ;; this is the only standard board with "opi_opi" board_build.arduino.memory_type = opi_opi upload_speed = 921600 +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2\" -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 @@ -614,10 +599,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= -D LEDPIN=38 -D DATA_PINS=38 ;; buildin WS2812b LED -D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1 -D WLED_DEBUG - ${esp32.AR_build_flags} -D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4 ;; I2S mic lib_deps = ${esp32s3.lib_deps} - ${esp32.AR_lib_deps} board_build.partitions = ${esp32.extreme_partitions} board_upload.flash_size = 16MB @@ -629,15 +612,14 @@ monitor_filters = esp32_exception_decoder board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM platform = ${esp32s3.platform} upload_speed = 921600 +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_4M_qspi\" -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") -DBOARD_HAS_PSRAM -DLOLIN_WIFI_FIX ; seems to work much better with this -D WLED_WATCHDOG_TIMEOUT=0 - ${esp32.AR_build_flags} lib_deps = ${esp32s3.lib_deps} - ${esp32.AR_lib_deps} board_build.partitions = ${esp32.default_partitions} board_build.f_flash = 80000000L board_build.flash_mode = qio @@ -649,6 +631,7 @@ board = lolin_s2_mini board_build.partitions = ${esp32.default_partitions} board_build.flash_mode = qio board_build.f_flash = 80000000L +custom_usermods = audioreactive build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\" -DARDUINO_USB_CDC_ON_BOOT=1 @@ -664,6 +647,17 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME= -D HW_PIN_DATASPI=11 -D HW_PIN_MISOSPI=9 ; -D STATUSLED=15 - ${esp32.AR_build_flags} lib_deps = ${esp32s2.lib_deps} - ${esp32.AR_lib_deps} + + +[env:usermods] +board = esp32dev +platform = ${esp32_idf_V4.platform} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_USERMODS\" + -DTOUCH_CS=9 +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 +board_build.partitions = ${esp32.extreme_partitions} ; We're gonna need a bigger boat diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 36cc4d670..f3b4e1c65 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -506,9 +506,8 @@ lib_deps = ${esp8266.lib_deps} extends = esp32 ;; use default esp32 platform board = esp32dev upload_speed = 921600 +custom_usermods = ${env:esp32dev.custom_usermods} RTC EleksTube_IPS build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED - -D USERMOD_RTC - -D USERMOD_ELEKSTUBE_IPS -D DATA_PINS=12 -D RLYPIN=27 -D BTNPIN=34 @@ -526,9 +525,6 @@ build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_DISABLE_BROWNOU -D SPI_FREQUENCY=40000000 -D USER_SETUP_LOADED monitor_filters = esp32_exception_decoder -lib_deps = - ${esp32.lib_deps} - TFT_eSPI @ 2.5.33 ;; this is the last version that compiles with the WLED default framework - newer versions require platform = espressif32 @ ^6.3.2 # ------------------------------------------------------------------------------ # Usermod examples diff --git a/requirements.in b/requirements.in index 7c715125f..a74bd418b 100644 --- a/requirements.in +++ b/requirements.in @@ -1 +1 @@ -platformio +platformio>=6.1.17 diff --git a/requirements.txt b/requirements.txt index ee70cd689..1737408aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,26 +2,24 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile +# pip-compile requirements.in # ajsonrpc==1.2.0 # via platformio -anyio==4.6.0 +anyio==4.8.0 # via starlette -bottle==0.13.1 +bottle==0.13.2 # via platformio -certifi==2024.8.30 +certifi==2025.1.31 # via requests -charset-normalizer==3.3.2 +charset-normalizer==3.4.1 # via requests -click==8.1.7 +click==8.1.8 # via # platformio # uvicorn colorama==0.4.6 - # via - # click - # platformio + # via platformio h11==0.14.0 # via # uvicorn @@ -30,13 +28,13 @@ idna==3.10 # via # anyio # requests -marshmallow==3.22.0 +marshmallow==3.26.1 # via platformio -packaging==24.1 +packaging==24.2 # via marshmallow -platformio==6.1.16 +platformio==6.1.17 # via -r requirements.in -pyelftools==0.31 +pyelftools==0.32 # via platformio pyserial==3.5 # via platformio @@ -46,13 +44,15 @@ semantic-version==2.10.0 # via platformio sniffio==1.3.1 # via anyio -starlette==0.39.1 +starlette==0.45.3 # via platformio tabulate==0.9.0 # via platformio -urllib3==2.2.3 +typing-extensions==4.12.2 + # via anyio +urllib3==2.3.0 # via requests -uvicorn==0.30.6 +uvicorn==0.34.0 # via platformio wsproto==1.2.0 # via platformio diff --git a/tools/cdata.js b/tools/cdata.js index b2feffee8..e02047e8b 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -17,7 +17,7 @@ const fs = require("node:fs"); const path = require("path"); -const inliner = require("inliner"); +const inline = require("web-resource-inliner"); const zlib = require("node:zlib"); const CleanCSS = require("clean-css"); const minifyHtml = require("html-minifier-terser").minify; @@ -128,21 +128,26 @@ async function minify(str, type = "plain") { async function writeHtmlGzipped(sourceFile, resultFile, page) { console.info("Reading " + sourceFile); - new inliner(sourceFile, async function (error, html) { - if (error) throw error; + inline.html({ + fileContent: fs.readFileSync(sourceFile, "utf8"), + relativeTo: path.dirname(sourceFile), + strict: true, + }, + async function (error, html) { + if (error) throw error; - html = adoptVersionAndRepo(html); - const originalLength = html.length; - html = await minify(html, "html-minify"); - const result = zlib.gzipSync(html, { level: zlib.constants.Z_BEST_COMPRESSION }); - console.info("Minified and compressed " + sourceFile + " from " + originalLength + " to " + result.length + " bytes"); - const array = hexdump(result); - let src = singleHeader; - src += `const uint16_t PAGE_${page}_L = ${result.length};\n`; - src += `const uint8_t PAGE_${page}[] PROGMEM = {\n${array}\n};\n\n`; - console.info("Writing " + resultFile); - fs.writeFileSync(resultFile, src); - }); + html = adoptVersionAndRepo(html); + const originalLength = html.length; + html = await minify(html, "html-minify"); + const result = zlib.gzipSync(html, { level: zlib.constants.Z_BEST_COMPRESSION }); + console.info("Minified and compressed " + sourceFile + " from " + originalLength + " to " + result.length + " bytes"); + const array = hexdump(result); + let src = singleHeader; + src += `const uint16_t PAGE_${page}_L = ${result.length};\n`; + src += `const uint8_t PAGE_${page}[] PROGMEM = {\n${array}\n};\n\n`; + console.info("Writing " + resultFile); + fs.writeFileSync(resultFile, src); + }); } async function specToChunk(srcDir, s) { diff --git a/usermods/ADS1115_v2/usermod_ads1115.h b/usermods/ADS1115_v2/ADS1115_v2.cpp similarity index 98% rename from usermods/ADS1115_v2/usermod_ads1115.h rename to usermods/ADS1115_v2/ADS1115_v2.cpp index 5e2b4b270..bbf457f48 100644 --- a/usermods/ADS1115_v2/usermod_ads1115.h +++ b/usermods/ADS1115_v2/ADS1115_v2.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include #include @@ -252,4 +250,7 @@ class ADS1115Usermod : public Usermod { int16_t results = ads.getLastConversionResults(); readings[activeChannel] = ads.computeVolts(results); } -}; \ No newline at end of file +}; + +static ADS1115Usermod ads1115_v2; +REGISTER_USERMOD(ads1115_v2); \ No newline at end of file diff --git a/usermods/ADS1115_v2/library.json b/usermods/ADS1115_v2/library.json new file mode 100644 index 000000000..0b93c9351 --- /dev/null +++ b/usermods/ADS1115_v2/library.json @@ -0,0 +1,7 @@ +{ + "name:": "ADS1115_v2", + "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/ADS1115_v2/readme.md b/usermods/ADS1115_v2/readme.md index 44092bc8e..7397fc2e9 100644 --- a/usermods/ADS1115_v2/readme.md +++ b/usermods/ADS1115_v2/readme.md @@ -6,5 +6,5 @@ Configuration is performed via the Usermod menu. There are no parameters to set ## Installation -Add the build flag `-D USERMOD_ADS1115` to your platformio environment. -Uncomment libraries with comment `#For ADS1115 sensor uncomment following` +Add 'ADS1115' to `custom_usermods` in your platformio environment. + diff --git a/usermods/AHT10_v2/usermod_aht10.h b/usermods/AHT10_v2/AHT10_v2.cpp similarity index 98% rename from usermods/AHT10_v2/usermod_aht10.h rename to usermods/AHT10_v2/AHT10_v2.cpp index b5dc1841d..f88bee1da 100644 --- a/usermods/AHT10_v2/usermod_aht10.h +++ b/usermods/AHT10_v2/AHT10_v2.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include @@ -54,12 +52,6 @@ private: _lastTemperature = 0; } - ~UsermodAHT10() - { - delete _aht; - _aht = nullptr; - } - #ifndef WLED_DISABLE_MQTT void mqttInitialize() { @@ -322,6 +314,15 @@ public: _initDone = true; return configComplete; } + + ~UsermodAHT10() + { + delete _aht; + _aht = nullptr; + } }; -const char UsermodAHT10::_name[] PROGMEM = "AHTxx"; \ No newline at end of file +const char UsermodAHT10::_name[] PROGMEM = "AHTxx"; + +static UsermodAHT10 aht10_v2; +REGISTER_USERMOD(aht10_v2); \ No newline at end of file diff --git a/usermods/AHT10_v2/README.md b/usermods/AHT10_v2/README.md index 69fab4671..d84c1c6ad 100644 --- a/usermods/AHT10_v2/README.md +++ b/usermods/AHT10_v2/README.md @@ -22,15 +22,9 @@ Dependencies, These must be added under `lib_deps` in your `platform.ini` (or `p # Compiling -To enable, compile with `USERMOD_AHT10` defined (e.g. in `platformio_override.ini`) +To enable, add 'AHT10' to `custom_usermods` in your platformio encrionment (e.g. in `platformio_override.ini`) ```ini [env:aht10_example] extends = env:esp32dev -build_flags = - ${common.build_flags} ${esp32.build_flags} - -D USERMOD_AHT10 - ; -D USERMOD_AHT10_DEBUG ; -- add a debug status to the info modal -lib_deps = - ${esp32.lib_deps} - enjoyneering/AHT10@~1.1.0 +custom_usermods = ${env:esp32dev.custom_usermods} AHT10 ``` diff --git a/usermods/AHT10_v2/library.json b/usermods/AHT10_v2/library.json new file mode 100644 index 000000000..94a206c57 --- /dev/null +++ b/usermods/AHT10_v2/library.json @@ -0,0 +1,6 @@ +{ + "name:": "AHT10_v2", + "dependencies": { + "enjoyneering/AHT10":"~1.1.0" + } +} diff --git a/usermods/AHT10_v2/platformio_override.ini b/usermods/AHT10_v2/platformio_override.ini index 30240f222..74dcd659b 100644 --- a/usermods/AHT10_v2/platformio_override.ini +++ b/usermods/AHT10_v2/platformio_override.ini @@ -2,8 +2,4 @@ extends = env:esp32dev build_flags = ${common.build_flags} ${esp32.build_flags} - -D USERMOD_AHT10 ; -D USERMOD_AHT10_DEBUG ; -- add a debug status to the info modal -lib_deps = - ${esp32.lib_deps} - enjoyneering/AHT10@~1.1.0 \ No newline at end of file diff --git a/usermods/Analog_Clock/Analog_Clock.h b/usermods/Analog_Clock/Analog_Clock.cpp similarity index 99% rename from usermods/Analog_Clock/Analog_Clock.h rename to usermods/Analog_Clock/Analog_Clock.cpp index 9d82f7670..970ba7224 100644 --- a/usermods/Analog_Clock/Analog_Clock.h +++ b/usermods/Analog_Clock/Analog_Clock.cpp @@ -1,4 +1,3 @@ -#pragma once #include "wled.h" /* @@ -254,3 +253,7 @@ public: return USERMOD_ID_ANALOG_CLOCK; } }; + + +static AnalogClockUsermod analog_clock; +REGISTER_USERMOD(analog_clock); \ No newline at end of file diff --git a/usermods/Analog_Clock/library.json b/usermods/Analog_Clock/library.json new file mode 100644 index 000000000..4936950e9 --- /dev/null +++ b/usermods/Analog_Clock/library.json @@ -0,0 +1,3 @@ +{ + "name:": "Analog_Clock" +} \ No newline at end of file diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.cpp similarity index 99% rename from usermods/Animated_Staircase/Animated_Staircase.h rename to usermods/Animated_Staircase/Animated_Staircase.cpp index 54a9b3331..2d2d27cf4 100644 --- a/usermods/Animated_Staircase/Animated_Staircase.h +++ b/usermods/Animated_Staircase/Animated_Staircase.cpp @@ -7,7 +7,6 @@ * * See the accompanying README.md file for more info. */ -#pragma once #include "wled.h" class Animated_Staircase : public Usermod { @@ -562,3 +561,7 @@ const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEch const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm"; const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm"; const char Animated_Staircase::_togglePower[] PROGMEM = "toggle-on-off"; + + +static Animated_Staircase animated_staircase; +REGISTER_USERMOD(animated_staircase); \ No newline at end of file diff --git a/usermods/Animated_Staircase/README.md b/usermods/Animated_Staircase/README.md index 2ad66b5ae..c24a037e1 100644 --- a/usermods/Animated_Staircase/README.md +++ b/usermods/Animated_Staircase/README.md @@ -15,10 +15,9 @@ To include this usermod in your WLED setup, you have to be able to [compile WLED Before compiling, you have to make the following modifications: -Edit `usermods_list.cpp`: -1. Open `wled00/usermods_list.cpp` -2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file -3. add `UsermodManager::add(new Animated_Staircase());` to the end of the `void registerUsermods()` function. +Edit your environment in `platformio_override.ini` +1. Open `platformio_override.ini` +2. add `Animated_Staircase` to the `custom_usermods` line for your environment You can configure usermod using the Usermods settings page. Please enter GPIO pins for PIR or ultrasonic sensors (trigger and echo). diff --git a/usermods/Animated_Staircase/library.json b/usermods/Animated_Staircase/library.json new file mode 100644 index 000000000..626baa494 --- /dev/null +++ b/usermods/Animated_Staircase/library.json @@ -0,0 +1,3 @@ +{ + "name:": "Animated_Staircase" +} \ No newline at end of file diff --git a/usermods/BH1750_v2/usermod_bh1750.h b/usermods/BH1750_v2/BH1750_v2.cpp similarity index 98% rename from usermods/BH1750_v2/usermod_bh1750.h rename to usermods/BH1750_v2/BH1750_v2.cpp index 2a2bd4637..f033f39ed 100644 --- a/usermods/BH1750_v2/usermod_bh1750.h +++ b/usermods/BH1750_v2/BH1750_v2.cpp @@ -1,15 +1,13 @@ // force the compiler to show a warning to confirm that this file is included #warning **** Included USERMOD_BH1750 **** -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - #include "wled.h" #include +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + // the max frequency to check photoresistor, 10 seconds #ifndef USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL #define USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL 10000 @@ -250,3 +248,7 @@ const char Usermod_BH1750::_maxReadInterval[] PROGMEM = "max-read-interval-ms"; const char Usermod_BH1750::_minReadInterval[] PROGMEM = "min-read-interval-ms"; const char Usermod_BH1750::_HomeAssistantDiscovery[] PROGMEM = "HomeAssistantDiscoveryLux"; const char Usermod_BH1750::_offset[] PROGMEM = "offset-lx"; + + +static Usermod_BH1750 bh1750_v2; +REGISTER_USERMOD(bh1750_v2); \ No newline at end of file diff --git a/usermods/BH1750_v2/library.json b/usermods/BH1750_v2/library.json new file mode 100644 index 000000000..b7f006cc2 --- /dev/null +++ b/usermods/BH1750_v2/library.json @@ -0,0 +1,6 @@ +{ + "name:": "BH1750_v2", + "dependencies": { + "claws/BH1750":"^1.2.0" + } +} diff --git a/usermods/BH1750_v2/readme.md b/usermods/BH1750_v2/readme.md index 6e6c693d4..bba4eb712 100644 --- a/usermods/BH1750_v2/readme.md +++ b/usermods/BH1750_v2/readme.md @@ -6,22 +6,11 @@ The luminance is displayed in both the Info section of the web UI, as well as pu ## Dependencies - Libraries - `claws/BH1750 @^1.2.0` - - This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`). - Data is published over MQTT - make sure you've enabled the MQTT sync interface. ## Compilation -To enable, compile with `USERMOD_BH1750` defined (e.g. in `platformio_override.ini`) -```ini -[env:usermod_BH1750_d1_mini] -extends = env:d1_mini -build_flags = - ${common.build_flags_esp8266} - -D USERMOD_BH1750 -lib_deps = - ${esp8266.lib_deps} - claws/BH1750 @ ^1.2.0 -``` +To enable, compile with `BH1750` in `custom_usermods` (e.g. in `platformio_override.ini`) ### Configuration Options The following settings can be set at compile-time but are configurable on the usermod menu (except First Measurement time): diff --git a/usermods/BME280_v2/usermod_bme280.h b/usermods/BME280_v2/BME280_v2.cpp similarity index 96% rename from usermods/BME280_v2/usermod_bme280.h rename to usermods/BME280_v2/BME280_v2.cpp index 9168f4229..dd5859044 100644 --- a/usermods/BME280_v2/usermod_bme280.h +++ b/usermods/BME280_v2/BME280_v2.cpp @@ -1,17 +1,15 @@ // force the compiler to show a warning to confirm that this file is included #warning **** Included USERMOD_BME280 version 2.0 **** -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - #include "wled.h" #include #include // BME280 sensor #include // BME280 extended measurements +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + class UsermodBME280 : public Usermod { private: @@ -241,7 +239,7 @@ public: // from the UI and values read from sensor, then publish to broker if (temperature != lastTemperature || PublishAlways) { - publishMqtt("temperature", String(temperature, TemperatureDecimals).c_str()); + publishMqtt("temperature", String(temperature, (unsigned) TemperatureDecimals).c_str()); } lastTemperature = temperature; // Update last sensor temperature for next loop @@ -254,17 +252,17 @@ public: if (humidity != lastHumidity || PublishAlways) { - publishMqtt("humidity", String(humidity, HumidityDecimals).c_str()); + publishMqtt("humidity", String(humidity, (unsigned) HumidityDecimals).c_str()); } if (heatIndex != lastHeatIndex || PublishAlways) { - publishMqtt("heat_index", String(heatIndex, TemperatureDecimals).c_str()); + publishMqtt("heat_index", String(heatIndex, (unsigned) TemperatureDecimals).c_str()); } if (dewPoint != lastDewPoint || PublishAlways) { - publishMqtt("dew_point", String(dewPoint, TemperatureDecimals).c_str()); + publishMqtt("dew_point", String(dewPoint, (unsigned) TemperatureDecimals).c_str()); } lastHumidity = humidity; @@ -281,7 +279,7 @@ public: if (pressure != lastPressure || PublishAlways) { - publishMqtt("pressure", String(pressure, PressureDecimals).c_str()); + publishMqtt("pressure", String(pressure, (unsigned) PressureDecimals).c_str()); } lastPressure = pressure; @@ -479,3 +477,7 @@ public: const char UsermodBME280::_name[] PROGMEM = "BME280/BMP280"; const char UsermodBME280::_enabled[] PROGMEM = "enabled"; + + +static UsermodBME280 bme280_v2; +REGISTER_USERMOD(bme280_v2); \ No newline at end of file diff --git a/usermods/BME280_v2/README.md b/usermods/BME280_v2/README.md index a4fc229a3..0daea5825 100644 --- a/usermods/BME280_v2/README.md +++ b/usermods/BME280_v2/README.md @@ -22,7 +22,6 @@ Dependencies - Libraries - `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280)) - `Wire` - - These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`). - Data is published over MQTT - make sure you've enabled the MQTT sync interface. - This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else is listening to the serial TX pin or your board will get confused by log messages! @@ -40,17 +39,11 @@ Methods also exist to read the read/calculated values from other WLED modules th # Compiling -To enable, compile with `USERMOD_BME280` defined (e.g. in `platformio_override.ini`) +To enable, add `BME280_v2` to your `custom_usermods` (e.g. in `platformio_override.ini`) ```ini [env:usermod_bme280_d1_mini] extends = env:d1_mini -build_flags = - ${common.build_flags_esp8266} - -D USERMOD_BME280 -lib_deps = - ${esp8266.lib_deps} - BME280@~3.0.0 - Wire +custom_usermods = ${env:d1_mini.custom_usermods} BME280_v2 ``` diff --git a/usermods/BME280_v2/library.json b/usermods/BME280_v2/library.json new file mode 100644 index 000000000..7ae712583 --- /dev/null +++ b/usermods/BME280_v2/library.json @@ -0,0 +1,6 @@ +{ + "name:": "BME280_v2", + "dependencies": { + "finitespace/BME280":"~3.0.0" + } +} \ No newline at end of file diff --git a/usermods/BME68X_v2/usermod_bme68x.h b/usermods/BME68X_v2/BME68X_v2.cpp similarity index 99% rename from usermods/BME68X_v2/usermod_bme68x.h rename to usermods/BME68X_v2/BME68X_v2.cpp index aca24d0a2..081d03ff9 100644 --- a/usermods/BME68X_v2/usermod_bme68x.h +++ b/usermods/BME68X_v2/BME68X_v2.cpp @@ -6,7 +6,6 @@ * @date 19 Feb 2024 */ -#pragma once #warning ********************Included USERMOD_BME68X ******************** #define UMOD_DEVICE "ESP32" // NOTE - Set your hardware here @@ -1112,3 +1111,7 @@ void UsermodBME68X::saveState() { if (WLED_MQTT_CONNECTED) mqtt->publish(charbuffer, 0, false, contbuffer); } } + + +static UsermodBME68X bme68x_v2; +REGISTER_USERMOD(bme68x_v2); \ No newline at end of file diff --git a/usermods/BME68X_v2/README.md b/usermods/BME68X_v2/README.md index 72ae25a57..7e7a15113 100644 --- a/usermods/BME68X_v2/README.md +++ b/usermods/BME68X_v2/README.md @@ -118,23 +118,6 @@ Methods also exist to read the read/calculated values from other WLED modules th - getStabStatus(); - getRunInStatus(); - -## Compiling - -To enable, compile with `USERMOD_BME68X` defined (e.g. in `platformio_override.ini`) and add the `BSEC Software Library` to the lib_deps. - -``` -[env:esp32-BME680] -board = esp32dev -platform = ${esp32.platform} -platform_packages = ${esp32.platform_packages} -lib_deps = ${esp32.lib_deps} - boschsensortec/BSEC Software Library @ ^1.8.1492 ; USERMOD: BME680 -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} - -D USERMOD_BME68X ; USERMOD: BME680 -``` - ## Revision History ### Version 1.0.0 - First version of the BME68X_v user module diff --git a/usermods/BME68X_v2/library.json.disabled b/usermods/BME68X_v2/library.json.disabled new file mode 100644 index 000000000..6bd0bb9b2 --- /dev/null +++ b/usermods/BME68X_v2/library.json.disabled @@ -0,0 +1,7 @@ +{ + "name:": "BME68X_v2", + "build": { "libArchive": false}, + "dependencies": { + "boschsensortec/BSEC Software Library":"^1.8.1492" + } +} diff --git a/usermods/Battery/usermod_v2_Battery.h b/usermods/Battery/Battery.cpp similarity index 99% rename from usermods/Battery/usermod_v2_Battery.h rename to usermods/Battery/Battery.cpp index b36c5f4d6..5572f5502 100644 --- a/usermods/Battery/usermod_v2_Battery.h +++ b/usermods/Battery/Battery.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "battery_defaults.h" #include "UMBattery.h" @@ -857,3 +855,7 @@ const char UsermodBattery::_preset[] PROGMEM = "preset"; const char UsermodBattery::_duration[] PROGMEM = "duration"; const char UsermodBattery::_init[] PROGMEM = "init"; const char UsermodBattery::_haDiscovery[] PROGMEM = "HA-discovery"; + + +static UsermodBattery battery; +REGISTER_USERMOD(battery); \ No newline at end of file diff --git a/usermods/Battery/library.json b/usermods/Battery/library.json new file mode 100644 index 000000000..3f4774b87 --- /dev/null +++ b/usermods/Battery/library.json @@ -0,0 +1,3 @@ +{ + "name:": "Battery" +} \ No newline at end of file diff --git a/usermods/Battery/readme.md b/usermods/Battery/readme.md index c3d3d8bf4..0e203f3a2 100644 --- a/usermods/Battery/readme.md +++ b/usermods/Battery/readme.md @@ -23,9 +23,7 @@ Enables battery level monitoring of your project. ## 🎈 Installation -| **Option 1** | **Option 2** | -|--------------|--------------| -| In `wled00/my_config.h`
Add the line: `#define USERMOD_BATTERY`

[Example: my_config.h](assets/installation_my_config_h.png) | In `platformio_override.ini` (or `platformio.ini`)
Under: `build_flags =`, add the line: `-D USERMOD_BATTERY`

[Example: platformio_override.ini](assets/installation_platformio_override_ini.png) | +In `platformio_override.ini` (or `platformio.ini`)
Under: `custom_usermods =`, add the line: `Battery`

[Example: platformio_override.ini](assets/installation_platformio_override_ini.png) |

diff --git a/usermods/Cronixie/usermod_cronixie.h b/usermods/Cronixie/Cronixie.cpp similarity index 99% rename from usermods/Cronixie/usermod_cronixie.h rename to usermods/Cronixie/Cronixie.cpp index 671c5d134..05557de0f 100644 --- a/usermods/Cronixie/usermod_cronixie.h +++ b/usermods/Cronixie/Cronixie.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" class UsermodCronixie : public Usermod { @@ -299,4 +297,7 @@ class UsermodCronixie : public Usermod { { return USERMOD_ID_CRONIXIE; } -}; \ No newline at end of file +}; + +static UsermodCronixie cronixie; +REGISTER_USERMOD(cronixie); \ No newline at end of file diff --git a/usermods/Cronixie/library.json b/usermods/Cronixie/library.json new file mode 100644 index 000000000..d48327649 --- /dev/null +++ b/usermods/Cronixie/library.json @@ -0,0 +1,3 @@ +{ + "name:": "Cronixie" +} \ No newline at end of file diff --git a/usermods/Cronixie/readme.md b/usermods/Cronixie/readme.md index 1eeac8ed0..38efdbab5 100644 --- a/usermods/Cronixie/readme.md +++ b/usermods/Cronixie/readme.md @@ -4,5 +4,5 @@ This usermod supports driving the Cronixie M and L clock kits by Diamex. ## Installation -Compile and upload after adding `-D USERMOD_CRONIXIE` to `build_flags` of your PlatformIO environment. +Compile and upload after adding `Cronixie` to `custom_usermods` of your PlatformIO environment. Make sure the Auto Brightness Limiter is enabled at 420mA (!) and configure 60 WS281x LEDs. \ No newline at end of file diff --git a/usermods/DHT/usermod_dht.h b/usermods/DHT/DHT.cpp similarity index 98% rename from usermods/DHT/usermod_dht.h rename to usermods/DHT/DHT.cpp index 05a7267b5..2ed3dd0ac 100644 --- a/usermods/DHT/usermod_dht.h +++ b/usermods/DHT/DHT.cpp @@ -1,7 +1,5 @@ -#pragma once - #include "wled.h" -#ifndef WLED_ENABLE_MQTT +#ifdef WLED_DISABLE_MQTT #error "This user mod requires MQTT to be enabled." #endif @@ -245,3 +243,7 @@ class UsermodDHT : public Usermod { } }; + + +static UsermodDHT dht; +REGISTER_USERMOD(dht); \ No newline at end of file diff --git a/usermods/DHT/library.json b/usermods/DHT/library.json new file mode 100644 index 000000000..d61634e9f --- /dev/null +++ b/usermods/DHT/library.json @@ -0,0 +1,7 @@ +{ + "name:": "DHT", + "build": { "libArchive": false}, + "dependencies": { + "DHT_nonblocking":"https://github.com/alwynallan/DHT_nonblocking" + } +} diff --git a/usermods/DHT/platformio_override.ini b/usermods/DHT/platformio_override.ini index d192f0434..6ec2fb999 100644 --- a/usermods/DHT/platformio_override.ini +++ b/usermods/DHT/platformio_override.ini @@ -1,6 +1,5 @@ ; Options ; ------- -; USERMOD_DHT - define this to have this user mod included wled00\usermods_list.cpp ; USERMOD_DHT_DHTTYPE - DHT model: 11, 21, 22 for DHT11, DHT21, or DHT22, defaults to 22/DHT22 ; USERMOD_DHT_PIN - pin to which DTH is connected, defaults to Q2 pin on QuinLed Dig-Uno's board ; USERMOD_DHT_CELSIUS - define this to report temperatures in degrees celsious, otherwise fahrenheit will be reported @@ -11,13 +10,11 @@ [env:d1_mini_usermod_dht_C] extends = env:d1_mini -build_flags = ${env:d1_mini.build_flags} -D USERMOD_DHT -D USERMOD_DHT_CELSIUS -lib_deps = ${env:d1_mini.lib_deps} - https://github.com/alwynallan/DHT_nonblocking +custom_usermods = ${env:d1_mini.custom_usermods} DHT +build_flags = ${env:d1_mini.build_flags} -D USERMOD_DHT_CELSIUS [env:custom32_LEDPIN_16_usermod_dht_C] extends = env:custom32_LEDPIN_16 -build_flags = ${env:custom32_LEDPIN_16.build_flags} -D USERMOD_DHT -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS -lib_deps = ${env.lib_deps} - https://github.com/alwynallan/DHT_nonblocking +custom_usermods = ${env:custom32_LEDPIN_16.custom_usermods} DHT +build_flags = ${env:custom32_LEDPIN_16.build_flags} -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS diff --git a/usermods/DHT/readme.md b/usermods/DHT/readme.md index 6089ffbf8..9080b9b20 100644 --- a/usermods/DHT/readme.md +++ b/usermods/DHT/readme.md @@ -15,7 +15,6 @@ Copy the example `platformio_override.ini` to the root directory. This file sho ### Define Your Options -* `USERMOD_DHT` - define this to include this user mod wled00\usermods_list.cpp * `USERMOD_DHT_DHTTYPE` - DHT model: 11, 21, 22 for DHT11, DHT21, or DHT22, defaults to 22/DHT22 * `USERMOD_DHT_PIN` - pin to which DTH is connected, defaults to Q2 pin on QuinLed Dig-Uno's board * `USERMOD_DHT_CELSIUS` - define this to report temperatures in degrees Celsius, otherwise Fahrenheit will be reported diff --git a/usermods/EXAMPLE/library.json b/usermods/EXAMPLE/library.json new file mode 100644 index 000000000..276aba493 --- /dev/null +++ b/usermods/EXAMPLE/library.json @@ -0,0 +1,4 @@ +{ + "name:": "EXAMPLE", + "dependencies": {} +} diff --git a/usermods/EXAMPLE_v2/readme.md b/usermods/EXAMPLE/readme.md similarity index 64% rename from usermods/EXAMPLE_v2/readme.md rename to usermods/EXAMPLE/readme.md index 8917a1fba..ee8a2282a 100644 --- a/usermods/EXAMPLE_v2/readme.md +++ b/usermods/EXAMPLE/readme.md @@ -4,7 +4,6 @@ In this usermod file you can find the documentation on how to take advantage of ## Installation -Copy `usermod_v2_example.h` to the wled00 directory. -Uncomment the corresponding lines in `usermods_list.cpp` and compile! +Add `EXAMPLE` to `custom_usermods` in your PlatformIO environment and compile! _(You shouldn't need to actually install this, it does nothing useful)_ diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE/usermod_v2_example.cpp similarity index 99% rename from usermods/EXAMPLE_v2/usermod_v2_example.h rename to usermods/EXAMPLE/usermod_v2_example.cpp index 4c07ad17b..fc50833ee 100644 --- a/usermods/EXAMPLE_v2/usermod_v2_example.h +++ b/usermods/EXAMPLE/usermod_v2_example.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" /* @@ -404,3 +402,6 @@ void MyExampleUsermod::publishMqtt(const char* state, bool retain) } #endif } + +static MyExampleUsermod example_usermod; +REGISTER_USERMOD(example_usermod); diff --git a/usermods/EleksTube_IPS/usermod_elekstube_ips.h b/usermods/EleksTube_IPS/EleksTube_IPS.cpp similarity index 98% rename from usermods/EleksTube_IPS/usermod_elekstube_ips.h rename to usermods/EleksTube_IPS/EleksTube_IPS.cpp index 0f7d92e7e..e8637b0fe 100644 --- a/usermods/EleksTube_IPS/usermod_elekstube_ips.h +++ b/usermods/EleksTube_IPS/EleksTube_IPS.cpp @@ -1,4 +1,3 @@ -#pragma once #include "TFTs.h" #include "wled.h" @@ -156,3 +155,7 @@ class ElekstubeIPSUsermod : public Usermod { const char ElekstubeIPSUsermod::_name[] PROGMEM = "EleksTubeIPS"; const char ElekstubeIPSUsermod::_tubeSeg[] PROGMEM = "tubeSegment"; const char ElekstubeIPSUsermod::_digitOffset[] PROGMEM = "digitOffset"; + + +static ElekstubeIPSUsermod elekstube_ips; +REGISTER_USERMOD(elekstube_ips); \ No newline at end of file diff --git a/usermods/EleksTube_IPS/library.json.disabled b/usermods/EleksTube_IPS/library.json.disabled new file mode 100644 index 000000000..eddd12b88 --- /dev/null +++ b/usermods/EleksTube_IPS/library.json.disabled @@ -0,0 +1,7 @@ +{ + "name:": "EleksTube_IPS", + "dependencies": { + "TFT_eSPI" : "2.5.33" + } +} +# Seems to add 300kb to the RAM requirement??? diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp b/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp index 823ad7472..d51ddb57c 100644 --- a/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp +++ b/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp @@ -1,11 +1,12 @@ -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - #include "wled.h" #include #include // from https://github.com/olikraus/u8g2/ #include //Dallastemperature sensor + +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + //The SCL and SDA pins are defined here. //Lolin32 boards use SCL=5 SDA=4 #define U8X8_PIN_SCL 5 diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp b/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp index 29a4332db..ce3c659e8 100644 --- a/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp +++ b/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp @@ -1,13 +1,13 @@ -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - #include "wled.h" #include #include // from https://github.com/olikraus/u8g2/ #include #include //BME280 sensor +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + void UpdateBME280Data(); #define Celsius // Show temperature measurement in Celsius otherwise is in Fahrenheit diff --git a/usermods/Fix_unreachable_netservices_v2/library.json b/usermods/Fix_unreachable_netservices_v2/library.json new file mode 100644 index 000000000..68b318184 --- /dev/null +++ b/usermods/Fix_unreachable_netservices_v2/library.json @@ -0,0 +1,4 @@ +{ + "name:": "Fix_unreachable_netservices_v2", + "platforms": ["espressif8266"] +} diff --git a/usermods/Fix_unreachable_netservices_v2/readme.md b/usermods/Fix_unreachable_netservices_v2/readme.md index 07d64bc67..9f3889ebb 100644 --- a/usermods/Fix_unreachable_netservices_v2/readme.md +++ b/usermods/Fix_unreachable_netservices_v2/readme.md @@ -30,41 +30,6 @@ The usermod supports the following state changes: ## Installation -1. Copy the file `usermod_Fix_unreachable_netservices.h` to the `wled00` directory. -2. Register the usermod by adding `#include "usermod_Fix_unreachable_netservices.h"` in the top and `registerUsermod(new FixUnreachableNetServices());` in the bottom of `usermods_list.cpp`. - -Example **usermods_list.cpp**: - -```cpp -#include "wled.h" -/* - * Register your v2 usermods here! - * (for v1 usermods using just usermod.cpp, you can ignore this file) - */ - -/* - * Add/uncomment your usermod filename here (and once more below) - * || || || - * \/ \/ \/ - */ -//#include "usermod_v2_example.h" -//#include "usermod_temperature.h" -//#include "usermod_v2_empty.h" -#include "usermod_Fix_unreachable_netservices.h" - -void registerUsermods() -{ - /* - * Add your usermod class name here - * || || || - * \/ \/ \/ - */ - //UsermodManager::add(new MyExampleUsermod()); - //UsermodManager::add(new UsermodTemperature()); - //UsermodManager::add(new UsermodRenameMe()); - UsermodManager::add(new FixUnreachableNetServices()); - -} -``` +1. Add `Fix_unreachable_netservices` to `custom_usermods` in your PlatformIO environment. Hopefully I can help someone with that - @gegu diff --git a/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.h b/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp similarity index 97% rename from usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.h rename to usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp index d3a00ac60..7fb8e9798 100644 --- a/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.h +++ b/usermods/Fix_unreachable_netservices_v2/usermod_Fix_unreachable_netservices.cpp @@ -1,12 +1,4 @@ -#pragma once - #include "wled.h" -#if defined(ESP32) -#warning "Usermod FixUnreachableNetServices works only with ESP8266 builds" -class FixUnreachableNetServices : public Usermod -{ -}; -#endif #if defined(ESP8266) #include @@ -168,4 +160,11 @@ Delay @@ -210,12 +208,6 @@ private: } } - ~UsermodINA226() - { - delete _ina226; - _ina226 = nullptr; - } - #ifndef WLED_DISABLE_MQTT void mqttInitialize() { @@ -551,6 +543,17 @@ public: _initDone = true; return configComplete; } + + ~UsermodINA226() + { + delete _ina226; + _ina226 = nullptr; + } + }; const char UsermodINA226::_name[] PROGMEM = "INA226"; + + +static UsermodINA226 ina226_v2; +REGISTER_USERMOD(ina226_v2); \ No newline at end of file diff --git a/usermods/INA226_v2/README.md b/usermods/INA226_v2/README.md index b1e691618..dfa9fc003 100644 --- a/usermods/INA226_v2/README.md +++ b/usermods/INA226_v2/README.md @@ -22,13 +22,6 @@ The following settings can be configured in the Usermod Menu: - **MqttPublishAlways**: Publish always, regardless if there is a change. - **MqttHomeAssistantDiscovery**: Enable Home Assistant discovery. -## Dependencies - -These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`). - -- Libraries - - `wollewald/INA226_WE@~1.2.9` (by [wollewald](https://registry.platformio.org/libraries/wollewald/INA226_WE)) - - `Wire` ## Understanding Samples and Conversion Times @@ -62,16 +55,12 @@ For detailed programming information and register configurations, refer to the [ ## Compiling -To enable, compile with `USERMOD_INA226` defined (e.g. in `platformio_override.ini`). +To enable, compile with `INA226` in `custom_usermods` (e.g. in `platformio_override.ini`). ```ini [env:ina226_example] extends = env:esp32dev -build_flags = - ${common.build_flags} ${esp32.build_flags} - -D USERMOD_INA226 +custom_usermods = ${env:esp32dev.custom_usermods} INA226 +build_flags = ${env:esp32dev.build_flags} ; -D USERMOD_INA226_DEBUG ; -- add a debug status to the info modal -lib_deps = - ${esp32.lib_deps} - wollewald/INA226_WE@~1.2.9 ``` \ No newline at end of file diff --git a/usermods/INA226_v2/library.json b/usermods/INA226_v2/library.json new file mode 100644 index 000000000..91a735fe7 --- /dev/null +++ b/usermods/INA226_v2/library.json @@ -0,0 +1,6 @@ +{ + "name:": "INA226_v2", + "dependencies": { + "wollewald/INA226_WE":"~1.2.9" + } +} diff --git a/usermods/INA226_v2/platformio_override.ini b/usermods/INA226_v2/platformio_override.ini index 885b2dd1e..9968cbf72 100644 --- a/usermods/INA226_v2/platformio_override.ini +++ b/usermods/INA226_v2/platformio_override.ini @@ -1,9 +1,6 @@ [env:ina226_example] extends = env:esp32dev +custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2 build_flags = - ${common.build_flags} ${esp32.build_flags} - -D USERMOD_INA226 + ${env:esp32dev.build_flags} ; -D USERMOD_INA226_DEBUG ; -- add a debug status to the info modal -lib_deps = - ${esp32.lib_deps} - wollewald/INA226_WE@~1.2.9 \ No newline at end of file diff --git a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h b/usermods/Internal_Temperature_v2/Internal_Temperature_v2.cpp similarity index 98% rename from usermods/Internal_Temperature_v2/usermod_internal_temperature.h rename to usermods/Internal_Temperature_v2/Internal_Temperature_v2.cpp index 6d4d4577c..7c30985ee 100644 --- a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h +++ b/usermods/Internal_Temperature_v2/Internal_Temperature_v2.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" class InternalTemperatureUsermod : public Usermod @@ -193,4 +191,7 @@ void InternalTemperatureUsermod::publishMqtt(const char *state, bool retain) mqtt->publish(subuf, 0, retain, state); } #endif -} \ No newline at end of file +} + +static InternalTemperatureUsermod internal_temperature_v2; +REGISTER_USERMOD(internal_temperature_v2); \ No newline at end of file diff --git a/usermods/Internal_Temperature_v2/library.json b/usermods/Internal_Temperature_v2/library.json new file mode 100644 index 000000000..6c1652380 --- /dev/null +++ b/usermods/Internal_Temperature_v2/library.json @@ -0,0 +1,3 @@ +{ + "name:": "Internal_Temperature_v2" +} \ No newline at end of file diff --git a/usermods/Internal_Temperature_v2/readme.md b/usermods/Internal_Temperature_v2/readme.md index d574f3abf..68bac8b02 100644 --- a/usermods/Internal_Temperature_v2/readme.md +++ b/usermods/Internal_Temperature_v2/readme.md @@ -23,8 +23,7 @@ ## Installation -- Add a build flag `-D USERMOD_INTERNAL_TEMPERATURE` to your `platformio.ini` (or `platformio_override.ini`). - +- Add `Internal_Temperature` to `custom_usermods` in your `platformio.ini` (or `platformio_override.ini`). ## 📝 Change Log diff --git a/usermods/LD2410_v2/usermod_ld2410.h b/usermods/LD2410_v2/LD2410_v2.cpp similarity index 98% rename from usermods/LD2410_v2/usermod_ld2410.h rename to usermods/LD2410_v2/LD2410_v2.cpp index 4d96b32ff..095da12f2 100644 --- a/usermods/LD2410_v2/usermod_ld2410.h +++ b/usermods/LD2410_v2/LD2410_v2.cpp @@ -1,14 +1,10 @@ -#warning **** Included USERMOD_LD2410 **** - -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - #include "wled.h" #include +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + class LD2410Usermod : public Usermod { private: @@ -235,3 +231,7 @@ void LD2410Usermod::publishMqtt(const char* topic, const char* state, bool retai } #endif } + + +static LD2410Usermod ld2410_v2; +REGISTER_USERMOD(ld2410_v2); \ No newline at end of file diff --git a/usermods/LD2410_v2/library.json b/usermods/LD2410_v2/library.json new file mode 100644 index 000000000..205bb8220 --- /dev/null +++ b/usermods/LD2410_v2/library.json @@ -0,0 +1,6 @@ +{ + "name:": "LD2410_v2", + "dependencies": { + "ncmreynolds/ld2410":"^0.1.3" + } +} \ No newline at end of file diff --git a/usermods/LD2410_v2/readme.md b/usermods/LD2410_v2/readme.md index 40463d4b0..ea85ab820 100644 --- a/usermods/LD2410_v2/readme.md +++ b/usermods/LD2410_v2/readme.md @@ -10,21 +10,15 @@ The movement and presence state are displayed in both the Info section of the we ## Dependencies - Libraries - `ncmreynolds/ld2410@^0.1.3` - - This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`). - Data is published over MQTT - make sure you've enabled the MQTT sync interface. ## Compilation -To enable, compile with `USERMOD_LD2410` defined (e.g. in `platformio_override.ini`) +To enable, compile with `LD2140` in `custom_usermods` (e.g. in `platformio_override.ini`) ```ini [env:usermod_USERMOD_LD2410_esp32dev] extends = env:esp32dev -build_flags = - ${common.build_flags_esp32} - -D USERMOD_LD2410 -lib_deps = - ${esp32.lib_deps} - ncmreynolds/ld2410@^0.1.3 +custom_usermods = ${env:esp32dev.custom_usermods} LD2140 ``` ### Configuration Options diff --git a/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h b/usermods/LDR_Dusk_Dawn_v2/LDR_Dusk_Dawn_v2.cpp similarity index 98% rename from usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h rename to usermods/LDR_Dusk_Dawn_v2/LDR_Dusk_Dawn_v2.cpp index 03f4c078a..9c5c835e9 100644 --- a/usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h +++ b/usermods/LDR_Dusk_Dawn_v2/LDR_Dusk_Dawn_v2.cpp @@ -1,4 +1,3 @@ -#pragma once #include "wled.h" #ifndef ARDUINO_ARCH_ESP32 @@ -151,3 +150,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod { }; const char LDR_Dusk_Dawn_v2::_name[] PROGMEM = "LDR_Dusk_Dawn_v2"; + + +static LDR_Dusk_Dawn_v2 ldr_dusk_dawn_v2; +REGISTER_USERMOD(ldr_dusk_dawn_v2); \ No newline at end of file diff --git a/usermods/LDR_Dusk_Dawn_v2/README.md b/usermods/LDR_Dusk_Dawn_v2/README.md index 5e33518a9..8fe86a369 100644 --- a/usermods/LDR_Dusk_Dawn_v2/README.md +++ b/usermods/LDR_Dusk_Dawn_v2/README.md @@ -2,13 +2,14 @@ This usermod will obtain readings from a Light Dependent Resistor (LDR) and will turn on/off specific presets based on those readings. This is useful for exterior lighting situations where you want the lights to only be on when it is dark out. # Installation -Add "-D USERMOD_LDR_DUSK_DAWN" to your platformio.ini [common] build_flags and build. +Add "LDR_Dusk_Dawn" to your platformio.ini environment's custom_usermods and build. Example: ``` -[common] -build_flags = - -D USERMOD_LDR_DUSK_DAWN # Enable LDR Dusk Dawn Usermod +[env:usermod_LDR_Dusk_Dawn_esp32dev] +extends = env:esp32dev +custom_usermods = ${env:esp32dev.custom_usermods} + LDR_Dusk_Dawn # Enable LDR Dusk Dawn Usermod ``` # Usermod Settings diff --git a/usermods/LDR_Dusk_Dawn_v2/library.json b/usermods/LDR_Dusk_Dawn_v2/library.json new file mode 100644 index 000000000..bb57dbd2a --- /dev/null +++ b/usermods/LDR_Dusk_Dawn_v2/library.json @@ -0,0 +1,3 @@ +{ + "name:": "LDR_Dusk_Dawn_v2" +} \ No newline at end of file diff --git a/usermods/MAX17048_v2/usermod_max17048.h b/usermods/MAX17048_v2/MAX17048_v2.cpp similarity index 99% rename from usermods/MAX17048_v2/usermod_max17048.h rename to usermods/MAX17048_v2/MAX17048_v2.cpp index c3a2664ab..c284bca7f 100644 --- a/usermods/MAX17048_v2/usermod_max17048.h +++ b/usermods/MAX17048_v2/MAX17048_v2.cpp @@ -1,8 +1,6 @@ // force the compiler to show a warning to confirm that this file is included #warning **** Included USERMOD_MAX17048 V2.0 **** -#pragma once - #include "wled.h" #include "Adafruit_MAX1704X.h" @@ -279,3 +277,7 @@ const char Usermod_MAX17048::_enabled[] PROGMEM = "enabled"; const char Usermod_MAX17048::_maxReadInterval[] PROGMEM = "max-read-interval-ms"; const char Usermod_MAX17048::_minReadInterval[] PROGMEM = "min-read-interval-ms"; const char Usermod_MAX17048::_HomeAssistantDiscovery[] PROGMEM = "HomeAssistantDiscovery"; + + +static Usermod_MAX17048 max17048_v2; +REGISTER_USERMOD(max17048_v2); \ No newline at end of file diff --git a/usermods/MAX17048_v2/library.json.disabled b/usermods/MAX17048_v2/library.json.disabled new file mode 100644 index 000000000..03b9acd9f --- /dev/null +++ b/usermods/MAX17048_v2/library.json.disabled @@ -0,0 +1,7 @@ +{ + "name:": "MAX17048_v2", + "build": { "libArchive": false}, + "dependencies": { + "Adafruit_MAX1704X":"https://github.com/adafruit/Adafruit_MAX1704X#1.0.2" + } +} diff --git a/usermods/MY9291/usermode_MY9291.h b/usermods/MY9291/MY9291.cpp similarity index 94% rename from usermods/MY9291/usermode_MY9291.h rename to usermods/MY9291/MY9291.cpp index 66bbc34cb..3881ffd07 100644 --- a/usermods/MY9291/usermode_MY9291.h +++ b/usermods/MY9291/MY9291.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "MY92xx.h" @@ -42,4 +40,7 @@ class MY9291Usermod : public Usermod { uint16_t getId() { return USERMOD_ID_MY9291; } -}; \ No newline at end of file +}; + +static MY9291Usermod my9291; +REGISTER_USERMOD(my9291); \ No newline at end of file diff --git a/usermods/MY9291/library.json b/usermods/MY9291/library.json new file mode 100644 index 000000000..96e0bbf93 --- /dev/null +++ b/usermods/MY9291/library.json @@ -0,0 +1,4 @@ +{ + "name:": "MY9291", + "platforms": ["espressif8266"] +} \ No newline at end of file diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp similarity index 96% rename from usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h rename to usermods/PIR_sensor_switch/PIR_sensor_switch.cpp index a61d05f33..6f09ce5be 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/PIR_sensor_switch.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #ifndef PIR_SENSOR_PIN @@ -571,3 +569,7 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root) // use "return !top["newestParameter"].isNull();" when updating Usermod with new features return !(pins.isNull() || pins.size() != PIR_SENSOR_MAX_SENSORS); } + + +static PIRsensorSwitch pir_sensor_switch; +REGISTER_USERMOD(pir_sensor_switch); \ No newline at end of file diff --git a/usermods/PIR_sensor_switch/library.json b/usermods/PIR_sensor_switch/library.json new file mode 100644 index 000000000..0ee7e18b5 --- /dev/null +++ b/usermods/PIR_sensor_switch/library.json @@ -0,0 +1,3 @@ +{ + "name:": "PIR_sensor_switch" +} \ No newline at end of file diff --git a/usermods/PWM_fan/usermod_PWM_fan.h b/usermods/PWM_fan/PWM_fan.cpp similarity index 98% rename from usermods/PWM_fan/usermod_PWM_fan.h rename to usermods/PWM_fan/PWM_fan.cpp index c3ef24fe4..a0939f085 100644 --- a/usermods/PWM_fan/usermod_PWM_fan.h +++ b/usermods/PWM_fan/PWM_fan.cpp @@ -1,10 +1,14 @@ -#pragma once +#include "wled.h" -#if !defined(USERMOD_DALLASTEMPERATURE) && !defined(USERMOD_SHT) +#if defined(USERMOD_DALLASTEMPERATURE) +#include "UsermodTemperature.h" +#elif defined(USERMOD_SHT) +#include "ShtUsermod.h" +#else #error The "PWM fan" usermod requires "Dallas Temeprature" or "SHT" usermod to function properly. #endif -#include "wled.h" + // PWM & tacho code curtesy of @KlausMu // https://github.com/KlausMu/esp32-fan-controller/tree/main/src @@ -397,3 +401,7 @@ const char PWMFanUsermod::_maxPWMValuePct[] PROGMEM = "max-PWM-percent"; const char PWMFanUsermod::_IRQperRotation[] PROGMEM = "IRQs-per-rotation"; const char PWMFanUsermod::_speed[] PROGMEM = "speed"; const char PWMFanUsermod::_lock[] PROGMEM = "lock"; + + +static PWMFanUsermod pwm_fan; +REGISTER_USERMOD(pwm_fan); \ No newline at end of file diff --git a/usermods/PWM_fan/library.json b/usermods/PWM_fan/library.json new file mode 100644 index 000000000..a0e53b21f --- /dev/null +++ b/usermods/PWM_fan/library.json @@ -0,0 +1,6 @@ +{ + "name:": "PWM_fan", + "build": { + "extraScript": "setup_deps.py" + } +} \ No newline at end of file diff --git a/usermods/PWM_fan/readme.md b/usermods/PWM_fan/readme.md index 6a44acf3b..9fecaabf2 100644 --- a/usermods/PWM_fan/readme.md +++ b/usermods/PWM_fan/readme.md @@ -11,8 +11,8 @@ If the _tachometer_ is supported, the current speed (in RPM) will be displayed o ## Installation -Add the compile-time option `-D USERMOD_PWM_FAN` to your `platformio.ini` (or `platformio_override.ini`) or use `#define USERMOD_PWM_FAN` in `myconfig.h`. -You will also need `-D USERMOD_DALLASTEMPERATURE`. +Add the `PWM_fan` to `custom_usermods` in your `platformio.ini` (or `platformio_override.ini`) +You will also need `Temperature` or `sht`. ### Define Your Options diff --git a/usermods/PWM_fan/setup_deps.py b/usermods/PWM_fan/setup_deps.py new file mode 100644 index 000000000..2f76ba857 --- /dev/null +++ b/usermods/PWM_fan/setup_deps.py @@ -0,0 +1,12 @@ +Import('env') + + +usermods = env.GetProjectOption("custom_usermods","").split() +# Check for dependencies +if "Temperature" in usermods: + env.Append(CPPDEFINES=[("USERMOD_DALLASTEMPERATURE")]) +elif "sht" in usermods: + env.Append(CPPDEFINES=[("USERMOD_SHT")]) +else: + raise RuntimeError("PWM_fan usermod requires Temperature or sht to be enabled") + diff --git a/usermods/RTC/usermod_rtc.h b/usermods/RTC/RTC.cpp similarity index 96% rename from usermods/RTC/usermod_rtc.h rename to usermods/RTC/RTC.cpp index 42965e3af..2b9c3b4f7 100644 --- a/usermods/RTC/usermod_rtc.h +++ b/usermods/RTC/RTC.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "src/dependencies/time/DS1307RTC.h" #include "wled.h" @@ -48,4 +46,7 @@ class RTCUsermod : public Usermod { { return USERMOD_ID_RTC; } -}; \ No newline at end of file +}; + +static RTCUsermod rtc; +REGISTER_USERMOD(rtc); \ No newline at end of file diff --git a/usermods/RTC/library.json b/usermods/RTC/library.json new file mode 100644 index 000000000..e0c527d2c --- /dev/null +++ b/usermods/RTC/library.json @@ -0,0 +1,3 @@ +{ + "name:": "RTC" +} \ No newline at end of file diff --git a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h b/usermods/SN_Photoresistor/SN_Photoresistor.cpp similarity index 98% rename from usermods/SN_Photoresistor/usermod_sn_photoresistor.h rename to usermods/SN_Photoresistor/SN_Photoresistor.cpp index 45cdb66ad..97f865a97 100644 --- a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h +++ b/usermods/SN_Photoresistor/SN_Photoresistor.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" //Pin defaults for QuinLed Dig-Uno (A0) @@ -210,3 +208,7 @@ const char Usermod_SN_Photoresistor::_referenceVoltage[] PROGMEM = "supplied-vol const char Usermod_SN_Photoresistor::_resistorValue[] PROGMEM = "resistor-value"; const char Usermod_SN_Photoresistor::_adcPrecision[] PROGMEM = "adc-precision"; const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset"; + + +static Usermod_SN_Photoresistor sn_photoresistor; +REGISTER_USERMOD(sn_photoresistor); \ No newline at end of file diff --git a/usermods/SN_Photoresistor/library.json b/usermods/SN_Photoresistor/library.json new file mode 100644 index 000000000..7cac93f8d --- /dev/null +++ b/usermods/SN_Photoresistor/library.json @@ -0,0 +1,3 @@ +{ + "name:": "SN_Photoresistor" +} \ No newline at end of file diff --git a/usermods/ST7789_display/README.md b/usermods/ST7789_display/README.md index ebaae4922..7dd3b599e 100644 --- a/usermods/ST7789_display/README.md +++ b/usermods/ST7789_display/README.md @@ -27,19 +27,6 @@ This usermod enables display of the following: ### Platformio.ini changes -In the `platformio.ini` file, uncomment the `TFT_eSPI` line within the [common] section, under `lib_deps`: - -```ini -# platformio.ini -... -[common] -... -lib_deps = - ... - #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line - #TFT_eSPI -... -``` In the `platformio.ini` file, you must change the environment setup to build for just the esp32dev platform as follows: diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.cpp similarity index 99% rename from usermods/ST7789_display/ST7789_display.h rename to usermods/ST7789_display/ST7789_display.cpp index 65f4cae5d..c596baecc 100644 --- a/usermods/ST7789_display/ST7789_display.h +++ b/usermods/ST7789_display/ST7789_display.cpp @@ -1,8 +1,6 @@ // Credits to @mrVanboy, @gwaland and my dearest friend @westward // Also for @spiff72 for usermod TTGO-T-Display // 210217 -#pragma once - #include "wled.h" #include #include @@ -410,4 +408,7 @@ class St7789DisplayUsermod : public Usermod { //More methods can be added in the future, this example will then be extended. //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! -}; \ No newline at end of file +}; + +static name. st7789_display; +REGISTER_USERMOD(st7789_display); \ No newline at end of file diff --git a/usermods/ST7789_display/library.json.disabled b/usermods/ST7789_display/library.json.disabled new file mode 100644 index 000000000..abcd4635c --- /dev/null +++ b/usermods/ST7789_display/library.json.disabled @@ -0,0 +1,3 @@ +{ + "name:": "ST7789_display" +} \ No newline at end of file diff --git a/usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h b/usermods/Si7021_MQTT_HA/Si7021_MQTT_HA.cpp similarity index 98% rename from usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h rename to usermods/Si7021_MQTT_HA/Si7021_MQTT_HA.cpp index 9f027382d..7845658ad 100644 --- a/usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h +++ b/usermods/Si7021_MQTT_HA/Si7021_MQTT_HA.cpp @@ -1,9 +1,3 @@ -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - // this is remixed from usermod_v2_SensorsToMqtt.h (sensors_to_mqtt usermod) // and usermod_multi_relay.h (multi_relay usermod) @@ -11,7 +5,11 @@ #include #include // EnvironmentCalculations::HeatIndex(), ::DewPoint(), ::AbsoluteHumidity() -Adafruit_Si7021 si7021; +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + +static Adafruit_Si7021 si7021; class Si7021_MQTT_HA : public Usermod { @@ -229,3 +227,7 @@ const char Si7021_MQTT_HA::_name[] PROGMEM = "Si7021 MQTT (Hom const char Si7021_MQTT_HA::_enabled[] PROGMEM = "enabled"; const char Si7021_MQTT_HA::_sendAdditionalSensors[] PROGMEM = "Send Dew Point, Abs. Humidity and Heat Index"; const char Si7021_MQTT_HA::_haAutoDiscovery[] PROGMEM = "Home Assistant MQTT Auto-Discovery"; + + +static Si7021_MQTT_HA si7021_mqtt_ha; +REGISTER_USERMOD(si7021_mqtt_ha); \ No newline at end of file diff --git a/usermods/Si7021_MQTT_HA/library.json b/usermods/Si7021_MQTT_HA/library.json new file mode 100644 index 000000000..5d7aa300a --- /dev/null +++ b/usermods/Si7021_MQTT_HA/library.json @@ -0,0 +1,7 @@ +{ + "name:": "Si7021_MQTT_HA", + "dependencies": { + "finitespace/BME280":"3.0.0", + "adafruit/Adafruit Si7021 Library" : "1.5.3" + } +} \ No newline at end of file diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/Temperature.cpp similarity index 78% rename from usermods/Temperature/usermod_temperature.h rename to usermods/Temperature/Temperature.cpp index 178bc05a0..a2e0ea91d 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/Temperature.cpp @@ -1,114 +1,7 @@ -#pragma once - -#include "wled.h" -#include "OneWire.h" - -//Pin defaults for QuinLed Dig-Uno if not overriden -#ifndef TEMPERATURE_PIN - #ifdef ARDUINO_ARCH_ESP32 - #define TEMPERATURE_PIN 18 - #else //ESP8266 boards - #define TEMPERATURE_PIN 14 - #endif -#endif - -// the frequency to check temperature, 1 minute -#ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL -#define USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL 60000 -#endif +#include "UsermodTemperature.h" static uint16_t mode_temperature(); -class UsermodTemperature : public Usermod { - - private: - - bool initDone = false; - OneWire *oneWire; - // GPIO pin used for sensor (with a default compile-time fallback) - int8_t temperaturePin = TEMPERATURE_PIN; - // measurement unit (true==°C, false==°F) - bool degC = true; - // using parasite power on the sensor - bool parasite = false; - int8_t parasitePin = -1; - // how often do we read from sensor? - unsigned long readingInterval = USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL; - // set last reading as "40 sec before boot", so first reading is taken after 20 sec - unsigned long lastMeasurement = UINT32_MAX - USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL; - // last time requestTemperatures was called - // used to determine when we can read the sensors temperature - // we have to wait at least 93.75 ms after requestTemperatures() is called - unsigned long lastTemperaturesRequest; - float temperature; - // indicates requestTemperatures has been called but the sensor measurement is not complete - bool waitingForConversion = false; - // flag set at startup if DS18B20 sensor not found, avoids trying to keep getting - // temperature if flashed to a board without a sensor attached - byte sensorFound; - - bool enabled = true; - - bool HApublished = false; - int16_t idx = -1; // Domoticz virtual sensor idx - - // strings to reduce flash memory usage (used more than twice) - static const char _name[]; - static const char _enabled[]; - static const char _readInterval[]; - static const char _parasite[]; - static const char _parasitePin[]; - static const char _domoticzIDX[]; - static const char _sensor[]; - static const char _temperature[]; - static const char _Temperature[]; - static const char _data_fx[]; - - //Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013 - float readDallas(); - void requestTemperatures(); - void readTemperature(); - bool findSensor(); -#ifndef WLED_DISABLE_MQTT - void publishHomeAssistantAutodiscovery(); -#endif - - static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid UsermodManager::lookup(USERMOD_ID_TEMPERATURE); - - public: - - UsermodTemperature() { _instance = this; } - static UsermodTemperature *getInstance() { return UsermodTemperature::_instance; } - - /* - * API calls te enable data exchange between WLED modules - */ - inline float getTemperatureC() { return temperature; } - inline float getTemperatureF() { return temperature * 1.8f + 32.0f; } - float getTemperature(); - const char *getTemperatureUnit(); - uint16_t getId() override { return USERMOD_ID_TEMPERATURE; } - - void setup() override; - void loop() override; - //void connected() override; -#ifndef WLED_DISABLE_MQTT - void onMqttConnect(bool sessionPresent) override; -#endif - //void onUpdateBegin(bool init) override; - - //bool handleButton(uint8_t b) override; - //void handleOverlayDraw() override; - - void addToJsonInfo(JsonObject& root) override; - //void addToJsonState(JsonObject &root) override; - //void readFromJsonState(JsonObject &root) override; - void addToConfig(JsonObject &root) override; - bool readFromConfig(JsonObject &root) override; - - void appendConfigData() override; -}; - //Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013 float UsermodTemperature::readDallas() { byte data[9]; @@ -471,3 +364,7 @@ static uint16_t mode_temperature() { SEGMENT.fill(SEGMENT.color_from_palette(i, false, false, 255)); return FRAMETIME; } + + +static UsermodTemperature temperature; +REGISTER_USERMOD(temperature); \ No newline at end of file diff --git a/usermods/Temperature/UsermodTemperature.h b/usermods/Temperature/UsermodTemperature.h new file mode 100644 index 000000000..2517a2b81 --- /dev/null +++ b/usermods/Temperature/UsermodTemperature.h @@ -0,0 +1,108 @@ +#pragma once +#include "wled.h" +#include "OneWire.h" + +//Pin defaults for QuinLed Dig-Uno if not overriden +#ifndef TEMPERATURE_PIN + #ifdef ARDUINO_ARCH_ESP32 + #define TEMPERATURE_PIN 18 + #else //ESP8266 boards + #define TEMPERATURE_PIN 14 + #endif +#endif + +// the frequency to check temperature, 1 minute +#ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL +#define USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL 60000 +#endif + +class UsermodTemperature : public Usermod { + + private: + + bool initDone = false; + OneWire *oneWire; + // GPIO pin used for sensor (with a default compile-time fallback) + int8_t temperaturePin = TEMPERATURE_PIN; + // measurement unit (true==°C, false==°F) + bool degC = true; + // using parasite power on the sensor + bool parasite = false; + int8_t parasitePin = -1; + // how often do we read from sensor? + unsigned long readingInterval = USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL; + // set last reading as "40 sec before boot", so first reading is taken after 20 sec + unsigned long lastMeasurement = UINT32_MAX - USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL; + // last time requestTemperatures was called + // used to determine when we can read the sensors temperature + // we have to wait at least 93.75 ms after requestTemperatures() is called + unsigned long lastTemperaturesRequest; + float temperature; + // indicates requestTemperatures has been called but the sensor measurement is not complete + bool waitingForConversion = false; + // flag set at startup if DS18B20 sensor not found, avoids trying to keep getting + // temperature if flashed to a board without a sensor attached + byte sensorFound; + + bool enabled = true; + + bool HApublished = false; + int16_t idx = -1; // Domoticz virtual sensor idx + + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _readInterval[]; + static const char _parasite[]; + static const char _parasitePin[]; + static const char _domoticzIDX[]; + static const char _sensor[]; + static const char _temperature[]; + static const char _Temperature[]; + static const char _data_fx[]; + + //Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013 + float readDallas(); + void requestTemperatures(); + void readTemperature(); + bool findSensor(); +#ifndef WLED_DISABLE_MQTT + void publishHomeAssistantAutodiscovery(); +#endif + + static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid UsermodManager::lookup(USERMOD_ID_TEMPERATURE); + + public: + + UsermodTemperature() { _instance = this; } + static UsermodTemperature *getInstance() { return UsermodTemperature::_instance; } + + /* + * API calls te enable data exchange between WLED modules + */ + inline float getTemperatureC() { return temperature; } + inline float getTemperatureF() { return temperature * 1.8f + 32.0f; } + float getTemperature(); + const char *getTemperatureUnit(); + uint16_t getId() override { return USERMOD_ID_TEMPERATURE; } + + void setup() override; + void loop() override; + //void connected() override; +#ifndef WLED_DISABLE_MQTT + void onMqttConnect(bool sessionPresent) override; +#endif + //void onUpdateBegin(bool init) override; + + //bool handleButton(uint8_t b) override; + //void handleOverlayDraw() override; + + void addToJsonInfo(JsonObject& root) override; + //void addToJsonState(JsonObject &root) override; + //void readFromJsonState(JsonObject &root) override; + void addToConfig(JsonObject &root) override; + bool readFromConfig(JsonObject &root) override; + + void appendConfigData() override; +}; + diff --git a/usermods/Temperature/library.json b/usermods/Temperature/library.json new file mode 100644 index 000000000..0d9f55ccd --- /dev/null +++ b/usermods/Temperature/library.json @@ -0,0 +1,7 @@ +{ + "name:": "Temperature", + "build": { "libArchive": false}, + "dependencies": { + "paulstoffregen/OneWire":"~2.3.8" + } +} diff --git a/usermods/Temperature/platformio_override.ini b/usermods/Temperature/platformio_override.ini index cc86367fd..a53b5974d 100644 --- a/usermods/Temperature/platformio_override.ini +++ b/usermods/Temperature/platformio_override.ini @@ -1,10 +1,5 @@ ; Options ; ------- -; USERMOD_DALLASTEMPERATURE - define this to have this user mod included wled00\usermods_list.cpp ; USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds ; -[env:d1_mini_usermod_dallas_temperature_C] -extends = env:d1_mini -build_flags = ${common.build_flags_esp8266} -D USERMOD_DALLASTEMPERATURE -lib_deps = ${env.lib_deps} - paulstoffregen/OneWire@~2.3.8 \ No newline at end of file + diff --git a/usermods/Temperature/readme.md b/usermods/Temperature/readme.md index 3d65be7eb..b7697edc3 100644 --- a/usermods/Temperature/readme.md +++ b/usermods/Temperature/readme.md @@ -11,11 +11,19 @@ Maintained by @blazoncek ## Installation -Copy the example `platformio_override.ini` to the root directory. This file should be placed in the same directory as `platformio.ini`. +Add `Temperature` to `custom_usermods` in your platformio_override.ini. + +Example **platformio_override.ini**: + +```ini +[env:usermod_temperature_esp32dev] +extends = env:esp32dev +custom_usermods = ${env:esp32dev.custom_usermods} + Temperature +``` ### Define Your Options -* `USERMOD_DALLASTEMPERATURE` - enables this user mod wled00/usermods_list.cpp * `USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL` - number of milliseconds between measurements, defaults to 60000 ms (60s) All parameters can be configured at runtime via the Usermods settings page, including pin, temperature in degrees Celsius or Fahrenheit and measurement interval. @@ -25,28 +33,6 @@ All parameters can be configured at runtime via the Usermods settings page, incl * [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link * [Srg74-WLED-Wemos-shield](https://github.com/srg74/WLED-wemos-shield) - another great DIY WLED board -### PlatformIO requirements - -If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:d1_mini_usermod_dallas_temperature_C`. - -If you are not using `platformio_override.ini`, you might have to uncomment `OneWire@~2.3.5 under` `[common]` section in `platformio.ini`: - -```ini -# platformio.ini -... -[platformio] -... -; default_envs = esp07 -default_envs = d1_mini -... -[common] -... -lib_deps = - ... - #For Dallas sensor uncomment following - paulstoffregen/OneWire @ ~2.3.8 -``` - ## Change Log 2020-09-12 diff --git a/usermods/TetrisAI_v2/usermod_v2_tetrisai.h b/usermods/TetrisAI_v2/TetrisAI_v2.cpp similarity index 99% rename from usermods/TetrisAI_v2/usermod_v2_tetrisai.h rename to usermods/TetrisAI_v2/TetrisAI_v2.cpp index 0f7039dac..b51250b26 100644 --- a/usermods/TetrisAI_v2/usermod_v2_tetrisai.h +++ b/usermods/TetrisAI_v2/TetrisAI_v2.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "FX.h" #include "fcn_declare.h" @@ -250,3 +248,7 @@ public: return USERMOD_ID_TETRISAI; } }; + + +static TetrisAIUsermod tetrisai_v2; +REGISTER_USERMOD(tetrisai_v2); \ No newline at end of file diff --git a/usermods/TetrisAI_v2/library.json b/usermods/TetrisAI_v2/library.json new file mode 100644 index 000000000..7163dadbf --- /dev/null +++ b/usermods/TetrisAI_v2/library.json @@ -0,0 +1,3 @@ +{ + "name:": "TetrisAI_v2" +} \ No newline at end of file diff --git a/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h b/usermods/VL53L0X_gestures/VL53L0X_gestures.cpp similarity index 98% rename from usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h rename to usermods/VL53L0X_gestures/VL53L0X_gestures.cpp index fe6b958f5..af3220b3c 100644 --- a/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h +++ b/usermods/VL53L0X_gestures/VL53L0X_gestures.cpp @@ -13,8 +13,6 @@ * lib_deps = ${env.lib_deps} * pololu/VL53L0X @ ^1.3.0 */ -#pragma once - #include "wled.h" #include @@ -126,4 +124,7 @@ class UsermodVL53L0XGestures : public Usermod { { return USERMOD_ID_VL53L0X; } -}; \ No newline at end of file +}; + +static UsermodVL53L0XGestures vl53l0x_gestures; +REGISTER_USERMOD(vl53l0x_gestures); \ No newline at end of file diff --git a/usermods/VL53L0X_gestures/library.json b/usermods/VL53L0X_gestures/library.json new file mode 100644 index 000000000..db24abd0b --- /dev/null +++ b/usermods/VL53L0X_gestures/library.json @@ -0,0 +1,7 @@ +{ + "name:": "VL53L0X_gestures", + "build": { "libArchive": false}, + "dependencies": { + "pololu/VL53L0X" : "^1.3.0" + } +} diff --git a/usermods/VL53L0X_gestures/readme.md b/usermods/VL53L0X_gestures/readme.md index a230b1a65..04c4a4aa5 100644 --- a/usermods/VL53L0X_gestures/readme.md +++ b/usermods/VL53L0X_gestures/readme.md @@ -10,20 +10,4 @@ Useful for controlling strips when you want to avoid touching anything. 1. Attach VL53L0X sensor to i2c pins according to default pins for your board. 2. Add `-D USERMOD_VL53L0X_GESTURES` to your build flags at platformio.ini (plaformio_override.ini) for needed environment. -In my case, for example: `build_flags = ${env.build_flags} -D USERMOD_VL53L0X_GESTURES` -3. Add "pololu/VL53L0X" dependency below to `lib_deps` like this: -```ini -lib_deps = ${env.lib_deps} - pololu/VL53L0X @ ^1.3.0 -``` -My entire `platformio_override.ini` for example (for nodemcu board): -```ini -[platformio] -default_envs = nodemcuv2 - -[env:nodemcuv2] -build_flags = ${env.build_flags} -D USERMOD_VL53L0X_GESTURES -lib_deps = ${env.lib_deps} - pololu/VL53L0X @ ^1.3.0 -``` diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.cpp similarity index 99% rename from usermods/audioreactive/audio_reactive.h rename to usermods/audioreactive/audio_reactive.cpp index d4b4b2d59..4b3520562 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.cpp @@ -1,4 +1,3 @@ -#pragma once #include "wled.h" @@ -2064,3 +2063,6 @@ const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic"; const char AudioReactive::_addPalettes[] PROGMEM = "add-palettes"; const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature + +static AudioReactive ar_module; +REGISTER_USERMOD(ar_module); diff --git a/usermods/audioreactive/library.json b/usermods/audioreactive/library.json new file mode 100644 index 000000000..fb2254a0e --- /dev/null +++ b/usermods/audioreactive/library.json @@ -0,0 +1,15 @@ +{ + "name": "audioreactive", + "build": { + "libArchive": false, + "extraScript": "override_sqrt.py" + }, + "dependencies": [ + { + "owner": "kosme", + "name": "arduinoFFT", + "version": "2.0.1", + "platforms": "espressif32" + } + ] +} diff --git a/usermods/audioreactive/override_sqrt.py b/usermods/audioreactive/override_sqrt.py new file mode 100644 index 000000000..36aa79df4 --- /dev/null +++ b/usermods/audioreactive/override_sqrt.py @@ -0,0 +1,5 @@ +Import('env') + +for lb in env.GetLibBuilders(): + if lb.name == "arduinoFFT": + lb.env.Append(CPPDEFINES=[("sqrt_internal", "sqrtf")]) diff --git a/usermods/audioreactive/readme.md b/usermods/audioreactive/readme.md index aad269c67..8db5c00bf 100644 --- a/usermods/audioreactive/readme.md +++ b/usermods/audioreactive/readme.md @@ -27,11 +27,7 @@ Currently ESP8266 is not supported, due to low speed and small RAM of this chip. There are however plans to create a lightweight audioreactive for the 8266, with reduced features. ## Installation -### using latest _arduinoFFT_ library version 2.x -The latest arduinoFFT release version should be used for audioreactive. - -* `build_flags` = `-D USERMOD_AUDIOREACTIVE -D sqrt_internal=sqrtf` -* `lib_deps`= `kosme/arduinoFFT @ 2.0.1` +Add 'ADS1115_v2' to `custom_usermods` in your platformio environment. ## Configuration diff --git a/usermods/boblight/boblight.h b/usermods/boblight/boblight.cpp similarity index 99% rename from usermods/boblight/boblight.h rename to usermods/boblight/boblight.cpp index b04b78fac..5980443d3 100644 --- a/usermods/boblight/boblight.h +++ b/usermods/boblight/boblight.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" /* @@ -457,3 +455,7 @@ void BobLightUsermod::pollBob() { } } } + + +static BobLightUsermod boblight; +REGISTER_USERMOD(boblight); \ No newline at end of file diff --git a/usermods/boblight/library.json b/usermods/boblight/library.json new file mode 100644 index 000000000..741d4cb18 --- /dev/null +++ b/usermods/boblight/library.json @@ -0,0 +1,3 @@ +{ + "name:": "boblight" +} \ No newline at end of file diff --git a/usermods/boblight/readme.md b/usermods/boblight/readme.md index 345830093..c47634574 100644 --- a/usermods/boblight/readme.md +++ b/usermods/boblight/readme.md @@ -20,8 +20,7 @@ The LEDs should be wired in a clockwise orientation starting in the middle of bo ## Installation -Add `-D USERMOD_BOBLIGHT` to your PlatformIO environment. -If you are not using PlatformIO (which you should) try adding `#define USERMOD_BOBLIGHT` to *my_config.h*. +Add `boblight` to `custom_usermods` in your PlatformIO environment. ## Configuration diff --git a/usermods/buzzer/usermod_v2_buzzer.h b/usermods/buzzer/buzzer.cpp similarity index 97% rename from usermods/buzzer/usermod_v2_buzzer.h rename to usermods/buzzer/buzzer.cpp index c6c2a47a9..60db08abc 100644 --- a/usermods/buzzer/usermod_v2_buzzer.h +++ b/usermods/buzzer/buzzer.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "Arduino.h" @@ -78,4 +76,7 @@ class BuzzerUsermod : public Usermod { { return USERMOD_ID_BUZZER; } -}; \ No newline at end of file +}; + +static BuzzerUsermod buzzer; +REGISTER_USERMOD(buzzer); \ No newline at end of file diff --git a/usermods/buzzer/library.json b/usermods/buzzer/library.json new file mode 100644 index 000000000..6bbcdcc34 --- /dev/null +++ b/usermods/buzzer/library.json @@ -0,0 +1,3 @@ +{ + "name:": "buzzer" +} \ No newline at end of file diff --git a/usermods/deep_sleep/usermod_deep_sleep.h b/usermods/deep_sleep/deep_sleep.cpp similarity index 98% rename from usermods/deep_sleep/usermod_deep_sleep.h rename to usermods/deep_sleep/deep_sleep.cpp index 7f4efd5ca..f6f3604fb 100644 --- a/usermods/deep_sleep/usermod_deep_sleep.h +++ b/usermods/deep_sleep/deep_sleep.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "driver/rtc_io.h" @@ -224,4 +222,7 @@ void addToConfig(JsonObject& root) override // add more strings here to reduce flash memory usage const char DeepSleepUsermod::_name[] PROGMEM = "DeepSleep"; -const char DeepSleepUsermod::_enabled[] PROGMEM = "enabled"; \ No newline at end of file +const char DeepSleepUsermod::_enabled[] PROGMEM = "enabled"; + +static DeepSleepUsermod deep_sleep; +REGISTER_USERMOD(deep_sleep); \ No newline at end of file diff --git a/usermods/deep_sleep/library.json b/usermods/deep_sleep/library.json new file mode 100644 index 000000000..c8f66de10 --- /dev/null +++ b/usermods/deep_sleep/library.json @@ -0,0 +1,3 @@ +{ + "name:": "deep_sleep" +} \ No newline at end of file diff --git a/usermods/deep_sleep/readme.md b/usermods/deep_sleep/readme.md index 006aa31fd..807757f82 100644 --- a/usermods/deep_sleep/readme.md +++ b/usermods/deep_sleep/readme.md @@ -42,7 +42,7 @@ To keep this usermod simple and easy to use, it is a very basic implementation o ## Usermod installation -Use `#define USERMOD_DEEP_SLEEP` in wled.h or `-D USERMOD_DEEP_SLEEP` in your platformio.ini. Settings can be changed in the usermod config UI. +Add `deep_sleep` to `custom_usermods` in your platformio.ini. Settings can be changed in the usermod config UI. ### Define Settings diff --git a/usermods/mpu6050_imu/library.json b/usermods/mpu6050_imu/library.json new file mode 100644 index 000000000..3c39de450 --- /dev/null +++ b/usermods/mpu6050_imu/library.json @@ -0,0 +1,7 @@ +{ + "name:": "mpu6050_imu", + "build": { "libArchive": false}, + "dependencies": { + "electroniccats/MPU6050":"1.0.1" + } +} diff --git a/usermods/mpu6050_imu/usermod_mpu6050_imu.h b/usermods/mpu6050_imu/mpu6050_imu.cpp similarity index 99% rename from usermods/mpu6050_imu/usermod_mpu6050_imu.h rename to usermods/mpu6050_imu/mpu6050_imu.cpp index f04578fe3..6df5d64e1 100644 --- a/usermods/mpu6050_imu/usermod_mpu6050_imu.h +++ b/usermods/mpu6050_imu/mpu6050_imu.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" /* This driver reads quaternion data from the MPU6060 and adds it to the JSON @@ -105,7 +103,7 @@ class MPU6050Driver : public Usermod { VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector - uint32 sample_count; + uint32_t sample_count; // Usermod output um_data_t um_data; @@ -446,3 +444,7 @@ const char MPU6050Driver::_z_acc_bias[] PROGMEM = "z_acc_bias"; const char MPU6050Driver::_x_gyro_bias[] PROGMEM = "x_gyro_bias"; const char MPU6050Driver::_y_gyro_bias[] PROGMEM = "y_gyro_bias"; const char MPU6050Driver::_z_gyro_bias[] PROGMEM = "z_gyro_bias"; + + +static MPU6050Driver mpu6050_imu; +REGISTER_USERMOD(mpu6050_imu); \ No newline at end of file diff --git a/usermods/mpu6050_imu/readme.md b/usermods/mpu6050_imu/readme.md index c324738d6..87c439131 100644 --- a/usermods/mpu6050_imu/readme.md +++ b/usermods/mpu6050_imu/readme.md @@ -16,26 +16,6 @@ As a memento to a long trip I was on, I built an icosahedron globe. I put lights I wanted to integrate an IMU to allow either on-board, or off-board effects that would react to the globes orientation. See the blog post on building it or a video demo . -## Adding Dependencies - -I2Cdev and MPU6050 must be installed. - -To install them, add electroniccats/MPU6050@1.0.1 to lib_deps in the platformio.ini file. - -For example: - -``` -lib_deps = - FastLED@3.3.2 - NeoPixelBus@2.5.7 - ESPAsyncTCP@1.2.0 - ESPAsyncUDP@697c75a025 - AsyncTCP@1.0.3 - Esp Async WebServer@1.2.0 - IRremoteESP8266@2.7.3 - electroniccats/MPU6050@1.0.1 -``` - ## Wiring The connections needed to the MPU6050 are as follows: @@ -74,18 +54,13 @@ to the info object ## Usermod installation -1. Copy the file `usermod_mpu6050_imu.h` to the `wled00` directory. -2. Register the usermod by adding `#include "usermod_mpu6050_imu.h"` in the top and `registerUsermod(new MPU6050Driver());` in the bottom of `usermods_list.cpp`. +Add `mpu6050_imu` to `custom_usermods` in your platformio_override.ini. -Example **usermods_list.cpp**: +Example **platformio_override.ini**: -```cpp -#include "wled.h" - -#include "usermod_mpu6050_imu.h" - -void registerUsermods() -{ - UsermodManager::add(new MPU6050Driver()); -} +```ini +[env:usermod_mpu6050_imu_esp32dev] +extends = env:esp32dev +custom_usermods = ${env:esp32dev.custom_usermods} + mpu6050_imu ``` diff --git a/usermods/mqtt_switch_v2/README.md b/usermods/mqtt_switch_v2/README.md deleted file mode 100644 index 382f72d0e..000000000 --- a/usermods/mqtt_switch_v2/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# DEPRECATION NOTICE -This usermod is deprecated and no longer maintained. It will be removed in a future WLED release. Please use usermod multi_relay which has more features. - - -# MQTT controllable switches -This usermod allows controlling switches (e.g. relays) via MQTT. - -## Usermod installation - -1. Copy the file `usermod_mqtt_switch.h` to the `wled00` directory. -2. Register the usermod by adding `#include "usermod_mqtt_switch.h"` in the top and `registerUsermod(new UsermodMqttSwitch());` in the bottom of `usermods_list.cpp`. - - -Example `usermods_list.cpp`: - -``` -#include "wled.h" -#include "usermod_mqtt_switch.h" - -void registerUsermods() -{ - UsermodManager::add(new UsermodMqttSwitch()); -} -``` - -## Define pins -Add a define for MQTTSWITCHPINS to platformio_override.ini. -The following example defines 3 switches connected to the GPIO pins 13, 5 and 2: - -``` -[env:livingroom] -board = esp12e -platform = ${common.platform_wled_default} -board_build.ldscript = ${common.ldscript_4m1m} -build_flags = ${common.build_flags_esp8266} - -D DATA_PINS=3 - -D BTNPIN=4 - -D RLYPIN=12 - -D RLYMDE=1 - -D STATUSPIN=15 - -D MQTTSWITCHPINS="13, 5, 2" -``` - -Pins can be inverted by setting `MQTTSWITCHINVERT`. For example `-D MQTTSWITCHINVERT="false, false, true"` would invert the switch on pin 2 in the previous example. - -The default state after booting before any MQTT message can be set by `MQTTSWITCHDEFAULTS`. For example `-D MQTTSWITCHDEFAULTS="ON, OFF, OFF"` would power on the switch on pin 13 and power off switches on pins 5 and 2. - -## MQTT topics -This usermod listens on `[mqttDeviceTopic]/switch/0/set` (where 0 is replaced with the index of the switch) for commands. Anything starting with `ON` turns on the switch, everything else turns it off. -Feedback about the current state is provided at `[mqttDeviceTopic]/switch/0/state`. - -### Home Assistant auto-discovery -Auto-discovery information is automatically published and you shouldn't have to do anything to register the switches in Home Assistant. - diff --git a/usermods/mqtt_switch_v2/usermod_mqtt_switch.h b/usermods/mqtt_switch_v2/usermod_mqtt_switch.h deleted file mode 100644 index 67dfc9cc0..000000000 --- a/usermods/mqtt_switch_v2/usermod_mqtt_switch.h +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once - -#warning "This usermod is deprecated and no longer maintained. It will be removed in a future WLED release. Please use usermod multi_relay which has more features." - -#include "wled.h" -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#ifndef MQTTSWITCHPINS -#error "Please define MQTTSWITCHPINS in platformio_override.ini. e.g. -D MQTTSWITCHPINS="12, 0, 2" " -// The following define helps Eclipse's C++ parser but is never used in production due to the #error statement on the line before -#define MQTTSWITCHPINS 12, 0, 2 -#endif - -// Default behavior: All outputs active high -#ifndef MQTTSWITCHINVERT -#define MQTTSWITCHINVERT -#endif - -// Default behavior: All outputs off -#ifndef MQTTSWITCHDEFAULTS -#define MQTTSWITCHDEFAULTS -#endif - -static const uint8_t switchPins[] = { MQTTSWITCHPINS }; -//This is a hack to get the number of pins defined by the user -#define NUM_SWITCH_PINS (sizeof(switchPins)) -static const bool switchInvert[NUM_SWITCH_PINS] = { MQTTSWITCHINVERT}; -//Make settings in config file more readable -#define ON 1 -#define OFF 0 -static const bool switchDefaults[NUM_SWITCH_PINS] = { MQTTSWITCHDEFAULTS}; -#undef ON -#undef OFF - -class UsermodMqttSwitch: public Usermod -{ -private: - bool mqttInitialized; - bool switchState[NUM_SWITCH_PINS]; - -public: - UsermodMqttSwitch() : - mqttInitialized(false) - { - } - - void setup() - { - for (int pinNr = 0; pinNr < NUM_SWITCH_PINS; pinNr++) { - setState(pinNr, switchDefaults[pinNr]); - pinMode(switchPins[pinNr], OUTPUT); - } - } - - void loop() - { - if (!mqttInitialized) { - mqttInit(); - return; // Try again in next loop iteration - } - } - - void mqttInit() - { - if (!mqtt) - return; - mqtt->onMessage( - std::bind(&UsermodMqttSwitch::onMqttMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6)); - mqtt->onConnect(std::bind(&UsermodMqttSwitch::onMqttConnect, this, std::placeholders::_1)); - mqttInitialized = true; - } - - void onMqttConnect(bool sessionPresent); - - void onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total); - void updateState(uint8_t pinNr); - - void setState(uint8_t pinNr, bool active) - { - if (pinNr > NUM_SWITCH_PINS) - return; - switchState[pinNr] = active; - digitalWrite((char) switchPins[pinNr], (char) (switchInvert[pinNr] ? !active : active)); - updateState(pinNr); - } -}; - -inline void UsermodMqttSwitch::onMqttConnect(bool sessionPresent) -{ - if (mqttDeviceTopic[0] == 0) - return; - - for (int pinNr = 0; pinNr < NUM_SWITCH_PINS; pinNr++) { - char buf[128]; - StaticJsonDocument<1024> json; - sprintf(buf, "%s Switch %d", serverDescription, pinNr + 1); - json[F("name")] = buf; - - sprintf(buf, "%s/switch/%d", mqttDeviceTopic, pinNr); - json["~"] = buf; - strcat(buf, "/set"); - mqtt->subscribe(buf, 0); - - json[F("stat_t")] = "~/state"; - json[F("cmd_t")] = "~/set"; - json[F("pl_off")] = F("OFF"); - json[F("pl_on")] = F("ON"); - - char uid[16]; - sprintf(uid, "%s_sw%d", escapedMac.c_str(), pinNr); - json[F("unique_id")] = uid; - - strcpy(buf, mqttDeviceTopic); - strcat(buf, "/status"); - json[F("avty_t")] = buf; - json[F("pl_avail")] = F("online"); - json[F("pl_not_avail")] = F("offline"); - //TODO: dev - sprintf(buf, "homeassistant/switch/%s/config", uid); - char json_str[1024]; - size_t payload_size = serializeJson(json, json_str); - mqtt->publish(buf, 0, true, json_str, payload_size); - updateState(pinNr); - } -} - -inline void UsermodMqttSwitch::onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) -{ - //Note: Payload is not necessarily null terminated. Check "len" instead. - for (int pinNr = 0; pinNr < NUM_SWITCH_PINS; pinNr++) { - char buf[64]; - sprintf(buf, "%s/switch/%d/set", mqttDeviceTopic, pinNr); - if (strcmp(topic, buf) == 0) { - //Any string starting with "ON" is interpreted as ON, everything else as OFF - setState(pinNr, len >= 2 && payload[0] == 'O' && payload[1] == 'N'); - break; - } - } -} - -inline void UsermodMqttSwitch::updateState(uint8_t pinNr) -{ - if (!mqttInitialized) - return; - - if (pinNr > NUM_SWITCH_PINS) - return; - - char buf[64]; - sprintf(buf, "%s/switch/%d/state", mqttDeviceTopic, pinNr); - if (switchState[pinNr]) { - mqtt->publish(buf, 0, false, "ON"); - } else { - mqtt->publish(buf, 0, false, "OFF"); - } -} diff --git a/usermods/multi_relay/library.json b/usermods/multi_relay/library.json new file mode 100644 index 000000000..7aa764399 --- /dev/null +++ b/usermods/multi_relay/library.json @@ -0,0 +1,3 @@ +{ + "name:": "multi_relay" +} \ No newline at end of file diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/multi_relay.cpp similarity index 99% rename from usermods/multi_relay/usermod_multi_relay.h rename to usermods/multi_relay/multi_relay.cpp index c4446c7a2..f8b1f566a 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/multi_relay.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) @@ -842,3 +840,7 @@ const char MultiRelay::_pcfAddress[] PROGMEM = "PCF8574-address"; const char MultiRelay::_switch[] PROGMEM = "switch"; const char MultiRelay::_toggle[] PROGMEM = "toggle"; const char MultiRelay::_Command[] PROGMEM = "/command"; + + +static MultiRelay multi_relay; +REGISTER_USERMOD(multi_relay); \ No newline at end of file diff --git a/usermods/multi_relay/readme.md b/usermods/multi_relay/readme.md index eaa069ae7..543809d8c 100644 --- a/usermods/multi_relay/readme.md +++ b/usermods/multi_relay/readme.md @@ -41,9 +41,7 @@ When a relay is switched, a message is published: ## Usermod installation -1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `UsermodManager::add(new MultiRelay());` at the bottom of `usermods_list.cpp`. -or -2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY` in your platformio.ini +Add `multi_relay` to the `custom_usermods` of your platformio.ini environment. You can override the default maximum number of relays (which is 4) by defining MULTI_RELAY_MAX_RELAYS. @@ -65,38 +63,6 @@ The following definitions should be a list of values (maximum number of entries ``` These can be set via your `platformio_override.ini` file or as `#define` in your `my_config.h` (remember to set `WLED_USE_MY_CONFIG` in your `platformio_override.ini`) -Example **usermods_list.cpp**: - -```cpp -#include "wled.h" -/* - * Register your v2 usermods here! - * (for v1 usermods using just usermod.cpp, you can ignore this file) - */ - -/* - * Add/uncomment your usermod filename here (and once more below) - * || || || - * \/ \/ \/ - */ -//#include "usermod_v2_example.h" -//#include "usermod_temperature.h" -#include "../usermods/usermod_multi_relay.h" - -void registerUsermods() -{ - /* - * Add your usermod class name here - * || || || - * \/ \/ \/ - */ - //UsermodManager::add(new MyExampleUsermod()); - //UsermodManager::add(new UsermodTemperature()); - UsermodManager::add(new MultiRelay()); - -} -``` - ## Configuration Usermod can be configured via the Usermods settings page. diff --git a/usermods/pixels_dice_tray/library.json b/usermods/pixels_dice_tray/library.json new file mode 100644 index 000000000..5043c0cfd --- /dev/null +++ b/usermods/pixels_dice_tray/library.json @@ -0,0 +1,8 @@ +{ + "name:": "pixels_dice_tray", + "build": { "libArchive": false}, + "dependencies": { + "arduino-pixels-dice":"https://github.com/axlan/arduino-pixels-dice.git", + "BLE":"*" + } +} diff --git a/usermods/pixels_dice_tray/pixels_dice_tray.h b/usermods/pixels_dice_tray/pixels_dice_tray.cpp similarity index 99% rename from usermods/pixels_dice_tray/pixels_dice_tray.h rename to usermods/pixels_dice_tray/pixels_dice_tray.cpp index 61348ebb8..73457c67f 100644 --- a/usermods/pixels_dice_tray/pixels_dice_tray.h +++ b/usermods/pixels_dice_tray/pixels_dice_tray.cpp @@ -1,5 +1,3 @@ -#pragma once - #include // https://github.com/axlan/arduino-pixels-dice #include "wled.h" @@ -533,3 +531,7 @@ class PixelsDiceTrayUsermod : public Usermod { // extended. Your usermod will remain compatible as it does not need to // implement all methods from the Usermod base class! }; + + +static PixelsDiceTrayUsermod pixels_dice_tray; +REGISTER_USERMOD(pixels_dice_tray); \ No newline at end of file diff --git a/usermods/pov_display/library.json.disabled b/usermods/pov_display/library.json.disabled new file mode 100644 index 000000000..2dd944a8a --- /dev/null +++ b/usermods/pov_display/library.json.disabled @@ -0,0 +1,7 @@ +{ + "name:": "pov_display", + "build": { "libArchive": false}, + "dependencies": { + "bitbank2/PNGdec":"^1.0.3" + } +} diff --git a/usermods/pov_display/usermod_pov_display.h b/usermods/pov_display/pov_display.cpp similarity index 96% rename from usermods/pov_display/usermod_pov_display.h rename to usermods/pov_display/pov_display.cpp index b1fc0dba6..b2b91f7d5 100644 --- a/usermods/pov_display/usermod_pov_display.h +++ b/usermods/pov_display/pov_display.cpp @@ -1,4 +1,3 @@ -#pragma once #include "wled.h" #include @@ -83,3 +82,7 @@ class PovDisplayUsermod : public Usermod void connected() {} }; + + +static PovDisplayUsermod pov_display; +REGISTER_USERMOD(pov_display); \ No newline at end of file diff --git a/usermods/pwm_outputs/library.json b/usermods/pwm_outputs/library.json new file mode 100644 index 000000000..4bf07777a --- /dev/null +++ b/usermods/pwm_outputs/library.json @@ -0,0 +1,3 @@ +{ + "name:": "pwm_outputs" +} \ No newline at end of file diff --git a/usermods/pwm_outputs/usermod_pwm_outputs.h b/usermods/pwm_outputs/pwm_outputs.cpp similarity index 98% rename from usermods/pwm_outputs/usermod_pwm_outputs.h rename to usermods/pwm_outputs/pwm_outputs.cpp index 09232f043..d94f1d848 100644 --- a/usermods/pwm_outputs/usermod_pwm_outputs.h +++ b/usermods/pwm_outputs/pwm_outputs.cpp @@ -1,4 +1,3 @@ -#pragma once #include "wled.h" #ifndef ESP32 @@ -219,3 +218,7 @@ class PwmOutputsUsermod : public Usermod { const char PwmOutputsUsermod::USERMOD_NAME[] PROGMEM = "PwmOutputs"; const char PwmOutputsUsermod::PWM_STATE_NAME[] PROGMEM = "pwm"; + + +static PwmOutputsUsermod pwm_outputs; +REGISTER_USERMOD(pwm_outputs); \ No newline at end of file diff --git a/usermods/quinled-an-penta/library.json b/usermods/quinled-an-penta/library.json new file mode 100644 index 000000000..9a1f4e0e5 --- /dev/null +++ b/usermods/quinled-an-penta/library.json @@ -0,0 +1,8 @@ +{ + "name:": "quinled-an-penta", + "build": { "libArchive": false}, + "dependencies": { + "olikraus/U8g2":"~2.28.8", + "robtillaart/SHT85":"~0.3.3" + } +} diff --git a/usermods/quinled-an-penta/quinled-an-penta.h b/usermods/quinled-an-penta/quinled-an-penta.cpp similarity index 99% rename from usermods/quinled-an-penta/quinled-an-penta.h rename to usermods/quinled-an-penta/quinled-an-penta.cpp index e44672039..a3b452bf1 100644 --- a/usermods/quinled-an-penta/quinled-an-penta.h +++ b/usermods/quinled-an-penta/quinled-an-penta.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "U8g2lib.h" #include "SHT85.h" #include "Wire.h" @@ -752,4 +750,7 @@ const unsigned char QuinLEDAnPentaUsermod::quinLedLogo[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; \ No newline at end of file +}; + +static QuinLEDAnPentaUsermod quinled_an_penta; +REGISTER_USERMOD(quinled_an_penta); \ No newline at end of file diff --git a/usermods/quinled-an-penta/readme.md b/usermods/quinled-an-penta/readme.md index c1260d913..db1f72c4a 100644 --- a/usermods/quinled-an-penta/readme.md +++ b/usermods/quinled-an-penta/readme.md @@ -5,29 +5,6 @@ The (un)official usermod to get the best out of the QuinLED-An-Penta (https://qu * "u8g2" by olikraus, v2.28 or higher: https://github.com/olikraus/u8g2 * "SHT85" by Rob Tillaart, v0.2 or higher: https://github.com/RobTillaart/SHT85 -## Usermod installation -Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one, add the buildflag `-D QUINLED_AN_PENTA` and the below library dependencies. - -ESP32 (**without** ethernet): -``` -[env:custom_esp32dev_usermod_quinled_an_penta] -extends = env:esp32dev -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D QUINLED_AN_PENTA -lib_deps = ${esp32.lib_deps} - olikraus/U8g2@~2.28.8 - robtillaart/SHT85@~0.2.0 -``` - -ESP32 (**with** ethernet): -``` -[env:custom_esp32dev_usermod_quinled_an_penta] -extends = env:esp32dev -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D WLED_USE_ETHERNET -D QUINLED_AN_PENTA -lib_deps = ${esp32.lib_deps} - olikraus/U8g2@~2.28.8 - robtillaart/SHT85@~0.2.0 -``` - ## Some words about the (optional) OLED This mod has been optimized for an SSD1306 driven 128x64 OLED. Using a smaller OLED or an OLED using a different driver will result in unexpected results. I highly recommend using these "two color monochromatic OLEDs", which have the first 16 pixels in a different color than the other 48, e.g. a yellow/blue OLED. diff --git a/usermods/rgb-rotary-encoder/library.json.disabled b/usermods/rgb-rotary-encoder/library.json.disabled new file mode 100644 index 000000000..b1394ba25 --- /dev/null +++ b/usermods/rgb-rotary-encoder/library.json.disabled @@ -0,0 +1,7 @@ +{ + "name:": "rgb-rotary-encoder", + "build": { "libArchive": false}, + "dependencies": { + "lennarthennigs/ESP Rotary":"^2.1.1" + } +} diff --git a/usermods/rgb-rotary-encoder/readme.md b/usermods/rgb-rotary-encoder/readme.md index 653179179..abd8a812c 100644 --- a/usermods/rgb-rotary-encoder/readme.md +++ b/usermods/rgb-rotary-encoder/readme.md @@ -8,30 +8,6 @@ https://user-images.githubusercontent.com/3090131/124680599-0180ab80-dec7-11eb-9 The actual / original code that controls the LED modes is from Adam Zeloof. I take no credit for it. I ported it to WLED, which involved replacing the LED library he used, (because WLED already has one, so no need to add another one) plus the rotary encoder library because it was not compatible with ESP, only Arduino. It was quite a bit more work than I hoped, but I got there eventually :) -## Requirements -* "ESP Rotary" by Lennart Hennigs, v2.1.1 or higher: https://github.com/LennartHennigs/ESPRotary - -## Usermod installation -Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one and add the buildflag `-D RGB_ROTARY_ENCODER`. - -ESP32: -``` -[env:custom_esp32dev_usermod_rgb_encoder_board] -extends = env:esp32dev -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D RGB_ROTARY_ENCODER -lib_deps = ${esp32.lib_deps} - lennarthennigs/ESP Rotary@^2.1.1 -``` - -ESP8266 / D1 Mini: -``` -[env:custom_d1_mini_usermod_rgb_encoder_board] -extends = env:d1_mini -build_flags = ${common.build_flags_esp8266} -D RGB_ROTARY_ENCODER -lib_deps = ${esp8266.lib_deps} - lennarthennigs/ESP Rotary@^2.1.1 -``` - ## How to connect the board to your ESP We'll need (minimum) three or (maximum) four GPIOs for the board: * "ea": reports the encoder direction diff --git a/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h b/usermods/rgb-rotary-encoder/rgb-rotary-encoder.cpp similarity index 99% rename from usermods/rgb-rotary-encoder/rgb-rotary-encoder.h rename to usermods/rgb-rotary-encoder/rgb-rotary-encoder.cpp index 00fc22725..1514e2307 100644 --- a/usermods/rgb-rotary-encoder/rgb-rotary-encoder.h +++ b/usermods/rgb-rotary-encoder/rgb-rotary-encoder.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "ESPRotary.h" #include #include "wled.h" @@ -340,4 +338,7 @@ const char RgbRotaryEncoderUsermod::_ebIo[] PROGMEM = "eb-pin"; const char RgbRotaryEncoderUsermod::_ledMode[] PROGMEM = "LED-Mode"; const char RgbRotaryEncoderUsermod::_ledBrightness[] PROGMEM = "LED-Brightness"; const char RgbRotaryEncoderUsermod::_stepsPerClick[] PROGMEM = "Steps-per-Click"; -const char RgbRotaryEncoderUsermod::_incrementPerClick[] PROGMEM = "Increment-per-Click"; \ No newline at end of file +const char RgbRotaryEncoderUsermod::_incrementPerClick[] PROGMEM = "Increment-per-Click"; + +static RgbRotaryEncoderUsermod rgb_rotary_encoder; +REGISTER_USERMOD(rgb_rotary_encoder); \ No newline at end of file diff --git a/usermods/sd_card/library.json b/usermods/sd_card/library.json new file mode 100644 index 000000000..1f123ead6 --- /dev/null +++ b/usermods/sd_card/library.json @@ -0,0 +1,3 @@ +{ + "name:": "sd_card" +} \ No newline at end of file diff --git a/usermods/sd_card/usermod_sd_card.h b/usermods/sd_card/sd_card.cpp similarity index 99% rename from usermods/sd_card/usermod_sd_card.h rename to usermods/sd_card/sd_card.cpp index da1999d9b..4e68b97a3 100644 --- a/usermods/sd_card/usermod_sd_card.h +++ b/usermods/sd_card/sd_card.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" // SD connected via MMC / SPI @@ -240,4 +238,7 @@ void listDir( const char * dirname, uint8_t levels){ } } -#endif \ No newline at end of file +#endif + +static UsermodSdCard sd_card; +REGISTER_USERMOD(sd_card); \ No newline at end of file diff --git a/usermods/sensors_to_mqtt/library.json b/usermods/sensors_to_mqtt/library.json new file mode 100644 index 000000000..d38c794e4 --- /dev/null +++ b/usermods/sensors_to_mqtt/library.json @@ -0,0 +1,10 @@ +{ + "name:": "sensors_to_mqtt", + "build": { "libArchive": false}, + "dependencies": { + "adafruit/Adafruit BMP280 Library":"2.6.8", + "adafruit/Adafruit CCS811 Library":"1.1.3", + "adafruit/Adafruit Si7021 Library":"1.5.3", + "adafruit/Adafruit Unified Sensor":"^1.1.15" + } +} diff --git a/usermods/sensors_to_mqtt/readme.md b/usermods/sensors_to_mqtt/readme.md index d427d3e14..061627937 100644 --- a/usermods/sensors_to_mqtt/readme.md +++ b/usermods/sensors_to_mqtt/readme.md @@ -60,25 +60,6 @@ SCL_PIN = 5; SDA_PIN = 4; ``` -## Enable in WLED - -1. Copy `usermod_v2_SensorsToMqtt.h` into the `wled00` directory. -2. Add to `build_flags` in platformio.ini: - -``` - -D USERMOD_SENSORSTOMQTT -``` - -3. And add to `lib_deps` in platformio.ini: - -``` - adafruit/Adafruit BMP280 Library @ 2.1.0 - adafruit/Adafruit CCS811 Library @ 1.0.4 - adafruit/Adafruit Si7021 Library @ 1.4.0 -``` - -The #ifdefs in `usermods_list.cpp` should do the rest - # Credits - Aircoookie for making WLED diff --git a/usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h b/usermods/sensors_to_mqtt/sensors_to_mqtt.cpp similarity index 95% rename from usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h rename to usermods/sensors_to_mqtt/sensors_to_mqtt.cpp index 9b5bd8c88..5f7da97a9 100644 --- a/usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h +++ b/usermods/sensors_to_mqtt/sensors_to_mqtt.cpp @@ -1,9 +1,3 @@ -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - #include "wled.h" #include #include @@ -11,9 +5,13 @@ #include #include -Adafruit_BMP280 bmp; -Adafruit_Si7021 si7021; -Adafruit_CCS811 ccs811; +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + +static Adafruit_BMP280 bmp; +static Adafruit_Si7021 si7021; +static Adafruit_CCS811 ccs811; class UserMod_SensorsToMQTT : public Usermod { @@ -23,7 +21,7 @@ private: float SensorPressure = 0; float SensorTemperature = 0; float SensorHumidity = 0; - char *SensorIaq = "Unknown"; + const char *SensorIaq = "Unknown"; String mqttTemperatureTopic = ""; String mqttHumidityTopic = ""; String mqttPressureTopic = ""; @@ -117,7 +115,7 @@ private: /** * Credits: Bouke_Regnerus @ https://community.home-assistant.io/t/example-indoor-air-quality-text-sensor-using-ccs811-sensor/125854 */ - char *_getIaqIndex(float humidity, int tvoc, int eco2) + const char *_getIaqIndex(float humidity, int tvoc, int eco2) { int iaq_index = 0; @@ -216,6 +214,7 @@ private: { return "Excellent"; } + return "Unknown"; } public: @@ -276,3 +275,7 @@ public: } } }; + + +static UserMod_SensorsToMQTT sensors_to_mqtt; +REGISTER_USERMOD(sensors_to_mqtt); \ No newline at end of file diff --git a/usermods/seven_segment_display/library.json b/usermods/seven_segment_display/library.json new file mode 100644 index 000000000..8764e92b3 --- /dev/null +++ b/usermods/seven_segment_display/library.json @@ -0,0 +1,3 @@ +{ + "name:": "seven_segment_display" +} \ No newline at end of file diff --git a/usermods/seven_segment_display/usermod_v2_seven_segment_display.h b/usermods/seven_segment_display/seven_segment_display.cpp similarity index 99% rename from usermods/seven_segment_display/usermod_v2_seven_segment_display.h rename to usermods/seven_segment_display/seven_segment_display.cpp index 20fef15df..13a6306be 100644 --- a/usermods/seven_segment_display/usermod_v2_seven_segment_display.h +++ b/usermods/seven_segment_display/seven_segment_display.cpp @@ -1,11 +1,9 @@ -#ifndef WLED_ENABLE_MQTT +#include "wled.h" + +#ifdef WLED_DISABLE_MQTT #error "This user mod requires MQTT to be enabled." #endif -#pragma once - -#include "wled.h" - class SevenSegmentDisplay : public Usermod { @@ -498,4 +496,7 @@ const char SevenSegmentDisplay::_str_timeEnabled[] PROGMEM = "timeEnabled"; const char SevenSegmentDisplay::_str_scrollSpd[] PROGMEM = "scrollSpd"; const char SevenSegmentDisplay::_str_displayMask[] PROGMEM = "displayMask"; const char SevenSegmentDisplay::_str_displayMsg[] PROGMEM = "displayMsg"; -const char SevenSegmentDisplay::_str_sevenSeg[] PROGMEM = "sevenSeg"; \ No newline at end of file +const char SevenSegmentDisplay::_str_sevenSeg[] PROGMEM = "sevenSeg"; + +static SevenSegmentDisplay seven_segment_display; +REGISTER_USERMOD(seven_segment_display); \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/library.json b/usermods/seven_segment_display_reloaded/library.json new file mode 100644 index 000000000..fdce8b536 --- /dev/null +++ b/usermods/seven_segment_display_reloaded/library.json @@ -0,0 +1,3 @@ +{ + "name:": "seven_segment_display_reloaded" +} \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h b/usermods/seven_segment_display_reloaded/seven_segment_display_reloaded.cpp similarity index 99% rename from usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h rename to usermods/seven_segment_display_reloaded/seven_segment_display_reloaded.cpp index 72f4c2dd6..971a80c8d 100644 --- a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h +++ b/usermods/seven_segment_display_reloaded/seven_segment_display_reloaded.cpp @@ -1,11 +1,9 @@ -#ifndef WLED_ENABLE_MQTT +#include "wled.h" + +#ifdef WLED_DISABLE_MQTT #error "This user mod requires MQTT to be enabled." #endif -#pragma once - -#include "wled.h" - class UsermodSSDR : public Usermod { //#define REFRESHTIME 497 @@ -593,3 +591,7 @@ const char UsermodSSDR::_str_years[] PROGMEM = "LED-Numbers-Year"; const char UsermodSSDR::_str_ldrEnabled[] PROGMEM = "enable-auto-brightness"; const char UsermodSSDR::_str_minBrightness[] PROGMEM = "auto-brightness-min"; const char UsermodSSDR::_str_maxBrightness[] PROGMEM = "auto-brightness-max"; + + +static UsermodSSDR seven_segment_display_reloaded; +REGISTER_USERMOD(seven_segment_display_reloaded); \ No newline at end of file diff --git a/usermods/sht/ShtUsermod.h b/usermods/sht/ShtUsermod.h new file mode 100644 index 000000000..5dd83f46d --- /dev/null +++ b/usermods/sht/ShtUsermod.h @@ -0,0 +1,71 @@ +#pragma once +#include "wled.h" + +#ifdef WLED_DISABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + +#define USERMOD_SHT_TYPE_SHT30 0 +#define USERMOD_SHT_TYPE_SHT31 1 +#define USERMOD_SHT_TYPE_SHT35 2 +#define USERMOD_SHT_TYPE_SHT85 3 + +class SHT; + +class ShtUsermod : public Usermod +{ + private: + bool enabled = false; // Is usermod enabled or not + bool firstRunDone = false; // Remembers if the first config load run had been done + bool initDone = false; // Remembers if the mod has been completely initialised + bool haMqttDiscovery = false; // Is MQTT discovery enabled or not + bool haMqttDiscoveryDone = false; // Remembers if we already published the HA discovery topics + + // SHT vars + SHT *shtTempHumidSensor = nullptr; // Instance of SHT lib + byte shtType = 0; // SHT sensor type to be used. Default: SHT30 + byte unitOfTemp = 0; // Temperature unit to be used. Default: Celsius (0 = Celsius, 1 = Fahrenheit) + bool shtInitDone = false; // Remembers if SHT sensor has been initialised + bool shtReadDataSuccess = false; // Did we have a successful data read and is a valid temperature and humidity available? + const byte shtI2cAddress = 0x44; // i2c address of the sensor. 0x44 is the default for all SHT sensors. Change this, if needed + unsigned long shtLastTimeUpdated = 0; // Remembers when we read data the last time + bool shtDataRequested = false; // Reading data is done async. This remembers if we asked the sensor to read data + float shtCurrentTempC = 0.0f; // Last read temperature in Celsius + float shtCurrentHumidity = 0.0f; // Last read humidity in RH% + + + void initShtTempHumiditySensor(); + void cleanupShtTempHumiditySensor(); + void cleanup(); + inline bool isShtReady() { return shtInitDone; } // Checks if the SHT sensor has been initialised. + + void publishTemperatureAndHumidityViaMqtt(); + void publishHomeAssistantAutodiscovery(); + void appendDeviceToMqttDiscoveryMessage(JsonDocument& root); + + public: + // Strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _shtType[]; + static const char _unitOfTemp[]; + static const char _haMqttDiscovery[]; + + void setup(); + void loop(); + void onMqttConnect(bool sessionPresent); + void appendConfigData(); + void addToConfig(JsonObject &root); + bool readFromConfig(JsonObject &root); + void addToJsonInfo(JsonObject& root); + + bool isEnabled() { return enabled; } + + float getTemperature(); + float getTemperatureC() { return roundf(shtCurrentTempC * 10.0f) / 10.0f; } + float getTemperatureF() { return (getTemperatureC() * 1.8f) + 32.0f; } + float getHumidity() { return roundf(shtCurrentHumidity * 10.0f) / 10.0f; } + const char* getUnitString(); + + uint16_t getId() { return USERMOD_ID_SHT; } +}; diff --git a/usermods/sht/library.json b/usermods/sht/library.json new file mode 100644 index 000000000..fc62941a3 --- /dev/null +++ b/usermods/sht/library.json @@ -0,0 +1,6 @@ +{ + "name:": "sht", + "dependencies": { + "robtillaart/SHT85": "~0.3.3" + } +} \ No newline at end of file diff --git a/usermods/sht/readme.md b/usermods/sht/readme.md index 0337805b3..c2cc5a1f8 100644 --- a/usermods/sht/readme.md +++ b/usermods/sht/readme.md @@ -5,26 +5,21 @@ Usermod to support various SHT i2c sensors like the SHT30, SHT31, SHT35 and SHT8 * "SHT85" by Rob Tillaart, v0.2 or higher: https://github.com/RobTillaart/SHT85 ## Usermod installation -Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one, add the buildflag `-D USERMOD_SHT` and the below library dependencies. + +Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one, add the custom_usermod `sht`. ESP32: ``` [env:custom_esp32dev_usermod_sht] extends = env:esp32dev -build_flags = ${common.build_flags_esp32} - -D USERMOD_SHT -lib_deps = ${esp32.lib_deps} - robtillaart/SHT85@~0.3.3 +custom_usermods = ${env:esp32dev.custom_usermods} sht ``` ESP8266: ``` [env:custom_d1_mini_usermod_sht] extends = env:d1_mini -build_flags = ${common.build_flags_esp8266} - -D USERMOD_SHT -lib_deps = ${esp8266.lib_deps} - robtillaart/SHT85@~0.3.3 +custom_usermods = ${env:d1_mini.custom_usermods} sht ``` ## MQTT Discovery for Home Assistant diff --git a/usermods/sht/usermod_sht.h b/usermods/sht/sht.cpp similarity index 79% rename from usermods/sht/usermod_sht.h rename to usermods/sht/sht.cpp index f10c78a25..e1eb9e885 100644 --- a/usermods/sht/usermod_sht.h +++ b/usermods/sht/sht.cpp @@ -1,74 +1,6 @@ -#ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." -#endif - -#pragma once - +#include "ShtUsermod.h" #include "SHT85.h" -#define USERMOD_SHT_TYPE_SHT30 0 -#define USERMOD_SHT_TYPE_SHT31 1 -#define USERMOD_SHT_TYPE_SHT35 2 -#define USERMOD_SHT_TYPE_SHT85 3 - -class ShtUsermod : public Usermod -{ - private: - bool enabled = false; // Is usermod enabled or not - bool firstRunDone = false; // Remembers if the first config load run had been done - bool initDone = false; // Remembers if the mod has been completely initialised - bool haMqttDiscovery = false; // Is MQTT discovery enabled or not - bool haMqttDiscoveryDone = false; // Remembers if we already published the HA discovery topics - - // SHT vars - SHT *shtTempHumidSensor = nullptr; // Instance of SHT lib - byte shtType = 0; // SHT sensor type to be used. Default: SHT30 - byte unitOfTemp = 0; // Temperature unit to be used. Default: Celsius (0 = Celsius, 1 = Fahrenheit) - bool shtInitDone = false; // Remembers if SHT sensor has been initialised - bool shtReadDataSuccess = false; // Did we have a successful data read and is a valid temperature and humidity available? - const byte shtI2cAddress = 0x44; // i2c address of the sensor. 0x44 is the default for all SHT sensors. Change this, if needed - unsigned long shtLastTimeUpdated = 0; // Remembers when we read data the last time - bool shtDataRequested = false; // Reading data is done async. This remembers if we asked the sensor to read data - float shtCurrentTempC = 0.0f; // Last read temperature in Celsius - float shtCurrentHumidity = 0.0f; // Last read humidity in RH% - - - void initShtTempHumiditySensor(); - void cleanupShtTempHumiditySensor(); - void cleanup(); - inline bool isShtReady() { return shtInitDone; } // Checks if the SHT sensor has been initialised. - - void publishTemperatureAndHumidityViaMqtt(); - void publishHomeAssistantAutodiscovery(); - void appendDeviceToMqttDiscoveryMessage(JsonDocument& root); - - public: - // Strings to reduce flash memory usage (used more than twice) - static const char _name[]; - static const char _enabled[]; - static const char _shtType[]; - static const char _unitOfTemp[]; - static const char _haMqttDiscovery[]; - - void setup(); - void loop(); - void onMqttConnect(bool sessionPresent); - void appendConfigData(); - void addToConfig(JsonObject &root); - bool readFromConfig(JsonObject &root); - void addToJsonInfo(JsonObject& root); - - bool isEnabled() { return enabled; } - - float getTemperature(); - float getTemperatureC() { return roundf(shtCurrentTempC * 10.0f) / 10.0f; } - float getTemperatureF() { return (getTemperatureC() * 1.8f) + 32.0f; } - float getHumidity() { return roundf(shtCurrentHumidity * 10.0f) / 10.0f; } - const char* getUnitString(); - - uint16_t getId() { return USERMOD_ID_SHT; } -}; - // Strings to reduce flash memory usage (used more than twice) const char ShtUsermod::_name[] PROGMEM = "SHT-Sensor"; const char ShtUsermod::_enabled[] PROGMEM = "Enabled"; @@ -477,4 +409,7 @@ float ShtUsermod::getTemperature() { */ const char* ShtUsermod::getUnitString() { return unitOfTemp ? "°F" : "°C"; -} \ No newline at end of file +} + +static ShtUsermod sht; +REGISTER_USERMOD(sht); diff --git a/usermods/smartnest/library.json b/usermods/smartnest/library.json new file mode 100644 index 000000000..e2c6ab351 --- /dev/null +++ b/usermods/smartnest/library.json @@ -0,0 +1,3 @@ +{ + "name:": "smartnest" +} \ No newline at end of file diff --git a/usermods/smartnest/usermod_smartnest.h b/usermods/smartnest/smartnest.cpp similarity index 98% rename from usermods/smartnest/usermod_smartnest.h rename to usermods/smartnest/smartnest.cpp index 9d21ef2e7..d0cb92dcf 100644 --- a/usermods/smartnest/usermod_smartnest.h +++ b/usermods/smartnest/smartnest.cpp @@ -1,11 +1,9 @@ -#ifndef WLED_ENABLE_MQTT +#include "wled.h" + +#ifdef WLED_DISABLE_MQTT #error "This user mod requires MQTT to be enabled." #endif -#pragma once - -#include "wled.h" - class Smartnest : public Usermod { private: @@ -203,3 +201,7 @@ public: } } }; + + +static Smartnest smartnest; +REGISTER_USERMOD(smartnest); \ No newline at end of file diff --git a/usermods/stairway_wipe_basic/library.json b/usermods/stairway_wipe_basic/library.json new file mode 100644 index 000000000..59cb5da93 --- /dev/null +++ b/usermods/stairway_wipe_basic/library.json @@ -0,0 +1,3 @@ +{ + "name:": "stairway_wipe_basic" +} \ No newline at end of file diff --git a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h b/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp similarity index 97% rename from usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h rename to usermods/stairway_wipe_basic/stairway_wipe_basic.cpp index f603ed6f3..cddd655d6 100644 --- a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h +++ b/usermods/stairway_wipe_basic/stairway_wipe_basic.cpp @@ -126,3 +126,7 @@ void setup() { //More methods can be added in the future, this example will then be extended. //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! }; + + +static StairwayWipeUsermod stairway_wipe_basic; +REGISTER_USERMOD(stairway_wipe_basic); \ No newline at end of file diff --git a/usermods/usermod_rotary_brightness_color/README.md b/usermods/usermod_rotary_brightness_color/README.md index 06a3a0f82..feb778dd6 100644 --- a/usermods/usermod_rotary_brightness_color/README.md +++ b/usermods/usermod_rotary_brightness_color/README.md @@ -37,6 +37,7 @@ Open Usermod Settings in WLED to change settings: No special requirements. ## Change Log - -2021-07 -* Upgraded to work with the latest WLED code, and make settings configurable in Usermod Settings +- 2021-07
+Upgraded to work with the latest WLED code, and make settings configurable in Usermod Settings +- 2025-03
+Upgraded to work with the latest WLED code diff --git a/usermods/usermod_rotary_brightness_color/library.json b/usermods/usermod_rotary_brightness_color/library.json new file mode 100644 index 000000000..777ec19c0 --- /dev/null +++ b/usermods/usermod_rotary_brightness_color/library.json @@ -0,0 +1,3 @@ +{ + "name:": "usermod_rotary_brightness_color" +} \ No newline at end of file diff --git a/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h b/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.cpp similarity index 91% rename from usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h rename to usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.cpp index 85a9a1605..0a485152f 100644 --- a/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h +++ b/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" //v2 usermod that allows to change brightness and color using a rotary encoder, @@ -95,9 +93,9 @@ public: } else { - fastled_col.red = col[0]; - fastled_col.green = col[1]; - fastled_col.blue = col[2]; + fastled_col.red = colPri[0]; + fastled_col.green = colPri[1]; + fastled_col.blue = colPri[2]; prim_hsv = rgb2hsv_approximate(fastled_col); new_val = (int16_t)prim_hsv.h + fadeAmount; if (new_val > 255) @@ -106,9 +104,9 @@ public: new_val += 255; // roll-over if smaller than 0 prim_hsv.h = (byte)new_val; hsv2rgb_rainbow(prim_hsv, fastled_col); - col[0] = fastled_col.red; - col[1] = fastled_col.green; - col[2] = fastled_col.blue; + colPri[0] = fastled_col.red; + colPri[1] = fastled_col.green; + colPri[2] = fastled_col.blue; } } else if (Enc_B == LOW) @@ -120,9 +118,9 @@ public: } else { - fastled_col.red = col[0]; - fastled_col.green = col[1]; - fastled_col.blue = col[2]; + fastled_col.red = colPri[0]; + fastled_col.green = colPri[1]; + fastled_col.blue = colPri[2]; prim_hsv = rgb2hsv_approximate(fastled_col); new_val = (int16_t)prim_hsv.h - fadeAmount; if (new_val > 255) @@ -131,9 +129,9 @@ public: new_val += 255; // roll-over if smaller than 0 prim_hsv.h = (byte)new_val; hsv2rgb_rainbow(prim_hsv, fastled_col); - col[0] = fastled_col.red; - col[1] = fastled_col.green; - col[2] = fastled_col.blue; + colPri[0] = fastled_col.red; + colPri[1] = fastled_col.green; + colPri[2] = fastled_col.blue; } } //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) @@ -187,3 +185,7 @@ public: return configComplete; } }; + + +static RotaryEncoderBrightnessColor usermod_rotary_brightness_color; +REGISTER_USERMOD(usermod_rotary_brightness_color); \ No newline at end of file diff --git a/usermods/usermod_v2_HttpPullLightControl/library.json.disabled b/usermods/usermod_v2_HttpPullLightControl/library.json.disabled new file mode 100644 index 000000000..0f66710b3 --- /dev/null +++ b/usermods/usermod_v2_HttpPullLightControl/library.json.disabled @@ -0,0 +1,3 @@ +{ + "name:": "usermod_v2_HttpPullLightControl" +} \ No newline at end of file diff --git a/usermods/usermod_v2_RF433/library.json b/usermods/usermod_v2_RF433/library.json new file mode 100644 index 000000000..9ba2bdcf6 --- /dev/null +++ b/usermods/usermod_v2_RF433/library.json @@ -0,0 +1,6 @@ +{ + "name:": "usermod_v2_RF433", + "dependencies": { + "sui77/rc-switch":"2.6.4" + } +} \ No newline at end of file diff --git a/usermods/usermod_v2_RF433/usermod_v2_RF433.h b/usermods/usermod_v2_RF433/usermod_v2_RF433.cpp similarity index 98% rename from usermods/usermod_v2_RF433/usermod_v2_RF433.h rename to usermods/usermod_v2_RF433/usermod_v2_RF433.cpp index ebaf433f1..9ac6c416d 100644 --- a/usermods/usermod_v2_RF433/usermod_v2_RF433.h +++ b/usermods/usermod_v2_RF433/usermod_v2_RF433.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include "Arduino.h" #include @@ -181,3 +179,5 @@ const char RF433Usermod::_modName[] PROGMEM = "RF433 Remote"; const char RF433Usermod::_modEnabled[] PROGMEM = "Enabled"; const char RF433Usermod::_receivePin[] PROGMEM = "RX Pin"; +static RF433Usermod usermod_v2_RF433; +REGISTER_USERMOD(usermod_v2_RF433); diff --git a/usermods/usermod_v2_animartrix/library.json b/usermods/usermod_v2_animartrix/library.json new file mode 100644 index 000000000..4552be330 --- /dev/null +++ b/usermods/usermod_v2_animartrix/library.json @@ -0,0 +1,6 @@ +{ + "name": "animartrix", + "dependencies": { + "Animartrix": "https://github.com/netmindz/animartrix.git#b172586" + } +} diff --git a/usermods/usermod_v2_animartrix/readme.md b/usermods/usermod_v2_animartrix/readme.md index 42d463c50..f0ff60a78 100644 --- a/usermods/usermod_v2_animartrix/readme.md +++ b/usermods/usermod_v2_animartrix/readme.md @@ -6,9 +6,5 @@ CC BY-NC 3.0 licensed effects by Stefan Petrick, include this usermod only if yo ## Installation -Please uncomment the two references to ANIMartRIX in your platform.ini - -lib_dep to a version of https://github.com/netmindz/animartrix.git -and the build_flags -D USERMOD_ANIMARTRIX - +Add 'animartrix' to 'custom_usermods' in your platformio_override.ini. diff --git a/usermods/usermod_v2_animartrix/usermod_v2_animartrix.h b/usermods/usermod_v2_animartrix/usermod_v2_animartrix.cpp similarity index 99% rename from usermods/usermod_v2_animartrix/usermod_v2_animartrix.h rename to usermods/usermod_v2_animartrix/usermod_v2_animartrix.cpp index d91cf6c96..d2968f2fb 100644 --- a/usermods/usermod_v2_animartrix/usermod_v2_animartrix.h +++ b/usermods/usermod_v2_animartrix/usermod_v2_animartrix.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include @@ -452,5 +450,6 @@ class AnimartrixUsermod : public Usermod { }; - +static AnimartrixUsermod animartrix_module("Animartrix", false); +REGISTER_USERMOD(animartrix_module); diff --git a/usermods/usermod_v2_auto_save/library.json b/usermods/usermod_v2_auto_save/library.json new file mode 100644 index 000000000..d703487a7 --- /dev/null +++ b/usermods/usermod_v2_auto_save/library.json @@ -0,0 +1,3 @@ +{ + "name": "auto_save" +} \ No newline at end of file diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.cpp similarity index 99% rename from usermods/usermod_v2_auto_save/usermod_v2_auto_save.h rename to usermods/usermod_v2_auto_save/usermod_v2_auto_save.cpp index a257413b4..1b97ea94d 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" // v2 Usermod to automatically save settings @@ -275,3 +273,6 @@ const char AutoSaveUsermod::_autoSaveEnabled[] PROGMEM = "enabled"; const char AutoSaveUsermod::_autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec"; const char AutoSaveUsermod::_autoSavePreset[] PROGMEM = "autoSavePreset"; const char AutoSaveUsermod::_autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot"; + +static AutoSaveUsermod autosave; +REGISTER_USERMOD(autosave); diff --git a/usermods/usermod_v2_four_line_display_ALT/library.json.disabled b/usermods/usermod_v2_four_line_display_ALT/library.json.disabled new file mode 100644 index 000000000..56612c96e --- /dev/null +++ b/usermods/usermod_v2_four_line_display_ALT/library.json.disabled @@ -0,0 +1,3 @@ +{ + "name:": "usermod_v2_four_line_display_ALT" +} \ No newline at end of file diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.cpp similarity index 99% rename from usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h rename to usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.cpp index 684dd86e4..93c4110c3 100644 --- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h +++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #undef U8X8_NO_HW_I2C // borrowed from WLEDMM: we do want I2C hardware drivers - if possible #include // from https://github.com/olikraus/u8g2/ @@ -1386,3 +1384,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) { // use "return !top["newestParameter"].isNull();" when updating Usermod with new features return !top[FPSTR(_contrastFix)].isNull(); } + + +static FourLineDisplayUsermod usermod_v2_four_line_display_alt; +REGISTER_USERMOD(usermod_v2_four_line_display_alt); \ No newline at end of file diff --git a/usermods/usermod_v2_klipper_percentage/library.json b/usermods/usermod_v2_klipper_percentage/library.json new file mode 100644 index 000000000..b31fb1ad1 --- /dev/null +++ b/usermods/usermod_v2_klipper_percentage/library.json @@ -0,0 +1,3 @@ +{ + "name:": "usermod_v2_klipper_percentage" +} \ No newline at end of file diff --git a/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h b/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.cpp similarity index 97% rename from usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h rename to usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.cpp index bd4170dd2..71c5c45f3 100644 --- a/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h +++ b/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" class klipper_percentage : public Usermod @@ -219,4 +217,7 @@ public: } }; const char klipper_percentage::_name[] PROGMEM = "Klipper_Percentage"; -const char klipper_percentage::_enabled[] PROGMEM = "enabled"; \ No newline at end of file +const char klipper_percentage::_enabled[] PROGMEM = "enabled"; + +static klipper_percentage usermod_v2_klipper_percentage; +REGISTER_USERMOD(usermod_v2_klipper_percentage); \ 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 new file mode 100644 index 000000000..fe23cd910 --- /dev/null +++ b/usermods/usermod_v2_ping_pong_clock/library.json @@ -0,0 +1,3 @@ +{ + "name:": "usermod_v2_ping_pong_clock" +} \ No newline at end of file diff --git a/usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.h b/usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.cpp similarity index 97% rename from usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.h rename to usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.cpp index 40ff675c0..c6632b53a 100644 --- a/usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.h +++ b/usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" class PingPongClockUsermod : public Usermod @@ -117,3 +115,7 @@ public: } }; + + +static PingPongClockUsermod usermod_v2_ping_pong_clock; +REGISTER_USERMOD(usermod_v2_ping_pong_clock); \ 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 new file mode 100644 index 000000000..5f857218b --- /dev/null +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/library.json @@ -0,0 +1,3 @@ +{ + "name:": "usermod_v2_rotary_encoder_ui_ALT" +} \ No newline at end of file diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp similarity index 98% rename from usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h rename to usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp index 383c1193e..a0cbc532f 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" // @@ -518,7 +516,7 @@ void RotaryEncoderUIUsermod::setup() loopTime = millis(); - currentCCT = (approximateKelvinFromRGB(RGBW32(col[0], col[1], col[2], col[3])) - 1900) >> 5; + currentCCT = (approximateKelvinFromRGB(RGBW32(colPri[0], colPri[1], colPri[2], colPri[3])) - 1900) >> 5; if (!initDone) sortModesAndPalettes(); @@ -920,17 +918,17 @@ void RotaryEncoderUIUsermod::changeHue(bool increase){ display->updateRedrawTime(); #endif currentHue1 = max(min((increase ? currentHue1+fadeAmount : currentHue1-fadeAmount), 255), 0); - colorHStoRGB(currentHue1*256, currentSat1, col); + colorHStoRGB(currentHue1*256, currentSat1, colPri); stateChanged = true; if (applyToAll) { for (unsigned i=0; iupdateRedrawTime(); #endif currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0); - colorHStoRGB(currentHue1*256, currentSat1, col); + colorHStoRGB(currentHue1*256, currentSat1, colPri); if (applyToAll) { for (unsigned i=0; i #include "wled.h" @@ -124,4 +122,7 @@ class WireguardUsermod : public Usermod { int endpoint_port = 0; bool is_enabled = false; unsigned long lastTime = 0; -}; \ No newline at end of file +}; + +static WireguardUsermod wireguard; +REGISTER_USERMOD(wireguard); \ No newline at end of file diff --git a/usermods/wizlights/library.json b/usermods/wizlights/library.json new file mode 100644 index 000000000..687fba0f7 --- /dev/null +++ b/usermods/wizlights/library.json @@ -0,0 +1,3 @@ +{ + "name:": "wizlights" +} \ No newline at end of file diff --git a/usermods/wizlights/wizlights.h b/usermods/wizlights/wizlights.cpp similarity index 98% rename from usermods/wizlights/wizlights.h rename to usermods/wizlights/wizlights.cpp index 08d204934..3ac756b12 100644 --- a/usermods/wizlights/wizlights.h +++ b/usermods/wizlights/wizlights.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" #include @@ -156,3 +154,7 @@ class WizLightsUsermod : public Usermod { uint16_t getId(){return USERMOD_ID_WIZLIGHTS;} }; + + +static WizLightsUsermod wizlights; +REGISTER_USERMOD(wizlights); \ No newline at end of file diff --git a/usermods/word-clock-matrix/library.json.disabled b/usermods/word-clock-matrix/library.json.disabled new file mode 100644 index 000000000..d971dfff4 --- /dev/null +++ b/usermods/word-clock-matrix/library.json.disabled @@ -0,0 +1,3 @@ +{ + "name:": "word-clock-matrix" +} \ No newline at end of file diff --git a/usermods/word-clock-matrix/usermod_word_clock_matrix.h b/usermods/word-clock-matrix/word-clock-matrix.cpp similarity index 99% rename from usermods/word-clock-matrix/usermod_word_clock_matrix.h rename to usermods/word-clock-matrix/word-clock-matrix.cpp index 82499c0ce..cd8f78c3a 100644 --- a/usermods/word-clock-matrix/usermod_word_clock_matrix.h +++ b/usermods/word-clock-matrix/word-clock-matrix.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "wled.h" /* @@ -336,3 +334,7 @@ public: }; + + +static WordClockMatrix word_clock_matrix; +REGISTER_USERMOD(word_clock_matrix); \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 3544e1fa7..1f8a315a6 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -676,8 +676,10 @@ typedef struct Segment { [[gnu::hot]] uint32_t getPixelColor(int i) const; // 1D support functions (some implement 2D as well) void blur(uint8_t, bool smear = false); + void clear(); void fill(uint32_t c); void fade_out(uint8_t r); + void fadeToSecondaryBy(uint8_t fadeBy); void fadeToBlackBy(uint8_t fadeBy); inline void blendPixelColor(int n, uint32_t color, uint8_t blend) { setPixelColor(n, color_blend(getPixelColor(n), color, blend)); } inline void blendPixelColor(int n, CRGB c, uint8_t blend) { blendPixelColor(n, RGBW32(c.r,c.g,c.b,0), blend); } diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 893123335..61d14a12b 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -684,9 +684,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); break; // 5x12 font default: return; } - uint32_t c = ColorFromPaletteWLED(grad, (i+1)*255/h, 255, NOBLEND); - // pre-scale color for all pixels - c = color_fade(c, _segBri); + CRGBW c = ColorFromPalette(grad, (i+1)*255/h, _segBri, LINEARBLEND_NOWRAP); _colorScaled = true; for (int j = 0; j= (int)vWidth() || y0 < 0 || y0 >= (int)vHeight()) continue; // drawing off-screen if (((bits>>(j+(8-w))) & 0x01)) { // bit set - setPixelColorXY(x0, y0, c); + setPixelColorXY(x0, y0, c.color32); } } _colorScaled = false; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7bd875ad0..9acc36e7c 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -270,7 +270,7 @@ void Segment::startTransition(uint16_t dur) { _t->_briT = on ? opacity : 0; _t->_cctT = cct; #ifndef WLED_DISABLE_MODE_BLEND - swapSegenv(_t->_segT); + swapSegenv(_t->_segT); // copy runtime data to temporary _t->_modeT = mode; _t->_segT._dataLenT = 0; _t->_segT._dataT = nullptr; @@ -282,6 +282,13 @@ void Segment::startTransition(uint16_t dur) { _t->_segT._dataLenT = _dataLen; } } + DEBUG_PRINTF_P(PSTR("-- pal: %d, bri: %d, C:[%08X,%08X,%08X], m: %d\n"), + (int)_t->_palTid, + (int)_t->_briT, + _t->_segT._colorT[0], + _t->_segT._colorT[1], + _t->_segT._colorT[2], + (int)_t->_modeT); #else for (size_t i=0; i_colorT[i] = colors[i]; #endif @@ -502,21 +509,17 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui #ifndef WLED_DISABLE_2D if (Segment::maxHeight>1) boundsUnchanged &= (startY == i1Y && stopY == i2Y); // 2D #endif + + if (stop && (spc > 0 || m12 != map1D2D)) clear(); +/* if (boundsUnchanged && (!grp || (grouping == grp && spacing == spc)) && (ofs == UINT16_MAX || ofs == offset) && (m12 == map1D2D) ) return; - +*/ stateChanged = true; // send UDP/WS broadcast - if (stop || spc != spacing || m12 != map1D2D) { - _vWidth = virtualWidth(); - _vHeight = virtualHeight(); - _vLength = virtualLength(); - _segBri = currentBri(); - fill(BLACK); // turn old segment range off or clears pixels if changing spacing (requires _vWidth/_vHeight/_vLength/_segBri) - } if (grp) { // prevent assignment of 0 grouping = grp; spacing = spc; @@ -527,10 +530,7 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui if (ofs < UINT16_MAX) offset = ofs; map1D2D = constrain(m12, 0, 7); - DEBUG_PRINT(F("setUp segment: ")); DEBUG_PRINT(i1); - DEBUG_PRINT(','); DEBUG_PRINT(i2); - DEBUG_PRINT(F(" -> ")); DEBUG_PRINT(i1Y); - DEBUG_PRINT(','); DEBUG_PRINTLN(i2Y); + DEBUG_PRINTF_P(PSTR("Segment geometry: %d,%d -> %d,%d\n"), (int)i1, (int)i2, (int)i1Y, (int)i2Y); markForReset(); if (boundsUnchanged) return; @@ -1138,12 +1138,9 @@ void Segment::refreshLightCapabilities() { } for (unsigned b = 0; b < BusManager::getNumBusses(); b++) { - Bus *bus = BusManager::getBus(b); - if (bus == nullptr || bus->getLength()==0) break; - if (!bus->isOk()) continue; - if (bus->getStart() >= segStopIdx) continue; - if (bus->getStart() + bus->getLength() <= segStartIdx) continue; - + const Bus *bus = BusManager::getBus(b); + if (!bus || !bus->isOk()) break; + if (bus->getStart() >= segStopIdx || bus->getStart() + bus->getLength() <= segStartIdx) continue; if (bus->hasRGB() || (strip.cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB; if (!strip.cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT; if (strip.correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider) @@ -1159,6 +1156,26 @@ void Segment::refreshLightCapabilities() { _capabilities = capabilities; } +/* + * Fills segment with black + */ +void Segment::clear() { + if (!isActive()) return; // not active + unsigned oldVW = _vWidth; + unsigned oldVH = _vHeight; + unsigned oldVL = _vLength; + unsigned oldSB = _segBri; + _vWidth = virtualWidth(); + _vHeight = virtualHeight(); + _vLength = virtualLength(); + _segBri = currentBri(); + fill(BLACK); + _vWidth = oldVW; + _vHeight = oldVH; + _vLength = oldVL; + _segBri = oldSB; +} + /* * Fills segment with color */ @@ -1178,42 +1195,45 @@ void Segment::fill(uint32_t c) { /* * fade out function, higher rate = quicker fade + * fading is highly dependant on frame rate (higher frame rates, faster fading) + * each frame will fade at max 9% or as little as 0.8% */ void Segment::fade_out(uint8_t rate) { if (!isActive()) return; // not active const int cols = is2D() ? vWidth() : vLength(); const int rows = vHeight(); // will be 1 for 1D - rate = (255-rate) >> 1; - float mappedRate = 1.0f / (float(rate) + 1.1f); - - uint32_t color = colors[1]; // SEGCOLOR(1); // target color - int w2 = W(color); - int r2 = R(color); - int g2 = G(color); - int b2 = B(color); + rate = (256-rate) >> 1; + const int mappedRate = 256 / (rate + 1); for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { - color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x); + uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x); if (color == colors[1]) continue; // already at target color - int w1 = W(color); - int r1 = R(color); - int g1 = G(color); - int b1 = B(color); + for (int i = 0; i < 32; i += 8) { + uint8_t c2 = (colors[1]>>i); // get background channel + uint8_t c1 = (color>>i); // get foreground channel + // we can't use bitshift since we are using int + int delta = (c2 - c1) * mappedRate / 256; + // if fade isn't complete, make sure delta is at least 1 (fixes rounding issues) + if (delta == 0) delta += (c2 == c1) ? 0 : (c2 > c1) ? 1 : -1; + // stuff new value back into color + color &= ~(0xFF< w1) ? 1 : -1; - rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1; - gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1; - bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1; - - if (is2D()) setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); - else setPixelColor(x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); + for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { + if (is2D()) setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), colors[1], fadeBy)); + else setPixelColor(x, color_blend(getPixelColor(x), colors[1], fadeBy)); } } @@ -1291,12 +1311,12 @@ uint32_t Segment::color_wheel(uint8_t pos) const { * Gets a single color from the currently selected palette. * @param i Palette Index (if mapping is true, the full palette will be _virtualSegmentLength long, if false, 255). Will wrap around automatically. * @param mapping if true, LED position in segment is considered for color - * @param wrap FastLED palettes will usually wrap back to the start smoothly. Set false to get a hard edge + * @param moving FastLED palettes will usually wrap back to the start smoothly. Set to true if effect has moving palette and you want wrap. * @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead * @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling) * @returns Single color from palette */ -uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) const { +uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool moving, uint8_t mcol, uint8_t pbri) const { uint32_t color = getCurrentColor(mcol < NUM_COLORS ? mcol : 0); // default palette or no RGB support on segment if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) { @@ -1306,9 +1326,15 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_ const int vL = vLength(); unsigned paletteIndex = i; if (mapping && vL > 1) paletteIndex = (i*255)/(vL -1); - // paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined) - if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end" - CRGBW palcol = ColorFromPaletteWLED(_currentPalette, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global + // paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined/no interpolation of palette entries) + // ColorFromPalette interpolations are: NOBLEND, LINEARBLEND, LINEARBLEND_NOWRAP + TBlendType blend = NOBLEND; + switch (strip.paletteBlend) { // NOTE: paletteBlend should be global + case 0: blend = moving ? LINEARBLEND : LINEARBLEND_NOWRAP; break; + case 1: blend = LINEARBLEND; break; + case 2: blend = LINEARBLEND_NOWRAP; break; + } + CRGBW palcol = ColorFromPalette(_currentPalette, paletteIndex, pbri, blend); palcol.w = W(color); return palcol.color32; @@ -1449,8 +1475,7 @@ void WS2812FX::finalizeInit() { _length = 0; for (int i=0; igetStart() + bus->getLength() > MAX_LEDS) break; + if (!bus || !bus->isOk() || bus->getStart() + bus->getLength() > MAX_LEDS) break; //RGBW mode is enabled if at least one of the strips is RGBW _hasWhiteChannel |= bus->hasWhite(); //refresh is required to remain off if at least one of the strips requires the refresh. @@ -1460,6 +1485,7 @@ void WS2812FX::finalizeInit() { // This must be done after all buses have been created, as some kinds (parallel I2S) interact bus->begin(); + bus->setBrightness(bri); } DEBUG_PRINTF_P(PSTR("Heap after buses: %d\n"), ESP.getFreeHeap()); @@ -1490,7 +1516,7 @@ void WS2812FX::service() { _segment_index = 0; for (segment &seg : _segments) { - if (_suspend) return; // immediately stop processing segments if suspend requested during service() + if (_suspend) break; // immediately stop processing segments if suspend requested during service() // process transition (mode changes in the middle of transition) seg.handleTransition(); @@ -1521,6 +1547,11 @@ void WS2812FX::service() { #ifndef WLED_DISABLE_MODE_BLEND Segment::setClippingRect(0, 0); // disable clipping (just in case) if (seg.isInTransition()) { + // a hack to determine if effect has changed + uint8_t m = seg.currentMode(); + Segment::modeBlend(true); // set semaphore + bool sameEffect = (m == seg.currentMode()); + Segment::modeBlend(false); // clear semaphore // set clipping rectangle // new mode is run inside clipping area and old mode outside clipping area unsigned p = seg.progress(); @@ -1529,7 +1560,20 @@ void WS2812FX::service() { unsigned dw = p * w / 0xFFFFU + 1; unsigned dh = p * h / 0xFFFFU + 1; unsigned orgBS = blendingStyle; - if (w*h == 1) blendingStyle = BLEND_STYLE_FADE; // disable belending for single pixel segments (use fade instead) + if (w*h == 1) blendingStyle = BLEND_STYLE_FADE; // disable style for single pixel segments (use fade instead) + else if (sameEffect && (blendingStyle & BLEND_STYLE_PUSH_MASK)) { + // when effect stays the same push will look awful, change it to swipe + switch (blendingStyle) { + case BLEND_STYLE_PUSH_BR: + case BLEND_STYLE_PUSH_TR: + case BLEND_STYLE_PUSH_RIGHT: blendingStyle = BLEND_STYLE_SWIPE_RIGHT; break; + case BLEND_STYLE_PUSH_BL: + case BLEND_STYLE_PUSH_TL: + case BLEND_STYLE_PUSH_LEFT: blendingStyle = BLEND_STYLE_SWIPE_LEFT; break; + case BLEND_STYLE_PUSH_DOWN: blendingStyle = BLEND_STYLE_SWIPE_DOWN; break; + case BLEND_STYLE_PUSH_UP: blendingStyle = BLEND_STYLE_SWIPE_UP; break; + } + } switch (blendingStyle) { case BLEND_STYLE_FAIRY_DUST: // fairy dust (must set entire segment, see isPixelXYClipped()) Segment::setClippingRect(0, w, 0, h); @@ -1575,7 +1619,7 @@ void WS2812FX::service() { Segment::setClippingRect(0, dw, h - dh, h); break; } - frameDelay = (*_mode[seg.currentMode()])(); // run new/current mode + frameDelay = (*_mode[m])(); // run new/current mode // now run old/previous mode Segment::tmpsegd_t _tmpSegData; Segment::modeBlend(true); // set semaphore @@ -1611,8 +1655,8 @@ void WS2812FX::service() { if (doShow) { yield(); Segment::handleRandomPalette(); // slowly transition random palette; move it into for loop when each segment has individual random palette - show(); _lastServiceShow = nowUp; // update timestamp, for precise FPS control + if (!_suspend) show(); } #ifdef WLED_DEBUG if ((_targetFps != FPS_UNLIMITED) && (millis() - nowUp > _frametime)) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); @@ -1747,8 +1791,8 @@ uint16_t WS2812FX::getLengthPhysical() const { //not influenced by auto-white mode, also true if white slider does not affect output white channel bool WS2812FX::hasRGBWBus() const { for (size_t b = 0; b < BusManager::getNumBusses(); b++) { - Bus *bus = BusManager::getBus(b); - if (bus == nullptr || bus->getLength()==0) break; + const Bus *bus = BusManager::getBus(b); + if (!bus || !bus->isOk()) break; if (bus->hasRGB() && bus->hasWhite()) return true; } return false; @@ -1757,8 +1801,8 @@ bool WS2812FX::hasRGBWBus() const { bool WS2812FX::hasCCTBus() const { if (cctFromRgb && !correctWB) return false; for (size_t b = 0; b < BusManager::getNumBusses(); b++) { - Bus *bus = BusManager::getBus(b); - if (bus == nullptr || bus->getLength()==0) break; + const Bus *bus = BusManager::getBus(b); + if (!bus || !bus->isOk()) break; if (bus->hasCCT()) return true; } return false; @@ -1811,10 +1855,11 @@ void WS2812FX::makeAutoSegments(bool forceReset) { #endif for (size_t i = s; i < BusManager::getNumBusses(); i++) { - Bus* b = BusManager::getBus(i); + const Bus *bus = BusManager::getBus(i); + if (!bus || !bus->isOk()) break; - segStarts[s] = b->getStart(); - segStops[s] = segStarts[s] + b->getLength(); + segStarts[s] = bus->getStart(); + segStops[s] = segStarts[s] + bus->getLength(); #ifndef WLED_DISABLE_2D if (isMatrix && segStops[s] <= Segment::maxWidth*Segment::maxHeight) continue; // ignore buses comprising matrix @@ -1904,7 +1949,8 @@ bool WS2812FX::checkSegmentAlignment() const { bool aligned = false; for (const segment &seg : _segments) { for (unsigned b = 0; bisOk()) break; if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true; } if (seg.start == 0 && seg.stop == _length) aligned = true; diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 6423a436b..cee34c2ea 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -43,6 +43,8 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const #define W(c) (byte((c) >> 24)) +static ColorOrderMap _colorOrderMap = {}; + bool ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) { if (count() >= WLED_MAX_COLOR_ORDER_MAPPINGS || len == 0 || (colorOrder & 0x0F) > COL_ORDER_MAX) return false; // upper nibble contains W swap information _mappings.push_back({start,len,colorOrder}); @@ -53,10 +55,8 @@ bool ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) { uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const { // upper nibble contains W swap information // when ColorOrderMap's upper nibble contains value >0 then swap information is used from it, otherwise global swap is used - for (unsigned i = 0; i < count(); i++) { - if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) { - return _mappings[i].colorOrder | ((_mappings[i].colorOrder >> 4) ? 0 : (defaultColorOrder & 0xF0)); - } + for (const auto& map : _mappings) { + if (pix >= map.start && pix < (map.start + map.len)) return map.colorOrder | ((map.colorOrder >> 4) ? 0 : (defaultColorOrder & 0xF0)); } return defaultColorOrder; } @@ -72,7 +72,7 @@ void Bus::calculateCCT(uint32_t c, uint8_t &ww, uint8_t &cw) { } else { cct = (approximateKelvinFromRGB(c) - 1900) >> 5; // convert K (from RGB value) to relative format } - + //0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold) if (cct < _cctBlend) ww = 255; else ww = ((255-cct) * 255) / (255 - _cctBlend); @@ -99,23 +99,14 @@ uint32_t Bus::autoWhiteCalc(uint32_t c) const { return RGBW32(r, g, b, w); } -uint8_t *Bus::allocateData(size_t size) { - freeData(); // should not happen, but for safety - return _data = (uint8_t *)(size>0 ? calloc(size, sizeof(uint8_t)) : nullptr); -} -void Bus::freeData() { - if (_data) free(_data); - _data = nullptr; -} - -BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com) +BusDigital::BusDigital(const BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start, bc.autoWhite, bc.count, bc.reversed, (bc.refreshReq || bc.type == TYPE_TM1814)) , _skip(bc.skipAmount) //sacrificial pixels , _colorOrder(bc.colorOrder) , _milliAmpsPerLed(bc.milliAmpsPerLed) , _milliAmpsMax(bc.milliAmpsMax) -, _colorOrderMap(com) +, _data(nullptr) { DEBUGBUS_PRINTLN(F("Bus: Creating digital bus.")); if (!isDigital(bc.type) || !bc.count) { DEBUGBUS_PRINTLN(F("Not digial or empty bus!")); return; } @@ -136,12 +127,14 @@ BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com _hasRgb = hasRGB(bc.type); _hasWhite = hasWhite(bc.type); _hasCCT = hasCCT(bc.type); - if (bc.doubleBuffer && !allocateData(bc.count * Bus::getNumberOfChannels(bc.type))) { DEBUGBUS_PRINTLN(F("Buffer allocation failed!")); return; } - //_buffering = bc.doubleBuffer; + if (bc.doubleBuffer) { + _data = (uint8_t*)calloc(_len, Bus::getNumberOfChannels(_type)); + if (!_data) DEBUGBUS_PRINTLN(F("Bus: Buffer allocation failed!")); + } uint16_t lenToCreate = bc.count; if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus _busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr); - _valid = (_busPtr != nullptr); + _valid = (_busPtr != nullptr) && bc.count > 0; DEBUGBUS_PRINTF_P(PSTR("Bus: %successfully inited #%u (len:%u, type:%u (RGB:%d, W:%d, CCT:%d), pins:%u,%u [itype:%u] mA=%d/%d)\n"), _valid?"S":"Uns", (int)nr, @@ -268,7 +261,7 @@ void BusDigital::show() { } } } - PolyBus::show(_busPtr, _iType, !_data); // faster if buffer consistency is not important (use !_buffering this causes 20% FPS drop) + PolyBus::show(_busPtr, _iType, !_data); // faster if buffer consistency is not important // restore bus brightness to its original value // this is done right after show, so this is only OK if LED updates are completed before show() returns // or async show has a separate buffer (ESP32 RMT and I2S are ok) @@ -421,11 +414,11 @@ void BusDigital::begin() { void BusDigital::cleanup() { DEBUGBUS_PRINTLN(F("Digital Cleanup.")); PolyBus::cleanup(_busPtr, _iType); + free(_data); + _data = nullptr; _iType = I_NONE; _valid = false; _busPtr = nullptr; - freeData(); - //PinManager::deallocateMultiplePins(_pins, 2, PinOwner::BusDigital); PinManager::deallocatePin(_pins[1], PinOwner::BusDigital); PinManager::deallocatePin(_pins[0], PinOwner::BusDigital); } @@ -449,7 +442,7 @@ void BusDigital::cleanup() { #else #ifdef SOC_LEDC_TIMER_BIT_WIDE_NUM // C6/H2/P4: 20 bit, S2/S3/C2/C3: 14 bit - #define MAX_BIT_WIDTH SOC_LEDC_TIMER_BIT_WIDE_NUM + #define MAX_BIT_WIDTH SOC_LEDC_TIMER_BIT_WIDE_NUM #else // ESP32: 20 bit (but in reality we would never go beyond 16 bit as the frequency would be to low) #define MAX_BIT_WIDTH 14 @@ -497,7 +490,6 @@ BusPwm::BusPwm(const BusConfig &bc) _hasRgb = hasRGB(bc.type); _hasWhite = hasWhite(bc.type); _hasCCT = hasCCT(bc.type); - _data = _pwmdata; // avoid malloc() and use already allocated memory _valid = true; DEBUGBUS_PRINTF_P(PSTR("%successfully inited PWM strip with type %u, frequency %u, bit depth %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _frequency, _depth, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]); } @@ -561,7 +553,7 @@ uint32_t BusPwm::getPixelColor(unsigned pix) const { void BusPwm::show() { if (!_valid) return; - const unsigned numPins = getPins(); + const size_t numPins = getPins(); #ifdef ESP8266 const unsigned analogPeriod = F_CPU / _frequency; const unsigned maxBri = analogPeriod; // compute to clock cycle accuracy @@ -571,7 +563,7 @@ void BusPwm::show() { // if _needsRefresh is true (UI hack) we are using dithering (credit @dedehai & @zalatnaicsongor) // https://github.com/wled-dev/WLED/pull/4115 and https://github.com/zalatnaicsongor/WLED/pull/1) const bool dithering = _needsRefresh; // avoid working with bitfield - const unsigned maxBri = (1<<_depth); // possible values: 16384 (14), 8192 (13), 4096 (12), 2048 (11), 1024 (10), 512 (9) and 256 (8) + const unsigned maxBri = (1<<_depth); // possible values: 16384 (14), 8192 (13), 4096 (12), 2048 (11), 1024 (10), 512 (9) and 256 (8) const unsigned bitShift = dithering * 4; // if dithering, _depth is 12 bit but LEDC channel is set to 8 bit (using 4 fractional bits) #endif // use CIE brightness formula (linear + cubic) to approximate human eye perceived brightness @@ -587,7 +579,7 @@ void BusPwm::show() { [[maybe_unused]] unsigned hPoint = 0; // phase shift (0 - maxBri) // we will be phase shifting every channel by previous pulse length (plus dead time if required) - // phase shifting is only mandatory when using H-bridge to drive reverse-polarity PWM CCT (2 wire) LED type + // phase shifting is only mandatory when using H-bridge to drive reverse-polarity PWM CCT (2 wire) LED type // CCT additive blending must be 0 (WW & CW will not overlap) otherwise signals *will* overlap // for all other cases it will just try to "spread" the load on PSU // Phase shifting requires that LEDC timers are synchronised (see setup()). For PWM CCT (and H-bridge) it is @@ -648,7 +640,7 @@ std::vector BusPwm::getLEDTypes() { } void BusPwm::deallocatePins() { - unsigned numPins = getPins(); + size_t numPins = getPins(); for (unsigned i = 0; i < numPins; i++) { PinManager::deallocatePin(_pins[i], PinOwner::BusPwm); if (!PinManager::isPinOk(_pins[i])) continue; @@ -666,7 +658,7 @@ void BusPwm::deallocatePins() { BusOnOff::BusOnOff(const BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite, 1, bc.reversed) -, _onoffdata(0) +, _data(0) { if (!Bus::isOnOff(bc.type)) return; @@ -679,7 +671,6 @@ BusOnOff::BusOnOff(const BusConfig &bc) _hasRgb = false; _hasWhite = false; _hasCCT = false; - _data = &_onoffdata; // avoid malloc() and use stack _valid = true; DEBUGBUS_PRINTF_P(PSTR("%successfully inited On/Off strip with pin %u\n"), _valid?"S":"Uns", _pin); } @@ -691,17 +682,17 @@ void BusOnOff::setPixelColor(unsigned pix, uint32_t c) { uint8_t g = G(c); uint8_t b = B(c); uint8_t w = W(c); - _data[0] = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0; + _data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0; } uint32_t BusOnOff::getPixelColor(unsigned pix) const { if (!_valid) return 0; - return RGBW32(_data[0], _data[0], _data[0], _data[0]); + return RGBW32(_data, _data, _data, _data); } void BusOnOff::show() { if (!_valid) return; - digitalWrite(_pin, _reversed ? !(bool)_data[0] : (bool)_data[0]); + digitalWrite(_pin, _reversed ? !(bool)_data : (bool)_data); } unsigned BusOnOff::getPins(uint8_t* pinArray) const { @@ -740,7 +731,8 @@ BusNetwork::BusNetwork(const BusConfig &bc) _hasCCT = false; _UDPchannels = _hasWhite + 3; _client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]); - _valid = (allocateData(_len * _UDPchannels) != nullptr); + _data = (uint8_t*)calloc(_len, _UDPchannels); + _valid = (_data != nullptr); DEBUGBUS_PRINTF_P(PSTR("%successfully inited virtual strip with type %u and IP %u.%u.%u.%u\n"), _valid?"S":"Uns", bc.type, bc.pins[0], bc.pins[1], bc.pins[2], bc.pins[3]); } @@ -790,9 +782,10 @@ std::vector BusNetwork::getLEDTypes() { void BusNetwork::cleanup() { DEBUGBUS_PRINTLN(F("Virtual Cleanup.")); + free(_data); + _data = nullptr; _type = I_NONE; _valid = false; - freeData(); } @@ -844,17 +837,17 @@ int BusManager::add(const BusConfig &bc) { unsigned numDigital = 0; for (const auto &bus : busses) if (bus->isDigital() && !bus->is2Pin()) numDigital++; if (Bus::isVirtual(bc.type)) { - //busses.push_back(std::make_unique(bc)); // when C++ >11 - busses.push_back(new BusNetwork(bc)); + busses.push_back(make_unique(bc)); + //busses.push_back(new BusNetwork(bc)); } else if (Bus::isDigital(bc.type)) { - //busses.push_back(std::make_unique(bc, numDigital, colorOrderMap)); - busses.push_back(new BusDigital(bc, numDigital, colorOrderMap)); + busses.push_back(make_unique(bc, numDigital)); + //busses.push_back(new BusDigital(bc, numDigital)); } else if (Bus::isOnOff(bc.type)) { - //busses.push_back(std::make_unique(bc)); - busses.push_back(new BusOnOff(bc)); + busses.push_back(make_unique(bc)); + //busses.push_back(new BusOnOff(bc)); } else { - //busses.push_back(std::make_unique(bc)); - busses.push_back(new BusPwm(bc)); + busses.push_back(make_unique(bc)); + //busses.push_back(new BusPwm(bc)); } return busses.size(); } @@ -898,7 +891,7 @@ void BusManager::removeAll() { DEBUGBUS_PRINTLN(F("Removing all.")); //prevents crashes due to deleting busses while in use. while (!canAllShow()) yield(); - for (auto &bus : busses) delete bus; // needed when not using std::unique_ptr C++ >11 + //for (auto &bus : busses) delete bus; // needed when not using std::unique_ptr C++ >11 busses.clear(); PolyBus::setParallelI2S1Output(false); } @@ -949,8 +942,8 @@ void BusManager::on() { uint8_t pins[2] = {255,255}; if (bus->isDigital() && bus->getPins(pins)) { if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) { - BusDigital *b = static_cast(bus); - b->begin(); + BusDigital &b = static_cast(*bus); + b.begin(); break; } } @@ -978,17 +971,13 @@ void BusManager::off() { } void BusManager::show() { - _milliAmpsUsed = 0; + _gMilliAmpsUsed = 0; for (auto &bus : busses) { bus->show(); - _milliAmpsUsed += bus->getUsedCurrent(); + _gMilliAmpsUsed += bus->getUsedCurrent(); } } -void BusManager::setStatusPixel(uint32_t c) { - for (auto &bus : busses) bus->setStatusPixel(c); -} - void IRAM_ATTR BusManager::setPixelColor(unsigned pix, uint32_t c) { for (auto &bus : busses) { unsigned bstart = bus->getStart(); @@ -997,10 +986,6 @@ void IRAM_ATTR BusManager::setPixelColor(unsigned pix, uint32_t c) { } } -void BusManager::setBrightness(uint8_t b) { - for (auto &bus : busses) bus->setBrightness(b); -} - void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) { if (cct > 255) cct = 255; if (cct >= 0) { @@ -1024,17 +1009,8 @@ bool BusManager::canAllShow() { return true; } -Bus* BusManager::getBus(uint8_t busNr) { - if (busNr >= busses.size()) return nullptr; - return busses[busNr]; -} +ColorOrderMap& BusManager::getColorOrderMap() { return _colorOrderMap; } -//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) -uint16_t BusManager::getTotalLength() { - unsigned len = 0; - for (const auto &bus : busses) len += bus->getLength(); - return len; -} bool PolyBus::_useParallelI2S = false; @@ -1045,8 +1021,7 @@ uint8_t Bus::_gAWM = 255; uint16_t BusDigital::_milliAmpsTotal = 0; -//std::vector> BusManager::busses; -std::vector BusManager::busses; -ColorOrderMap BusManager::colorOrderMap = {}; -uint16_t BusManager::_milliAmpsUsed = 0; -uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT; +std::vector> BusManager::busses; +//std::vector BusManager::busses; +uint16_t BusManager::_gMilliAmpsUsed = 0; +uint16_t BusManager::_gMilliAmpsMax = ABL_MILLIAMPS_DEFAULT; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 59e574cb0..0570cc2d6 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -11,6 +11,18 @@ #include #include +#if __cplusplus >= 201402L +using std::make_unique; +#else +// Really simple C++11 shim for non-array case; implementation from cppreference.com +template +std::unique_ptr +make_unique(Args&&... args) +{ + return std::unique_ptr(new T(std::forward(args)...)); +} +#endif + // enable additional debug output #if defined(WLED_DEBUG_HOST) #include "net_debug.h" @@ -94,11 +106,10 @@ class Bus { : _type(type) , _bri(255) , _start(start) - , _len(len) + , _len(std::max(len,(uint16_t)1)) , _reversed(reversed) , _valid(false) , _needsRefresh(refresh) - , _data(nullptr) // keep data access consistent across all types of buses { _autoWhiteMode = Bus::hasWhite(type) ? aw : RGBW_MODE_MANUAL_ONLY; }; @@ -202,7 +213,6 @@ class Bus { bool _hasCCT;// : 1; //} __attribute__ ((packed)); uint8_t _autoWhiteMode; - uint8_t *_data; // global Auto White Calculation override static uint8_t _gAWM; // _cct has the following menaings (see calculateCCT() & BusManager::setSegmentCCT()): @@ -217,14 +227,12 @@ class Bus { static uint8_t _cctBlend; uint32_t autoWhiteCalc(uint32_t c) const; - uint8_t *allocateData(size_t size = 1); - void freeData(); }; class BusDigital : public Bus { public: - BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com); + BusDigital(const BusConfig &bc, uint8_t nr); ~BusDigital() { cleanup(); } void show() override; @@ -248,15 +256,15 @@ class BusDigital : public Bus { static std::vector getLEDTypes(); private: - uint8_t _skip; - uint8_t _colorOrder; - uint8_t _pins[2]; - uint8_t _iType; + uint8_t _skip; + uint8_t _colorOrder; + uint8_t _pins[2]; + uint8_t _iType; uint16_t _frequencykHz; - uint8_t _milliAmpsPerLed; + uint8_t _milliAmpsPerLed; uint16_t _milliAmpsMax; - void * _busPtr; - const ColorOrderMap &_colorOrderMap; + uint8_t *_data; + void *_busPtr; static uint16_t _milliAmpsTotal; // is overwitten/recalculated on each show() @@ -286,13 +294,13 @@ class BusPwm : public Bus { uint16_t getFrequency() const override { return _frequency; } unsigned getBusSize() const override { return sizeof(BusPwm); } void show() override; - inline void cleanup() { deallocatePins(); _data = nullptr; } + inline void cleanup() { deallocatePins(); } static std::vector getLEDTypes(); private: uint8_t _pins[OUTPUT_MAX_PINS]; - uint8_t _pwmdata[OUTPUT_MAX_PINS]; + uint8_t _data[OUTPUT_MAX_PINS]; #ifdef ARDUINO_ARCH_ESP32 uint8_t _ledcStart; #endif @@ -313,13 +321,13 @@ class BusOnOff : public Bus { unsigned getPins(uint8_t* pinArray) const override; unsigned getBusSize() const override { return sizeof(BusOnOff); } void show() override; - inline void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); _data = nullptr; } + inline void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); } static std::vector getLEDTypes(); private: uint8_t _pin; - uint8_t _onoffdata; + uint8_t _data; }; @@ -343,6 +351,7 @@ class BusNetwork : public Bus { uint8_t _UDPtype; uint8_t _UDPchannels; bool _broadcastLock; + uint8_t *_data; }; @@ -363,7 +372,7 @@ struct BusConfig { uint16_t milliAmpsMax; BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, bool dblBfr=false, uint8_t maPerLed=LED_MILLIAMPS_DEFAULT, uint16_t maMax=ABL_MILLIAMPS_DEFAULT) - : count(len) + : count(std::max(len,(uint16_t)1)) , start(pstart) , colorOrder(pcolorOrder) , reversed(rev) @@ -416,59 +425,58 @@ struct BusConfig { #endif #endif -class BusManager { - public: - BusManager() {}; +namespace BusManager { - static unsigned memUsage(); - static uint16_t currentMilliamps() { return _milliAmpsUsed + MA_FOR_ESP; } - static uint16_t ablMilliampsMax() { return _milliAmpsMax; } + extern std::vector> busses; + //extern std::vector busses; + extern uint16_t _gMilliAmpsUsed; + extern uint16_t _gMilliAmpsMax; - static int add(const BusConfig &bc); - static void useParallelOutput(); // workaround for inaccessible PolyBus - static bool hasParallelOutput(); // workaround for inaccessible PolyBus + #ifdef ESP32_DATA_IDLE_HIGH + void esp32RMTInvertIdle() ; + #endif + inline size_t getNumVirtualBusses() { + size_t j = 0; + for (const auto &bus : busses) j += bus->isVirtual(); + return j; + } - //do not call this method from system context (network callback) - static void removeAll(); + size_t memUsage(); + inline uint16_t currentMilliamps() { return _gMilliAmpsUsed + MA_FOR_ESP; } + //inline uint16_t ablMilliampsMax() { unsigned sum = 0; for (auto &bus : busses) sum += bus->getMaxCurrent(); return sum; } + inline uint16_t ablMilliampsMax() { return _gMilliAmpsMax; } // used for compatibility reasons (and enabling virtual global ABL) + inline void setMilliampsMax(uint16_t max) { _gMilliAmpsMax = max;} - static void on(); - static void off(); + void useParallelOutput(); // workaround for inaccessible PolyBus + bool hasParallelOutput(); // workaround for inaccessible PolyBus - static void show(); - static bool canAllShow(); - static void setStatusPixel(uint32_t c); - [[gnu::hot]] static void setPixelColor(unsigned pix, uint32_t c); - static void setBrightness(uint8_t b); - // for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K - // WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT() - static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false); - static inline void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;} - [[gnu::hot]] static uint32_t getPixelColor(unsigned pix); - static inline int16_t getSegmentCCT() { return Bus::getCCT(); } + //do not call this method from system context (network callback) + void removeAll(); + int add(const BusConfig &bc); - static Bus* getBus(uint8_t busNr); + void on(); + void off(); - //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) - static uint16_t getTotalLength(); - static inline uint8_t getNumBusses() { return busses.size(); } - static String getLEDTypesJSONString(); + [[gnu::hot]] void setPixelColor(unsigned pix, uint32_t c); + [[gnu::hot]] uint32_t getPixelColor(unsigned pix); + void show(); + bool canAllShow(); + inline void setStatusPixel(uint32_t c) { for (auto &bus : busses) bus->setStatusPixel(c);} + inline void setBrightness(uint8_t b) { for (auto &bus : busses) bus->setBrightness(b); } + // for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K + // WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT() + void setSegmentCCT(int16_t cct, bool allowWBCorrection = false); + inline int16_t getSegmentCCT() { return Bus::getCCT(); } + inline Bus* getBus(size_t busNr) { return busNr < busses.size() ? busses[busNr].get() : nullptr; } + inline size_t getNumBusses() { return busses.size(); } - static inline ColorOrderMap& getColorOrderMap() { return colorOrderMap; } - - private: - //static std::vector> busses; // we'd need C++ >11 - static std::vector busses; - static ColorOrderMap colorOrderMap; - static uint16_t _milliAmpsUsed; - static uint16_t _milliAmpsMax; - - #ifdef ESP32_DATA_IDLE_HIGH - static void esp32RMTInvertIdle() ; - #endif - static uint8_t getNumVirtualBusses() { - int j = 0; - for (const auto &bus : busses) j += bus->isVirtual(); - return j; - } + //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) + inline uint16_t getTotalLength(bool onlyPhysical = false) { + unsigned len = 0; + for (const auto &bus : busses) if (!(bus->isVirtual() && onlyPhysical)) len += bus->getLength(); + return len; + } + String getLEDTypesJSONString(); + ColorOrderMap& getColorOrderMap(); }; #endif diff --git a/wled00/button.cpp b/wled00/button.cpp index 5144f09f2..cf8fabe42 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -40,7 +40,7 @@ void longPressAction(uint8_t b) { if (!macroLongPress[b]) { switch (b) { - case 0: setRandomColor(col); colorUpdated(CALL_MODE_BUTTON); break; + case 0: setRandomColor(colPri); colorUpdated(CALL_MODE_BUTTON); break; case 1: if(buttonBriDirection) { if (bri == 255) break; // avoid unnecessary updates to brightness @@ -230,7 +230,7 @@ void handleAnalog(uint8_t b) effectPalette = constrain(effectPalette, 0, strip.getPaletteCount()-1); // map is allowed to "overshoot", so we need to contrain the result } else if (macroDoublePress[b] == 200) { // primary color, hue, full saturation - colorHStoRGB(aRead*256,255,col); + colorHStoRGB(aRead*256,255,colPri); } else { // otherwise use "double press" for segment selection Segment& seg = strip.getSegment(macroDoublePress[b]); diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 3687b4734..11862f83f 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -170,7 +170,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback for (JsonObject elm : ins) { - if (s >= WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES) break; + if (s >= WLED_MAX_BUSSES) break; uint8_t pins[5] = {255, 255, 255, 255, 255}; JsonArray pinArr = elm["pin"]; if (pinArr.size() == 0) continue; @@ -199,12 +199,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { } ledType |= refresh << 7; // hack bit 7 to indicate strip requires off refresh - busConfigs.push_back(std::move(BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax))); + //busConfigs.push_back(std::move(BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax))); + busConfigs.emplace_back(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax); doInitBusses = true; // finalization done in beginStrip() - s++; + if (!Bus::isVirtual(ledType)) s++; // have as many virtual buses as you want } } - if (hw_led["rev"]) BusManager::getBus(0)->setReversed(true); //set 0.11 global reversed setting for first bus + if (hw_led["rev"] && BusManager::getNumBusses()) BusManager::getBus(0)->setReversed(true); //set 0.11 global reversed setting for first bus // read color order map configuration JsonArray hw_com = hw[F("com")]; @@ -824,8 +825,8 @@ void serializeConfig() { for (size_t s = 0; s < BusManager::getNumBusses(); s++) { DEBUG_PRINTF_P(PSTR("Cfg: Saving bus #%u\n"), s); - Bus *bus = BusManager::getBus(s); - if (!bus || bus->getLength()==0) break; + const Bus *bus = BusManager::getBus(s); + if (!bus || !bus->isOk()) break; DEBUG_PRINTF_P(PSTR(" (%d-%d, type:%d, CO:%d, rev:%d, skip:%d, AW:%d kHz:%d, mA:%d/%d)\n"), (int)bus->getStart(), (int)(bus->getStart()+bus->getLength()), (int)(bus->getType() & 0x7F), @@ -838,28 +839,27 @@ void serializeConfig() { ); JsonObject ins = hw_led_ins.createNestedObject(); ins["start"] = bus->getStart(); - ins["len"] = bus->getLength(); + ins["len"] = bus->getLength(); JsonArray ins_pin = ins.createNestedArray("pin"); uint8_t pins[5]; uint8_t nPins = bus->getPins(pins); for (int i = 0; i < nPins; i++) ins_pin.add(pins[i]); - ins[F("order")] = bus->getColorOrder(); - ins["rev"] = bus->isReversed(); - ins[F("skip")] = bus->skippedLeds(); - ins["type"] = bus->getType() & 0x7F; - ins["ref"] = bus->isOffRefreshRequired(); - ins[F("rgbwm")] = bus->getAutoWhiteMode(); - ins[F("freq")] = bus->getFrequency(); + ins[F("order")] = bus->getColorOrder(); + ins["rev"] = bus->isReversed(); + ins[F("skip")] = bus->skippedLeds(); + ins["type"] = bus->getType() & 0x7F; + ins["ref"] = bus->isOffRefreshRequired(); + ins[F("rgbwm")] = bus->getAutoWhiteMode(); + ins[F("freq")] = bus->getFrequency(); ins[F("maxpwr")] = bus->getMaxCurrent(); - ins[F("ledma")] = bus->getLEDCurrent(); + ins[F("ledma")] = bus->getLEDCurrent(); } JsonArray hw_com = hw.createNestedArray(F("com")); const ColorOrderMap& com = BusManager::getColorOrderMap(); for (size_t s = 0; s < com.count(); s++) { const ColorOrderMapEntry *entry = com.get(s); - if (!entry) break; - + if (!entry || !entry->len) break; JsonObject co = hw_com.createNestedObject(); co["start"] = entry->start; co["len"] = entry->len; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 7bfd71c29..ba38d5a15 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -10,12 +10,13 @@ */ uint32_t color_blend(uint32_t color1, uint32_t color2, uint8_t blend) { // min / max blend checking is omitted: calls with 0 or 255 are rare, checking lowers overall performance - uint32_t rb1 = color1 & 0x00FF00FF; - uint32_t wg1 = (color1>>8) & 0x00FF00FF; - uint32_t rb2 = color2 & 0x00FF00FF; - uint32_t wg2 = (color2>>8) & 0x00FF00FF; - uint32_t rb3 = ((((rb1 << 8) | rb2) + (rb2 * blend) - (rb1 * blend)) >> 8) & 0x00FF00FF; - uint32_t wg3 = ((((wg1 << 8) | wg2) + (wg2 * blend) - (wg1 * blend))) & 0xFF00FF00; + const uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; // mask for R and B channels or W and G if negated (poorman's SIMD; https://github.com/wled/WLED/pull/4568#discussion_r1986587221) + uint32_t rb1 = color1 & TWO_CHANNEL_MASK; // extract R & B channels from color1 + uint32_t wg1 = (color1 >> 8) & TWO_CHANNEL_MASK; // extract W & G channels from color1 (shifted for multiplication later) + uint32_t rb2 = color2 & TWO_CHANNEL_MASK; // extract R & B channels from color2 + uint32_t wg2 = (color2 >> 8) & TWO_CHANNEL_MASK; // extract W & G channels from color2 (shifted for multiplication later) + uint32_t rb3 = ((((rb1 << 8) | rb2) + (rb2 * blend) - (rb1 * blend)) >> 8) & TWO_CHANNEL_MASK; // blend red and blue + uint32_t wg3 = ((((wg1 << 8) | wg2) + (wg2 * blend) - (wg1 * blend))) & ~TWO_CHANNEL_MASK; // negated mask for white and green return rb3 | wg3; } @@ -28,8 +29,9 @@ uint32_t color_add(uint32_t c1, uint32_t c2, bool preserveCR) { if (c1 == BLACK) return c2; if (c2 == BLACK) return c1; - uint32_t rb = (c1 & 0x00FF00FF) + (c2 & 0x00FF00FF); // mask and add two colors at once - uint32_t wg = ((c1>>8) & 0x00FF00FF) + ((c2>>8) & 0x00FF00FF); + const uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; // mask for R and B channels or W and G if negated + uint32_t rb = ( c1 & TWO_CHANNEL_MASK) + ( c2 & TWO_CHANNEL_MASK); // mask and add two colors at once + uint32_t wg = ((c1>>8) & TWO_CHANNEL_MASK) + ((c2>>8) & TWO_CHANNEL_MASK); uint32_t r = rb >> 16; // extract single color values uint32_t b = rb & 0xFFFF; uint32_t w = wg >> 16; @@ -44,10 +46,10 @@ uint32_t color_add(uint32_t c1, uint32_t c2, bool preserveCR) //max = b > max ? b : max; //max = w > max ? w : max; if (max > 255) { - uint32_t scale = (uint32_t(255)<<8) / max; // division of two 8bit (shifted) values does not work -> use bit shifts and multiplaction instead - rb = ((rb * scale) >> 8) & 0x00FF00FF; // - wg = (wg * scale) & 0xFF00FF00; - } else wg = wg << 8; //shift white and green back to correct position + const uint32_t scale = (uint32_t(255)<<8) / max; // division of two 8bit (shifted) values does not work -> use bit shifts and multiplaction instead + rb = ((rb * scale) >> 8) & TWO_CHANNEL_MASK; + wg = (wg * scale) & ~TWO_CHANNEL_MASK; + } else wg <<= 8; //shift white and green back to correct position return rb | wg; } else { r = r > 255 ? 255 : r; @@ -77,8 +79,9 @@ uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) addRemains |= B(c1) ? 0x00000001 : 0; addRemains |= W(c1) ? 0x01000000 : 0; } - uint32_t rb = (((c1 & 0x00FF00FF) * scale) >> 8) & 0x00FF00FF; // scale red and blue - uint32_t wg = (((c1 & 0xFF00FF00) >> 8) * scale) & 0xFF00FF00; // scale white and green + const uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; + uint32_t rb = (((c1 & TWO_CHANNEL_MASK) * scale) >> 8) & TWO_CHANNEL_MASK; // scale red and blue + uint32_t wg = (((c1 >> 8) & TWO_CHANNEL_MASK) * scale) & ~TWO_CHANNEL_MASK; // scale white and green scaledcolor = (rb | wg) + addRemains; return scaledcolor; } @@ -95,7 +98,7 @@ uint32_t ColorFromPaletteWLED(const CRGBPalette16& pal, unsigned index, uint8_t unsigned red1 = entry->r; unsigned green1 = entry->g; unsigned blue1 = entry->b; - if(lo4 && blendType != NOBLEND) { + if (lo4 && blendType != NOBLEND) { if (hi4 == 15) entry = &(pal[0]); else ++entry; unsigned f2 = (lo4 << 4); @@ -105,6 +108,7 @@ uint32_t ColorFromPaletteWLED(const CRGBPalette16& pal, unsigned index, uint8_t blue1 = (blue1 * f1 + (unsigned)entry->b * f2) >> 8; } if (brightness < 255) { // note: zero checking could be done to return black but that is hardly ever used so it is omitted + // actually color_fade(c1, brightness) uint32_t scale = brightness + 1; // adjust for rounding (bitshift) red1 = (red1 * scale) >> 8; // note: using color_fade() is 30% slower green1 = (green1 * scale) >> 8; diff --git a/wled00/const.h b/wled00/const.h index b830bed74..2b460f3f1 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -49,31 +49,31 @@ #define WLED_MAX_DIGITAL_CHANNELS 3 #define WLED_MAX_ANALOG_CHANNELS 5 #define WLED_MAX_BUSSES 4 // will allow 3 digital & 1 analog RGB - #define WLED_MIN_VIRTUAL_BUSSES 3 + #define WLED_MIN_VIRTUAL_BUSSES 3 // no longer used for bus creation but used to distinguish S2/S3 in UI #else #define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM #define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white #define WLED_MAX_DIGITAL_CHANNELS 2 //#define WLED_MAX_ANALOG_CHANNELS 6 - #define WLED_MIN_VIRTUAL_BUSSES 4 + #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI #elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB // the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though) - #define WLED_MAX_BUSSES 14 // will allow 12 digital & 2 analog RGB - #define WLED_MAX_DIGITAL_CHANNELS 12 // x4 RMT + x1/x8 I2S0 + #define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog RGB + #define WLED_MAX_DIGITAL_CHANNELS 5 //#define WLED_MAX_ANALOG_CHANNELS 8 - #define WLED_MIN_VIRTUAL_BUSSES 4 + #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB supports parallel x8 LCD on I2S1 #define WLED_MAX_BUSSES 14 // will allow 12 digital & 2 analog RGB #define WLED_MAX_DIGITAL_CHANNELS 12 // x4 RMT + x8 I2S-LCD //#define WLED_MAX_ANALOG_CHANNELS 8 - #define WLED_MIN_VIRTUAL_BUSSES 6 + #define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI #else // the last digital bus (I2S0) will prevent Audioreactive usermod from functioning #define WLED_MAX_BUSSES 19 // will allow 16 digital & 3 analog RGB #define WLED_MAX_DIGITAL_CHANNELS 16 // x1/x8 I2S1 + x8 RMT //#define WLED_MAX_ANALOG_CHANNELS 16 - #define WLED_MIN_VIRTUAL_BUSSES 6 + #define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI #endif #endif #else @@ -87,7 +87,7 @@ #ifndef WLED_MAX_DIGITAL_CHANNELS #error You must also define WLED_MAX_DIGITAL_CHANNELS. #endif - #define WLED_MIN_VIRTUAL_BUSSES (5-WLED_MAX_BUSSES) + #define WLED_MIN_VIRTUAL_BUSSES 3 #else #if WLED_MAX_BUSSES > 20 #error Maximum number of buses is 20. @@ -98,7 +98,11 @@ #ifndef WLED_MAX_DIGITAL_CHANNELS #error You must also define WLED_MAX_DIGITAL_CHANNELS. #endif - #define WLED_MIN_VIRTUAL_BUSSES (20-WLED_MAX_BUSSES) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) + #define WLED_MIN_VIRTUAL_BUSSES 4 + #else + #define WLED_MIN_VIRTUAL_BUSSES 6 + #endif #endif #endif diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 3d3e44319..c55c98373 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -6,6 +6,7 @@ + WLED diff --git a/wled00/data/index.js b/wled00/data/index.js index f3648d3b5..147abf389 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -409,7 +409,9 @@ function pName(i) function isPlaylist(i) { - return pJson[i].playlist && pJson[i].playlist.ps; + if (isNumeric(i)) return pJson[i].playlist && pJson[i].playlist.ps; + if (isObj(i)) return i.playlist && i.playlist.ps; + return false; } function papiVal(i) @@ -775,8 +777,8 @@ function populateSegments(s) } let segp = `
`+ - ``+ - `
`+ + ``+ + `
`+ ``+ `
`+ `
`+ @@ -814,7 +816,7 @@ function populateSegments(s) cn += `
`+ ``+ `
`+ `&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};`+ @@ -1666,13 +1668,17 @@ function setEffectParameters(idx) paOnOff[0] = paOnOff[0].substring(0,dPos); } if (paOnOff.length>0 && paOnOff[0] != "!") text = paOnOff[0]; + gId("adPal").classList.remove("hide"); + if (lastinfo.cpalcount>0) gId("rmPal").classList.remove("hide"); } else { // disable palette list text += ' not used'; palw.style.display = "none"; + gId("adPal").classList.add("hide"); + gId("rmPal").classList.add("hide"); // Close palette dialog if not available - if (gId("palw").lastElementChild.tagName == "DIALOG") { - gId("palw").lastElementChild.close(); + if (palw.lastElementChild.tagName == "DIALOG") { + palw.lastElementChild.close(); } } pall.innerHTML = icon + text; @@ -1887,7 +1893,7 @@ function makeSeg() function resetUtil(off=false) { gId('segutil').innerHTML = `
` - + '' + + '' + `
Add segment
` + '
' + `` @@ -1901,15 +1907,16 @@ function resetUtil(off=false) if (lSeg>2) d.querySelectorAll("#Segments .pop").forEach((e)=>{e.classList.remove("hide");}); } -function makePlSel(el, incPl=false) +function makePlSel(p, el) { var plSelContent = ""; delete pJson["0"]; // remove filler preset Object.entries(pJson).sort(cmpP).forEach((a)=>{ var n = a[1].n ? a[1].n : "Preset " + a[0]; + if (isPlaylist(a[1])) n += ' ▶'; // mark playlist if (cfg.comp.idsort) n = a[0] + ' ' + n; - if (!(!incPl && a[1].playlist && a[1].playlist.ps)) // skip playlists, sub-playlists not yet supported - plSelContent += ``; + // skip endless playlists and itself + if (!isPlaylist(a[1]) || (a[1].playlist.repeat > 0 && a[0]!=p)) plSelContent += ``; }); return plSelContent; } @@ -1934,21 +1941,23 @@ function refreshPlE(p) }); } -// p: preset ID, i: ps index +// p: preset ID, i: playlist item index function addPl(p,i) { - plJson[p].ps.splice(i+1,0,0); - plJson[p].dur.splice(i+1,0,plJson[p].dur[i]); - plJson[p].transition.splice(i+1,0,plJson[p].transition[i]); + const pl = plJson[p]; + pl.ps.splice(i+1,0,1); + pl.dur.splice(i+1,0,pl.dur[i]); + pl.transition.splice(i+1,0,pl.transition[i]); refreshPlE(p); } function delPl(p,i) { - if (plJson[p].ps.length < 2) return; - plJson[p].ps.splice(i,1); - plJson[p].dur.splice(i,1); - plJson[p].transition.splice(i,1); + const pl = plJson[p]; + if (pl.ps.length < 2) return; + pl.ps.splice(i,1); + pl.dur.splice(i,1); + pl.transition.splice(i,1); refreshPlE(p); } @@ -1965,6 +1974,13 @@ function pleDur(p,i,field) function pleTr(p,i,field) { + const du = gId(`pl${p}du${i}`); + const dv = parseFloat(du.value); + if (dv > 0) { + field.max = dv; + if (parseFloat(field.value) > dv) + field.value = du.value; + } if (field.validity.valid) plJson[p].transition[i] = Math.floor(field.value*10); } @@ -1984,6 +2000,17 @@ function plR(p) } } +function plM(p) +{ + const man = gId(`pl${p}manual`).checked; + plJson[p].dur.forEach((e,i)=>{ + const d = gId(`pl${p}du${i}`); + plJson[p].dur[i] = e = man ? 0 : 100; + d.value = e/10; // 10s default + d.readOnly = man; + }); +} + function makeP(i,pl) { var content = ""; @@ -1997,12 +2024,17 @@ function makeP(i,pl) r: false, end: 0 }; - var rep = plJson[i].repeat ? plJson[i].repeat : 0; + const rep = plJson[i].repeat ? plJson[i].repeat : 0; + const man = plJson[i].dur == 0; content = `
+
`; @@ -2086,25 +2118,26 @@ function makePUtil() function makePlEntry(p,i) { + const man = gId(`pl${p}manual`).checked; return `
- + - - + +
DurationDuration (0=inf.) Transition #${i+1}
ssss
@@ -2657,28 +2690,28 @@ function fromRgb() var g = gId('sliderG').value; var b = gId('sliderB').value; setPicker(`rgb(${r},${g},${b})`); - let cd = gId('csl').children; // color slots - cd[csel].dataset.r = r; - cd[csel].dataset.g = g; - cd[csel].dataset.b = b; - setCSL(cd[csel]); + let cd = gId('csl').children[csel]; // color slots + cd.dataset.r = r; + cd.dataset.g = g; + cd.dataset.b = b; + setCSL(cd); } function fromW() { let w = gId('sliderW'); - let cd = gId('csl').children; // color slots - cd[csel].dataset.w = w.value; - setCSL(cd[csel]); + let cd = gId('csl').children[csel]; // color slots + cd.dataset.w = w.value; + setCSL(cd); updateTrail(w); } // sr 0: from RGB sliders, 1: from picker, 2: from hex function setColor(sr) { - var cd = gId('csl').children; // color slots - let cdd = cd[csel].dataset; - let w = 0, r,g,b; + var cd = gId('csl').children[csel]; // color slots + let cdd = cd.dataset; + let w = parseInt(cdd.w), r = parseInt(cdd.r), g = parseInt(cdd.g), b = parseInt(cdd.b); if (sr == 1 && isRgbBlack(cdd)) cpick.color.setChannel('hsv', 'v', 100); if (sr != 2 && hasWhite) w = parseInt(gId('sliderW').value); var col = cpick.color.rgb; @@ -2686,7 +2719,7 @@ function setColor(sr) cdd.g = g = hasRGB ? col.g : w; cdd.b = b = hasRGB ? col.b : w; cdd.w = w; - setCSL(cd[csel]); + setCSL(cd); var obj = {"seg": {"col": [[],[],[]]}}; obj.seg.col[csel] = [r, g, b, w]; requestJson(obj); diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 0900be399..a45ed050e 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -24,6 +24,7 @@ function is16b(t) { return !!(gT(t).c & 0x10); } // is digital 16 bit type function mustR(t) { return !!(gT(t).c & 0x20); } // Off refresh is mandatory function numPins(t){ return Math.max(gT(t).t.length, 1); } // type length determines number of GPIO pins + function chrID(x) { return String.fromCharCode((x<10?48:55)+x); } function S() { getLoc(); loadJS(getURL('/settings/s.js?p=2'), false, ()=>{ @@ -42,10 +43,10 @@ if (loc) d.Sf.action = getURL('/settings/leds'); } function bLimits(b,v,p,m,l,o=5,d=2,a=6) { - oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S): 19 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266 - maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 16 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266 + oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S): 20 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266 + maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 17 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266 maxA = a; // maxA - max analog channels: 16 - ESP32, 8 - S3/S2, 6 - C3, 5 - 8266 - maxV = v; // maxV - min virtual buses: 4 - ESP32/S3, 3 - S2/C3, 2 - ESP8266 + maxV = v; // maxV - min virtual buses: 6 - ESP32/S3, 4 - S2/C3, 3 - ESP8266 (only used to distinguish S2/S3) maxPB = p; // maxPB - max LEDs per bus maxM = m; // maxM - max LED memory maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32) @@ -138,7 +139,7 @@ gId("ppldis").style.display = ppl ? 'inline' : 'none'; // set PPL minimum value and clear actual PPL limit if ABL is disabled d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,x)=>{ - var n = String.fromCharCode((x<10?48:55)+x); + var n = chrID(x); gId("PSU"+n).style.display = ppl ? "inline" : "none"; const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT const c = parseInt(d.Sf["LC"+n].value); //get LED count @@ -169,7 +170,7 @@ // select appropriate LED current d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{ sel.value = 0; // set custom - var n = String.fromCharCode((x<10?48:55)+x); + var n = chrID(x); if (en) switch (parseInt(d.Sf["LA"+n].value)) { case 0: break; // disable ABL @@ -359,8 +360,9 @@ gId("prl").classList.add("hide"); } else gId("prl").classList.remove("hide"); + // S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel maxD = (S2 || S3 ? 4 : 8) + (d.Sf["PR"].checked ? 8 : S2); // TODO: use bLimits() : 4/8RMT + (x1/x8 parallel) I2S1 - maxB = oMaxB - (d.Sf["PR"].checked ? 0 : 7 + S3); // S2 (maxV==3) does support single I2S + maxB = oMaxB - (d.Sf["PR"].checked ? 0 : 7 + S3); // S2 (maxV==4) does support mono I2S } // distribute ABL current if not using PPL enPPL(sDI); @@ -399,7 +401,7 @@ } function lastEnd(i) { if (i-- < 1) return 0; - var s = String.fromCharCode((i<10?48:55)+i); + var s = chrID(i); v = parseInt(d.getElementsByName("LS"+s)[0].value) + parseInt(d.getElementsByName("LC"+s)[0].value); var t = parseInt(d.getElementsByName("LT"+s)[0].value); if (isPWM(t)) v = 1; //PWM busses @@ -421,8 +423,8 @@ if (isVir(t)) virtB++; }); - if ((n==1 && i>=maxB+maxV) || (n==-1 && i==0)) return; - var s = String.fromCharCode((i<10?48:55)+i); + if ((n==1 && i>=36) || (n==-1 && i==0)) return; // used to be i>=maxB+maxV when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") + var s = chrID(i); if (n==1) { // npm run build has trouble minimizing spaces inside string @@ -495,7 +497,7 @@ mA/LED: function addCOM(start=0,len=1,co=0) { var i = gEBCN("com_entry").length; if (i >= maxCO) return; - var s = String.fromCharCode((i<10?48:55)+i); + var s = chrID(i); var b = `

${i+1}: Start:   @@ -560,7 +562,7 @@ Swap: `; c += `  function checkSi() { //on load, checks whether there are custom start fields var cs = false; for (var i=1; i < gEBCN("iST").length; i++) { - var v = parseInt(gId("ls"+(i-1)).value) + parseInt(gN("LC"+(i-1)).value); - if (v != parseInt(gId("ls"+i).value)) {cs = true; startsDirty[i] = true;} + var s = chrID(i); + var p = chrID(i-1); // cover edge case 'A' previous char being '9' + var v = parseInt(gId("ls"+p).value) + parseInt(gN("LC"+p).value); + if (v != parseInt(gId("ls"+s).value)) {cs = true; startsDirty[i] = true;} } if (gId("ls0") && parseInt(gId("ls0").value) != 0) {cs = true; startsDirty[0] = true;} gId("si").checked = cs; @@ -614,22 +618,32 @@ Swap: addCOM(e.start, e.len, e.order); }); } - if (c.hw.btn) { - var b = c.hw.btn; + let b = c.hw.btn; + if (b) { if (Array.isArray(b.ins)) gId("btns").innerHTML = ""; b.ins.forEach((v,i,a)=>{ addBtn(i,v.pin[0],v.type); }); d.getElementsByName("TT")[0].value = b.tt; } - if (c.hw.ir) { - d.getElementsByName("IR")[0].value = c.hw.ir.pin; - d.getElementsByName("IT")[0].value = c.hw.ir.type; + let ir = c.hw.ir; + if (ir) { + d.getElementsByName("IR")[0].value = ir.pin; + d.getElementsByName("IT")[0].value = ir.type; } - if (c.hw.relay) { - d.getElementsByName("RL")[0].value = c.hw.relay.pin; - d.getElementsByName("RM")[0].checked = c.hw.relay.rev; - d.getElementsByName("RO")[0].checked = c.hw.relay.odrain; + let rl = c.hw.relay; + if (rl) { + d.getElementsByName("RL")[0].value = rl.pin; + d.getElementsByName("RM")[0].checked = rl.rev; + d.getElementsByName("RO")[0].checked = rl.odrain; + } + let li = c.light; + if (li) { + d.getElementsByName("MS")[0].checked = li.aseg; } UI(); } diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 7845778d7..29f015bdc 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -19,6 +19,9 @@ public: void disable(); void enable(); + /// True if dmx is currently connected + bool isConnected() const { return connected; } + private: /// @return true if rdm identify is active bool isIdentifyOn() const; diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 9bc323d7f..4f7603f50 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -327,6 +327,7 @@ void serializePlaylist(JsonObject obj); //presets.cpp const char *getPresetsFileName(bool persistent = true); +bool presetNeedsSaving(); void initPresetsFile(); void handlePresets(); bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE); @@ -408,7 +409,7 @@ class Usermod { protected: um_data_t *um_data; // um_data should be allocated using new in (derived) Usermod's setup() or constructor public: - Usermod() { um_data = nullptr; } + Usermod() : um_data(nullptr) {}; virtual ~Usermod() { if (um_data) delete um_data; } virtual void setup() = 0; // pure virtual, has to be overriden virtual void loop() = 0; // pure virtual, has to be overriden @@ -445,8 +446,6 @@ class Usermod { }; namespace UsermodManager { - extern byte numMods; - void loop(); void handleOverlayDraw(); bool handleButton(uint8_t b); @@ -468,13 +467,12 @@ namespace UsermodManager { #endif void onUpdateBegin(bool); void onStateChange(uint8_t); - bool add(Usermod* um); Usermod* lookup(uint16_t mod_id); - inline byte getModCount() {return numMods;}; + size_t getModCount(); }; -//usermods_list.cpp -void registerUsermods(); +// Register usermods by building a static list via a linker section +#define REGISTER_USERMOD(x) Usermod* const um_##x __attribute__((__section__(".dtors.tbl.usermods.1"), used)) = &x //usermod.cpp void userSetup(); diff --git a/wled00/hue.cpp b/wled00/hue.cpp index 950c54896..d5fcb7cb9 100644 --- a/wled00/hue.cpp +++ b/wled00/hue.cpp @@ -195,9 +195,9 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len) { switch(hueColormode) { - case 1: if (hueX != hueXLast || hueY != hueYLast) colorXYtoRGB(hueX,hueY,col); hueXLast = hueX; hueYLast = hueY; break; - case 2: if (hueHue != hueHueLast || hueSat != hueSatLast) colorHStoRGB(hueHue,hueSat,col); hueHueLast = hueHue; hueSatLast = hueSat; break; - case 3: if (hueCt != hueCtLast) colorCTtoRGB(hueCt,col); hueCtLast = hueCt; break; + case 1: if (hueX != hueXLast || hueY != hueYLast) colorXYtoRGB(hueX,hueY,colPri); hueXLast = hueX; hueYLast = hueY; break; + case 2: if (hueHue != hueHueLast || hueSat != hueSatLast) colorHStoRGB(hueHue,hueSat,colPri); hueHueLast = hueHue; hueSatLast = hueSat; break; + case 3: if (hueCt != hueCtLast) colorCTtoRGB(hueCt,colPri); hueCtLast = hueCt; break; } } hueReceived = true; diff --git a/wled00/json.cpp b/wled00/json.cpp index 200307464..24988be15 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -91,14 +91,20 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) } } - uint16_t grp = elem["grp"] | seg.grouping; - uint16_t spc = elem[F("spc")] | seg.spacing; - uint16_t of = seg.offset; - uint8_t soundSim = elem["si"] | seg.soundSim; - uint8_t map1D2D = elem["m12"] | seg.map1D2D; - uint8_t set = elem[F("set")] | seg.set; - seg.set = constrain(set, 0, 3); - seg.soundSim = constrain(soundSim, 0, 3); + uint16_t grp = elem["grp"] | seg.grouping; + uint16_t spc = elem[F("spc")] | seg.spacing; + uint16_t of = seg.offset; + uint8_t soundSim = elem["si"] | seg.soundSim; + uint8_t map1D2D = elem["m12"] | seg.map1D2D; + uint8_t set = elem[F("set")] | seg.set; + bool selected = getBoolVal(elem["sel"], seg.selected); + bool reverse = getBoolVal(elem["rev"], seg.reverse); + bool mirror = getBoolVal(elem["mi"] , seg.mirror); + #ifndef WLED_DISABLE_2D + bool reverse_y = getBoolVal(elem["rY"] , seg.reverse_y); + bool mirror_y = getBoolVal(elem["mY"] , seg.mirror_y); + bool transpose = getBoolVal(elem[F("tp")], seg.transpose); + #endif int len = (stop > start) ? stop - start : 1; int offset = elem[F("of")] | INT32_MAX; @@ -200,20 +206,16 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) } #endif + //seg.map1D2D = constrain(map1D2D, 0, 7); // done in setGeometry() + seg.set = constrain(set, 0, 3); + seg.soundSim = constrain(soundSim, 0, 3); + seg.selected = selected; + seg.reverse = reverse; + seg.mirror = mirror; #ifndef WLED_DISABLE_2D - bool reverse = seg.reverse; - bool mirror = seg.mirror; - #endif - seg.selected = getBoolVal(elem["sel"], seg.selected); - seg.reverse = getBoolVal(elem["rev"], seg.reverse); - seg.mirror = getBoolVal(elem["mi"] , seg.mirror); - #ifndef WLED_DISABLE_2D - bool reverse_y = seg.reverse_y; - bool mirror_y = seg.mirror_y; - seg.reverse_y = getBoolVal(elem["rY"] , seg.reverse_y); - seg.mirror_y = getBoolVal(elem["mY"] , seg.mirror_y); - seg.transpose = getBoolVal(elem[F("tp")], seg.transpose); - if (seg.is2D() && seg.map1D2D == M12_pArc && (reverse != seg.reverse || reverse_y != seg.reverse_y || mirror != seg.mirror || mirror_y != seg.mirror_y)) seg.fill(BLACK); // clear entire segment (in case of Arc 1D to 2D expansion) + seg.reverse_y = reverse_y; + seg.mirror_y = mirror_y; + seg.transpose = transpose; #endif byte fx = seg.mode; @@ -392,35 +394,38 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) int it = 0; JsonVariant segVar = root["seg"]; - if (!segVar.isNull()) strip.suspend(); - if (segVar.is()) - { - int id = segVar["id"] | -1; - //if "seg" is not an array and ID not specified, apply to all selected/checked segments - if (id < 0) { - //apply all selected segments - //bool didSet = false; - for (size_t s = 0; s < strip.getSegmentsNum(); s++) { - Segment &sg = strip.getSegment(s); - if (sg.isActive() && sg.isSelected()) { - deserializeSegment(segVar, s, presetId); - //didSet = true; + if (!segVar.isNull()) { + // we may be called during strip.service() so we must not modify segments while effects are executing + strip.suspend(); + const unsigned long start = millis(); + while (strip.isServicing() && millis() - start < strip.getFrameTime()) yield(); // wait until frame is over + #ifdef WLED_DEBUG + if (millis() - start > 0) DEBUG_PRINTLN(F("JSON: Waited for strip to finish servicing.")); + #endif + if (segVar.is()) { + int id = segVar["id"] | -1; + //if "seg" is not an array and ID not specified, apply to all selected/checked segments + if (id < 0) { + //apply all selected segments + for (size_t s = 0; s < strip.getSegmentsNum(); s++) { + Segment &sg = strip.getSegment(s); + if (sg.isActive() && sg.isSelected()) { + deserializeSegment(segVar, s, presetId); + } } + } else { + deserializeSegment(segVar, id, presetId); //apply only the segment with the specified ID } - //TODO: not sure if it is good idea to change first active but unselected segment - //if (!didSet) deserializeSegment(segVar, strip.getMainSegmentId(), presetId); } else { - deserializeSegment(segVar, id, presetId); //apply only the segment with the specified ID + size_t deleted = 0; + JsonArray segs = segVar.as(); + for (JsonObject elem : segs) { + if (deserializeSegment(elem, it++, presetId) && !elem["stop"].isNull() && elem["stop"]==0) deleted++; + } + if (strip.getSegmentsNum() > 3 && deleted >= strip.getSegmentsNum()/2U) strip.purgeSegments(); // batch deleting more than half segments } - } else { - size_t deleted = 0; - JsonArray segs = segVar.as(); - for (JsonObject elem : segs) { - if (deserializeSegment(elem, it++, presetId) && !elem["stop"].isNull() && elem["stop"]==0) deleted++; - } - if (strip.getSegmentsNum() > 3 && deleted >= strip.getSegmentsNum()/2U) strip.purgeSegments(); // batch deleting more than half segments + strip.resume(); } - strip.resume(); UsermodManager::readFromJsonState(root); diff --git a/wled00/led.cpp b/wled00/led.cpp index 9731da655..2d2f5b6f2 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -9,10 +9,10 @@ void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelect void setValuesFromSegment(uint8_t s) { Segment& seg = strip.getSegment(s); - col[0] = R(seg.colors[0]); - col[1] = G(seg.colors[0]); - col[2] = B(seg.colors[0]); - col[3] = W(seg.colors[0]); + colPri[0] = R(seg.colors[0]); + colPri[1] = G(seg.colors[0]); + colPri[2] = B(seg.colors[0]); + colPri[3] = W(seg.colors[0]); colSec[0] = R(seg.colors[1]); colSec[1] = G(seg.colors[1]); colSec[2] = B(seg.colors[1]); @@ -39,7 +39,7 @@ void applyValuesToSelectedSegs() if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;} if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette);} if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent);} - uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]); + uint32_t col0 = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]); uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]); if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0);} if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1);} @@ -112,10 +112,11 @@ void stateUpdated(byte callMode) { } } + unsigned long now = millis(); if (callMode != CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)) { briNlT = bri; - nightlightDelayMs -= (millis() - nightlightStartTime); - nightlightStartTime = millis(); + nightlightDelayMs -= (now - nightlightStartTime); + nightlightStartTime = now; } if (briT == 0) { if (callMode != CALL_MODE_NOTIFICATION) strip.resetTimebase(); //effect start from beginning @@ -141,7 +142,7 @@ void stateUpdated(byte callMode) { } else strip.setTransitionMode(true); // force all segments to transition mode transitionActive = true; - transitionStartTime = millis(); + transitionStartTime = now; } @@ -150,14 +151,14 @@ void updateInterfaces(uint8_t callMode) { sendDataWs(); lastInterfaceUpdate = millis(); - interfaceUpdateCallMode = 0; //disable further updates + interfaceUpdateCallMode = CALL_MODE_INIT; //disable further updates if (callMode == CALL_MODE_WS_SEND) return; #ifndef WLED_DISABLE_ALEXA if (espalexaDevice != nullptr && callMode != CALL_MODE_ALEXA) { espalexaDevice->setValue(bri); - espalexaDevice->setColor(col[0], col[1], col[2]); + espalexaDevice->setColor(colPri[0], colPri[1], colPri[2]); } #endif #ifndef WLED_DISABLE_MQTT @@ -211,7 +212,7 @@ void handleNightlight() { nightlightDelayMs = (unsigned)(nightlightDelayMins*60000); nightlightActiveOld = true; briNlT = bri; - for (unsigned i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color + for (unsigned i=0; i<4; i++) colNlT[i] = colPri[i]; // remember starting color if (nightlightMode == NL_MODE_SUN) { //save current @@ -236,7 +237,7 @@ void handleNightlight() { bri = briNlT + ((nightlightTargetBri - briNlT)*nper); if (nightlightMode == NL_MODE_COLORFADE) // color fading only is enabled with "NF=2" { - for (unsigned i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color + for (unsigned i=0; i<4; i++) colPri[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color } colorUpdated(CALL_MODE_NO_NOTIFY); } diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 8cbe79093..a462881ec 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -103,7 +103,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp //Prefix is stripped from the topic at this point if (strcmp_P(topic, PSTR("/col")) == 0) { - colorFromDecOrHexString(col, payloadStr); + colorFromDecOrHexString(colPri, payloadStr); colorUpdated(CALL_MODE_DIRECT_CHANGE); } else if (strcmp_P(topic, PSTR("/api")) == 0) { if (requestJSONBufferLock(15)) { @@ -169,7 +169,7 @@ void publishMqtt() strcat_P(subuf, PSTR("/g")); mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) - sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2])); + sprintf_P(s, PSTR("#%06X"), (colPri[3] << 24) | (colPri[0] << 16) | (colPri[1] << 8) | (colPri[2])); strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1); strcat_P(subuf, PSTR("/c")); mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263) diff --git a/wled00/playlist.cpp b/wled00/playlist.cpp index 1908334d7..2e51503e3 100644 --- a/wled00/playlist.cpp +++ b/wled00/playlist.cpp @@ -10,19 +10,19 @@ typedef struct PlaylistEntry { uint16_t tr; //Duration of the transition TO this entry (in tenths of seconds) } ple; -byte playlistRepeat = 1; //how many times to repeat the playlist (0 = infinitely) -byte playlistEndPreset = 0; //what preset to apply after playlist end (0 = stay on last preset) -byte playlistOptions = 0; //bit 0: shuffle playlist after each iteration. bits 1-7 TBD +static byte playlistRepeat = 1; //how many times to repeat the playlist (0 = infinitely) +static byte playlistEndPreset = 0; //what preset to apply after playlist end (0 = stay on last preset) +static byte playlistOptions = 0; //bit 0: shuffle playlist after each iteration. bits 1-7 TBD -PlaylistEntry *playlistEntries = nullptr; -byte playlistLen; //number of playlist entries -int8_t playlistIndex = -1; -uint16_t playlistEntryDur = 0; //duration of the current entry in tenths of seconds +static PlaylistEntry *playlistEntries = nullptr; +static byte playlistLen; //number of playlist entries +static int8_t playlistIndex = -1; +static uint16_t playlistEntryDur = 0; //duration of the current entry in tenths of seconds //values we need to keep about the parent playlist while inside sub-playlist -//int8_t parentPlaylistIndex = -1; -//byte parentPlaylistRepeat = 0; -//byte parentPlaylistPresetId = 0; //for re-loading +static int16_t parentPlaylistIndex = -1; +static byte parentPlaylistRepeat = 0; +static byte parentPlaylistPresetId = 0; //for re-loading void shufflePlaylist() { @@ -54,6 +54,12 @@ void unloadPlaylist() { int16_t loadPlaylist(JsonObject playlistObj, byte presetId) { + if (currentPlaylist > 0 && parentPlaylistPresetId > 0) return -1; // we are already in nested playlist, do nothing + if (currentPlaylist > 0) { + parentPlaylistIndex = playlistIndex; + parentPlaylistRepeat = playlistRepeat; + parentPlaylistPresetId = currentPlaylist; + } unloadPlaylist(); JsonArray presets = playlistObj["ps"]; @@ -79,7 +85,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) { } else { for (int dur : durations) { if (it >= playlistLen) break; - playlistEntries[it].dur = (dur > 1) ? dur : 100; + playlistEntries[it].dur = constrain(dur, 0, 65530); it++; } } @@ -117,6 +123,19 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) { shuffle = shuffle || playlistObj["r"]; if (shuffle) playlistOptions |= PL_OPTION_SHUFFLE; + if (parentPlaylistPresetId == 0 && parentPlaylistIndex > -1) { + // we are re-loading playlist when returning from nested playlist + playlistIndex = parentPlaylistIndex; + playlistRepeat = parentPlaylistRepeat; + parentPlaylistIndex = -1; + parentPlaylistRepeat = 0; + } else if (rep == 0) { + // endless playlist will never return to parent so erase parent information if it was called from it + parentPlaylistPresetId = 0; + parentPlaylistIndex = -1; + parentPlaylistRepeat = 0; + } + currentPlaylist = presetId; DEBUG_PRINTLN(F("Playlist loaded.")); return currentPlaylist; @@ -127,7 +146,7 @@ void handlePlaylist() { static unsigned long presetCycledTime = 0; if (currentPlaylist < 0 || playlistEntries == nullptr) return; -if (millis() - presetCycledTime > (100 * playlistEntryDur) || doAdvancePlaylist) { + if ((playlistEntryDur < UINT16_MAX && millis() - presetCycledTime > 100 * playlistEntryDur) || doAdvancePlaylist) { presetCycledTime = millis(); if (bri == 0 || nightlightActive) return; @@ -137,7 +156,10 @@ if (millis() - presetCycledTime > (100 * playlistEntryDur) || doAdvancePlaylist) if (!playlistIndex) { if (playlistRepeat == 1) { //stop if all repetitions are done unloadPlaylist(); - if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset); + if (parentPlaylistPresetId > 0) { + applyPresetFromPlaylist(parentPlaylistPresetId); // reload previous playlist (unfortunately asynchronous) + parentPlaylistPresetId = 0; // reset previous playlist but do not reset Index or Repeat (they will be loaded & reset in loadPlaylist()) + } else if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset); return; } if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist @@ -147,7 +169,7 @@ if (millis() - presetCycledTime > (100 * playlistEntryDur) || doAdvancePlaylist) jsonTransitionOnce = true; strip.setTransition(playlistEntries[playlistIndex].tr * 100); - playlistEntryDur = playlistEntries[playlistIndex].dur; + playlistEntryDur = playlistEntries[playlistIndex].dur > 0 ? playlistEntries[playlistIndex].dur : UINT16_MAX; applyPresetFromPlaylist(playlistEntries[playlistIndex].preset); doAdvancePlaylist = false; } diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 15eed3e46..54f052637 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -22,6 +22,10 @@ const char *getPresetsFileName(bool persistent) { return persistent ? presets_json : tmp_json; } +bool presetNeedsSaving() { + return presetToSave; +} + static void doSaveState() { bool persist = (presetToSave < 251); @@ -269,7 +273,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj) quickLoad = nullptr; } else { // store playlist - // WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1 + // WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1 it will also be randomised if selected includeBri = true; // !sObj["on"].isNull(); playlistSave = true; } diff --git a/wled00/set.cpp b/wled00/set.cpp index b2340066f..00333788d 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -145,8 +145,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) #endif bool busesChanged = false; - for (int s = 0; s < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; s++) { - int offset = s < 10 ? 48 : 55; + for (int s = 0; s < 36; s++) { // theoretical limit is 36 : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + int offset = s < 10 ? '0' : 'A'; char lp[4] = "L0"; lp[2] = offset+s; lp[3] = 0; //ascii 0-9 //strip data pin char lc[4] = "LC"; lc[2] = offset+s; lc[3] = 0; //strip length char co[4] = "CO"; co[2] = offset+s; co[3] = 0; //strip color order @@ -161,11 +161,11 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED mA char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max mA if (!request->hasArg(lp)) { - DEBUG_PRINTF_P(PSTR("No data for %d\n"), s); + DEBUG_PRINTF_P(PSTR("# of buses: %d\n"), s+1); break; } for (int i = 0; i < 5; i++) { - lp[1] = offset+i; + lp[1] = '0'+i; if (!request->hasArg(lp)) break; pins[i] = (request->arg(lp).length() > 0) ? request->arg(lp).toInt() : 255; } @@ -212,7 +212,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) type |= request->hasArg(rf) << 7; // off refresh override // actual finalization is done in WLED::loop() (removing old busses and adding new) // this may happen even before this loop is finished so we do "doInitBusses" after the loop - busConfigs.push_back(std::move(BusConfig(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, useGlobalLedBuffer, maPerLed, maMax))); + busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, useGlobalLedBuffer, maPerLed, maMax); busesChanged = true; } //doInitBusses = busesChanged; // we will do that below to ensure all input data is processed @@ -220,7 +220,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) // we will not bother with pre-allocating ColorOrderMappings vector BusManager::getColorOrderMap().reset(); for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { - int offset = s < 10 ? 48 : 55; + int offset = s < 10 ? '0' : 'A'; char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED char xc[4] = "XC"; xc[2] = offset+s; xc[3] = 0; //strip length char xo[4] = "XO"; xo[2] = offset+s; xo[3] = 0; //color order @@ -259,7 +259,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) disablePullUp = (bool)request->hasArg(F("IP")); touchThreshold = request->arg(F("TT")).toInt(); for (int i = 0; i < WLED_MAX_BUTTONS; i++) { - int offset = i < 10 ? 48 : 55; + int offset = i < 10 ? '0' : 'A'; char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10) char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10) int hw_btn_pin = request->arg(bt).toInt(); @@ -1193,7 +1193,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) } // you can add more if you need - // global col[], effectCurrent, ... are updated in stateChanged() + // global colPri[], effectCurrent, ... are updated in stateChanged() if (!apply) return true; // when called by JSON API, do not call colorUpdated() here pos = req.indexOf(F("&NN")); //do not send UDP notifications this time diff --git a/wled00/src/dependencies/time/DS1307RTC.h b/wled00/src/dependencies/time/DS1307RTC.h index 551ae9965..bc272701f 100644 --- a/wled00/src/dependencies/time/DS1307RTC.h +++ b/wled00/src/dependencies/time/DS1307RTC.h @@ -7,6 +7,7 @@ #define DS1307RTC_h #include "TimeLib.h" +#include "Wire.h" // library interface description class DS1307RTC diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 1fdb6d688..9bfb7e737 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -3,75 +3,81 @@ * Registration and management utility for v2 usermods */ -static Usermod* ums[WLED_MAX_USERMODS] = {nullptr}; -byte UsermodManager::numMods = 0; +// Global usermod instance list +// Table begin and end references +// Zero-length arrays -- so they'll get assigned addresses, but consume no flash +// The numeric suffix ensures they're put in the right place; the linker script will sort them +// We stick them in the '.dtors' segment because it's always included by the linker scripts +// even though it never gets called. Who calls exit() in an embedded program anyways? +// If someone ever does, though, it'll explode as these aren't function pointers. +static Usermod * const _usermod_table_begin[0] __attribute__((__section__(".dtors.tbl.usermods.0"), unused)) = {}; +static Usermod * const _usermod_table_end[0] __attribute__((__section__(".dtors.tbl.usermods.99"), unused)) = {}; + +static size_t getCount() { + return &_usermod_table_end[0] - &_usermod_table_begin[0]; +} + //Usermod Manager internals -void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++) ums[i]->setup(); } -void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); } -void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); } -void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); } -void UsermodManager::appendConfigData(Print& dest) { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(dest); } +void UsermodManager::setup() { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->setup(); } +void UsermodManager::connected() { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->connected(); } +void UsermodManager::loop() { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->loop(); } +void UsermodManager::handleOverlayDraw() { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->handleOverlayDraw(); } +void UsermodManager::appendConfigData(Print& dest) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->appendConfigData(dest); } bool UsermodManager::handleButton(uint8_t b) { bool overrideIO = false; - for (unsigned i = 0; i < numMods; i++) { - if (ums[i]->handleButton(b)) overrideIO = true; + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) { + if ((*mod)->handleButton(b)) overrideIO = true; } return overrideIO; } bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) { - for (unsigned i = 0; i < numMods; i++) { - if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided - if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time) + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) { + if (mod_id > 0 && (*mod)->getId() != mod_id) continue; // only get data form requested usermod if provided + if ((*mod)->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time) } return false; } -void UsermodManager::addToJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); } -void UsermodManager::addToJsonInfo(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); } -void UsermodManager::readFromJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } -void UsermodManager::addToConfig(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToConfig(obj); } +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::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) { bool allComplete = true; - for (unsigned i = 0; i < numMods; i++) { - if (!ums[i]->readFromConfig(obj)) allComplete = false; + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) { + if (!(*mod)->readFromConfig(obj)) allComplete = false; } return allComplete; } #ifndef WLED_DISABLE_MQTT -void UsermodManager::onMqttConnect(bool sessionPresent) { for (unsigned i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); } +void UsermodManager::onMqttConnect(bool sessionPresent) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->onMqttConnect(sessionPresent); } bool UsermodManager::onMqttMessage(char* topic, char* payload) { - for (unsigned i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true; + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) if ((*mod)->onMqttMessage(topic, payload)) return true; return false; } #endif #ifndef WLED_DISABLE_ESPNOW bool UsermodManager::onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len) { - for (unsigned i = 0; i < numMods; i++) if (ums[i]->onEspNowMessage(sender, payload, len)) return true; + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) if ((*mod)->onEspNowMessage(sender, payload, len)) return true; return false; } #endif -void UsermodManager::onUpdateBegin(bool init) { for (unsigned i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin -void UsermodManager::onStateChange(uint8_t mode) { for (unsigned i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed +void UsermodManager::onUpdateBegin(bool init) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->onUpdateBegin(init); } // notify usermods that update is to begin +void UsermodManager::onStateChange(uint8_t mode) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->onStateChange(mode); } // notify usermods that WLED state changed /* * Enables usermods to lookup another Usermod. */ Usermod* UsermodManager::lookup(uint16_t mod_id) { - for (unsigned i = 0; i < numMods; i++) { - if (ums[i]->getId() == mod_id) { - return ums[i]; + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) { + if ((*mod)->getId() == mod_id) { + return *mod; } } return nullptr; } -bool UsermodManager::add(Usermod* um) -{ - if (numMods >= WLED_MAX_USERMODS || um == nullptr) return false; - ums[numMods++] = um; - return true; -} - +size_t UsermodManager::getModCount() { return getCount(); }; /* Usermod v2 interface shim for oappend */ Print* Usermod::oappend_shim = nullptr; diff --git a/wled00/usermod_v2_empty.h b/wled00/usermod_v2_empty.h deleted file mode 100644 index 6537b56bc..000000000 --- a/wled00/usermod_v2_empty.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "wled.h" - -//This is an empty v2 usermod template. Please see the file usermod_v2_example.h in the EXAMPLE_v2 usermod folder for documentation on the functions you can use! - -class UsermodRenameMe : public Usermod { - private: - - public: - void setup() { - - } - - void loop() { - - } -}; \ No newline at end of file diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp deleted file mode 100644 index df4715d14..000000000 --- a/wled00/usermods_list.cpp +++ /dev/null @@ -1,497 +0,0 @@ -#include "wled.h" -/* - * Register your v2 usermods here! - * (for v1 usermods using just usermod.cpp, you can ignore this file) - */ - -/* - * Add/uncomment your usermod filename here (and once more below) - * || || || - * \/ \/ \/ - */ -//#include "../usermods/EXAMPLE_v2/usermod_v2_example.h" - -#ifdef USERMOD_BATTERY - #include "../usermods/Battery/usermod_v2_Battery.h" -#endif - -#ifdef USERMOD_DALLASTEMPERATURE - #include "../usermods/Temperature/usermod_temperature.h" -#endif - -#ifdef USERMOD_SHT -#include "../usermods/sht/usermod_sht.h" -#endif - -#ifdef USERMOD_SN_PHOTORESISTOR - #include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h" -#endif - -#ifdef USERMOD_PWM_FAN - // requires DALLASTEMPERATURE or SHT included before it - #include "../usermods/PWM_fan/usermod_PWM_fan.h" -#endif - -#ifdef USERMOD_BUZZER - #include "../usermods/buzzer/usermod_v2_buzzer.h" -#endif - -#ifdef USERMOD_SENSORSTOMQTT - #include "../usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h" -#endif - -#ifdef USERMOD_PIRSWITCH - #include "../usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h" -#endif - -#ifdef USERMOD_BH1750 - #include "../usermods/BH1750_v2/usermod_bh1750.h" -#endif - -// BME280 v2 usermod. Define "USERMOD_BME280" in my_config.h -#ifdef USERMOD_BME280 - #include "../usermods/BME280_v2/usermod_bme280.h" -#endif - -#ifdef USERMOD_BME68X - #include "../usermods/BME68X_v2/usermod_bme68x.h" -#endif - - -#ifdef USERMOD_FOUR_LINE_DISPLAY - #include "../usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h" -#endif - -#ifdef USERMOD_ROTARY_ENCODER_UI - #include "../usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h" -#endif - -#ifdef USERMOD_AUTO_SAVE - #include "../usermods/usermod_v2_auto_save/usermod_v2_auto_save.h" -#endif - -#ifdef USERMOD_DHT - #include "../usermods/DHT/usermod_dht.h" -#endif - -#ifdef USERMOD_VL53L0X_GESTURES - #include "../usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h" -#endif - -#ifdef USERMOD_ANIMATED_STAIRCASE - #include "../usermods/Animated_Staircase/Animated_Staircase.h" -#endif - -#ifdef USERMOD_MULTI_RELAY - #include "../usermods/multi_relay/usermod_multi_relay.h" -#endif - -#ifdef USERMOD_RTC - #include "../usermods/RTC/usermod_rtc.h" -#endif - -#ifdef USERMOD_ELEKSTUBE_IPS - #include "../usermods/EleksTube_IPS/usermod_elekstube_ips.h" -#endif - -#ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR - #include "../usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h" -#endif - -#ifdef RGB_ROTARY_ENCODER - #include "../usermods/rgb-rotary-encoder/rgb-rotary-encoder.h" -#endif - -#ifdef USERMOD_ST7789_DISPLAY - #include "../usermods/ST7789_display/ST7789_Display.h" -#endif - -#ifdef USERMOD_PIXELS_DICE_TRAY - #include "../usermods/pixels_dice_tray/pixels_dice_tray.h" -#endif - -#ifdef USERMOD_SEVEN_SEGMENT - #include "../usermods/seven_segment_display/usermod_v2_seven_segment_display.h" -#endif - -#ifdef USERMOD_SSDR - #include "../usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h" -#endif - -#ifdef USERMOD_CRONIXIE - #include "../usermods/Cronixie/usermod_cronixie.h" -#endif - -#ifdef QUINLED_AN_PENTA - #include "../usermods/quinled-an-penta/quinled-an-penta.h" -#endif - -#ifdef USERMOD_WIZLIGHTS - #include "../usermods/wizlights/wizlights.h" -#endif - -#ifdef USERMOD_WIREGUARD - #include "../usermods/wireguard/wireguard.h" -#endif - -#ifdef USERMOD_WORDCLOCK - #include "../usermods/usermod_v2_word_clock/usermod_v2_word_clock.h" -#endif - -#ifdef USERMOD_MY9291 - #include "../usermods/MY9291/usermode_MY9291.h" -#endif - -#ifdef USERMOD_SI7021_MQTT_HA - #include "../usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h" -#endif - -#ifdef USERMOD_SMARTNEST - #include "../usermods/smartnest/usermod_smartnest.h" -#endif - -#ifdef USERMOD_AUDIOREACTIVE - #include "../usermods/audioreactive/audio_reactive.h" -#endif - -#ifdef USERMOD_ANALOG_CLOCK - #include "../usermods/Analog_Clock/Analog_Clock.h" -#endif - -#ifdef USERMOD_PING_PONG_CLOCK - #include "../usermods/usermod_v2_ping_pong_clock/usermod_v2_ping_pong_clock.h" -#endif - -#ifdef USERMOD_ADS1115 - #include "../usermods/ADS1115_v2/usermod_ads1115.h" -#endif - -#ifdef USERMOD_KLIPPER_PERCENTAGE - #include "../usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h" -#endif - -#ifdef USERMOD_BOBLIGHT - #include "../usermods/boblight/boblight.h" -#endif - -#ifdef USERMOD_ANIMARTRIX - #include "../usermods/usermod_v2_animartrix/usermod_v2_animartrix.h" -#endif - -#ifdef USERMOD_INTERNAL_TEMPERATURE - #include "../usermods/Internal_Temperature_v2/usermod_internal_temperature.h" -#endif - -#if defined(WLED_USE_SD_MMC) || defined(WLED_USE_SD_SPI) -// This include of SD.h and SD_MMC.h must happen here, else they won't be -// resolved correctly (when included in mod's header only) - #ifdef WLED_USE_SD_MMC - #include "SD_MMC.h" - #elif defined(WLED_USE_SD_SPI) - #include "SD.h" - #include "SPI.h" - #endif - #include "../usermods/sd_card/usermod_sd_card.h" -#endif - -#ifdef USERMOD_PWM_OUTPUTS - #include "../usermods/pwm_outputs/usermod_pwm_outputs.h" -#endif - -#ifdef USERMOD_HTTP_PULL_LIGHT_CONTROL - #include "../usermods/usermod_v2_HttpPullLightControl/usermod_v2_HttpPullLightControl.h" -#endif - -#ifdef USERMOD_MPU6050_IMU - #include "../usermods/mpu6050_imu/usermod_mpu6050_imu.h" -#endif - -#ifdef USERMOD_MPU6050_IMU - #include "../usermods/mpu6050_imu/usermod_gyro_surge.h" -#endif - -#ifdef USERMOD_LDR_DUSK_DAWN - #include "../usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h" -#endif - -#ifdef USERMOD_POV_DISPLAY - #include "../usermods/pov_display/usermod_pov_display.h" -#endif - -#ifdef USERMOD_STAIRCASE_WIPE - #include "../usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h" -#endif - -#ifdef USERMOD_MAX17048 - #include "../usermods/MAX17048_v2/usermod_max17048.h" -#endif - -#ifdef USERMOD_TETRISAI - #include "../usermods/TetrisAI_v2/usermod_v2_tetrisai.h" -#endif - -#ifdef USERMOD_AHT10 - #include "../usermods/AHT10_v2/usermod_aht10.h" -#endif - -#ifdef USERMOD_INA226 - #include "../usermods/INA226_v2/usermod_ina226.h" -#endif - -#ifdef USERMOD_LD2410 -#include "../usermods/LD2410_v2/usermod_ld2410.h" -#endif - -#ifdef USERMOD_DEEP_SLEEP - #include "../usermods/deep_sleep/usermod_deep_sleep.h" -#endif - -#ifdef USERMOD_RF433 - #include "../usermods/usermod_v2_RF433/usermod_v2_RF433.h" -#endif - -#ifdef USERMOD_BRIGHTNESS_FOLLOW_SUN - #include "../usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h" -#endif - -void registerUsermods() -{ -/* - * Add your usermod class name here - * || || || - * \/ \/ \/ - */ - //UsermodManager::add(new MyExampleUsermod()); - - #ifdef USERMOD_BATTERY - UsermodManager::add(new UsermodBattery()); - #endif - - #ifdef USERMOD_DALLASTEMPERATURE - UsermodManager::add(new UsermodTemperature()); - #endif - - #ifdef USERMOD_SN_PHOTORESISTOR - UsermodManager::add(new Usermod_SN_Photoresistor()); - #endif - - #ifdef USERMOD_PWM_FAN - UsermodManager::add(new PWMFanUsermod()); - #endif - - #ifdef USERMOD_BUZZER - UsermodManager::add(new BuzzerUsermod()); - #endif - - #ifdef USERMOD_BH1750 - UsermodManager::add(new Usermod_BH1750()); - #endif - - #ifdef USERMOD_BME280 - UsermodManager::add(new UsermodBME280()); - #endif - - #ifdef USERMOD_BME68X - UsermodManager::add(new UsermodBME68X()); - #endif - - #ifdef USERMOD_SENSORSTOMQTT - UsermodManager::add(new UserMod_SensorsToMQTT()); - #endif - - #ifdef USERMOD_PIRSWITCH - UsermodManager::add(new PIRsensorSwitch()); - #endif - - #ifdef USERMOD_FOUR_LINE_DISPLAY - UsermodManager::add(new FourLineDisplayUsermod()); - #endif - - #ifdef USERMOD_ROTARY_ENCODER_UI - UsermodManager::add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY - #endif - - #ifdef USERMOD_AUTO_SAVE - UsermodManager::add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY - #endif - - #ifdef USERMOD_DHT - UsermodManager::add(new UsermodDHT()); - #endif - - #ifdef USERMOD_VL53L0X_GESTURES - UsermodManager::add(new UsermodVL53L0XGestures()); - #endif - - #ifdef USERMOD_ANIMATED_STAIRCASE - UsermodManager::add(new Animated_Staircase()); - #endif - - #ifdef USERMOD_MULTI_RELAY - UsermodManager::add(new MultiRelay()); - #endif - - #ifdef USERMOD_RTC - UsermodManager::add(new RTCUsermod()); - #endif - - #ifdef USERMOD_ELEKSTUBE_IPS - UsermodManager::add(new ElekstubeIPSUsermod()); - #endif - - #ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR - UsermodManager::add(new RotaryEncoderBrightnessColor()); - #endif - - #ifdef RGB_ROTARY_ENCODER - UsermodManager::add(new RgbRotaryEncoderUsermod()); - #endif - - #ifdef USERMOD_ST7789_DISPLAY - UsermodManager::add(new St7789DisplayUsermod()); - #endif - - #ifdef USERMOD_PIXELS_DICE_TRAY - UsermodManager::add(new PixelsDiceTrayUsermod()); - #endif - - #ifdef USERMOD_SEVEN_SEGMENT - UsermodManager::add(new SevenSegmentDisplay()); - #endif - - #ifdef USERMOD_SSDR - UsermodManager::add(new UsermodSSDR()); - #endif - - #ifdef USERMOD_CRONIXIE - UsermodManager::add(new UsermodCronixie()); - #endif - - #ifdef QUINLED_AN_PENTA - UsermodManager::add(new QuinLEDAnPentaUsermod()); - #endif - - #ifdef USERMOD_WIZLIGHTS - UsermodManager::add(new WizLightsUsermod()); - #endif - - #ifdef USERMOD_WIREGUARD - UsermodManager::add(new WireguardUsermod()); - #endif - - #ifdef USERMOD_WORDCLOCK - UsermodManager::add(new WordClockUsermod()); - #endif - - #ifdef USERMOD_MY9291 - UsermodManager::add(new MY9291Usermod()); - #endif - - #ifdef USERMOD_SI7021_MQTT_HA - UsermodManager::add(new Si7021_MQTT_HA()); - #endif - - #ifdef USERMOD_SMARTNEST - UsermodManager::add(new Smartnest()); - #endif - - #ifdef USERMOD_AUDIOREACTIVE - UsermodManager::add(new AudioReactive()); - #endif - - #ifdef USERMOD_ANALOG_CLOCK - UsermodManager::add(new AnalogClockUsermod()); - #endif - - #ifdef USERMOD_PING_PONG_CLOCK - UsermodManager::add(new PingPongClockUsermod()); - #endif - - #ifdef USERMOD_ADS1115 - UsermodManager::add(new ADS1115Usermod()); - #endif - - #ifdef USERMOD_KLIPPER_PERCENTAGE - UsermodManager::add(new klipper_percentage()); - #endif - - #ifdef USERMOD_BOBLIGHT - UsermodManager::add(new BobLightUsermod()); - #endif - - #ifdef SD_ADAPTER - UsermodManager::add(new UsermodSdCard()); - #endif - - #ifdef USERMOD_PWM_OUTPUTS - UsermodManager::add(new PwmOutputsUsermod()); - #endif - - #ifdef USERMOD_SHT - UsermodManager::add(new ShtUsermod()); - #endif - - #ifdef USERMOD_ANIMARTRIX - UsermodManager::add(new AnimartrixUsermod("Animartrix", false)); - #endif - - #ifdef USERMOD_INTERNAL_TEMPERATURE - UsermodManager::add(new InternalTemperatureUsermod()); - #endif - - #ifdef USERMOD_HTTP_PULL_LIGHT_CONTROL - UsermodManager::add(new HttpPullLightControl()); - #endif - - #ifdef USERMOD_MPU6050_IMU - static MPU6050Driver mpu6050; UsermodManager::add(&mpu6050); - #endif - - #ifdef USERMOD_GYRO_SURGE - static GyroSurge gyro_surge; UsermodManager::add(&gyro_surge); - #endif - - #ifdef USERMOD_LDR_DUSK_DAWN - UsermodManager::add(new LDR_Dusk_Dawn_v2()); - #endif - - #ifdef USERMOD_STAIRCASE_WIPE - UsermodManager::add(new StairwayWipeUsermod()); - #endif - - #ifdef USERMOD_MAX17048 - UsermodManager::add(new Usermod_MAX17048()); - #endif - - #ifdef USERMOD_TETRISAI - UsermodManager::add(new TetrisAIUsermod()); - #endif - - #ifdef USERMOD_AHT10 - UsermodManager::add(new UsermodAHT10()); - #endif - - #ifdef USERMOD_INA226 - UsermodManager::add(new UsermodINA226()); - #endif - - #ifdef USERMOD_LD2410 - UsermodManager::add(new LD2410Usermod()); - #endif - - #ifdef USERMOD_POV_DISPLAY - UsermodManager::add(new PovDisplayUsermod()); - #endif - - #ifdef USERMOD_DEEP_SLEEP - UsermodManager::add(new DeepSleepUsermod()); - #endif - - #ifdef USERMOD_RF433 - UsermodManager::add(new RF433Usermod()); - #endif - - #ifdef USERMOD_BRIGHTNESS_FOLLOW_SUN - UsermodManager::add(new UsermodBrightnessFollowSun()); - #endif -} diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 1d42e8c11..7e2095838 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -109,7 +109,6 @@ void WLED::loop() if (WLED_CONNECTED && aOtaEnabled && !otaLock && correctPIN) ArduinoOTA.handle(); #endif handleNightlight(); - handlePlaylist(); yield(); #ifndef WLED_DISABLE_HUESYNC @@ -117,6 +116,10 @@ void WLED::loop() yield(); #endif + if (!presetNeedsSaving()) { + handlePlaylist(); + yield(); + } handlePresets(); yield(); @@ -391,9 +394,6 @@ void WLED::setup() PinManager::allocatePin(2, true, PinOwner::DMX); #endif - DEBUG_PRINTLN(F("Registering usermods ...")); - registerUsermods(); - DEBUG_PRINTF_P(PSTR("heap %u\n"), ESP.getFreeHeap()); bool fsinit = false; @@ -463,7 +463,7 @@ void WLED::setup() #endif // fill in unique mdns default - if (strcmp(cmDNS, "x") == 0) sprintf_P(cmDNS, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6); + if (strcmp(cmDNS, DEFAULT_MDNS_NAME) == 0) sprintf_P(cmDNS, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6); #ifndef WLED_DISABLE_MQTT if (mqttDeviceTopic[0] == 0) sprintf_P(mqttDeviceTopic, PSTR("wled/%*s"), 6, escapedMac.c_str() + 6); if (mqttClientID[0] == 0) sprintf_P(mqttClientID, PSTR("WLED-%*s"), 6, escapedMac.c_str() + 6); @@ -546,16 +546,16 @@ void WLED::beginStrip() Segment &seg = strip.getSegment(i); if (seg.isActive()) seg.colors[0] = BLACK; } - col[0] = col[1] = col[2] = col[3] = 0; // needed for colorUpdated() + colPri[0] = colPri[1] = colPri[2] = colPri[3] = 0; // needed for colorUpdated() } briLast = briS; bri = 0; strip.fill(BLACK); strip.show(); } + colorUpdated(CALL_MODE_INIT); // will not send notification but will initiate transition if (bootPreset > 0) { applyPreset(bootPreset, CALL_MODE_INIT); } - colorUpdated(CALL_MODE_INIT); // will not send notification // init relay pin if (rlyPin >= 0) { diff --git a/wled00/wled.h b/wled00/wled.h index 0b65a9508..ea40c5dfe 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -217,6 +217,10 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; #define WLED_AP_PASS DEFAULT_AP_PASS #endif +#ifndef WLED_PIN + #define WLED_PIN "" +#endif + #ifndef SPIFFS_EDITOR_AIRCOOOKIE #error You are not using the Aircoookie fork of the ESPAsyncWebserver library.\ Using upstream puts your WiFi password at risk of being served by the filesystem.\ @@ -277,7 +281,11 @@ WLED_GLOBAL char releaseString[] _INIT(WLED_RELEASE_NAME); // must include the q // AP and OTA default passwords (for maximum security change them!) WLED_GLOBAL char apPass[65] _INIT(WLED_AP_PASS); +#ifdef WLED_OTA_PASS +WLED_GLOBAL char otaPass[33] _INIT(WLED_OTA_PASS); +#else WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS); +#endif // Hardware and pin config #ifndef BTNPIN @@ -411,7 +419,7 @@ WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on col WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value -WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color. +WLED_GLOBAL byte colPri[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. colPri[] should be updated if you want to change the color. WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color WLED_GLOBAL byte nightlightTargetBri _INIT(0); // brightness after nightlight is over @@ -570,11 +578,15 @@ WLED_GLOBAL byte macroLongPress[WLED_MAX_BUTTONS] _INIT({0}); WLED_GLOBAL byte macroDoublePress[WLED_MAX_BUTTONS] _INIT({0}); // Security CONFIG -WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks -WLED_GLOBAL bool wifiLock _INIT(false); // prevents access to WiFi settings when OTA lock is enabled -WLED_GLOBAL bool aOtaEnabled _INIT(true); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on -WLED_GLOBAL char settingsPIN[5] _INIT(""); // PIN for settings pages -WLED_GLOBAL bool correctPIN _INIT(true); +#ifdef WLED_OTA_PASS +WLED_GLOBAL bool otaLock _INIT(true); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks +#else +WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks +#endif +WLED_GLOBAL bool wifiLock _INIT(false); // prevents access to WiFi settings when OTA lock is enabled +WLED_GLOBAL bool aOtaEnabled _INIT(true); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on +WLED_GLOBAL char settingsPIN[5] _INIT(WLED_PIN); // PIN for settings pages +WLED_GLOBAL bool correctPIN _INIT(!strlen(settingsPIN)); WLED_GLOBAL unsigned long lastEditTime _INIT(0); WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use in usermod @@ -895,12 +907,11 @@ WLED_GLOBAL ESPAsyncE131 ddp _INIT_N(((handleE131Packet))); WLED_GLOBAL bool e131NewData _INIT(false); // led fx library object -WLED_GLOBAL BusManager busses _INIT(BusManager()); -WLED_GLOBAL WS2812FX strip _INIT(WS2812FX()); -WLED_GLOBAL std::vector busConfigs; //temporary, to remember values from network callback until after -WLED_GLOBAL bool doInitBusses _INIT(false); -WLED_GLOBAL int8_t loadLedmap _INIT(-1); -WLED_GLOBAL uint8_t currentLedmap _INIT(0); +WLED_GLOBAL WS2812FX strip _INIT(WS2812FX()); +WLED_GLOBAL std::vector busConfigs; //temporary, to remember values from network callback until after +WLED_GLOBAL bool doInitBusses _INIT(false); +WLED_GLOBAL int8_t loadLedmap _INIT(-1); +WLED_GLOBAL uint8_t currentLedmap _INIT(0); #ifndef ESP8266 WLED_GLOBAL char *ledmapNames[WLED_MAX_LEDMAPS-1] _INIT_N(({nullptr})); #endif diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index da7fd2a3a..77f4133c0 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -567,13 +567,14 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { //else if (url.indexOf("/edit") >= 0) subPage = 10; else subPage = SUBPAGE_WELCOME; - if (!correctPIN && strlen(settingsPIN) > 0 && (subPage > 0 && subPage < 11)) { + bool pinRequired = !correctPIN && strlen(settingsPIN) > 0 && (subPage > (WLED_WIFI_CONFIGURED ? SUBPAGE_MENU : SUBPAGE_WIFI) && subPage < SUBPAGE_LOCK); + if (pinRequired) { originalSubPage = subPage; subPage = SUBPAGE_PINREQ; // require PIN } // if OTA locked or too frequent PIN entry requests fail hard - if ((subPage == SUBPAGE_WIFI && wifiLock && otaLock) || (post && !correctPIN && millis()-lastEditTime < PIN_RETRY_COOLDOWN)) + if ((subPage == SUBPAGE_WIFI && wifiLock && otaLock) || (post && pinRequired && millis()-lastEditTime < PIN_RETRY_COOLDOWN)) { serveMessage(request, 401, FPSTR(s_accessdenied), FPSTR(s_unlock_ota), 254); return; } @@ -609,7 +610,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { if (!s2[0]) strcpy_P(s2, s_redirecting); bool redirectAfter9s = (subPage == SUBPAGE_WIFI || ((subPage == SUBPAGE_SEC || subPage == SUBPAGE_UM) && doReboot)); - serveMessage(request, (correctPIN ? 200 : 401), s, s2, redirectAfter9s ? 129 : (correctPIN ? 1 : 3)); + serveMessage(request, (!pinRequired ? 200 : 401), s, s2, redirectAfter9s ? 129 : (!pinRequired ? 1 : 3)); return; } } diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 9178a87a6..19868d01d 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -11,7 +11,7 @@ void XML_response(Print& dest) dest.printf_P(PSTR("%d"), (nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri); for (int i = 0; i < 3; i++) { - dest.printf_P(PSTR("%d"), col[i]); + dest.printf_P(PSTR("%d"), colPri[i]); } for (int i = 0; i < 3; i++) { @@ -20,7 +20,7 @@ void XML_response(Print& dest) dest.printf_P(PSTR("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%s%s%d"), notifyDirect, receiveGroups!=0, nightlightActive, nightlightMode > NL_MODE_SET, nightlightDelayMins, nightlightTargetBri, effectCurrent, effectSpeed, effectIntensity, effectPalette, - strip.hasWhiteChannel() ? col[3] : -1, colSec[3], currentPreset, currentPlaylist >= 0, + strip.hasWhiteChannel() ? colPri[3] : -1, colSec[3], currentPreset, currentPlaylist >= 0, serverDescription, realtimeMode ? PSTR(" (live)") : "", strip.getFirstSelectedSegId() ); @@ -275,7 +275,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) // set limits settingsScript.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"), WLED_MAX_BUSSES, - WLED_MIN_VIRTUAL_BUSSES, + WLED_MIN_VIRTUAL_BUSSES, // irrelevant, but kept to distinguish S2/S3 in UI MAX_LEDS_PER_BUS, MAX_LED_MEMORY, MAX_LEDS, @@ -296,9 +296,9 @@ void getSettingsJS(byte subPage, Print& settingsScript) unsigned sumMa = 0; for (int s = 0; s < BusManager::getNumBusses(); s++) { - Bus* bus = BusManager::getBus(s); - if (bus == nullptr) continue; - int offset = s < 10 ? 48 : 55; + const Bus* bus = BusManager::getBus(s); + if (!bus || !bus->isOk()) break; // should not happen but for safety + int offset = s < 10 ? '0' : 'A'; char lp[4] = "L0"; lp[2] = offset+s; lp[3] = 0; //ascii 0-9 //strip data pin char lc[4] = "LC"; lc[2] = offset+s; lc[3] = 0; //strip length char co[4] = "CO"; co[2] = offset+s; co[3] = 0; //strip color order @@ -316,7 +316,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) uint8_t pins[5]; int nPins = bus->getPins(pins); for (int i = 0; i < nPins; i++) { - lp[1] = offset+i; + lp[1] = '0'+i; if (PinManager::isPinOk(pins[i]) || bus->isVirtual()) printSetFormValue(settingsScript,lp,pins[i]); } printSetFormValue(settingsScript,lc,bus->getLength()); @@ -361,7 +361,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) const ColorOrderMap& com = BusManager::getColorOrderMap(); for (int s = 0; s < com.count(); s++) { const ColorOrderMapEntry* entry = com.get(s); - if (entry == nullptr) break; + if (!entry || !entry->len) break; settingsScript.printf_P(PSTR("addCOM(%d,%d,%d);"), entry->start, entry->len, entry->colorOrder); }