diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index 504cb865a9cc0b..c7730f2c27b32d 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -104,6 +104,8 @@ jobs: build \ " - name: Run Discover Commissionables Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -115,6 +117,8 @@ jobs: --factoryreset \ ' - name: Run Pairing Onnetwork Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -126,6 +130,8 @@ jobs: --factoryreset \ ' - name: Run IM Invoke Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -137,6 +143,8 @@ jobs: --factoryreset \ ' - name: Run IM Extendable Invoke Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -148,6 +156,8 @@ jobs: --factoryreset \ ' - name: Run IM Read Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -159,6 +169,8 @@ jobs: --factoryreset \ ' - name: Run IM Write Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -170,6 +182,8 @@ jobs: --factoryreset \ ' - name: Run IM Subscribe Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -181,6 +195,8 @@ jobs: --factoryreset \ ' - name: Run Pairing AlreadyDiscovered Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -191,19 +207,22 @@ jobs: --tool-args "already-discovered --nodeid 1 --setup-pin-code 20202021 --address ::1 --port 5540 -t 1000" \ --factoryreset \ ' - # Disabled due to failure: https://github.com/project-chip/connectedhomeip/issues/27361 - # - name: Run Pairing Address-PaseOnly Test - # run: | - # scripts/run_in_python_env.sh out/venv \ - # './scripts/tests/run_java_test.py \ - # --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ - # --app-args "--discriminator 3840 --interface-id -1" \ - # --tool-path out/linux-x64-java-matter-controller \ - # --tool-cluster "pairing" \ - # --tool-args "address-paseonly --nodeid 1 --setup-pin-code 20202021 --address ::1 --port 5540 -t 1000" \ - # --factoryreset \ - # ' + - name: Run Pairing Address-PaseOnly Test + # Disabled due to failure: https://github.com/project-chip/connectedhomeip/issues/27361 + if: false + run: | + scripts/run_in_python_env.sh out/venv \ + './scripts/tests/run_java_test.py \ + --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ + --app-args "--discriminator 3840 --interface-id -1" \ + --tool-path out/linux-x64-java-matter-controller \ + --tool-cluster "pairing" \ + --tool-args "address-paseonly --nodeid 1 --setup-pin-code 20202021 --address ::1 --port 5540 -t 1000" \ + --factoryreset \ + ' - name: Run Pairing SetupQRCode Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -215,6 +234,8 @@ jobs: --factoryreset \ ' - name: Run Pairing ManualCode Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -226,6 +247,8 @@ jobs: --factoryreset \ ' - name: Run Pairing ICD Onnetwork Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_java_test.py \ @@ -236,7 +259,23 @@ jobs: --tool-args "onnetwork-long --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \ --factoryreset \ ' + - name: Run Pairing Onnetwork and get diagnostic log Test + # TODO: test below is disabled because it seems flaky (crashes on pool not being empty on app exit) + # See: https://github.com/project-chip/connectedhomeip/issues/36734 + if: false + run: | + scripts/run_in_python_env.sh out/venv \ + './scripts/tests/run_java_test.py \ + --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ + --app-args "--discriminator 3840 --interface-id -1 --crash_log ./crashLog.log --end_user_support_log ./enduser.log --network_diagnostics_log ./network.log" \ + --tool-path out/linux-x64-java-matter-controller \ + --tool-cluster "bdx" \ + --tool-args "onnetwork-long-downloadLog --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 3000 --logType CrashLogs --fileName ./crashLog.log" \ + --factoryreset \ + ' - name: Run Pairing Onnetwork Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_kotlin_test.py \ @@ -248,6 +287,8 @@ jobs: --factoryreset \ ' - name: Run Kotlin IM Invoke Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_kotlin_test.py \ @@ -259,6 +300,8 @@ jobs: --factoryreset \ ' - name: Run Kotlin IM Read Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_kotlin_test.py \ @@ -270,6 +313,8 @@ jobs: --factoryreset \ ' - name: Run Kotlin IM Write Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_kotlin_test.py \ @@ -281,6 +326,8 @@ jobs: --factoryreset \ ' - name: Run Kotlin IM Subscribe Test + # Generally completes in seconds + timeout-minutes: 2 run: | scripts/run_in_python_env.sh out/venv \ './scripts/tests/run_kotlin_test.py \ diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index ceee20818defd8..7e19267b3742af 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -496,6 +496,7 @@ jobs: --target linux-x64-network-manager-ipv6only-no-ble-no-wifi-tsan-clang-test \ --target linux-x64-fabric-admin-rpc-ipv6only-no-ble-no-wifi-clang \ --target linux-x64-fabric-bridge-rpc-ipv6only-no-ble-no-wifi-clang \ + --target linux-x64-fabric-sync-ipv6only-no-ble-no-wifi-clang \ --target linux-x64-light-data-model-no-unique-id-ipv6only-no-ble-no-wifi-clang \ --target linux-x64-python-bindings \ build \ @@ -513,6 +514,7 @@ jobs: echo "NETWORK_MANAGEMENT_APP: out/linux-x64-network-manager-ipv6only-no-ble-no-wifi-tsan-clang-test/matter-network-manager-app" >> /tmp/test_env.yaml echo "FABRIC_ADMIN_APP: out/linux-x64-fabric-admin-rpc-ipv6only-no-ble-no-wifi-clang/fabric-admin" >> /tmp/test_env.yaml echo "FABRIC_BRIDGE_APP: out/linux-x64-fabric-bridge-rpc-ipv6only-no-ble-no-wifi-clang/fabric-bridge-app" >> /tmp/test_env.yaml + echo "FABRIC_SYNC_APP: out/linux-x64-fabric-sync-ipv6only-no-ble-no-wifi-clang/fabric-sync" >> /tmp/test_env.yaml echo "LIGHTING_APP_NO_UNIQUE_ID: out/linux-x64-light-data-model-no-unique-id-ipv6only-no-ble-no-wifi-clang/chip-lighting-app" >> /tmp/test_env.yaml echo "TRACE_APP: out/trace_data/app-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml echo "TRACE_TEST_JSON: out/trace_data/test-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml diff --git a/docs/testing/python.md b/docs/testing/python.md index a7bec6d07e17c3..9bda585726d409 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -722,6 +722,11 @@ for that run, e.g.: - Example: `"Manual pairing code: \\[\\d+\\]"` +- `app-stdin-pipe`: Specifies the path to the named pipe that the test runner + might use to send input to the application. + + - Example: `/tmp/app-fifo` + - `script-args`: Specifies the arguments to be passed to the test script. - Example: diff --git a/docs/upgrading.md b/docs/upgrading.md index 517a83f6574dc9..e9e17239d50049 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -102,3 +102,8 @@ To preserve `codegen/zap` generated logic, use `CodegenDataModelProviderInstance` (see changes in [36558](https://github.com/project-chip/connectedhomeip/pull/36558) and [36613](https://github.com/project-chip/connectedhomeip/pull/36613) ). + +To use default attribute persistence, you need to pass in a +`PersistentStorageDelegate` to `CodegenDataModelProviderInstance`. See example +changes in [36658](https://github.com/project-chip/connectedhomeip/pull/36658) +). diff --git a/examples/air-purifier-app/ameba/main/chipinterface.cpp b/examples/air-purifier-app/ameba/main/chipinterface.cpp index 72563f987efdbe..368fa8eee05a8a 100644 --- a/examples/air-purifier-app/ameba/main/chipinterface.cpp +++ b/examples/air-purifier-app/ameba/main/chipinterface.cpp @@ -135,7 +135,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; diff --git a/examples/air-purifier-app/cc32xx/main/AppTask.cpp b/examples/air-purifier-app/cc32xx/main/AppTask.cpp index e7527ef338f05a..a14ccbeff0a900 100644 --- a/examples/air-purifier-app/cc32xx/main/AppTask.cpp +++ b/examples/air-purifier-app/cc32xx/main/AppTask.cpp @@ -165,7 +165,7 @@ int AppTask::Init() PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index 06ba9f01cd8256..7ba25ed011cd41 100644 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -150,7 +150,7 @@ static void InitServer(intptr_t context) initParams.appDelegate = &sAmebaObserver; initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); diff --git a/examples/all-clusters-app/asr/BUILD.gn b/examples/all-clusters-app/asr/BUILD.gn index e27884810cbd8f..c9764e954189b2 100644 --- a/examples/all-clusters-app/asr/BUILD.gn +++ b/examples/all-clusters-app/asr/BUILD.gn @@ -111,6 +111,7 @@ asr_executable("clusters_app") { "${chip_root}/examples/all-clusters-app/all-clusters-common", "${chip_root}/examples/common/QRCode", "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:default", "${chip_root}/src/setup_payload", diff --git a/examples/all-clusters-app/infineon/psoc6/BUILD.gn b/examples/all-clusters-app/infineon/psoc6/BUILD.gn index aeb1fa0b6feb4d..bc250abd5c6e90 100644 --- a/examples/all-clusters-app/infineon/psoc6/BUILD.gn +++ b/examples/all-clusters-app/infineon/psoc6/BUILD.gn @@ -148,6 +148,7 @@ psoc6_executable("clusters_app") { "${chip_root}/examples/all-clusters-app/all-clusters-common", "${chip_root}/examples/common/QRCode", "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:default", "${chip_root}/src/setup_payload", diff --git a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp index 3b127091f13277..3f56626cd97b59 100644 --- a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp @@ -130,7 +130,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 0e16c64c41de13..64dcf06e90736b 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -92,6 +92,7 @@ source_set("chip-all-clusters-common") { deps = [ "${chip_root}/examples/all-clusters-app/all-clusters-common", "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/app/tests/suites/credentials:dac_provider", "${chip_root}/src/lib", "${chip_root}/third_party/jsoncpp", diff --git a/examples/all-clusters-app/linux/fuzzing-main.cpp b/examples/all-clusters-app/linux/fuzzing-main.cpp index 5056f08cce65f4..565e8198c26d25 100644 --- a/examples/all-clusters-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-app/linux/fuzzing-main.cpp @@ -57,7 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-app/mbed/main/AppTask.cpp b/examples/all-clusters-app/mbed/main/AppTask.cpp index 98b8597ba43e5f..3a6686b517a78a 100644 --- a/examples/all-clusters-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-app/mbed/main/AppTask.cpp @@ -72,7 +72,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp index 9dcd4238240111..44a656279118a4 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -227,7 +227,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/all-clusters-app/nxp/mw320/BUILD.gn b/examples/all-clusters-app/nxp/mw320/BUILD.gn index 89ba7f249719cc..73ea8cc02023ab 100644 --- a/examples/all-clusters-app/nxp/mw320/BUILD.gn +++ b/examples/all-clusters-app/nxp/mw320/BUILD.gn @@ -64,6 +64,7 @@ mw320_executable("shell_mw320") { ] deps = [ + "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/platform:syscalls_stub", "${chip_root}/src/platform/logging:default", ] diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp index bf0d6a282e9373..fbf99510c3cbfa 100644 --- a/examples/all-clusters-app/nxp/mw320/main.cpp +++ b/examples/all-clusters-app/nxp/mw320/main.cpp @@ -1069,7 +1069,7 @@ static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); chip::Server::GetInstance().Init(initParams); PRINTF("Done to call chip::Server() \r\n"); } diff --git a/examples/all-clusters-app/tizen/BUILD.gn b/examples/all-clusters-app/tizen/BUILD.gn index 332b03cbebaf00..59aac2228161d4 100644 --- a/examples/all-clusters-app/tizen/BUILD.gn +++ b/examples/all-clusters-app/tizen/BUILD.gn @@ -53,6 +53,7 @@ source_set("chip-all-clusters-common") { deps = [ "${chip_root}/examples/all-clusters-app/all-clusters-common", "${chip_root}/examples/platform/tizen:app-main", + "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/lib/shell:shell_core", ] diff --git a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp index cec1c457e04f04..7e2dc227f69b56 100644 --- a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp @@ -159,7 +159,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; diff --git a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp index 29ad68b74241f1..893f585717dc9f 100644 --- a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp @@ -128,7 +128,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp index ccd2ffa782b4dd..df61dc538ad10c 100644 --- a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp @@ -44,7 +44,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp index e516aee49e6e74..16e1a665da4518 100644 --- a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp @@ -68,7 +68,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp index 8d9771fa593204..7cad0ac8a13a00 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp @@ -174,7 +174,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml index 0526dc5a78160d..efd089817efe68 100644 --- a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml +++ b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml @@ -46,6 +46,15 @@ + + + diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index 69bfdc109912c9..fb8141e72d33a8 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -72,6 +72,7 @@ class SelectActionFragment : Fragment() { binding.provisionCustomFlowBtn.setOnClickListener { handleProvisionCustomFlowClicked() } binding.wildcardBtn.setOnClickListener { handleWildcardClicked() } binding.unpairDeviceBtn.setOnClickListener { handleUnpairDeviceClicked() } + binding.diagnosticLogBtn.setOnClickListener { handleDiagnosticLogClicked() } binding.groupSettingBtn.setOnClickListener { handleGroupSettingClicked() } binding.otaProviderBtn.setOnClickListener { handleOTAProviderClicked() } binding.icdBtn.setOnClickListener { handleICDClicked() } @@ -225,6 +226,10 @@ class SelectActionFragment : Fragment() { showFragment(OtaProviderClientFragment.newInstance()) } + private fun handleDiagnosticLogClicked() { + showFragment(DiagnosticLogFragment.newInstance()) + } + /** Notifies listener of provision-WiFi-credentials button click. */ private fun handleProvisionWiFiCredentialsClicked() { getCallback()?.setNetworkType(ProvisionNetworkType.WIFI) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt new file mode 100644 index 00000000000000..ea7d5438d247c3 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt @@ -0,0 +1,172 @@ +package com.google.chip.chiptool.clusterclient + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.os.Environment +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import androidx.core.content.FileProvider +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.DiagnosticLogType +import chip.devicecontroller.DownloadLogCallback +import com.google.chip.chiptool.ChipClient +import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.DiagnosticLogFragmentBinding +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class DiagnosticLogFragment : Fragment() { + private val deviceController: ChipDeviceController + get() = ChipClient.getDeviceController(requireContext()) + + private lateinit var scope: CoroutineScope + + private lateinit var addressUpdateFragment: AddressUpdateFragment + + private var _binding: DiagnosticLogFragmentBinding? = null + private val binding + get() = _binding!! + + private val timeout: Long + get() = binding.timeoutEd.text.toString().toULongOrNull()?.toLong() ?: 0L + + private val diagnosticLogTypeList = DiagnosticLogType.values() + private val diagnosticLogType: DiagnosticLogType + get() = diagnosticLogTypeList[binding.diagnosticTypeSp.selectedItemPosition] + + private var mDownloadFile: File? = null + private var mDownloadFileOutputStream: FileOutputStream? = null + + private var mReceiveFileLen = 0U + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = DiagnosticLogFragmentBinding.inflate(inflater, container, false) + scope = viewLifecycleOwner.lifecycleScope + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + binding.getDiagnosticLogBtn.setOnClickListener { scope.launch { getDiagnosticLogClick() } } + + binding.diagnosticTypeSp.adapter = + ArrayAdapter( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + diagnosticLogTypeList + ) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + inner class ChipDownloadLogCallback : DownloadLogCallback { + override fun onError(fabricIndex: Int, nodeId: Long, errorCode: Long) { + Log.d(TAG, "onError: $fabricIndex, ${nodeId.toULong()}, $errorCode") + showMessage("Downloading Failed") + mDownloadFileOutputStream?.flush() ?: return + } + + override fun onSuccess(fabricIndex: Int, nodeId: Long) { + Log.d(TAG, "onSuccess: $fabricIndex, ${nodeId.toULong()}") + mDownloadFileOutputStream?.flush() ?: return + showMessage("Downloading Completed") + mDownloadFile?.let { showNotification(it) } ?: return + } + + override fun onTransferData(fabricIndex: Int, nodeId: Long, data: ByteArray): Boolean { + Log.d(TAG, "onTransferData : ${data.size}") + if (mDownloadFileOutputStream == null) { + Log.d(TAG, "mDownloadFileOutputStream or mDownloadFile is null") + return false + } + return addData(mDownloadFileOutputStream!!, data) + } + + private fun addData(outputStream: FileOutputStream, data: ByteArray): Boolean { + try { + outputStream.write(data) + } catch (e: IOException) { + Log.d(TAG, "IOException", e) + return false + } + mReceiveFileLen += data.size.toUInt() + showMessage("Receive Data Size : $mReceiveFileLen") + return true + } + } + + private fun getDiagnosticLogClick() { + mDownloadFile = + createLogFile( + deviceController.fabricIndex.toUInt(), + addressUpdateFragment.deviceId.toULong(), + diagnosticLogType + ) + mDownloadFileOutputStream = FileOutputStream(mDownloadFile) + deviceController.downloadLogFromNode( + addressUpdateFragment.deviceId, + diagnosticLogType, + timeout, + ChipDownloadLogCallback() + ) + } + + private fun isExternalStorageWritable(): Boolean { + return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + } + + private fun createLogFile(fabricIndex: UInt, nodeId: ULong, type: DiagnosticLogType): File? { + if (!isExternalStorageWritable()) { + return null + } + val now = System.currentTimeMillis() + val fileName = "${type}_${fabricIndex}_${nodeId}_$now.txt" + mReceiveFileLen = 0U + return File(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), fileName) + } + + private fun showNotification(file: File) { + val intent = + Intent(Intent.ACTION_VIEW).apply { + setDataAndType(getFileUri(file), "text/plain") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + + requireActivity().startActivity(intent) + } + + private fun getFileUri(file: File): Uri { + return FileProvider.getUriForFile( + requireContext(), + "${requireContext().packageName}.provider", + file + ) + } + + private fun showMessage(msg: String) { + requireActivity().runOnUiThread { binding.diagnosticLogTv.text = msg } + } + + companion object { + private const val TAG = "DiagnosticLogFragment" + + fun newInstance(): DiagnosticLogFragment = DiagnosticLogFragment() + } +} diff --git a/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml new file mode 100644 index 00000000000000..56b770a645b442 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + +