From 063fbab6b2e222bce6aa3bc433e059ae9a6f5277 Mon Sep 17 00:00:00 2001 From: iranl Date: Sun, 11 Aug 2024 11:20:51 +0200 Subject: [PATCH] OTA and Debug improvements (#445) * Use esp_crt_bundle for HTTPS requests * Remove Solo1 support * Improve Nuki device config read functions * Webserial * OTA Improvements * WebCfg fixes * Debug improvements --- .github/workflows/beta.yml | 22 +++- .github/workflows/build.yml | 5 +- .github/workflows/nightly.yml | 34 ++++-- .github/workflows/release.yml | 20 +++- pio_package.py | 9 +- src/Config.h | 24 ++++ src/NukiNetwork.cpp | 90 +++++++++++---- src/NukiNetworkLock.cpp | 24 +++- src/WebCfgServer.cpp | 185 ++++++++++++++++++++++-------- src/WebCfgServer.h | 10 +- src/networkDevices/WifiDevice.cpp | 2 +- 11 files changed, 317 insertions(+), 108 deletions(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 487c952..8547928 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -52,13 +52,12 @@ jobs: python3 resources/config_version.py beta - name: Build ${{ matrix.build }} PlatformIO Project ${{ matrix.board }} run: | + ORIGBOARD="${BOARD}" if [ "$BUILD" = "debug" ]; then BOARD="${BOARD}_dbg" fi echo "::group::Building with PlatformIO" - if [ "$BUILD" = "release" ]; then - make updater_${BOARD} - fi + make updater_${ORIGBOARD} make $BOARD echo "::endgroup::" - name: Add flash script @@ -118,24 +117,39 @@ jobs: with: path: release pattern: '*-release-assets' + - name: Download debug assets + uses: actions/download-artifact@v4 + with: + path: debug + pattern: '*-debug-assets' - name: Copy binaries to ota/beta env: Version: ${{ github.run_id }}.${{ github.run_number }}.${{ github.run_attempt }} run: | mkdir -p ota/beta/ + mkdir -p ota/debug/beta/ + mkdir -p ota/master/ + mkdir -p ota/debug/master/ + mkdir -p webflash/ mkdir -p resources/ mkdir -p src/ cp -vf release/*/nuki_hub_*.bin ota/beta/ + cp -vf debug/*/nuki_hub_*.bin ota/debug/beta/ cp -vf master/resources/ota_manifest.py resources/ota_manifest.py cp -vf master/src/Config.h src/Config.h python3 resources/ota_manifest.py beta $Version find * -not -path "ota*" -not -path "webflash*" -delete rm -rf .github .gitignore .gitmodules + touch ota/beta/empty + touch ota/master/empty + touch ota/debug/beta/empty + touch ota/debug/master/empty + touch webflash/empty - name: Commit binaries to binary uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "Update binaries" - file_pattern: 'ota/* ota/master/* ota/beta/* webflash/*' + file_pattern: 'ota/* ota/debug/* ota/master/* ota/debug/master/* ota/beta/* ota/debug/beta/* webflash/*' branch: binary skip_dirty_check: true skip_fetch: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01b69ac..24828c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,13 +57,12 @@ jobs: sed -i "s/unknownbuildnr/$Version/g" src/Config.h - name: Build ${{ matrix.build }} PlatformIO Project ${{ matrix.board }} run: | + ORIGBOARD="${BOARD}" if [ "$BUILD" = "debug" ]; then BOARD="${BOARD}_dbg" fi echo "::group::Building with PlatformIO" - if [ "$BUILD" = "release" ]; then - make updater_${BOARD} - fi + make updater_${ORIGBOARD} make $BOARD echo "::endgroup::" - name: Add flash script diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index cb99157..96b47e6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -12,19 +12,20 @@ jobs: name: Count commits in last 24h if: github.repository == 'technyon/nuki_hub' runs-on: ubuntu-latest + outputs: + has-commits: ${{ steps.commits.outputs.NEW_COMMIT_COUNT }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive - name: Get new commits - run: echo "NEW_COMMIT_COUNT=$(git log --oneline --since '24 hours ago' | wc -l)" >> $GITHUB_ENV - - name: Check if commits larger than 0 - if: ${{ env.NEW_COMMIT_COUNT < 1 }} - run: exit 1 + id: commits + run: echo "NEW_COMMIT_COUNT=$(git log --oneline --since '24 hours ago' | wc -l)" >> $GITHUB_OUTPUT build: name: Build ${{ matrix.board }} (${{ matrix.build }}) needs: check-commits + if: needs.check-commits.outputs.has-commits > 0 runs-on: ubuntu-latest strategy: fail-fast: false @@ -69,13 +70,12 @@ jobs: python3 resources/config_version.py master - name: Build ${{ matrix.build }} PlatformIO Project ${{ matrix.board }} run: | + ORIGBOARD="${BOARD}" if [ "$BUILD" = "debug" ]; then BOARD="${BOARD}_dbg" fi echo "::group::Building with PlatformIO" - if [ "$BUILD" = "release" ]; then - make updater_${BOARD} - fi + make updater_${ORIGBOARD} make $BOARD echo "::endgroup::" - name: Add flash script @@ -109,7 +109,8 @@ jobs: path: ${{ matrix.build }}/${{ env.VARIANT }} ota-nightly: name: Create nightly from latest master - needs: build + needs: [check-commits, build] + if: needs.check-commits.outputs.has-commits > 0 runs-on: ubuntu-latest steps: - name: Git Checkout @@ -135,26 +136,39 @@ jobs: with: path: release pattern: '*-release-assets' + - name: Download debug assets + uses: actions/download-artifact@v4 + with: + path: debug + pattern: '*-debug-assets' - name: Copy binaries to ota/master env: Version: ${{ github.run_id }}.${{ github.run_number }}.${{ github.run_attempt }} run: | - mkdir -p ota/master/ mkdir -p ota/beta/ + mkdir -p ota/debug/beta/ + mkdir -p ota/master/ + mkdir -p ota/debug/master/ + mkdir -p webflash/ mkdir -p resources/ mkdir -p src/ cp -vf release/*/nuki_hub_*.bin ota/master/ + cp -vf debug/*/nuki_hub_*.bin ota/debug/master/ cp -vf master/resources/ota_manifest.py resources/ota_manifest.py cp -vf master/src/Config.h src/Config.h python3 resources/ota_manifest.py master $Version find * -not -path "ota*" -not -path "webflash*" -delete rm -rf .github .gitignore .gitmodules touch ota/beta/empty + touch ota/master/empty + touch ota/debug/beta/empty + touch ota/debug/master/empty + touch webflash/empty - name: Commit binaries to binary uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "Update binaries" - file_pattern: 'ota/* ota/master/* ota/beta/* webflash/*' + file_pattern: 'ota/* ota/debug/* ota/master/* ota/debug/master/* ota/beta/* ota/debug/beta/* webflash/*' branch: binary skip_dirty_check: true skip_fetch: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd4edf4..37795e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,13 +51,12 @@ jobs: sed -i "s/unknownbuildnr/$Version/g" src/Config.h - name: Build ${{ matrix.build }} PlatformIO Project ${{ matrix.board }} run: | + ORIGBOARD="${BOARD}" if [ "$BUILD" = "debug" ]; then BOARD="${BOARD}_dbg" fi echo "::group::Building with PlatformIO" - if [ "$BUILD" = "release" ]; then - make updater_${BOARD} - fi + make updater_${ORIGBOARD} make $BOARD echo "::endgroup::" - name: Add flash script @@ -181,10 +180,15 @@ jobs: env: Version: ${{ github.run_id }}.${{ github.run_number }}.${{ github.run_attempt }} run: | - mkdir -p ota/ + mkdir -p ota/beta/ + mkdir -p ota/debug/beta/ + mkdir -p ota/master/ + mkdir -p ota/debug/master/ + mkdir -p webflash/ mkdir -p resources/ mkdir -p src/ cp -vf release/*/nuki_hub_*.bin ota/ + cp -vf debug/*/nuki_hub_*.bin ota/debug/ cp -vf release/*/webflash_nuki_hub_*.bin webflash/ cp -vf master/resources/ota_manifest.py resources/ota_manifest.py cp -vf master/src/Config.h src/Config.h @@ -192,12 +196,18 @@ jobs: python3 resources/ota_manifest.py beta none find * -not -path "ota*" -not -path "webflash*" -delete rm -rf ota/beta/*.bin + rm -rf ota/debug/beta/*.bin rm -rf .github .gitignore .gitmodules + touch ota/beta/empty + touch ota/master/empty + touch ota/debug/beta/empty + touch ota/debug/master/empty + touch webflash/empty - name: Commit binaries to binary uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "Update binaries" - file_pattern: 'ota/* ota/master/* webflash/*' + file_pattern: 'ota/* ota/debug/* ota/master/* ota/debug/master/* ota/beta/* ota/debug/beta/* webflash/*' branch: binary skip_dirty_check: true skip_fetch: true diff --git a/pio_package.py b/pio_package.py index 46e1135..f5e118b 100644 --- a/pio_package.py +++ b/pio_package.py @@ -26,8 +26,7 @@ def copy_files(source, target, env): shutil.copy(file, f"{target_dir}/nuki_hub.{file.name}") elif "firmware" in file.stem: shutil.copy(file, f"{target_dir}/nuki_hub_{board}{file.suffix}") - if env.GetProjectOption("custom_build") == 'release': - shutil.copy(f"{project_dir}/updater/release/{board}/updater.bin", f"{target_dir}/nuki_hub_updater_{board}{file.suffix}") + shutil.copy(f"{project_dir}/updater/release/{board}/updater.bin", f"{target_dir}/nuki_hub_updater_{board}{file.suffix}") else: shutil.copy(file, f"{target_dir}/{file.name}") @@ -68,8 +67,7 @@ def package_last_files(source, target, env): shutil.copy(file, f"{target_dir}/{file.name}") env.AddPostAction("$BUILD_DIR/firmware.bin", copy_files) -if env.GetProjectOption("custom_build") == 'release': - env.AddPostAction("$PROJECT_DIR/updater/release/" + get_board_name(env) + "/updater.bin", copy_files) +env.AddPostAction("$PROJECT_DIR/updater/release/" + get_board_name(env) + "/updater.bin", copy_files) env.AddPostAction("$BUILD_DIR/firmware.bin", package_last_files) env.AddPostAction("$BUILD_DIR/partitions.bin", copy_files) env.AddPostAction("$BUILD_DIR/bootloader.bin", copy_files) @@ -77,5 +75,4 @@ env.AddPostAction("$BUILD_DIR/bootloader.bin", copy_files) if env.GetProjectOption("custom_build") == 'debug': env.AddPostAction("$BUILD_DIR/firmware.elf", copy_files) -if env.GetProjectOption("custom_build") == 'release': - env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_bin) \ No newline at end of file +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_bin) \ No newline at end of file diff --git a/src/Config.h b/src/Config.h index c90a0e3..9850560 100644 --- a/src/Config.h +++ b/src/Config.h @@ -16,6 +16,12 @@ #define GITHUB_BETA_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/beta/nuki_hub_updater_esp32c3.bin" #define GITHUB_MASTER_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_esp32c3.bin" #define GITHUB_MASTER_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_updater_esp32c3.bin" +#define GITHUB_LATEST_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_esp32c3.bin" +#define GITHUB_LATEST_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_updater_esp32c3.bin" +#define GITHUB_BETA_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_esp32c3.bin" +#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32c3.bin" +#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32c3.bin" +#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32c3.bin" #elif defined(CONFIG_IDF_TARGET_ESP32S3) #define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32s3.bin" #define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32s3.bin" @@ -23,6 +29,12 @@ #define GITHUB_BETA_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/beta/nuki_hub_updater_esp32s3.bin" #define GITHUB_MASTER_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_esp32s3.bin" #define GITHUB_MASTER_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_updater_esp32s3.bin" +#define GITHUB_LATEST_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_esp32s3.bin" +#define GITHUB_LATEST_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_updater_esp32s3.bin" +#define GITHUB_BETA_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_esp32s3.bin" +#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32s3.bin" +#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32s3.bin" +#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32s3.bin" #elif defined(CONFIG_IDF_TARGET_ESP32C6) #define GITHUB_LATEST_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32c6.bin" #define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32c6.bin" @@ -30,6 +42,12 @@ #define GITHUB_BETA_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/beta/nuki_hub_updater_esp32c6.bin" #define GITHUB_MASTER_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_esp32c6.bin" #define GITHUB_MASTER_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_updater_esp32c6.bin" +#define GITHUB_LATEST_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_esp32c6.bin" +#define GITHUB_LATEST_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_updater_esp32c6.bin" +#define GITHUB_BETA_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_esp32c6.bin" +#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32c6.bin" +#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32c6.bin" +#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32c6.bin" #else #define GITHUB_LATEST_RELEASE_BINARY_URL "https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_esp32.bin" #define GITHUB_LATEST_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/nuki_hub_updater_esp32.bin" @@ -37,6 +55,12 @@ #define GITHUB_BETA_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/beta/nuki_hub_updater_esp32.bin" #define GITHUB_MASTER_RELEASE_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_esp32.bin" #define GITHUB_MASTER_UPDATER_BINARY_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/master/nuki_hub_updater_esp32.bin" +#define GITHUB_LATEST_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_esp32.bin" +#define GITHUB_LATEST_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/nuki_hub_updater_esp32.bin" +#define GITHUB_BETA_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_esp32.bin" +#define GITHUB_BETA_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/beta/nuki_hub_updater_esp32.bin" +#define GITHUB_MASTER_RELEASE_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_esp32.bin" +#define GITHUB_MASTER_UPDATER_BINARY_URL_DBG (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/debug/master/nuki_hub_updater_esp32.bin" #endif #ifndef NUKI_HUB_UPDATER diff --git a/src/NukiNetwork.cpp b/src/NukiNetwork.cpp index 3a4d986..28b2fc1 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -13,7 +13,6 @@ #ifndef NUKI_HUB_UPDATER #include -bool _versionPublished = false; #endif NukiNetwork* NukiNetwork::_inst = nullptr; @@ -466,16 +465,16 @@ bool NukiNetwork::update() publishULong(_maintenancePathPrefix, mqtt_topic_uptime, ts / 1000 / 60, true); publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true); + if(_lastMaintenanceTs == 0) + { + publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_fw, getRestartReason().c_str(), true); + publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_esp, getEspRestartReason().c_str(), true); + publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION, true); + publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_build, NUKI_HUB_BUILD, true); + } if(_publishDebugInfo) { publishUInt(_maintenancePathPrefix, mqtt_topic_freeheap, esp_get_free_heap_size(), true); - publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_fw, getRestartReason().c_str(), true); - publishString(_maintenancePathPrefix, mqtt_topic_restart_reason_esp, getEspRestartReason().c_str(), true); - } - if (!_versionPublished) { - publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION, true); - publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_build, NUKI_HUB_BUILD, true); - _versionPublished = true; } _lastMaintenanceTs = ts; } @@ -504,13 +503,16 @@ bool NukiNetwork::update() if (!jsonError) { - _latestVersion = doc["release"]["version"]; + String currentVersion = NUKI_HUB_VERSION; + + if(atof(doc["release"]["version"]) >= atof(currentVersion.c_str())) _latestVersion = doc["release"]["version"]; + else if(currentVersion.indexOf("beta") > 0) _latestVersion = doc["beta"]["version"]; + else if(currentVersion.indexOf("master") > 0) _latestVersion = doc["master"]["version"]; + else _latestVersion = doc["release"]["version"]; + publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_latest, _latestVersion, true); - if (_latestVersion != _preferences->getString(preference_latest_version).c_str()) - { - _preferences->putString(preference_latest_version, _latestVersion); - } + if(strcmp(_latestVersion, _preferences->getString(preference_latest_version).c_str()) != 0) _preferences->putString(preference_latest_version, _latestVersion); } } } @@ -923,7 +925,11 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha json["avty"]["t"] = availabilityTopic; json["pl_lock"] = lockAction; json["pl_unlk"] = unlockAction; - json["pl_open"] = openAction; + + uint32_t aclPrefs[17]; + _preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs)); + if((int)aclPrefs[2]) json["pl_open"] = openAction; + json["stat_t"] = String("~") + mqtt_topic_lock_ha_state; json["stat_jammed"] = "jammed"; json["stat_locked"] = "locked"; @@ -1199,6 +1205,38 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha { { (char*)"en", (char*)"true" }, {(char*)"ic", (char*)"mdi:counter"}}); + // Nuki Hub restart reason + publishHassTopic("sensor", + "nuki_hub_restart_reason", + uidString, + "_nuki_hub_restart_reason", + "Nuki Hub restart reason", + name, + baseTopic, + _lockPath + mqtt_topic_restart_reason_fw, + deviceType, + "", + "", + "diagnostic", + "", + { { (char*)"en", (char*)"true" }}); + + // Nuki Hub restart reason ESP + publishHassTopic("sensor", + "nuki_hub_restart_reason_esp", + uidString, + "_nuki_hub_restart_reason_esp", + "Nuki Hub restart reason ESP", + name, + baseTopic, + _lockPath + mqtt_topic_restart_reason_esp, + deviceType, + "", + "", + "diagnostic", + "", + { { (char*)"en", (char*)"true" }}); + if(_preferences->getBool(preference_check_updates)) { // NUKI Hub latest @@ -1292,7 +1330,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha publishHassTopic("button", "query_lockstate", uidString, - "_query_lockstate_button", + "_query_lockstate", "Query lock state", name, baseTopic, @@ -1309,7 +1347,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha publishHassTopic("button", "query_config", uidString, - "_query_config_button", + "_query_config", "Query config", name, baseTopic, @@ -1326,7 +1364,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha publishHassTopic("button", "query_commandresult", uidString, - "_query_commandresult_button", + "_query_commandresult", "Query lock state command result", name, baseTopic, @@ -1375,7 +1413,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons publishHassTopic("button", "unlatch", uidString, - "_unlatch_button", + "_unlatch", "Open", name, baseTopic, @@ -1399,7 +1437,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons publishHassTopic("button", "lockngo", uidString, - "_lock_n_go_button", + "_lockngo", "Lock 'n' Go", name, baseTopic, @@ -1423,7 +1461,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons publishHassTopic("button", "lockngounlatch", uidString, - "_lock_n_go_unlatch_button", + "_lockngounlatch", "Lock 'n' Go with unlatch", name, baseTopic, @@ -1445,7 +1483,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons publishHassTopic("button", "query_battery", uidString, - "_query_battery_button", + "_query_battery", "Query battery", name, baseTopic, @@ -2444,7 +2482,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co publishHassTopic("button", "unlatch", uidString, - "_unlatch_button", + "_unlatch", "Open", name, baseTopic, @@ -2505,7 +2543,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co } publishHassTopic("binary_sensor", - "ring", + "ring_detect", uidString, "_ring_detect", "Ring detect", @@ -3346,7 +3384,7 @@ void NukiNetwork::publishHASSConfigKeypad(char *deviceType, const char *baseTopi publishHassTopic("button", "query_keypad", uidString, - "_query_keypad_button", + "_query_keypad", "Query keypad", name, baseTopic, @@ -3487,7 +3525,7 @@ void NukiNetwork::removeHASSConfig(char* uidString) removeHassTopic((char*)"button", (char*)"lockngounlatch", uidString); removeHassTopic((char*)"sensor", (char*)"battery_level", uidString); removeHassTopic((char*)"binary_sensor", (char*)"door_sensor", uidString); - removeHassTopic((char*)"binary_sensor", (char*)"ring", uidString); + removeHassTopic((char*)"binary_sensor", (char*)"ring_detect", uidString); removeHassTopic((char*)"sensor", (char*)"sound_level", uidString); removeHassTopic((char*)"sensor", (char*)"last_action_authorization", uidString); removeHassTopic((char*)"sensor", (char*)"keypad_status", uidString); @@ -3558,6 +3596,8 @@ void NukiNetwork::removeHASSConfig(char* uidString) removeHassTopic((char*)"sensor", (char*)"uptime", uidString); removeHassTopic((char*)"sensor", (char*)"mqtt_log", uidString); removeHassTopic((char*)"binary_sensor", (char*)"hybrid_connected", uidString); + removeHassTopic((char*)"sensor", (char*)"nuki_hub_restart_reason", uidString); + removeHassTopic((char*)"sensor", (char*)"nuki_hub_restart_reason_esp", uidString); } void NukiNetwork::removeHASSConfigTopic(char *deviceType, char *name, char *uidString) diff --git a/src/NukiNetworkLock.cpp b/src/NukiNetworkLock.cpp index bf57be3..6c47281 100644 --- a/src/NukiNetworkLock.cpp +++ b/src/NukiNetworkLock.cpp @@ -196,8 +196,28 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(value, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false)) { Log->println(F("Update requested via MQTT.")); - _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL); - _preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL); + String currentVersion = NUKI_HUB_VERSION; + + if(atof(_preferences->getString(preference_latest_version).c_str()) >= atof(currentVersion.c_str())) + { + _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL); + } + else if(currentVersion.indexOf("beta") > 0) + { + _preferences->putString(preference_ota_updater_url, GITHUB_BETA_RELEASE_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_BETA_UPDATER_BINARY_URL); + } + else if(currentVersion.indexOf("master") > 0) + { + _preferences->putString(preference_ota_updater_url, GITHUB_MASTER_RELEASE_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_MASTER_UPDATER_BINARY_URL); + } + else + { + _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL); + } delay(200); restartEsp(RestartReason::OTAReboot); } diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index 825a1e2..4904b37 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -48,8 +48,9 @@ WebCfgServer::WebCfgServer(NukiNetwork* network, EthServer* ethServer, Preferenc memcpy(&_credPassword, pass, str.length()); } - #ifndef NUKI_HUB_UPDATER _confirmCode = generateConfirmCode(); + + #ifndef NUKI_HUB_UPDATER _pinsConfigured = true; if(_nuki != nullptr && !_nuki->isPinSet()) @@ -312,6 +313,14 @@ void WebCfgServer::initialize() buildOtaHtml(response, _server.arg("errored") != ""); _server.send(200, "text/html", response); }); + _server.on("/otadebug", [&]() { + if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { + return _server.requestAuthentication(); + } + String response = ""; + buildOtaHtml(response, _server.arg("errored") != "", true); + _server.send(200, "text/html", response); + }); _server.on("/reboottoota", [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { return _server.requestAuthentication(); @@ -327,29 +336,12 @@ void WebCfgServer::initialize() if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { return _server.requestAuthentication(); } - String response = ""; - String key = _server.argName(0); - if(key == "beta") - { - buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest BETA version", 2); - _preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL); - _preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL); - } - else if(key == "master") - { - buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest development version", 2); - _preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL); - _preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL); - } - else - { - buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest RELEASE version", 2); - _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL); - _preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL); - } - _server.send(200, "text/html", response); - waitAndProcess(true, 1000); - restartEsp(RestartReason::OTAReboot); + #ifndef NUKI_HUB_UPDATER + processUpdate(); + #else + _server.sendHeader("Location", "/"); + _server.send(302, "text/plain", ""); + #endif }); _server.on("/uploadota", HTTP_POST, [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { @@ -401,7 +393,7 @@ void WebCfgServer::update() _server.handleClient(); } -void WebCfgServer::buildOtaHtml(String &response, bool errored) +void WebCfgServer::buildOtaHtml(String &response, bool errored, bool debug) { buildHtmlHeader(response); @@ -421,20 +413,34 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored) response.concat("

Update Nuki Hub

"); response.concat("Click on the button to reboot and automatically update Nuki Hub and the Nuki Hub updater to the latest versions from GitHub"); response.concat("
"); - response.concat("

"); - response.concat("

"); - response.concat("

"); + + String release_type; + + if(debug) release_type = "debug"; + else release_type = "release"; + + #ifndef DEBUG_NUKIHUB + String build_type = "release"; + #else + String build_type = "debug"; + #endif + + response.concat("

"); + response.concat("

"); + response.concat("

"); response.concat("

"); - response.concat("Current version: "); + response.concat("Current version: "); response.concat(NUKI_HUB_VERSION); response.concat(" ("); response.concat(NUKI_HUB_BUILD); - response.concat("), "); + response.concat("), "); response.concat(NUKI_HUB_DATE); response.concat("
"); #ifndef NUKI_HUB_UPDATER + bool manifestSuccess = false; + NetworkClientSecure *client = new NetworkClientSecure; if (client) { client->setDefaultCACertBundle(); @@ -454,28 +460,34 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored) if (!jsonError) { - response.concat("Latest release version: "); + manifestSuccess = true; + response.concat("Latest release version: "); response.concat(doc["release"]["fullversion"].as()); response.concat(" ("); response.concat(doc["release"]["build"].as()); - response.concat("), "); + response.concat("), "); response.concat(doc["release"]["time"].as()); response.concat("
"); - response.concat("Latest beta version: "); - response.concat(doc["beta"]["fullversion"].as()); + response.concat("Latest beta version: "); if(doc["beta"]["fullversion"] != "No beta available") { + response.concat(doc["beta"]["fullversion"].as()); response.concat(" ("); response.concat(doc["beta"]["build"].as()); - response.concat("), "); + response.concat("), "); response.concat(doc["beta"]["time"].as()); } + else + { + response.concat(doc["beta"]["fullversion"].as()); + response.concat(""); + } response.concat("
"); - response.concat("Latest development version: "); + response.concat("Latest development version: "); response.concat(doc["master"]["fullversion"].as()); response.concat(" ("); response.concat(doc["master"]["build"].as()); - response.concat("), "); + response.concat("), "); response.concat(doc["master"]["time"].as()); response.concat("
"); } @@ -485,6 +497,11 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored) } delete client; } + + if(!manifestSuccess) + { + response.concat("currentverlatestverdevverbetaver"); + } #endif response.concat("
"); @@ -665,11 +682,20 @@ void WebCfgServer::handleOtaUpload() } } -void WebCfgServer::buildConfirmHtml(String &response, const String &message, uint32_t redirectDelay) +void WebCfgServer::buildConfirmHtml(String &response, const String &message, uint32_t redirectDelay, bool redirect) { - String delay(redirectDelay); - String header = ""; + String header; + if(!redirect) + { + String delay(redirectDelay); + header = ""; + } + else + { + String delay(redirectDelay * 1000); + header = ""; + } buildHtmlHeader(response, header); response.concat(message); response.concat(""); @@ -688,6 +714,12 @@ void WebCfgServer::sendFavicon() _server.send(200, "image/png", (const char*)favicon_32x32, sizeof(favicon_32x32)); } +String WebCfgServer::generateConfirmCode() +{ + int code = random(1000,9999); + return String(code); +} + #ifndef NUKI_HUB_UPDATER void WebCfgServer::sendSettings() { @@ -2976,6 +3008,72 @@ void WebCfgServer::processUnpair(bool opener) restartEsp(RestartReason::DeviceUnpaired); } +void WebCfgServer::processUpdate() +{ + String response = ""; + String key = _server.argName(0); + String key2 = _server.argName(1); + String key3 = _server.argName(2); + String value3 = _server.arg(2); + String key4 = _server.argName(3); + + if(key3 != "token" || value3 != _confirmCode) + { + buildConfirmHtml(response, "Confirm code is invalid.", 3, true); + _server.send(200, "text/html", response); + return; + } + + if(key == "beta") + { + if(key2 == "debug") + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest DEBUG BETA version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL_DBG); + _preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL_DBG); + } + else + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest BETA version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL); + } + } + else if(key == "master") + { + if(key2 == "debug") + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest DEBUG DEVELOPMENT version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL_DBG); + _preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL_DBG); + } + else + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest DEVELOPMENT version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL); + } + } + else + { + if(key2 == "debug") + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest DEBUG RELEASE version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL_DBG); + _preferences->putString(preference_ota_main_url, GITHUB_LATEST_UPDATER_BINARY_URL_DBG); + } + else + { + buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater
Updating to latest RELEASE version", 2, true); + _preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL); + _preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL); + } + } + _server.send(200, "text/html", response); + waitAndProcess(true, 1000); + restartEsp(RestartReason::OTAReboot); +} + void WebCfgServer::processFactoryReset() { bool resetWifi = false; @@ -3238,13 +3336,6 @@ void WebCfgServer::printParameter(String& response, const char *description, con } - -String WebCfgServer::generateConfirmCode() -{ - int code = random(1000,9999); - return String(code); -} - const std::vector> WebCfgServer::getNetworkDetectionOptions() const { std::vector> options; diff --git a/src/WebCfgServer.h b/src/WebCfgServer.h index 6510170..fbcf541 100644 --- a/src/WebCfgServer.h +++ b/src/WebCfgServer.h @@ -61,6 +61,7 @@ private: void buildConfigureWifiHtml(String& response); void buildInfoHtml(String& response); void processUnpair(bool opener); + void processUpdate(); void processFactoryReset(); void printInputField(String& response, const char* token, const char* description, const char* value, const size_t& maxLength, const char* id, const bool& isPassword = false, const bool& showLengthRestriction = false); void printInputField(String& response, const char* token, const char* description, const int value, size_t maxLength, const char* id); @@ -76,19 +77,18 @@ private: String pinStateToString(uint8_t value); void printParameter(String& response, const char* description, const char* value, const char *link = "", const char *id = ""); - - String generateConfirmCode(); NukiWrapper* _nuki = nullptr; NukiOpenerWrapper* _nukiOpener = nullptr; Gpio* _gpio = nullptr; bool _pinsConfigured = false; bool _brokerConfigured = false; - String _confirmCode = "----"; #endif - void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5); - void buildOtaHtml(String& response, bool errored); + String generateConfirmCode(); + String _confirmCode = "----"; + void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5, bool redirect = false); + void buildOtaHtml(String& response, bool errored, bool debug = false); void buildOtaCompletedHtml(String& response); void sendCss(); void sendFavicon(); diff --git a/src/networkDevices/WifiDevice.cpp b/src/networkDevices/WifiDevice.cpp index 30b96da..b3072ee 100644 --- a/src/networkDevices/WifiDevice.cpp +++ b/src/networkDevices/WifiDevice.cpp @@ -78,7 +78,7 @@ void WifiDevice::initialize() _wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled)); // reduced timeout if ESP is set to restart on disconnect _wm.setFindBestRSSI(_preferences->getBool(preference_find_best_rssi)); - _wm.setConnectTimeout(5); + _wm.setConnectTimeout(20); _wm.setConfigPortalTimeout(_restartOnDisconnect ? 60 * 3 : 60 * 30); _wm.setShowInfoUpdate(false); _wm.setMenu(wm_menu);