diff --git a/.github/dist/package_esp32_index_2_0_4.json b/.github/dist/package_esp32_index_2_0_4.json deleted file mode 100644 index a3fb91c..0000000 --- a/.github/dist/package_esp32_index_2_0_4.json +++ /dev/null @@ -1,1572 +0,0 @@ -{ - "packages": [ - { - "name": "esp32", - "maintainer": "Espressif Systems", - "websiteURL": "https://github.com/espressif/arduino-esp32", - "email": "hristo@espressif.com", - "help": { - "online": "http://esp32.com" - }, - "platforms": [ - { - "name": "esp32", - "architecture": "esp32", - "version": "2.0.4", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.4/esp32-2.0.4.zip", - "archiveFileName": "esp32-2.0.4.zip", - "checksum": "SHA-256:832609d6f4cd0edf4e471f02e30b7f0e1c86fdd1b950990ef40431e656237214", - "size": "259715595", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Board" - }, - { - "name": "ESP32-S2 Dev Board" - }, - { - "name": "ESP32-S3 Dev Board" - }, - { - "name": "ESP32-C3 Dev Board" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s3-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.3.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - }, - { - "packager": "esp32", - "name": "mklittlefs", - "version": "3.0.0-gnu12-dc7f933" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "2.0.3", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.3/esp32-2.0.3.zip", - "archiveFileName": "esp32-2.0.3.zip", - "checksum": "SHA-256:7a44ab32a2bfe18a84fd1f75aa1921dae92c6b4a74a2eb4d0c7d479b34996f3b", - "size": "246542267", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Board" - }, - { - "name": "ESP32-S2 Dev Board" - }, - { - "name": "ESP32-S3 Dev Board" - }, - { - "name": "ESP32-C3 Dev Board" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s3-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.3.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - }, - { - "packager": "esp32", - "name": "mklittlefs", - "version": "3.0.0-gnu12-dc7f933" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "2.0.2", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esp32-2.0.2.zip", - "archiveFileName": "esp32-2.0.2.zip", - "checksum": "SHA-256:e139f22aab9cbe8109815de0be110e58a8f1d6c90a2e263eb0b0d646b53a5a33", - "size": "151846438", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Board" - }, - { - "name": "ESP32-S2 Dev Board" - }, - { - "name": "ESP32-C3 Dev Board" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.1.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - }, - { - "packager": "esp32", - "name": "mklittlefs", - "version": "3.0.0-gnu12-dc7f933" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "2.0.1", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.1/esp32-2.0.1.zip", - "archiveFileName": "esp32-2.0.1.zip", - "checksum": "SHA-256:3a7cd46ba47990dd37fbe02b7f0a910dd5cc7af1d190350b69d320ed36cd6b41", - "size": "148976301", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Board" - }, - { - "name": "ESP32-S2 Dev Board" - }, - { - "name": "ESP32-C3 Dev Board" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.1.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - }, - { - "packager": "esp32", - "name": "mklittlefs", - "version": "3.0.0-gnu12-dc7f933" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "2.0.0", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0/esp32-2.0.0.zip", - "archiveFileName": "esp32-2.0.0.zip", - "checksum": "SHA-256:10e1c42dbf11d2359259a80008f13f37d2f9bb8f49a25d34d387cf4531052cbc", - "size": "139313137", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - }, - { - "name": "WEMOS D1 MINI ESP32" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r1" - }, - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r1" - }, - { - "packager": "esp32", - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r1" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.1.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - }, - { - "packager": "esp32", - "name": "mklittlefs", - "version": "3.0.0-gnu12-dc7f933" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "1.0.6", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.6/esp32-1.0.6.zip", - "archiveFileName": "esp32-1.0.6.zip", - "checksum": "SHA-256:982da9aaa181b6cb9c692dd4c9622b022ecc0d1e3aa0c5b70428ccc3c1b4556b", - "size": "51126662", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - }, - { - "name": "WEMOS D1 MINI ESP32" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "1.22.0-97-gc752ad5-5.2.0" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.0.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - } - ] - }, - { - "name": "esp32", - "architecture": "esp32", - "version": "1.0.5", - "category": "ESP32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5/esp32-1.0.5.zip", - "archiveFileName": "esp32-1.0.5.zip", - "checksum": "SHA-256:dc5c6c72a127b3171c654f3c3476911d3c2b0ab21affdb7b0f0756c105ca71a7", - "size": "49552769", - "help": { - "online": "" - }, - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - }, - { - "name": "WEMOS D1 MINI ESP32" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "name": "xtensa-esp32-elf-gcc", - "version": "1.22.0-97-gc752ad5-5.2.0" - }, - { - "packager": "esp32", - "name": "esptool_py", - "version": "3.0.0" - }, - { - "packager": "esp32", - "name": "mkspiffs", - "version": "0.2.3" - } - ] - }, - { - "category": "ESP32", - "name": "esp32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.4/esp32-1.0.4.zip", - "checksum": "SHA-256:d9108bf873933c4e48a3ca401fb51e41b2cc3f98d7c9b9be9881e7ca34bf0efe", - "help": { - "online": "" - }, - "version": "1.0.4", - "architecture": "esp32", - "archiveFileName": "esp32-1.0.4.zip", - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - }, - { - "name": "WEMOS D1 MINI ESP32" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc" - }, - { - "packager": "esp32", - "version": "2.6.1", - "name": "esptool_py" - }, - { - "packager": "esp32", - "version": "0.2.3", - "name": "mkspiffs" - } - ], - "size": "36853332" - }, - { - "category": "ESP32", - "name": "esp32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.3/esp32-1.0.3.zip", - "checksum": "SHA-256:19a30ece8a3ab26ab420c3d5531a9a1c51cb04e421a4f1d86dc072c209060436", - "help": { - "online": "" - }, - "version": "1.0.3", - "architecture": "esp32", - "archiveFileName": "esp32-1.0.3.zip", - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - }, - { - "name": "WEMOS D1 MINI ESP32" - } - ], - "toolsDependencies": [ - { - "packager": "esp32", - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc" - }, - { - "packager": "esp32", - "version": "2.6.1", - "name": "esptool_py" - }, - { - "packager": "esp32", - "version": "0.2.3", - "name": "mkspiffs" - } - ], - "size": "36811826" - }, - { - "category": "ESP32", - "help": { - "online": "" - }, - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.2/esp32-1.0.2.zip", - "checksum": "SHA-256:c3a5a5050705d41ab205d25a7399e921057b754ef8f883419f58c0c7f08df11c", - "version": "1.0.2", - "architecture": "esp32", - "archiveFileName": "esp32-1.0.2.zip", - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - } - ], - "size": "31174160", - "toolsDependencies": [ - { - "packager": "esp32", - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc" - }, - { - "packager": "esp32", - "version": "2.6.1", - "name": "esptool_py" - }, - { - "packager": "esp32", - "version": "0.2.3", - "name": "mkspiffs" - } - ], - "name": "esp32" - }, - { - "category": "ESP32", - "help": { - "online": "" - }, - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.1/esp32-1.0.1.zip", - "checksum": "SHA-256:1a7fa2f9bb0b6b5a20dfea227497f4851dc8b886caf7ecb998f745589c97ed34", - "name": "esp32", - "version": "1.0.1", - "architecture": "esp32", - "archiveFileName": "esp32-1.0.1.zip", - "size": "31273425", - "toolsDependencies": [ - { - "packager": "esp32", - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc" - }, - { - "packager": "esp32", - "version": "2.6.0", - "name": "esptool_py" - }, - { - "packager": "esp32", - "version": "0.2.3", - "name": "mkspiffs" - } - ], - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - } - ] - }, - { - "category": "ESP32", - "help": { - "online": "" - }, - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.0/esp32-1.0.0.zip", - "checksum": "SHA-256:94d586174f103e2014be590ab307c5cdda6fa2ec70204c7f121882ace5e05c80", - "name": "esp32", - "version": "1.0.0", - "architecture": "esp32", - "archiveFileName": "esp32-1.0.0.zip", - "size": "26381887", - "toolsDependencies": [ - { - "packager": "esp32", - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc" - }, - { - "packager": "esp32", - "version": "2.3.1", - "name": "esptool" - }, - { - "packager": "esp32", - "version": "0.2.3", - "name": "mkspiffs" - } - ], - "boards": [ - { - "name": "ESP32 Dev Module" - }, - { - "name": "WEMOS LoLin32" - } - ] - } - ], - "tools": [ - { - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "checksum": "SHA-256:179cbad579790ad35e0f414a18d90017c0f158c397022411a8e9867db2174f15", - "size": "106843321" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "checksum": "SHA-256:fb339d476c79c76db8f903b265cab6bb6950d5ed954dec644445252d3378023c", - "size": "103277393" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "checksum": "SHA-256:51a6296d8334b7452dba44b2b62e87afd7fd1c74bafa1aa29b1f4ab72cb9e5e0", - "size": "103062256" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "checksum": "SHA-256:fef60f7ef37ffaa50416d8f244cdbd710d6729dae41ef06c4ec0e50a1f3b7dd7", - "size": "109460025" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "checksum": "SHA-256:4aacc1742a76349d790b1ac8e9e9d963daefda5346dbd6741cfe8e7a35a44e4e", - "size": "113703959" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "checksum": "SHA-256:eb2a442d7f551ebeb842995ec372ec4b364314ca2d7aae779399a74972f7d6bc", - "size": "144711970" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "checksum": "SHA-256:f5607e5187317d521f0474cade83f8eb590f2d165d95c3779b6ce11fbac21d1f", - "size": "146606480" - } - ] - }, - { - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r2", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "checksum": "SHA-256:812d735063da9d063b374b59f55832a96c41fbd27ddaef19000a75de8607ba21", - "size": "106837189" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "checksum": "SHA-256:712f1fbc3e08304a6f32aa18b346b16bbcb413b507b3d4c7c3211bf0d7dc4813", - "size": "103273444" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "checksum": "SHA-256:80a3342cda2cd4b6b75ebb2b36d5d12fce7d375cfadadcff01ec3a907f0a16a2", - "size": "103058744" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "checksum": "SHA-256:7f0162a81558ab0ed09d6c5d356def25b5cb3d5c2d61358f20152fa260ccc8ae", - "size": "109447789" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "checksum": "SHA-256:3ff7e5427907cf8e271c1f959b70fb01e39625c3caf61a6567e7b38aa0c11578", - "size": "113672945" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-win32.zip", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-win32.zip", - "checksum": "SHA-256:c8ff08883c1456c278fad85e1c43b7c6e251d525683214168655550e85c5b82e", - "size": "140809778" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-win64.zip", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-win64.zip", - "checksum": "SHA-256:6c04cb4728db928ec6473e63146b695b6dec686a0d40dd73dd3353f05247b19e", - "size": "142365782" - } - ] - }, - { - "name": "riscv32-esp-elf-gcc", - "version": "gcc8_4_0-esp-2021r1", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "checksum": "SHA-256:3459618f33bbd5f54d7d7783e807cb6eef6472a220f2f1eb3faced735b9d13bb", - "size": "152812483" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "checksum": "SHA-256:24b9e54b348bbd5fb816fc4c52abb47337c702beecdbba840750b7cfb9d38069", - "size": "151726623" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "checksum": "SHA-256:954d340ebffef12a2ce9be1ea004e6f45a8863f1e6f41f46fd3f04f58499627c", - "size": "155430963" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "checksum": "SHA-256:612fb3a3f84f703222327bd16581df8f80fda8cdf137637fe5d611587d1b664e", - "size": "159836199" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-win32.zip", - "archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-win32.zip", - "checksum": "SHA-256:5711eb407ffe44adddbd1281b6b575a5645e7193ca78faefa27dc5bc5b662bec", - "size": "191266312" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "checksum": "SHA-256:9edd1e77627688f435561922d14299f6a0021ba1f6ff67e472e1108695a69e53", - "size": "90569312" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "checksum": "SHA-256:3a21a3e310e6b1e7d7bed1f3e59698a5bd29ed3a5ca79fba9265d7dd2f1e0cd2", - "size": "86838362" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "checksum": "SHA-256:89313c4c1d8db1b01624f31b58bf3fbe527160569828ac4301e9daa75c52716d", - "size": "86187540" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "checksum": "SHA-256:a1f165a836f175daa6fbfde4ca99cb93b377f021fbfc41f79a700bd4df965a9a", - "size": "92580267" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "checksum": "SHA-256:dda3d7a43efd995d9a51d5a5741626dbf915df46078aef0b5aea7163ac82398b", - "size": "97807647" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "checksum": "SHA-256:fd147592928ef2d7092ba34b01ecd776fe26ba3d7e3f9b6b215a3b46e981ee2c", - "size": "116464819" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "checksum": "SHA-256:9395315c07de0b9f05c9a6616ba1f05e76ab651053f2f40479163a8e03cfa830", - "size": "119511910" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r2", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "checksum": "SHA-256:3eb3d68b27fa6ba5af6f88da21cb8face9be0094daaa8960793cfe570ab785ff", - "size": "90565318" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "checksum": "SHA-256:aa534be24e45e06b7080a6a3bb8cd9e3cfb818f5f8bce2244d7cfb5e91336541", - "size": "86860292" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "checksum": "SHA-256:f0e49ce06fe7833ff5d76961dc2dac5449d320f823bb8c05a302cf85a3a6eb04", - "size": "86183421" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "checksum": "SHA-256:06de09b74652de43e5b22db3b7fc992623044baa75e9faaab68317a986715ba3", - "size": "92582250" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "checksum": "SHA-256:96443f69c8569417c780ee749d91ef33cffe22153fffa30a0fbf12107d87381b", - "size": "97808961" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win32.zip", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win32.zip", - "checksum": "SHA-256:076a4171bdc33e5ced3952efffb233d70263dfa760e636704050597a9edf61db", - "size": "112578260" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win64.zip", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win64.zip", - "checksum": "SHA-256:c35b7998f7f503e0cb22055d1e279ae14b6b0e09bb3ff3846b17d552ece9c247", - "size": "115278695" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "gcc8_4_0-esp-2021r1", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "checksum": "SHA-256:44a0b467b9d2b759ab48b2f27aed684581f33c96e2842992781c4e045992c5b0", - "size": "86361217" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "checksum": "SHA-256:fdacdb2a7bbf6293bcafda9b52463a4da8a2f3b7e1df9f83d35ff9d1efa22012", - "size": "84520407" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "checksum": "SHA-256:e2024096492dfaa50fc6ac336cd8faa2e395e8cebb617753eab0b5f16d3dd0dc", - "size": "88375391" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "checksum": "SHA-256:7bbc6a2b94f009cd8a3351b9c7acf7a5caa1c4d3700500ead60f84965386a61b", - "size": "93357296" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-win32.zip", - "archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-win32.zip", - "checksum": "SHA-256:e4f9fdda192abfc9807e3e7fcd6e9fea30c1a0cf3f3c5a5c961b5114fc8c9b7e", - "size": "105603626" - } - ] - }, - { - "name": "xtensa-esp32-elf-gcc", - "version": "1.22.0-97-gc752ad5-5.2.0", - "systems": [ - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-win32-1.22.0-97-gc752ad5-5.2.0.zip", - "archiveFileName": "xtensa-esp32-elf-win32-1.22.0-97-gc752ad5-5.2.0.zip", - "checksum": "SHA-256:80571e5d5a63494f4fa758bb9d8fb882ba4059853a8c412a84d232dc1c1400e6", - "size": "125747216" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-macos-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "archiveFileName": "xtensa-esp32-elf-macos-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "checksum": "SHA-256:b1ce39a563ae359cf363fb7d8ee80cb1e5226fda83188203cff60f16f55e33ef", - "size": "50525386" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "archiveFileName": "xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "checksum": "SHA-256:96f5f6e7611a0ed1dc47048c54c3113fc5cebffbf0ba90d8bfcd497afc7ef9f3", - "size": "44225380" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux32-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "archiveFileName": "xtensa-esp32-elf-linux32-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "checksum": "SHA-256:8094a2c30b474e99ce64dd0ba8f310c4614eb3b3cac884a3aea0fd5f565af119", - "size": "45575521" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "checksum": "SHA-256:d70d550f88448fa476b29fa50ef5502ab497a16ac7fa9ca24c6d0a39bb1e681e", - "size": "50657803" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-97-gc752ad5-5.2.0.tar.gz", - "checksum": "SHA-256:d70d550f88448fa476b29fa50ef5502ab497a16ac7fa9ca24c6d0a39bb1e681e", - "size": "50657803" - } - ] - }, - { - "version": "1.22.0-80-g6c4433a-5.2.0", - "name": "xtensa-esp32-elf-gcc", - "systems": [ - { - "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip", - "checksum": "SHA-256:f217fccbeaaa8c92db239036e0d6202458de4488b954a3a38f35ac2ec48058a4", - "host": "i686-mingw32", - "archiveFileName": "xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip", - "size": "125719261" - }, - { - "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "checksum": "SHA-256:a4307a97945d2f2f2745f415fbe80d727750e19f91f9a1e7e2f8a6065652f9da", - "host": "x86_64-apple-darwin", - "archiveFileName": "xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "size": "46517409" - }, - { - "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "checksum": "SHA-256:3fe96c151d46c1d4e5edc6ed690851b8e53634041114bad04729bc16b0445156", - "host": "x86_64-pc-linux-gnu", - "archiveFileName": "xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "size": "44219107" - }, - { - "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "checksum": "SHA-256:b4055695ffc2dfc0bcb6dafdc2572a6e01151c4179ef5fa972b3fcb2183eb155", - "host": "i686-pc-linux-gnu", - "archiveFileName": "xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz", - "size": "45566336" - }, - { - "url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux-armel-1.22.0-87-gb57bad3-5.2.0.tar.gz", - "checksum": "SHA-256:9c68c87bb23b1256dc0a1859b515946763e5292dcab4a4159a52fae5618ce861", - "host": "arm-linux-gnueabihf", - "archiveFileName": "xtensa-esp32-elf-linux-armel-1.22.0-87-gb57bad3-5.2.0.tar.gz", - "size": "50655584" - } - ] - }, - { - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "checksum": "SHA-256:a32451a8edc1104b83cd9971178e61826e957d7db9ad9f81798a8969fd5a954e", - "size": "90894048" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "checksum": "SHA-256:2ac2c94a533a99a091d2159c678c611c712c494b5f68d97913254712047260f9", - "size": "87178224" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "checksum": "SHA-256:da49afee1e2e03eaab3f492718789442d33b562800e2a892679f95b50be24d14", - "size": "86569314" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "checksum": "SHA-256:36d3c4990a5feb68aa8534463bc9e8ee367fe23886f78e1d726f4411c7571462", - "size": "92884013" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "checksum": "SHA-256:de9af641678c93775e932ee5ec4f478f8925cfc1ebc22e41adc4fb85430a0c35", - "size": "98224709" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "checksum": "SHA-256:ccf08afe60046f87b0e81ca17dc5073eda68ab5e7522c163dd5b583d713b7b39", - "size": "116924759" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "checksum": "SHA-256:37c91490b8fc75e638c23785e261eaf553be2dcd106cf6cff5b76981fa02955b", - "size": "119912142" - } - ] - }, - { - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r2", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz", - "checksum": "SHA-256:a6e0947c92b823ca04f062522249f0a428357e0b056f1ff4c6bcabef83cf63a7", - "size": "90901736" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz", - "checksum": "SHA-256:d2e5600fc194b508bd393b236a09fd62ed70afb6c36619d4b106b696a56ca66d", - "size": "87176557" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz", - "checksum": "SHA-256:3fff4199e986dd74660f17ca27d9414cb98f1b911a7f13bb3b22e784cb1156cf", - "size": "86581102" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz", - "checksum": "SHA-256:7732f9fb371d36b6b324820e300beecc33c2719921a61cf1cdb5bc625016b346", - "size": "92875986" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-macos.tar.gz", - "checksum": "SHA-256:e6dd32782fcff8f633299b97d1c671d6b6513390aca2ddbd7543c2cc62e72d7e", - "size": "98212907" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win32.zip", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win32.zip", - "checksum": "SHA-256:41b917b35f6fbe7d30b7de91c32cf348c406acfa729a1eabc450d040dc46fbe2", - "size": "113022469" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win64.zip", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win64.zip", - "checksum": "SHA-256:a764c1a0ee743d69f8cbfadbe4426a2c15c0e233b0894244c7cadf3b4d7dd32a", - "size": "115696999" - } - ] - }, - { - "name": "xtensa-esp32s2-elf-gcc", - "version": "gcc8_4_0-esp-2021r1", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz", - "checksum": "SHA-256:b127baccfe6949ee7eaf3d0782ea772750a9b8e2732b16ce6bcc9dcd91f7209a", - "size": "86687290" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz", - "checksum": "SHA-256:7ca0d240f11e1c53c01a56257b0c968f876ab405142d1068d8c9b456d939554c", - "size": "84916701" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz", - "checksum": "SHA-256:9941f993ff84d1c606b45ffbeeb7bcdc5a72cf24e787bb9230390510fe3511c6", - "size": "88699953" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-macos.tar.gz", - "checksum": "SHA-256:4b55b1a9ca7fc945be6fc3513802b6cece9264bee4cbca76013569cec2695973", - "size": "93757895" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-win32.zip", - "archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-win32.zip", - "checksum": "SHA-256:c94ec1e45c81b7e4944d216bab4aa41d46849768d7761fd691661dab1a3df828", - "size": "106013515" - } - ] - }, - { - "name": "xtensa-esp32s3-elf-gcc", - "version": "gcc8_4_0-esp-2021r2-patch3", - "systems": [ - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz", - "checksum": "SHA-256:59b271d014ff3915b6db1b43b610a45eea15fe5d6877d12cae8a191cc996ed37", - "size": "90903617" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-arm64.tar.gz", - "checksum": "SHA-256:7051b32483e61f98606d71c98e372929428a5165df791dcd5830ed9517763152", - "size": "87065204" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz", - "checksum": "SHA-256:48c8dbbf96eec691a812327dc580042d9718fe989e60c2111ebfd692ac710081", - "size": "86455731" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-i686.tar.gz", - "checksum": "SHA-256:552dca3f4302ab7ca88a934b0391200198c9d10a4d8ac413fe604cbf8601f950", - "size": "92906274" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-macos.tar.gz", - "checksum": "SHA-256:e5af78f05d3af07617805d06ebb45ff2fe9b6aed6970a84c35eea28a5d8d5e53", - "size": "98553473" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-win32.zip", - "checksum": "SHA-256:1b70163acccc5655449de1d149427a54f384156bd35816ec60c422d76d033f05", - "size": "116847008" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch3/xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "archiveFileName": "xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-win64.zip", - "checksum": "SHA-256:58e58575d1938879fd51e822181e54bcb343aa846eb3fca8f616c2cde7bd0041", - "size": "120066269" - } - ] - }, - { - "name": "esptool_py", - "version": "3.3.0", - "systems": [ - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-windows.zip", - "archiveFileName": "esptool-3.3-windows.zip", - "checksum": "SHA-256:55a1d7165414bf4dbd2bb16ca094e555d671958450f5d1536b457a518d2b15df", - "size": "7436864" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-windows.zip", - "archiveFileName": "esptool-3.3-windows.zip", - "checksum": "SHA-256:55a1d7165414bf4dbd2bb16ca094e555d671958450f5d1536b457a518d2b15df", - "size": "7436864" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-macos.tar.gz", - "archiveFileName": "esptool-3.3-macos.tar.gz", - "checksum": "SHA-256:3e5f7b521ae33c8c63f3b48efc909c08f37bef1a083c0eafa408312c09900afd", - "size": "6944975" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-linux.tar.gz", - "archiveFileName": "esptool-3.3-linux.tar.gz", - "checksum": "SHA-256:fbe91a49e5f5deca4881f5eed32e8903faf97bfd365fe2d0d1512b80bdb67f5e", - "size": "97026" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-linux.tar.gz", - "archiveFileName": "esptool-3.3-linux.tar.gz", - "checksum": "SHA-256:fbe91a49e5f5deca4881f5eed32e8903faf97bfd365fe2d0d1512b80bdb67f5e", - "size": "97026" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-linux.tar.gz", - "archiveFileName": "esptool-3.3-linux.tar.gz", - "checksum": "SHA-256:fbe91a49e5f5deca4881f5eed32e8903faf97bfd365fe2d0d1512b80bdb67f5e", - "size": "97026" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.2/esptool-3.3-linux.tar.gz", - "archiveFileName": "esptool-3.3-linux.tar.gz", - "checksum": "SHA-256:fbe91a49e5f5deca4881f5eed32e8903faf97bfd365fe2d0d1512b80bdb67f5e", - "size": "97026" - } - ] - }, - { - "name": "esptool_py", - "version": "3.1.0", - "systems": [ - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-windows.zip", - "archiveFileName": "esptool-3.1.0-windows.zip", - "checksum": "SHA-256:c9b4f9bc6e94db136c2545c87c00c7ab1441644ca0bac50811bc3c014e22514b", - "size": "7411889" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-macos.tar.gz", - "archiveFileName": "esptool-3.1.0-macos.tar.gz", - "checksum": "SHA-256:1dffcb884665fb616779aea62a68f517aac251ea6dfe95560906c364d6ef3065", - "size": "6776909" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-linux.tar.gz", - "archiveFileName": "esptool-3.1.0-linux.tar.gz", - "checksum": "SHA-256:15eca9896a30e804aa24be6f7a06e39397541b8b09a7a4c48deb65f826e7baad", - "size": "80550" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-linux.tar.gz", - "archiveFileName": "esptool-3.1.0-linux.tar.gz", - "checksum": "SHA-256:15eca9896a30e804aa24be6f7a06e39397541b8b09a7a4c48deb65f826e7baad", - "size": "80550" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-linux.tar.gz", - "archiveFileName": "esptool-3.1.0-linux.tar.gz", - "checksum": "SHA-256:15eca9896a30e804aa24be6f7a06e39397541b8b09a7a4c48deb65f826e7baad", - "size": "80550" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/2.0.0-alpha1/esptool-3.1.0-linux.tar.gz", - "archiveFileName": "esptool-3.1.0-linux.tar.gz", - "checksum": "SHA-256:15eca9896a30e804aa24be6f7a06e39397541b8b09a7a4c48deb65f826e7baad", - "size": "80550" - } - ] - }, - { - "name": "esptool_py", - "version": "3.0.0", - "systems": [ - { - "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-windows.zip", - "archiveFileName": "esptool-3.0.0.2-windows.zip", - "checksum": "SHA-256:b192bfc1545a3c92658ce586b4edcc2aca3f0ad4b3fa8417d658bc8a48f1387e", - "size": "3434736" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-macos.tar.gz", - "archiveFileName": "esptool-3.0.0.2-macos.tar.gz", - "checksum": "SHA-256:2cafab7f1ebce89475b84c115548eaace40b6366d7b3f9862cdb2fc64f806643", - "size": "3859642" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz", - "archiveFileName": "esptool-3.0.0.2-linux.tar.gz", - "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", - "size": "57526" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz", - "archiveFileName": "esptool-3.0.0.2-linux.tar.gz", - "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", - "size": "57526" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz", - "archiveFileName": "esptool-3.0.0.2-linux.tar.gz", - "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", - "size": "57526" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/1.0.5-rc5/esptool-3.0.0.2-linux.tar.gz", - "archiveFileName": "esptool-3.0.0.2-linux.tar.gz", - "checksum": "SHA-256:d5cb51da1c74ff69f81b820470d2ecccb5c7c3a2dec7776483d4c89588b00020", - "size": "57526" - } - ] - }, - { - "version": "2.6.1", - "name": "esptool_py", - "systems": [ - { - "url": "https://dl.espressif.com/dl/esptool-2.6.1-windows.zip", - "checksum": "SHA-256:84cf0b369a7707fe566434faba148852fc464992111d5baa95b658b374802f96", - "host": "i686-mingw32", - "archiveFileName": "esptool-2.6.1-windows.zip", - "size": "3422445" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.1-macos.tar.gz", - "checksum": "SHA-256:f4eb758a301d6902cc9dfcd49d36345d2f075ad123da7cf8132d15cfb7533457", - "host": "x86_64-apple-darwin", - "archiveFileName": "esptool-2.6.1-macos.tar.gz", - "size": "3837085" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz", - "checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb", - "host": "x86_64-pc-linux-gnu", - "archiveFileName": "esptool-2.6.1-linux.tar.gz", - "size": "44762" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz", - "checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb", - "host": "i686-pc-linux-gnu", - "archiveFileName": "esptool-2.6.1-linux.tar.gz", - "size": "44762" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.1-linux.tar.gz", - "checksum": "SHA-256:eaf82ff4070d9792f6a42ae1e485375de5a87bec59ef01dfb95de901519ec7fb", - "host": "arm-linux-gnueabihf", - "archiveFileName": "esptool-2.6.1-linux.tar.gz", - "size": "44762" - } - ] - }, - { - "version": "2.6.0", - "name": "esptool_py", - "systems": [ - { - "url": "https://dl.espressif.com/dl/esptool-2.6.0-windows.zip", - "checksum": "SHA-256:a73f4cf68db240d7f1d250c5c7f2dfcb53c17a37483729f1bf71f8f43d79a799", - "host": "i686-mingw32", - "archiveFileName": "esptool-2.6.0-windows.zip", - "size": "3421208" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.0-macos.tar.gz", - "checksum": "SHA-256:0a881b91547c840fab8c72ae3d031069384278b8c2e5241647e8c8292c5e4a4b", - "host": "x86_64-apple-darwin", - "archiveFileName": "esptool-2.6.0-macos.tar.gz", - "size": "3835660" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz", - "checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110", - "host": "x86_64-pc-linux-gnu", - "archiveFileName": "esptool-2.6.0-linux.tar.gz", - "size": "43535" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz", - "checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110", - "host": "i686-pc-linux-gnu", - "archiveFileName": "esptool-2.6.0-linux.tar.gz", - "size": "43535" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz", - "checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110", - "host": "arm-linux-gnueabihf", - "archiveFileName": "esptool-2.6.0-linux.tar.gz", - "size": "43535" - } - ] - }, - { - "version": "3.0.0-gnu12-dc7f933", - "name": "mklittlefs", - "systems": [ - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/aarch64-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "archiveFileName": "aarch64-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "checksum": "SHA-256:fc56e389383749e4cf4fab0fcf75cc0ebc41e59383caf6c2eff1c3d9794af200", - "size": "44651" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/arm-linux-gnueabihf.mklittlefs-c41e51a.200706.tar.gz", - "archiveFileName": "arm-linux-gnueabihf.mklittlefs-c41e51a.200706.tar.gz", - "checksum": "SHA-256:52b642dd0545eb3bd8dfb75dde6601df21700e4867763fd2696274be279294c5", - "size": "37211" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/i686-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "archiveFileName": "i686-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "checksum": "SHA-256:7886051d8ccc54aed0af2e7cdf6ff992bb51638df86f3b545955697720b6d062", - "size": "48033" - }, - { - "host": "i686-mingw32", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/i686-w64-mingw32.mklittlefs-c41e51a.200706.zip", - "archiveFileName": "i686-w64-mingw32.mklittlefs-c41e51a.200706.zip", - "checksum": "SHA-256:43740db30ce451454f2337331f10ab4ed41bd83dbf0fa0cb4387107388b59f42", - "size": "332655" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/x86_64-apple-darwin14.mklittlefs-c41e51a.200706.tar.gz", - "archiveFileName": "x86_64-apple-darwin14.mklittlefs-c41e51a.200706.tar.gz", - "checksum": "SHA-256:e3edd5e05b70db3c7df6b9d626558348ad04804022fe955c799aeb51808c7dc3", - "size": "362608" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/x86_64-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "archiveFileName": "x86_64-linux-gnu.mklittlefs-c41e51a.200706.tar.gz", - "checksum": "SHA-256:66e84dda0aad747517da3785125e05738a540948aab2b7eaa02855167a1eea53", - "size": "46778" - }, - { - "host": "x86_64-mingw32", - "url": "https://github.com/earlephilhower/esp-quick-toolchain/releases/download/3.0.0-gnu12/x86_64-w64-mingw32.mklittlefs-c41e51a.200706.zip", - "archiveFileName": "x86_64-w64-mingw32.mklittlefs-c41e51a.200706.zip", - "checksum": "SHA-256:2e319077491f8e832e96eb4f2f7a70dd919333cee4b388c394e0e848d031d542", - "size": "345132" - } - ] - }, - { - "name": "mkspiffs", - "version": "0.2.3", - "systems": [ - { - "host": "i686-mingw32", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-win32.zip", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-win32.zip", - "checksum": "SHA-256:b647f2c2efe6949819c85ea9404271b55c7c9c25bcb98d3b98a1d0ba771adf56", - "size": "249809" - }, - { - "host": "x86_64-apple-darwin", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-osx.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-osx.tar.gz", - "checksum": "SHA-256:9f43fc74a858cf564966b5035322c3e5e61c31a647c5a1d71b388ed6efc48423", - "size": "130270" - }, - { - "host": "i386-apple-darwin", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-osx.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-osx.tar.gz", - "checksum": "SHA-256:9f43fc74a858cf564966b5035322c3e5e61c31a647c5a1d71b388ed6efc48423", - "size": "130270" - }, - { - "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-linux64.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux64.tar.gz", - "checksum": "SHA-256:5e1a4ff41385e842f389f6b5254102a547e566a06b49babeffa93ef37115cb5d", - "size": "50646" - }, - { - "host": "i686-pc-linux-gnu", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-linux32.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux32.tar.gz", - "checksum": "SHA-256:464463a93e8833209cdc29ba65e1a12fec31718dc10075c195a2445b2c3f6cb0", - "size": "48751" - }, - { - "host": "arm-linux-gnueabihf", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz", - "checksum": "SHA-256:ade3dc00117912ac08a1bdbfbfe76b12d21a34bc5fa1de0cfc45fe7a8d0a0185", - "size": "40665" - }, - { - "host": "aarch64-linux-gnu", - "url": "https://github.com/igrr/mkspiffs/releases/download/0.2.3/mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz", - "archiveFileName": "mkspiffs-0.2.3-arduino-esp32-linux-armhf.tar.gz", - "checksum": "SHA-256:ade3dc00117912ac08a1bdbfbfe76b12d21a34bc5fa1de0cfc45fe7a8d0a0185", - "size": "40665" - } - ] - }, - { - "version": "2.3.1", - "name": "esptool", - "systems": [ - { - "url": "https://dl.espressif.com/dl/esptool-2.3.1-windows.zip", - "checksum": "SHA-256:c187763d0faac7da7c30a292a23c759bbc256fcd084dc8846ed284000cb0fe29", - "host": "i686-mingw32", - "archiveFileName": "esptool-2.3.1-windows.zip", - "size": "3396085" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.3.1-macos.tar.gz", - "checksum": "SHA-256:cd922418f02e0ca11dc066b36a22646a1b441da00d762b4464ca598c902c5ecb", - "host": "x86_64-apple-darwin", - "archiveFileName": "esptool-2.3.1-macos.tar.gz", - "size": "3810932" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.3.1-linux.tar.gz", - "checksum": "SHA-256:cff30841dad80ed5d7d2d58a31843b63afa57528979a9c839806568167691d8e", - "host": "x86_64-pc-linux-gnu", - "archiveFileName": "esptool-2.3.1-linux.tar.gz", - "size": "39563" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.3.1-linux.tar.gz", - "checksum": "SHA-256:cff30841dad80ed5d7d2d58a31843b63afa57528979a9c839806568167691d8e", - "host": "i686-pc-linux-gnu", - "archiveFileName": "esptool-2.3.1-linux.tar.gz", - "size": "39563" - }, - { - "url": "https://dl.espressif.com/dl/esptool-2.3.1-linux.tar.gz", - "checksum": "SHA-256:cff30841dad80ed5d7d2d58a31843b63afa57528979a9c839806568167691d8e", - "host": "arm-linux-gnueabihf", - "archiveFileName": "esptool-2.3.1-linux.tar.gz", - "size": "39563" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef96147..458faea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,53 +1,79 @@ name: Build using Github Actions on: [push, pull_request] jobs: - build-source: + build: name: Checkout source code and build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y python3-serial cmake - - name: Install Arduino IDE - run: | - curl -L https://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz -o /tmp/arduino-ide.tar.xz - tar -xf /tmp/arduino-ide.tar.xz --directory ~/ - cd ~/arduino* - ./install.sh - ./arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" --save-prefs - ./arduino --install-boards esp32:esp32:2.0.15 - - name: Install Arduino CMake Toolchain - uses: actions/checkout@v2 + - uses: actions/cache@v4 with: - repository: technyon/Arduino-CMake-Toolchain - path: arduino-toolchain - - name: Build - run: | - mkdir -p build - cd build - touch file_opts - cmake -D CMAKE_TOOLCHAIN_FILE=../arduino-toolchain/Arduino-toolchain.cmake .. - echo "# Espressif ESP32 Partition Table" > partitions.csv - echo "# Name, Type, SubType, Offset, Size, Flags" >> partitions.csv - echo "nvs, data, nvs, 0x9000, 0x5000," >> partitions.csv - echo "otadata, data, ota, 0xe000, 0x2000," >> partitions.csv - echo "app0, app, ota_0, 0x10000, 0x1E0000," >> partitions.csv - echo "app1, app, ota_1, 0x1F0000,0x1E0000," >> partitions.csv - echo "spiffs, data, spiffs, 0x3D0000,0x30000," >> partitions.csv - make - - name: Upload artifacts - run: | - mkdir release - cp build/nuki_hub.bin release/ - cp build/nuki_hub.partitions.bin release/ - cp $(find ~/.arduino15/packages/esp32/ | grep boot_app0.bin) release/ - echo "esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 boot_app0.bin 0x1000 bootloader_dio_80m.bin 0x10000 nuki_hub.bin 0x8000 nuki_hub.partitions.bin" > release/flash.sh - - uses: actions/upload-artifact@v3 + path: | + ~/.cache/pip + ~/.platformio/.cache + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v5 with: - name: release-assets - path: release/ - + python-version: '3.9' + - name: Install PlatformIO Core + run: pip install --upgrade platformio + - name: Install ESPTool + run: pip install --upgrade esptool + - name: Build PlatformIO Project esp32dev + run: | + pio run --environment esp32dev + mkdir -p release/esp32dev + cp .pio/build/esp32dev/firmware.bin release/esp32dev/nuki_hub.bin + cp .pio/build/esp32dev/partitions.bin release/esp32dev/nuki_hub.partitions.bin + cp .pio/build/esp32dev/bootloader.bin release/esp32dev/bootloader.bin + esptool.py --chip esp32 merge_bin -o release/esp32dev/nuki_hub_esp32.bin --flash_mode dio --flash_freq keep --flash_size keep 0x1000 release/esp32dev/bootloader.bin 0x10000 release/esp32dev/nuki_hub.bin 0x8000 release/esp32dev/nuki_hub.partitions.bin + echo "esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq keep --flash_size detect 0x1000 bootloader.bin 0x10000 nuki_hub.bin 0x8000 nuki_hub.partitions.bin" > release/esp32dev/flash.sh + - name: Build PlatformIO Project esp32-s3 + run: | + pio run --environment esp32-s3 + mkdir -p release/esp32-s3 + cp .pio/build/esp32-s3/firmware.bin release/esp32-s3/nuki_hub.bin + cp .pio/build/esp32-s3/partitions.bin release/esp32-s3/nuki_hub.partitions.bin + cp .pio/build/esp32-s3/bootloader.bin release/esp32-s3/bootloader.bin + esptool.py --chip esp32s3 merge_bin -o release/esp32-s3/nuki_hub_esp32s3.bin --flash_mode dio --flash_freq keep --flash_size keep 0x0 release/esp32-s3/bootloader.bin 0x10000 release/esp32-s3/nuki_hub.bin 0x8000 release/esp32-s3/nuki_hub.partitions.bin + echo "esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq keep --flash_size detect 0x0 bootloader.bin 0x10000 nuki_hub.bin 0x8000 nuki_hub.partitions.bin" > release/esp32-s3/flash.sh + - name: Build PlatformIO Project esp32-c3 + run: | + pio run --environment esp32-c3 + mkdir -p release/esp32-c3 + cp .pio/build/esp32-c3/firmware.bin release/esp32-c3/nuki_hub.bin + cp .pio/build/esp32-c3/partitions.bin release/esp32-c3/nuki_hub.partitions.bin + cp .pio/build/esp32-c3/bootloader.bin release/esp32-c3/bootloader.bin + esptool.py --chip esp32c3 merge_bin -o release/esp32-c3/nuki_hub_esp32c3.bin --flash_mode dio --flash_freq keep --flash_size keep 0x0 release/esp32-c3/bootloader.bin 0x10000 release/esp32-c3/nuki_hub.bin 0x8000 release/esp32-c3/nuki_hub.partitions.bin + echo "esptool.py --chip esp32c3 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq keep --flash_size detect 0x0 bootloader.bin 0x10000 nuki_hub.bin 0x8000 nuki_hub.partitions.bin" > release/esp32-c3/flash.sh + - name: Build PlatformIO Project esp32solo1 + run: | + pio run --environment esp32solo1 + mkdir -p release/esp32solo1 + cp .pio/build/esp32solo1/firmware.bin release/esp32solo1/nuki_hub.bin + cp .pio/build/esp32solo1/partitions.bin release/esp32solo1/nuki_hub.partitions.bin + cp .pio/build/esp32solo1/bootloader.bin release/esp32solo1/bootloader.bin + esptool.py --chip esp32 merge_bin -o release/esp32solo1/nuki_hub_esp32solo1.bin --flash_mode dio --flash_freq keep --flash_size keep 0x1000 release/esp32solo1/bootloader.bin 0x10000 release/esp32solo1/nuki_hub.bin 0x8000 release/esp32solo1/nuki_hub.partitions.bin + echo "esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq keep --flash_size detect 0x1000 bootloader.bin 0x10000 nuki_hub.bin 0x8000 nuki_hub.partitions.bin" > release/esp32solo1/flash.sh + - name: Upload Artifact esp32dev + uses: actions/upload-artifact@v4 + with: + name: esp32dev-assets + path: release/esp32dev + - name: Upload Artifact esp32-s3 + uses: actions/upload-artifact@v4 + with: + name: esp32-s3-assets + path: release/esp32-s3 + - name: Upload Artifact esp32-c3 + uses: actions/upload-artifact@v4 + with: + name: esp32-c3-assets + path: release/esp32-c3 + - name: Upload Artifact esp32solo1 + uses: actions/upload-artifact@v4 + with: + name: esp32solo1-assets + path: release/esp32solo1 \ No newline at end of file diff --git a/MqttTopics.h b/MqttTopics.h index e6c8496..6178a6c 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -58,6 +58,10 @@ #define mqtt_topic_keypad_json_action "/keypad/actionJson" #define mqtt_topic_keypad_json_command_result "/keypad/commandResultJson" +#define mqtt_topic_timecontrol_json "/timecontrol/json" +#define mqtt_topic_timecontrol_action "/timecontrol/action" +#define mqtt_topic_timecontrol_command_result "/timecontrol/commandResult" + #define mqtt_topic_info_hardware_version "/info/hardwareVersion" #define mqtt_topic_info_firmware_version "/info/firmwareVersion" #define mqtt_topic_info_nuki_hub_version "/info/nukiHubVersion" diff --git a/NetworkLock.cpp b/NetworkLock.cpp index 87bc210..a852ea6 100644 --- a/NetworkLock.cpp +++ b/NetworkLock.cpp @@ -75,6 +75,12 @@ void NetworkLock::initialize() _network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--"); } + if(_preferences->getBool(preference_timecontrol_control_enabled)) + { + _network->subscribe(_mqttPath, mqtt_topic_timecontrol_action); + _network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--"); + } + _network->addReconnectedCallback([&]() { _reconnected = true; @@ -210,6 +216,18 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns publishString(mqtt_topic_keypad_json_action, "--"); } + + if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action)) + { + if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + + if(_timeControlCommandReceivedReceivedCallback != NULL) + { + _timeControlCommandReceivedReceivedCallback(value); + } + + publishString(mqtt_topic_timecontrol_action, "--"); + } } void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState) @@ -692,6 +710,78 @@ void NetworkLock::publishKeypad(const std::list& entries, } } +void NetworkLock::publishTimeControl(const std::list& timeControlEntries) +{ + char str[50]; + JsonDocument json; + + for(const auto& entry : timeControlEntries) + { + auto jsonEntry = json.add(); + + jsonEntry["entryId"] = entry.entryId; + jsonEntry["enabled"] = entry.enabled; + uint8_t weekdaysInt = entry.weekdays; + JsonArray weekdays = jsonEntry["weekdays"].to(); + + while(weekdaysInt > 0) { + if(weekdaysInt >= 64) + { + weekdays.add("mon"); + weekdaysInt -= 64; + continue; + } + if(weekdaysInt >= 32) + { + weekdays.add("tue"); + weekdaysInt -= 32; + continue; + } + if(weekdaysInt >= 16) + { + weekdays.add("wed"); + weekdaysInt -= 16; + continue; + } + if(weekdaysInt >= 8) + { + weekdays.add("thu"); + weekdaysInt -= 8; + continue; + } + if(weekdaysInt >= 4) + { + weekdays.add("fri"); + weekdaysInt -= 4; + continue; + } + if(weekdaysInt >= 2) + { + weekdays.add("sat"); + weekdaysInt -= 2; + continue; + } + if(weekdaysInt >= 1) + { + weekdays.add("sun"); + weekdaysInt -= 1; + continue; + } + } + + char timeT[5]; + sprintf(timeT, "%02d:%02d", entry.timeHour, entry.timeMin); + jsonEntry["time"] = timeT; + + memset(str, 0, sizeof(str)); + NukiLock::lockactionToString(entry.lockAction, str); + jsonEntry["lockAction"] = str; + } + + serializeJson(json, _buffer, _bufferSize); + publishString(mqtt_topic_timecontrol_json, _buffer); +} + void NetworkLock::publishConfigCommandResult(const char* result) { publishString(mqtt_topic_config_action_command_result, result); @@ -707,6 +797,11 @@ void NetworkLock::publishKeypadJsonCommandResult(const char* result) publishString(mqtt_topic_keypad_json_command_result, result); } +void NetworkLock::publishTimeControlCommandResult(const char* result) +{ + publishString(mqtt_topic_timecontrol_command_result, result); +} + void NetworkLock::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *)) { _lockActionReceivedCallback = lockActionReceivedCallback; @@ -727,6 +822,11 @@ void NetworkLock::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandR _keypadJsonCommandReceivedReceivedCallback = keypadJsonCommandReceivedReceivedCallback; } +void NetworkLock::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *)) +{ + _timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback; +} + void NetworkLock::buildMqttPath(const char* path, char* outPath) { int offset = 0; diff --git a/NetworkLock.h b/NetworkLock.h index 510852b..ffd87bd 100644 --- a/NetworkLock.h +++ b/NetworkLock.h @@ -37,15 +37,17 @@ public: void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction); void removeHASSConfig(char* uidString); void publishKeypad(const std::list& entries, uint maxKeypadCodeCount); + void publishTimeControl(const std::list& timeControlEntries); void publishConfigCommandResult(const char* result); void publishKeypadCommandResult(const char* result); void publishKeypadJsonCommandResult(const char* result); + void publishTimeControlCommandResult(const char* result); void setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char* value)); void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* value)); void setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled)); void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value)); - + void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value)); void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override; bool reconnected(); @@ -99,4 +101,5 @@ private: void (*_configUpdateReceivedCallback)(const char* value) = nullptr; void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr; void (*_keypadJsonCommandReceivedReceivedCallback)(const char* value) = nullptr; -}; + void (*_timeControlCommandReceivedReceivedCallback)(const char* value) = nullptr; +}; \ No newline at end of file diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index d95c97c..86fe33c 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -66,6 +66,12 @@ void NetworkOpener::initialize() _network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--"); } + if(_preferences->getBool(preference_timecontrol_control_enabled)) + { + _network->subscribe(_mqttPath, mqtt_topic_timecontrol_action); + _network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--"); + } + _network->addReconnectedCallback([&]() { _reconnected = true; @@ -202,6 +208,18 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u publishString(mqtt_topic_keypad_json_action, "--"); } + + if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action)) + { + if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + + if(_timeControlCommandReceivedReceivedCallback != NULL) + { + _timeControlCommandReceivedReceivedCallback(value); + } + + publishString(mqtt_topic_timecontrol_action, "--"); + } } void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState) @@ -375,24 +393,24 @@ void NetworkOpener::publishAuthorizationInfo(const std::list& entrie } } +void NetworkOpener::publishTimeControl(const std::list& timeControlEntries) +{ + char str[50]; + JsonDocument json; + + for(const auto& entry : timeControlEntries) + { + auto jsonEntry = json.add(); + + jsonEntry["entryId"] = entry.entryId; + jsonEntry["enabled"] = entry.enabled; + uint8_t weekdaysInt = entry.weekdays; + JsonArray weekdays = jsonEntry["weekdays"].to(); + + while(weekdaysInt > 0) { + if(weekdaysInt >= 64) + { + weekdays.add("mon"); + weekdaysInt -= 64; + continue; + } + if(weekdaysInt >= 32) + { + weekdays.add("tue"); + weekdaysInt -= 32; + continue; + } + if(weekdaysInt >= 16) + { + weekdays.add("wed"); + weekdaysInt -= 16; + continue; + } + if(weekdaysInt >= 8) + { + weekdays.add("thu"); + weekdaysInt -= 8; + continue; + } + if(weekdaysInt >= 4) + { + weekdays.add("fri"); + weekdaysInt -= 4; + continue; + } + if(weekdaysInt >= 2) + { + weekdays.add("sat"); + weekdaysInt -= 2; + continue; + } + if(weekdaysInt >= 1) + { + weekdays.add("sun"); + weekdaysInt -= 1; + continue; + } + } + + char timeT[5]; + sprintf(timeT, "%02d:%02d", entry.timeHour, entry.timeMin); + jsonEntry["time"] = timeT; + + memset(str, 0, sizeof(str)); + NukiOpener::lockactionToString(entry.lockAction, str); + jsonEntry["lockAction"] = str; + } + + serializeJson(json, _buffer, _bufferSize); + publishString(mqtt_topic_timecontrol_json, _buffer); +} + void NetworkOpener::publishConfigCommandResult(const char* result) { publishString(mqtt_topic_config_action_command_result, result); @@ -766,6 +856,11 @@ void NetworkOpener::publishKeypadJsonCommandResult(const char* result) publishString(mqtt_topic_keypad_json_command_result, result); } +void NetworkOpener::publishTimeControlCommandResult(const char* result) +{ + publishString(mqtt_topic_timecontrol_command_result, result); +} + void NetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *)) { _lockActionReceivedCallback = lockActionReceivedCallback; @@ -786,6 +881,11 @@ void NetworkOpener::setKeypadJsonCommandReceivedCallback(void (*keypadJsonComman _keypadJsonCommandReceivedReceivedCallback = keypadJsonCommandReceivedReceivedCallback; } +void NetworkOpener::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *)) +{ + _timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback; +} + void NetworkOpener::publishFloat(const char *topic, const float value, const uint8_t precision) { _network->publishFloat(_mqttPath, topic, value, precision); diff --git a/NetworkOpener.h b/NetworkOpener.h index 477fa06..915cdf6 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -34,15 +34,17 @@ public: void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction); void removeHASSConfig(char* uidString); void publishKeypad(const std::list& entries, uint maxKeypadCodeCount); + void publishTimeControl(const std::list& timeControlEntries); void publishConfigCommandResult(const char* result); void publishKeypadCommandResult(const char* result); void publishKeypadJsonCommandResult(const char* result); + void publishTimeControlCommandResult(const char* result); void setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char* value)); void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* value)); void setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled)); void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value)); - + void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value)); void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override; bool reconnected(); @@ -104,4 +106,5 @@ private: void (*_configUpdateReceivedCallback)(const char* value) = nullptr; void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr; void (*_keypadJsonCommandReceivedReceivedCallback)(const char* value) = nullptr; + void (*_timeControlCommandReceivedReceivedCallback)(const char* value) = nullptr; }; diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index aa8eae1..ce3bb30 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -172,6 +172,11 @@ void NukiOpenerWrapper::update() setupHASS(); } } + if(_nextTimeControlUpdateTs != 0 && ts > _nextTimeControlUpdateTs) + { + _nextTimeControlUpdateTs = 0; + updateTimeControl(true); + } if(_hassEnabled && _configRead && _network->reconnected()) { setupHASS(); @@ -406,7 +411,9 @@ void NukiOpenerWrapper::updateConfig() _hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]); _network->publishConfig(_nukiConfig); _retryConfigCount = 0; - + + if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false); + const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4); if(isPinSet()) { @@ -501,6 +508,9 @@ void NukiOpenerWrapper::updateKeypad() { std::list entries; _nukiOpener.getKeypadEntries(&entries); + + Log->print(F("Opener keypad codes: ")); + Log->println(entries.size()); entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; }); @@ -524,6 +534,43 @@ void NukiOpenerWrapper::updateKeypad() postponeBleWatchdog(); } +void NukiOpenerWrapper::updateTimeControl(bool retrieved) +{ + if(!_preferences->getBool(preference_timecontrol_info_enabled)) return; + + if(!retrieved) + { + Log->print(F("Querying opener time control: ")); + Nuki::CmdResult result = _nukiOpener.retrieveTimeControlEntries(); + printCommandResult(result); + if(result == Nuki::CmdResult::Success) + { + _nextTimeControlUpdateTs = millis() + 5000; + } + } + else + { + std::list timeControlEntries; + _nukiOpener.getTimeControlEntries(&timeControlEntries); + + Log->print(F("Opener time control entries: ")); + Log->println(timeControlEntries.size()); + + timeControlEntries.sort([](const NukiOpener::TimeControlEntry& a, const NukiOpener::TimeControlEntry& b) { return a.entryId < b.entryId; }); + + _network->publishTimeControl(timeControlEntries); + + _timeControlIds.clear(); + _timeControlIds.reserve(timeControlEntries.size()); + for(const auto& entry : timeControlEntries) + { + _timeControlIds.push_back(entry.entryId); + } + } + + postponeBleWatchdog(); +} + void NukiOpenerWrapper::postponeBleWatchdog() { _disableBleWatchdogTs = millis() + 15000; @@ -531,24 +578,31 @@ void NukiOpenerWrapper::postponeBleWatchdog() NukiOpener::LockAction NukiOpenerWrapper::lockActionToEnum(const char *str) { - if(strcmp(str, "activateRTO") == 0) return NukiOpener::LockAction::ActivateRTO; - else if(strcmp(str, "deactivateRTO") == 0) return NukiOpener::LockAction::DeactivateRTO; - else if(strcmp(str, "electricStrikeActuation") == 0) return NukiOpener::LockAction::ElectricStrikeActuation; - else if(strcmp(str, "activateCM") == 0) return NukiOpener::LockAction::ActivateCM; - else if(strcmp(str, "deactivateCM") == 0) return NukiOpener::LockAction::DeactivateCM; - else if(strcmp(str, "fobAction2") == 0) return NukiOpener::LockAction::FobAction2; - else if(strcmp(str, "fobAction1") == 0) return NukiOpener::LockAction::FobAction1; - else if(strcmp(str, "fobAction3") == 0) return NukiOpener::LockAction::FobAction3; + if(strcmp(str, "activateRTO") == 0 || strcmp(str, "ActivateRTO") == 0) return NukiOpener::LockAction::ActivateRTO; + else if(strcmp(str, "deactivateRTO") == 0 || strcmp(str, "DeactivateRTO") == 0) return NukiOpener::LockAction::DeactivateRTO; + else if(strcmp(str, "electricStrikeActuation") == 0 || strcmp(str, "ElectricStrikeActuation") == 0) return NukiOpener::LockAction::ElectricStrikeActuation; + else if(strcmp(str, "activateCM") == 0 || strcmp(str, "ActivateCM") == 0) return NukiOpener::LockAction::ActivateCM; + else if(strcmp(str, "deactivateCM") == 0 || strcmp(str, "DeactivateCM") == 0) return NukiOpener::LockAction::DeactivateCM; + else if(strcmp(str, "fobAction2") == 0 || strcmp(str, "FobAction2") == 0) return NukiOpener::LockAction::FobAction2; + else if(strcmp(str, "fobAction1") == 0 || strcmp(str, "FobAction1") == 0) return NukiOpener::LockAction::FobAction1; + else if(strcmp(str, "fobAction3") == 0 || strcmp(str, "FobAction3") == 0) return NukiOpener::LockAction::FobAction3; return (NukiOpener::LockAction)0xff; } LockActionResult NukiOpenerWrapper::onLockActionReceivedCallback(const char *value) { - NukiOpener::LockAction action = nukiOpenerInst->lockActionToEnum(value); - if((int)action == 0xff) + NukiOpener::LockAction action; + + if(strlen(value) > 0) { - return LockActionResult::UnknownAction; + action = nukiOpenerInst->lockActionToEnum(value); + + if((int)action == 0xff) + { + return LockActionResult::UnknownAction; + } } + else return LockActionResult::UnknownAction; nukiOpenerPreferences = new Preferences(); nukiOpenerPreferences->begin("nukihub", true); @@ -1672,6 +1726,181 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) } } +void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value) +{ + if(_nukiOpener.getSecurityPincode() == 0) + { + _network->publishTimeControlCommandResult("noPinSet"); + return; + } + + if(!_preferences->getBool(preference_timecontrol_control_enabled)) + { + _network->publishTimeControlCommandResult("timeControlControlDisabled"); + return; + } + + JsonDocument json; + DeserializationError jsonError = deserializeJson(json, value); + + if(jsonError) + { + _network->publishTimeControlCommandResult("invalidJson"); + return; + } + + Nuki::CmdResult result = (Nuki::CmdResult)-1; + + const char *action = json["action"].as(); + uint8_t entryId = json["entryId"].as(); + uint8_t enabled = json["enabled"].as(); + String weekdays = json["weekdays"].as(); + const char *time = json["time"].as(); + const char *lockAct = json["lockAction"].as(); + NukiOpener::LockAction timeControlLockAction; + + if(strlen(lockAct) > 0) + { + + timeControlLockAction = nukiOpenerInst->lockActionToEnum(lockAct); + + if((int)timeControlLockAction == 0xff) + { + _network->publishTimeControlCommandResult("invalidLockAction"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidLockAction"); + return; + } + + if(action) + { + bool idExists = false; + + if(entryId) + { + idExists = std::find(_timeControlIds.begin(), _timeControlIds.end(), entryId) != _timeControlIds.end(); + } + + if(strcmp(action, "delete") == 0) { + if(idExists) + { + result = _nukiOpener.removeTimeControlEntry(entryId); + Log->print("Delete time control "); + Log->println((int)result); + } + else + { + _network->publishTimeControlCommandResult("noExistingEntryIdSet"); + return; + } + } + else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0) + { + uint8_t timeHour; + uint8_t timeMin; + uint8_t weekdaysInt = 0; + unsigned int timeAr[2]; + + if(time) + { + if(strlen(time) == 5) + { + String timeStr = time; + timeAr[0] = (uint8_t)timeStr.substring(0, 2).toInt(); + timeAr[1] = (uint8_t)timeStr.substring(3, 5).toInt(); + + if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59) + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + + if(weekdays.indexOf("mon") >= 0) weekdaysInt += 64; + if(weekdays.indexOf("tue") >= 0) weekdaysInt += 32; + if(weekdays.indexOf("wed") >= 0) weekdaysInt += 16; + if(weekdays.indexOf("thu") >= 0) weekdaysInt += 8; + if(weekdays.indexOf("fri") >= 0) weekdaysInt += 4; + if(weekdays.indexOf("sat") >= 0) weekdaysInt += 2; + if(weekdays.indexOf("sun") >= 0) weekdaysInt += 1; + + if(strcmp(action, "add") == 0) + { + NukiOpener::NewTimeControlEntry entry; + memset(&entry, 0, sizeof(entry)); + entry.weekdays = weekdaysInt; + + if(time) + { + entry.timeHour = timeAr[0]; + entry.timeMin = timeAr[1]; + } + + entry.lockAction = timeControlLockAction; + + result = _nukiOpener.addTimeControlEntry(entry); + Log->print("Add time control: "); + Log->println((int)result); + } + else if (strcmp(action, "update") == 0) + { + NukiOpener::TimeControlEntry entry; + memset(&entry, 0, sizeof(entry)); + entry.entryId = entryId; + entry.enabled = enabled == 0 ? 0 : 1; + entry.weekdays = weekdaysInt; + + if(time) + { + entry.timeHour = timeAr[0]; + entry.timeMin = timeAr[1]; + } + + entry.lockAction = timeControlLockAction; + + result = _nukiOpener.updateTimeControlEntry(entry); + Log->print("Update time control: "); + Log->println((int)result); + } + } + else + { + _network->publishTimeControlCommandResult("invalidAction"); + return; + } + + if((int)result != -1) + { + char resultStr[15]; + memset(&resultStr, 0, sizeof(resultStr)); + NukiOpener::cmdResultToString(result, resultStr); + _network->publishTimeControlCommandResult(resultStr); + } + + _nextConfigUpdateTs = millis() + 300; + } + else + { + _network->publishTimeControlCommandResult("noActionSet"); + return; + } +} + const NukiOpener::OpenerState &NukiOpenerWrapper::keyTurnerState() { return _keyTurnerState; diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index 3e04d36..6414396 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -50,16 +50,19 @@ private: static void onConfigUpdateReceivedCallback(const char* value); static void onKeypadCommandReceivedCallback(const char* command, const uint& id, const String& name, const String& code, const int& enabled); static void onKeypadJsonCommandReceivedCallback(const char* value); + static void onTimeControlCommandReceivedCallback(const char* value); static void gpioActionCallback(const GpioAction& action, const int& pin); void onKeypadCommandReceived(const char* command, const uint& id, const String& name, const String& code, const int& enabled); void onConfigUpdateReceived(const char* value); void onKeypadJsonCommandReceived(const char* value); + void onTimeControlCommandReceived(const char* value); void updateKeyTurnerState(); void updateBatteryState(); void updateConfig(); void updateAuthData(); void updateKeypad(); + void updateTimeControl(bool retrieved); void postponeBleWatchdog(); void updateGpioOutputs(); @@ -102,6 +105,7 @@ private: int _retryLockstateCount = 0; unsigned long _nextRetryTs = 0; std::vector _keypadCodeIds; + std::vector _timeControlIds; NukiOpener::OpenerState _lastKeyTurnerState; NukiOpener::OpenerState _keyTurnerState; @@ -126,6 +130,7 @@ private: unsigned long _nextLockStateUpdateTs = 0; unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; + unsigned long _nextTimeControlUpdateTs = 0; unsigned long _nextKeypadUpdateTs = 0; unsigned long _nextPairTs = 0; long _nextRssiTs = 0; diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 83be572..f88818d 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -33,6 +33,7 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback); network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback); network->setKeypadJsonCommandReceivedCallback(nukiInst->onKeypadJsonCommandReceivedCallback); + network->setTimeControlCommandReceivedCallback(nukiInst->onTimeControlCommandReceivedCallback); _gpio->addCallback(NukiWrapper::gpioActionCallback); } @@ -190,6 +191,11 @@ void NukiWrapper::update() setupHASS(); } } + if(_nextTimeControlUpdateTs != 0 && ts > _nextTimeControlUpdateTs) + { + _nextTimeControlUpdateTs = 0; + updateTimeControl(true); + } if(_hassEnabled && _configRead && _network->reconnected()) { setupHASS(); @@ -386,7 +392,9 @@ void NukiWrapper::updateConfig() _hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]); _network->publishConfig(_nukiConfig); _retryConfigCount = 0; - + + if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false); + const int pinStatus = _preferences->getInt(preference_lock_pin_status, 4); if(isPinSet()) { @@ -481,6 +489,9 @@ void NukiWrapper::updateKeypad() { std::list entries; _nukiLock.getKeypadEntries(&entries); + + Log->print(F("Lock keypad codes: ")); + Log->println(entries.size()); entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; }); @@ -504,6 +515,43 @@ void NukiWrapper::updateKeypad() postponeBleWatchdog(); } +void NukiWrapper::updateTimeControl(bool retrieved) +{ + if(!_preferences->getBool(preference_timecontrol_info_enabled)) return; + + if(!retrieved) + { + Log->print(F("Querying lock time control: ")); + Nuki::CmdResult result = _nukiLock.retrieveTimeControlEntries(); + printCommandResult(result); + if(result == Nuki::CmdResult::Success) + { + _nextTimeControlUpdateTs = millis() + 5000; + } + } + else + { + std::list timeControlEntries; + _nukiLock.getTimeControlEntries(&timeControlEntries); + + Log->print(F("Lock time control entries: ")); + Log->println(timeControlEntries.size()); + + timeControlEntries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; }); + + _network->publishTimeControl(timeControlEntries); + + _timeControlIds.clear(); + _timeControlIds.reserve(timeControlEntries.size()); + for(const auto& entry : timeControlEntries) + { + _timeControlIds.push_back(entry.entryId); + } + } + + postponeBleWatchdog(); +} + void NukiWrapper::postponeBleWatchdog() { _disableBleWatchdogTs = millis() + 15000; @@ -511,26 +559,32 @@ void NukiWrapper::postponeBleWatchdog() NukiLock::LockAction NukiWrapper::lockActionToEnum(const char *str) { - if(strcmp(str, "unlock") == 0) return NukiLock::LockAction::Unlock; - else if(strcmp(str, "lock") == 0) return NukiLock::LockAction::Lock; - else if(strcmp(str, "unlatch") == 0) return NukiLock::LockAction::Unlatch; - else if(strcmp(str, "lockNgo") == 0) return NukiLock::LockAction::LockNgo; - else if(strcmp(str, "lockNgoUnlatch") == 0) return NukiLock::LockAction::LockNgoUnlatch; - else if(strcmp(str, "fullLock") == 0) return NukiLock::LockAction::FullLock; - else if(strcmp(str, "fobAction2") == 0) return NukiLock::LockAction::FobAction2; - else if(strcmp(str, "fobAction1") == 0) return NukiLock::LockAction::FobAction1; - else if(strcmp(str, "fobAction3") == 0) return NukiLock::LockAction::FobAction3; + if(strcmp(str, "unlock") == 0 || strcmp(str, "Unlock") == 0) return NukiLock::LockAction::Unlock; + else if(strcmp(str, "lock") == 0 || strcmp(str, "Lock") == 0) return NukiLock::LockAction::Lock; + else if(strcmp(str, "unlatch") == 0 || strcmp(str, "Unlatch") == 0) return NukiLock::LockAction::Unlatch; + else if(strcmp(str, "lockNgo") == 0 || strcmp(str, "LockNgo") == 0) return NukiLock::LockAction::LockNgo; + else if(strcmp(str, "lockNgoUnlatch") == 0 || strcmp(str, "LockNgoUnlatch") == 0) return NukiLock::LockAction::LockNgoUnlatch; + else if(strcmp(str, "fullLock") == 0 || strcmp(str, "FullLock") == 0) return NukiLock::LockAction::FullLock; + else if(strcmp(str, "fobAction2") == 0 || strcmp(str, "FobAction2") == 0) return NukiLock::LockAction::FobAction2; + else if(strcmp(str, "fobAction1") == 0 || strcmp(str, "FobAction1") == 0) return NukiLock::LockAction::FobAction1; + else if(strcmp(str, "fobAction3") == 0 || strcmp(str, "FobAction3") == 0) return NukiLock::LockAction::FobAction3; return (NukiLock::LockAction)0xff; } LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value) { - NukiLock::LockAction action = nukiInst->lockActionToEnum(value); - - if((int)action == 0xff) + NukiLock::LockAction action; + + if(strlen(value) > 0) { - return LockActionResult::UnknownAction; + action = nukiInst->lockActionToEnum(value); + + if((int)action == 0xff) + { + return LockActionResult::UnknownAction; + } } + else return LockActionResult::UnknownAction; nukiLockPreferences = new Preferences(); nukiLockPreferences->begin("nukihub", true); @@ -1185,6 +1239,11 @@ void NukiWrapper::onKeypadJsonCommandReceivedCallback(const char *value) nukiInst->onKeypadJsonCommandReceived(value); } +void NukiWrapper::onTimeControlCommandReceivedCallback(const char *value) +{ + nukiInst->onTimeControlCommandReceived(value); +} + void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin) { switch(action) @@ -1654,6 +1713,181 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) } } +void NukiWrapper::onTimeControlCommandReceived(const char *value) +{ + if(_nukiLock.getSecurityPincode() == 0) + { + _network->publishTimeControlCommandResult("noPinSet"); + return; + } + + if(!_preferences->getBool(preference_timecontrol_control_enabled)) + { + _network->publishTimeControlCommandResult("timeControlControlDisabled"); + return; + } + + JsonDocument json; + DeserializationError jsonError = deserializeJson(json, value); + + if(jsonError) + { + _network->publishTimeControlCommandResult("invalidJson"); + return; + } + + Nuki::CmdResult result = (Nuki::CmdResult)-1; + + const char *action = json["action"].as(); + uint8_t entryId = json["entryId"].as(); + uint8_t enabled = json["enabled"].as(); + String weekdays = json["weekdays"].as(); + const char *time = json["time"].as(); + const char *lockAct = json["lockAction"].as(); + NukiLock::LockAction timeControlLockAction; + + if(strlen(lockAct) > 0) + { + + timeControlLockAction = nukiInst->lockActionToEnum(lockAct); + + if((int)timeControlLockAction == 0xff) + { + _network->publishTimeControlCommandResult("invalidLockAction"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidLockAction"); + return; + } + + if(action) + { + bool idExists = false; + + if(entryId) + { + idExists = std::find(_timeControlIds.begin(), _timeControlIds.end(), entryId) != _timeControlIds.end(); + } + + if(strcmp(action, "delete") == 0) { + if(idExists) + { + result = _nukiLock.removeTimeControlEntry(entryId); + Log->print("Delete time control "); + Log->println((int)result); + } + else + { + _network->publishTimeControlCommandResult("noExistingEntryIdSet"); + return; + } + } + else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0) + { + uint8_t timeHour; + uint8_t timeMin; + uint8_t weekdaysInt = 0; + unsigned int timeAr[2]; + + if(time) + { + if(strlen(time) == 5) + { + String timeStr = time; + timeAr[0] = (uint8_t)timeStr.substring(0, 2).toInt(); + timeAr[1] = (uint8_t)timeStr.substring(3, 5).toInt(); + + if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59) + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + } + else + { + _network->publishTimeControlCommandResult("invalidTime"); + return; + } + + if(weekdays.indexOf("mon") >= 0) weekdaysInt += 64; + if(weekdays.indexOf("tue") >= 0) weekdaysInt += 32; + if(weekdays.indexOf("wed") >= 0) weekdaysInt += 16; + if(weekdays.indexOf("thu") >= 0) weekdaysInt += 8; + if(weekdays.indexOf("fri") >= 0) weekdaysInt += 4; + if(weekdays.indexOf("sat") >= 0) weekdaysInt += 2; + if(weekdays.indexOf("sun") >= 0) weekdaysInt += 1; + + if(strcmp(action, "add") == 0) + { + NukiLock::NewTimeControlEntry entry; + memset(&entry, 0, sizeof(entry)); + entry.weekdays = weekdaysInt; + + if(time) + { + entry.timeHour = timeAr[0]; + entry.timeMin = timeAr[1]; + } + + entry.lockAction = timeControlLockAction; + + result = _nukiLock.addTimeControlEntry(entry); + Log->print("Add time control: "); + Log->println((int)result); + } + else if (strcmp(action, "update") == 0) + { + NukiLock::TimeControlEntry entry; + memset(&entry, 0, sizeof(entry)); + entry.entryId = entryId; + entry.enabled = enabled == 0 ? 0 : 1; + entry.weekdays = weekdaysInt; + + if(time) + { + entry.timeHour = timeAr[0]; + entry.timeMin = timeAr[1]; + } + + entry.lockAction = timeControlLockAction; + + result = _nukiLock.updateTimeControlEntry(entry); + Log->print("Update time control: "); + Log->println((int)result); + } + } + else + { + _network->publishTimeControlCommandResult("invalidAction"); + return; + } + + if((int)result != -1) + { + char resultStr[15]; + memset(&resultStr, 0, sizeof(resultStr)); + NukiLock::cmdResultToString(result, resultStr); + _network->publishTimeControlCommandResult(resultStr); + } + + _nextConfigUpdateTs = millis() + 300; + } + else + { + _network->publishTimeControlCommandResult("noActionSet"); + return; + } +} + const NukiLock::KeyTurnerState &NukiWrapper::keyTurnerState() { return _keyTurnerState; diff --git a/NukiWrapper.h b/NukiWrapper.h index a901ced..f5d0291 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -48,16 +48,19 @@ private: static void onConfigUpdateReceivedCallback(const char* value); static void onKeypadCommandReceivedCallback(const char* command, const uint& id, const String& name, const String& code, const int& enabled); static void onKeypadJsonCommandReceivedCallback(const char* value); + static void onTimeControlCommandReceivedCallback(const char* value); static void gpioActionCallback(const GpioAction& action, const int& pin); void onKeypadCommandReceived(const char* command, const uint& id, const String& name, const String& code, const int& enabled); void onConfigUpdateReceived(const char* value); void onKeypadJsonCommandReceived(const char* value); + void onTimeControlCommandReceived(const char* value); void updateKeyTurnerState(); void updateBatteryState(); void updateConfig(); void updateAuthData(); void updateKeypad(); + void updateTimeControl(bool retrieved); void postponeBleWatchdog(); void updateGpioOutputs(); @@ -91,6 +94,7 @@ private: bool _publishAuthData = false; bool _clearAuthData = false; std::vector _keypadCodeIds; + std::vector _timeControlIds; NukiLock::KeyTurnerState _lastKeyTurnerState; NukiLock::KeyTurnerState _keyTurnerState; @@ -121,6 +125,7 @@ private: unsigned long _nextLockStateUpdateTs = 0; unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; + unsigned long _nextTimeControlUpdateTs = 0; unsigned long _nextKeypadUpdateTs = 0; unsigned long _nextRssiTs = 0; unsigned long _lastRssi = 0; diff --git a/PreferencesKeys.h b/PreferencesKeys.h index 537f4a1..94d458c 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -49,6 +49,8 @@ #define preference_access_level "accLvl" #define preference_keypad_info_enabled "kpInfoEnabled" #define preference_keypad_control_enabled "kpCntrlEnabled" +#define preference_timecontrol_control_enabled "tcCntrlEnabled" +#define preference_timecontrol_info_enabled "tcInfoEnabled" #define preference_publish_authdata "pubAuth" #define preference_acl "aclLckOpn" #define preference_conf_lock_basic_acl "confLckBasAcl" @@ -82,9 +84,10 @@ private: preference_ip_dhcp_enabled, preference_ip_address, preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname, preference_network_timeout, preference_restart_on_disconnect, - preference_restart_ble_beacon_lost, preference_query_interval_lockstate, + preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_acl, + preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_conf_lock_basic_acl, preference_conf_lock_advanced_acl, preference_conf_opener_basic_acl, preference_conf_opener_advanced_acl, preference_access_level, preference_register_as_app, preference_command_nr_of_retries, preference_command_retry_delay, preference_cred_user, preference_cred_password, preference_publish_authdata, @@ -102,7 +105,7 @@ private: { preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode, preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, - preference_register_as_app, preference_ip_dhcp_enabled, + preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_ip_dhcp_enabled, preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled }; @@ -135,56 +138,56 @@ private: { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getChar(key)) : String(preferences->getChar(key))); + s.concat(isRedacted(key) ? redact((const int32_t)preferences->getChar(key)) : String(preferences->getChar(key))); s.concat("\n"); } const void appendPreferenceUInt8(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getUChar(key)) : String(preferences->getUChar(key))); + s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUChar(key)) : String(preferences->getUChar(key))); s.concat("\n"); } const void appendPreferenceInt16(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getShort(key)) : String(preferences->getShort(key))); + s.concat(isRedacted(key) ? redact((const int32_t)preferences->getShort(key)) : String(preferences->getShort(key))); s.concat("\n"); } const void appendPreferenceUInt16(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getUShort(key)) : String(preferences->getUShort(key))); + s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUShort(key)) : String(preferences->getUShort(key))); s.concat("\n"); } const void appendPreferenceInt32(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getInt(key)) : String(preferences->getInt(key))); + s.concat(isRedacted(key) ? redact((const int32_t)preferences->getInt(key)) : String(preferences->getInt(key))); s.concat("\n"); } const void appendPreferenceUInt32(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getUInt(key)) : String(preferences->getUInt(key))); + s.concat(isRedacted(key) ? redact((const uint32_t)preferences->getUInt(key)) : String(preferences->getUInt(key))); s.concat("\n"); } const void appendPreferenceInt64(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getLong64(key)) : String(preferences->getLong64(key))); + s.concat(isRedacted(key) ? redact((const int64_t)preferences->getLong64(key)) : String(preferences->getLong64(key))); s.concat("\n"); } const void appendPreferenceUInt64(Preferences *preferences, String& s, const char* description, const char* key) { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getULong64(key)) : String(preferences->getULong64(key))); + s.concat(isRedacted(key) ? redact((const uint64_t)preferences->getULong64(key)) : String(preferences->getULong64(key))); s.concat("\n"); } const void appendPreferenceBool(Preferences *preferences, String& s, const char* description, const char* key) @@ -198,7 +201,7 @@ private: { s.concat(description); s.concat(": "); - s.concat(isRedacted(key) ? redact(preferences->getString(key)) : preferences->getString(key)); + s.concat(isRedacted(key) ? redact((const String)preferences->getString(key)) : preferences->getString(key)); s.concat("\n"); } @@ -258,4 +261,4 @@ public: return s; } -}; +}; \ No newline at end of file diff --git a/README.md b/README.md index 5124bc3..37ec45f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Feel free to join us on Discord: https://discord.gg/feB9FnMY ## Supported devices Supported ESP32 devices: -- All dual-core ESP32 models with WIFI and BLE which are supported by Arduino Core 2.0.15 should work, but builds are currently only provided for the ESP32 and not for the ESP32-S3 or ESP32-C3. +- All dual-core ESP32 models with WIFI and BLE which are supported by Arduino Core 2.0.15 should work. Tested builds are provided for the ESP32 and ESP32-S3. +- Single-core ESP32 models with WIFI and BLE which are supported by Arduino Core 2.0.15 might work. Untested builds are provided for the ESP32-C3 and ESP32-Solo1. - The ESP32-S2 has no BLE and as such can't run Nuki Hub. - The ESP32-C6 and ESP32-H2 are not supported by Arduino Core 2.0.15 as such can't run Nuki Hub (at this time). @@ -46,8 +47,9 @@ Please go to "MQTT and Network Configuration" and select "Wi-Fi only" as the net Flash the firmware to an ESP32. The easiest way to install is to use the web installer using a compatible browser like Chrome/Opera/Edge:
https://technyon.github.io/nuki_hub/
+NOTE: Webflash is not available for the ESP32-Solo1

-Alternatively download the latest release from https://github.com/technyon/nuki_hub/releases
+Alternatively download the latest release for your ESP32 model from https://github.com/technyon/nuki_hub/releases
Unpack the 7z archive and read the included readme.txt for installation instructions for either "Espressif Flash Download Tools" or "esptool". ## Initial setup (Network and MQTT) @@ -150,6 +152,8 @@ In a browser navigate to the IP address assigned to the ESP32. #### Nuki General Access Control - Publish keypad codes information (Only available when a Keypad is detected): Enable to publish information about keypad codes through MQTT, see the "[Keypad control](#keypad-control-optional)" section of this README - Add, modify and delete keypad codes (Only available when a Keypad is detected): Enable to allow configuration of keypad codes through MQTT, see the "[Keypad control](#keypad-control-optional)" section of this README +- Publish time control information: Enable to publish information about time control entries through MQTT, see the "Time control" section of this README +- Add, modify and delete time control entries: Enable to allow configuration of time control entries through MQTT, see the "Time control" section of this README - Publish auth data: Enable to publish authorization data to the MQTT topic lock/log. Requires the Nuki security code / PIN to be set, see "Nuki Lock PIN / Nuki Opener PIN" below. #### Nuki Lock/Opener Access Control @@ -257,6 +261,10 @@ In a browser navigate to the IP address assigned to the ESP32. - See the "[Keypad control](#keypad-control-optional)" section of this README. +### Time Control + +- See the "Time control" section of this README. + ### Info - info/nukiHubVersion: Set to the current version number of the Nuki Hub firmware. @@ -489,6 +497,30 @@ For example, to add a code: - write 1 to enabled - write "add" to action +## Time control using JSON (optional) + +Time control entries can be added, updated and removed. This has to enabled first in the configuration portal. Check "Add, modify and delete time control entries" under "Access Level Configuration" and save the configuration. + +Information about current time control entries is published as JSON data to the "timecontrol/json" MQTT topic.
+This needs to be enabled separately by checking "Publish time control entries information" under "Access Level Configuration" and saving the configuration. + +To change Nuki Lock/Opener time control settings set the `timecontrol/actionJson` topic to a JSON formatted value containing the following nodes. + +| Node | Delete | Add | Update | Usage | Possible values | +|------------------|----------|----------|----------|------------------------------------------------------------------------------------------|----------------------------------------------------------------| +| action | Required | Required | Required | The action to execute | "delete", "add", "update" | +| entryId | Required | Not used | Required | The entry ID of the existing entry to delete or update | Integer | +| enabled | Not used | Not used | Optional | Enable or disable the entry, enabled if not set | 1 = enabled, 0 = disabled | +| weekdays | Not used | Optional | Optional | Weekdays on which the chosen lock action should be exectued | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" | +| time | Not used | Required | Required | The time on which the chosen lock action should be executed | "HH:MM" | +| lockAction | Not used | Required | Required | The lock action that should be executed on the chosen weekdays at the chosen time | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock". For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM" | + +Example usage:
+Examples: +- Delete: `{ "action": "delete", "entryId": "1234" }` +- Add: `{ "action": "add", "weekdays": [ "wed", "thu", "fri" ], "time": "08:00", "lockAction": "Unlock" }` +- Update: `{ "action": "update", "entryId": "1234", "enabled": "1", "weekdays": [ "mon", "tue", "sat", "sun" ], "time": "08:00", "lockAction": "Lock" }` + ## GPIO lock control (optional) The lock can be controlled via GPIO.
@@ -567,6 +599,7 @@ Reported as working are: - [M5Stack ATOM Lite](https://shop.m5stack.com/products/atom-lite-esp32-development-kit) - ESP32-WROOM-32D (DEVKIT V4) - ESP32-WROOM-32E +- ESP32-S3-WROOM-1 For more information check the related issue: https://github.com/technyon/nuki_hub/issues/39 diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index bc7d067..2362fb3 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -479,6 +479,16 @@ bool WebCfgServer::processArgs(String& message) _preferences->putBool(preference_keypad_control_enabled, (value == "1")); configChanged = true; } + else if(key == "TCPUB") + { + _preferences->putBool(preference_timecontrol_info_enabled, (value == "1")); + configChanged = true; + } + else if(key == "TCENA") + { + _preferences->putBool(preference_timecontrol_control_enabled, (value == "1")); + configChanged = true; + } else if(key == "PUBAUTH") { _preferences->putBool(preference_publish_authdata, (value == "1")); @@ -1268,7 +1278,9 @@ void WebCfgServer::buildAccLvlHtml(String &response) printCheckBox(response, "KPPUB", "Publish keypad codes information", _preferences->getBool(preference_keypad_info_enabled), ""); printCheckBox(response, "KPENA", "Add, modify and delete keypad codes", _preferences->getBool(preference_keypad_control_enabled), ""); } - printCheckBox(response, "PUBAUTH", "Publish authorisation log (may reduce battery life)", _preferences->getBool(preference_publish_authdata), ""); + printCheckBox(response, "TCPUB", "Publish time control entries information", _preferences->getBool(preference_timecontrol_info_enabled)); + printCheckBox(response, "TCENA", "Add, modify and delete time control entries", _preferences->getBool(preference_timecontrol_control_enabled)); + printCheckBox(response, "PUBAUTH", "Publish authorisation log (may reduce battery life)", _preferences->getBool(preference_publish_authdata)); response.concat("
"); if(_nuki != nullptr) { diff --git a/lib/Ethernet/docs/api.md b/lib/Ethernet/docs/api.md index 2354a59..76265c8 100644 --- a/lib/Ethernet/docs/api.md +++ b/lib/Ethernet/docs/api.md @@ -332,7 +332,7 @@ void setup() { Serial.begin(9600); // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { - Serial.println("Failure to configure Ethernet using DHCP"); + Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: for(;;) ; diff --git a/lib/Ethernet/library.properties b/lib/Ethernet/library.properties index ef8982a..046e6c2 100644 --- a/lib/Ethernet/library.properties +++ b/lib/Ethernet/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=2.0.0 +version=2.0.2 author=Various (see AUTHORS file for details) maintainer=Arduino sentence=Enables network connection (local and Internet) using the Arduino Ethernet Board or Shield. @@ -7,4 +7,4 @@ paragraph=With this library you can use the Arduino Ethernet (shield or board) t category=Communication url=https://www.arduino.cc/en/Reference/Ethernet architectures=* -includes=Ethernet.h +includes=Ethernet.h \ No newline at end of file diff --git a/lib/Ethernet/src/Dhcp.cpp b/lib/Ethernet/src/Dhcp.cpp index ec91019..28df310 100644 --- a/lib/Ethernet/src/Dhcp.cpp +++ b/lib/Ethernet/src/Dhcp.cpp @@ -32,6 +32,7 @@ void DhcpClass::reset_DHCP_lease() memset(_dhcpDhcpServerIp, 0, sizeof(_dhcpDhcpServerIp)); memset(_dhcpDnsServerIp, 0, sizeof(_dhcpDnsServerIp)); } + //return:0 on error, 1 if request is sent and response is received int DhcpClass::request_DHCP_lease() { @@ -433,4 +434,4 @@ void DhcpClass::printByte(char * buf, uint8_t n ) char c = m - 16 * n; *str-- = c < 10 ? c + '0' : c + 'A' - 10; } while(n); -} +} \ No newline at end of file diff --git a/lib/Ethernet/src/Ethernet.cpp b/lib/Ethernet/src/Ethernet.cpp index d502c13..8f6f76a 100644 --- a/lib/Ethernet/src/Ethernet.cpp +++ b/lib/Ethernet/src/Ethernet.cpp @@ -87,14 +87,10 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress g W5100.setIPAddress(&ip[0]); W5100.setGatewayIp(&gateway[0]); W5100.setSubnetMask(&subnet[0]); -#elif ARDUINO > 106 || TEENSYDUINO > 121 - W5100.setIPAddress(ip._address.bytes); - W5100.setGatewayIp(gateway._address.bytes); - W5100.setSubnetMask(subnet._address.bytes); #else - W5100.setIPAddress(ip._address); - W5100.setGatewayIp(gateway._address); - W5100.setSubnetMask(subnet._address); + W5100.setIPAddress(ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); #endif SPI.endTransaction(); _dnsServerAddress = dns; @@ -244,4 +240,4 @@ void EthernetClass::setRetransmissionCount(uint8_t num) -EthernetClass Ethernet; +EthernetClass Ethernet; \ No newline at end of file diff --git a/partitions.csv b/partitions.csv new file mode 100644 index 0000000..0181072 --- /dev/null +++ b/partitions.csv @@ -0,0 +1 @@ +# Espressif ESP32 Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, app0, app, ota_0, 0x10000, 0x1E0000, app1, app, ota_1, 0x1F0000, 0x1E0000 #spiffs, data, spiffs, 0x3D0000, 0x30000 spiffs, data, spiffs, 0x3D0000, 0x20000, coredump, data, coredump,0x3F0000, 0x10000, \ No newline at end of file diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..af66466 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,64 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = esp32dev +src_dir = . + +[env] +platform = espressif32 +framework = arduino +build_type = release +board_build.partitions = partitions.csv +build_flags = + -fexceptions + -DTLS_CA_MAX_SIZE=2200 + -DTLS_CERT_MAX_SIZE=1500 + -DTLS_KEY_MAX_SIZE=1800 + -DESP_PLATFORM + -DESP32 + -DARDUINO_ARCH_ESP32 + -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE + -DCONFIG_NIMBLE_CPP_LOG_LEVEL=0 +; -DDEBUG_SENSE_NUKI +; -DDEBUG_NUKI_COMMAND +; -DDEBUG_NUKI_CONNECT +; -DDEBUG_NUKI_COMMUNICATION +; -DDEBUG_NUKI_HEX_DATA +; -DDEBUG_NUKI_READABLE_DATA +lib_deps = + https://github.com/technyon/nuki_ble.git + bertmelis/espMqttClient@1.6.0 + bblanchon/ArduinoJson@7.0.4 +monitor_speed = 115200 +monitor_filters = + esp32_exception_decoder + time +build_src_filter = + -<*> + +<*.cpp> + +<*.h> + + + +[env:esp32dev] +board = esp32dev + +[env:esp32-c3] +board = esp32-c3-devkitc-02 + +[env:esp32solo1] +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32-2023.10.03.zip +board = esp32-solo1 +build_flags = + ${env.build_flags} + -DFRAMEWORK_ARDUINO_SOLO1 + +[env:esp32-s3] +board = esp32-s3-devkitc-1 \ No newline at end of file diff --git a/webflash/manifest.json b/webflash/manifest.json index b0ed619..d430d8b 100644 --- a/webflash/manifest.json +++ b/webflash/manifest.json @@ -10,6 +10,18 @@ { "path": "nuki_hub.bin", "offset": 65536 }, { "path": "nuki_hub.partitions.bin", "offset": 32768 } ] + }, + { + "chipFamily": "ESP32-S3", + "parts": [ + { "path": "nuki_hub_esp32s3.bin", "offset": 0 }, + ] + }, + { + "chipFamily": "ESP32-C3", + "parts": [ + { "path": "nuki_hub_esp32c3.bin", "offset": 0 }, + ] } ] } diff --git a/webflash/nuki_hub_esp32c3.bin b/webflash/nuki_hub_esp32c3.bin new file mode 100644 index 0000000..2f78a32 Binary files /dev/null and b/webflash/nuki_hub_esp32c3.bin differ diff --git a/webflash/nuki_hub_esp32s3.bin b/webflash/nuki_hub_esp32s3.bin new file mode 100644 index 0000000..a96f680 Binary files /dev/null and b/webflash/nuki_hub_esp32s3.bin differ