From 21816f94e916ea4a3af388556b910b628c1cd2cd Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 12 Feb 2024 14:10:36 +0100 Subject: [PATCH 001/101] Migrate library structure --- app/build.gradle.kts | 2 +- {lib_proto => lib/ble/proto}/.gitignore | 0 {lib_proto => lib/ble/proto}/build.gradle.kts | 0 {lib_proto => lib/ble/proto}/module-rules.pro | 0 {lib_proto => lib/ble/proto}/src/main/AndroidManifest.xml | 0 {lib_proto => lib/ble/proto}/src/main/proto/common.proto | 0 {lib_proto => lib/ble/proto}/src/main/proto/request.proto | 0 {lib_proto => lib/ble/proto}/src/main/proto/response.proto | 0 {lib_proto => lib/ble/proto}/src/main/proto/result.proto | 0 {lib_proto => lib/ble/proto}/src/main/proto/version.proto | 0 {lib_provisioner => lib/ble/provisioner}/.gitignore | 0 {lib_provisioner => lib/ble/provisioner}/build.gradle.kts | 2 +- {lib_provisioner => lib/ble/provisioner}/module-rules.pro | 0 .../ble/provisioner}/src/main/AndroidManifest.xml | 0 .../main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt | 0 .../wifi/provisioner/library/ProvisionerRepository.kt | 1 + .../wifi/provisioner/library/ProvisionerRepositoryImpl.kt | 0 .../java/no/nordicsemi/wifi/provisioner/library/Resource.kt | 0 .../wifi/provisioner/library/domain/AuthModeDomain.kt | 0 .../nordicsemi/wifi/provisioner/library/domain/BandDomain.kt | 0 .../wifi/provisioner/library/domain/ConnectionInfoDomain.kt | 0 .../wifi/provisioner/library/domain/DeviceStatusDomain.kt | 0 .../wifi/provisioner/library/domain/ScanParamsDomain.kt | 0 .../wifi/provisioner/library/domain/ScanRecordDomain.kt | 0 .../nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt | 0 .../wifi/provisioner/library/domain/ToDomainMapper.kt | 0 .../wifi/provisioner/library/domain/VersionDomain.kt | 0 .../wifi/provisioner/library/domain/WifiConfigDomain.kt | 0 .../library/domain/WifiConnectionFailureReasonDomain.kt | 0 .../provisioner/library/domain/WifiConnectionStateDomain.kt | 0 .../wifi/provisioner/library/domain/WifiInfoDomain.kt | 0 .../wifi/provisioner/library/internal/BleManagerStatus.kt | 0 .../provisioner/library/internal/ByteArrayReadResponse.kt | 0 .../provisioner/library/internal/ConnectionObserverAdapter.kt | 0 .../library/internal/NotificationTimeoutException.kt | 0 .../provisioner/library/internal/ProvisionerBleManager.kt | 0 .../provisioner/library/internal/ResponseErrorException.kt | 0 settings.gradle.kts | 4 ++-- 38 files changed, 5 insertions(+), 4 deletions(-) rename {lib_proto => lib/ble/proto}/.gitignore (100%) rename {lib_proto => lib/ble/proto}/build.gradle.kts (100%) rename {lib_proto => lib/ble/proto}/module-rules.pro (100%) rename {lib_proto => lib/ble/proto}/src/main/AndroidManifest.xml (100%) rename {lib_proto => lib/ble/proto}/src/main/proto/common.proto (100%) rename {lib_proto => lib/ble/proto}/src/main/proto/request.proto (100%) rename {lib_proto => lib/ble/proto}/src/main/proto/response.proto (100%) rename {lib_proto => lib/ble/proto}/src/main/proto/result.proto (100%) rename {lib_proto => lib/ble/proto}/src/main/proto/version.proto (100%) rename {lib_provisioner => lib/ble/provisioner}/.gitignore (100%) rename {lib_provisioner => lib/ble/provisioner}/build.gradle.kts (97%) rename {lib_provisioner => lib/ble/provisioner}/module-rules.pro (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/AndroidManifest.xml (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt (98%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt (100%) rename {lib_provisioner => lib/ble/provisioner}/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt (100%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a5da9776..d23d0607 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -39,7 +39,7 @@ android { } dependencies { - implementation(project(":lib_provisioner")) + implementation(project(":lib:ble:provisioner")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/lib_proto/.gitignore b/lib/ble/proto/.gitignore similarity index 100% rename from lib_proto/.gitignore rename to lib/ble/proto/.gitignore diff --git a/lib_proto/build.gradle.kts b/lib/ble/proto/build.gradle.kts similarity index 100% rename from lib_proto/build.gradle.kts rename to lib/ble/proto/build.gradle.kts diff --git a/lib_proto/module-rules.pro b/lib/ble/proto/module-rules.pro similarity index 100% rename from lib_proto/module-rules.pro rename to lib/ble/proto/module-rules.pro diff --git a/lib_proto/src/main/AndroidManifest.xml b/lib/ble/proto/src/main/AndroidManifest.xml similarity index 100% rename from lib_proto/src/main/AndroidManifest.xml rename to lib/ble/proto/src/main/AndroidManifest.xml diff --git a/lib_proto/src/main/proto/common.proto b/lib/ble/proto/src/main/proto/common.proto similarity index 100% rename from lib_proto/src/main/proto/common.proto rename to lib/ble/proto/src/main/proto/common.proto diff --git a/lib_proto/src/main/proto/request.proto b/lib/ble/proto/src/main/proto/request.proto similarity index 100% rename from lib_proto/src/main/proto/request.proto rename to lib/ble/proto/src/main/proto/request.proto diff --git a/lib_proto/src/main/proto/response.proto b/lib/ble/proto/src/main/proto/response.proto similarity index 100% rename from lib_proto/src/main/proto/response.proto rename to lib/ble/proto/src/main/proto/response.proto diff --git a/lib_proto/src/main/proto/result.proto b/lib/ble/proto/src/main/proto/result.proto similarity index 100% rename from lib_proto/src/main/proto/result.proto rename to lib/ble/proto/src/main/proto/result.proto diff --git a/lib_proto/src/main/proto/version.proto b/lib/ble/proto/src/main/proto/version.proto similarity index 100% rename from lib_proto/src/main/proto/version.proto rename to lib/ble/proto/src/main/proto/version.proto diff --git a/lib_provisioner/.gitignore b/lib/ble/provisioner/.gitignore similarity index 100% rename from lib_provisioner/.gitignore rename to lib/ble/provisioner/.gitignore diff --git a/lib_provisioner/build.gradle.kts b/lib/ble/provisioner/build.gradle.kts similarity index 97% rename from lib_provisioner/build.gradle.kts rename to lib/ble/provisioner/build.gradle.kts index 54657bdf..5455e719 100644 --- a/lib_provisioner/build.gradle.kts +++ b/lib/ble/provisioner/build.gradle.kts @@ -39,7 +39,7 @@ android { } dependencies { - implementation(project(":lib_proto")) + implementation(project(":lib:ble:proto")) implementation(libs.nordic.ble.common) implementation(libs.nordic.ble.ktx) diff --git a/lib_provisioner/module-rules.pro b/lib/ble/provisioner/module-rules.pro similarity index 100% rename from lib_provisioner/module-rules.pro rename to lib/ble/provisioner/module-rules.pro diff --git a/lib_provisioner/src/main/AndroidManifest.xml b/lib/ble/provisioner/src/main/AndroidManifest.xml similarity index 100% rename from lib_provisioner/src/main/AndroidManifest.xml rename to lib/ble/provisioner/src/main/AndroidManifest.xml diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt similarity index 98% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt index 46cb8878..c84b80f0 100644 --- a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt @@ -42,6 +42,7 @@ import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain import no.nordicsemi.wifi.provisioner.library.internal.ConnectionStatus import kotlinx.coroutines.flow.Flow import no.nordicsemi.wifi.provisioner.library.internal.ResponseErrorException +import no.nordicsemi.wifi.provisioner.library.internal.NotificationTimeoutException /** * A class responsible for establishing connection and maintaining communication with a nRF 7 device. diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt diff --git a/lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt similarity index 100% rename from lib_provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index fbff25a6..9ff60437 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -55,8 +55,8 @@ dependencyResolutionManagement { rootProject.name = "Android-nRF-Wifi-Provisioner" include(":app") -include(":lib_provisioner") -include(":lib_proto") +include(":lib:ble:provisioner") +include(":lib:ble:proto") //if (file('../Android-Common-Libraries').exists()) { // includeBuild('../Android-Common-Libraries') From 5b8f17b9232f09696e573a8f5c69600d6e4c731b Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 12 Feb 2024 15:30:45 +0100 Subject: [PATCH 002/101] More improvements to the library structure --- .../provisioning/home/view/HomeScreen1.kt | 178 ++++++++++++++++++ .../home/view/sections/ActionButtonSection.kt | 7 +- feature/ble/.gitignore | 1 + feature/ble/build.gradle.kts | 43 +++++ feature/ble/consumer-rules.pro | 0 feature/ble/proguard-rules.pro | 21 +++ .../ble/ExampleInstrumentedTest.kt | 24 +++ feature/ble/src/main/AndroidManifest.xml | 4 + .../wifi/provisioning/ble/ExampleUnitTest.kt | 17 ++ feature/softap/.gitignore | 1 + feature/softap/build.gradle.kts | 43 +++++ feature/softap/consumer-rules.pro | 0 feature/softap/proguard-rules.pro | 21 +++ .../softap/ExampleInstrumentedTest.kt | 24 +++ feature/softap/src/main/AndroidManifest.xml | 4 + .../provisioning/softap/ExampleUnitTest.kt | 17 ++ lib/ble/proto/src/main/AndroidManifest.xml | 4 +- lib/ble/proto/src/main/proto/common.proto | 2 +- lib/ble/proto/src/main/proto/request.proto | 2 +- lib/ble/proto/src/main/proto/response.proto | 2 +- lib/ble/proto/src/main/proto/result.proto | 2 +- lib/ble/proto/src/main/proto/version.proto | 2 +- .../provisioner/library/domain/ToApiMapper.kt | 8 +- .../library/domain/ToDomainMapper.kt | 18 +- .../library/internal/ProvisionerBleManager.kt | 16 +- settings.gradle.kts | 2 + 26 files changed, 429 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt create mode 100644 feature/ble/.gitignore create mode 100644 feature/ble/build.gradle.kts create mode 100644 feature/ble/consumer-rules.pro create mode 100644 feature/ble/proguard-rules.pro create mode 100644 feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt create mode 100644 feature/ble/src/main/AndroidManifest.xml create mode 100644 feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt create mode 100644 feature/softap/.gitignore create mode 100644 feature/softap/build.gradle.kts create mode 100644 feature/softap/consumer-rules.pro create mode 100644 feature/softap/proguard-rules.pro create mode 100644 feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt create mode 100644 feature/softap/src/main/AndroidManifest.xml create mode 100644 feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt new file mode 100644 index 00000000..65dd1e53 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioning.home.view + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import no.nordicsemi.android.wifi.provisioning.R +import no.nordicsemi.android.wifi.provisioning.home.view.components.LoggerIconAppBar +import no.nordicsemi.android.wifi.provisioning.home.view.sections.ActionButtonSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.DeviceSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioning.home.view.sections.PasswordSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.ProvisioningSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.StatusSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.UnprovisioningSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.VersionSection +import no.nordicsemi.android.wifi.provisioning.home.view.sections.VolatileMemorySwitch +import no.nordicsemi.android.wifi.provisioning.home.view.sections.WifiSection +import no.nordicsemi.android.wifi.provisioning.home.viewmodel.HomeViewModel +import no.nordicsemi.android.wifi.provisioning.password.PasswordDialog +import no.nordicsemi.android.wifi.provisioning.password.PasswordSetDialogEvent + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun HomeScreen1() { + val viewModel = hiltViewModel() + + val state by viewModel.state.collectAsStateWithLifecycle() + val onEvent: (HomeScreenViewEvent) -> Unit = { viewModel.onEvent(it) } + + Scaffold( + topBar = { + LoggerIconAppBar(stringResource(id = R.string.app_name)) { + viewModel.onEvent(OpenLoggerEvent) + } + }, + containerColor = MaterialTheme.colorScheme.surface, + ) { + Column(modifier = Modifier.padding(it)) { + Box(modifier = Modifier.weight(1f)) { + Content(state) { viewModel.onEvent(it) } + } + ActionButtonSection(state, onEvent) + } + } + + if (state.showPasswordDialog == true) { + PasswordDialog { + (it as? PasswordSetDialogEvent)?.let { onEvent(OnPasswordSelectedEvent(it.password)) } + onEvent(OnHidePasswordDialog) + } + } +} + +@Composable +private fun Content(state: HomeViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(horizontal = 16.dp) + ) { + Spacer(modifier = Modifier.size(12.dp)) + + DeviceSection(state.device, !state.isRunning(), onEvent) + + Spacer(modifier = Modifier.size(12.dp)) + + if (!state.isConnected && state.device != null) { + DisconnectedDeviceStatus() + } else { + state.version?.let { + SectionTitle(text = stringResource(id = R.string.section_device)) + + Spacer(modifier = Modifier.size(12.dp)) + + VersionSection(it) + } + + Spacer(modifier = Modifier.size(12.dp)) + + state.status?.let { StatusSection(it) } + + state.network?.let { + Spacer(modifier = Modifier.size(12.dp)) + + SectionTitle(text = stringResource(id = R.string.section_provisioning)) + + Spacer(modifier = Modifier.size(12.dp)) + + WifiSection(it, !state.isRunning(), onEvent) + } + + state.password?.let { + Spacer(modifier = Modifier.size(10.dp)) + + PasswordSection(!state.isRunning(), onEvent) + } + + state.network?.let { + VolatileMemorySwitch( + volatileMemory = state.persistentMemory, + enabled = !state.isRunning(), + onEvent = onEvent + ) + } + + state.provisioningStatus?.let { + SectionTitle(text = stringResource(id = R.string.section_status)) + + Spacer(modifier = Modifier.size(8.dp)) + + ProvisioningSection(it) + } + + state.unprovisioningStatus?.let { + SectionTitle(text = stringResource(id = R.string.section_status)) + + Spacer(modifier = Modifier.size(8.dp)) + + UnprovisioningSection(it) + } + } + } +} + +@Composable +private fun SectionTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) +} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt index cd11a720..c2952314 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt @@ -34,6 +34,7 @@ package no.nordicsemi.android.wifi.provisioning.home.view.sections import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme @@ -93,11 +94,7 @@ fun ActionButtonSection(viewEntity: HomeViewEntity, onEvent: (HomeScreenViewEven @Composable private fun ActionButton(text: String, onClick: () -> Unit) { - Box( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f)) - ) { + Box(modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)) { Button( onClick = onClick, modifier = Modifier diff --git a/feature/ble/.gitignore b/feature/ble/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/ble/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts new file mode 100644 index 00000000..2b5c4873 --- /dev/null +++ b/feature/ble/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioning.ble" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} \ No newline at end of file diff --git a/feature/ble/consumer-rules.pro b/feature/ble/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/ble/proguard-rules.pro b/feature/ble/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/ble/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt b/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..df3ebac1 --- /dev/null +++ b/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package no.nordicsemi.android.wifi.provisioning.ble + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("no.nordicsemi.android.wifi.provisioning.ble.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/feature/ble/src/main/AndroidManifest.xml b/feature/ble/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/feature/ble/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt b/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt new file mode 100644 index 00000000..03190228 --- /dev/null +++ b/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package no.nordicsemi.android.wifi.provisioning.ble + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/feature/softap/.gitignore b/feature/softap/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/softap/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts new file mode 100644 index 00000000..2865bb89 --- /dev/null +++ b/feature/softap/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioning.softap" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} \ No newline at end of file diff --git a/feature/softap/consumer-rules.pro b/feature/softap/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/softap/proguard-rules.pro b/feature/softap/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/softap/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt b/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..cbeff9b2 --- /dev/null +++ b/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package no.nordicsemi.android.wifi.provisioning.softap + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("no.nordicsemi.android.wifi.provisioning.softap.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/feature/softap/src/main/AndroidManifest.xml b/feature/softap/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/feature/softap/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt b/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt new file mode 100644 index 00000000..b6de196f --- /dev/null +++ b/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package no.nordicsemi.android.wifi.provisioning.softap + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/lib/ble/proto/src/main/AndroidManifest.xml b/lib/ble/proto/src/main/AndroidManifest.xml index 07fd1f83..d554f457 100644 --- a/lib/ble/proto/src/main/AndroidManifest.xml +++ b/lib/ble/proto/src/main/AndroidManifest.xml @@ -30,6 +30,4 @@ ~ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - - - \ No newline at end of file + \ No newline at end of file diff --git a/lib/ble/proto/src/main/proto/common.proto b/lib/ble/proto/src/main/proto/common.proto index 3c2e070d..59f1d3cb 100644 --- a/lib/ble/proto/src/main/proto/common.proto +++ b/lib/ble/proto/src/main/proto/common.proto @@ -1,7 +1,7 @@ syntax = "proto2"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning"; +option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; // Common ENUMs diff --git a/lib/ble/proto/src/main/proto/request.proto b/lib/ble/proto/src/main/proto/request.proto index 95bf223d..3c5fc4fe 100644 --- a/lib/ble/proto/src/main/proto/request.proto +++ b/lib/ble/proto/src/main/proto/request.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning"; +option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; // Requests diff --git a/lib/ble/proto/src/main/proto/response.proto b/lib/ble/proto/src/main/proto/response.proto index 3245ea33..395ae01c 100644 --- a/lib/ble/proto/src/main/proto/response.proto +++ b/lib/ble/proto/src/main/proto/response.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning"; +option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; // Responses diff --git a/lib/ble/proto/src/main/proto/result.proto b/lib/ble/proto/src/main/proto/result.proto index 55a6e84e..92833a81 100644 --- a/lib/ble/proto/src/main/proto/result.proto +++ b/lib/ble/proto/src/main/proto/result.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning"; +option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; // States are sent over Data Out characteristic diff --git a/lib/ble/proto/src/main/proto/version.proto b/lib/ble/proto/src/main/proto/version.proto index 59f33c65..63deb046 100644 --- a/lib/ble/proto/src/main/proto/version.proto +++ b/lib/ble/proto/src/main/proto/version.proto @@ -1,7 +1,7 @@ syntax = "proto2"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning"; +option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; /* Response payload for returned from Version characteristic. */ message Info { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt index 22f0376d..42abd274 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt @@ -31,10 +31,10 @@ package no.nordicsemi.wifi.provisioner.library.domain -import no.nordicsemi.android.wifi.provisioning.AuthMode -import no.nordicsemi.android.wifi.provisioning.Band -import no.nordicsemi.android.wifi.provisioning.WifiConfig -import no.nordicsemi.android.wifi.provisioning.WifiInfo +import no.nordicsemi.android.wifi.provisioning.ble.proto.AuthMode +import no.nordicsemi.android.wifi.provisioning.ble.proto.Band +import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiInfo import okio.ByteString.Companion.toByteString internal fun WifiConfigDomain.toApi(): WifiConfig { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt index e4e4c5f6..0f0f9c1d 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt @@ -32,15 +32,15 @@ package no.nordicsemi.wifi.provisioner.library.domain import android.util.Log -import no.nordicsemi.android.wifi.provisioning.AuthMode -import no.nordicsemi.android.wifi.provisioning.Band -import no.nordicsemi.android.wifi.provisioning.ConnectionFailureReason -import no.nordicsemi.android.wifi.provisioning.ConnectionInfo -import no.nordicsemi.android.wifi.provisioning.ConnectionState -import no.nordicsemi.android.wifi.provisioning.DeviceStatus -import no.nordicsemi.android.wifi.provisioning.ScanParams -import no.nordicsemi.android.wifi.provisioning.ScanRecord -import no.nordicsemi.android.wifi.provisioning.WifiInfo +import no.nordicsemi.android.wifi.provisioning.ble.proto.AuthMode +import no.nordicsemi.android.wifi.provisioning.ble.proto.Band +import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionFailureReason +import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionInfo +import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionState +import no.nordicsemi.android.wifi.provisioning.ble.proto.DeviceStatus +import no.nordicsemi.android.wifi.provisioning.ble.proto.ScanParams +import no.nordicsemi.android.wifi.provisioning.ble.proto.ScanRecord +import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiInfo import okio.ByteString private const val TAG = "DOMAIN-MAPPER" diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt index da2eb0e0..0fcd157f 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt @@ -51,14 +51,14 @@ import no.nordicsemi.android.ble.ktx.asValidResponseFlow import no.nordicsemi.android.ble.ktx.suspend import no.nordicsemi.android.ble.ktx.suspendForValidResponse import no.nordicsemi.android.common.logger.NordicLogger -import no.nordicsemi.android.wifi.provisioning.DeviceStatus -import no.nordicsemi.android.wifi.provisioning.Info -import no.nordicsemi.android.wifi.provisioning.OpCode -import no.nordicsemi.android.wifi.provisioning.Request -import no.nordicsemi.android.wifi.provisioning.Response -import no.nordicsemi.android.wifi.provisioning.Result -import no.nordicsemi.android.wifi.provisioning.Status -import no.nordicsemi.android.wifi.provisioning.WifiConfig +import no.nordicsemi.android.wifi.provisioning.ble.proto.Result +import no.nordicsemi.android.wifi.provisioning.ble.proto.DeviceStatus +import no.nordicsemi.android.wifi.provisioning.ble.proto.Info +import no.nordicsemi.android.wifi.provisioning.ble.proto.OpCode +import no.nordicsemi.android.wifi.provisioning.ble.proto.Request +import no.nordicsemi.android.wifi.provisioning.ble.proto.Response +import no.nordicsemi.android.wifi.provisioning.ble.proto.Status +import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiConfig import java.util.* val PROVISIONING_SERVICE_UUID: UUID = UUID.fromString("14387800-130c-49e7-b877-2881c89cb258") diff --git a/settings.gradle.kts b/settings.gradle.kts index 9ff60437..f104a259 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -55,6 +55,8 @@ dependencyResolutionManagement { rootProject.name = "Android-nRF-Wifi-Provisioner" include(":app") +include(":feature:ble") +include(":feature:softap") include(":lib:ble:provisioner") include(":lib:ble:proto") From 854e239be055d89dbe8fe3f0c897e67b7c29a284 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 13 Feb 2024 14:46:08 +0100 Subject: [PATCH 003/101] Finally, some kind og working state! --- app/build.gradle.kts | 11 +- app/src/main/AndroidManifest.xml | 4 +- .../HomeDestination.kt | 8 +- .../MainActivity.kt | 4 +- .../WifiProvisionerApplication.kt | 2 +- .../home/view/HomeScreen.kt | 36 ++-- .../home/view/HomeScreenViewEvent.kt | 22 +-- .../home/view/HomeViewEntity.kt | 20 +- .../home/view/UiMapper.kt | 12 +- .../home/view/components/DataItem.kt | 4 +- .../home/view/components/ErrorText.kt | 2 +- .../home/view/components/LoadingItem.kt | 3 +- .../view/components/PlaceholderModifier.kt | 2 +- .../home/view/components/TopAppBar.kt | 23 +-- .../home/view/sections/ActionButtonSection.kt | 22 +-- .../home/view/sections/DeviceSection.kt | 20 +- .../view/sections/DisconnectedDeviceStatus.kt | 6 +- .../home/view/sections/PasswordSection.kt | 10 +- .../home/view/sections/ProvisioningSection.kt | 20 +- .../home/view/sections/StatusSection.kt | 24 +-- .../view/sections/UnprovisioningSection.kt | 18 +- .../home/view/sections/VersionSection.kt | 20 +- .../view/sections/VolatileMemorySwitch.kt | 8 +- .../home/view/sections/WifiSection.kt | 16 +- .../home/viewmodel/HomeViewModel.kt | 56 +++--- .../password/PasswordDialog.kt | 4 +- .../password/PasswordDialogEvent.kt | 2 +- .../repository/PasswordManager.kt | 2 +- .../ProvisionerResourceRepository.kt | 23 +-- .../repository/RepositoryModule.kt | 4 +- .../scanner/ProvisioningData.kt | 22 ++- .../ProvisioningScannerDestinations.kt | 31 +-- .../scanner/ProvisioningSection.kt | 4 +- .../wifi/view/SelectChannelDialog.kt | 8 +- .../wifi/view/WifiLoadingItem.kt | 4 +- .../wifi/view/WifiScannerScreen.kt | 16 +- .../wifi/view/WifiScannerViewEntity.kt | 8 +- .../wifi/view/WifiScannerViewEvent.kt | 4 +- .../wifi/view/WifiSortView.kt | 14 +- .../wifi/viewmodel/WifiAggregator.kt | 8 +- .../wifi/viewmodel/WifiScannerViewModel.kt | 24 +-- .../wifi/viewmodel/WifiSortOption.kt | 2 +- .../provisioning/home/view/HomeScreen1.kt | 178 ------------------ .../provisioning/scanner/view/FilterView.kt | 64 ------- .../scanner/view/ProvisionerScannerAppBar.kt | 94 --------- .../scanner/view/ProvisionerScannerScreen.kt | 141 -------------- .../scanner/view/ScanEmptyView.kt | 105 ----------- .../scanner/viewmodel/ProvisionerViewModel.kt | 81 -------- build.gradle.kts | 2 +- feature/ble/build.gradle.kts | 95 ++++++---- .../ble/ExampleInstrumentedTest.kt | 24 --- .../wifi/provisioning/ble/ExampleUnitTest.kt | 17 -- feature/softap/build.gradle.kts | 94 +++++---- .../softap/ExampleInstrumentedTest.kt | 24 --- .../provisioning/softap/ExampleUnitTest.kt | 17 -- gradle/wrapper/gradle-wrapper.properties | 37 +--- lib/ble/proto/build.gradle.kts | 2 +- lib/ble/proto/src/main/proto/common.proto | 2 +- lib/ble/proto/src/main/proto/request.proto | 2 +- lib/ble/proto/src/main/proto/response.proto | 2 +- lib/ble/proto/src/main/proto/result.proto | 2 +- lib/ble/proto/src/main/proto/version.proto | 2 +- lib/ble/provisioner/build.gradle.kts | 7 +- .../wifi/provisioner/ble}/Ext.kt | 4 +- .../provisioner/ble}/ProvisionerRepository.kt | 23 +-- .../ble}/ProvisionerRepositoryImpl.kt | 35 ++-- .../wifi/provisioner/ble}/Resource.kt | 2 +- .../provisioner/ble}/domain/AuthModeDomain.kt | 2 +- .../provisioner/ble}/domain/BandDomain.kt | 2 +- .../ble}/domain/ConnectionInfoDomain.kt | 2 +- .../ble}/domain/DeviceStatusDomain.kt | 2 +- .../ble}/domain/ScanParamsDomain.kt | 2 +- .../ble}/domain/ScanRecordDomain.kt | 2 +- .../provisioner/ble}/domain/ToApiMapper.kt | 10 +- .../provisioner/ble}/domain/ToDomainMapper.kt | 20 +- .../provisioner/ble}/domain/VersionDomain.kt | 2 +- .../ble}/domain/WifiConfigDomain.kt | 2 +- .../WifiConnectionFailureReasonDomain.kt | 2 +- .../ble}/domain/WifiConnectionStateDomain.kt | 2 +- .../provisioner/ble}/domain/WifiInfoDomain.kt | 2 +- .../ble}/internal/BleManagerStatus.kt | 2 +- .../ble}/internal/ByteArrayReadResponse.kt | 2 +- .../internal/ConnectionObserverAdapter.kt | 2 +- .../internal/NotificationTimeoutException.kt | 2 +- .../ble}/internal/ProvisionerBleManager.kt | 103 +++++----- .../ble}/internal/ResponseErrorException.kt | 2 +- lib/softap/.gitignore | 1 + lib/softap/build.gradle.kts | 8 + lib/softap/consumer-rules.pro | 0 lib/softap/proguard-rules.pro | 21 +++ lib/softap/src/main/AndroidManifest.xml | 4 + settings.gradle.kts | 3 +- 92 files changed, 538 insertions(+), 1273 deletions(-) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/HomeDestination.kt (89%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/MainActivity.kt (94%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/WifiProvisionerApplication.kt (97%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/HomeScreen.kt (80%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/HomeScreenViewEvent.kt (73%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/HomeViewEntity.kt (83%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/UiMapper.kt (90%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/components/DataItem.kt (98%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/components/ErrorText.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/components/LoadingItem.kt (97%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/components/PlaceholderModifier.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/components/TopAppBar.kt (71%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/ActionButtonSection.kt (82%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/DeviceSection.kt (87%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/DisconnectedDeviceStatus.kt (90%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/PasswordSection.kt (85%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/ProvisioningSection.kt (92%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/StatusSection.kt (88%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/UnprovisioningSection.kt (81%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/VersionSection.kt (78%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/VolatileMemorySwitch.kt (91%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/view/sections/WifiSection.kt (81%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/home/viewmodel/HomeViewModel.kt (78%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/password/PasswordDialog.kt (97%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/password/PasswordDialogEvent.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/repository/PasswordManager.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/repository/ProvisionerResourceRepository.kt (83%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/repository/RepositoryModule.kt (94%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/scanner/ProvisioningData.kt (74%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/scanner/ProvisioningScannerDestinations.kt (70%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/scanner/ProvisioningSection.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/SelectChannelDialog.kt (94%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/WifiLoadingItem.kt (96%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/WifiScannerScreen.kt (93%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/WifiScannerViewEntity.kt (90%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/WifiScannerViewEvent.kt (93%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/view/WifiSortView.kt (89%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/viewmodel/WifiAggregator.kt (90%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/viewmodel/WifiScannerViewModel.kt (81%) rename app/src/main/java/no/nordicsemi/android/wifi/{provisioning => provisioner}/wifi/viewmodel/WifiSortOption.kt (96%) delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/FilterView.kt delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerAppBar.kt delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerScreen.kt delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ScanEmptyView.kt delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/viewmodel/ProvisionerViewModel.kt delete mode 100644 feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt delete mode 100644 feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt delete mode 100644 feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt delete mode 100644 feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/Ext.kt (93%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/ProvisionerRepository.kt (88%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/ProvisionerRepositoryImpl.kt (74%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/Resource.kt (97%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/AuthModeDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/BandDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/ConnectionInfoDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/DeviceStatusDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/ScanParamsDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/ScanRecordDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/ToApiMapper.kt (89%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/ToDomainMapper.kt (87%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/VersionDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/WifiConfigDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/WifiConnectionFailureReasonDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/WifiConnectionStateDomain.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/domain/WifiInfoDomain.kt (97%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/BleManagerStatus.kt (97%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/ByteArrayReadResponse.kt (97%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/ConnectionObserverAdapter.kt (98%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/NotificationTimeoutException.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/ProvisionerBleManager.kt (75%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/{wifi/provisioner/library => android/wifi/provisioner/ble}/internal/ResponseErrorException.kt (96%) create mode 100644 lib/softap/.gitignore create mode 100644 lib/softap/build.gradle.kts create mode 100644 lib/softap/consumer-rules.pro create mode 100644 lib/softap/proguard-rules.pro create mode 100644 lib/softap/src/main/AndroidManifest.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d23d0607..b1e6bba1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -35,11 +35,16 @@ plugins { } android { - namespace = "no.nordicsemi.android.wifi.provisioning" + namespace = "no.nordicsemi.android.wifi.provisioner.app" + defaultConfig { + applicationId = "no.nordicsemi.android.wifi.provisioning" + } } dependencies { implementation(project(":lib:ble:provisioner")) + implementation(project(":feature:ble")) + implementation(project(":feature:softap")) implementation(libs.androidx.lifecycle.runtime.compose) @@ -58,9 +63,9 @@ dependencies { implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) - implementation(libs.nordic.uiscanner) implementation(libs.nordic.uilogger) - implementation(libs.nordic.permission) + implementation(libs.nordic.blek.uiscanner) + implementation(libs.nordic.permissions.ble) implementation(libs.accompanist.placeholder) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4aee587d..ef4ed705 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,7 +34,7 @@ xmlns:tools="http://schemas.android.com/tools"> diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/HomeDestination.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt similarity index 89% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/HomeDestination.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt index ac98746a..9b3b8598 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/HomeDestination.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt @@ -29,14 +29,14 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning +package no.nordicsemi.android.wifi.provisioner import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreen -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiScannerScreen +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreen +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerScreen val HomeDestinationId = createSimpleDestination("home-destination") val WifiScannerId = createDestination("wifi-scanner-destination") diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/MainActivity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt similarity index 94% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/MainActivity.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt index 0e8d22bf..6f9c383c 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/MainActivity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning +package no.nordicsemi.android.wifi.provisioner import android.os.Bundle import androidx.activity.compose.setContent @@ -40,7 +40,7 @@ import dagger.hilt.android.AndroidEntryPoint import no.nordicsemi.android.common.navigation.NavigationView import no.nordicsemi.android.common.theme.NordicActivity import no.nordicsemi.android.common.theme.NordicTheme -import no.nordicsemi.android.wifi.provisioning.scanner.ProvisionerScannerDestination +import no.nordicsemi.android.wifi.provisioner.scanner.ProvisionerScannerDestination @AndroidEntryPoint class MainActivity : NordicActivity() { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/WifiProvisionerApplication.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/WifiProvisionerApplication.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt index fb6ce46f..8e1edd4a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/WifiProvisionerApplication.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning +package no.nordicsemi.android.wifi.provisioner import android.app.Application import dagger.hilt.android.HiltAndroidApp diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt similarity index 80% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt index e9f6637b..7039e3b1 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view +package no.nordicsemi.android.wifi.provisioner.home.view import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -38,7 +38,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -49,23 +48,22 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoggerIconAppBar -import no.nordicsemi.android.wifi.provisioning.home.view.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.DeviceSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioning.home.view.sections.PasswordSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.ProvisioningSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.StatusSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.VersionSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.VolatileMemorySwitch -import no.nordicsemi.android.wifi.provisioning.home.view.sections.WifiSection -import no.nordicsemi.android.wifi.provisioning.home.viewmodel.HomeViewModel -import no.nordicsemi.android.wifi.provisioning.password.PasswordDialog -import no.nordicsemi.android.wifi.provisioning.password.PasswordSetDialogEvent - -@OptIn(ExperimentalMaterial3Api::class) +import no.nordicsemi.android.wifi.provisioner.home.view.components.LoggerIconAppBar +import no.nordicsemi.android.wifi.provisioner.home.view.sections.ActionButtonSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.DeviceSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioner.home.view.sections.PasswordSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.StatusSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.UnprovisioningSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.VersionSection +import no.nordicsemi.android.wifi.provisioner.home.view.sections.VolatileMemorySwitch +import no.nordicsemi.android.wifi.provisioner.home.view.sections.WifiSection +import no.nordicsemi.android.wifi.provisioner.home.viewmodel.HomeViewModel +import no.nordicsemi.android.wifi.provisioner.password.PasswordDialog +import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent +import no.nordicsemi.android.wifi.provisioner.app.R + @Composable fun HomeScreen() { val viewModel = hiltViewModel() diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreenViewEvent.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt similarity index 73% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreenViewEvent.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt index 0ce6901e..0be30ff4 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreenViewEvent.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt @@ -29,28 +29,28 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view +package no.nordicsemi.android.wifi.provisioner.home.view sealed interface HomeScreenViewEvent -object OnSelectDeviceClickEvent : HomeScreenViewEvent +data object OnSelectDeviceClickEvent : HomeScreenViewEvent -object OnFinishedEvent : HomeScreenViewEvent +data object OnFinishedEvent : HomeScreenViewEvent -object OnProvisionNextDeviceEvent : HomeScreenViewEvent +data object OnProvisionNextDeviceEvent : HomeScreenViewEvent -object OnSelectWifiEvent : HomeScreenViewEvent +data object OnSelectWifiEvent : HomeScreenViewEvent -object OnShowPasswordDialog : HomeScreenViewEvent +data object OnShowPasswordDialog : HomeScreenViewEvent -object OnHidePasswordDialog : HomeScreenViewEvent +data object OnHidePasswordDialog : HomeScreenViewEvent data class OnPasswordSelectedEvent(val password: String) : HomeScreenViewEvent -object OnProvisionClickEvent : HomeScreenViewEvent +data object OnProvisionClickEvent : HomeScreenViewEvent -object OpenLoggerEvent : HomeScreenViewEvent +data object OpenLoggerEvent : HomeScreenViewEvent -object OnUnprovisionEvent : HomeScreenViewEvent +data object OnUnprovisionEvent : HomeScreenViewEvent -object OnVolatileMemoryChangedEvent : HomeScreenViewEvent +data object OnVolatileMemoryChangedEvent : HomeScreenViewEvent diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeViewEntity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt similarity index 83% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeViewEntity.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt index e7d35530..76c9c354 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeViewEntity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt @@ -29,19 +29,19 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view +package no.nordicsemi.android.wifi.provisioner.home.view -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.Success -import no.nordicsemi.wifi.provisioner.library.domain.DeviceStatusDomain -import no.nordicsemi.wifi.provisioner.library.domain.VersionDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain +import no.nordicsemi.android.kotlin.ble.core.ServerDevice +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain data class HomeViewEntity( - val device: DiscoveredBluetoothDevice? = null, + val device: ServerDevice? = null, val version: Resource? = null, val status: Resource? = null, val network: WifiData? = null, diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/UiMapper.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt similarity index 90% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/UiMapper.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt index 2fdf7a53..1f2a677d 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/UiMapper.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt @@ -29,16 +29,16 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view +package no.nordicsemi.android.wifi.provisioner.home.view import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.wifi.provisioner.library.domain.AuthModeDomain -import no.nordicsemi.wifi.provisioner.library.domain.BandDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionFailureReasonDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.BandDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureReasonDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain @DrawableRes internal fun WifiConnectionStateDomain?.toIcon(): Int { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/DataItem.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/DataItem.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt index 0cab9902..2a8659b4 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/DataItem.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.components +package no.nordicsemi.android.wifi.provisioner.home.view.components import androidx.annotation.DrawableRes import androidx.compose.animation.AnimatedVisibility @@ -63,7 +63,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R +import no.nordicsemi.android.wifi.provisioner.app.R @Composable fun ErrorDataItem( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/ErrorText.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/ErrorText.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt index eddd7cba..5c2c8ec7 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/ErrorText.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.components +package no.nordicsemi.android.wifi.provisioner.home.view.components import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/LoadingItem.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/LoadingItem.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/LoadingItem.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/LoadingItem.kt index 54e92e2f..1ae29c84 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/LoadingItem.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/LoadingItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.components +package no.nordicsemi.android.wifi.provisioner.home.view.components import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -52,6 +52,7 @@ import androidx.compose.ui.unit.dp @Composable fun LoadingItem(modifier: Modifier = Modifier) { Row( + modifier = modifier, verticalAlignment = Alignment.CenterVertically, ) { Box( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/PlaceholderModifier.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/PlaceholderModifier.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/PlaceholderModifier.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/PlaceholderModifier.kt index f89eb733..4e09a1bc 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/PlaceholderModifier.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/PlaceholderModifier.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.components +package no.nordicsemi.android.wifi.provisioner.home.view.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/TopAppBar.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt similarity index 71% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/TopAppBar.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt index a31647d1..beb1020c 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/components/TopAppBar.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt @@ -29,20 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.components +package no.nordicsemi.android.wifi.provisioner.home.view.components -import androidx.compose.foundation.layout.size import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp +import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar -import no.nordicsemi.android.common.ui.logger.R as loggerR @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -59,14 +51,9 @@ fun LoggerIconAppBar(text: String, onLoggerClick: () -> Unit) { NordicAppBar( text = text, actions = { - IconButton(onClick = { onLoggerClick() }) { - Icon( - painterResource(id = loggerR.drawable.ic_logger), - contentDescription = stringResource(id = loggerR.string.open_logger), - tint = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier.size(24.dp) - ) - } + LoggerAppBarIcon( + onClick = onLoggerClick + ) } ) } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt similarity index 82% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt index c2952314..505f77a7 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ActionButtonSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt @@ -29,30 +29,28 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.HomeViewEntity -import no.nordicsemi.android.wifi.provisioning.home.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioning.home.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.HomeViewEntity +import no.nordicsemi.android.wifi.provisioner.home.view.OnFinishedEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionClickEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionNextDeviceEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.home.view.OnUnprovisionEvent @Composable fun ActionButtonSection(viewEntity: HomeViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DeviceSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt similarity index 87% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DeviceSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt index 88f81775..3011bee8 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DeviceSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -52,16 +52,16 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.NordicTheme import no.nordicsemi.android.common.theme.view.NordicText -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice -import no.nordicsemi.android.wifi.provisioning.BuildConfig -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnSelectDeviceClickEvent -import no.nordicsemi.android.wifi.provisioning.home.view.components.ClickableDataItem +import no.nordicsemi.android.kotlin.ble.core.ServerDevice +import no.nordicsemi.android.wifi.provisioner.app.BuildConfig +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectDeviceClickEvent +import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable internal fun DeviceSection( - device: DiscoveredBluetoothDevice?, + device: ServerDevice?, isEditable: Boolean = false, onEvent: (HomeScreenViewEvent) -> Unit ) { @@ -74,13 +74,13 @@ internal fun DeviceSection( @Composable private fun BluetoothDevice( - device: DiscoveredBluetoothDevice, + device: ServerDevice, isEditable: Boolean = false, onEvent: (HomeScreenViewEvent) -> Unit ) { ClickableDataItem( iconRes = R.drawable.ic_phone_ok, - title = device.displayNameOrAddress, + title = device.name ?: device.address, isEditable = isEditable, description = device.address ) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DisconnectedDeviceStatus.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt similarity index 90% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DisconnectedDeviceStatus.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt index 25e5d8f0..154ede5a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/DisconnectedDeviceStatus.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt @@ -29,12 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem @Composable fun DisconnectedDeviceStatus() { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/PasswordSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt similarity index 85% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/PasswordSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt index 0b3d149d..664bba79 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/PasswordSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt @@ -29,14 +29,14 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioning.home.view.components.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable internal fun PasswordSection(isEditable: Boolean = false, onEvent: (HomeScreenViewEvent) -> Unit) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ProvisioningSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt similarity index 92% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ProvisioningSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt index e585a6b9..59c4ff46 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/ProvisioningSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -42,15 +42,15 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoadingItem -import no.nordicsemi.android.wifi.provisioning.home.view.toDisplayString -import no.nordicsemi.wifi.provisioner.library.Error -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.Success -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem +import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.Error +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.common.theme.view.ProgressItem import no.nordicsemi.android.common.theme.view.ProgressItemStatus diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/StatusSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt similarity index 88% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/StatusSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt index a0793a6f..d82f01b9 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/StatusSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -41,17 +41,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoadingItem -import no.nordicsemi.android.wifi.provisioning.home.view.toDisplayString -import no.nordicsemi.android.wifi.provisioning.home.view.toIcon -import no.nordicsemi.wifi.provisioner.library.Error -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.Success -import no.nordicsemi.wifi.provisioner.library.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem +import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.home.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.Error +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain @Composable internal fun StatusSection(status: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/UnprovisioningSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt similarity index 81% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/UnprovisioningSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt index f4004dbe..8fe54857 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/UnprovisioningSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt @@ -29,21 +29,21 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoadingItem -import no.nordicsemi.wifi.provisioner.library.Error -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.Success +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem +import no.nordicsemi.android.wifi.provisioner.ble.Error +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.Success @Composable internal fun UnprovisioningSection(status: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VersionSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt similarity index 78% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VersionSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt index 64638002..4fb6d9b2 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VersionSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt @@ -29,19 +29,19 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoadingItem -import no.nordicsemi.wifi.provisioner.library.Error -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.Success -import no.nordicsemi.wifi.provisioner.library.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem +import no.nordicsemi.android.wifi.provisioner.ble.Error +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain @Composable internal fun VersionSection(version: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VolatileMemorySwitch.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt similarity index 91% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VolatileMemorySwitch.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt index f5ac22b6..f09c8ead 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/VolatileMemorySwitch.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -46,9 +46,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnVolatileMemoryChangedEvent @Composable fun VolatileMemorySwitch( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/WifiSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt similarity index 81% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/WifiSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt index 3645586e..91ea103a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/sections/WifiSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt @@ -29,18 +29,18 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.view.sections +package no.nordicsemi.android.wifi.provisioner.home.view.sections import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioning.home.view.components.ClickableDataItem -import no.nordicsemi.android.wifi.provisioning.home.view.toIcon -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.home.view.toIcon +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain @Composable internal fun WifiSection( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/viewmodel/HomeViewModel.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt similarity index 78% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/viewmodel/HomeViewModel.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt index a05ab7e7..3b0ad88b 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt @@ -29,13 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.home.viewmodel +package no.nordicsemi.android.wifi.provisioner.home.viewmodel -import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -47,29 +45,29 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice -import no.nordicsemi.android.wifi.provisioning.WifiScannerId -import no.nordicsemi.android.wifi.provisioning.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioning.home.view.HomeViewEntity -import no.nordicsemi.android.wifi.provisioning.home.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnHidePasswordDialog -import no.nordicsemi.android.wifi.provisioning.home.view.OnPasswordSelectedEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnSelectDeviceClickEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioning.home.view.OnUnprovisionEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OnVolatileMemoryChangedEvent -import no.nordicsemi.android.wifi.provisioning.home.view.OpenLoggerEvent -import no.nordicsemi.android.wifi.provisioning.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioning.scanner.ProvisionerScannerDestinationId -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Success -import no.nordicsemi.wifi.provisioner.library.domain.WifiConfigDomain -import no.nordicsemi.wifi.provisioner.library.internal.ConnectionStatus -import no.nordicsemi.wifi.provisioner.library.launchWithCatch +import no.nordicsemi.android.kotlin.ble.core.RealServerDevice +import no.nordicsemi.android.wifi.provisioner.WifiScannerId +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus +import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch +import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.home.view.HomeViewEntity +import no.nordicsemi.android.wifi.provisioner.home.view.OnFinishedEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnHidePasswordDialog +import no.nordicsemi.android.wifi.provisioner.home.view.OnPasswordSelectedEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionClickEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionNextDeviceEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectDeviceClickEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.home.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.home.view.OpenLoggerEvent +import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository +import no.nordicsemi.android.wifi.provisioner.scanner.ProvisionerScannerDestinationId +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData import javax.inject.Inject @HiltViewModel @@ -88,7 +86,7 @@ class HomeViewModel @Inject constructor( init { navigationManager.resultFrom(ProvisionerScannerDestinationId) .mapNotNull { it as? NavigationResult.Success } - .onEach { installBluetoothDevice(it.value) } + .onEach { installBluetoothDevice(it.value as RealServerDevice) } .launchIn(viewModelScope) navigationManager.resultFrom(WifiScannerId) @@ -109,7 +107,7 @@ class HomeViewModel @Inject constructor( OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() OnShowPasswordDialog -> showPasswordDialog() - OpenLoggerEvent -> repository.openLogger() + OpenLoggerEvent -> {}//repository.openLogger() OnUnprovisionEvent -> cancelConfig() OnProvisionNextDeviceEvent -> provisionNextDevice() OnVolatileMemoryChangedEvent -> onVolatileMemoryChangeEvent() @@ -181,7 +179,7 @@ class HomeViewModel @Inject constructor( ) } - private fun installBluetoothDevice(device: DiscoveredBluetoothDevice) { + private fun installBluetoothDevice(device: RealServerDevice) { _state.value = HomeViewEntity(device = device, version = Loading()) viewModelScope.launchWithCatch { release() diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialog.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialog.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt index e52483e9..bf1ad279 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialog.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.password +package no.nordicsemi.android.wifi.provisioner.password import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Visibility @@ -47,7 +47,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation -import no.nordicsemi.android.wifi.provisioning.R +import no.nordicsemi.android.wifi.provisioner.app.R @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialogEvent.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialogEvent.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialogEvent.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialogEvent.kt index 3feb1078..e716e8d8 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/password/PasswordDialogEvent.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialogEvent.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.password +package no.nordicsemi.android.wifi.provisioner.password sealed interface PasswordDialogEvent diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/PasswordManager.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/PasswordManager.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt index 003cad3c..eefd9cc2 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/PasswordManager.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.repository +package no.nordicsemi.android.wifi.provisioner.repository import javax.inject.Inject diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/ProvisionerResourceRepository.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt similarity index 83% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/ProvisionerResourceRepository.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt index e9688a36..61bc842e 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/ProvisionerResourceRepository.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.repository +package no.nordicsemi.android.wifi.provisioner.repository import android.bluetooth.BluetoothDevice import kotlinx.coroutines.flow.Flow @@ -37,15 +37,14 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart -import no.nordicsemi.wifi.provisioner.library.ProvisionerRepository -import no.nordicsemi.wifi.provisioner.library.Resource -import no.nordicsemi.wifi.provisioner.library.domain.DeviceStatusDomain -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain -import no.nordicsemi.wifi.provisioner.library.domain.VersionDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConfigDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain -import no.nordicsemi.wifi.provisioner.library.internal.ConnectionStatus -import javax.inject.Inject +import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository +import no.nordicsemi.android.wifi.provisioner.ble.Resource +import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus class ProvisionerResourceRepository( val repository: ProvisionerRepository @@ -95,10 +94,6 @@ class ProvisionerResourceRepository( repository.release() } - fun openLogger() { - repository.openLogger() - } - private fun runTask(block: suspend () -> T): Flow> { return flow { emit(Resource.createSuccess(block())) } .onStart { emit(Resource.createLoading()) } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/RepositoryModule.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/RepositoryModule.kt similarity index 94% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/RepositoryModule.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/RepositoryModule.kt index 63dc529b..f86d2c2c 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/repository/RepositoryModule.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/RepositoryModule.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.repository +package no.nordicsemi.android.wifi.provisioner.repository import android.content.Context import dagger.Module @@ -37,7 +37,7 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import no.nordicsemi.wifi.provisioner.library.ProvisionerRepository +import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository @Module @InstallIn(SingletonComponent::class) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningData.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt similarity index 74% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningData.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt index 5339519e..e4be2070 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningData.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt @@ -29,10 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.scanner +package no.nordicsemi.android.wifi.provisioner.scanner import android.os.ParcelUuid -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice +import no.nordicsemi.android.common.core.DataByteArray +import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResultData +import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResults import no.nordicsemi.android.support.v18.scanner.ScanResult import java.util.* @@ -42,23 +44,23 @@ internal data class ProvisioningData( val isConnected: Boolean, val rssi: Int ) { - constructor(data: ByteArray) : this( - version = data[0].toInt(), + constructor(data: DataByteArray) : this( + version = data.value[0].toInt(), // 2 bytes reserved for flags - isProvisioned = data[1].toInt() and 0x01 != 0, - isConnected = data[1].toInt() and 0x02 != 0, - rssi = data[3].toInt() + isProvisioned = data.value[1].toInt() and 0x01 != 0, + isConnected = data.value[1].toInt() and 0x02 != 0, + rssi = data.value[3].toInt() ) companion object { private val parcelUuid = ParcelUuid(UUID.fromString("14387800-130c-49e7-b877-2881c89cb258")) - fun create(scanResult: ScanResult) = scanResult.scanRecord?.serviceData + fun create(scanResult: BleScanResultData) = scanResult.scanRecord?.serviceData ?.get(parcelUuid) ?.let { ProvisioningData(it) } } } -internal fun DiscoveredBluetoothDevice.provisioningData(): ProvisioningData? { - return scanResult?.let { ProvisioningData.create(it) } +internal fun BleScanResults.provisioningData(): ProvisioningData? { + return lastScanResult?.let { ProvisioningData.create(it) } } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningScannerDestinations.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt similarity index 70% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningScannerDestinations.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt index 60df2445..42d5b349 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningScannerDestinations.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt @@ -29,32 +29,41 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.scanner +package no.nordicsemi.android.wifi.provisioner.scanner import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.defineDestination import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel -import no.nordicsemi.android.common.ui.scanner.DeviceSelected -import no.nordicsemi.android.common.ui.scanner.ScanningCancelled -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice -import no.nordicsemi.android.wifi.provisioning.scanner.view.ProvisionerScannerScreen +import no.nordicsemi.android.kotlin.ble.core.ServerDevice +import no.nordicsemi.android.kotlin.ble.ui.scanner.DeviceSelected +import no.nordicsemi.android.kotlin.ble.ui.scanner.ScannerScreen +import no.nordicsemi.android.kotlin.ble.ui.scanner.ScanningCancelled +import no.nordicsemi.android.kotlin.ble.ui.scanner.main.DeviceListItem val ProvisionerScannerDestinationId = - createDestination("uiscanner-destination") + createDestination("uiscanner-destination") val ProvisionerScannerDestination = defineDestination(ProvisionerScannerDestinationId) { val viewModel = hiltViewModel() - ProvisionerScannerScreen( - onResult = { - when (it) { + ScannerScreen( + uuid = null, + onResult = { result -> + when (result) { is DeviceSelected -> viewModel.navigateUpWithResult( - ProvisionerScannerDestinationId, - it.device + from = ProvisionerScannerDestinationId, + result = result.scanResults.device ) ScanningCancelled -> viewModel.navigateUp() } + }, + deviceItem = { + DeviceListItem( + name = it.advertisedName, + address = it.device.address, + extras = { it.provisioningData()?.let { ProvisioningSection(data = it) } } + ) } ) } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningSection.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningSection.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt index fbf8c02a..c7eb9ef3 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/ProvisioningSection.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.scanner +package no.nordicsemi.android.wifi.provisioner.scanner import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -43,8 +43,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R import no.nordicsemi.android.common.theme.view.RssiIcon +import no.nordicsemi.android.wifi.provisioner.app.R @Composable internal fun ProvisioningSection(data: ProvisioningData) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/SelectChannelDialog.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt similarity index 94% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/SelectChannelDialog.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt index 9a49205c..f7fe7c81 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/SelectChannelDialog.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -47,9 +47,9 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.toDisplayString -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain @Composable internal fun SelectChannelDialog( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiLoadingItem.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiLoadingItem.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt index d5c9273c..1535c68b 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiLoadingItem.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -48,7 +48,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.home.view.components.applyPlaceholder +import no.nordicsemi.android.wifi.provisioner.home.view.components.applyPlaceholder @Composable fun WifiLoadingItem() { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt similarity index 93% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerScreen.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt index 09ac31fa..865e879b 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -65,13 +65,13 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.theme.view.getWiFiRes -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.BackIconAppBar -import no.nordicsemi.android.wifi.provisioning.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioning.home.view.toDisplayString -import no.nordicsemi.android.wifi.provisioning.home.view.toIcon -import no.nordicsemi.android.wifi.provisioning.wifi.viewmodel.WifiScannerViewModel -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.BackIconAppBar +import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.home.view.toIcon +import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiScannerViewModel +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain @Composable internal fun WifiScannerScreen() { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEntity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt similarity index 90% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEntity.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt index e513a25b..be7f4929 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEntity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view -import no.nordicsemi.android.wifi.provisioning.wifi.viewmodel.WifiSortOption -import no.nordicsemi.wifi.provisioner.library.domain.AuthModeDomain -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain data class WifiScannerViewEntity( val isLoading: Boolean = true, diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEvent.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt similarity index 93% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEvent.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt index c671ec47..04d73ee1 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiScannerViewEvent.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view -import no.nordicsemi.android.wifi.provisioning.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption internal sealed class WifiScannerViewEvent diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiSortView.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt similarity index 89% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiSortView.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt index e3cf2256..7b960e2f 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/view/WifiSortView.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.view +package no.nordicsemi.android.wifi.provisioner.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -39,13 +39,9 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.Label import androidx.compose.material.icons.filled.Done -import androidx.compose.material.icons.filled.Label import androidx.compose.material.icons.filled.NetworkWifi -import androidx.compose.material.icons.filled.NetworkWifi3Bar -import androidx.compose.material.icons.filled.SignalWifi4Bar -import androidx.compose.material.icons.filled.Widgets -import androidx.compose.material.icons.filled.Wifi import androidx.compose.material3.ElevatedFilterChip import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -57,8 +53,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption import no.nordicsemi.android.common.theme.R as themeR @OptIn(ExperimentalMaterial3Api::class) @@ -108,7 +104,7 @@ internal fun WifiSortView( if (isNameSortSelected) { Icon(Icons.Default.Done, contentDescription = "") } else { - Icon(Icons.Default.Label, contentDescription = "") + Icon(Icons.AutoMirrored.Filled.Label, contentDescription = "") } }, ) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiAggregator.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt similarity index 90% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiAggregator.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt index fc90722d..7c859a5c 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiAggregator.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel -import no.nordicsemi.android.wifi.provisioning.wifi.view.ScanRecordsForSsid -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.wifi.view.ScanRecordsForSsid +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import javax.inject.Inject class WifiAggregator @Inject constructor() { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiScannerViewModel.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt similarity index 81% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiScannerViewModel.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt index e74a07d7..eaa70d81 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiScannerViewModel.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -40,17 +40,17 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.wifi.provisioning.WifiScannerId -import no.nordicsemi.android.wifi.provisioning.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioning.wifi.view.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioning.wifi.view.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiScannerViewEntity -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioning.wifi.view.WifiSelectedEvent -import no.nordicsemi.wifi.provisioner.library.Error -import no.nordicsemi.wifi.provisioner.library.Loading -import no.nordicsemi.wifi.provisioner.library.Success +import no.nordicsemi.android.wifi.provisioner.WifiScannerId +import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository +import no.nordicsemi.android.wifi.provisioner.wifi.view.NavigateUpEvent +import no.nordicsemi.android.wifi.provisioner.wifi.view.OnSortOptionSelected +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerViewEntity +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerViewEvent +import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiSelectedEvent +import no.nordicsemi.android.wifi.provisioner.ble.Error +import no.nordicsemi.android.wifi.provisioner.ble.Loading +import no.nordicsemi.android.wifi.provisioner.ble.Success import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiSortOption.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiSortOption.kt rename to app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt index 7aad5b0f..6dde02ae 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/wifi/viewmodel/WifiSortOption.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioning.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel enum class WifiSortOption { NAME, RSSI diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt deleted file mode 100644 index 65dd1e53..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/home/view/HomeScreen1.kt +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.home.view - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import no.nordicsemi.android.wifi.provisioning.R -import no.nordicsemi.android.wifi.provisioning.home.view.components.LoggerIconAppBar -import no.nordicsemi.android.wifi.provisioning.home.view.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.DeviceSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioning.home.view.sections.PasswordSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.ProvisioningSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.StatusSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.VersionSection -import no.nordicsemi.android.wifi.provisioning.home.view.sections.VolatileMemorySwitch -import no.nordicsemi.android.wifi.provisioning.home.view.sections.WifiSection -import no.nordicsemi.android.wifi.provisioning.home.viewmodel.HomeViewModel -import no.nordicsemi.android.wifi.provisioning.password.PasswordDialog -import no.nordicsemi.android.wifi.provisioning.password.PasswordSetDialogEvent - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeScreen1() { - val viewModel = hiltViewModel() - - val state by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (HomeScreenViewEvent) -> Unit = { viewModel.onEvent(it) } - - Scaffold( - topBar = { - LoggerIconAppBar(stringResource(id = R.string.app_name)) { - viewModel.onEvent(OpenLoggerEvent) - } - }, - containerColor = MaterialTheme.colorScheme.surface, - ) { - Column(modifier = Modifier.padding(it)) { - Box(modifier = Modifier.weight(1f)) { - Content(state) { viewModel.onEvent(it) } - } - ActionButtonSection(state, onEvent) - } - } - - if (state.showPasswordDialog == true) { - PasswordDialog { - (it as? PasswordSetDialogEvent)?.let { onEvent(OnPasswordSelectedEvent(it.password)) } - onEvent(OnHidePasswordDialog) - } - } -} - -@Composable -private fun Content(state: HomeViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { - Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .padding(horizontal = 16.dp) - ) { - Spacer(modifier = Modifier.size(12.dp)) - - DeviceSection(state.device, !state.isRunning(), onEvent) - - Spacer(modifier = Modifier.size(12.dp)) - - if (!state.isConnected && state.device != null) { - DisconnectedDeviceStatus() - } else { - state.version?.let { - SectionTitle(text = stringResource(id = R.string.section_device)) - - Spacer(modifier = Modifier.size(12.dp)) - - VersionSection(it) - } - - Spacer(modifier = Modifier.size(12.dp)) - - state.status?.let { StatusSection(it) } - - state.network?.let { - Spacer(modifier = Modifier.size(12.dp)) - - SectionTitle(text = stringResource(id = R.string.section_provisioning)) - - Spacer(modifier = Modifier.size(12.dp)) - - WifiSection(it, !state.isRunning(), onEvent) - } - - state.password?.let { - Spacer(modifier = Modifier.size(10.dp)) - - PasswordSection(!state.isRunning(), onEvent) - } - - state.network?.let { - VolatileMemorySwitch( - volatileMemory = state.persistentMemory, - enabled = !state.isRunning(), - onEvent = onEvent - ) - } - - state.provisioningStatus?.let { - SectionTitle(text = stringResource(id = R.string.section_status)) - - Spacer(modifier = Modifier.size(8.dp)) - - ProvisioningSection(it) - } - - state.unprovisioningStatus?.let { - SectionTitle(text = stringResource(id = R.string.section_status)) - - Spacer(modifier = Modifier.size(8.dp)) - - UnprovisioningSection(it) - } - } - } -} - -@Composable -private fun SectionTitle(text: String) { - Text( - text = text, - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) -} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/FilterView.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/FilterView.kt deleted file mode 100644 index c48a7baf..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/FilterView.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.scanner.view - -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Done -import androidx.compose.material.icons.filled.SignalWifiOff -import androidx.compose.material3.ElevatedFilterChip -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioning.R - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -internal fun FilterView(allDevices: Boolean, onChange: () -> Unit) { - ElevatedFilterChip( - selected = !allDevices, - onClick = { onChange() }, - label = { Text(text = stringResource(id = R.string.unprovisioned)) }, - modifier = Modifier.padding(end = 8.dp), - leadingIcon = { - if (!allDevices) { - Icon(Icons.Default.Done, contentDescription = "") - } else { - Icon(Icons.Default.SignalWifiOff, contentDescription = "") - } - }, - ) -} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerAppBar.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerAppBar.kt deleted file mode 100644 index ecaacdea..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerAppBar.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.scanner.view - -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.SmallTopAppBar -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.colorResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import no.nordicsemi.android.common.ui.scanner.R -import no.nordicsemi.android.common.theme.R as themeR - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun ProvisionerScannerAppBar( - text: String, - showProgress: Boolean = false, - allDevicesFilter: Boolean = false, - onFilterChange: () -> Unit, - onNavigationButtonClick: () -> Unit -) { - SmallTopAppBar( - title = { Text(text, overflow = TextOverflow.Ellipsis, maxLines = 1) }, - colors = TopAppBarDefaults.smallTopAppBarColors( - scrolledContainerColor = MaterialTheme.colorScheme.primary, - containerColor = colorResource(id = themeR.color.appBarColor), - titleContentColor = MaterialTheme.colorScheme.onPrimary, - actionIconContentColor = MaterialTheme.colorScheme.onPrimary, - navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, - ), - navigationIcon = { - IconButton(onClick = { onNavigationButtonClick() }) { - Icon( - Icons.Default.ArrowBack, - contentDescription = stringResource(id = R.string.navigation_item_accessibility), - tint = MaterialTheme.colorScheme.onSecondary, - ) - } - }, - actions = { - if (showProgress) { - FilterView(allDevices = allDevicesFilter, onChange = onFilterChange) - CircularProgressIndicator( - modifier = Modifier - .padding(horizontal = 16.dp) - .size(30.dp), - color = MaterialTheme.colorScheme.onPrimary - ) - } - }, - ) -} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerScreen.kt deleted file mode 100644 index c1ff223e..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ProvisionerScannerScreen.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.scanner.view - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import no.nordicsemi.android.common.permission.RequireBluetooth -import no.nordicsemi.android.common.permission.RequireLocation -import no.nordicsemi.android.common.ui.scanner.DeviceSelected -import no.nordicsemi.android.common.ui.scanner.ScannerScreenResult -import no.nordicsemi.android.common.ui.scanner.ScanningCancelled -import no.nordicsemi.android.common.ui.scanner.main.DeviceListItem -import no.nordicsemi.android.common.ui.scanner.main.DeviceListItems -import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice -import no.nordicsemi.android.common.ui.scanner.repository.ScanningState -import no.nordicsemi.android.wifi.provisioning.scanner.ProvisioningSection -import no.nordicsemi.android.wifi.provisioning.scanner.provisioningData -import no.nordicsemi.android.wifi.provisioning.scanner.viewmodel.ProvisionerViewModel -import no.nordicsemi.android.common.ui.scanner.R as scannerR - -@Composable -fun ProvisionerScannerScreen( - onResult: (ScannerScreenResult) -> Unit -) { - val isLoading = rememberSaveable { mutableStateOf(false) } - val allDevices = rememberSaveable { mutableStateOf(false) } - - Column { - ProvisionerScannerAppBar( - stringResource(id = scannerR.string.scanner_screen), - isLoading.value, - allDevices.value, - { allDevices.value = !allDevices.value }) { - onResult(ScanningCancelled) - } - - RequireBluetooth { - RequireLocation { isLocationPermissionRequired -> - Box(modifier = Modifier.fillMaxSize()) { - - val viewModel = hiltViewModel() - - val scanningState by viewModel.devices.collectAsStateWithLifecycle() - - LaunchedEffect(scanningState.isRunning()) { - isLoading.value = scanningState.isRunning() - } - - LaunchedEffect(allDevices.value) { - viewModel.switchFilter() - } - - LazyColumn(contentPadding = PaddingValues(horizontal = 8.dp)) { - item { Spacer(modifier = Modifier.size(16.dp)) } - - when (val result = scanningState) { - is ScanningState.Loading -> item { - ProvisionerScanEmptyView( - isLocationPermissionRequired - ) - } - is ScanningState.DevicesDiscovered -> { - if (result.isEmpty()) { - item { ProvisionerScanEmptyView(isLocationPermissionRequired) } - } else { - DeviceListItems(result, { onResult(DeviceSelected(it)) }) { - ProvisionerExtrasSection(it) - } - } - } - is ScanningState.Error -> item { ErrorSection() } - } - - item { Spacer(modifier = Modifier.size(16.dp)) } - } - } - } - } - } -} - -@Composable -private fun ErrorSection() { - Text( - text = stringResource(id = no.nordicsemi.android.common.ui.scanner.R.string.scan_failed), - color = MaterialTheme.colorScheme.error - ) -} - -@Composable -private fun ProvisionerExtrasSection(device: DiscoveredBluetoothDevice) { - DeviceListItem(device.name, device.address) { - device.provisioningData()?.let { ProvisioningSection(data = it) } - } -} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ScanEmptyView.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ScanEmptyView.kt deleted file mode 100644 index 74534f09..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/view/ScanEmptyView.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.scanner.view - -import android.content.Context -import android.content.Intent -import android.provider.Settings -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.BluetoothDisabled -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import no.nordicsemi.android.common.core.parseBold -import no.nordicsemi.android.common.ui.scanner.R -import no.nordicsemi.android.wifi.provisioning.R as localR - -@Composable -internal fun ProvisionerScanEmptyView(requireLocation: Boolean) { - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.padding(horizontal = 16.dp) - ) { - Image( - imageVector = Icons.Default.BluetoothDisabled, - contentDescription = "", - modifier = Modifier.padding(16.dp).size(48.dp), - colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground), - ) - - Text( - text = stringResource(id = R.string.no_device_guide_title), - color = MaterialTheme.colorScheme.secondary - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Text(text = stringResource(id = localR.string.no_device_info).parseBold()) - - if (requireLocation) { - Spacer(modifier = Modifier.height(8.dp)) - - Text(text = stringResource(id = R.string.no_device_guide_location_info)) - - Spacer(modifier = Modifier.height(16.dp)) - - val context = LocalContext.current - Button(onClick = { openLocationSettings(context) }) { - Text(text = stringResource(id = R.string.action_location_settings)) - } - Spacer(modifier = Modifier.height(8.dp)) - } else { - Spacer(modifier = Modifier.height(16.dp)) - } - } -} - -private fun openLocationSettings(context: Context) { - val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - context.startActivity(intent) -} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/viewmodel/ProvisionerViewModel.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/viewmodel/ProvisionerViewModel.kt deleted file mode 100644 index 6b77f923..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioning/scanner/viewmodel/ProvisionerViewModel.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioning.scanner.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import no.nordicsemi.android.wifi.provisioning.scanner.provisioningData -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.stateIn -import no.nordicsemi.android.common.ui.scanner.repository.ScannerRepository -import no.nordicsemi.android.common.ui.scanner.repository.ScanningState -import javax.inject.Inject - -@HiltViewModel -internal class ProvisionerViewModel @Inject constructor( - private val scannerRepository: ScannerRepository, -) : ViewModel() { - - //By default only not connected - private val _allDevices = MutableStateFlow(true) - val allDevices = _allDevices.asStateFlow() - - val devices = allDevices.combine(scannerRepository.getScannerState()) { onlyUnprovisioned, result -> - when (result) { - is ScanningState.DevicesDiscovered -> result.applyFilters(onlyUnprovisioned) - else -> result - } - }.stateIn(viewModelScope, SharingStarted.Lazily, ScanningState.Loading) - - private fun ScanningState.DevicesDiscovered.applyFilters(allDevices: Boolean) = - ScanningState.DevicesDiscovered( - devices - .filter { it.provisioningData() != null } - .filter { - val provisioningData = it.provisioningData() - (provisioningData?.isConnected == false).takeIf { !allDevices } ?: true - } - ) - - fun switchFilter() { - _allDevices.value = !allDevices.value - } - - override fun onCleared() { - super.onCleared() - scannerRepository.clear() - } -} diff --git a/build.gradle.kts b/build.gradle.kts index 09dea01a..3648359b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,7 +35,7 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.nordic.kotlin) apply false alias(libs.plugins.hilt) apply false - alias(libs.plugins.protobuf) apply false + alias(libs.plugins.wire) apply false alias(libs.plugins.nordic.application) apply false alias(libs.plugins.nordic.application.compose) apply false alias(libs.plugins.nordic.library) apply false diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 2b5c4873..83fa1adb 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -1,43 +1,68 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") + alias(libs.plugins.nordic.feature) + alias(libs.plugins.nordic.hilt) } android { - namespace = "no.nordicsemi.android.wifi.provisioning.ble" - compileSdk = 34 - - defaultConfig { - minSdk = 24 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } + namespace = "no.nordicsemi.android.wifi.provisioner.feature.ble" } dependencies { + implementation(project(":lib:ble:provisioner")) + + implementation(libs.androidx.lifecycle.runtime.compose) + + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.iconsExtended) + + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.hilt.navigation.compose) + implementation(libs.nordic.scanner) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.lifecycle.viewModel.compose) - implementation("androidx.core:core-ktx:1.10.1") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("com.google.android.material:material:1.9.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") -} \ No newline at end of file + implementation(libs.nordic.core) + implementation(libs.nordic.theme) + implementation(libs.nordic.navigation) + implementation(libs.nordic.blek.uiscanner) + implementation(libs.nordic.permissions.ble) + + implementation(libs.accompanist.placeholder) + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) +} diff --git a/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt b/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt deleted file mode 100644 index df3ebac1..00000000 --- a/feature/ble/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nordicsemi.android.wifi.provisioning.ble - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("no.nordicsemi.android.wifi.provisioning.ble.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt b/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt deleted file mode 100644 index 03190228..00000000 --- a/feature/ble/src/test/java/no/nordicsemi/android/wifi/provisioning/ble/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nordicsemi.android.wifi.provisioning.ble - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index 2865bb89..f15e6c2e 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -1,43 +1,67 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") + alias(libs.plugins.nordic.feature) + alias(libs.plugins.nordic.hilt) } android { - namespace = "no.nordicsemi.android.wifi.provisioning.softap" - compileSdk = 34 - - defaultConfig { - minSdk = 24 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } + namespace = "no.nordicsemi.android.wifi.provisioner.feature.softap" } dependencies { - implementation("androidx.core:core-ktx:1.10.1") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("com.google.android.material:material:1.9.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") -} \ No newline at end of file + implementation(libs.androidx.lifecycle.runtime.compose) + + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.iconsExtended) + + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.hilt.navigation.compose) + implementation(libs.nordic.scanner) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.lifecycle.viewModel.compose) + + implementation(libs.nordic.core) + implementation(libs.nordic.theme) + implementation(libs.nordic.navigation) + implementation(libs.nordic.blek.uiscanner) + implementation(libs.nordic.permissions.ble) + + implementation(libs.accompanist.placeholder) + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) +} diff --git a/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt b/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt deleted file mode 100644 index cbeff9b2..00000000 --- a/feature/softap/src/androidTest/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nordicsemi.android.wifi.provisioning.softap - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("no.nordicsemi.android.wifi.provisioning.softap.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt b/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt deleted file mode 100644 index b6de196f..00000000 --- a/feature/softap/src/test/java/no/nordicsemi/android/wifi/provisioning/softap/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nordicsemi.android.wifi.provisioning.softap - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9bb2ed58..f33bad43 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,37 +1,6 @@ -# -# Copyright (c) 2022, Nordic Semiconductor -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, are -# permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this list of -# conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright notice, this list -# of conditions and the following disclaimer in the documentation and/or other materials -# provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -#Mon Jun 13 12:29:45 CEST 2022 +#Mon Feb 12 16:06:22 CET 2024 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/lib/ble/proto/build.gradle.kts b/lib/ble/proto/build.gradle.kts index a9ad5a68..e1c8b51f 100644 --- a/lib/ble/proto/build.gradle.kts +++ b/lib/ble/proto/build.gradle.kts @@ -40,5 +40,5 @@ wire { } android { - namespace = "no.nordicsemi.wifi.provisioner.proto" + namespace = "no.nordicsemi.android.wifi.provisioner.ble.proto" } diff --git a/lib/ble/proto/src/main/proto/common.proto b/lib/ble/proto/src/main/proto/common.proto index 59f1d3cb..039f0a13 100644 --- a/lib/ble/proto/src/main/proto/common.proto +++ b/lib/ble/proto/src/main/proto/common.proto @@ -1,7 +1,7 @@ syntax = "proto2"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; // Common ENUMs diff --git a/lib/ble/proto/src/main/proto/request.proto b/lib/ble/proto/src/main/proto/request.proto index 3c5fc4fe..6d0604d6 100644 --- a/lib/ble/proto/src/main/proto/request.proto +++ b/lib/ble/proto/src/main/proto/request.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; // Requests diff --git a/lib/ble/proto/src/main/proto/response.proto b/lib/ble/proto/src/main/proto/response.proto index 395ae01c..8d16f0fa 100644 --- a/lib/ble/proto/src/main/proto/response.proto +++ b/lib/ble/proto/src/main/proto/response.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; // Responses diff --git a/lib/ble/proto/src/main/proto/result.proto b/lib/ble/proto/src/main/proto/result.proto index 92833a81..e97b1952 100644 --- a/lib/ble/proto/src/main/proto/result.proto +++ b/lib/ble/proto/src/main/proto/result.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "common.proto"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; // States are sent over Data Out characteristic diff --git a/lib/ble/proto/src/main/proto/version.proto b/lib/ble/proto/src/main/proto/version.proto index 63deb046..7e5e96f7 100644 --- a/lib/ble/proto/src/main/proto/version.proto +++ b/lib/ble/proto/src/main/proto/version.proto @@ -1,7 +1,7 @@ syntax = "proto2"; option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioning.ble.proto"; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; /* Response payload for returned from Version characteristic. */ message Info { diff --git a/lib/ble/provisioner/build.gradle.kts b/lib/ble/provisioner/build.gradle.kts index 5455e719..696c6aba 100644 --- a/lib/ble/provisioner/build.gradle.kts +++ b/lib/ble/provisioner/build.gradle.kts @@ -35,15 +35,10 @@ plugins { } android { - namespace = "no.nordicsemi.wifi.provisioner.library" + namespace = "no.nordicsemi.android.wifi.provisioner.ble" } dependencies { implementation(project(":lib:ble:proto")) - - implementation(libs.nordic.ble.common) implementation(libs.nordic.ble.ktx) - implementation(libs.nordic.uilogger) - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt similarity index 93% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt index ab57fdf2..00bb9ec3 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Ext.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library +package no.nordicsemi.android.wifi.provisioner.ble import android.util.Log import kotlinx.coroutines.CoroutineExceptionHandler @@ -42,6 +42,6 @@ private val exceptionHandler = CoroutineExceptionHandler { _, t -> } fun CoroutineScope.launchWithCatch(block: suspend CoroutineScope.() -> Unit) = - launch(Job() + exceptionHandler) { + launch(Job() + no.nordicsemi.android.wifi.provisioner.ble.exceptionHandler) { block() } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt similarity index 88% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt index c84b80f0..f7cdb328 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepository.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt @@ -29,20 +29,20 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library +package no.nordicsemi.android.wifi.provisioner.ble import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice import android.content.Context -import no.nordicsemi.wifi.provisioner.library.domain.DeviceStatusDomain -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain -import no.nordicsemi.wifi.provisioner.library.domain.VersionDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConfigDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain -import no.nordicsemi.wifi.provisioner.library.internal.ConnectionStatus +import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus +import no.nordicsemi.android.wifi.provisioner.ble.internal.ResponseErrorException +import no.nordicsemi.android.wifi.provisioner.ble.internal.NotificationTimeoutException import kotlinx.coroutines.flow.Flow -import no.nordicsemi.wifi.provisioner.library.internal.ResponseErrorException -import no.nordicsemi.wifi.provisioner.library.internal.NotificationTimeoutException /** * A class responsible for establishing connection and maintaining communication with a nRF 7 device. @@ -126,11 +126,6 @@ interface ProvisionerRepository { */ suspend fun release() - /** - * Opens nRF Logger app. - */ - fun openLogger() - companion object { @SuppressLint("StaticFieldLeak") private var instance: ProvisionerRepository? = null diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt similarity index 74% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt index 9517f21b..5c429dfa 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/ProvisionerRepositoryImpl.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt @@ -29,26 +29,25 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library +package no.nordicsemi.android.wifi.provisioner.ble import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice import android.content.Context -import no.nordicsemi.wifi.provisioner.library.domain.DeviceStatusDomain -import no.nordicsemi.wifi.provisioner.library.domain.ScanRecordDomain -import no.nordicsemi.wifi.provisioner.library.domain.VersionDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConfigDomain -import no.nordicsemi.wifi.provisioner.library.domain.WifiConnectionStateDomain -import no.nordicsemi.wifi.provisioner.library.domain.toApi -import no.nordicsemi.wifi.provisioner.library.domain.toDomain -import no.nordicsemi.wifi.provisioner.library.internal.ConnectionStatus -import no.nordicsemi.wifi.provisioner.library.internal.ProvisionerBleManager +import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.toApi +import no.nordicsemi.android.wifi.provisioner.ble.domain.toDomain +import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus +import no.nordicsemi.android.wifi.provisioner.ble.internal.ProvisionerBleManager import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart -import no.nordicsemi.android.common.logger.NordicLogger class ProvisionerRepositoryImpl internal constructor( private val context: Context @@ -58,7 +57,7 @@ class ProvisionerRepositoryImpl internal constructor( @SuppressLint("MissingPermission") override suspend fun start(device: BluetoothDevice): Flow { - manager = ProvisionerFactory.createBleManager(context, device) + manager = ProvisionerFactory.createBleManager(context) return manager!!.start(device) } @@ -94,10 +93,6 @@ class ProvisionerRepositoryImpl internal constructor( manager = null } - override fun openLogger() { - NordicLogger.launch(context, manager?.logger) - } - private fun runTask(block: suspend () -> T): Flow> { return flow { emit(Resource.createSuccess(block())) } .onStart { emit(Resource.createLoading()) } @@ -114,11 +109,7 @@ internal object ProvisionerFactory { return ProvisionerRepositoryImpl(context) } - fun createBleManager(context: Context, device: BluetoothDevice): ProvisionerBleManager { - return ProvisionerBleManager(context, createNordicLogger(context, device.address)) - } - - private fun createNordicLogger(context: Context, address: String): NordicLogger { - return NordicLogger(context, "Wi-Fi", address, null) + fun createBleManager(context: Context): ProvisionerBleManager { + return ProvisionerBleManager(context) } } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt similarity index 97% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt index ea3b5cc7..9d498a73 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/Resource.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library +package no.nordicsemi.android.wifi.provisioner.ble sealed interface Resource { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt index 3edf1873..8ef63ba1 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/AuthModeDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain enum class AuthModeDomain(val id: Int) { OPEN(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt index 09a9659f..93f98062 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/BandDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain enum class BandDomain(val id: Int) { BAND_ANY(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt index 56a3c859..f9a363ee 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ConnectionInfoDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class ConnectionInfoDomain( val ipv4Address: String diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt index 33abf0f0..3b69527e 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/DeviceStatusDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class DeviceStatusDomain( val wifiState: WifiConnectionStateDomain?, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt index d3f8a3d2..677a708d 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanParamsDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class ScanParamsDomain( val band: BandDomain, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt index 66093d65..8407c375 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ScanRecordDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class ScanRecordDomain( val rssi: Int?, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt similarity index 89% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt index 42abd274..a63260a8 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToApiMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt @@ -29,12 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain -import no.nordicsemi.android.wifi.provisioning.ble.proto.AuthMode -import no.nordicsemi.android.wifi.provisioning.ble.proto.Band -import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiConfig -import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiInfo +import no.nordicsemi.android.wifi.provisioner.ble.proto.AuthMode +import no.nordicsemi.android.wifi.provisioner.ble.proto.Band +import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo import okio.ByteString.Companion.toByteString internal fun WifiConfigDomain.toApi(): WifiConfig { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt similarity index 87% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt index 0f0f9c1d..26273bc2 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/ToDomainMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt @@ -29,18 +29,18 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain import android.util.Log -import no.nordicsemi.android.wifi.provisioning.ble.proto.AuthMode -import no.nordicsemi.android.wifi.provisioning.ble.proto.Band -import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionFailureReason -import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionInfo -import no.nordicsemi.android.wifi.provisioning.ble.proto.ConnectionState -import no.nordicsemi.android.wifi.provisioning.ble.proto.DeviceStatus -import no.nordicsemi.android.wifi.provisioning.ble.proto.ScanParams -import no.nordicsemi.android.wifi.provisioning.ble.proto.ScanRecord -import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiInfo +import no.nordicsemi.android.wifi.provisioner.ble.proto.AuthMode +import no.nordicsemi.android.wifi.provisioner.ble.proto.Band +import no.nordicsemi.android.wifi.provisioner.ble.proto.ConnectionFailureReason +import no.nordicsemi.android.wifi.provisioner.ble.proto.ConnectionInfo +import no.nordicsemi.android.wifi.provisioner.ble.proto.ConnectionState +import no.nordicsemi.android.wifi.provisioner.ble.proto.DeviceStatus +import no.nordicsemi.android.wifi.provisioner.ble.proto.ScanParams +import no.nordicsemi.android.wifi.provisioner.ble.proto.ScanRecord +import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo import okio.ByteString private const val TAG = "DOMAIN-MAPPER" diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt index a3ce9ad5..38809f72 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/VersionDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt @@ -29,6 +29,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class VersionDomain(val value: Int) diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt index c9bd0ea6..8508dafc 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConfigDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain data class WifiConfigDomain( val info: WifiInfoDomain, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt index f68ed6d6..1163eea9 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionFailureReasonDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain enum class WifiConnectionFailureReasonDomain(val id: Int) { AUTH_ERROR(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt index 31078872..3f337734 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiConnectionStateDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain enum class WifiConnectionStateDomain(val id: Int) { DISCONNECTED(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt similarity index 97% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt index c5522163..66ab2a3d 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/domain/WifiInfoDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain import okio.ByteString diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt similarity index 97% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt index 26c06b32..67ac4a74 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/BleManagerStatus.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal enum class ConnectionStatus { IDLE, CONNECTING, CONNECTED, SUCCESS, LINK_LOSS, DISCONNECTING, DISCONNECTED, UNKNOWN_ERROR, MISSING_SERVICE, FAIL_TO_CONNECT; diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt similarity index 97% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt index dc034b57..7bac1957 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ByteArrayReadResponse.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal import android.bluetooth.BluetoothDevice import no.nordicsemi.android.ble.callback.profile.ProfileReadResponse diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt similarity index 98% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt index ac27dbfa..89bab844 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ConnectionObserverAdapter.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal import android.bluetooth.BluetoothDevice import android.util.Log diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt index 4fcdb4f2..89432909 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/NotificationTimeoutException.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt @@ -29,6 +29,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal class NotificationTimeoutException : Exception("Timeout exception.") diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt similarity index 75% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt index 0fcd157f..15d966f3 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ProvisionerBleManager.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt @@ -28,7 +28,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice @@ -50,15 +50,14 @@ import no.nordicsemi.android.ble.BleManager import no.nordicsemi.android.ble.ktx.asValidResponseFlow import no.nordicsemi.android.ble.ktx.suspend import no.nordicsemi.android.ble.ktx.suspendForValidResponse -import no.nordicsemi.android.common.logger.NordicLogger -import no.nordicsemi.android.wifi.provisioning.ble.proto.Result -import no.nordicsemi.android.wifi.provisioning.ble.proto.DeviceStatus -import no.nordicsemi.android.wifi.provisioning.ble.proto.Info -import no.nordicsemi.android.wifi.provisioning.ble.proto.OpCode -import no.nordicsemi.android.wifi.provisioning.ble.proto.Request -import no.nordicsemi.android.wifi.provisioning.ble.proto.Response -import no.nordicsemi.android.wifi.provisioning.ble.proto.Status -import no.nordicsemi.android.wifi.provisioning.ble.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioner.ble.proto.Result +import no.nordicsemi.android.wifi.provisioner.ble.proto.DeviceStatus +import no.nordicsemi.android.wifi.provisioner.ble.proto.Info +import no.nordicsemi.android.wifi.provisioner.ble.proto.OpCode +import no.nordicsemi.android.wifi.provisioner.ble.proto.Request +import no.nordicsemi.android.wifi.provisioner.ble.proto.Response +import no.nordicsemi.android.wifi.provisioner.ble.proto.Status +import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiConfig import java.util.* val PROVISIONING_SERVICE_UUID: UUID = UUID.fromString("14387800-130c-49e7-b877-2881c89cb258") @@ -71,7 +70,6 @@ private const val TIMEOUT_MILLIS = 60_000L internal class ProvisionerBleManager( context: Context, - val logger: NordicLogger ) : BleManager(context) { private var versionCharacteristic: BluetoothGattCharacteristic? = null @@ -86,12 +84,8 @@ internal class ProvisionerBleManager( connectionObserver = dataHolder } - fun openLogger() { - NordicLogger.launch(context, logger) - } - override fun log(priority: Int, message: String) { - logger.log(priority, message) + //logger.log(priority, message) } override fun getMinLogPriority(): Int { @@ -119,49 +113,46 @@ internal class ProvisionerBleManager( disconnect().suspend() } - private inner class ProvisioningManagerGattCallback : BleManagerGattCallback() { + @SuppressLint("WrongConstant") + override fun initialize() { + requestMtu(512).enqueue() + enableIndications(controlPointCharacteristic).enqueue() + enableNotifications(dataOutCharacteristic).enqueue() + } - @SuppressLint("WrongConstant") - override fun initialize() { - requestMtu(512).enqueue() - enableIndications(controlPointCharacteristic).enqueue() - enableNotifications(dataOutCharacteristic).enqueue() + override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean { + val service: BluetoothGattService? = gatt.getService(PROVISIONING_SERVICE_UUID) + if (service != null) { + versionCharacteristic = service.getCharacteristic(VERSION_CHARACTERISTIC_UUID) + controlPointCharacteristic = + service.getCharacteristic(CONTROL_POINT_CHARACTERISTIC_UUID) + dataOutCharacteristic = service.getCharacteristic(DATA_OUT_CHARACTERISTIC_UUID) } - - override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean { - val service: BluetoothGattService? = gatt.getService(PROVISIONING_SERVICE_UUID) - if (service != null) { - versionCharacteristic = service.getCharacteristic(VERSION_CHARACTERISTIC_UUID) - controlPointCharacteristic = - service.getCharacteristic(CONTROL_POINT_CHARACTERISTIC_UUID) - dataOutCharacteristic = service.getCharacteristic(DATA_OUT_CHARACTERISTIC_UUID) - } - var writeRequest = false - var writeCommand = false - - controlPointCharacteristic?.let { - val rxProperties: Int = it.properties - writeRequest = rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE > 0 - writeCommand = - rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE > 0 - - // Set the WRITE REQUEST type when the characteristic supports it. - // This will allow to send long write (also if the characteristic support it). - // In case there is no WRITE REQUEST property, this manager will divide texts - // longer then MTU-3 bytes into up to MTU-3 bytes chunks. - if (!writeRequest) { - useLongWrite = false - } + var writeRequest = false + var writeCommand = false + + controlPointCharacteristic?.let { + val rxProperties: Int = it.properties + writeRequest = rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE > 0 + writeCommand = + rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE > 0 + + // Set the WRITE REQUEST type when the characteristic supports it. + // This will allow to send long write (also if the characteristic support it). + // In case there is no WRITE REQUEST property, this manager will divide texts + // longer then MTU-3 bytes into up to MTU-3 bytes chunks. + if (!writeRequest) { + useLongWrite = false } - return versionCharacteristic != null && controlPointCharacteristic != null && dataOutCharacteristic != null } + return versionCharacteristic != null && controlPointCharacteristic != null && dataOutCharacteristic != null + } - override fun onServicesInvalidated() { - versionCharacteristic = null - controlPointCharacteristic = null - dataOutCharacteristic = null - useLongWrite = true - } + override fun onServicesInvalidated() { + versionCharacteristic = null + controlPointCharacteristic = null + dataOutCharacteristic = null + useLongWrite = true } suspend fun getVersion(): Info = withTimeout(TIMEOUT_MILLIS) { @@ -305,8 +296,4 @@ internal class ProvisionerBleManager( } return ResponseErrorException(errorCode) } - - override fun getGattCallback(): BleManagerGattCallback { - return ProvisioningManagerGattCallback() - } } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt index 0588d788..4eabf3a7 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/wifi/provisioner/library/internal/ResponseErrorException.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.wifi.provisioner.library.internal +package no.nordicsemi.android.wifi.provisioner.ble.internal data class ResponseErrorException(val code: ResponseError) : Exception("Received error response.") diff --git a/lib/softap/.gitignore b/lib/softap/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/lib/softap/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/lib/softap/build.gradle.kts b/lib/softap/build.gradle.kts new file mode 100644 index 00000000..f349e4c8 --- /dev/null +++ b/lib/softap/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + alias(libs.plugins.nordic.feature) + alias(libs.plugins.nordic.hilt) +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioner.softap" +} \ No newline at end of file diff --git a/lib/softap/consumer-rules.pro b/lib/softap/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/lib/softap/proguard-rules.pro b/lib/softap/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/lib/softap/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/lib/softap/src/main/AndroidManifest.xml b/lib/softap/src/main/AndroidManifest.xml new file mode 100644 index 00000000..44008a43 --- /dev/null +++ b/lib/softap/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index f104a259..9a2c52d4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,7 +48,7 @@ dependencyResolutionManagement { } versionCatalogs { create("libs") { - from("no.nordicsemi.android.gradle:version-catalog:1.4.6") + from("no.nordicsemi.android.gradle:version-catalog:1.11.4") } } } @@ -59,6 +59,7 @@ include(":feature:ble") include(":feature:softap") include(":lib:ble:provisioner") include(":lib:ble:proto") +include(":lib:softap") //if (file('../Android-Common-Libraries').exists()) { // includeBuild('../Android-Common-Libraries') From e8150e8d22b5acafb65b5ed85dc8c0c154a2a83a Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 13 Feb 2024 14:51:05 +0100 Subject: [PATCH 004/101] refactoring --- .../android/wifi/provisioner/WifiProvisionerApplication.kt | 3 +-- .../android/wifi/provisioner/scanner/ProvisioningData.kt | 3 +-- .../java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt index 8e1edd4a..c84b00ed 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt @@ -35,5 +35,4 @@ import android.app.Application import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class WifiProvisionerApplication : Application() { -} +class WifiProvisionerApplication : Application() diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt index e4be2070..b2e92f31 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt @@ -35,8 +35,7 @@ import android.os.ParcelUuid import no.nordicsemi.android.common.core.DataByteArray import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResultData import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResults -import no.nordicsemi.android.support.v18.scanner.ScanResult -import java.util.* +import java.util.UUID internal data class ProvisioningData( val version: Int, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt index 00bb9ec3..5720014c 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt @@ -42,6 +42,6 @@ private val exceptionHandler = CoroutineExceptionHandler { _, t -> } fun CoroutineScope.launchWithCatch(block: suspend CoroutineScope.() -> Unit) = - launch(Job() + no.nordicsemi.android.wifi.provisioner.ble.exceptionHandler) { + launch(Job() + exceptionHandler) { block() } From 9c610a960610f90c97bbadb0ba1f3f3e0a2ad3d6 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 13 Feb 2024 14:53:03 +0100 Subject: [PATCH 005/101] Remove password manager --- .../provisioner/repository/PasswordManager.kt | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt deleted file mode 100644 index eefd9cc2..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/PasswordManager.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.repository - -import javax.inject.Inject - -class PasswordManager @Inject constructor() { - - private val passwords = mutableMapOf() - - fun getPasswordOrNull(ssid: String): String? { - return passwords[ssid] - } - - fun storePassword(ssid: String, password: String) { - passwords[ssid] = password - } -} From e042e7db00498c75a95fd2ee2a0bfb803475a268 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 13 Feb 2024 14:57:25 +0100 Subject: [PATCH 006/101] More clean up --- .../home/view/components/ErrorText.kt | 42 ------------------- .../ble/ProvisionerRepositoryImpl.kt | 15 +------ .../ble/internal/ProvisionerBleManager.kt | 5 +-- 3 files changed, 3 insertions(+), 59 deletions(-) delete mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt deleted file mode 100644 index 5c2c8ec7..00000000 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/ErrorText.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.home.view.components - -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable - -@Composable -fun ErrorText(text: String) = Text( - text = text, - color = MaterialTheme.colorScheme.error -) diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt index 5c429dfa..f0c236d9 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt @@ -34,6 +34,8 @@ package no.nordicsemi.android.wifi.provisioner.ble import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice import android.content.Context +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain @@ -43,11 +45,6 @@ import no.nordicsemi.android.wifi.provisioner.ble.domain.toApi import no.nordicsemi.android.wifi.provisioner.ble.domain.toDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.internal.ProvisionerBleManager -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onStart class ProvisionerRepositoryImpl internal constructor( private val context: Context @@ -93,14 +90,6 @@ class ProvisionerRepositoryImpl internal constructor( manager = null } - private fun runTask(block: suspend () -> T): Flow> { - return flow { emit(Resource.createSuccess(block())) } - .onStart { emit(Resource.createLoading()) } - .catch { - it.printStackTrace() - emit(Resource.createError(it)) - } - } } internal object ProvisionerFactory { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt index 15d966f3..0bce0750 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt @@ -128,14 +128,11 @@ internal class ProvisionerBleManager( service.getCharacteristic(CONTROL_POINT_CHARACTERISTIC_UUID) dataOutCharacteristic = service.getCharacteristic(DATA_OUT_CHARACTERISTIC_UUID) } - var writeRequest = false - var writeCommand = false + var writeRequest: Boolean controlPointCharacteristic?.let { val rxProperties: Int = it.properties writeRequest = rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE > 0 - writeCommand = - rxProperties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE > 0 // Set the WRITE REQUEST type when the characteristic supports it. // This will allow to send long write (also if the characteristic support it). From 1edb3e4cd2e15e1b180d8103a0e6fcf952c9487c Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 13 Feb 2024 15:08:18 +0100 Subject: [PATCH 007/101] Filter devices with UUID --- .../android/wifi/provisioner/scanner/ProvisioningData.kt | 2 +- .../provisioner/scanner/ProvisioningScannerDestinations.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt index b2e92f31..288ac1d2 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt @@ -52,7 +52,7 @@ internal data class ProvisioningData( ) companion object { - private val parcelUuid = ParcelUuid(UUID.fromString("14387800-130c-49e7-b877-2881c89cb258")) + val parcelUuid = ParcelUuid(UUID.fromString("14387800-130c-49e7-b877-2881c89cb258")) fun create(scanResult: BleScanResultData) = scanResult.scanRecord?.serviceData ?.get(parcelUuid) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt index 42d5b349..a7a78643 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt @@ -48,7 +48,7 @@ val ProvisionerScannerDestination = defineDestination(ProvisionerScannerDestinat val viewModel = hiltViewModel() ScannerScreen( - uuid = null, + uuid = ProvisioningData.parcelUuid, onResult = { result -> when (result) { is DeviceSelected -> viewModel.navigateUpWithResult( @@ -62,7 +62,7 @@ val ProvisionerScannerDestination = defineDestination(ProvisionerScannerDestinat DeviceListItem( name = it.advertisedName, address = it.device.address, - extras = { it.provisioningData()?.let { ProvisioningSection(data = it) } } + extras = { it.provisioningData()?.let { ProvisioningSection(data = it) }} ) } ) From fc88c5af0ce6bbc3356e8af5a6df5df2a5abf095 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 14 Feb 2024 13:43:45 +0100 Subject: [PATCH 008/101] More refactoring - Adds a new home screen and allows navigation to the ble provisioner. --- .../wifi/provisioner/HomeDestination.kt | 9 +- .../android/wifi/provisioner/HomeScreen.kt | 138 +++++++++++++++++ .../android/wifi/provisioner/MainActivity.kt | 7 +- feature/ble/build.gradle.kts | 2 + .../provisioner/ble}/components/DataItem.kt | 2 +- .../ble}/components/LoadingItem.kt | 0 .../ble}/components/PlaceholderModifier.kt | 0 .../ble}/password/PasswordDialog.kt | 2 +- .../ble}/password/PasswordDialogEvent.kt | 0 .../ProvisionerResourceRepository.kt | 2 +- .../ble}/repository/RepositoryModule.kt | 0 .../ble}/scanner/ProvisioningData.kt | 0 .../ProvisioningScannerDestinations.kt | 13 +- .../ble}/scanner/ProvisioningSection.kt | 2 +- .../ble}/sections/ActionButtonSection.kt | 22 +-- .../ble}/sections/DeviceSection.kt | 30 +++- .../ble}/sections/DisconnectedDeviceStatus.kt | 4 +- .../ble}/sections/PasswordSection.kt | 8 +- .../ble}/sections/ProvisioningSection.kt | 6 +- .../ble}/sections/StatusSection.kt | 8 +- .../ble}/sections/UnprovisioningSection.kt | 2 +- .../ble}/sections/VersionSection.kt | 4 +- .../ble}/sections/VolatileMemorySwitch.kt | 8 +- .../provisioner/ble}/sections/WifiSection.kt | 12 +- .../provisioner/ble/view/BleDestination.kt | 38 ++--- .../ble/view/BleProvisioningScreen.kt | 52 ++++--- .../ble/view/BleScreenViewEvent.kt | 2 +- .../provisioner/ble/view/BleViewEntity.kt | 6 +- .../wifi/provisioner/ble}/view/UiMapper.kt | 4 +- .../provisioner/ble/viewmodel/BleViewModel.kt | 60 ++++---- .../ble}/wifi/view/SelectChannelDialog.kt | 6 +- .../wifi/view/WiFiAccessPointListsScreen.kt | 25 +-- .../ble}/wifi/view/WifiLoadingItem.kt | 2 +- .../ble}/wifi/view/WifiScannerViewEntity.kt | 20 +-- .../ble}/wifi/view/WifiScannerViewEvent.kt | 4 +- .../ble}/wifi/view/WifiSortView.kt | 8 +- .../ble}/wifi/viewmodel/WifiAggregator.kt | 6 +- .../wifi/viewmodel/WifiScannerViewModel.kt | 18 +-- .../ble}/wifi/viewmodel/WifiSortOption.kt | 2 +- .../src/main/res/drawable/ic_disconnected.xml | 0 .../ble}/src/main/res/drawable/ic_error.xml | 0 .../res/drawable/ic_launcher_background.xml | 0 .../res/drawable/ic_launcher_foreground.xml | 0 .../src/main/res/drawable/ic_no_phone.xml | 0 .../ble}/src/main/res/drawable/ic_no_wifi.xml | 0 .../ble/src/main/res/drawable/ic_nrf70.png | Bin 0 -> 9040 bytes .../src/main/res/drawable/ic_password.xml | 0 .../src/main/res/drawable/ic_phone_ok.xml | 0 .../ble}/src/main/res/drawable/ic_storage.xml | 0 .../src/main/res/drawable/ic_upload_wifi.xml | 0 .../ble}/src/main/res/drawable/ic_version.xml | 0 .../src/main/res/drawable/ic_wifi_error.xml | 0 .../src/main/res/drawable/ic_wifi_loading.xml | 0 .../src/main/res/drawable/ic_wifi_lock.xml | 0 .../ble}/src/main/res/drawable/ic_wifi_ok.xml | 0 .../src/main/res/drawable/ic_wifi_open.xml | 0 .../res/values/ic_launcher_background.xml | 4 + feature/ble/src/main/res/values/strings.xml | 143 ++++++++++++++++++ 58 files changed, 489 insertions(+), 192 deletions(-) create mode 100644 app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/components/DataItem.kt (99%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/components/LoadingItem.kt (100%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/components/PlaceholderModifier.kt (100%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/password/PasswordDialog.kt (98%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/password/PasswordDialogEvent.kt (100%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/repository/ProvisionerResourceRepository.kt (98%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/repository/RepositoryModule.kt (100%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/scanner/ProvisioningData.kt (100%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/scanner/ProvisioningScannerDestinations.kt (85%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/scanner/ProvisioningSection.kt (98%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/ActionButtonSection.kt (82%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/DeviceSection.kt (83%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/DisconnectedDeviceStatus.kt (94%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/PasswordSection.kt (88%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/ProvisioningSection.kt (97%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/StatusSection.kt (96%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/UnprovisioningSection.kt (98%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/VersionSection.kt (96%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/VolatileMemorySwitch.kt (91%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/sections/WifiSection.kt (86%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt (63%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt (75%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt (97%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt (96%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner/home => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/view/UiMapper.kt (97%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt (78%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/view/SelectChannelDialog.kt (95%) rename app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt (92%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/view/WifiLoadingItem.kt (98%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/view/WifiScannerViewEntity.kt (83%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/view/WifiScannerViewEvent.kt (92%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/view/WifiSortView.kt (94%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/viewmodel/WifiAggregator.kt (92%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/viewmodel/WifiScannerViewModel.kt (84%) rename {app/src/main/java/no/nordicsemi/android/wifi/provisioner => feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/wifi/viewmodel/WifiSortOption.kt (96%) rename {app => feature/ble}/src/main/res/drawable/ic_disconnected.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_error.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_launcher_background.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_launcher_foreground.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_no_phone.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_no_wifi.xml (100%) create mode 100644 feature/ble/src/main/res/drawable/ic_nrf70.png rename {app => feature/ble}/src/main/res/drawable/ic_password.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_phone_ok.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_storage.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_upload_wifi.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_version.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_wifi_error.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_wifi_loading.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_wifi_lock.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_wifi_ok.xml (100%) rename {app => feature/ble}/src/main/res/drawable/ic_wifi_open.xml (100%) create mode 100644 feature/ble/src/main/res/values/ic_launcher_background.xml create mode 100644 feature/ble/src/main/res/values/strings.xml diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt index 9b3b8598..ac0bd461 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeDestination.kt @@ -31,17 +31,12 @@ package no.nordicsemi.android.wifi.provisioner -import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreen -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerScreen + val HomeDestinationId = createSimpleDestination("home-destination") -val WifiScannerId = createDestination("wifi-scanner-destination") -val HomeDestinations = listOf( +val HomeDestination = listOf( defineDestination(HomeDestinationId) { HomeScreen() }, - defineDestination(WifiScannerId) { WifiScannerScreen() } ) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt new file mode 100644 index 00000000..0e2de382 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestinationId + +@Composable +fun HomeScreen() { + val vm: SimpleNavigationViewModel = hiltViewModel() + + Scaffold( + topBar = { + + }, + contentWindowInsets = WindowInsets(0, 0, 0, 0), + containerColor = colorResource(id = no.nordicsemi.android.common.theme.R.color.appBarColor), + ) { innerPadding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues = innerPadding) + // .padding(bottom = 16.dp, top = 56.dp) + .consumeWindowInsets(paddingValues = innerPadding) + .windowInsetsPadding( + insets = WindowInsets.safeDrawing.only( + sides = WindowInsetsSides.Horizontal + ), + ) + .windowInsetsPadding( + insets = WindowInsets.safeDrawing.only( + sides = WindowInsetsSides.Vertical + ), + ), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(id = R.string.app_name), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.ExtraBold + ) + Row( + modifier = Modifier + .fillMaxWidth() + .weight(weight = 1f), + horizontalArrangement = Arrangement.Center + ) { + Image( + painter = painterResource(id = R.drawable.ic_nrf70), + contentDescription = stringResource(id = R.string.ic_nrf70), + modifier = Modifier + .widthIn(max = 200.dp) + .padding(8.dp) + .background(Color.White) + ) + } + Row(modifier = Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) { + Button(onClick = { vm.navigateTo(BleProvisioningDestinationId) }) { + Text(text = "Provision over BLE") + } + Button(onClick = { /*TODO*/ }) { + Text(text = "Provision over Wi-Fi") + } + } + Spacer(modifier = Modifier.size(16.dp)) + } + } +} + +@Composable +private fun SectionTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) +} diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt index 6f9c383c..f16417a0 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt @@ -33,6 +33,7 @@ package no.nordicsemi.android.wifi.provisioner import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.ui.Modifier @@ -40,7 +41,7 @@ import dagger.hilt.android.AndroidEntryPoint import no.nordicsemi.android.common.navigation.NavigationView import no.nordicsemi.android.common.theme.NordicActivity import no.nordicsemi.android.common.theme.NordicTheme -import no.nordicsemi.android.wifi.provisioner.scanner.ProvisionerScannerDestination +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestinations @AndroidEntryPoint class MainActivity : NordicActivity() { @@ -48,10 +49,12 @@ class MainActivity : NordicActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { NordicTheme { Surface(modifier = Modifier.fillMaxSize()) { - NavigationView(HomeDestinations + ProvisionerScannerDestination) + NavigationView(HomeDestination + BleProvisioningDestinations) } } } diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 83fa1adb..4d4e28ed 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -58,6 +58,8 @@ dependencies { implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) + implementation(libs.nordic.logger) + implementation(libs.nordic.uilogger) implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.permissions.ble) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt similarity index 99% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt index 2a8659b4..328e0aa3 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/DataItem.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt @@ -63,7 +63,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable fun ErrorDataItem( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/LoadingItem.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/LoadingItem.kt similarity index 100% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/LoadingItem.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/LoadingItem.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/PlaceholderModifier.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/PlaceholderModifier.kt similarity index 100% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/PlaceholderModifier.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/PlaceholderModifier.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt index bf1ad279..0d7ed64c 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt @@ -47,7 +47,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation -import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialogEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt similarity index 100% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/password/PasswordDialogEvent.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt index 61bc842e..1ec75744 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/ProvisionerResourceRepository.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt @@ -47,7 +47,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDoma import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus class ProvisionerResourceRepository( - val repository: ProvisionerRepository + private val repository: ProvisionerRepository ) { suspend fun start(device: BluetoothDevice): Flow { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/RepositoryModule.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt similarity index 100% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/repository/RepositoryModule.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt similarity index 100% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningData.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt similarity index 85% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt index a7a78643..65cf48c5 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningScannerDestinations.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.scanner +package no.nordicsemi.android.wifi.provisioner.ble.scanner import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.navigation.createDestination @@ -40,11 +40,14 @@ import no.nordicsemi.android.kotlin.ble.ui.scanner.DeviceSelected import no.nordicsemi.android.kotlin.ble.ui.scanner.ScannerScreen import no.nordicsemi.android.kotlin.ble.ui.scanner.ScanningCancelled import no.nordicsemi.android.kotlin.ble.ui.scanner.main.DeviceListItem +import no.nordicsemi.android.wifi.provisioner.scanner.ProvisioningData +import no.nordicsemi.android.wifi.provisioner.scanner.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.scanner.provisioningData -val ProvisionerScannerDestinationId = - createDestination("uiscanner-destination") +val BleScannerDestinationId = + createDestination("ble-scanner-destination") -val ProvisionerScannerDestination = defineDestination(ProvisionerScannerDestinationId) { +val BleScannerDestination = defineDestination(BleScannerDestinationId) { val viewModel = hiltViewModel() ScannerScreen( @@ -52,7 +55,7 @@ val ProvisionerScannerDestination = defineDestination(ProvisionerScannerDestinat onResult = { result -> when (result) { is DeviceSelected -> viewModel.navigateUpWithResult( - from = ProvisionerScannerDestinationId, + from = BleScannerDestinationId, result = result.scanResults.device ) ScanningCancelled -> viewModel.navigateUp() diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt index c7eb9ef3..f72d004d 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/scanner/ProvisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt @@ -44,7 +44,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable internal fun ProvisioningSection(data: ProvisioningData) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt similarity index 82% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index 505f77a7..a04945f3 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth @@ -42,18 +42,18 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.HomeViewEntity -import no.nordicsemi.android.wifi.provisioner.home.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.home.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity +import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionClickEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent @Composable -fun ActionButtonSection(viewEntity: HomeViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { +fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { if (viewEntity.isRunning()) { return } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt similarity index 83% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt index 3011bee8..ab0a1170 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DeviceSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -53,10 +53,11 @@ import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.NordicTheme import no.nordicsemi.android.common.theme.view.NordicText import no.nordicsemi.android.kotlin.ble.core.ServerDevice -import no.nordicsemi.android.wifi.provisioner.app.BuildConfig -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectDeviceClickEvent +import no.nordicsemi.android.wifi.provisioner.feature.ble.BuildConfig +import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable @@ -66,7 +67,7 @@ internal fun DeviceSection( onEvent: (HomeScreenViewEvent) -> Unit ) { if (device == null) { - DeviceNotSelectedSection() + DeviceNotSelectedSection(onEvent) } else { BluetoothDevice(device, isEditable, onEvent) } @@ -87,9 +88,22 @@ private fun BluetoothDevice( onEvent(OnSelectDeviceClickEvent) } } +@Composable +private fun DeviceNotSelectedSection( + onEvent: (HomeScreenViewEvent) -> Unit +) { + ClickableDataItem( + iconRes = R.drawable.ic_phone_ok, + title = "Not selected", + isEditable = false, + description = "Please select a device to provision" + ) { + onEvent(OnProvisionNextDeviceEvent) + } +} @Composable -private fun DeviceNotSelectedSection() { +private fun DeviceNotSelectedSection2() { Column(horizontalAlignment = Alignment.CenterHorizontally) { Image( painter = painterResource(id = R.drawable.ic_nrf70), @@ -126,6 +140,6 @@ private fun DeviceNotSelectedSection() { @Composable private fun DeviceNotSelectedSectionPreview() { NordicTheme { - DeviceNotSelectedSection() + DeviceNotSelectedSection {} } } \ No newline at end of file diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt similarity index 94% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt index 154ede5a..e6dcb813 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/DisconnectedDeviceStatus.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem @Composable diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt similarity index 88% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt index 664bba79..efa5d8d0 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/PasswordSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt @@ -29,13 +29,13 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt index 59c4ff46..478da361 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/ProvisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -42,10 +42,9 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem -import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource @@ -53,6 +52,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.common.theme.view.ProgressItem import no.nordicsemi.android.common.theme.view.ProgressItemStatus +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable internal fun ProvisioningSection(status: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt index d82f01b9..c0f0ddfe 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/StatusSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -41,17 +41,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem -import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.home.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable internal fun StatusSection(status: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt index 8fe54857..e7f33901 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/UnprovisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt @@ -36,7 +36,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt index 4fb6d9b2..ebf029b1 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VersionSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt @@ -29,11 +29,10 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem @@ -42,6 +41,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable internal fun VersionSection(version: Resource) { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt similarity index 91% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt index f09c8ead..38aff5fd 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/VolatileMemorySwitch.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -46,9 +46,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable fun VolatileMemorySwitch( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt similarity index 86% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index 91ea103a..91963e4e 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -29,18 +29,18 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem -import no.nordicsemi.android.wifi.provisioner.home.view.toIcon -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable internal fun WifiSection( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt similarity index 63% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index beb1020c..77cffd96 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/components/TopAppBar.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -29,31 +29,19 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.components +package no.nordicsemi.android.wifi.provisioner.ble.view -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.runtime.Composable -import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon -import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.common.navigation.createDestination +import no.nordicsemi.android.common.navigation.createSimpleDestination +import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun BackIconAppBar(text: String, onClick: () -> Unit) { - NordicAppBar( - text = text, - onNavigationButtonClick = onClick - ) -} +val BleProvisioningDestinationId = createSimpleDestination("ble-provisioning-destination") +val WiFiAccessPointsListId = createDestination("wifi-access-points-destination") -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun LoggerIconAppBar(text: String, onLoggerClick: () -> Unit) { - NordicAppBar( - text = text, - actions = { - LoggerAppBarIcon( - onClick = onLoggerClick - ) - } - ) -} +val BleProvisioningDestinations = listOf( + defineDestination(BleProvisioningDestinationId) { BleProvisioningScreen() }, + defineDestination(WiFiAccessPointsListId) { WiFiAccessPointListsScreen() } +) + BleScannerDestination diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt similarity index 75% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index 7039e3b1..d32d8aec 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view +package no.nordicsemi.android.wifi.provisioner.ble.view import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -38,6 +38,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -48,38 +49,47 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import no.nordicsemi.android.wifi.provisioner.home.view.components.LoggerIconAppBar -import no.nordicsemi.android.wifi.provisioner.home.view.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.DeviceSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioner.home.view.sections.PasswordSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.ProvisioningSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.StatusSection +import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon +import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.wifi.provisioner.ble.sections.ActionButtonSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.DeviceSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioner.ble.sections.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.StatusSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.VersionSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.VolatileMemorySwitch +import no.nordicsemi.android.wifi.provisioner.ble.sections.WifiSection +import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.sections.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.VersionSection -import no.nordicsemi.android.wifi.provisioner.home.view.sections.VolatileMemorySwitch -import no.nordicsemi.android.wifi.provisioner.home.view.sections.WifiSection -import no.nordicsemi.android.wifi.provisioner.home.viewmodel.HomeViewModel import no.nordicsemi.android.wifi.provisioner.password.PasswordDialog import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent -import no.nordicsemi.android.wifi.provisioner.app.R +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun HomeScreen() { - val viewModel = hiltViewModel() +fun BleProvisioningScreen() { + val viewModel = hiltViewModel() val state by viewModel.state.collectAsStateWithLifecycle() val onEvent: (HomeScreenViewEvent) -> Unit = { viewModel.onEvent(it) } Scaffold( topBar = { - LoggerIconAppBar(stringResource(id = R.string.app_name)) { - viewModel.onEvent(OpenLoggerEvent) - } + NordicAppBar( + text = stringResource(id = R.string.app_name), + actions = { + LoggerAppBarIcon( + onClick = { viewModel.onEvent(OpenLoggerEvent) } + ) + }, + showBackButton = true, + onNavigationButtonClick = viewModel::navigateUp + ) }, containerColor = MaterialTheme.colorScheme.surface, - ) { - Column(modifier = Modifier.padding(it)) { + ) { paddingValues -> + Column(modifier = Modifier.padding(paddingValues)) { Box(modifier = Modifier.weight(1f)) { Content(state) { viewModel.onEvent(it) } } @@ -96,7 +106,7 @@ fun HomeScreen() { } @Composable -private fun Content(state: HomeViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { +private fun Content(state: BleViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { Column( modifier = Modifier .verticalScroll(rememberScrollState()) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt index 0be30ff4..8758afff 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeScreenViewEvent.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view +package no.nordicsemi.android.wifi.provisioner.ble.view sealed interface HomeScreenViewEvent diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt index 76c9c354..e88ed8cf 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/HomeViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt @@ -29,18 +29,18 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view +package no.nordicsemi.android.wifi.provisioner.ble.view import no.nordicsemi.android.kotlin.ble.core.ServerDevice -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData -data class HomeViewEntity( +data class BleViewEntity( val device: ServerDevice? = null, val version: Resource? = null, val status: Resource? = null, diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt similarity index 97% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt index 1f2a677d..f2371d73 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/view/UiMapper.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt @@ -29,16 +29,16 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view +package no.nordicsemi.android.wifi.provisioner.ble.view import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.BandDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureReasonDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.feature.ble.R @DrawableRes internal fun WifiConnectionStateDomain?.toIcon(): Int { diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt similarity index 78% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 3b0ad88b..13d7691e 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/home/viewmodel/HomeViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.viewmodel +package no.nordicsemi.android.wifi.provisioner.ble.viewmodel -import androidx.lifecycle.ViewModel +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job @@ -45,51 +45,53 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.kotlin.ble.core.RealServerDevice -import no.nordicsemi.android.wifi.provisioner.WifiScannerId import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch -import no.nordicsemi.android.wifi.provisioner.home.view.HomeScreenViewEvent -import no.nordicsemi.android.wifi.provisioner.home.view.HomeViewEntity -import no.nordicsemi.android.wifi.provisioner.home.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnHidePasswordDialog -import no.nordicsemi.android.wifi.provisioner.home.view.OnPasswordSelectedEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectDeviceClickEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.home.view.OnUnprovisionEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OnVolatileMemoryChangedEvent -import no.nordicsemi.android.wifi.provisioner.home.view.OpenLoggerEvent +import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId +import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity +import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnHidePasswordDialog +import no.nordicsemi.android.wifi.provisioner.ble.view.OnPasswordSelectedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionClickEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog +import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioner.scanner.ProvisionerScannerDestinationId -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData import javax.inject.Inject @HiltViewModel -class HomeViewModel @Inject constructor( +class BleViewModel @Inject constructor( private val navigationManager: Navigator, - private val repository: ProvisionerResourceRepository -) : ViewModel() { + private val repository: ProvisionerResourceRepository, + savedStateHandle: SavedStateHandle +) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { private var connectionObserverJob: Job? = null - private val _state = MutableStateFlow(HomeViewEntity()) + private val _state = MutableStateFlow(BleViewEntity()) val state = _state.asStateFlow() private val pendingJobs = mutableListOf() init { - navigationManager.resultFrom(ProvisionerScannerDestinationId) + navigationManager.resultFrom(BleScannerDestinationId) .mapNotNull { it as? NavigationResult.Success } .onEach { installBluetoothDevice(it.value as RealServerDevice) } .launchIn(viewModelScope) - navigationManager.resultFrom(WifiScannerId) + navigationManager.resultFrom(WiFiAccessPointsListId) .mapNotNull { it as? NavigationResult.Success } .onEach { installWifi(it.value) } .launchIn(viewModelScope) @@ -103,7 +105,7 @@ class HomeViewModel @Inject constructor( OnFinishedEvent -> finish() is OnPasswordSelectedEvent -> onPasswordSelected(event.password) OnSelectDeviceClickEvent -> requestBluetoothDevice() - OnSelectWifiEvent -> navigationManager.navigateTo(WifiScannerId) + OnSelectWifiEvent -> navigationManager.navigateTo(WiFiAccessPointsListId) OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() OnShowPasswordDialog -> showPasswordDialog() @@ -128,7 +130,7 @@ class HomeViewModel @Inject constructor( launch { release() } requestBluetoothDevice() delay(500) //nasty delay to prevent screen change before navigation - _state.value = HomeViewEntity() + _state.value = BleViewEntity() } } @@ -154,7 +156,7 @@ class HomeViewModel @Inject constructor( private fun finish() { viewModelScope.launch { release() - _state.value = HomeViewEntity() + _state.value = BleViewEntity() } } @@ -167,7 +169,7 @@ class HomeViewModel @Inject constructor( } private fun requestBluetoothDevice() { - navigationManager.navigateTo(ProvisionerScannerDestinationId) + navigationManager.navigateTo(BleScannerDestinationId) } private fun installWifi(wifiData: WifiData) { @@ -180,7 +182,7 @@ class HomeViewModel @Inject constructor( } private fun installBluetoothDevice(device: RealServerDevice) { - _state.value = HomeViewEntity(device = device, version = Loading()) + _state.value = BleViewEntity(device = device, version = Loading()) viewModelScope.launchWithCatch { release() repository.start(device.device) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt similarity index 95% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt index f7fe7c81..61e5cb4a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/SelectChannelDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -47,9 +47,9 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString @Composable internal fun SelectChannelDialog( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt similarity index 92% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index 865e879b..f9881c3a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -48,6 +48,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -64,25 +65,27 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.BackIconAppBar -import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioner.home.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.home.view.toIcon -import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiScannerViewModel import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel +import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +@OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun WifiScannerScreen() { +internal fun WiFiAccessPointListsScreen() { val viewModel = hiltViewModel() val viewEntity by viewModel.state.collectAsStateWithLifecycle() val onEvent: (WifiScannerViewEvent) -> Unit = { viewModel.onEvent(it) } Column(horizontalAlignment = Alignment.CenterHorizontally) { - BackIconAppBar(stringResource(id = R.string.wifi_title)) { - viewModel.onEvent(NavigateUpEvent) - } + NordicAppBar( + text = stringResource(id = R.string.wifi_title), + onNavigationButtonClick = { viewModel.onEvent(NavigateUpEvent) } + ) if (viewEntity.isLoading) { LoadingItem() diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt similarity index 98% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt index 1535c68b..2f887466 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiLoadingItem.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt similarity index 83% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt index be7f4929..93c3e004 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view -import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, @@ -41,14 +41,11 @@ data class WifiScannerViewEntity( val sortOption: WifiSortOption = WifiSortOption.RSSI, private val items: List = emptyList() ) { - val sortedItems: List - - init { - sortedItems = when (sortOption) { - WifiSortOption.NAME -> items.sortedBy { it.wifiData.ssid } - WifiSortOption.RSSI -> items.sortedByDescending { it.biggestRssi } - } + val sortedItems: List = when (sortOption) { + WifiSortOption.NAME -> items.sortedBy { it.wifiData.ssid } + WifiSortOption.RSSI -> items.sortedByDescending { it.biggestRssi } } + } data class ScanRecordsForSsid( @@ -56,11 +53,8 @@ data class ScanRecordsForSsid( val items: List = emptyList(), ) { - val biggestRssi: Int + val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } - init { - biggestRssi = items.maxOf { it.rssi ?: 0 } - } } data class WifiData( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt similarity index 92% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt index 04d73ee1..4c40b654 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiScannerViewEvent.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view -import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption internal sealed class WifiScannerViewEvent diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt similarity index 94% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt index 7b960e2f..3f0ec8df 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/view/WifiSortView.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.view +package no.nordicsemi.android.wifi.provisioner.ble.wifi.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -43,7 +43,6 @@ import androidx.compose.material.icons.automirrored.filled.Label import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.NetworkWifi import androidx.compose.material3.ElevatedFilterChip -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -53,11 +52,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.common.theme.R as themeR -@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun WifiSortView( sortOption: WifiSortOption, diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt similarity index 92% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt index 7c859a5c..4418e859 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiAggregator.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt @@ -29,10 +29,10 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel -import no.nordicsemi.android.wifi.provisioner.wifi.view.ScanRecordsForSsid -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.ScanRecordsForSsid +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import javax.inject.Inject diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt similarity index 84% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index eaa70d81..abeb6f72 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -40,17 +40,17 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.wifi.provisioner.WifiScannerId import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioner.wifi.view.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioner.wifi.view.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerViewEntity -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioner.wifi.view.WifiSelectedEvent +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.NavigateUpEvent +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.OnSortOptionSelected +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEntity +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId import javax.inject.Inject @HiltViewModel @@ -105,7 +105,7 @@ internal class WifiScannerViewModel @Inject constructor( private fun navigateUp(wifiData: WifiData) { viewModelScope.launch { stopScanning() - navigationManager.navigateUpWithResult(WifiScannerId, wifiData) + navigationManager.navigateUpWithResult(WiFiAccessPointsListId, wifiData) } } } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt similarity index 96% rename from app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt index 6dde02ae..a1edb84d 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/wifi/viewmodel/WifiSortOption.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel enum class WifiSortOption { NAME, RSSI diff --git a/app/src/main/res/drawable/ic_disconnected.xml b/feature/ble/src/main/res/drawable/ic_disconnected.xml similarity index 100% rename from app/src/main/res/drawable/ic_disconnected.xml rename to feature/ble/src/main/res/drawable/ic_disconnected.xml diff --git a/app/src/main/res/drawable/ic_error.xml b/feature/ble/src/main/res/drawable/ic_error.xml similarity index 100% rename from app/src/main/res/drawable/ic_error.xml rename to feature/ble/src/main/res/drawable/ic_error.xml diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/feature/ble/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_background.xml rename to feature/ble/src/main/res/drawable/ic_launcher_background.xml diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/feature/ble/src/main/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_foreground.xml rename to feature/ble/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/app/src/main/res/drawable/ic_no_phone.xml b/feature/ble/src/main/res/drawable/ic_no_phone.xml similarity index 100% rename from app/src/main/res/drawable/ic_no_phone.xml rename to feature/ble/src/main/res/drawable/ic_no_phone.xml diff --git a/app/src/main/res/drawable/ic_no_wifi.xml b/feature/ble/src/main/res/drawable/ic_no_wifi.xml similarity index 100% rename from app/src/main/res/drawable/ic_no_wifi.xml rename to feature/ble/src/main/res/drawable/ic_no_wifi.xml diff --git a/feature/ble/src/main/res/drawable/ic_nrf70.png b/feature/ble/src/main/res/drawable/ic_nrf70.png new file mode 100644 index 0000000000000000000000000000000000000000..7073c85db9da623e2bcff4f032e1d6eda3cecc2b GIT binary patch literal 9040 zcmbtac|4Tu*B8pfV3O=iN_moywFWcfkz{@BvQDz^Te4G(%9bQs49PA_vNOu0sjOKV zyM~yt4rUmP<-K`+@8|vf|IX(#pSkD0uj^droa;K@?>T4YnW4TGJF5UI0|NuQ_MN|t z7#L1afp;Y66mX|KUpWQ%;1AHW2r%|`3J5~_IWnj}@V@VOUfUDt>}ceOd=TvW-BE>s z;lhUY-|8lh#+E0^zGuHTv;4l_LWUScOgN&K#le=Q$Dsn0JJ}lHSHQbm#`9t3GZihb;20FBQ8V zV%(S_=Z4Ra81@tzY43MM*;g*lf5_vg6@Qv$6o9w@DS{SM^4e>6^DqZC*WIQs@YWCOG#>RtLNyh zf{V%Hh6q`q<-fia*Kncv*_mO~ieKY~oacT<7u~Gq`y)3DEQ;dgC?nr05oBGJ`GT$J zr||s=z0DlW5#%stwkYnIcF7X;@;zuB>F_`0$^ zcBOdMl%un}8-ydC+L^D+-sdg1U=8@{G7#|>x&hjVM?H=?k4O-YJzH=+3t}g|=l`gy zL9d;j30aQcS}*$La|rcj_q!=2$Ot>N^DeyAyE5x)?9OV3!bBaHS?t7k2YJjJ3Y~S2 z7^(Adsq`}48#&-7&*msf1Uy&thI)tY?d?|3eC3wSUgY0JOnk1R&L-Gqr!^42A`i++ z9W-(WuqrV#u6y`upP|8)vIwlCt-r!qxfoaQR&~hS)oA#XlJ|`+`a$>VAx%)q-gR&~ zbd^-MeX!ihzdAJ~-t)Su5Kl#lXuqgp`qK6%_{M%EBPR8Q$6@#2ycZ8+2tQA=TRZ$c zQZK=cQT0@pSfNC-=am7z8PVzvYVXvkK8JG}tJ~{g_*w8 z7`W(~jJT}ZV&L(+BS>8YZcH|rvy9#O!y;}@zb=+cmv8yXv6XslFRjdibk}&I$2k|u zQo@IKjwl{?;rssX9zx{zlaos_=+3^kG)-H@)1yA!%FozcQe$S z>KNXsu%5NSkXpWFhem|rn?zb>z29#q;rZhAs8!5HYf@^y;lcn?1as)nDmkW^;fD6u zsiJ-OvlzTB{O+qzFaPEdY&+-jkkn56@6DRxqHr+e=D#|w#lOhFm7sw%7 z>Uq47`Jiy8dW^nt3#V$tmfciJ0S9G`-%`=Z%}>=#Kje*zaG(op+>tUX-+K#0z2!+! z%y3;Es~9aKYIDwlDV8cVik-PtLo#+A&0qhPtmX*Xf5=U8%v$~3L-7;C59aG+wAkjh z+ntSEEt%EER!+0TT@oocx$9LC6f;u==X?A!cBgqKF~P>lqP%=Isp0Jb?9*V|(`4Ix zss7RVY(?T(o)P(O=i6^VS5EL&W_pJ~Lt1Z76F*ordTvdxoc>a<20EO0H+`4>cV2C& zc4;E7;G^X^%?!G=lDTqrU{hk9fvHf|s;$joH~~E?`%&w3q^&Q`IT~YS;6`WbT+$Ec z7+~{eL+ZaaV)U9?ryDy<^?6x!C?B*}HVm#7Nf}U;?W1@>Fcow zdQ0hBcN!AzzH4_i*K8}FGZGD_C0DwQtb>rY`LFW!J#}!{M17$S+DBYTd{Sh(t8srt z{uNrgSsW*p+O7AQYl?e4t6P20``O@y1OSm!w_QYl`$A+GOXurRu>s@~Uo&Y`_$Nk4t@l&Msdl$=_w*(OAyWeT~FS zbGO13wPUr4H^pWYc3(ZtTar}6JLvusuFtstLq$P%2L4+*+i$fkS0PwG6tk{aA={0o zi&JhU`nV!u6f4rv)cH+vq^%c?Yt*L#Grmoe0CojHb8Q5_AkBaRAfRjmDah|&(iNJE{ciWNkNvp^fVlG zacjW^&>d&Gr`|1*&yajtcsp9h7WYhzM_Hfl<-7m<;Cd-6oHD3G1{R*Ho+ zpg!CX6i;hayvVu`!D_WRU9wpm8b@Az3#N+CQPjS|;u-#l%!6?P{$lBWUlRE<~}^CWEK{;#*!HXJW?e>tBE z4(q_XidMT@*#;Hf5)UnRqPRDNs`kADn52mFb>RDE*tECDGZ>F^&njJv=X7nv74fs> zT)eGZq>CzDQ`BbPRxPT-pm#ieaI4Sq)i3K?#fxvwfYb%xT|Hi*mtcAgIGYJ0{TuO; zwO1koZ=_V*vo5SXhi|SSEu5jSg{Jp%#h_^tC{$V{X74Z#K~=7Xo+!N zc#VQmSn>1O&y{6(eetvF^^LD|P~}FnbO^~~SN-1Ro}B(HH$2dUSo>Aq&EcGYO+)zU z_r`%D#bd^T>q$D{NM=~}n>0>^&4XT-U#SZy`;WLM!wk45m5K-9H9n8f+o8YQok0O* z2N3D317q^w7S>6pXQP}_x)?^qJ*mBB_5ruPU0Vuo_y=>PDcU@5aN)@?6&(`UL=fov z({(|%!rZcTDV%@a#@s*Q>R`{=2)r9xBs5xI5o&KkE~6M`8YD8WXRKWiIlKC{OmFJ` z%>!$^=KCa__BOM;!ObThTy)!#VT0@^riIVmQV8n@H+;AU8lJL}#Mua=y&iq2xzl(_ zKhHQ;v}nrUzPQAk2@(0w(MfDOdkrjDBt!*oL0UykpzL*>eyzVE*PhG{L*$YfbM7Nr zHNqKm+tM{NCm;isr=}-kiiun#>b{R; z*1@1#_-oe($`zdkdbszs0zpySBrx)6DXltacgWDmA`308k&&%_BDxpU`%te9zw%5p zYHz{Mxx^6qb}4+oTCc5L=B;I>z~lFp^5!(n$Y#PJ!mH9rNB-r7{w8DO;(ql4o?Wd;w?5$$0GH&?7lqT?X7DU z-@|CFEGfC~uCOPmu}EB3U~Y>&KmC2+?FyNFI3(j2XIG9>CSyD9z#pidVx7f>yF&tJGot^s8 z>$Ano_dlBSow_qdnz~Jc%7g6cyVn(FQ{@%qqzTPC*YXd>bpGl`dOCq#&NUajQJbEq z5mn1Gj&O~rGy6E4#f9CIQe5DB%0cTXr=%f)Cr|9y)ju@wBb3Bl=h{)AfRRQRT3(>o z=>6_$Y&fohfEjgflmUYR++^gKC0foX%P|Aj$Y#|^6$+6k(3~pE40Bjp4&&c4%jJ9a z@keFUZ3%q8caY`AdpA&kVNUsS;|H0eDJ8ucju9?mFaJz|o%yGG!j5kOGQZ0k4Sx<$ zX3UYu@G_u%g@6Jeq~$kGjkY{y=gR+7ET_k%-#!tYv>4WU*AD{yB(PDA6~9!@ z@sLEwd?-rv+3~eOiWlf*rWXq{j9+ZWRBi&3a_22S2ZU78d)40YNS6A&l9^K^H~Hgto5<^omIdiZxjRIGs7H%F=^wADPr>2 z(WfVY8!1P&Sq(D)aQxo_vIx7N@pqMACct~2&mL<7T)hQOisF6k!Xq0VI5>e!h-$); z`!KInRRbj@=7jHnCvTmQ;s0qDyuR5*j8zj4?dwgCyGZxp(3TT&xW-U)k*>^pj#M;Z zN(^xRj{`&`{Cj*{rN$S-y!ZeuH~=j&WdM(j%1q|=Vu(>{&a~Vd>Ea^~u=V&Hx!e{` z%VlEBku0NBJJGxEi2Ve!fC4^54f zOv@K%5M2o)R>@;OKf;EMMeK}lk3>E|W`?+;bO1NXSl5kP_weY?M(#H4_9 z+a6c+aeWj=`Xk##3pT2N4uvvT@e`ab1Z=eZ3m-5pUmX89Y!GcTjohebr**#0^}a!P zgy+UYr(L1JERT;T>CB&%SyOs)*Ou>qLU+OD_fPb#zI*k_SmlUb!cK&T#7Lr1tgT%j zTze0a&(E>T>;Re?bQ&4`?4uHjKNuzW2M?Jomq(Xxtc8`kikRh_XZ#x(ci3={1aekO z%MkDLSIIR<&u?X|Wy;aaA>l{6nMOE&t-HZ@;2d-&w8QHa+8pfUZjq#li`ZKcXO_Y zH=0c^gq(H82E|R}Nbhz+&0 zK>+As`ENMBX*+7NApv-`JdVkQhyMX_+PF0R_Jw1VE`U`<9mguqFd#o-{un3K=oA>@N6IMu@hZ5$cl z8c8%vADxQW-w2lK=l=nCFm z>2>e~61fFJdIwOXETGu@hxffi)QMFySLNiylq)oqZm_y63qM12F8koh!g46b`TigS zIcsSEml+sUdCdTLo$?2sY6gn@@<8(+tIr&w7!wRb0z)asjs%9{8#%+xwIeWZ6tf6M zHozHPX%0I4Trqpy{QzJMQ>VW6E@4e?ofevH9y!Ts*o0^}cHMo9K<8b#SbUbOjU(Dk zlszh%2r|xbN9hEO!aY)1&-d4!?;eazw2)$F`h?E(n?6!dw?QNJZu@QNel61Ij$ix! z2OzJCacX44G7R&;205nNT{fC;xBCNw62sgYkU;0fVRj(JY+-HWe5wRRK=dKYBiWL?haRo|_jj0AB&#_3GMU{Q04WsnCka^!u|~r?fO7%h;khh=#}`IG z#6Q?X%cmBFRaIduV1D z;=lxb%=&-U`oZbKRXEg%A)pOcN4Cp9py{(7QsNzcg!2LEpew2?;cSH$k#cFegD3tB zGi;sd47^+JDD|_(@SyB#CEBh~H~v<6*hb-E4Zxh4UjVj5+H`k5m-pU6uKZ+`)y4iL zsegfHXZHaJ7HmE+6iT;tetssp7meU1RD|6Zdua`H>+{cjmyHMqtBZ?vPp3l`ed*@x zj*K~E7nE@herIMR@R}y*#~@?JUbsVmnSD1ei7izg)Lc&K~( ztn%@}nBchz?)0q_qsdSUt}=L!Pp1XnW7}Veew3}Hc+bAOovF{x;v~+&%KV3SM(j$; z8T>YerzOpns_L(^Lmx)7;n%avuRKIb^*7C7-||;Ndwd*sdLUr4_w5OvBLtjxP;kXq zR4Zgg2Up@NJ2#aBoD~3NG;^aygFQ#=InU86*r!c}ru)mQNxP#@=`{x9xLHr3bWFrf z*zdWnaRgYMSo=FU(Y3;aWz}11L-i0UUSm~*`Eus*0ZkA?ByQi+joU3;aW>*8>DLOj z9|Wg+UFwdn9B@V$m>g;K;l~TbzX9$NtpEOkg-G8D&n+W6n)}l(QuZQ0Yr*mYxqDl!>>o{w^({By0R5{CF@u`Yp z)17%x*=_@eK-G__+seEC*ZjvaAU@{azu^$DFQiGzj*v)`6xxN(_FvRuHe)ZRfqMye0cr z+4EL}ONbuwahMm3N((kRYd0MXCx~R+2MXX4N=vv=ry-0>BS>4+Xs1mouOMauq)?@j1>H|u+&Gfp|eR)RY4JOJH7o&6}9r%}=;m_ugVCl`7> zO*2v@<5frn?9>r(1KB_QK_P!qj3H-va8KfwzxGLVVv;%6-rjCVsWf zKUNPhlpGV1(rktuWN#<$@RUVLm7j(ReC#14BTHtA0jEPeH=p1Qry=eM`(*=3#H89hy z@K+H!+nGMC;nSzKKZM6rk;fws4F&^wG)gbe82|^1_?C|EQy+Tfu|RkgTo% zb&n`u#HENA@>pM7zKA{_RN+@d->&1>IvKILz2BGpahULY`J8}NY~^t#Uw>wi_xjK^ z>sQWc5%pNS(@#eM6|e7EMmfAK3tcXZHb7wJ^Y`AC^td{NRaf>P$tnq0j+wS&zYYh# zaYN{Zv%TK!NGJuIR}3qDW7wY1<3~WU!m9uzhzM?*vr|rP4>Bf*&|Vd`N$bEZ3Zq_fATSK$^*#oabg>CW>%69kor6w)kFvi-% z?rPFO_~GQl+h+BFZv*?UKQK<-Bm}ie?VRM-IW}bBq2K8(^Rmr~GHTbgRuL^5!J#p- z-8AE9-GEdxjPv07}Iis5C*KO5R#8p{hYOV&Rk&(;Q>RIuU(E-rEkew2;=K2$}vRUmomc1(DMHl$@d` zu~#sF4U>%a0-9_SkQcrsas2Nf7YrO?JH4K$PKZbJhqcUA>!?+>bZNXm2)m6AyQiP@ zQhwdGI--t#UsgQfAUB~5trLrXR2^dkC+E9yHWa%>tvtLR;CvGjbZbpTtgX#FK z;l1fc7arCm##)aNxu&4gc15S#X?dtcm2KeX2*C`m;*a(r!>ACKry)`!l+v+mU8(qw zeRHOQiv;HTZJhL7Sh&KHkcm}3zGo55Au> z+$6P!{X}fs&|KZurrED<{$b@qSnk7icQ(ox)1*EmKD+Z)(g|cx#Lz&tO%V>8Y1J+4LbKjU10q z%fV!K6a(SlkZ>R|bpT5wh+vveCV7}D3ryg9!KHqY(!zR4+H}lt5Ev%|m zTe|wSGR)P!n+LE{d$! + + #00A9CE + \ No newline at end of file diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml new file mode 100644 index 00000000..40c22dd7 --- /dev/null +++ b/feature/ble/src/main/res/values/strings.xml @@ -0,0 +1,143 @@ + + + + nRF Wi-Fi Provisioner + + Change + An icon of nRF70 Series + The nRF Wi-Fi Provisioner app allows provisioning nRF 700x devices to + Wi-Fi networks over Bluetooth LE.\n\n + + ### Key features:\n + * Provisioning nRF 700x devices to Wi-Fi networks.\n + * Displaying connection status of provisioned devices.\n + * Re-provisioning already provisioned devices to alternate networks.\n\n + + ### Requirements:\n + * [nRF700x DK](https://www.nordicsemi.com/News/2022/08/Nordic-Semiconductor-announces-its-first-WiFi-chip).\n + * Wi-Fi Provisioning Service sample programmed.\n\n + + Make sure the device is powered ON and in range. + + Device status + Provisioning data + Upload status + + Unknown error + + 1. Make sure the device is turned on and is connected to a power source. + + Unprovisioned + Start + Select device + Next device + Finish + Set password + Password + **** **** + Dismiss + Accept + Clear + + Device status + Disconnected + Wi-Fi status + Selected Wi-Fi + Start provisioning + Version + Scanning error + Unprovision + Select password + Provision + Provisioning status + Unrovisioning status + Success + + Icon representing data available in the section. + + Connecting + Authentication + Association + Obtaining IP + Connected + Disconnected + Unprovisioned + Error occurred during provisioning. + Icon indicating wifi and it\'s authentication method. + + Wi-Fi + + IPv4: %s + SSID: %s + BSSID: %s + Band: %s + Band: %s, Channel: %s + Channel: %s + 2.4 GHz + 5 GHz + Any + + Authentication error. + The specified network could not be find. + Timeout occurred. + Could not obtain IP from provided provisioning information. + Could not connect to provisioned network. + + Connection info + Wi-Fi info + + Scan params + Passive: %s + Period: %s [ms] + Group channels: %s + + Hide password + Show password + Version: %s (%s) + + Disconnected + Authentication + Association + Obtaining IP + Result + Connected + Connection failed + + V %d + Select Wi-Fi + + Persistent storage + + Sort by: + Name + RSSI + \ No newline at end of file From 6d6b0025c8358d6e229cb9cce3d39849b88b813c Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 14 Feb 2024 13:53:41 +0100 Subject: [PATCH 009/101] More refactoring Rename event name. --- .../ble/sections/ActionButtonSection.kt | 4 +- .../provisioner/ble/sections/DeviceSection.kt | 63 ++----------------- .../ble/sections/PasswordSection.kt | 4 +- .../ble/sections/VolatileMemorySwitch.kt | 4 +- .../provisioner/ble/sections/WifiSection.kt | 4 +- .../ble/view/BleProvisioningScreen.kt | 4 +- .../ble/view/BleScreenViewEvent.kt | 24 +++---- .../provisioner/ble/viewmodel/BleViewModel.kt | 4 +- 8 files changed, 29 insertions(+), 82 deletions(-) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index a04945f3..eaaedfed 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -43,7 +43,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionClickEvent @@ -53,7 +53,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent @Composable -fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { +fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (BleProvisioningViewEvent) -> Unit) { if (viewEntity.isRunning()) { return } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt index ab0a1170..2d1a28f7 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt @@ -31,40 +31,21 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.NordicTheme -import no.nordicsemi.android.common.theme.view.NordicText import no.nordicsemi.android.kotlin.ble.core.ServerDevice -import no.nordicsemi.android.wifi.provisioner.feature.ble.BuildConfig -import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent +import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable internal fun DeviceSection( device: ServerDevice?, isEditable: Boolean = false, - onEvent: (HomeScreenViewEvent) -> Unit + onEvent: (BleProvisioningViewEvent) -> Unit ) { if (device == null) { DeviceNotSelectedSection(onEvent) @@ -77,7 +58,7 @@ internal fun DeviceSection( private fun BluetoothDevice( device: ServerDevice, isEditable: Boolean = false, - onEvent: (HomeScreenViewEvent) -> Unit + onEvent: (BleProvisioningViewEvent) -> Unit ) { ClickableDataItem( iconRes = R.drawable.ic_phone_ok, @@ -90,7 +71,7 @@ private fun BluetoothDevice( } @Composable private fun DeviceNotSelectedSection( - onEvent: (HomeScreenViewEvent) -> Unit + onEvent: (BleProvisioningViewEvent) -> Unit ) { ClickableDataItem( iconRes = R.drawable.ic_phone_ok, @@ -102,40 +83,6 @@ private fun DeviceNotSelectedSection( } } -@Composable -private fun DeviceNotSelectedSection2() { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Image( - painter = painterResource(id = R.drawable.ic_nrf70), - contentDescription = stringResource(id = R.string.ic_nrf70), - modifier = Modifier - .widthIn(max = 200.dp) - .padding(8.dp) - .background(Color.White) - ) - - Spacer(modifier = Modifier.size(16.dp)) - - NordicText( - text = stringResource(id = R.string.app_info), - style = MaterialTheme.typography.bodyMedium - ) - - Spacer(modifier = Modifier.size(32.dp)) - - Text( - text = stringResource( - id = R.string.app_version, - BuildConfig.VERSION_NAME, - BuildConfig.VERSION_CODE - ), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.End, - style = MaterialTheme.typography.labelMedium - ) - } -} - @Preview @Composable private fun DeviceNotSelectedSectionPreview() { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt index efa5d8d0..08924adc 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt @@ -33,13 +33,13 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem @Composable -internal fun PasswordSection(isEditable: Boolean = false, onEvent: (HomeScreenViewEvent) -> Unit) { +internal fun PasswordSection(isEditable: Boolean = false, onEvent: (BleProvisioningViewEvent) -> Unit) { ClickableDataItem( iconRes = R.drawable.ic_password, title = stringResource(id = R.string.password), diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt index 38aff5fd..99f3ed2f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt @@ -46,7 +46,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R @@ -54,7 +54,7 @@ import no.nordicsemi.android.wifi.provisioner.feature.ble.R fun VolatileMemorySwitch( volatileMemory: Boolean, enabled: Boolean, - onEvent: (HomeScreenViewEvent) -> Unit + onEvent: (BleProvisioningViewEvent) -> Unit ) { Row( modifier = Modifier diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index 91963e4e..8351e260 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -34,7 +34,7 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon @@ -46,7 +46,7 @@ import no.nordicsemi.android.wifi.provisioner.feature.ble.R internal fun WifiSection( record: WifiData, isEditable: Boolean = false, - onEvent: (HomeScreenViewEvent) -> Unit + onEvent: (BleProvisioningViewEvent) -> Unit ) { Column { ClickableDataItem( diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index d32d8aec..495f2866 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -72,7 +72,7 @@ fun BleProvisioningScreen() { val viewModel = hiltViewModel() val state by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (HomeScreenViewEvent) -> Unit = { viewModel.onEvent(it) } + val onEvent: (BleProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } Scaffold( topBar = { @@ -106,7 +106,7 @@ fun BleProvisioningScreen() { } @Composable -private fun Content(state: BleViewEntity, onEvent: (HomeScreenViewEvent) -> Unit) { +private fun Content(state: BleViewEntity, onEvent: (BleProvisioningViewEvent) -> Unit) { Column( modifier = Modifier .verticalScroll(rememberScrollState()) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt index 8758afff..7973c2f8 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt @@ -31,26 +31,26 @@ package no.nordicsemi.android.wifi.provisioner.ble.view -sealed interface HomeScreenViewEvent +sealed interface BleProvisioningViewEvent -data object OnSelectDeviceClickEvent : HomeScreenViewEvent +data object OnSelectDeviceClickEvent : BleProvisioningViewEvent -data object OnFinishedEvent : HomeScreenViewEvent +data object OnFinishedEvent : BleProvisioningViewEvent -data object OnProvisionNextDeviceEvent : HomeScreenViewEvent +data object OnProvisionNextDeviceEvent : BleProvisioningViewEvent -data object OnSelectWifiEvent : HomeScreenViewEvent +data object OnSelectWifiEvent : BleProvisioningViewEvent -data object OnShowPasswordDialog : HomeScreenViewEvent +data object OnShowPasswordDialog : BleProvisioningViewEvent -data object OnHidePasswordDialog : HomeScreenViewEvent +data object OnHidePasswordDialog : BleProvisioningViewEvent -data class OnPasswordSelectedEvent(val password: String) : HomeScreenViewEvent +data class OnPasswordSelectedEvent(val password: String) : BleProvisioningViewEvent -data object OnProvisionClickEvent : HomeScreenViewEvent +data object OnProvisionClickEvent : BleProvisioningViewEvent -data object OpenLoggerEvent : HomeScreenViewEvent +data object OpenLoggerEvent : BleProvisioningViewEvent -data object OnUnprovisionEvent : HomeScreenViewEvent +data object OnUnprovisionEvent : BleProvisioningViewEvent -data object OnVolatileMemoryChangedEvent : HomeScreenViewEvent +data object OnVolatileMemoryChangedEvent : BleProvisioningViewEvent diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 13d7691e..33cf3f91 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -54,7 +54,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity -import no.nordicsemi.android.wifi.provisioner.ble.view.HomeScreenViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnHidePasswordDialog import no.nordicsemi.android.wifi.provisioner.ble.view.OnPasswordSelectedEvent @@ -97,7 +97,7 @@ class BleViewModel @Inject constructor( .launchIn(viewModelScope) } - fun onEvent(event: HomeScreenViewEvent) { + fun onEvent(event: BleProvisioningViewEvent) { if (event != OpenLoggerEvent) { cancelPendingJobs() } From d4863b9b319411805d591e0c8d1f02b4ff3f30df Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 15 Feb 2024 10:33:09 +0100 Subject: [PATCH 010/101] Adds SoftApProvisioning landing screen --- app/src/main/AndroidManifest.xml | 2 +- .../android/wifi/provisioner/HomeScreen.kt | 8 +-- .../android/wifi/provisioner/MainActivity.kt | 7 ++- app/src/main/res/values/strings.xml | 2 +- .../ble/view/BleProvisioningScreen.kt | 36 +++++------ feature/ble/src/main/res/values/strings.xml | 2 +- feature/softap/build.gradle.kts | 3 +- .../softap/view/SoftApDestinations.kt | 14 +++++ .../softap/view/SoftApProvisioningScreen.kt | 60 +++++++++++++++++++ .../softap/src/main/res/values/strings.xml | 4 ++ 10 files changed, 105 insertions(+), 33 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt create mode 100644 feature/softap/src/main/res/values/strings.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ef4ed705..fe28d8a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,7 +37,7 @@ android:name="no.nordicsemi.android.wifi.provisioner.WifiProvisionerApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" - android:label="@string/app_name" + android:label="@string/label_ble_provisioner" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/NordicTheme" diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 0e2de382..8c6d784a 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -65,15 +65,13 @@ import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestinationId +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestinationId @Composable fun HomeScreen() { val vm: SimpleNavigationViewModel = hiltViewModel() Scaffold( - topBar = { - - }, contentWindowInsets = WindowInsets(0, 0, 0, 0), containerColor = colorResource(id = no.nordicsemi.android.common.theme.R.color.appBarColor), ) { innerPadding -> @@ -96,7 +94,7 @@ fun HomeScreen() { horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = stringResource(id = R.string.app_name), + text = stringResource(id = R.string.label_ble_provisioner), style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.ExtraBold ) @@ -119,7 +117,7 @@ fun HomeScreen() { Button(onClick = { vm.navigateTo(BleProvisioningDestinationId) }) { Text(text = "Provision over BLE") } - Button(onClick = { /*TODO*/ }) { + Button(onClick = { vm.navigateTo(SoftApProvisionerDestinationId) }) { Text(text = "Provision over Wi-Fi") } } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt index f16417a0..14643c85 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt @@ -42,6 +42,7 @@ import no.nordicsemi.android.common.navigation.NavigationView import no.nordicsemi.android.common.theme.NordicActivity import no.nordicsemi.android.common.theme.NordicTheme import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestinations +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestinations @AndroidEntryPoint class MainActivity : NordicActivity() { @@ -54,7 +55,11 @@ class MainActivity : NordicActivity() { setContent { NordicTheme { Surface(modifier = Modifier.fillMaxSize()) { - NavigationView(HomeDestination + BleProvisioningDestinations) + NavigationView( + destinations = HomeDestination + + BleProvisioningDestinations + + SoftApProvisionerDestinations + ) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40c22dd7..b82ba295 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,7 +30,7 @@ --> - nRF Wi-Fi Provisioner + nRF Wi-Fi Provisioner Change An icon of nRF70 Series diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index 495f2866..e9c1afe4 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -40,7 +40,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -73,28 +72,21 @@ fun BleProvisioningScreen() { val state by viewModel.state.collectAsStateWithLifecycle() val onEvent: (BleProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } - - Scaffold( - topBar = { - NordicAppBar( - text = stringResource(id = R.string.app_name), - actions = { - LoggerAppBarIcon( - onClick = { viewModel.onEvent(OpenLoggerEvent) } - ) - }, - showBackButton = true, - onNavigationButtonClick = viewModel::navigateUp - ) - }, - containerColor = MaterialTheme.colorScheme.surface, - ) { paddingValues -> - Column(modifier = Modifier.padding(paddingValues)) { - Box(modifier = Modifier.weight(1f)) { - Content(state) { viewModel.onEvent(it) } - } - ActionButtonSection(state, onEvent) + Column { + NordicAppBar( + text = stringResource(id = R.string.label_ble_provisioner), + actions = { + LoggerAppBarIcon( + onClick = { viewModel.onEvent(OpenLoggerEvent) } + ) + }, + showBackButton = true, + onNavigationButtonClick = viewModel::navigateUp + ) + Box(modifier = Modifier.weight(1f)) { + Content(state) { viewModel.onEvent(it) } } + ActionButtonSection(state, onEvent) } if (state.showPasswordDialog == true) { diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml index 40c22dd7..cdb17c49 100644 --- a/feature/ble/src/main/res/values/strings.xml +++ b/feature/ble/src/main/res/values/strings.xml @@ -30,7 +30,7 @@ --> - nRF Wi-Fi Provisioner + Bluetooth LE Change An icon of nRF70 Series diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index f15e6c2e..f4b366b1 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -57,8 +57,7 @@ dependencies { implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) - implementation(libs.nordic.blek.uiscanner) - implementation(libs.nordic.permissions.ble) + implementation(libs.nordic.uilogger) implementation(libs.accompanist.placeholder) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt new file mode 100644 index 00000000..e1a34750 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -0,0 +1,14 @@ +package no.nordicsemi.android.wifi.provisioner.softap.view + +import no.nordicsemi.android.common.navigation.createSimpleDestination +import no.nordicsemi.android.common.navigation.defineDestination + +/** + * Created by Roshan Rajaratnam on 14/02/2024. + */ + +val SoftApProvisionerDestinationId = createSimpleDestination("softap-provider-destination") + +val SoftApProvisionerDestinations = listOf( + defineDestination(SoftApProvisionerDestinationId) { SoftApProvisioningScreen() } +) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt new file mode 100644 index 00000000..b13b941d --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.view + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.hilt.navigation.compose.hiltViewModel +import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.wifi.provisioner.feature.softap.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SoftApProvisioningScreen() { + val viewModel = hiltViewModel() + Column { + NordicAppBar( + text = stringResource(id = R.string.label_wifi_provisioner), + actions = { + LoggerAppBarIcon( + onClick = { /*TODO*/ } + ) + }, + showBackButton = true, + onNavigationButtonClick = viewModel::navigateUp + ) + } +} diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml new file mode 100644 index 00000000..e3d8c39f --- /dev/null +++ b/feature/softap/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + "Wi-Fi Provisioner " + \ No newline at end of file From 4a3b316da894e8553b3e4c9ce5b7e6f46acfb727 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 19 Feb 2024 12:28:10 +0100 Subject: [PATCH 011/101] General improvements --- app/src/main/res/values/strings.xml | 1 - feature/ble/build.gradle.kts | 1 + .../ble/password/PasswordDialog.kt | 5 +- .../provisioner/ble/sections/DeviceSection.kt | 26 ++- .../ble/sections/DisconnectedDeviceStatus.kt | 6 +- .../ble/sections/PasswordSection.kt | 16 +- .../ble/sections/ProvisioningSection.kt | 14 +- .../provisioner/ble/sections/StatusSection.kt | 12 +- .../ble/sections/UnprovisioningSection.kt | 12 +- .../ble/sections/VersionSection.kt | 10 +- .../provisioner/ble/sections/WifiSection.kt | 16 +- .../ble/view/BleProvisioningScreen.kt | 5 +- .../wifi/provisioner/ble/view/UiMapper.kt | 97 ++++----- .../wifi/view/WiFiAccessPointListsScreen.kt | 11 +- .../ble/wifi/view/WifiLoadingItem.kt | 2 +- feature/softap/build.gradle.kts | 1 + feature/softap/src/main/AndroidManifest.xml | 7 +- .../softap/sections/WifiDeviceSection.kt | 24 +++ .../softap/sections/WifiSection.kt | 25 +++ .../softap/view/SoftApProvisioningScreen.kt | 130 ++++++++++- .../softap/viewmodel/SoftApViewModel.kt | 63 ++++++ .../softap/src/main/res/values/strings.xml | 4 + feature/ui/.gitignore | 1 + feature/ui/build.gradle.kts | 48 +++++ feature/ui/consumer-rules.pro | 0 feature/ui/proguard-rules.pro | 21 ++ feature/ui/src/main/AndroidManifest.xml | 2 + .../android/wifi/provisioner/ui}/DataItem.kt | 37 ++-- .../wifi/provisioner/ui}/LoadingItem.kt | 2 +- .../provisioner/ui}/PlaceholderModifier.kt | 2 +- .../main/res/drawable/ic_disconnected.xml} | 4 +- feature/ui/src/main/res/drawable/ic_error.xml | 38 ++++ .../res/drawable/ic_launcher_background.xml | 201 ++++++++++++++++++ .../res/drawable/ic_launcher_foreground.xml | 54 +++++ feature/ui/src/main/res/drawable/ic_nrf70.png | Bin 0 -> 9040 bytes feature/ui/src/main/res/values/strings.xml | 5 + settings.gradle.kts | 1 + 37 files changed, 766 insertions(+), 138 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt create mode 100644 feature/ui/.gitignore create mode 100644 feature/ui/build.gradle.kts create mode 100644 feature/ui/consumer-rules.pro create mode 100644 feature/ui/proguard-rules.pro create mode 100644 feature/ui/src/main/AndroidManifest.xml rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/DataItem.kt (90%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/LoadingItem.kt (98%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/PlaceholderModifier.kt (96%) rename feature/{ble/src/main/res/drawable/ic_phone_ok.xml => ui/src/main/res/drawable/ic_disconnected.xml} (79%) create mode 100644 feature/ui/src/main/res/drawable/ic_error.xml create mode 100644 feature/ui/src/main/res/drawable/ic_launcher_background.xml create mode 100644 feature/ui/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 feature/ui/src/main/res/drawable/ic_nrf70.png create mode 100644 feature/ui/src/main/res/values/strings.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b82ba295..9b34b9ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -82,7 +82,6 @@ Unrovisioning status Success - Icon representing data available in the section. Connecting Authentication diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 4d4e28ed..ff479da6 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -40,6 +40,7 @@ android { dependencies { implementation(project(":lib:ble:provisioner")) + implementation(project(":feature:ui")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt index 0d7ed64c..c2ad4b53 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.password +package no.nordicsemi.android.wifi.provisioner.ble.password import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Visibility @@ -48,6 +48,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.password.DismissEvent +import no.nordicsemi.android.wifi.provisioner.password.PasswordDialogEvent +import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt index 2d1a28f7..18c662a7 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt @@ -31,7 +31,10 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.PhoneAndroid import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import no.nordicsemi.android.common.theme.NordicTheme import no.nordicsemi.android.kotlin.ble.core.ServerDevice @@ -39,7 +42,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem @Composable internal fun DeviceSection( @@ -61,26 +64,27 @@ private fun BluetoothDevice( onEvent: (BleProvisioningViewEvent) -> Unit ) { ClickableDataItem( - iconRes = R.drawable.ic_phone_ok, + imageVector = Icons.Outlined.PhoneAndroid, title = device.name ?: device.address, isEditable = isEditable, - description = device.address - ) { - onEvent(OnSelectDeviceClickEvent) - } + description = device.address, + onClick = { onEvent(OnSelectDeviceClickEvent) }, + buttonText = stringResource(id = R.string.change_device) + ) } + @Composable private fun DeviceNotSelectedSection( onEvent: (BleProvisioningViewEvent) -> Unit ) { ClickableDataItem( - iconRes = R.drawable.ic_phone_ok, + imageVector = Icons.Outlined.PhoneAndroid, title = "Not selected", isEditable = false, - description = "Please select a device to provision" - ) { - onEvent(OnProvisionNextDeviceEvent) - } + description = "Please select a device to provision", + onClick = { onEvent(OnProvisionNextDeviceEvent) }, + buttonText = stringResource(id = R.string.change_device) + ) } @Preview diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt index e6dcb813..0979d298 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt @@ -31,15 +31,17 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.LinkOff import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.DataItem @Composable fun DisconnectedDeviceStatus() { DataItem( - iconRes = R.drawable.ic_disconnected, + imageVector = Icons.Outlined.LinkOff, title = stringResource(id = R.string.device_info), description = stringResource(id = R.string.disconnected) ) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt index 08924adc..85ae6237 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt @@ -31,21 +31,25 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Password import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem @Composable internal fun PasswordSection(isEditable: Boolean = false, onEvent: (BleProvisioningViewEvent) -> Unit) { ClickableDataItem( - iconRes = R.drawable.ic_password, + imageVector = Icons.Outlined.Password, title = stringResource(id = R.string.password), isEditable = isEditable, - description = stringResource(id = R.string.password_encoded) - ) { - onEvent(OnShowPasswordDialog) - } + description = stringResource(id = R.string.password_encoded), + onClick = { + onEvent(OnShowPasswordDialog) + }, + buttonText = stringResource(id = R.string.set_password) + ) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt index 478da361..d723a6e5 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt @@ -36,23 +36,25 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Wifi import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem -import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString +import no.nordicsemi.android.common.theme.view.ProgressItem +import no.nordicsemi.android.common.theme.view.ProgressItemStatus import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain -import no.nordicsemi.android.common.theme.view.ProgressItem -import no.nordicsemi.android.common.theme.view.ProgressItemStatus +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem @Composable internal fun ProvisioningSection(status: Resource) { @@ -82,7 +84,7 @@ private fun ProvisioningSection( errorMessage: String? = null ) { DataItem( - iconRes = R.drawable.ic_upload_wifi, + imageVector = Icons.Default.Wifi, title = stringResource(id = R.string.provision_status), description = status.toDisplayString(), isInitiallyExpanded = true diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt index c0f0ddfe..5329bc00 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt @@ -41,17 +41,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem @Composable internal fun StatusSection(status: Resource) { @@ -75,7 +75,7 @@ private fun ErrorSection(error: Throwable) { private fun StatusSection(status: DeviceStatusDomain) { if (status.isContentEmpty()) { DataItem( - iconRes = status.wifiState.toIcon(), + imageVector = status.wifiState.toImageVector(), title = stringResource(id = R.string.status_info), description = status.wifiState.toDisplayString() ) @@ -83,7 +83,7 @@ private fun StatusSection(status: DeviceStatusDomain) { } DataItem( - iconRes = status.wifiState.toIcon(), + imageVector = status.wifiState.toImageVector(), title = stringResource(id = R.string.status_info), description = status.wifiState.toDisplayString() ) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt index e7f33901..4782bcb5 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt @@ -29,21 +29,23 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.sections +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.SignalWifiStatusbar4Bar import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ui.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem @Composable internal fun UnprovisioningSection(status: Resource) { @@ -67,7 +69,7 @@ private fun ErrorItem(error: Throwable) { @Composable private fun ProvisioningSection() { DataItem( - iconRes = R.drawable.ic_upload_wifi, + imageVector = Icons.Default.SignalWifiStatusbar4Bar, title = stringResource(id = R.string.unprovision_status), description = stringResource(id = R.string.success) ) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt index ebf029b1..4c88b75d 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt @@ -31,17 +31,19 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Code import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.home.view.components.DataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem -import no.nordicsemi.android.wifi.provisioner.home.view.components.LoadingItem import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem @Composable internal fun VersionSection(version: Resource) { @@ -64,7 +66,7 @@ private fun ErrorSection(error: Throwable) { @Composable private fun VersionSection(version: VersionDomain) { DataItem( - iconRes = R.drawable.ic_version, + imageVector = Icons.Default.Code, title = stringResource(id = R.string.dk_version), description = version.value.toString() ) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index 8351e260..a7ecd4ae 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -36,11 +36,11 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.home.view.components.ClickableDataItem -import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem @Composable internal fun WifiSection( @@ -50,13 +50,15 @@ internal fun WifiSection( ) { Column { ClickableDataItem( - iconRes = record.authMode.toIcon(), + imageVector = record.authMode.toImageVector(), title = stringResource(id = R.string.selected_wifi), isEditable = isEditable, - description = record.selectedChannel?.let { getDescription(record = it) } ?: record.ssid - ) { - onEvent(OnSelectWifiEvent) - } + description = record.selectedChannel?.let { getDescription(record = it) } ?: record.ssid, + onClick = { + onEvent(OnSelectWifiEvent) + }, + buttonText = stringResource(id = R.string.change_device) + ) } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index e9c1afe4..a8e4a66b 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -61,8 +61,8 @@ import no.nordicsemi.android.wifi.provisioner.ble.sections.VolatileMemorySwitch import no.nordicsemi.android.wifi.provisioner.ble.sections.WifiSection import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.sections.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioner.password.PasswordDialog +import no.nordicsemi.android.wifi.provisioner.ble.sections.UnprovisioningSection +import no.nordicsemi.android.wifi.provisioner.ble.password.PasswordDialog import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent @OptIn(ExperimentalMaterial3Api::class) @@ -87,6 +87,7 @@ fun BleProvisioningScreen() { Content(state) { viewModel.onEvent(it) } } ActionButtonSection(state, onEvent) + Spacer(modifier = Modifier.size(16.dp)) } if (state.showPasswordDialog == true) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt index f2371d73..52f5a49a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt @@ -31,7 +31,14 @@ package no.nordicsemi.android.wifi.provisioner.ble.view -import androidx.annotation.DrawableRes +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.SignalWifi4Bar +import androidx.compose.material.icons.filled.SignalWifiOff +import androidx.compose.material.icons.filled.SignalWifiStatusbarConnectedNoInternet4 +import androidx.compose.material.icons.filled.WifiFind +import androidx.compose.material.icons.outlined.SignalWifi4BarLock +import androidx.compose.material.icons.outlined.SignalWifiStatusbarConnectedNoInternet4 +import androidx.compose.material.icons.outlined.Wifi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain @@ -40,62 +47,50 @@ import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureRe import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R -@DrawableRes -internal fun WifiConnectionStateDomain?.toIcon(): Int { - return when (this) { - WifiConnectionStateDomain.DISCONNECTED -> R.drawable.ic_wifi_error - WifiConnectionStateDomain.AUTHENTICATION, - WifiConnectionStateDomain.ASSOCIATION, - WifiConnectionStateDomain.OBTAINING_IP -> R.drawable.ic_wifi_loading - WifiConnectionStateDomain.CONNECTED -> R.drawable.ic_wifi_ok - WifiConnectionStateDomain.CONNECTION_FAILED -> R.drawable.ic_wifi_error - null -> R.drawable.ic_no_wifi - } +internal fun WifiConnectionStateDomain?.toImageVector() = when (this) { + WifiConnectionStateDomain.DISCONNECTED -> Icons.Outlined.SignalWifiStatusbarConnectedNoInternet4 + WifiConnectionStateDomain.AUTHENTICATION, + WifiConnectionStateDomain.ASSOCIATION, + WifiConnectionStateDomain.OBTAINING_IP -> Icons.Default.WifiFind + WifiConnectionStateDomain.CONNECTED -> Icons.Default.SignalWifi4Bar + WifiConnectionStateDomain.CONNECTION_FAILED -> Icons.Default.SignalWifiStatusbarConnectedNoInternet4 + null -> Icons.Default.SignalWifiOff } @Composable -internal fun WifiConnectionStateDomain?.toDisplayString(): String { - return when (this) { - WifiConnectionStateDomain.DISCONNECTED -> R.string.wifi_status_disconnected - WifiConnectionStateDomain.AUTHENTICATION -> R.string.wifi_status_authentication - WifiConnectionStateDomain.ASSOCIATION -> R.string.wifi_status_association - WifiConnectionStateDomain.OBTAINING_IP -> R.string.wifi_status_obtaining_ip - WifiConnectionStateDomain.CONNECTED -> R.string.wifi_status_connected - WifiConnectionStateDomain.CONNECTION_FAILED -> R.string.wifi_status_error - null -> R.string.wifi_status_unprovisioned - }.let { stringResource(id = it) } -} +internal fun WifiConnectionStateDomain?.toDisplayString() = when (this) { + WifiConnectionStateDomain.DISCONNECTED -> R.string.wifi_status_disconnected + WifiConnectionStateDomain.AUTHENTICATION -> R.string.wifi_status_authentication + WifiConnectionStateDomain.ASSOCIATION -> R.string.wifi_status_association + WifiConnectionStateDomain.OBTAINING_IP -> R.string.wifi_status_obtaining_ip + WifiConnectionStateDomain.CONNECTED -> R.string.wifi_status_connected + WifiConnectionStateDomain.CONNECTION_FAILED -> R.string.wifi_status_error + null -> R.string.wifi_status_unprovisioned +}.let { stringResource(id = it) } -@DrawableRes -internal fun AuthModeDomain?.toIcon(): Int { - return when (this) { - AuthModeDomain.OPEN -> R.drawable.ic_wifi_open - AuthModeDomain.WEP, - AuthModeDomain.WPA_PSK, - AuthModeDomain.WPA2_PSK, - AuthModeDomain.WPA_WPA2_PSK, - AuthModeDomain.WPA2_ENTERPRISE, - AuthModeDomain.WPA3_PSK, - null -> R.drawable.ic_wifi_lock - } +internal fun AuthModeDomain?.toImageVector() = when (this) { + AuthModeDomain.OPEN -> Icons.Outlined.Wifi + AuthModeDomain.WEP, + AuthModeDomain.WPA_PSK, + AuthModeDomain.WPA2_PSK, + AuthModeDomain.WPA_WPA2_PSK, + AuthModeDomain.WPA2_ENTERPRISE, + AuthModeDomain.WPA3_PSK, + null -> Icons.Outlined.SignalWifi4BarLock } @Composable -internal fun BandDomain.toDisplayString(): String { - return when (this) { - BandDomain.BAND_ANY -> R.string.any - BandDomain.BAND_2_4_GH -> R.string.band_2_4 - BandDomain.BAND_5_GH -> R.string.band_5 - }.let { stringResource(id = it) } -} +internal fun BandDomain.toDisplayString() = when (this) { + BandDomain.BAND_ANY -> R.string.any + BandDomain.BAND_2_4_GH -> R.string.band_2_4 + BandDomain.BAND_5_GH -> R.string.band_5 +}.let { stringResource(id = it) } @Composable -internal fun WifiConnectionFailureReasonDomain.toDisplayString(): String { - return when (this) { - WifiConnectionFailureReasonDomain.AUTH_ERROR -> R.string.error_auth - WifiConnectionFailureReasonDomain.NETWORK_NOT_FOUND -> R.string.error_network_not_found - WifiConnectionFailureReasonDomain.TIMEOUT -> R.string.error_timeout - WifiConnectionFailureReasonDomain.FAIL_IP -> R.string.error_ip_fail - WifiConnectionFailureReasonDomain.FAIL_CONN -> R.string.error_fail_connection - }.let { stringResource(id = it) } -} +internal fun WifiConnectionFailureReasonDomain.toDisplayString() = when (this) { + WifiConnectionFailureReasonDomain.AUTH_ERROR -> R.string.error_auth + WifiConnectionFailureReasonDomain.NETWORK_NOT_FOUND -> R.string.error_network_not_found + WifiConnectionFailureReasonDomain.TIMEOUT -> R.string.error_timeout + WifiConnectionFailureReasonDomain.FAIL_IP -> R.string.error_ip_fail + WifiConnectionFailureReasonDomain.FAIL_CONN -> R.string.error_fail_connection +}.let { stringResource(id = it) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index f9881c3a..bbe2a0c7 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -60,7 +60,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -69,10 +68,10 @@ import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ble.view.toIcon +import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.home.view.components.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -111,9 +110,7 @@ private fun LoadingItem() { @Composable private fun ErrorItem(error: Throwable) { - Box( - modifier = Modifier.padding(16.dp) - ) { + Box(modifier = Modifier.padding(16.dp)) { ErrorDataItem( iconRes = R.drawable.ic_error, title = stringResource(id = R.string.wifi_scanning), @@ -168,7 +165,7 @@ private fun WifiItem(records: ScanRecordsForSsid, onEvent: (WifiScannerViewEvent verticalAlignment = Alignment.CenterVertically ) { Icon( - painter = painterResource(id = wifiData.authMode.toIcon()), + imageVector = wifiData.authMode.toImageVector(), contentDescription = stringResource(id = R.string.cd_wifi_icon), tint = MaterialTheme.colorScheme.onPrimary, modifier = Modifier diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt index 2f887466..59f1844c 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt @@ -48,7 +48,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.home.view.components.applyPlaceholder +import no.nordicsemi.android.wifi.provisioner.ui.applyPlaceholder @Composable fun WifiLoadingItem() { diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index f4b366b1..bc05c45d 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -40,6 +40,7 @@ android { dependencies { + implementation(project(":feature:ui")) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.compose.ui) diff --git a/feature/softap/src/main/AndroidManifest.xml b/feature/softap/src/main/AndroidManifest.xml index a5918e68..6fc79c92 100644 --- a/feature/softap/src/main/AndroidManifest.xml +++ b/feature/softap/src/main/AndroidManifest.xml @@ -1,4 +1,9 @@ - + + + \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt new file mode 100644 index 00000000..98e3d188 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt @@ -0,0 +1,24 @@ +package no.nordicsemi.android.wifi.provisioner.softap.sections + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem + +/** + * Created by Roshan Rajaratnam on 19/02/2024. + */ + +@Composable +fun WifiDeviceNotSelected(onClick: () -> Unit) { + ClickableDataItem( + imageVector = Icons.Outlined.Wifi, + title = "Not selected", + isEditable = false, + description = "Please setup the Wi-Fi network", + onClick = onClick, + buttonText = stringResource(id = R.string.change_wifi) + ) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt new file mode 100644 index 00000000..49db0149 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt @@ -0,0 +1,25 @@ +package no.nordicsemi.android.wifi.provisioner.softap.sections + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.SignalWifiConnectedNoInternet4 +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem + +/** + * Created by Roshan Rajaratnam on 16/02/2024. + */ +@Composable +private fun WifiNotSelectedSection( + onClick: () -> Unit +) { + ClickableDataItem( + imageVector = Icons.Outlined.SignalWifiConnectedNoInternet4, + title = "Not selected", + isEditable = false, + description = "Please select a device to provision", + onClick = onClick, + buttonText = stringResource(id = R.string.setup_wifi) + ) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index b13b941d..7e4f5422 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -31,21 +31,69 @@ package no.nordicsemi.android.wifi.provisioner.softap.view +import android.content.Context +import android.net.ConnectivityManager +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon -import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.sections.WifiDeviceNotSelected +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApViewModel +@RequiresApi(Build.VERSION_CODES.Q) @OptIn(ExperimentalMaterial3Api::class) @Composable fun SoftApProvisioningScreen() { - val viewModel = hiltViewModel() - Column { + val viewModel = hiltViewModel() + val context = LocalContext.current + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + var ssid by rememberSaveable { mutableStateOf("mobileappsrules") } + var password by rememberSaveable { mutableStateOf("") } + var showDialog by rememberSaveable { mutableStateOf(false) } + var showPassword by rememberSaveable { mutableStateOf(false) } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 56.dp) + ) { NordicAppBar( text = stringResource(id = R.string.label_wifi_provisioner), actions = { @@ -56,5 +104,81 @@ fun SoftApProvisioningScreen() { showBackButton = true, onNavigationButtonClick = viewModel::navigateUp ) + Column( + modifier = Modifier + .weight(1f) + .padding(horizontal = 16.dp) + ) { + Spacer(modifier = Modifier.size(12.dp)) + WifiDeviceNotSelected { showDialog = true } + Spacer(modifier = Modifier.size(12.dp)) + } + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Button(onClick = { showDialog = true }) { + Text(text = "Setup Wi-Fi") + } + } + } + + if (showDialog) { + AlertDialog( + onDismissRequest = { showDialog = false }, + icon = { + Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) + }, + title = { + Text( + text = "Setup Wi-fi", + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + Column { + Text( + text = "Please provide the Wi-Fi SSID and the Password", + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.size(size = 16.dp)) + OutlinedTextField(value = ssid, onValueChange = { ssid = it }) + Spacer(modifier = Modifier.size(size = 8.dp)) + OutlinedTextField( + value = password, + onValueChange = { password = it }, + visualTransformation = if(showPassword) + VisualTransformation.None + else + PasswordVisualTransformation(), + trailingIcon = { + IconButton(onClick = { showPassword = !showPassword }) { + Icon( + imageVector = if (!showPassword) + Icons.Outlined.Visibility + else Icons.Outlined.VisibilityOff, + contentDescription = null + ) + } + } + ) + } + }, + dismissButton = { + TextButton( + onClick = { + showDialog = false + } + ) { Text(text = "Cancel") } + }, + confirmButton = { + TextButton( + onClick = { + showDialog = false + viewModel.connect(connectivityManager) + } + ) { Text(text = "Confirm") } + } + ) } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt new file mode 100644 index 00000000..84548cb2 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -0,0 +1,63 @@ +package no.nordicsemi.android.wifi.provisioner.softap.viewmodel + +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.net.wifi.WifiNetworkSpecifier +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import javax.inject.Inject + +/** + * Created by Roshan Rajaratnam on 15/02/2024. + */ +@HiltViewModel +class SoftApViewModel @Inject constructor( + navigator: Navigator, + savedStateHandle: SavedStateHandle +) : SimpleNavigationViewModel(navigator = navigator, savedStateHandle = savedStateHandle) { + + val wifiConfigFlow = MutableStateFlow(null) + var network: Network? = null + private set + + @RequiresApi(Build.VERSION_CODES.Q) + fun connect(connectivityManager: ConnectivityManager, ssid: String = "mobileappsrules") { + val specifier = WifiNetworkSpecifier.Builder() + .setSsid(ssid) + .setWpa2Passphrase("") + .build() + + val request = NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .setNetworkSpecifier(specifier) + .build() + + val networkCallback = object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + // do success processing here.. + this@SoftApViewModel.network = network + Log.d("AAAA", "Wifi connected") + } + + override fun onUnavailable() { + // do failure processing here.. + Log.d("AAAA", "Something went wrong!") + } + } + connectivityManager.requestNetwork(request, networkCallback) + } + + +} + +data class WifiConfig(val ssid: String, val password:String) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index e3d8c39f..b7643082 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -1,4 +1,8 @@ "Wi-Fi Provisioner " + Setup Wi-Fi + Change Wi-Fi + Dismiss + Confirm \ No newline at end of file diff --git a/feature/ui/.gitignore b/feature/ui/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/ui/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/ui/build.gradle.kts b/feature/ui/build.gradle.kts new file mode 100644 index 00000000..96fe1487 --- /dev/null +++ b/feature/ui/build.gradle.kts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +plugins { + alias(libs.plugins.nordic.feature) +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioner.ui" +} + +dependencies { + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.iconsExtended) + + implementation(libs.accompanist.placeholder) +} diff --git a/feature/ui/consumer-rules.pro b/feature/ui/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/ui/proguard-rules.pro b/feature/ui/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/ui/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/ui/src/main/AndroidManifest.xml b/feature/ui/src/main/AndroidManifest.xml new file mode 100644 index 00000000..568741e5 --- /dev/null +++ b/feature/ui/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt similarity index 90% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt index 328e0aa3..af24bf57 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/DataItem.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.components +package no.nordicsemi.android.wifi.provisioner.ui import androidx.annotation.DrawableRes import androidx.compose.animation.AnimatedVisibility @@ -48,6 +48,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.ArrowDropUp +import androidx.compose.material.icons.outlined.Code import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -58,12 +59,12 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable fun ErrorDataItem( @@ -97,13 +98,12 @@ fun ErrorDataItem( @Composable fun DataItem( - @DrawableRes - iconRes: Int, + imageVector: ImageVector, title: String, description: String ) { DataItem( - iconRes = iconRes, + imageVector = imageVector, title = title, description = description, isExpanded = null @@ -112,12 +112,12 @@ fun DataItem( @Composable fun ClickableDataItem( - @DrawableRes - iconRes: Int, + imageVector: ImageVector, title: String, description: String, isEditable: Boolean = false, - onClick: () -> Unit + onClick: () -> Unit, + buttonText:String ) { Row( modifier = Modifier @@ -128,7 +128,7 @@ fun ClickableDataItem( ) { Box(modifier = Modifier.weight(1f)) { DataItem( - iconRes = iconRes, + imageVector = imageVector, title = title, description = description, isExpanded = null @@ -138,16 +138,13 @@ fun ClickableDataItem( TextButton( onClick = { onClick() }, enabled = isEditable - ) { - Text(text = stringResource(id = R.string.change_device)) - } + ) { Text(text = buttonText) } } } @Composable fun DataItem( - @DrawableRes - iconRes: Int, + imageVector: ImageVector, title: String, description: String, isInitiallyExpanded: Boolean = false, @@ -162,7 +159,7 @@ fun DataItem( .padding(vertical = 8.dp) ) { DataItem( - iconRes = iconRes, + imageVector = imageVector, title = title, description = description, isExpanded = isExpanded.value @@ -184,15 +181,14 @@ fun DataItem( @Composable private fun DataItem( - @DrawableRes - iconRes: Int, + imageVector: ImageVector, title: String, description: String, isExpanded: Boolean? ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( - painter = painterResource(id = iconRes), + imageVector = imageVector, contentDescription = stringResource(id = R.string.cd_data_item_icon) ) @@ -214,6 +210,7 @@ private fun DataItem( } } + @Composable private fun ExpandedIcon(isExpanded: Boolean) { val icon = if (isExpanded) { @@ -227,11 +224,11 @@ private fun ExpandedIcon(isExpanded: Boolean) { @Preview @Composable private fun DataItemPreview() { - DataItem(iconRes = R.drawable.ic_version, title = "Title", description = "Description") + DataItem(imageVector = Icons.Outlined.Code, title = "Title", description = "Description") { } } @Preview @Composable private fun DataItemExpandedPreview() { - DataItem(iconRes = R.drawable.ic_version, title = "Title", description = "Description") { } + DataItem(imageVector = Icons.Outlined.Code, title = "Title", description = "Description") { } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/LoadingItem.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/LoadingItem.kt similarity index 98% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/LoadingItem.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/LoadingItem.kt index 1ae29c84..96f2df2e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/LoadingItem.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/LoadingItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.components +package no.nordicsemi.android.wifi.provisioner.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/PlaceholderModifier.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PlaceholderModifier.kt similarity index 96% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/PlaceholderModifier.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PlaceholderModifier.kt index 4e09a1bc..d73e438b 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/components/PlaceholderModifier.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PlaceholderModifier.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.home.view.components +package no.nordicsemi.android.wifi.provisioner.ui import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable diff --git a/feature/ble/src/main/res/drawable/ic_phone_ok.xml b/feature/ui/src/main/res/drawable/ic_disconnected.xml similarity index 79% rename from feature/ble/src/main/res/drawable/ic_phone_ok.xml rename to feature/ui/src/main/res/drawable/ic_disconnected.xml index d5ac4579..e7b219f4 100644 --- a/feature/ble/src/main/res/drawable/ic_phone_ok.xml +++ b/feature/ui/src/main/res/drawable/ic_disconnected.xml @@ -35,6 +35,6 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:fillColor="#FF000000" + android:pathData="M4,1C2.89,1 2,1.89 2,3V7C2,8.11 2.89,9 4,9H1V11H13V9H10C11.11,9 12,8.11 12,7V3C12,1.89 11.11,1 10,1H4M4,3H10V7H4V3M14,13C12.89,13 12,13.89 12,15V19C12,20.11 12.89,21 14,21H11V23H23V21H20C21.11,21 22,20.11 22,19V15C22,13.89 21.11,13 20,13H14M3.88,13.46L2.46,14.88L4.59,17L2.46,19.12L3.88,20.54L6,18.41L8.12,20.54L9.54,19.12L7.41,17L9.54,14.88L8.12,13.46L6,15.59L3.88,13.46M14,15H20V19H14V15Z"/> diff --git a/feature/ui/src/main/res/drawable/ic_error.xml b/feature/ui/src/main/res/drawable/ic_error.xml new file mode 100644 index 00000000..effdb42b --- /dev/null +++ b/feature/ui/src/main/res/drawable/ic_error.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/feature/ui/src/main/res/drawable/ic_launcher_background.xml b/feature/ui/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..59b53bf6 --- /dev/null +++ b/feature/ui/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml b/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..8e36a423 --- /dev/null +++ b/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,54 @@ + + + + + + + + + + diff --git a/feature/ui/src/main/res/drawable/ic_nrf70.png b/feature/ui/src/main/res/drawable/ic_nrf70.png new file mode 100644 index 0000000000000000000000000000000000000000..7073c85db9da623e2bcff4f032e1d6eda3cecc2b GIT binary patch literal 9040 zcmbtac|4Tu*B8pfV3O=iN_moywFWcfkz{@BvQDz^Te4G(%9bQs49PA_vNOu0sjOKV zyM~yt4rUmP<-K`+@8|vf|IX(#pSkD0uj^droa;K@?>T4YnW4TGJF5UI0|NuQ_MN|t z7#L1afp;Y66mX|KUpWQ%;1AHW2r%|`3J5~_IWnj}@V@VOUfUDt>}ceOd=TvW-BE>s z;lhUY-|8lh#+E0^zGuHTv;4l_LWUScOgN&K#le=Q$Dsn0JJ}lHSHQbm#`9t3GZihb;20FBQ8V zV%(S_=Z4Ra81@tzY43MM*;g*lf5_vg6@Qv$6o9w@DS{SM^4e>6^DqZC*WIQs@YWCOG#>RtLNyh zf{V%Hh6q`q<-fia*Kncv*_mO~ieKY~oacT<7u~Gq`y)3DEQ;dgC?nr05oBGJ`GT$J zr||s=z0DlW5#%stwkYnIcF7X;@;zuB>F_`0$^ zcBOdMl%un}8-ydC+L^D+-sdg1U=8@{G7#|>x&hjVM?H=?k4O-YJzH=+3t}g|=l`gy zL9d;j30aQcS}*$La|rcj_q!=2$Ot>N^DeyAyE5x)?9OV3!bBaHS?t7k2YJjJ3Y~S2 z7^(Adsq`}48#&-7&*msf1Uy&thI)tY?d?|3eC3wSUgY0JOnk1R&L-Gqr!^42A`i++ z9W-(WuqrV#u6y`upP|8)vIwlCt-r!qxfoaQR&~hS)oA#XlJ|`+`a$>VAx%)q-gR&~ zbd^-MeX!ihzdAJ~-t)Su5Kl#lXuqgp`qK6%_{M%EBPR8Q$6@#2ycZ8+2tQA=TRZ$c zQZK=cQT0@pSfNC-=am7z8PVzvYVXvkK8JG}tJ~{g_*w8 z7`W(~jJT}ZV&L(+BS>8YZcH|rvy9#O!y;}@zb=+cmv8yXv6XslFRjdibk}&I$2k|u zQo@IKjwl{?;rssX9zx{zlaos_=+3^kG)-H@)1yA!%FozcQe$S z>KNXsu%5NSkXpWFhem|rn?zb>z29#q;rZhAs8!5HYf@^y;lcn?1as)nDmkW^;fD6u zsiJ-OvlzTB{O+qzFaPEdY&+-jkkn56@6DRxqHr+e=D#|w#lOhFm7sw%7 z>Uq47`Jiy8dW^nt3#V$tmfciJ0S9G`-%`=Z%}>=#Kje*zaG(op+>tUX-+K#0z2!+! z%y3;Es~9aKYIDwlDV8cVik-PtLo#+A&0qhPtmX*Xf5=U8%v$~3L-7;C59aG+wAkjh z+ntSEEt%EER!+0TT@oocx$9LC6f;u==X?A!cBgqKF~P>lqP%=Isp0Jb?9*V|(`4Ix zss7RVY(?T(o)P(O=i6^VS5EL&W_pJ~Lt1Z76F*ordTvdxoc>a<20EO0H+`4>cV2C& zc4;E7;G^X^%?!G=lDTqrU{hk9fvHf|s;$joH~~E?`%&w3q^&Q`IT~YS;6`WbT+$Ec z7+~{eL+ZaaV)U9?ryDy<^?6x!C?B*}HVm#7Nf}U;?W1@>Fcow zdQ0hBcN!AzzH4_i*K8}FGZGD_C0DwQtb>rY`LFW!J#}!{M17$S+DBYTd{Sh(t8srt z{uNrgSsW*p+O7AQYl?e4t6P20``O@y1OSm!w_QYl`$A+GOXurRu>s@~Uo&Y`_$Nk4t@l&Msdl$=_w*(OAyWeT~FS zbGO13wPUr4H^pWYc3(ZtTar}6JLvusuFtstLq$P%2L4+*+i$fkS0PwG6tk{aA={0o zi&JhU`nV!u6f4rv)cH+vq^%c?Yt*L#Grmoe0CojHb8Q5_AkBaRAfRjmDah|&(iNJE{ciWNkNvp^fVlG zacjW^&>d&Gr`|1*&yajtcsp9h7WYhzM_Hfl<-7m<;Cd-6oHD3G1{R*Ho+ zpg!CX6i;hayvVu`!D_WRU9wpm8b@Az3#N+CQPjS|;u-#l%!6?P{$lBWUlRE<~}^CWEK{;#*!HXJW?e>tBE z4(q_XidMT@*#;Hf5)UnRqPRDNs`kADn52mFb>RDE*tECDGZ>F^&njJv=X7nv74fs> zT)eGZq>CzDQ`BbPRxPT-pm#ieaI4Sq)i3K?#fxvwfYb%xT|Hi*mtcAgIGYJ0{TuO; zwO1koZ=_V*vo5SXhi|SSEu5jSg{Jp%#h_^tC{$V{X74Z#K~=7Xo+!N zc#VQmSn>1O&y{6(eetvF^^LD|P~}FnbO^~~SN-1Ro}B(HH$2dUSo>Aq&EcGYO+)zU z_r`%D#bd^T>q$D{NM=~}n>0>^&4XT-U#SZy`;WLM!wk45m5K-9H9n8f+o8YQok0O* z2N3D317q^w7S>6pXQP}_x)?^qJ*mBB_5ruPU0Vuo_y=>PDcU@5aN)@?6&(`UL=fov z({(|%!rZcTDV%@a#@s*Q>R`{=2)r9xBs5xI5o&KkE~6M`8YD8WXRKWiIlKC{OmFJ` z%>!$^=KCa__BOM;!ObThTy)!#VT0@^riIVmQV8n@H+;AU8lJL}#Mua=y&iq2xzl(_ zKhHQ;v}nrUzPQAk2@(0w(MfDOdkrjDBt!*oL0UykpzL*>eyzVE*PhG{L*$YfbM7Nr zHNqKm+tM{NCm;isr=}-kiiun#>b{R; z*1@1#_-oe($`zdkdbszs0zpySBrx)6DXltacgWDmA`308k&&%_BDxpU`%te9zw%5p zYHz{Mxx^6qb}4+oTCc5L=B;I>z~lFp^5!(n$Y#PJ!mH9rNB-r7{w8DO;(ql4o?Wd;w?5$$0GH&?7lqT?X7DU z-@|CFEGfC~uCOPmu}EB3U~Y>&KmC2+?FyNFI3(j2XIG9>CSyD9z#pidVx7f>yF&tJGot^s8 z>$Ano_dlBSow_qdnz~Jc%7g6cyVn(FQ{@%qqzTPC*YXd>bpGl`dOCq#&NUajQJbEq z5mn1Gj&O~rGy6E4#f9CIQe5DB%0cTXr=%f)Cr|9y)ju@wBb3Bl=h{)AfRRQRT3(>o z=>6_$Y&fohfEjgflmUYR++^gKC0foX%P|Aj$Y#|^6$+6k(3~pE40Bjp4&&c4%jJ9a z@keFUZ3%q8caY`AdpA&kVNUsS;|H0eDJ8ucju9?mFaJz|o%yGG!j5kOGQZ0k4Sx<$ zX3UYu@G_u%g@6Jeq~$kGjkY{y=gR+7ET_k%-#!tYv>4WU*AD{yB(PDA6~9!@ z@sLEwd?-rv+3~eOiWlf*rWXq{j9+ZWRBi&3a_22S2ZU78d)40YNS6A&l9^K^H~Hgto5<^omIdiZxjRIGs7H%F=^wADPr>2 z(WfVY8!1P&Sq(D)aQxo_vIx7N@pqMACct~2&mL<7T)hQOisF6k!Xq0VI5>e!h-$); z`!KInRRbj@=7jHnCvTmQ;s0qDyuR5*j8zj4?dwgCyGZxp(3TT&xW-U)k*>^pj#M;Z zN(^xRj{`&`{Cj*{rN$S-y!ZeuH~=j&WdM(j%1q|=Vu(>{&a~Vd>Ea^~u=V&Hx!e{` z%VlEBku0NBJJGxEi2Ve!fC4^54f zOv@K%5M2o)R>@;OKf;EMMeK}lk3>E|W`?+;bO1NXSl5kP_weY?M(#H4_9 z+a6c+aeWj=`Xk##3pT2N4uvvT@e`ab1Z=eZ3m-5pUmX89Y!GcTjohebr**#0^}a!P zgy+UYr(L1JERT;T>CB&%SyOs)*Ou>qLU+OD_fPb#zI*k_SmlUb!cK&T#7Lr1tgT%j zTze0a&(E>T>;Re?bQ&4`?4uHjKNuzW2M?Jomq(Xxtc8`kikRh_XZ#x(ci3={1aekO z%MkDLSIIR<&u?X|Wy;aaA>l{6nMOE&t-HZ@;2d-&w8QHa+8pfUZjq#li`ZKcXO_Y zH=0c^gq(H82E|R}Nbhz+&0 zK>+As`ENMBX*+7NApv-`JdVkQhyMX_+PF0R_Jw1VE`U`<9mguqFd#o-{un3K=oA>@N6IMu@hZ5$cl z8c8%vADxQW-w2lK=l=nCFm z>2>e~61fFJdIwOXETGu@hxffi)QMFySLNiylq)oqZm_y63qM12F8koh!g46b`TigS zIcsSEml+sUdCdTLo$?2sY6gn@@<8(+tIr&w7!wRb0z)asjs%9{8#%+xwIeWZ6tf6M zHozHPX%0I4Trqpy{QzJMQ>VW6E@4e?ofevH9y!Ts*o0^}cHMo9K<8b#SbUbOjU(Dk zlszh%2r|xbN9hEO!aY)1&-d4!?;eazw2)$F`h?E(n?6!dw?QNJZu@QNel61Ij$ix! z2OzJCacX44G7R&;205nNT{fC;xBCNw62sgYkU;0fVRj(JY+-HWe5wRRK=dKYBiWL?haRo|_jj0AB&#_3GMU{Q04WsnCka^!u|~r?fO7%h;khh=#}`IG z#6Q?X%cmBFRaIduV1D z;=lxb%=&-U`oZbKRXEg%A)pOcN4Cp9py{(7QsNzcg!2LEpew2?;cSH$k#cFegD3tB zGi;sd47^+JDD|_(@SyB#CEBh~H~v<6*hb-E4Zxh4UjVj5+H`k5m-pU6uKZ+`)y4iL zsegfHXZHaJ7HmE+6iT;tetssp7meU1RD|6Zdua`H>+{cjmyHMqtBZ?vPp3l`ed*@x zj*K~E7nE@herIMR@R}y*#~@?JUbsVmnSD1ei7izg)Lc&K~( ztn%@}nBchz?)0q_qsdSUt}=L!Pp1XnW7}Veew3}Hc+bAOovF{x;v~+&%KV3SM(j$; z8T>YerzOpns_L(^Lmx)7;n%avuRKIb^*7C7-||;Ndwd*sdLUr4_w5OvBLtjxP;kXq zR4Zgg2Up@NJ2#aBoD~3NG;^aygFQ#=InU86*r!c}ru)mQNxP#@=`{x9xLHr3bWFrf z*zdWnaRgYMSo=FU(Y3;aWz}11L-i0UUSm~*`Eus*0ZkA?ByQi+joU3;aW>*8>DLOj z9|Wg+UFwdn9B@V$m>g;K;l~TbzX9$NtpEOkg-G8D&n+W6n)}l(QuZQ0Yr*mYxqDl!>>o{w^({By0R5{CF@u`Yp z)17%x*=_@eK-G__+seEC*ZjvaAU@{azu^$DFQiGzj*v)`6xxN(_FvRuHe)ZRfqMye0cr z+4EL}ONbuwahMm3N((kRYd0MXCx~R+2MXX4N=vv=ry-0>BS>4+Xs1mouOMauq)?@j1>H|u+&Gfp|eR)RY4JOJH7o&6}9r%}=;m_ugVCl`7> zO*2v@<5frn?9>r(1KB_QK_P!qj3H-va8KfwzxGLVVv;%6-rjCVsWf zKUNPhlpGV1(rktuWN#<$@RUVLm7j(ReC#14BTHtA0jEPeH=p1Qry=eM`(*=3#H89hy z@K+H!+nGMC;nSzKKZM6rk;fws4F&^wG)gbe82|^1_?C|EQy+Tfu|RkgTo% zb&n`u#HENA@>pM7zKA{_RN+@d->&1>IvKILz2BGpahULY`J8}NY~^t#Uw>wi_xjK^ z>sQWc5%pNS(@#eM6|e7EMmfAK3tcXZHb7wJ^Y`AC^td{NRaf>P$tnq0j+wS&zYYh# zaYN{Zv%TK!NGJuIR}3qDW7wY1<3~WU!m9uzhzM?*vr|rP4>Bf*&|Vd`N$bEZ3Zq_fATSK$^*#oabg>CW>%69kor6w)kFvi-% z?rPFO_~GQl+h+BFZv*?UKQK<-Bm}ie?VRM-IW}bBq2K8(^Rmr~GHTbgRuL^5!J#p- z-8AE9-GEdxjPv07}Iis5C*KO5R#8p{hYOV&Rk&(;Q>RIuU(E-rEkew2;=K2$}vRUmomc1(DMHl$@d` zu~#sF4U>%a0-9_SkQcrsas2Nf7YrO?JH4K$PKZbJhqcUA>!?+>bZNXm2)m6AyQiP@ zQhwdGI--t#UsgQfAUB~5trLrXR2^dkC+E9yHWa%>tvtLR;CvGjbZbpTtgX#FK z;l1fc7arCm##)aNxu&4gc15S#X?dtcm2KeX2*C`m;*a(r!>ACKry)`!l+v+mU8(qw zeRHOQiv;HTZJhL7Sh&KHkcm}3zGo55Au> z+$6P!{X}fs&|KZurrED<{$b@qSnk7icQ(ox)1*EmKD+Z)(g|cx#Lz&tO%V>8Y1J+4LbKjU10q z%fV!K6a(SlkZ>R|bpT5wh+vveCV7}D3ryg9!KHqY(!zR4+H}lt5Ev%|m zTe|wSGR)P!n+LE{d$! + + Icon representing data available in the section. + Unknown Error + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 9a2c52d4..552afb7f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -68,3 +68,4 @@ include(":lib:softap") //if (file('../Android-BLE-Library').exists()) { // includeBuild('../Android-BLE-Library') //} +include(":feature:ui") From 32544f2faeb4c47245a018c3298c7ba739150d14 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 26 Feb 2024 14:37:24 +0100 Subject: [PATCH 012/101] Adds support for a SoftAP provisioning --- app/src/main/AndroidManifest.xml | 3 +- feature/softap/build.gradle.kts | 9 +- feature/softap/src/main/AndroidManifest.xml | 3 + .../softap/di/DispatchersModule.kt | 37 +++++ .../softap/di/SoftApManagerModule.kt | 32 ++++ .../softap/view/SoftApProvisioningScreen.kt | 11 +- .../softap/viewmodel/SoftApViewModel.kt | 83 +++++----- lib/softap/build.gradle.kts | 10 +- lib/softap/src/main/AndroidManifest.xml | 5 +- .../softap/NetworkServiceDiscoveryListener.kt | 46 ++++++ .../provisioner/softap/ProvisioningState.kt | 34 +++++ .../wifi/provisioner/softap/SoftApManager.kt | 142 ++++++++++++++++++ .../wifi/provisioner/softap/WifiService.kt | 27 ++++ .../softap/credentials/Credentials.kt | 8 + .../softap/di/WifiServiceModule.kt | 98 ++++++++++++ 15 files changed, 503 insertions(+), 45 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt create mode 100644 lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fe28d8a3..98b886f6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,12 +36,13 @@ + tools:targetApi="tiramisu"> + + + \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt new file mode 100644 index 00000000..8c035bdc --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt @@ -0,0 +1,37 @@ +/* + * + * * Copyright (c) 2022, Nordic Semiconductor + * * + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package no.nordicsemi.android.wifi.provisioner.softap.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import javax.inject.Qualifier + +@Module +@InstallIn(SingletonComponent::class) +class DispatchersModule { + @Provides + @DefaultDispatcher + fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default + + @Provides + @IODispatcher + fun provideIODispatcher(): CoroutineDispatcher = Dispatchers.IO +} + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class DefaultDispatcher + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class IODispatcher \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt new file mode 100644 index 00000000..02c33eb0 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt @@ -0,0 +1,32 @@ +package no.nordicsemi.android.wifi.provisioner.softap.di + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.WifiService +import javax.inject.Singleton + +/** + * Created by Roshan Rajaratnam on 22/02/2024. + */ +@Module +@InstallIn(SingletonComponent::class) +object SoftApManagerModule { + + @Provides + @Singleton + fun provideSoftApManager( + @ApplicationContext context: Context, + wifiService: WifiService, + @IODispatcher coroutineDispatcher: CoroutineDispatcher + ) = SoftApManager( + context = context, + wifiService = wifiService, + coroutineDispatcher = coroutineDispatcher + ) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 7e4f5422..40612421 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -31,8 +31,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.view -import android.content.Context -import android.net.ConnectivityManager import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Arrangement @@ -80,9 +78,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApViewModel @Composable fun SoftApProvisioningScreen() { val viewModel = hiltViewModel() - val context = LocalContext.current - val connectivityManager = - context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + LocalContext.current var ssid by rememberSaveable { mutableStateOf("mobileappsrules") } var password by rememberSaveable { mutableStateOf("") } @@ -175,7 +171,10 @@ fun SoftApProvisioningScreen() { TextButton( onClick = { showDialog = false - viewModel.connect(connectivityManager) + viewModel.connect( + ssid = ssid, + password = password + ) } ) { Text(text = "Confirm") } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 84548cb2..9dbb9222 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -1,18 +1,20 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel -import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.net.NetworkRequest -import android.net.wifi.WifiNetworkSpecifier import android.os.Build import android.util.Log import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.wifi.provisioner.softap.ProvisioningState +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.credentials.Credentials import javax.inject.Inject /** @@ -21,43 +23,54 @@ import javax.inject.Inject @HiltViewModel class SoftApViewModel @Inject constructor( navigator: Navigator, - savedStateHandle: SavedStateHandle + savedStateHandle: SavedStateHandle, + private val softApManager: SoftApManager ) : SimpleNavigationViewModel(navigator = navigator, savedStateHandle = savedStateHandle) { - val wifiConfigFlow = MutableStateFlow(null) - var network: Network? = null - private set + init { + softApManager.provisioningState.onEach { + when (it) { + ProvisioningState.Disconnected -> {} + ProvisioningState.Connecting -> {} + ProvisioningState.Connected -> { + provision() + } + ProvisioningState.Provisioning -> {} + ProvisioningState.ProvisioningComplete -> {} + } + }.launchIn(viewModelScope) + } @RequiresApi(Build.VERSION_CODES.Q) - fun connect(connectivityManager: ConnectivityManager, ssid: String = "mobileappsrules") { - val specifier = WifiNetworkSpecifier.Builder() - .setSsid(ssid) - .setWpa2Passphrase("") - .build() - - val request = NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .setNetworkSpecifier(specifier) - .build() - - val networkCallback = object : ConnectivityManager.NetworkCallback() { + internal fun connect(ssid: String = "mobileappsrules", password: String) { + softApManager.connect(ssid = ssid, password = password) + } - override fun onAvailable(network: Network) { - // do success processing here.. - this@SoftApViewModel.network = network - Log.d("AAAA", "Wifi connected") - } + internal fun listSsids() { + val handler = CoroutineExceptionHandler { _, t -> + Log.e("AAAA", "$t") + } + viewModelScope.launch(handler) { + softApManager.listSsids() + } + } - override fun onUnavailable() { - // do failure processing here.. - Log.d("AAAA", "Something went wrong!") + internal fun provision( + credentials: Credentials = Credentials( + ssid = "OnHub", + password = "newbird379" + ) + ) { + val handler = CoroutineExceptionHandler { _, t -> + Log.e("AAAA", "$t") + } + viewModelScope.launch(handler) { + softApManager.provision(credentials = credentials).also { response -> + if (response.isSuccessful) { + softApManager.disconnect() + } } } - connectivityManager.requestNetwork(request, networkCallback) } - - } -data class WifiConfig(val ssid: String, val password:String) diff --git a/lib/softap/build.gradle.kts b/lib/softap/build.gradle.kts index f349e4c8..5dc35110 100644 --- a/lib/softap/build.gradle.kts +++ b/lib/softap/build.gradle.kts @@ -1,8 +1,16 @@ plugins { - alias(libs.plugins.nordic.feature) + alias(libs.plugins.nordic.library) alias(libs.plugins.nordic.hilt) } android { namespace = "no.nordicsemi.android.wifi.provisioner.softap" +} + +dependencies { + implementation(libs.retrofit.core) + implementation(libs.retrofit.converter.scalars) + implementation(libs.okhttp) + implementation(libs.okhttp.logging) + implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") } \ No newline at end of file diff --git a/lib/softap/src/main/AndroidManifest.xml b/lib/softap/src/main/AndroidManifest.xml index 44008a43..7ec779a7 100644 --- a/lib/softap/src/main/AndroidManifest.xml +++ b/lib/softap/src/main/AndroidManifest.xml @@ -1,4 +1,7 @@ - + + + + \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt new file mode 100644 index 00000000..46df5f0e --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -0,0 +1,46 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +import android.net.nsd.NsdManager +import android.net.nsd.NsdServiceInfo +import android.util.Log + +/** + * Created by Roshan Rajaratnam on 23/02/2024. + */ +internal class NetworkServiceDiscoveryListener(private val nsdManager: NsdManager) : + NsdManager.DiscoveryListener { + + // Called as soon as service discovery begins. + override fun onDiscoveryStarted(regType: String) { + Log.d("AAAA", "Service discovery started $regType") + } + + override fun onServiceFound(service: NsdServiceInfo) { + // A service was found! Do something with it. + Log.d("AAAA", "Service discovery success $service") + } + + override fun onServiceLost(service: NsdServiceInfo) { + // When the network service is no longer available. + // Internal bookkeeping code goes here. + Log.e("AAAA", "service lost: $service") + } + + override fun onDiscoveryStopped(serviceType: String) { + Log.i("AAAA", "Discovery stopped: $serviceType") + } + + override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { + try { + Log.e("AAAA", "Discovery failed: Error code:$errorCode") + // nsdManager.stopServiceDiscovery(this) + } catch (e: Exception) { + Log.e("AAAA", "error on start discovery failed: $e") + } + } + + override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { + Log.e("AAAA", "Discovery failed: Error code:$errorCode") + nsdManager.stopServiceDiscovery(this) + } +} \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt new file mode 100644 index 00000000..e62cda0f --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt @@ -0,0 +1,34 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +/** + * Created by Roshan Rajaratnam on 23/02/2024. + * + * Defines the WifiNetworkState + */ +sealed class ProvisioningState { + + /** + * State when connected to a Unprovisioned Wifi Node + */ + data object Disconnected : ProvisioningState() + + /** + * State when connected to a Unprovisioned Wifi Node + */ + data object Connecting : ProvisioningState() + + /** + * State when connected to a Unprovisioned Wifi Node + */ + data object Connected : ProvisioningState() + + /** + * State when connected to a Unprovisioned Wifi Node + */ + data object Provisioning : ProvisioningState() + + /** + * State when Disconnected from an Unprovisioned Wifi Node + */ + data object ProvisioningComplete : ProvisioningState() +} \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt new file mode 100644 index 00000000..257dd197 --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -0,0 +1,142 @@ +@file:Suppress("unused") + +package no.nordicsemi.android.wifi.provisioner.softap + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.net.nsd.NsdManager +import android.net.wifi.WifiNetworkSpecifier +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.withContext +import no.nordicsemi.android.wifi.provisioner.softap.credentials.Credentials +import okhttp3.ResponseBody +import retrofit2.Response +import javax.inject.Inject + +/** + * Created by Roshan Rajaratnam on 23/02/2024. + * + * Entry point to the SoftApManager + * + * @param context Application context. + * @param wifiService WifiServer api. + * @param coroutineDispatcher Coroutine dispatcher. + * + */ +class SoftApManager @Inject constructor( + context: Context, + private val wifiService: WifiService, + private val coroutineDispatcher: CoroutineDispatcher +) { + private val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager + + private var _provisioningState = + MutableStateFlow(ProvisioningState.Disconnected) + val provisioningState = _provisioningState.asStateFlow() + + private val networkCallback = object : ConnectivityManager.NetworkCallback() { + + @RequiresApi(Build.VERSION_CODES.M) + override fun onAvailable(network: Network) { + super.onAvailable(network) + // do success processing here.. + try { + if (connectivityManager.bindProcessToNetwork(network)) { + Log.d( + "AAAA", "Link properties ${ + connectivityManager.getLinkProperties(network)?.toString() + }" + ) + _provisioningState.value = ProvisioningState.Connected + } else { + disconnect() + } + } catch (e: Exception) { + Log.e("AAAA", "Error: $e") + } + } + + override fun onUnavailable() { + // do failure processing here.. + Log.d("AAAA", "Something went wrong!") + disconnect() + } + } + + /** + * Connects to an unprovisioned wifi device by establishing a temporary wifi network connection + * with the given ssid and the password. + * + * Note: The SSID and the password are the ones used to connect to the unprovisioned device, not + * the SSID or the passphrase of the network that the device must be provisioned into. + */ + @RequiresApi(Build.VERSION_CODES.Q) + fun connect(ssid: String, password: String = "") { + _provisioningState.value = ProvisioningState.Connecting + val specifier = WifiNetworkSpecifier.Builder() + .setSsid(ssid) + .setWpa2Passphrase(password) + .build() + + val request = NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .setNetworkSpecifier(specifier) + .build() + connectivityManager.requestNetwork(request, networkCallback) + } + + /** + * Disconnects from an unprovisioned or a newly provisioned device. + */ + fun disconnect() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + connectivityManager.bindProcessToNetwork(null) + } + connectivityManager.unregisterNetworkCallback(networkCallback) + _provisioningState.value = ProvisioningState.Disconnected + } + + /** + * Lists the SSIDs scanned by the nRF7002 device + */ + suspend fun listSsids(): Response = withContext(coroutineDispatcher) { + wifiService.listSsids() + } + + /** + * Provisions the nRF7002 device a wifi network with the given credentials. + * + * @param credentials Credentials of the wifi network. + */ + suspend fun provision(credentials: Credentials) = withContext(coroutineDispatcher) { + wifiService.provision(credentials.value).also { + nsdManager.discoverServices( + "_https._tcp", + NsdManager.PROTOCOL_DNS_SD, + NetworkServiceDiscoveryListener(nsdManager = nsdManager) + ) + } + + } + + /** + * Toggles the given LED on the nRF7000 device. + * + * @param led Led number to blink. + * @param toggle Boolean representing on or off. + */ + suspend fun blink(led: Int, toggle: Boolean) = withContext(coroutineDispatcher) { + wifiService.blink(led = led, toggle = if (toggle) "1" else "0") + } +} \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt new file mode 100644 index 00000000..3fde1334 --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt @@ -0,0 +1,27 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +import okhttp3.ResponseBody +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Headers +import retrofit2.http.PUT +import retrofit2.http.Path + +/** + * Created by Roshan Rajaratnam on 19/02/2024. + */ +interface WifiService { + + @Headers("Content-Type: text/plain") + @GET("wifi/ssid") + suspend fun listSsids(): Response + + @Headers("Content-Type: text/plain") + @PUT("wifi/prov") + suspend fun provision(@Body credentials: String): Response + + @Headers("Content-Type: text/plain") + @PUT("led/{led}") + suspend fun blink(@Path("led") led : Int, @Body toggle: String): Response +} \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt new file mode 100644 index 00000000..0d1e171f --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt @@ -0,0 +1,8 @@ +package no.nordicsemi.android.wifi.provisioner.softap.credentials + +/** + * Created by Roshan Rajaratnam on 22/02/2024. + */ +data class Credentials(private val ssid: String, private val password: String) { + val value = "$ssid $password" +} \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt new file mode 100644 index 00000000..3012174d --- /dev/null +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -0,0 +1,98 @@ +/* + * + * * Copyright (c) 2022, Nordic Semiconductor + * * + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package no.nordicsemi.android.wifi.provisioner.softap.di + +import android.util.Log +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import no.nordicsemi.android.wifi.provisioner.softap.BuildConfig +import no.nordicsemi.android.wifi.provisioner.softap.WifiService +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import okhttp3.logging.HttpLoggingInterceptor.Level +import okhttp3.tls.HandshakeCertificates +import okhttp3.tls.decodeCertificatePem +import retrofit2.Retrofit +import retrofit2.converter.scalars.ScalarsConverterFactory +import retrofit2.create +import java.util.concurrent.TimeUnit +import javax.inject.Singleton +import javax.net.ssl.HostnameVerifier + + +/** + * Created by Roshan Rajaratnam on 19/02/2024. + */ +@Module +@InstallIn(SingletonComponent::class) +object WifiServiceModule { + + @Provides + @Singleton + fun provideOkHttpClient(): OkHttpClient { + val interceptor = HttpLoggingInterceptor().apply { + level = when { + BuildConfig.DEBUG -> Level.BODY + else -> Level.NONE + } + } + val certificate = HandshakeCertificates.Builder() + .addTrustedCertificate(CERTIFICATE.decodeCertificatePem()) + .build() + + // This is a work around to avoid unknown host exception + val hostNameVerifier = HostnameVerifier { hostname, session -> + true + } + + return OkHttpClient.Builder() + .sslSocketFactory(certificate.sslSocketFactory(), certificate.trustManager) + .addInterceptor(interceptor) + .hostnameVerifier(hostNameVerifier) + .followRedirects(false) + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + + @Provides + @Singleton + fun provideService(client: OkHttpClient): WifiService = Retrofit.Builder() + .baseUrl("https://192.0.2.1/") + .client(client) + .addConverterFactory(ScalarsConverterFactory.create()) + .build() + .create() + + private const val CERTIFICATE = "" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIDmTCCAoGgAwIBAgIUNPeHg7DpZ5bXuQIi6Xb5+3QsLU8wDQYJKoZIhvcNAQEL\n" + + "BQAwXDELMAkGA1UEBhMCTk8xDzANBgNVBAgMBk5vcndheTEhMB8GA1UECgwYSW50\n" + + "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRkwFwYDVQQDDBBodHRwc2VydmVyLmxvY2Fs\n" + + "MB4XDTIzMDgyOTA5MDUxMVoXDTMzMDgyNjA5MDUxMVowXDELMAkGA1UEBhMCTk8x\n" + + "DzANBgNVBAgMBk5vcndheTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg\n" + + "THRkMRkwFwYDVQQDDBBodHRwc2VydmVyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEF\n" + + "AAOCAQ8AMIIBCgKCAQEAtu0duZvD2kDOg1Qqh9VxhC/kVpquO3C31w8J3CgI/tZA\n" + + "hlOGxxjXySrQdHUUpQHjWk9LaQhD8TMag8hA+4Rxx+MJpvx6G29se9dbG7TRTswx\n" + + "MdRweXjlygjl+2DJr5Fy7541ceRfBc2O2+AZWsCxxryVhEyIUSAIhEL7cEF2NV7m\n" + + "3O5POSPSOe86s8REaRbnrEcVAXGgViNf2oQGLAS2ul8gzkIcU/7/foHNI8RL/9qD\n" + + "arQrxyUrUzAnGxdaaVgajbHVGpGyKOuhEYwZlHZbJI+juHtw3iDaOb8oz1fXsoDo\n" + + "mSO0Zzt4Q/pGvxgitbBKKHaM0juo2q81tto/pa82bwIDAQABo1MwUTAdBgNVHQ4E\n" + + "FgQUfLgHfBTGAvqmcg/c7AhbLwaA5WUwHwYDVR0jBBgwFoAUfLgHfBTGAvqmcg/c\n" + + "7AhbLwaA5WUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYieg\n" + + "3NtCYNWAq0ASjMUIlN4xTWlWPvQMLcvaBWs27GB8dYR9uq450G1ADZqMWV7CWT5G\n" + + "6QVVUj5XOCLhlmIfuBBdh5Yw9DSq7f6ALa+eUwsn/yC2pVrMYiWuSwAMB0XO06ip\n" + + "p95K05lDFhjAzHTNJSXs0bHFNnxDwk687hfWQCsjPh2Gocg5OGJVq6b9KA9kv3FT\n" + + "ndfNnVdyfBsKn/USf96kJ97qUkTWKwNNvPn9eBhP9T5FdTfv9bCjv3kqHTCSvF5/\n" + + "Hv7J6UHlxNcWxBDq0FGj3jxKoxUyXuDi7curcCPPC/gy57NMyg0nyq/gE4alJKVH\n" + + "8ticzSyJlz9rS7AbAg==\n" + + "-----END CERTIFICATE-----\n" +} \ No newline at end of file From 6aa61979459e9de73daf40d279c7915e85af3be2 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 26 Feb 2024 14:38:22 +0100 Subject: [PATCH 013/101] Minor improvements --- .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 2 ++ .../android/wifi/provisioner/softap/di/WifiServiceModule.kt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 9dbb9222..92ce641d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -1,3 +1,5 @@ +@file:Suppress("unused") + package no.nordicsemi.android.wifi.provisioner.softap.viewmodel import android.os.Build diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index 3012174d..82c645b8 100644 --- a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -8,7 +8,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.di -import android.util.Log import dagger.Module import dagger.Provides import dagger.hilt.InstallIn From 9bc45f3d4a31ecbfadcb74ecc5c5c8813c075102 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 12:20:50 +0200 Subject: [PATCH 014/101] Updates the new certificate and adds support for the new protobuf schema. --- feature/softap/build.gradle.kts | 2 +- lib/softap/{ => proto}/.gitignore | 0 lib/softap/proto/build.gradle.kts | 44 +++++++++++++++++++ lib/softap/proto/module-rules.pro | 21 +++++++++ lib/softap/proto/src/main/AndroidManifest.xml | 33 ++++++++++++++ lib/softap/proto/src/main/proto/common.proto | 44 +++++++++++++++++++ lib/softap/provisioner/.gitignore | 1 + lib/softap/{ => provisioner}/build.gradle.kts | 0 .../{ => provisioner}/consumer-rules.pro | 0 .../{ => provisioner}/proguard-rules.pro | 0 .../src/main/AndroidManifest.xml | 0 .../softap/NetworkServiceDiscoveryListener.kt | 0 .../provisioner/softap/ProvisioningState.kt | 0 .../wifi/provisioner/softap/SoftApManager.kt | 0 .../wifi/provisioner/softap/WifiService.kt | 4 +- .../softap/credentials/Credentials.kt | 0 .../softap/di/WifiServiceModule.kt | 30 +++++-------- settings.gradle.kts | 3 +- 18 files changed, 158 insertions(+), 24 deletions(-) rename lib/softap/{ => proto}/.gitignore (100%) create mode 100644 lib/softap/proto/build.gradle.kts create mode 100644 lib/softap/proto/module-rules.pro create mode 100644 lib/softap/proto/src/main/AndroidManifest.xml create mode 100644 lib/softap/proto/src/main/proto/common.proto create mode 100644 lib/softap/provisioner/.gitignore rename lib/softap/{ => provisioner}/build.gradle.kts (100%) rename lib/softap/{ => provisioner}/consumer-rules.pro (100%) rename lib/softap/{ => provisioner}/proguard-rules.pro (100%) rename lib/softap/{ => provisioner}/src/main/AndroidManifest.xml (100%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt (100%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt (100%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt (100%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt (92%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt (100%) rename lib/softap/{ => provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt (59%) diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index 71342af2..a951f622 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -41,7 +41,7 @@ android { dependencies { implementation(project(":feature:ui")) - implementation(project(":lib:softap")) + implementation(project(":lib:softap:provisioner")) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.compose.ui) diff --git a/lib/softap/.gitignore b/lib/softap/proto/.gitignore similarity index 100% rename from lib/softap/.gitignore rename to lib/softap/proto/.gitignore diff --git a/lib/softap/proto/build.gradle.kts b/lib/softap/proto/build.gradle.kts new file mode 100644 index 00000000..c3ade32d --- /dev/null +++ b/lib/softap/proto/build.gradle.kts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +plugins { + alias(libs.plugins.nordic.library) + alias(libs.plugins.nordic.kotlin) + alias(libs.plugins.wire) +} + +wire { + kotlin {} +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioner.softap.proto" +} diff --git a/lib/softap/proto/module-rules.pro b/lib/softap/proto/module-rules.pro new file mode 100644 index 00000000..ff59496d --- /dev/null +++ b/lib/softap/proto/module-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle.kts. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/lib/softap/proto/src/main/AndroidManifest.xml b/lib/softap/proto/src/main/AndroidManifest.xml new file mode 100644 index 00000000..d554f457 --- /dev/null +++ b/lib/softap/proto/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + \ No newline at end of file diff --git a/lib/softap/proto/src/main/proto/common.proto b/lib/softap/proto/src/main/proto/common.proto new file mode 100644 index 00000000..eb8dca75 --- /dev/null +++ b/lib/softap/proto/src/main/proto/common.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.softap.proto"; + +// Common ENUMs +enum Band { + BAND_UNSPECIFIED = 0; + BAND_2_4_GHZ = 1; + BAND_5_GHZ = 2; + BAND_6_GHZ = 3; +} + +enum AuthMode { + AUTH_MODE_UNSPECIFIED = 0; + OPEN = 1; + WEP = 2; + WPA_PSK = 3; + WPA2_PSK = 4; + WPA_WPA2_PSK = 5; + WPA2_ENTERPRISE = 6; + WPA3_PSK = 7; +} + +message WifiScanResult { + string ssid = 1; + string bssid = 2; + Band band = 3; + uint32 channel = 4; + AuthMode authMode = 5; + int32 rssi = 6; +} + +message ScanResults { + repeated WifiScanResult results = 1; +} + +message WifiConfig { + string ssid = 1; + string passphrase = 2; + Band band = 3; + uint32 channel = 4; + AuthMode authMode = 5; +} \ No newline at end of file diff --git a/lib/softap/provisioner/.gitignore b/lib/softap/provisioner/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/lib/softap/provisioner/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/lib/softap/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts similarity index 100% rename from lib/softap/build.gradle.kts rename to lib/softap/provisioner/build.gradle.kts diff --git a/lib/softap/consumer-rules.pro b/lib/softap/provisioner/consumer-rules.pro similarity index 100% rename from lib/softap/consumer-rules.pro rename to lib/softap/provisioner/consumer-rules.pro diff --git a/lib/softap/proguard-rules.pro b/lib/softap/provisioner/proguard-rules.pro similarity index 100% rename from lib/softap/proguard-rules.pro rename to lib/softap/provisioner/proguard-rules.pro diff --git a/lib/softap/src/main/AndroidManifest.xml b/lib/softap/provisioner/src/main/AndroidManifest.xml similarity index 100% rename from lib/softap/src/main/AndroidManifest.xml rename to lib/softap/provisioner/src/main/AndroidManifest.xml diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt similarity index 100% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt similarity index 100% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt similarity index 100% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt similarity index 92% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt index 3fde1334..8211979e 100644 --- a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt @@ -14,11 +14,11 @@ import retrofit2.http.Path interface WifiService { @Headers("Content-Type: text/plain") - @GET("wifi/ssid") + @GET("prov/networks") suspend fun listSsids(): Response @Headers("Content-Type: text/plain") - @PUT("wifi/prov") + @PUT("prov/configure") suspend fun provision(@Body credentials: String): Response @Headers("Content-Type: text/plain") diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt similarity index 100% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt similarity index 59% rename from lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index 82c645b8..0473d417 100644 --- a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -73,25 +73,15 @@ object WifiServiceModule { private const val CERTIFICATE = "" + "-----BEGIN CERTIFICATE-----\n" + - "MIIDmTCCAoGgAwIBAgIUNPeHg7DpZ5bXuQIi6Xb5+3QsLU8wDQYJKoZIhvcNAQEL\n" + - "BQAwXDELMAkGA1UEBhMCTk8xDzANBgNVBAgMBk5vcndheTEhMB8GA1UECgwYSW50\n" + - "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRkwFwYDVQQDDBBodHRwc2VydmVyLmxvY2Fs\n" + - "MB4XDTIzMDgyOTA5MDUxMVoXDTMzMDgyNjA5MDUxMVowXDELMAkGA1UEBhMCTk8x\n" + - "DzANBgNVBAgMBk5vcndheTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg\n" + - "THRkMRkwFwYDVQQDDBBodHRwc2VydmVyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEF\n" + - "AAOCAQ8AMIIBCgKCAQEAtu0duZvD2kDOg1Qqh9VxhC/kVpquO3C31w8J3CgI/tZA\n" + - "hlOGxxjXySrQdHUUpQHjWk9LaQhD8TMag8hA+4Rxx+MJpvx6G29se9dbG7TRTswx\n" + - "MdRweXjlygjl+2DJr5Fy7541ceRfBc2O2+AZWsCxxryVhEyIUSAIhEL7cEF2NV7m\n" + - "3O5POSPSOe86s8REaRbnrEcVAXGgViNf2oQGLAS2ul8gzkIcU/7/foHNI8RL/9qD\n" + - "arQrxyUrUzAnGxdaaVgajbHVGpGyKOuhEYwZlHZbJI+juHtw3iDaOb8oz1fXsoDo\n" + - "mSO0Zzt4Q/pGvxgitbBKKHaM0juo2q81tto/pa82bwIDAQABo1MwUTAdBgNVHQ4E\n" + - "FgQUfLgHfBTGAvqmcg/c7AhbLwaA5WUwHwYDVR0jBBgwFoAUfLgHfBTGAvqmcg/c\n" + - "7AhbLwaA5WUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYieg\n" + - "3NtCYNWAq0ASjMUIlN4xTWlWPvQMLcvaBWs27GB8dYR9uq450G1ADZqMWV7CWT5G\n" + - "6QVVUj5XOCLhlmIfuBBdh5Yw9DSq7f6ALa+eUwsn/yC2pVrMYiWuSwAMB0XO06ip\n" + - "p95K05lDFhjAzHTNJSXs0bHFNnxDwk687hfWQCsjPh2Gocg5OGJVq6b9KA9kv3FT\n" + - "ndfNnVdyfBsKn/USf96kJ97qUkTWKwNNvPn9eBhP9T5FdTfv9bCjv3kqHTCSvF5/\n" + - "Hv7J6UHlxNcWxBDq0FGj3jxKoxUyXuDi7curcCPPC/gy57NMyg0nyq/gE4alJKVH\n" + - "8ticzSyJlz9rS7AbAg==\n" + + "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + + "YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxGjAY\n" + + "BgNVBAoMEVRlc3QgT3JnYW5pemF0aW9uMRcwFQYDVQQDDA53aWZpcHJvdi5sb2Nh\n" + + "bDAeFw0yNDAzMjYxMzI4MzNaFw0yNTAzMjYxMzI4MzNaMGAxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRowGAYDVQQKDBFUZXN0IE9y\n" + + "Z2FuaXphdGlvbjEXMBUGA1UEAwwOd2lmaXByb3YubG9jYWwwWTATBgcqhkjOPQIB\n" + + "BggqhkjOPQMBBwNCAAR6COfDiVYhNJkqCe3COkrN/Y9U8LPSDElE+mDk0ri7Ivb8\n" + + "LefdeYP3HgoTEEgem5eDNy10UZlf6+q6VUWyCH8toxMwETAPBgNVHRMBAf8EBTAD\n" + + "AQH/MAoGCCqGSM49BAMCA0kAMEYCIQDmEcPlg4GuPIAE9xvpW8t8LGit/+eDWCqE\n" + + "3ADi/H6f0QIhALUgBnN1+7awE7M1FvSnizX3b5ff7BfzltskPYnpjxqS\n" + "-----END CERTIFICATE-----\n" } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 552afb7f..6083ac9d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -59,7 +59,8 @@ include(":feature:ble") include(":feature:softap") include(":lib:ble:provisioner") include(":lib:ble:proto") -include(":lib:softap") +include(":lib:softap:proto") +include(":lib:softap:provisioner") //if (file('../Android-Common-Libraries').exists()) { // includeBuild('../Android-Common-Libraries') From 3621aa66242ba21d62fb162a3507bdc2d598fe4d Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 13:58:13 +0200 Subject: [PATCH 015/101] fix project setup --- lib/softap/provisioner/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 5dc35110..c360a341 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -8,6 +8,7 @@ android { } dependencies { + implementation(project(":lib:softap:proto")) implementation(libs.retrofit.core) implementation(libs.retrofit.converter.scalars) implementation(libs.okhttp) From 035a988a16e5106be52bc05bbf478cd857f29efd Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 13:58:53 +0200 Subject: [PATCH 016/101] Map domain to api --- .../softap/domain/AuthModeDomain.kt | 43 ++++++++++++++++ .../provisioner/softap/domain/BandDomain.kt | 41 ++++++++++++++++ .../softap/domain/ScanResultsDomain.kt | 5 ++ .../provisioner/softap/domain/ToApiMapper.kt | 49 +++++++++++++++++++ .../softap/domain/WifiConfigDomain.kt | 40 +++++++++++++++ .../softap/domain/WifiScanResultDomain.kt | 10 ++++ 6 files changed, 188 insertions(+) create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt new file mode 100644 index 00000000..3f208644 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.domain + +enum class AuthModeDomain(val id: Int) { + AUTH_MODE_UNSPECIFIED(0), + OPEN(1), + WEP(2), + WPA_PSK(3), + WPA2_PSK(4), + WPA_WPA2_PSK(5), + WPA2_ENTERPRISE(6), + WPA3_PSK(7) +} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt new file mode 100644 index 00000000..870a87ba --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.domain + +import no.nordicsemi.android.wifi.provisioner.softap.proto.Band + +enum class BandDomain(val id: Int) { + BAND_UNSPECIFIED(0), + BAND_2_4_GH(1), + BAND_5_GH(2), + BAND_6_GH(3) +} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt new file mode 100644 index 00000000..eaf891b9 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt @@ -0,0 +1,5 @@ +package no.nordicsemi.android.wifi.provisioner.softap.domain + +data class ScanResultsDomain( + val wifiScanResults : List +) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt new file mode 100644 index 00000000..e4457499 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -0,0 +1,49 @@ +package no.nordicsemi.android.wifi.provisioner.softap.domain + +import no.nordicsemi.android.wifi.provisioner.softap.proto.AuthMode +import no.nordicsemi.android.wifi.provisioner.softap.proto.Band +import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult + + +fun AuthModeDomain.toApi() : AuthMode = when(this) { + AuthModeDomain.AUTH_MODE_UNSPECIFIED -> AuthMode.AUTH_MODE_UNSPECIFIED + AuthModeDomain.OPEN -> AuthMode.OPEN + AuthModeDomain.WEP -> AuthMode.WEP + AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK + AuthModeDomain.WPA2_PSK -> AuthMode.WPA2_PSK + AuthModeDomain.WPA_WPA2_PSK -> AuthMode.WPA_WPA2_PSK + AuthModeDomain.WPA2_ENTERPRISE -> AuthMode.WPA2_ENTERPRISE + AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK +} + +internal fun BandDomain.toApi() : Band = when(this) { + BandDomain.BAND_UNSPECIFIED -> Band.BAND_UNSPECIFIED + BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GHZ + BandDomain.BAND_5_GH -> Band.BAND_5_GHZ + BandDomain.BAND_6_GH -> Band.BAND_6_GHZ +} + +fun WifiConfigDomain.toApi(): WifiConfig { + return WifiConfig( + ssid = ssid, + passphrase = passphrase, + band = bandDomain.toApi(), + channel = channel, + authMode = authModeDomain.toApi() + ) +} + +fun ScanResultsDomain.toApi(): ScanResults = ScanResults( + results = wifiScanResults.map { it.toApi() } +) + +fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( + ssid = ssid, + bssid = bssid, + band = bandDomain.toApi(), + channel = channel, + authMode = authModeDomain.toApi(), + rssi = rssi +) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt new file mode 100644 index 00000000..c93d7fae --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.domain + +data class WifiConfigDomain( + val ssid: String, + val passphrase: String, + val bandDomain: BandDomain, + val channel: Int, + val authModeDomain: AuthModeDomain +) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt new file mode 100644 index 00000000..fbf784dd --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt @@ -0,0 +1,10 @@ +package no.nordicsemi.android.wifi.provisioner.softap.domain + +data class WifiScanResultDomain( + val ssid: String, + val bssid: String, + val bandDomain: BandDomain, + val channel: Int, + val authModeDomain: AuthModeDomain, + val rssi: Int +) \ No newline at end of file From 9d66174bd662dec609fa3b6ba77f74abb0a4155c Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 14:02:11 +0200 Subject: [PATCH 017/101] Maps API to domain --- .../softap/domain/ToDomainMapper.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt new file mode 100644 index 00000000..1ae885c3 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -0,0 +1,49 @@ +package no.nordicsemi.android.wifi.provisioner.softap.domain + +import no.nordicsemi.android.wifi.provisioner.softap.proto.AuthMode +import no.nordicsemi.android.wifi.provisioner.softap.proto.Band +import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult + + +fun AuthMode.toDomain() : AuthModeDomain = when(this) { + AuthMode.AUTH_MODE_UNSPECIFIED -> AuthModeDomain.AUTH_MODE_UNSPECIFIED + AuthMode.OPEN -> AuthModeDomain.OPEN + AuthMode.WEP -> AuthModeDomain.WEP + AuthMode.WPA_PSK -> AuthModeDomain.WPA_PSK + AuthMode.WPA2_PSK -> AuthModeDomain.WPA2_PSK + AuthMode.WPA_WPA2_PSK -> AuthModeDomain.WPA_WPA2_PSK + AuthMode.WPA2_ENTERPRISE -> AuthModeDomain.WPA2_ENTERPRISE + AuthMode.WPA3_PSK -> AuthModeDomain.WPA3_PSK +} + +internal fun Band.toDomain() : BandDomain = when(this) { + Band.BAND_UNSPECIFIED -> BandDomain.BAND_UNSPECIFIED + Band.BAND_2_4_GHZ -> BandDomain.BAND_2_4_GH + Band.BAND_5_GHZ -> BandDomain.BAND_5_GH + Band.BAND_6_GHZ -> BandDomain.BAND_6_GH +} + +fun WifiConfig.toDomain(): WifiConfigDomain { + return WifiConfigDomain( + ssid = ssid, + passphrase = passphrase, + bandDomain = band.toDomain(), + channel = channel, + authModeDomain = authMode.toDomain() + ) +} + +fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDomain( + ssid = ssid, + bssid = bssid, + bandDomain = band.toDomain(), + channel = channel, + authModeDomain = authMode.toDomain(), + rssi = rssi +) + +fun ScanResults.toDomain(): ScanResultsDomain = ScanResultsDomain( + wifiScanResults = results.map { it.toDomain() } +) From bf20fbc82920fa2fe62ea937bc623fdf8e25920f Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 14:03:21 +0200 Subject: [PATCH 018/101] Clean up --- .../wifi/provisioner/softap/domain/BandDomain.kt | 2 -- .../wifi/provisioner/softap/domain/ToApiMapper.kt | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt index 870a87ba..84006df2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt @@ -31,8 +31,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain -import no.nordicsemi.android.wifi.provisioner.softap.proto.Band - enum class BandDomain(val id: Int) { BAND_UNSPECIFIED(0), BAND_2_4_GH(1), diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index e4457499..16a887c2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -35,10 +35,6 @@ fun WifiConfigDomain.toApi(): WifiConfig { ) } -fun ScanResultsDomain.toApi(): ScanResults = ScanResults( - results = wifiScanResults.map { it.toApi() } -) - fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( ssid = ssid, bssid = bssid, @@ -46,4 +42,8 @@ fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( channel = channel, authMode = authModeDomain.toApi(), rssi = rssi -) \ No newline at end of file +) + +fun ScanResultsDomain.toApi(): ScanResults = ScanResults( + results = wifiScanResults.map { it.toApi() } +) From cfb164bbc1a442fc579d0e68d9a4838cbaf5748f Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 14:44:15 +0200 Subject: [PATCH 019/101] Fix visibility --- .../wifi/provisioner/softap/domain/ToApiMapper.kt | 9 ++++----- .../wifi/provisioner/softap/domain/ToDomainMapper.kt | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index 16a887c2..4b4c2ef7 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -6,8 +6,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult - -fun AuthModeDomain.toApi() : AuthMode = when(this) { +internal fun AuthModeDomain.toApi() : AuthMode = when(this) { AuthModeDomain.AUTH_MODE_UNSPECIFIED -> AuthMode.AUTH_MODE_UNSPECIFIED AuthModeDomain.OPEN -> AuthMode.OPEN AuthModeDomain.WEP -> AuthMode.WEP @@ -25,7 +24,7 @@ internal fun BandDomain.toApi() : Band = when(this) { BandDomain.BAND_6_GH -> Band.BAND_6_GHZ } -fun WifiConfigDomain.toApi(): WifiConfig { +internal fun WifiConfigDomain.toApi(): WifiConfig { return WifiConfig( ssid = ssid, passphrase = passphrase, @@ -35,7 +34,7 @@ fun WifiConfigDomain.toApi(): WifiConfig { ) } -fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( +internal fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( ssid = ssid, bssid = bssid, band = bandDomain.toApi(), @@ -44,6 +43,6 @@ fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( rssi = rssi ) -fun ScanResultsDomain.toApi(): ScanResults = ScanResults( +internal fun ScanResultsDomain.toApi(): ScanResults = ScanResults( results = wifiScanResults.map { it.toApi() } ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt index 1ae885c3..6c313b26 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -6,8 +6,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult - -fun AuthMode.toDomain() : AuthModeDomain = when(this) { +internal fun AuthMode.toDomain() : AuthModeDomain = when(this) { AuthMode.AUTH_MODE_UNSPECIFIED -> AuthModeDomain.AUTH_MODE_UNSPECIFIED AuthMode.OPEN -> AuthModeDomain.OPEN AuthMode.WEP -> AuthModeDomain.WEP @@ -25,7 +24,7 @@ internal fun Band.toDomain() : BandDomain = when(this) { Band.BAND_6_GHZ -> BandDomain.BAND_6_GH } -fun WifiConfig.toDomain(): WifiConfigDomain { +internal fun WifiConfig.toDomain(): WifiConfigDomain { return WifiConfigDomain( ssid = ssid, passphrase = passphrase, @@ -35,7 +34,7 @@ fun WifiConfig.toDomain(): WifiConfigDomain { ) } -fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDomain( +internal fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDomain( ssid = ssid, bssid = bssid, bandDomain = band.toDomain(), @@ -46,4 +45,4 @@ fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDomain( fun ScanResults.toDomain(): ScanResultsDomain = ScanResultsDomain( wifiScanResults = results.map { it.toDomain() } -) +) \ No newline at end of file From 8a56d69a5d694d25b84b4b82784bcf3f7b7916ec Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 9 Apr 2024 14:45:05 +0200 Subject: [PATCH 020/101] Default values used for provisioning --- .../wifi/provisioner/softap/domain/WifiConfigDomain.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt index c93d7fae..bae2bc8c 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt @@ -34,7 +34,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain data class WifiConfigDomain( val ssid: String, val passphrase: String, - val bandDomain: BandDomain, - val channel: Int, - val authModeDomain: AuthModeDomain + val bandDomain: BandDomain = BandDomain.BAND_UNSPECIFIED, + val channel: Int = 0, + val authModeDomain: AuthModeDomain = AuthModeDomain.AUTH_MODE_UNSPECIFIED ) \ No newline at end of file From b37faa34611b9086fa70b366287f5c2f5bfe8cae Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 10 Apr 2024 14:12:49 +0200 Subject: [PATCH 021/101] Fix DI --- .../wifi/provisioner/softap/di/DispatchersModule.kt | 0 .../wifi/provisioner/softap/di/SoftApManagerModule.kt | 0 .../wifi/provisioner/softap/di/WifiServiceModule.kt | 8 ++++++-- 3 files changed, 6 insertions(+), 2 deletions(-) rename {feature/softap => lib/softap/provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt (100%) rename {feature/softap => lib/softap/provisioner}/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt (100%) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt similarity index 100% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt similarity index 100% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index 0473d417..53cad4d2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -8,6 +8,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.di +import android.util.Log import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -20,7 +21,7 @@ import okhttp3.logging.HttpLoggingInterceptor.Level import okhttp3.tls.HandshakeCertificates import okhttp3.tls.decodeCertificatePem import retrofit2.Retrofit -import retrofit2.converter.scalars.ScalarsConverterFactory +import retrofit2.converter.wire.WireConverterFactory import retrofit2.create import java.util.concurrent.TimeUnit import javax.inject.Singleton @@ -49,6 +50,7 @@ object WifiServiceModule { // This is a work around to avoid unknown host exception val hostNameVerifier = HostnameVerifier { hostname, session -> + Log.d("AAAA", "Hostname: $hostname") true } @@ -67,10 +69,12 @@ object WifiServiceModule { fun provideService(client: OkHttpClient): WifiService = Retrofit.Builder() .baseUrl("https://192.0.2.1/") .client(client) - .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(WireConverterFactory.create()) .build() .create() + internal val SERVICE_NAME = "wifiprov" + private const val CERTIFICATE = "" + "-----BEGIN CERTIFICATE-----\n" + "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + From e6f5c6f834b9bea815473941a1d09fec12a0ad45 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 10 Apr 2024 14:13:07 +0200 Subject: [PATCH 022/101] Adds missing permission --- lib/softap/provisioner/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/softap/provisioner/src/main/AndroidManifest.xml b/lib/softap/provisioner/src/main/AndroidManifest.xml index 7ec779a7..aea2a374 100644 --- a/lib/softap/provisioner/src/main/AndroidManifest.xml +++ b/lib/softap/provisioner/src/main/AndroidManifest.xml @@ -4,4 +4,5 @@ + \ No newline at end of file From 7013a9e7d61a61eb650cbf3602e3d59088d11eee Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 10 Apr 2024 14:14:09 +0200 Subject: [PATCH 023/101] Improvements to ProvisioningState --- .../provisioner/softap/ProvisioningState.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt index e62cda0f..8e073d4e 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt @@ -1,5 +1,7 @@ package no.nordicsemi.android.wifi.provisioner.softap +import android.net.nsd.NsdServiceInfo + /** * Created by Roshan Rajaratnam on 23/02/2024. * @@ -8,20 +10,30 @@ package no.nordicsemi.android.wifi.provisioner.softap sealed class ProvisioningState { /** - * State when connected to a Unprovisioned Wifi Node + * State when connected to a Unprovisioned Wifi Node. */ data object Disconnected : ProvisioningState() /** - * State when connected to a Unprovisioned Wifi Node + * State when connected to a Unprovisioned Wifi Node. */ data object Connecting : ProvisioningState() /** - * State when connected to a Unprovisioned Wifi Node + * State when connected to a Unprovisioned Wifi Node. */ data object Connected : ProvisioningState() + /** + * State when the discovering the network services available on the network. + */ + data object InitiatingNetworkServiceDiscovery : ProvisioningState() + + /** + * State when the network service discovery is complete. + */ + data class NetworkServiceDiscoveryComplete(val serviceInfo : NsdServiceInfo) : ProvisioningState() + /** * State when connected to a Unprovisioned Wifi Node */ From e232d4ea2c063f79214bd3c5015736387f8af547 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 11:03:31 +0200 Subject: [PATCH 024/101] Clean up WifiService API --- .../wifi/provisioner/softap/WifiService.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt index 8211979e..064c9170 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt @@ -1,12 +1,17 @@ package no.nordicsemi.android.wifi.provisioner.softap +import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult import okhttp3.ResponseBody import retrofit2.Response import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Headers +import retrofit2.http.POST import retrofit2.http.PUT import retrofit2.http.Path +import java.net.InetAddress /** * Created by Roshan Rajaratnam on 19/02/2024. @@ -15,13 +20,9 @@ interface WifiService { @Headers("Content-Type: text/plain") @GET("prov/networks") - suspend fun listSsids(): Response + suspend fun listSsids(): ScanResults @Headers("Content-Type: text/plain") - @PUT("prov/configure") - suspend fun provision(@Body credentials: String): Response - - @Headers("Content-Type: text/plain") - @PUT("led/{led}") - suspend fun blink(@Path("led") led : Int, @Body toggle: String): Response + @POST("prov/configure") + suspend fun provision(@Body config: WifiConfig): Response } \ No newline at end of file From 5283867ee0e440af13c38b2508fca91fc4cfaee6 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 12:45:18 +0200 Subject: [PATCH 025/101] Adds support for NetworkServiceDiscoveryListener --- .../softap/NetworkServiceDiscoveryListener.kt | 120 ++++++++++++++---- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 46df5f0e..1016b1bd 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -3,44 +3,112 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.util.Log +import kotlinx.coroutines.sync.Mutex +import java.net.InetAddress /** - * Created by Roshan Rajaratnam on 23/02/2024. + * NetworkServiceDiscoveryListener that would listen to the network service discovery events. + * + * @param nsdManager NsdManager instance. + * @property discoveredIps List of discovered IP addresses of the network services. Note that this + * list could be empty if no services are discovered. */ -internal class NetworkServiceDiscoveryListener(private val nsdManager: NsdManager) : - NsdManager.DiscoveryListener { +class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager) { + private val mutex = Mutex(true) + private val _discoveredIps = mutableListOf() + val discoveredIps: List + get() = _discoveredIps - // Called as soon as service discovery begins. - override fun onDiscoveryStarted(regType: String) { - Log.d("AAAA", "Service discovery started $regType") - } + private var _serviceInfo: NsdServiceInfo? = null + + /** + * Callback used to listen for service discovery. + */ + private val nsdListener = object : NsdManager.DiscoveryListener { + + // Called as soon as service discovery begins. + override fun onDiscoveryStarted(regType: String) { + Log.d("AAAA", "Service discovery started $regType") + } + + override fun onServiceFound(service: NsdServiceInfo) { + // A service was found! Do something with it. + Log.d("AAAA", "Service discovery success $service") + if (service.serviceName == "wifiprov") { + nsdManager.resolveService(service, resolveListener) + } + } + + override fun onServiceLost(service: NsdServiceInfo) { + // When the network service is no longer available. + // Internal bookkeeping code goes here. + Log.e("AAAA", "service lost: $service") + } + + override fun onDiscoveryStopped(serviceType: String) { + Log.i("AAAA", "Discovery stopped: $serviceType") + } - override fun onServiceFound(service: NsdServiceInfo) { - // A service was found! Do something with it. - Log.d("AAAA", "Service discovery success $service") + override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { + try { + Log.e("AAAA", "Discovery failed: Error code:$errorCode") + // nsdManager.stopServiceDiscovery(this) + } catch (e: Exception) { + Log.e("AAAA", "error on start discovery failed: $e") + } finally { + nsdManager.stopServiceDiscovery(this) + } + } + + override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { + Log.e("AAAA", "Discovery failed: Error code:$errorCode") + nsdManager.stopServiceDiscovery(this) + } } - override fun onServiceLost(service: NsdServiceInfo) { - // When the network service is no longer available. - // Internal bookkeeping code goes here. - Log.e("AAAA", "service lost: $service") + /** + * Callback used to listen for service resolution. + */ + private val resolveListener = object : NsdManager.ResolveListener { + override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { + // Called when the resolve fails. Use the error code to debug. + Log.e("AAAA", "Resolve failed: $errorCode") + } + + override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { + Log.d("AAAA", "Resolve success: $serviceInfo") + serviceInfo?.let { + _serviceInfo = it + _discoveredIps.add(it.host) + mutex.unlock() + } + } } - override fun onDiscoveryStopped(serviceType: String) { - Log.i("AAAA", "Discovery stopped: $serviceType") + /** + * Discovers the network services. + * + * @return NsdServiceInfo instance. + */ + internal suspend fun discoverServices(): NsdServiceInfo? { + nsdManager.discoverServices( + SERVICE_TYPE, + NsdManager.PROTOCOL_DNS_SD, + nsdListener + ) + mutex.lock() + return _serviceInfo!! } - override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { - try { - Log.e("AAAA", "Discovery failed: Error code:$errorCode") - // nsdManager.stopServiceDiscovery(this) - } catch (e: Exception) { - Log.e("AAAA", "error on start discovery failed: $e") - } + /** + * Stops the network service discovery. + */ + internal fun stopDiscovery() { + nsdManager.stopServiceDiscovery(nsdListener) } - override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e("AAAA", "Discovery failed: Error code:$errorCode") - nsdManager.stopServiceDiscovery(this) + internal companion object { + const val SERVICE_NAME = "wifiprov" + private const val SERVICE_TYPE = "_http._tcp." } } \ No newline at end of file From d57b9d2420c821902653f65b9b2fafb8b103a98a Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 12:48:16 +0200 Subject: [PATCH 026/101] Add missing wire converter factory --- lib/softap/provisioner/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index c360a341..63aa6093 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -10,8 +10,10 @@ android { dependencies { implementation(project(":lib:softap:proto")) implementation(libs.retrofit.core) + implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.converter.scalars) implementation(libs.okhttp) implementation(libs.okhttp.logging) + implementation("com.squareup.retrofit2:converter-wire:2.11.0") implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") } \ No newline at end of file From 808bae2f72e5efb54554c20a4771671b9dde5584 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 12:50:41 +0200 Subject: [PATCH 027/101] Inject NetworkServiceDiscoveryListener --- .../wifi/provisioner/softap/SoftApManager.kt | 49 ++++++++++--------- .../softap/di/SoftApManagerModule.kt | 3 ++ .../softap/di/WifiServiceModule.kt | 23 +++++++-- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 257dd197..aea28d23 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -8,6 +8,7 @@ import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import android.net.nsd.NsdManager +import android.net.nsd.NsdServiceInfo import android.net.wifi.WifiNetworkSpecifier import android.os.Build import android.util.Log @@ -16,9 +17,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.withContext -import no.nordicsemi.android.wifi.provisioner.softap.credentials.Credentials -import okhttp3.ResponseBody -import retrofit2.Response +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi +import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain import javax.inject.Inject /** @@ -33,6 +34,7 @@ import javax.inject.Inject */ class SoftApManager @Inject constructor( context: Context, + private val nsdListener: NetworkServiceDiscoveryListener, private val wifiService: WifiService, private val coroutineDispatcher: CoroutineDispatcher ) { @@ -44,6 +46,9 @@ class SoftApManager @Inject constructor( MutableStateFlow(ProvisioningState.Disconnected) val provisioningState = _provisioningState.asStateFlow() + private val _discoveredServices = mutableListOf() + private var discoveredService: NsdServiceInfo? = null + private val networkCallback = object : ConnectivityManager.NetworkCallback() { @RequiresApi(Build.VERSION_CODES.M) @@ -69,7 +74,6 @@ class SoftApManager @Inject constructor( override fun onUnavailable() { // do failure processing here.. Log.d("AAAA", "Something went wrong!") - disconnect() } } @@ -108,35 +112,34 @@ class SoftApManager @Inject constructor( } /** - * Lists the SSIDs scanned by the nRF7002 device + * Discover services on the network. */ - suspend fun listSsids(): Response = withContext(coroutineDispatcher) { - wifiService.listSsids() + suspend fun discoverServices() { + val serviceInfo = nsdListener.discoverServices() + _provisioningState.value = + ProvisioningState.NetworkServiceDiscoveryComplete(serviceInfo!!) } /** - * Provisions the nRF7002 device a wifi network with the given credentials. - * - * @param credentials Credentials of the wifi network. + * Stops the network service discovery. */ - suspend fun provision(credentials: Credentials) = withContext(coroutineDispatcher) { - wifiService.provision(credentials.value).also { - nsdManager.discoverServices( - "_https._tcp", - NsdManager.PROTOCOL_DNS_SD, - NetworkServiceDiscoveryListener(nsdManager = nsdManager) - ) - } + fun stopDiscovery() { + nsdListener.stopDiscovery() + } + /** + * Lists the SSIDs scanned by the nRF7002 device + */ + suspend fun listSsids() = withContext(coroutineDispatcher) { + wifiService.listSsids().toDomain() } /** - * Toggles the given LED on the nRF7000 device. + * Provisions the nRF7002 device a wifi network with the given credentials. * - * @param led Led number to blink. - * @param toggle Boolean representing on or off. + * @param config Credentials of the wifi network. */ - suspend fun blink(led: Int, toggle: Boolean) = withContext(coroutineDispatcher) { - wifiService.blink(led = led, toggle = if (toggle) "1" else "0") + suspend fun provision(config: WifiConfigDomain) = withContext(coroutineDispatcher) { + wifiService.provision(config.toApi()) } } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt index 02c33eb0..fadd8762 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt @@ -7,6 +7,7 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineDispatcher +import no.nordicsemi.android.wifi.provisioner.softap.NetworkServiceDiscoveryListener import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager import no.nordicsemi.android.wifi.provisioner.softap.WifiService import javax.inject.Singleton @@ -22,10 +23,12 @@ object SoftApManagerModule { @Singleton fun provideSoftApManager( @ApplicationContext context: Context, + nsdListener: NetworkServiceDiscoveryListener, wifiService: WifiService, @IODispatcher coroutineDispatcher: CoroutineDispatcher ) = SoftApManager( context = context, + nsdListener = nsdListener, wifiService = wifiService, coroutineDispatcher = coroutineDispatcher ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index 53cad4d2..ef45bf6a 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -8,12 +8,17 @@ package no.nordicsemi.android.wifi.provisioner.softap.di +import android.content.Context +import android.net.ConnectivityManager +import android.net.nsd.NsdManager import android.util.Log import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import no.nordicsemi.android.wifi.provisioner.softap.BuildConfig +import no.nordicsemi.android.wifi.provisioner.softap.NetworkServiceDiscoveryListener import no.nordicsemi.android.wifi.provisioner.softap.WifiService import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor @@ -37,7 +42,15 @@ object WifiServiceModule { @Provides @Singleton - fun provideOkHttpClient(): OkHttpClient { + fun provideNetworkServiceDiscoveryListener(@ApplicationContext context : Context): NetworkServiceDiscoveryListener { + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager + return NetworkServiceDiscoveryListener(nsdManager) + } + + @Provides + @Singleton + fun provideOkHttpClient(nsdListener: NetworkServiceDiscoveryListener): OkHttpClient { val interceptor = HttpLoggingInterceptor().apply { level = when { BuildConfig.DEBUG -> Level.BODY @@ -59,6 +72,10 @@ object WifiServiceModule { .addInterceptor(interceptor) .hostnameVerifier(hostNameVerifier) .followRedirects(false) + .dns { + Log.d("AAAA", "DNS: $it") + nsdListener.discoveredIps + } .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .build() @@ -67,14 +84,12 @@ object WifiServiceModule { @Provides @Singleton fun provideService(client: OkHttpClient): WifiService = Retrofit.Builder() - .baseUrl("https://192.0.2.1/") + .baseUrl("https://${NetworkServiceDiscoveryListener.SERVICE_NAME}.local/") .client(client) .addConverterFactory(WireConverterFactory.create()) .build() .create() - internal val SERVICE_NAME = "wifiprov" - private const val CERTIFICATE = "" + "-----BEGIN CERTIFICATE-----\n" + "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + From 53792f6ef46ae6e16c025a9c5ab40247c7093a12 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 13:49:05 +0200 Subject: [PATCH 028/101] Clean up --- .../android/wifi/provisioner/softap/di/WifiServiceModule.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index ef45bf6a..6b1ab5e1 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -62,9 +62,8 @@ object WifiServiceModule { .build() // This is a work around to avoid unknown host exception - val hostNameVerifier = HostnameVerifier { hostname, session -> - Log.d("AAAA", "Hostname: $hostname") - true + val hostNameVerifier = HostnameVerifier { hostname, _ -> + hostname.contains(NetworkServiceDiscoveryListener.SERVICE_NAME) } return OkHttpClient.Builder() @@ -73,7 +72,6 @@ object WifiServiceModule { .hostnameVerifier(hostNameVerifier) .followRedirects(false) .dns { - Log.d("AAAA", "DNS: $it") nsdListener.discoveredIps } .readTimeout(10, TimeUnit.SECONDS) From 10f552bd2385992b5087177cf7a3568d07543612 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 13:52:13 +0200 Subject: [PATCH 029/101] Remove unnecessary insets --- .../android/wifi/provisioner/HomeScreen.kt | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 8c6d784a..9107cce8 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -37,17 +37,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.WindowInsetsSides -import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -72,25 +66,12 @@ fun HomeScreen() { val vm: SimpleNavigationViewModel = hiltViewModel() Scaffold( - contentWindowInsets = WindowInsets(0, 0, 0, 0), containerColor = colorResource(id = no.nordicsemi.android.common.theme.R.color.appBarColor), ) { innerPadding -> Column( modifier = Modifier .fillMaxSize() - .padding(paddingValues = innerPadding) - // .padding(bottom = 16.dp, top = 56.dp) - .consumeWindowInsets(paddingValues = innerPadding) - .windowInsetsPadding( - insets = WindowInsets.safeDrawing.only( - sides = WindowInsetsSides.Horizontal - ), - ) - .windowInsetsPadding( - insets = WindowInsets.safeDrawing.only( - sides = WindowInsetsSides.Vertical - ), - ), + .padding(paddingValues = innerPadding), horizontalAlignment = Alignment.CenterHorizontally ) { Text( From 403ea6d4e72149c6a9b2aed2d9c1a2f1547c8faa Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 14:02:51 +0200 Subject: [PATCH 030/101] clean up --- .../android/wifi/provisioner/softap/di/WifiServiceModule.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index 6b1ab5e1..d0d0cb49 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -11,7 +11,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.di import android.content.Context import android.net.ConnectivityManager import android.net.nsd.NsdManager -import android.util.Log import dagger.Module import dagger.Provides import dagger.hilt.InstallIn From 986ecfdfd557a5a98a3617d116a0408b06d70a2f Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 11 Apr 2024 14:49:35 +0200 Subject: [PATCH 031/101] Improvements --- .../wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 1016b1bd..051acc40 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -34,7 +34,7 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceFound(service: NsdServiceInfo) { // A service was found! Do something with it. Log.d("AAAA", "Service discovery success $service") - if (service.serviceName == "wifiprov") { + if (service.serviceName == SERVICE_NAME) { nsdManager.resolveService(service, resolveListener) } } From 210f17b421ca86ceb7d518345d4149212e711415 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 09:24:41 +0200 Subject: [PATCH 032/101] Add missing strings --- feature/softap/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index b7643082..b3c9c575 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -2,6 +2,7 @@ "Wi-Fi Provisioner " Setup Wi-Fi + Please provide the Wi-Fi SSID and the Password Change Wi-Fi Dismiss Confirm From 2c9cab23d28912126d4f03663b9274c35f4b0787 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:26:55 +0200 Subject: [PATCH 033/101] Clean up --- .../provisioner/softap/domain/ToApiMapper.kt | 24 +++++++++---------- .../softap/domain/ToDomainMapper.kt | 24 +++++++++---------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index 4b4c2ef7..32737097 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -6,7 +6,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult -internal fun AuthModeDomain.toApi() : AuthMode = when(this) { +internal fun AuthModeDomain.toApi() = when(this) { AuthModeDomain.AUTH_MODE_UNSPECIFIED -> AuthMode.AUTH_MODE_UNSPECIFIED AuthModeDomain.OPEN -> AuthMode.OPEN AuthModeDomain.WEP -> AuthMode.WEP @@ -17,24 +17,22 @@ internal fun AuthModeDomain.toApi() : AuthMode = when(this) { AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK } -internal fun BandDomain.toApi() : Band = when(this) { +internal fun BandDomain.toApi() = when(this) { BandDomain.BAND_UNSPECIFIED -> Band.BAND_UNSPECIFIED BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GHZ BandDomain.BAND_5_GH -> Band.BAND_5_GHZ BandDomain.BAND_6_GH -> Band.BAND_6_GHZ } -internal fun WifiConfigDomain.toApi(): WifiConfig { - return WifiConfig( - ssid = ssid, - passphrase = passphrase, - band = bandDomain.toApi(), - channel = channel, - authMode = authModeDomain.toApi() - ) -} +internal fun WifiConfigDomain.toApi() = WifiConfig( + ssid = ssid, + passphrase = passphrase, + band = bandDomain.toApi(), + channel = channel, + authMode = authModeDomain.toApi() +) -internal fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( +internal fun WifiScanResultDomain.toApi() = WifiScanResult( ssid = ssid, bssid = bssid, band = bandDomain.toApi(), @@ -43,6 +41,6 @@ internal fun WifiScanResultDomain.toApi(): WifiScanResult = WifiScanResult( rssi = rssi ) -internal fun ScanResultsDomain.toApi(): ScanResults = ScanResults( +internal fun ScanResultsDomain.toApi() = ScanResults( results = wifiScanResults.map { it.toApi() } ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt index 6c313b26..2a47012a 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -6,7 +6,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult -internal fun AuthMode.toDomain() : AuthModeDomain = when(this) { +internal fun AuthMode.toDomain() = when(this) { AuthMode.AUTH_MODE_UNSPECIFIED -> AuthModeDomain.AUTH_MODE_UNSPECIFIED AuthMode.OPEN -> AuthModeDomain.OPEN AuthMode.WEP -> AuthModeDomain.WEP @@ -17,24 +17,22 @@ internal fun AuthMode.toDomain() : AuthModeDomain = when(this) { AuthMode.WPA3_PSK -> AuthModeDomain.WPA3_PSK } -internal fun Band.toDomain() : BandDomain = when(this) { +internal fun Band.toDomain() = when(this) { Band.BAND_UNSPECIFIED -> BandDomain.BAND_UNSPECIFIED Band.BAND_2_4_GHZ -> BandDomain.BAND_2_4_GH Band.BAND_5_GHZ -> BandDomain.BAND_5_GH Band.BAND_6_GHZ -> BandDomain.BAND_6_GH } -internal fun WifiConfig.toDomain(): WifiConfigDomain { - return WifiConfigDomain( - ssid = ssid, - passphrase = passphrase, - bandDomain = band.toDomain(), - channel = channel, - authModeDomain = authMode.toDomain() - ) -} +internal fun WifiConfig.toDomain() = WifiConfigDomain( + ssid = ssid, + passphrase = passphrase, + bandDomain = band.toDomain(), + channel = channel, + authModeDomain = authMode.toDomain() +) -internal fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDomain( +internal fun WifiScanResult.toDomain() = WifiScanResultDomain( ssid = ssid, bssid = bssid, bandDomain = band.toDomain(), @@ -43,6 +41,6 @@ internal fun WifiScanResult.toDomain(): WifiScanResultDomain = WifiScanResultDom rssi = rssi ) -fun ScanResults.toDomain(): ScanResultsDomain = ScanResultsDomain( +fun ScanResults.toDomain() = ScanResultsDomain( wifiScanResults = results.map { it.toDomain() } ) \ No newline at end of file From fb3183f66986a46cd7c53d8b28302eafbee369d4 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:31:29 +0200 Subject: [PATCH 034/101] Add default values --- .../android/wifi/provisioner/softap/domain/WifiConfigDomain.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt index bae2bc8c..ce5dbf6b 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt @@ -36,5 +36,5 @@ data class WifiConfigDomain( val passphrase: String, val bandDomain: BandDomain = BandDomain.BAND_UNSPECIFIED, val channel: Int = 0, - val authModeDomain: AuthModeDomain = AuthModeDomain.AUTH_MODE_UNSPECIFIED + val authModeDomain: AuthModeDomain ) \ No newline at end of file From 17403930a396ded4e761c28f27e5faedaf339f0b Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:37:20 +0200 Subject: [PATCH 035/101] Clean up --- .../provisioner/softap/view/SoftApProvisioningScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 40612421..f15745a6 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -111,7 +111,7 @@ fun SoftApProvisioningScreen() { } Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { Button(onClick = { showDialog = true }) { - Text(text = "Setup Wi-Fi") + Text(text = stringResource(id = R.string.setup_wifi)) } } } @@ -124,7 +124,7 @@ fun SoftApProvisioningScreen() { }, title = { Text( - text = "Setup Wi-fi", + text = stringResource(id = R.string.setup_wifi), modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = MaterialTheme.typography.titleLarge @@ -133,7 +133,7 @@ fun SoftApProvisioningScreen() { text = { Column { Text( - text = "Please provide the Wi-Fi SSID and the Password", + text = stringResource(id = R.string.setup_wifi_rationale), modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyMedium ) From 843d4949be860f089bcd164fc107f314b05d72ef Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:37:52 +0200 Subject: [PATCH 036/101] Fix SoftApManager api --- .../provisioner/softap/ProvisioningState.kt | 10 -------- .../wifi/provisioner/softap/SoftApManager.kt | 25 ++++++++----------- .../softap/di/WifiServiceModule.kt | 7 +++++- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt index 8e073d4e..eba56fd4 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt @@ -24,16 +24,6 @@ sealed class ProvisioningState { */ data object Connected : ProvisioningState() - /** - * State when the discovering the network services available on the network. - */ - data object InitiatingNetworkServiceDiscovery : ProvisioningState() - - /** - * State when the network service discovery is complete. - */ - data class NetworkServiceDiscoveryComplete(val serviceInfo : NsdServiceInfo) : ProvisioningState() - /** * State when connected to a Unprovisioned Wifi Node */ diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index aea28d23..23d72211 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -26,22 +26,19 @@ import javax.inject.Inject * Created by Roshan Rajaratnam on 23/02/2024. * * Entry point to the SoftApManager - * - * @param context Application context. - * @param wifiService WifiServer api. - * @param coroutineDispatcher Coroutine dispatcher. - * + * @property connectivityManager Android's connectivity manager. + * @property nsdListener Network service discovery listener. + * @property wifiService WifiServer api. + * @property coroutineDispatcher Coroutine dispatcher. + * @property provisioningState Provisioning state. + * @constructor Create empty SoftApManager. */ class SoftApManager @Inject constructor( - context: Context, + private val connectivityManager: ConnectivityManager, private val nsdListener: NetworkServiceDiscoveryListener, private val wifiService: WifiService, private val coroutineDispatcher: CoroutineDispatcher ) { - private val connectivityManager = - context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager - private var _provisioningState = MutableStateFlow(ProvisioningState.Disconnected) val provisioningState = _provisioningState.asStateFlow() @@ -114,16 +111,16 @@ class SoftApManager @Inject constructor( /** * Discover services on the network. */ - suspend fun discoverServices() { + suspend fun discoverServices(): NsdServiceInfo { val serviceInfo = nsdListener.discoverServices() - _provisioningState.value = - ProvisioningState.NetworkServiceDiscoveryComplete(serviceInfo!!) + nsdListener.stopDiscovery() + return serviceInfo!! } /** * Stops the network service discovery. */ - fun stopDiscovery() { + private fun stopDiscovery() { nsdListener.stopDiscovery() } diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt index d0d0cb49..ccee931b 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt @@ -39,10 +39,15 @@ import javax.net.ssl.HostnameVerifier @InstallIn(SingletonComponent::class) object WifiServiceModule { + @Provides + @Singleton + fun provideConnectivityManager(@ApplicationContext context: Context): ConnectivityManager { + return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + @Provides @Singleton fun provideNetworkServiceDiscoveryListener(@ApplicationContext context : Context): NetworkServiceDiscoveryListener { - context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager return NetworkServiceDiscoveryListener(nsdManager) } From 254e1e8ed46e6c0d4e5e662b6ae7dc1dfa939aaa Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:38:27 +0200 Subject: [PATCH 037/101] Improvements. --- .../softap/viewmodel/SoftApViewModel.kt | 59 ++++++++++++++----- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 92ce641d..c4eb052a 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -16,7 +16,9 @@ import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.wifi.provisioner.softap.ProvisioningState import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.credentials.Credentials +import no.nordicsemi.android.wifi.provisioner.softap.domain.AuthModeDomain +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain +import okhttp3.OkHttpClient import javax.inject.Inject /** @@ -26,16 +28,16 @@ import javax.inject.Inject class SoftApViewModel @Inject constructor( navigator: Navigator, savedStateHandle: SavedStateHandle, - private val softApManager: SoftApManager + private val softApManager: SoftApManager, + private val okHttpClient: OkHttpClient ) : SimpleNavigationViewModel(navigator = navigator, savedStateHandle = savedStateHandle) { - init { softApManager.provisioningState.onEach { when (it) { ProvisioningState.Disconnected -> {} ProvisioningState.Connecting -> {} ProvisioningState.Connected -> { - provision() + discoverServices() } ProvisioningState.Provisioning -> {} ProvisioningState.ProvisioningComplete -> {} @@ -43,34 +45,61 @@ class SoftApViewModel @Inject constructor( }.launchIn(viewModelScope) } + override fun onCleared() { + super.onCleared() + softApManager.disconnect() + } + @RequiresApi(Build.VERSION_CODES.Q) internal fun connect(ssid: String = "mobileappsrules", password: String) { softApManager.connect(ssid = ssid, password = password) } - internal fun listSsids() { + private fun discoverServices() { + viewModelScope.launch { + softApManager.discoverServices() + listSsids() + } + } + + private fun listSsids() { val handler = CoroutineExceptionHandler { _, t -> Log.e("AAAA", "$t") } viewModelScope.launch(handler) { - softApManager.listSsids() + val result = softApManager.listSsids() + Log.d("AAAA", "Results: $result") + if (result.wifiScanResults.isNotEmpty()) { + val wifConfig = WifiConfigDomain( + ssid = "", + passphrase = "", + authModeDomain = AuthModeDomain.WPA3_PSK, + ) + provision(wifConfig) + } } } - internal fun provision( - credentials: Credentials = Credentials( - ssid = "OnHub", - password = "newbird379" - ) - ) { + private fun provision(config: WifiConfigDomain) { + val handler = CoroutineExceptionHandler { _, t -> Log.e("AAAA", "$t") } viewModelScope.launch(handler) { - softApManager.provision(credentials = credentials).also { response -> - if (response.isSuccessful) { - softApManager.disconnect() + try { + softApManager.provision(config = config).also { response -> + if (response.isSuccessful) { + softApManager.disconnect() + softApManager.discoverServices() + } } + } catch (exception: Exception) { + // TODO This workaround was added to start the service discovery again once the + // provisioning is completed. This has to be cleaned up once the fw disconnects + // gracefully. + Log.e("AAAA", "Error: $exception") + softApManager.disconnect() + softApManager.discoverServices() } } } From f430e0dac4d048953d77ebb9edfa1b52cbdc1c79 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:47:31 +0200 Subject: [PATCH 038/101] Improvements. --- .../android/wifi/provisioner/softap/ProvisioningState.kt | 2 -- .../android/wifi/provisioner/softap/SoftApManager.kt | 2 -- .../wifi/provisioner/softap/di/SoftApManagerModule.kt | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt index eba56fd4..de7f1ab2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt @@ -1,7 +1,5 @@ package no.nordicsemi.android.wifi.provisioner.softap -import android.net.nsd.NsdServiceInfo - /** * Created by Roshan Rajaratnam on 23/02/2024. * diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 23d72211..e75dfbe2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -2,12 +2,10 @@ package no.nordicsemi.android.wifi.provisioner.softap -import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest -import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.net.wifi.WifiNetworkSpecifier import android.os.Build diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt index fadd8762..390d69ac 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt @@ -1,6 +1,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.di import android.content.Context +import android.net.ConnectivityManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -22,12 +23,12 @@ object SoftApManagerModule { @Provides @Singleton fun provideSoftApManager( - @ApplicationContext context: Context, + connectivityManager: ConnectivityManager, nsdListener: NetworkServiceDiscoveryListener, wifiService: WifiService, @IODispatcher coroutineDispatcher: CoroutineDispatcher ) = SoftApManager( - context = context, + connectivityManager = connectivityManager, nsdListener = nsdListener, wifiService = wifiService, coroutineDispatcher = coroutineDispatcher From 01d7cd0c31de21d379e5c02e1e706e5e9dea5184 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 11:47:55 +0200 Subject: [PATCH 039/101] Fix imports --- .../android/wifi/provisioner/softap/di/SoftApManagerModule.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt index 390d69ac..c773365f 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt @@ -1,11 +1,9 @@ package no.nordicsemi.android.wifi.provisioner.softap.di -import android.content.Context import android.net.ConnectivityManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineDispatcher import no.nordicsemi.android.wifi.provisioner.softap.NetworkServiceDiscoveryListener From 16fe56b70352e616e0e54c3a4520e7e4b151de94 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 12 Apr 2024 14:13:50 +0200 Subject: [PATCH 040/101] Fix packages --- .../android/wifi/provisioner/ble/password/PasswordDialog.kt | 3 --- .../wifi/provisioner/ble/password/PasswordDialogEvent.kt | 2 +- .../ble/repository/ProvisionerResourceRepository.kt | 2 +- .../wifi/provisioner/ble/repository/RepositoryModule.kt | 1 + .../android/wifi/provisioner/ble/scanner/ProvisioningData.kt | 2 +- .../provisioner/ble/scanner/ProvisioningScannerDestinations.kt | 3 --- .../wifi/provisioner/ble/scanner/ProvisioningSection.kt | 2 +- .../android/wifi/provisioner/ble/view/BleProvisioningScreen.kt | 2 +- .../android/wifi/provisioner/ble/viewmodel/BleViewModel.kt | 2 +- .../provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt | 2 +- 10 files changed, 8 insertions(+), 13 deletions(-) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt index c2ad4b53..937b5d1e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt @@ -48,9 +48,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.password.DismissEvent -import no.nordicsemi.android.wifi.provisioner.password.PasswordDialogEvent -import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt index e716e8d8..463c5d33 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.password +package no.nordicsemi.android.wifi.provisioner.ble.password sealed interface PasswordDialogEvent diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt index 1ec75744..c14556a1 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.repository +package no.nordicsemi.android.wifi.provisioner.ble.repository import android.bluetooth.BluetoothDevice import kotlinx.coroutines.flow.Flow diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt index f86d2c2c..998a449f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt @@ -38,6 +38,7 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository +import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository @Module @InstallIn(SingletonComponent::class) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt index 288ac1d2..f6c58e27 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.scanner +package no.nordicsemi.android.wifi.provisioner.ble.scanner import android.os.ParcelUuid import no.nordicsemi.android.common.core.DataByteArray diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt index 65cf48c5..86be940f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningScannerDestinations.kt @@ -40,9 +40,6 @@ import no.nordicsemi.android.kotlin.ble.ui.scanner.DeviceSelected import no.nordicsemi.android.kotlin.ble.ui.scanner.ScannerScreen import no.nordicsemi.android.kotlin.ble.ui.scanner.ScanningCancelled import no.nordicsemi.android.kotlin.ble.ui.scanner.main.DeviceListItem -import no.nordicsemi.android.wifi.provisioner.scanner.ProvisioningData -import no.nordicsemi.android.wifi.provisioner.scanner.ProvisioningSection -import no.nordicsemi.android.wifi.provisioner.scanner.provisioningData val BleScannerDestinationId = createDestination("ble-scanner-destination") diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt index f72d004d..24355aae 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.scanner +package no.nordicsemi.android.wifi.provisioner.ble.scanner import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index a8e4a66b..a91a4073 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -63,7 +63,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ble.sections.UnprovisioningSection import no.nordicsemi.android.wifi.provisioner.ble.password.PasswordDialog -import no.nordicsemi.android.wifi.provisioner.password.PasswordSetDialogEvent +import no.nordicsemi.android.wifi.provisioner.ble.password.PasswordSetDialogEvent @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 33cf3f91..c6f8ca13 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -68,7 +68,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEv import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository +import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import javax.inject.Inject @HiltViewModel diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index abeb6f72..13bee1ae 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -40,7 +40,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.wifi.provisioner.repository.ProvisionerResourceRepository +import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.NavigateUpEvent import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.OnSortOptionSelected import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData From e0187e71ee7c75c687d536e91eff925fffbd9a13 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 17 Apr 2024 10:12:23 +0200 Subject: [PATCH 041/101] Fix imports --- .../provisioner/ble/view/BleDestination.kt | 11 ++++++++++- .../wifi/view/WiFiAccessPointListsScreen.kt | 18 ++++++++---------- .../ble/wifi/view/WifiScannerViewEntity.kt | 6 +----- .../ble/wifi/view/WifiScannerViewEvent.kt | 4 ++-- .../ble/wifi/viewmodel/WifiScannerViewModel.kt | 1 + feature/ble/src/main/res/values/strings.xml | 4 ---- feature/ui/build.gradle.kts | 2 ++ .../provisioner/ui}/view/WifiLoadingItem.kt | 2 +- .../provisioner/ui/view}/WifiSortOption.kt | 2 +- .../wifi/provisioner/ui}/view/WifiSortView.kt | 7 +++---- feature/ui/src/main/res/values/strings.xml | 4 ++++ .../provisioner/ble/domain/WifiInfoDomain.kt | 9 +++------ .../softap/NetworkServiceDiscoveryListener.kt | 6 +++++- 13 files changed, 41 insertions(+), 35 deletions(-) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/view/WifiLoadingItem.kt (98%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view}/WifiSortOption.kt (96%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/view/WifiSortView.kt (95%) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 77cffd96..927b8517 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -31,17 +31,26 @@ package no.nordicsemi.android.wifi.provisioner.ble.view +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel val BleProvisioningDestinationId = createSimpleDestination("ble-provisioning-destination") val WiFiAccessPointsListId = createDestination("wifi-access-points-destination") val BleProvisioningDestinations = listOf( defineDestination(BleProvisioningDestinationId) { BleProvisioningScreen() }, - defineDestination(WiFiAccessPointsListId) { WiFiAccessPointListsScreen() } + defineDestination(WiFiAccessPointsListId) { + + val viewModel = hiltViewModel() + val viewEntity by viewModel.state.collectAsStateWithLifecycle() + WiFiAccessPointListsScreen(viewEntity = viewEntity, onEvent = viewModel::onEvent) + } ) + BleScannerDestination diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index bbe2a0c7..54676a55 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -53,7 +53,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable @@ -62,34 +61,33 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector -import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortView @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun WiFiAccessPointListsScreen() { - val viewModel = hiltViewModel() - val viewEntity by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (WifiScannerViewEvent) -> Unit = { viewModel.onEvent(it) } +internal fun WiFiAccessPointListsScreen( + viewEntity: WifiScannerViewEntity, + onEvent: (WifiScannerViewEvent) -> Unit +) { Column(horizontalAlignment = Alignment.CenterHorizontally) { NordicAppBar( text = stringResource(id = R.string.wifi_title), - onNavigationButtonClick = { viewModel.onEvent(NavigateUpEvent) } + onNavigationButtonClick = { onEvent(NavigateUpEvent) } ) if (viewEntity.isLoading) { LoadingItem() } else if (viewEntity.error != null) { - ErrorItem(viewEntity.error!!) + ErrorItem(viewEntity.error) } else { WifiList(viewEntity, onEvent) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt index 93c3e004..95cfc545 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt @@ -33,7 +33,7 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.view import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, @@ -45,16 +45,13 @@ data class WifiScannerViewEntity( WifiSortOption.NAME -> items.sortedBy { it.wifiData.ssid } WifiSortOption.RSSI -> items.sortedByDescending { it.biggestRssi } } - } data class ScanRecordsForSsid( val wifiData: WifiData, val items: List = emptyList(), ) { - val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } - } data class WifiData( @@ -63,7 +60,6 @@ data class WifiData( val channelFallback: ScanRecordDomain, //Needed for proto v1 val selectedChannel: ScanRecordDomain? = null ) { - fun isPasswordRequired(): Boolean { return authMode != AuthModeDomain.OPEN } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt index 4c40b654..ff98b0ba 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt @@ -31,11 +31,11 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.view -import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption internal sealed class WifiScannerViewEvent -internal object NavigateUpEvent : WifiScannerViewEvent() +internal data object NavigateUpEvent : WifiScannerViewEvent() internal data class WifiSelectedEvent(val wifiData: WifiData) : WifiScannerViewEvent() diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index 13bee1ae..55189586 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -51,6 +51,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption import javax.inject.Inject @HiltViewModel diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml index cdb17c49..1c1f78e5 100644 --- a/feature/ble/src/main/res/values/strings.xml +++ b/feature/ble/src/main/res/values/strings.xml @@ -136,8 +136,4 @@ Select Wi-Fi Persistent storage - - Sort by: - Name - RSSI \ No newline at end of file diff --git a/feature/ui/build.gradle.kts b/feature/ui/build.gradle.kts index 96fe1487..bb909f64 100644 --- a/feature/ui/build.gradle.kts +++ b/feature/ui/build.gradle.kts @@ -38,6 +38,8 @@ android { } dependencies { + implementation(libs.nordic.theme) + implementation(libs.androidx.compose.ui) implementation(libs.androidx.compose.ui.tooling) implementation(libs.androidx.compose.foundation) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiLoadingItem.kt similarity index 98% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiLoadingItem.kt index 59f1844c..e2db3d96 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiLoadingItem.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiLoadingItem.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.view +package no.nordicsemi.android.wifi.provisioner.ui.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt similarity index 96% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt index a1edb84d..65fadc3f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiSortOption.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel +package no.nordicsemi.android.wifi.provisioner.ui.view enum class WifiSortOption { NAME, RSSI diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt similarity index 95% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt index 3f0ec8df..ea12e510 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiSortView.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.view +package no.nordicsemi.android.wifi.provisioner.ui.view import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -52,12 +52,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiSortOption -import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.common.theme.R as themeR @Composable -internal fun WifiSortView( +fun WifiSortView( sortOption: WifiSortOption, onChanged: (WifiSortOption) -> Unit, ) { diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 7309bfbc..4008f391 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -2,4 +2,8 @@ Icon representing data available in the section. Unknown Error + + Sort by: + Name + RSSI \ No newline at end of file diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt index 66ab2a3d..757dea06 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt @@ -41,11 +41,8 @@ data class WifiInfoDomain( val authModeDomain: AuthModeDomain? ) { - val macAddress: String - - init { - macAddress = bssid.toByteArray().joinToString(":") { - "%02x".format(it).uppercase() - } + val macAddress: String = bssid.toByteArray().joinToString(":") { + "%02x".format(it).uppercase() } + } diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 051acc40..ff6f35f9 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -2,7 +2,9 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo +import android.os.Build import android.util.Log +import androidx.annotation.RequiresApi import kotlinx.coroutines.sync.Mutex import java.net.InetAddress @@ -21,6 +23,7 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage private var _serviceInfo: NsdServiceInfo? = null + /** * Callback used to listen for service discovery. */ @@ -33,8 +36,9 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceFound(service: NsdServiceInfo) { // A service was found! Do something with it. - Log.d("AAAA", "Service discovery success $service") + Log.d("AAAA", "Service discovered $service") if (service.serviceName == SERVICE_NAME) { + Log.d("AAAA", "Resolving service $service") nsdManager.resolveService(service, resolveListener) } } From 696f2eb29197e152e02f86e5f042ced641f5d9d6 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 17 Apr 2024 14:33:47 +0200 Subject: [PATCH 042/101] Refactoring --- app/build.gradle.kts | 1 + feature/ble/build.gradle.kts | 3 +- .../wifi/view/WiFiAccessPointListsScreen.kt | 4 + .../ble/wifi/view/WifiScannerViewEntity.kt | 5 +- .../proto => feature/common}/.gitignore | 0 feature/common/build.gradle.kts | 43 ++++++++++ feature/common/consumer-rules.pro | 0 .../common/proguard-rules.pro | 2 +- .../provisioner/ExampleInstrumentedTest.kt | 24 ++++++ feature/common/src/main/AndroidManifest.xml | 4 + .../wifi/provisioner/WifiDataConfiguration.kt | 3 + .../event}/WifiScannerViewEvent.kt | 12 +-- .../wifi/provisioner/event}/WifiSortOption.kt | 2 +- .../wifi/provisioner/ExampleUnitTest.kt | 17 ++++ feature/softap/build.gradle.kts | 1 + .../softap/view/SoftApProvisioningScreen.kt | 2 +- .../softap/src/main/res/values/strings.xml | 2 + feature/ui/build.gradle.kts | 2 + .../android/wifi/provisioner/ui/DataItem.kt | 30 +++++++ .../wifi/provisioner/ui/view/WifiSortView.kt | 1 + lib/softap/proto/build.gradle.kts | 44 ---------- lib/softap/proto/src/main/AndroidManifest.xml | 33 ------- lib/softap/provisioner/build.gradle.kts | 5 +- .../softap/NetworkServiceDiscoveryListener.kt | 2 - .../wifi/provisioner/softap/WifiService.kt | 4 - .../softap/domain/AuthModeDomain.kt | 15 ++-- .../softap/domain/ScanRecordDomain.kt | 6 ++ .../softap/domain/ScanResultsDomain.kt | 2 +- .../provisioner/softap/domain/ToApiMapper.kt | 20 ++--- .../softap/domain/ToDomainMapper.kt | 24 +++--- .../softap/domain/WifiConfigDomain.kt | 7 +- ...iScanResultDomain.kt => WifiInfoDomain.kt} | 8 +- .../src/main/proto/common.proto | 85 +++++++++---------- settings.gradle.kts | 6 +- 34 files changed, 236 insertions(+), 183 deletions(-) rename {lib/softap/proto => feature/common}/.gitignore (100%) create mode 100644 feature/common/build.gradle.kts create mode 100644 feature/common/consumer-rules.pro rename lib/softap/proto/module-rules.pro => feature/common/proguard-rules.pro (94%) create mode 100644 feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt create mode 100644 feature/common/src/main/AndroidManifest.xml create mode 100644 feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view => common/src/main/java/no/nordicsemi/android/wifi/provisioner/event}/WifiScannerViewEvent.kt (79%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view => common/src/main/java/no/nordicsemi/android/wifi/provisioner/event}/WifiSortOption.kt (96%) create mode 100644 feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt delete mode 100644 lib/softap/proto/build.gradle.kts delete mode 100644 lib/softap/proto/src/main/AndroidManifest.xml create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt rename lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/{WifiScanResultDomain.kt => WifiInfoDomain.kt} (54%) rename lib/softap/{proto => provisioner}/src/main/proto/common.proto (53%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b1e6bba1..4a7bc6b1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,6 +45,7 @@ dependencies { implementation(project(":lib:ble:provisioner")) implementation(project(":feature:ble")) implementation(project(":feature:softap")) + implementation(project(":feature:common")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index ff479da6..57e331df 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -39,8 +39,9 @@ android { } dependencies { - implementation(project(":lib:ble:provisioner")) + implementation(project(":feature:common")) implementation(project(":feature:ui")) + implementation(project(":lib:ble:provisioner")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index 54676a55..0cbce9d6 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -66,6 +66,10 @@ import no.nordicsemi.android.common.theme.view.getWiFiRes import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector +import no.nordicsemi.android.wifi.provisioner.event.NavigateUpEvent +import no.nordicsemi.android.wifi.provisioner.event.OnSortOptionSelected +import no.nordicsemi.android.wifi.provisioner.event.WifiScannerViewEvent +import no.nordicsemi.android.wifi.provisioner.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt index 95cfc545..a3ee699a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt @@ -31,9 +31,10 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.view +import no.nordicsemi.android.wifi.provisioner.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.event.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, @@ -59,7 +60,7 @@ data class WifiData( val authMode: AuthModeDomain, val channelFallback: ScanRecordDomain, //Needed for proto v1 val selectedChannel: ScanRecordDomain? = null -) { +) : WifiDataConfiguration { fun isPasswordRequired(): Boolean { return authMode != AuthModeDomain.OPEN } diff --git a/lib/softap/proto/.gitignore b/feature/common/.gitignore similarity index 100% rename from lib/softap/proto/.gitignore rename to feature/common/.gitignore diff --git a/feature/common/build.gradle.kts b/feature/common/build.gradle.kts new file mode 100644 index 00000000..659a8d39 --- /dev/null +++ b/feature/common/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "no.nordicsemi.android.wifi.provisioner" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.10.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} \ No newline at end of file diff --git a/feature/common/consumer-rules.pro b/feature/common/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/lib/softap/proto/module-rules.pro b/feature/common/proguard-rules.pro similarity index 94% rename from lib/softap/proto/module-rules.pro rename to feature/common/proguard-rules.pro index ff59496d..481bb434 100644 --- a/lib/softap/proto/module-rules.pro +++ b/feature/common/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. +# proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt b/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..25b90b6a --- /dev/null +++ b/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package no.nordicsemi.android.wifi.provisioner + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("no.nordicsemi.android.wifi.provisioner.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/feature/common/src/main/AndroidManifest.xml b/feature/common/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/feature/common/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt new file mode 100644 index 00000000..90f1afae --- /dev/null +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt @@ -0,0 +1,3 @@ +package no.nordicsemi.android.wifi.provisioner + +interface WifiDataConfiguration \ No newline at end of file diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt similarity index 79% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt index ff98b0ba..5227f1a3 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt @@ -29,14 +29,14 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.view +package no.nordicsemi.android.wifi.provisioner.event -import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.WifiDataConfiguration -internal sealed class WifiScannerViewEvent +sealed class WifiScannerViewEvent -internal data object NavigateUpEvent : WifiScannerViewEvent() +data object NavigateUpEvent : WifiScannerViewEvent() -internal data class WifiSelectedEvent(val wifiData: WifiData) : WifiScannerViewEvent() +data class WifiSelectedEvent(val wifiData: WifiDataConfiguration) : WifiScannerViewEvent() -internal data class OnSortOptionSelected(val sortOption: WifiSortOption) : WifiScannerViewEvent() +data class OnSortOptionSelected(val sortOption: WifiSortOption) : WifiScannerViewEvent() diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt similarity index 96% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt rename to feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt index 65fadc3f..c5e2e0df 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortOption.kt +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view +package no.nordicsemi.android.wifi.provisioner.event enum class WifiSortOption { NAME, RSSI diff --git a/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt b/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt new file mode 100644 index 00000000..b6e89404 --- /dev/null +++ b/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package no.nordicsemi.android.wifi.provisioner + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index a951f622..a03ce7e1 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -40,6 +40,7 @@ android { dependencies { + implementation(project(":feature:common")) implementation(project(":feature:ui")) implementation(project(":lib:softap:provisioner")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index f15745a6..140b11e9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -80,7 +80,7 @@ fun SoftApProvisioningScreen() { val viewModel = hiltViewModel() LocalContext.current - var ssid by rememberSaveable { mutableStateOf("mobileappsrules") } + var ssid by rememberSaveable { mutableStateOf("0018F0-nrf-wifiprov") } var password by rememberSaveable { mutableStateOf("") } var showDialog by rememberSaveable { mutableStateOf(false) } var showPassword by rememberSaveable { mutableStateOf(false) } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index b3c9c575..0c61e709 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -6,4 +6,6 @@ Change Wi-Fi Dismiss Confirm + Wi-Fi Access Points + Scanning error \ No newline at end of file diff --git a/feature/ui/build.gradle.kts b/feature/ui/build.gradle.kts index bb909f64..33aa504a 100644 --- a/feature/ui/build.gradle.kts +++ b/feature/ui/build.gradle.kts @@ -38,6 +38,8 @@ android { } dependencies { + implementation(project(":feature:common")) + implementation(libs.nordic.theme) implementation(libs.androidx.compose.ui) diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt index af24bf57..5d13752b 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/DataItem.kt @@ -96,6 +96,36 @@ fun ErrorDataItem( } } +@Composable +fun ErrorDataItem( + imageVector: ImageVector, + title: String, + error: Throwable? +) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + imageVector = imageVector, + contentDescription = stringResource(id = R.string.cd_data_item_icon), + ) + + Spacer(modifier = Modifier.size(16.dp)) + + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + style = MaterialTheme.typography.labelLarge + ) + + Text( + text = error?.message ?: stringResource(id = R.string.unknown_error), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.error + ) + } + } +} + + @Composable fun DataItem( imageVector: ImageVector, diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt index ea12e510..ace61ff3 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt @@ -52,6 +52,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.event.WifiSortOption import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.common.theme.R as themeR diff --git a/lib/softap/proto/build.gradle.kts b/lib/softap/proto/build.gradle.kts deleted file mode 100644 index c3ade32d..00000000 --- a/lib/softap/proto/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -plugins { - alias(libs.plugins.nordic.library) - alias(libs.plugins.nordic.kotlin) - alias(libs.plugins.wire) -} - -wire { - kotlin {} -} - -android { - namespace = "no.nordicsemi.android.wifi.provisioner.softap.proto" -} diff --git a/lib/softap/proto/src/main/AndroidManifest.xml b/lib/softap/proto/src/main/AndroidManifest.xml deleted file mode 100644 index d554f457..00000000 --- a/lib/softap/proto/src/main/AndroidManifest.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - \ No newline at end of file diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 63aa6093..bbaf85f2 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -1,14 +1,17 @@ plugins { alias(libs.plugins.nordic.library) alias(libs.plugins.nordic.hilt) + alias(libs.plugins.wire) } +wire { + kotlin {} +} android { namespace = "no.nordicsemi.android.wifi.provisioner.softap" } dependencies { - implementation(project(":lib:softap:proto")) implementation(libs.retrofit.core) implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.converter.scalars) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index ff6f35f9..291d9cff 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -2,9 +2,7 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo -import android.os.Build import android.util.Log -import androidx.annotation.RequiresApi import kotlinx.coroutines.sync.Mutex import java.net.InetAddress diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt index 064c9170..373bd8a5 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt @@ -2,16 +2,12 @@ package no.nordicsemi.android.wifi.provisioner.softap import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig -import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult import okhttp3.ResponseBody import retrofit2.Response import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Headers import retrofit2.http.POST -import retrofit2.http.PUT -import retrofit2.http.Path -import java.net.InetAddress /** * Created by Roshan Rajaratnam on 19/02/2024. diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt index 3f208644..db55deda 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt @@ -32,12 +32,11 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain enum class AuthModeDomain(val id: Int) { - AUTH_MODE_UNSPECIFIED(0), - OPEN(1), - WEP(2), - WPA_PSK(3), - WPA2_PSK(4), - WPA_WPA2_PSK(5), - WPA2_ENTERPRISE(6), - WPA3_PSK(7) + OPEN(0), + WEP(1), + WPA_PSK(2), + WPA2_PSK(3), + WPA_WPA2_PSK(4), + WPA2_ENTERPRISE(5), + WPA3_PSK(6) } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt new file mode 100644 index 00000000..7a9beece --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt @@ -0,0 +1,6 @@ +package no.nordicsemi.android.wifi.provisioner.softap.domain + +data class ScanRecordDomain( + val infoDomain: WifiInfoDomain?, + val rssi: Int +) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt index eaf891b9..07020d84 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt @@ -1,5 +1,5 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain data class ScanResultsDomain( - val wifiScanResults : List + val results : List ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index 32737097..6d4f4a63 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -2,12 +2,12 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain import no.nordicsemi.android.wifi.provisioner.softap.proto.AuthMode import no.nordicsemi.android.wifi.provisioner.softap.proto.Band +import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig -import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo internal fun AuthModeDomain.toApi() = when(this) { - AuthModeDomain.AUTH_MODE_UNSPECIFIED -> AuthMode.AUTH_MODE_UNSPECIFIED AuthModeDomain.OPEN -> AuthMode.OPEN AuthModeDomain.WEP -> AuthMode.WEP AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK @@ -25,22 +25,22 @@ internal fun BandDomain.toApi() = when(this) { } internal fun WifiConfigDomain.toApi() = WifiConfig( + info = wifiInfoDomain?.toApi(), + passphrase = passphrase +) + +internal fun WifiInfoDomain.toApi() = WifiInfo( ssid = ssid, - passphrase = passphrase, band = bandDomain.toApi(), channel = channel, authMode = authModeDomain.toApi() ) -internal fun WifiScanResultDomain.toApi() = WifiScanResult( - ssid = ssid, - bssid = bssid, - band = bandDomain.toApi(), - channel = channel, - authMode = authModeDomain.toApi(), +internal fun ScanRecordDomain.toApi() = ScanRecord( + wifi = infoDomain?.toApi(), rssi = rssi ) internal fun ScanResultsDomain.toApi() = ScanResults( - results = wifiScanResults.map { it.toApi() } + results = results.map { it.toApi() } ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt index 2a47012a..0a2f7987 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -2,12 +2,12 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain import no.nordicsemi.android.wifi.provisioner.softap.proto.AuthMode import no.nordicsemi.android.wifi.provisioner.softap.proto.Band +import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig -import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiScanResult +import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo internal fun AuthMode.toDomain() = when(this) { - AuthMode.AUTH_MODE_UNSPECIFIED -> AuthModeDomain.AUTH_MODE_UNSPECIFIED AuthMode.OPEN -> AuthModeDomain.OPEN AuthMode.WEP -> AuthModeDomain.WEP AuthMode.WPA_PSK -> AuthModeDomain.WPA_PSK @@ -24,23 +24,23 @@ internal fun Band.toDomain() = when(this) { Band.BAND_6_GHZ -> BandDomain.BAND_6_GH } -internal fun WifiConfig.toDomain() = WifiConfigDomain( +internal fun WifiInfo.toDomain() = WifiInfoDomain( ssid = ssid, - passphrase = passphrase, bandDomain = band.toDomain(), channel = channel, authModeDomain = authMode.toDomain() ) -internal fun WifiScanResult.toDomain() = WifiScanResultDomain( - ssid = ssid, - bssid = bssid, - bandDomain = band.toDomain(), - channel = channel, - authModeDomain = authMode.toDomain(), +internal fun WifiConfig.toDomain() = WifiConfigDomain( + wifiInfoDomain = info?.toDomain(), + passphrase = passphrase +) + +internal fun ScanRecord.toDomain() = ScanRecordDomain( + infoDomain = wifi?.toDomain(), rssi = rssi ) -fun ScanResults.toDomain() = ScanResultsDomain( - wifiScanResults = results.map { it.toDomain() } +internal fun ScanResults.toDomain() = ScanResultsDomain( + results = results.map { it.toDomain() } ) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt index ce5dbf6b..0e928cd1 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt @@ -32,9 +32,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain data class WifiConfigDomain( - val ssid: String, - val passphrase: String, - val bandDomain: BandDomain = BandDomain.BAND_UNSPECIFIED, - val channel: Int = 0, - val authModeDomain: AuthModeDomain + val wifiInfoDomain: WifiInfoDomain?, + val passphrase: String ) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt similarity index 54% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt index fbf784dd..63bb2474 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiScanResultDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt @@ -1,10 +1,8 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain -data class WifiScanResultDomain( +data class WifiInfoDomain( val ssid: String, - val bssid: String, val bandDomain: BandDomain, val channel: Int, - val authModeDomain: AuthModeDomain, - val rssi: Int -) \ No newline at end of file + val authModeDomain: AuthModeDomain +) diff --git a/lib/softap/proto/src/main/proto/common.proto b/lib/softap/provisioner/src/main/proto/common.proto similarity index 53% rename from lib/softap/proto/src/main/proto/common.proto rename to lib/softap/provisioner/src/main/proto/common.proto index eb8dca75..b352bc84 100644 --- a/lib/softap/proto/src/main/proto/common.proto +++ b/lib/softap/provisioner/src/main/proto/common.proto @@ -1,44 +1,43 @@ -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.softap.proto"; - -// Common ENUMs -enum Band { - BAND_UNSPECIFIED = 0; - BAND_2_4_GHZ = 1; - BAND_5_GHZ = 2; - BAND_6_GHZ = 3; -} - -enum AuthMode { - AUTH_MODE_UNSPECIFIED = 0; - OPEN = 1; - WEP = 2; - WPA_PSK = 3; - WPA2_PSK = 4; - WPA_WPA2_PSK = 5; - WPA2_ENTERPRISE = 6; - WPA3_PSK = 7; -} - -message WifiScanResult { - string ssid = 1; - string bssid = 2; - Band band = 3; - uint32 channel = 4; - AuthMode authMode = 5; - int32 rssi = 6; -} - -message ScanResults { - repeated WifiScanResult results = 1; -} - -message WifiConfig { - string ssid = 1; - string passphrase = 2; - Band band = 3; - uint32 channel = 4; - AuthMode authMode = 5; +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.softap.proto"; + +// Common ENUMs +enum Band { + BAND_UNSPECIFIED = 0; + BAND_2_4_GHZ = 1; + BAND_5_GHZ = 2; + BAND_6_GHZ = 3; +} + +enum AuthMode { + OPEN = 0; + WEP = 1; + WPA_PSK = 2; + WPA2_PSK = 3; + WPA_WPA2_PSK = 4; + WPA2_ENTERPRISE = 5; + WPA3_PSK = 6; +} + +message WifiInfo { + string ssid = 1; + Band band = 3; + uint32 channel = 4; + AuthMode authMode = 5; +} + +message WifiConfig { + WifiInfo info = 1; + string passphrase = 2; +} + +message ScanRecord { + WifiInfo wifi = 1; + int32 rssi = 2; +} + +message ScanResults { + repeated ScanRecord results = 1; } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 6083ac9d..7257d56e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -57,9 +57,10 @@ rootProject.name = "Android-nRF-Wifi-Provisioner" include(":app") include(":feature:ble") include(":feature:softap") -include(":lib:ble:provisioner") +include(":feature:ui") +include(":feature:common") include(":lib:ble:proto") -include(":lib:softap:proto") +include(":lib:ble:provisioner") include(":lib:softap:provisioner") //if (file('../Android-Common-Libraries').exists()) { @@ -69,4 +70,3 @@ include(":lib:softap:provisioner") //if (file('../Android-BLE-Library').exists()) { // includeBuild('../Android-BLE-Library') //} -include(":feature:ui") From e46f468c5f9575e2b69b9ee12574001167f687be Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 18 Apr 2024 14:18:34 +0200 Subject: [PATCH 043/101] Improvements to Library and app architecture --- build.gradle.kts | 1 + .../ProvisionerResourceRepository.kt | 8 ++-- .../provisioner/ble/sections/WifiSection.kt | 4 +- .../provisioner/ble/view/BleDestination.kt | 7 ++-- .../wifi/provisioner/ble/view/UiMapper.kt | 19 ++++----- .../provisioner/ble/viewmodel/BleViewModel.kt | 11 +++-- .../ble/wifi/view/SelectChannelDialog.kt | 8 ++-- .../wifi/view/WiFiAccessPointListsScreen.kt | 12 +++--- .../ble/wifi/view/WifiScannerViewEntity.kt | 18 ++++---- .../ble/wifi/viewmodel/WifiAggregator.kt | 8 ++-- .../wifi/viewmodel/WifiScannerViewModel.kt | 14 +++---- feature/common/build.gradle.kts | 41 +++--------------- feature/common/src/main/AndroidManifest.xml | 4 +- .../wifi/provisioner/WifiDataConfiguration.kt | 3 -- .../common/WifiDataConfiguration.kt | 14 +++++++ .../event/WifiScannerViewEvent.kt | 4 +- .../{ => common}/event/WifiSortOption.kt | 2 +- .../softap/view/WifiScannerViewEntity.kt | 39 ++++++++++++++--- .../wifi/provisioner/ui/view/WifiSortView.kt | 2 +- lib/ble/provisioner/build.gradle.kts | 2 +- .../provisioner/ble/ProvisionerRepository.kt | 8 ++-- .../ble/ProvisionerRepositoryImpl.kt | 8 ++-- .../ble/domain/DeviceStatusDomain.kt | 2 +- .../provisioner/ble/domain/ToApiMapper.kt | 22 +++++----- .../provisioner/ble/domain/ToDomainMapper.kt | 24 +++++------ lib/domain/.gitignore | 1 + lib/domain/build.gradle.kts | 9 ++++ .../provisioner}/domain/AuthModeDomain.kt | 2 +- .../wifi/provisioner}/domain/BandDomain.kt | 4 +- .../provisioner}/domain/ScanRecordDomain.kt | 4 +- .../provisioner}/domain/WifiConfigDomain.kt | 4 +- .../provisioner}/domain/WifiInfoDomain.kt | 9 ++-- lib/softap/provisioner/build.gradle.kts | 1 + .../wifi/provisioner/softap/SoftApManager.kt | 2 +- .../softap/domain/AuthModeDomain.kt | 42 ------------------- .../softap/domain/ScanRecordDomain.kt | 6 --- .../softap/domain/ScanResultsDomain.kt | 2 + .../provisioner/softap/domain/ToApiMapper.kt | 18 +++++--- .../softap/domain/ToDomainMapper.kt | 21 +++++++--- .../softap/domain/WifiConfigDomain.kt | 37 ---------------- .../softap/domain/WifiInfoDomain.kt | 8 ---- settings.gradle.kts | 2 +- 42 files changed, 201 insertions(+), 256 deletions(-) delete mode 100644 feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt create mode 100644 feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt rename feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/{ => common}/event/WifiScannerViewEvent.kt (93%) rename feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/{ => common}/event/WifiSortOption.kt (96%) rename lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt => feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt (54%) create mode 100644 lib/domain/.gitignore create mode 100644 lib/domain/build.gradle.kts rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/AuthModeDomain.kt (96%) rename lib/{softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/BandDomain.kt (95%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/ScanRecordDomain.kt (94%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/WifiConfigDomain.kt (95%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/WifiInfoDomain.kt (92%) delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt diff --git a/build.gradle.kts b/build.gradle.kts index 3648359b..7c56c389 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,4 +43,5 @@ plugins { alias(libs.plugins.nordic.hilt) apply false alias(libs.plugins.nordic.feature) apply false alias(libs.plugins.kotlin.android) apply false + id("org.jetbrains.kotlin.jvm") version "1.9.21" apply false } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt index c14556a1..60a7dbf9 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt @@ -40,9 +40,9 @@ import kotlinx.coroutines.flow.onStart import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus @@ -62,7 +62,7 @@ class ProvisionerResourceRepository( return runTask { repository.getStatus() } } - fun startScan(): Flow> { + fun startScan(): Flow> { return repository.startScan() .map { Resource.createSuccess(it) } .onStart { emit(Resource.createLoading()) } @@ -76,7 +76,7 @@ class ProvisionerResourceRepository( repository.stopScan() } - fun setConfig(config: WifiConfigDomain): Flow> { + fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow> { return repository.setConfig(config) .map { Resource.createSuccess(it) } .onStart { emit(Resource.createLoading()) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index a7ecd4ae..4be83c06 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -37,7 +37,7 @@ import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem @@ -63,7 +63,7 @@ internal fun WifiSection( } @Composable -private fun getDescription(record: ScanRecordDomain): String { +private fun getDescription(record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain): String { return StringBuilder() .append(record.wifiInfo.ssid) .appendLine() diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 927b8517..d8c62e38 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -37,18 +37,19 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel val BleProvisioningDestinationId = createSimpleDestination("ble-provisioning-destination") -val WiFiAccessPointsListId = createDestination("wifi-access-points-destination") +val WiFiAccessPointsListId = createDestination( + name = "wifi-access-points-destination" +) val BleProvisioningDestinations = listOf( defineDestination(BleProvisioningDestinationId) { BleProvisioningScreen() }, defineDestination(WiFiAccessPointsListId) { - val viewModel = hiltViewModel() val viewEntity by viewModel.state.collectAsStateWithLifecycle() WiFiAccessPointListsScreen(viewEntity = viewEntity, onEvent = viewModel::onEvent) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt index 52f5a49a..f1a3eb5a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt @@ -41,8 +41,7 @@ import androidx.compose.material.icons.outlined.SignalWifiStatusbarConnectedNoIn import androidx.compose.material.icons.outlined.Wifi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.BandDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureReasonDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R @@ -68,14 +67,14 @@ internal fun WifiConnectionStateDomain?.toDisplayString() = when (this) { null -> R.string.wifi_status_unprovisioned }.let { stringResource(id = it) } -internal fun AuthModeDomain?.toImageVector() = when (this) { - AuthModeDomain.OPEN -> Icons.Outlined.Wifi - AuthModeDomain.WEP, - AuthModeDomain.WPA_PSK, - AuthModeDomain.WPA2_PSK, - AuthModeDomain.WPA_WPA2_PSK, - AuthModeDomain.WPA2_ENTERPRISE, - AuthModeDomain.WPA3_PSK, +internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain?.toImageVector() = when (this) { + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN -> Icons.Outlined.Wifi + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP, + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK, + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK, + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK, + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE, + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK, null -> Icons.Outlined.SignalWifi4BarLock } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index c6f8ca13..cae7f69b 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -49,7 +49,7 @@ import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewMod import no.nordicsemi.android.kotlin.ble.core.RealServerDevice import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId @@ -233,10 +233,15 @@ class BleViewModel @Inject constructor( .let { pendingJobs.add(it) } } - private fun WifiData.toConfig(): WifiConfigDomain { + private fun WifiData.toConfig(): no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo val anyChannel = selectedChannel?.wifiInfo?.let { false } ?: true - return WifiConfigDomain(wifiInfo, state.password, !state.persistentMemory, anyChannel) + return no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain( + wifiInfo, + state.password, + !state.persistentMemory, + anyChannel + ) } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt index 61e5cb4a..f3a72f22 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt @@ -47,7 +47,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString @@ -55,7 +55,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString internal fun SelectChannelDialog( records: ScanRecordsForSsid, onDismiss: () -> Unit, - onRecordSelected: (ScanRecordDomain?) -> Unit + onRecordSelected: (no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain?) -> Unit ) { AlertDialog( onDismissRequest = { onDismiss() }, @@ -88,8 +88,8 @@ internal fun SelectChannelDialog( @Composable private fun ChannelListItem( - record: ScanRecordDomain, - onRecordSelected: (ScanRecordDomain) -> Unit + record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain, + onRecordSelected: (no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain) -> Unit ) { val wifi = record.wifiInfo diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index 0cbce9d6..4ebc8eef 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -63,13 +63,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector -import no.nordicsemi.android.wifi.provisioner.event.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioner.event.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioner.event.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioner.event.WifiSelectedEvent +import no.nordicsemi.android.wifi.provisioner.common.event.NavigateUpEvent +import no.nordicsemi.android.wifi.provisioner.common.event.OnSortOptionSelected +import no.nordicsemi.android.wifi.provisioner.common.event.WifiScannerViewEvent +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem @@ -142,7 +142,7 @@ private fun WifiList(viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerVie @Composable private fun WifiItem(records: ScanRecordsForSsid, onEvent: (WifiScannerViewEvent) -> Unit) { val wifiData = records.wifiData - val selectedScanRecord = remember { mutableStateOf(null) } + val selectedScanRecord = remember { mutableStateOf(null) } val scanRecord = selectedScanRecord.value val wifi = scanRecord?.wifiInfo diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt index a3ee699a..58d7b746 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt @@ -31,10 +31,10 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.view -import no.nordicsemi.android.wifi.provisioner.WifiDataConfiguration -import no.nordicsemi.android.wifi.provisioner.ble.domain.AuthModeDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.event.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, @@ -50,18 +50,18 @@ data class WifiScannerViewEntity( data class ScanRecordsForSsid( val wifiData: WifiData, - val items: List = emptyList(), + val items: List = emptyList(), ) { val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } } data class WifiData( val ssid: String, - val authMode: AuthModeDomain, - val channelFallback: ScanRecordDomain, //Needed for proto v1 - val selectedChannel: ScanRecordDomain? = null + val authMode: no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain, + val channelFallback: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain, //Needed for proto v1 + val selectedChannel: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain? = null ) : WifiDataConfiguration { fun isPasswordRequired(): Boolean { - return authMode != AuthModeDomain.OPEN + return authMode != no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt index 4418e859..20adcb56 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt @@ -33,14 +33,14 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.ScanRecordsForSsid import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import javax.inject.Inject class WifiAggregator @Inject constructor() { - private val records = mutableMapOf>() + private val records = mutableMapOf>() - fun addWifi(record: ScanRecordDomain): List { + fun addWifi(record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain): List { if (record.wifiInfo.authModeDomain == null) { return createResult(records) } @@ -53,7 +53,7 @@ class WifiAggregator @Inject constructor() { return createResult(records) } - private fun createResult(records: Map>): List { + private fun createResult(records: Map>): List { return records.map { ScanRecordsForSsid( WifiData(it.key, it.value.first().wifiInfo.authModeDomain!!, it.value.first()), diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index 55189586..6c6e9ba3 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -40,18 +40,18 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.android.wifi.provisioner.common.event.NavigateUpEvent +import no.nordicsemi.android.wifi.provisioner.common.event.OnSortOptionSelected import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEntity -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiSelectedEvent +import no.nordicsemi.android.wifi.provisioner.common.event.WifiScannerViewEvent +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId -import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption import javax.inject.Inject @HiltViewModel @@ -103,7 +103,7 @@ internal class WifiScannerViewModel @Inject constructor( } } - private fun navigateUp(wifiData: WifiData) { + private fun navigateUp(wifiData: WifiDataConfiguration) { viewModelScope.launch { stopScanning() navigationManager.navigateUpWithResult(WiFiAccessPointsListId, wifiData) diff --git a/feature/common/build.gradle.kts b/feature/common/build.gradle.kts index 659a8d39..5b64cc71 100644 --- a/feature/common/build.gradle.kts +++ b/feature/common/build.gradle.kts @@ -1,43 +1,12 @@ + plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") + alias(libs.plugins.nordic.library) } android { - namespace = "no.nordicsemi.android.wifi.provisioner" - compileSdk = 34 - - defaultConfig { - minSdk = 24 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } + namespace = "no.nordicsemi.android.wifi.provisioner.common" } -dependencies { - - implementation("androidx.core:core-ktx:1.10.1") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("com.google.android.material:material:1.10.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +dependencies{ + implementation(project(":lib:domain")) } \ No newline at end of file diff --git a/feature/common/src/main/AndroidManifest.xml b/feature/common/src/main/AndroidManifest.xml index a5918e68..1d26c87a 100644 --- a/feature/common/src/main/AndroidManifest.xml +++ b/feature/common/src/main/AndroidManifest.xml @@ -1,4 +1,2 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt deleted file mode 100644 index 90f1afae..00000000 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiDataConfiguration.kt +++ /dev/null @@ -1,3 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner - -interface WifiDataConfiguration \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt new file mode 100644 index 00000000..8e2513f4 --- /dev/null +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt @@ -0,0 +1,14 @@ +package no.nordicsemi.android.wifi.provisioner.common + +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain + +/** + * Common interface for the Wifi data configuration. + * + * @property ssid SSID of the network. + * @property authMode Authentication mode used for provisioning. + */ +interface WifiDataConfiguration { + val ssid: String + val authMode: AuthModeDomain +} \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt similarity index 93% rename from feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt index 5227f1a3..37fa3338 100644 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiScannerViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.event +package no.nordicsemi.android.wifi.provisioner.common.event -import no.nordicsemi.android.wifi.provisioner.WifiDataConfiguration +import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration sealed class WifiScannerViewEvent diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt similarity index 96% rename from feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt rename to feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt index c5e2e0df..2fa30aaf 100644 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/event/WifiSortOption.kt +++ b/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.event +package no.nordicsemi.android.wifi.provisioner.common.event enum class WifiSortOption { NAME, RSSI diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt similarity index 54% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt rename to feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt index 93f98062..c19dee7c 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/BandDomain.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt @@ -29,10 +29,39 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.android.wifi.provisioner.softap.view -enum class BandDomain(val id: Int) { - BAND_ANY(0), - BAND_2_4_GH(1), - BAND_5_GH(2) +import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain + +data class WifiScannerViewEntity( + val isLoading: Boolean = true, + val error: Throwable? = null, + val sortOption: WifiSortOption = WifiSortOption.RSSI, + private val items: List = emptyList() +) { + val sortedItems: List = when (sortOption) { + WifiSortOption.NAME -> items.sortedBy { it.wifiData.ssid } + WifiSortOption.RSSI -> items.sortedByDescending { it.biggestRssi } + } +} + +data class ScanRecordsForSsid( + val wifiData: WifiData, + val items: List = emptyList(), +) { + val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } +} + +data class WifiData( + override val ssid: String, + override val authMode: AuthModeDomain, + val channelFallback: ScanRecordDomain, //Needed for proto v1 + val selectedChannel: ScanRecordDomain? = null +) : WifiDataConfiguration { + fun isPasswordRequired(): Boolean { + return authMode != AuthModeDomain.OPEN + } } diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt index ace61ff3..749f3507 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt @@ -52,7 +52,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.event.WifiSortOption +import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.common.theme.R as themeR diff --git a/lib/ble/provisioner/build.gradle.kts b/lib/ble/provisioner/build.gradle.kts index 696c6aba..50a061fc 100644 --- a/lib/ble/provisioner/build.gradle.kts +++ b/lib/ble/provisioner/build.gradle.kts @@ -39,6 +39,6 @@ android { } dependencies { - implementation(project(":lib:ble:proto")) + api(project(":lib:domain")) implementation(libs.nordic.ble.ktx) } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt index f7cdb328..59b556c4 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt @@ -35,9 +35,9 @@ import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice import android.content.Context import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.internal.ResponseErrorException @@ -97,7 +97,7 @@ interface ProvisionerRepository { * @throws [ResponseErrorException] when the IoT reports result different that success * @throws [NotificationTimeoutException] when the first result is not received before timeout time */ - fun startScan(): Flow + fun startScan(): Flow /** * Stop scanning for available Wi-Fi's. Should be called after [startScan]. @@ -112,7 +112,7 @@ interface ProvisionerRepository { * @throws [ResponseErrorException] when the IoT reports result different that success * @throws [NotificationTimeoutException] when the first result is not received before timeout time */ - fun setConfig(config: WifiConfigDomain): Flow + fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow /** * Unprovision the DK - forget slected SSID, password, etc. diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt index f0c236d9..dcb333d9 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt @@ -37,9 +37,9 @@ import android.content.Context import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.toApi import no.nordicsemi.android.wifi.provisioner.ble.domain.toDomain @@ -67,7 +67,7 @@ class ProvisionerRepositoryImpl internal constructor( return status?.toDomain()!! } - override fun startScan(): Flow { + override fun startScan(): Flow { return manager?.startScan()!! .map { it.toDomain() } } @@ -76,7 +76,7 @@ class ProvisionerRepositoryImpl internal constructor( manager?.stopScan() } - override fun setConfig(config: WifiConfigDomain): Flow { + override fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow { return manager?.provision(config.toApi())!! .map { it.toDomain() } } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt index 3b69527e..1ae4f08f 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt @@ -33,7 +33,7 @@ package no.nordicsemi.android.wifi.provisioner.ble.domain data class DeviceStatusDomain( val wifiState: WifiConnectionStateDomain?, - val wifiInfo: WifiInfoDomain?, + val wifiInfo: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain?, val connectionInfo: ConnectionInfoDomain?, val scanParams: ScanParamsDomain? ) { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt index a63260a8..009f874d 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt @@ -37,16 +37,16 @@ import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo import okio.ByteString.Companion.toByteString -internal fun WifiConfigDomain.toApi(): WifiConfig { +internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain.toApi(): WifiConfig { return WifiConfig( wifi = info.toApi(), - passphrase = password?.toByteArray()?.toByteString(), + passphrase = passphrase?.toByteArray()?.toByteString(), volatileMemory = volatileMemory, anyChannel = anyChannel ) } -internal fun WifiInfoDomain.toApi(): WifiInfo { +internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain.toApi(): WifiInfo { return WifiInfo( ssid = ssid.toByteArray().toByteString(), bssid = bssid, @@ -64,14 +64,14 @@ internal fun BandDomain.toApi(): Band { } } -internal fun AuthModeDomain.toApi(): AuthMode { +internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.toApi(): AuthMode { return when (this) { - AuthModeDomain.OPEN -> AuthMode.OPEN - AuthModeDomain.WEP -> AuthMode.WEP - AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK - AuthModeDomain.WPA2_PSK -> AuthMode.WPA2_PSK - AuthModeDomain.WPA_WPA2_PSK -> AuthMode.WPA_WPA2_PSK - AuthModeDomain.WPA2_ENTERPRISE -> AuthMode.WPA2_ENTERPRISE - AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN -> AuthMode.OPEN + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP -> AuthMode.WEP + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK -> AuthMode.WPA2_PSK + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK -> AuthMode.WPA_WPA2_PSK + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE -> AuthMode.WPA2_ENTERPRISE + no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK } } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt index 26273bc2..b5719e5f 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt @@ -80,15 +80,15 @@ internal fun ConnectionState.toDomain(): WifiConnectionStateDomain { } } -internal fun AuthMode.toDomain(): AuthModeDomain { +internal fun AuthMode.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain { return when (this) { - AuthMode.OPEN -> AuthModeDomain.OPEN - AuthMode.WEP -> AuthModeDomain.WEP - AuthMode.WPA_PSK -> AuthModeDomain.WPA_PSK - AuthMode.WPA2_PSK -> AuthModeDomain.WPA2_PSK - AuthMode.WPA_WPA2_PSK -> AuthModeDomain.WPA_WPA2_PSK - AuthMode.WPA2_ENTERPRISE -> AuthModeDomain.WPA2_ENTERPRISE - AuthMode.WPA3_PSK -> AuthModeDomain.WPA3_PSK + AuthMode.OPEN -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN + AuthMode.WEP -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP + AuthMode.WPA_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK + AuthMode.WPA2_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK + AuthMode.WPA_WPA2_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK + AuthMode.WPA2_ENTERPRISE -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE + AuthMode.WPA3_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK } } @@ -110,8 +110,8 @@ internal fun ConnectionFailureReason.toDomain(): WifiConnectionFailureReasonDoma } } -internal fun WifiInfo.toDomain(): WifiInfoDomain { - return WifiInfoDomain( +internal fun WifiInfo.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain { + return no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain( ssid.utf8(), bssid, band?.toDomain(), @@ -120,9 +120,9 @@ internal fun WifiInfo.toDomain(): WifiInfoDomain { ) } -internal fun ScanRecord.toDomain(): ScanRecordDomain { +internal fun ScanRecord.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain { Log.d(TAG, "mapper: $this") - return ScanRecordDomain(rssi, wifi!!.toDomain()) + return no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain(rssi, wifi!!.toDomain()) } internal fun ByteString.toIp(): String { diff --git a/lib/domain/.gitignore b/lib/domain/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/lib/domain/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/lib/domain/build.gradle.kts b/lib/domain/build.gradle.kts new file mode 100644 index 00000000..b0ca5924 --- /dev/null +++ b/lib/domain/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("java-library") + id("org.jetbrains.kotlin.jvm") +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/AuthModeDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/AuthModeDomain.kt index 8ef63ba1..3a7bf8a6 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/AuthModeDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/AuthModeDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain enum class AuthModeDomain(val id: Int) { OPEN(0), diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt similarity index 95% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt index 84006df2..7bbe3943 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/BandDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt @@ -29,10 +29,10 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.softap.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain enum class BandDomain(val id: Int) { - BAND_UNSPECIFIED(0), + BAND_ANY(0), BAND_2_4_GH(1), BAND_5_GH(2), BAND_6_GH(3) diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanRecordDomain.kt similarity index 94% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanRecordDomain.kt index 8407c375..f129b156 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanRecordDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanRecordDomain.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain data class ScanRecordDomain( val rssi: Int?, - val wifiInfo: WifiInfoDomain + val wifiInfo: WifiInfoDomain? ) diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt similarity index 95% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt index 8508dafc..2e104348 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain data class WifiConfigDomain( val info: WifiInfoDomain, - val password: String?, + val passphrase: String?, val volatileMemory: Boolean, val anyChannel: Boolean ) diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt similarity index 92% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt index 757dea06..36c34f79 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiInfoDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt @@ -29,20 +29,17 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain -import okio.ByteString data class WifiInfoDomain( val ssid: String, - internal val bssid: ByteString, - val band: BandDomain?, + internal val bssid: String, + val band: BandDomain, val channel: Int, val authModeDomain: AuthModeDomain? ) { - val macAddress: String = bssid.toByteArray().joinToString(":") { "%02x".format(it).uppercase() } - } diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index bbaf85f2..47deec62 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -12,6 +12,7 @@ android { } dependencies { + api(project(":lib:domain")) implementation(libs.retrofit.core) implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.converter.scalars) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index e75dfbe2..0d977fc8 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -15,9 +15,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.withContext -import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import javax.inject.Inject /** diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt deleted file mode 100644 index db55deda..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/AuthModeDomain.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.domain - -enum class AuthModeDomain(val id: Int) { - OPEN(0), - WEP(1), - WPA_PSK(2), - WPA2_PSK(3), - WPA_WPA2_PSK(4), - WPA2_ENTERPRISE(5), - WPA3_PSK(6) -} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt deleted file mode 100644 index 7a9beece..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanRecordDomain.kt +++ /dev/null @@ -1,6 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.domain - -data class ScanRecordDomain( - val infoDomain: WifiInfoDomain?, - val rssi: Int -) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt index 07020d84..595643bb 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt @@ -1,5 +1,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.domain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain + data class ScanResultsDomain( val results : List ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index 6d4f4a63..b5999dce 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -6,6 +6,11 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain internal fun AuthModeDomain.toApi() = when(this) { AuthModeDomain.OPEN -> AuthMode.OPEN @@ -18,29 +23,30 @@ internal fun AuthModeDomain.toApi() = when(this) { } internal fun BandDomain.toApi() = when(this) { - BandDomain.BAND_UNSPECIFIED -> Band.BAND_UNSPECIFIED + BandDomain.BAND_ANY -> Band.BAND_UNSPECIFIED BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GHZ BandDomain.BAND_5_GH -> Band.BAND_5_GHZ BandDomain.BAND_6_GH -> Band.BAND_6_GHZ } internal fun WifiConfigDomain.toApi() = WifiConfig( - info = wifiInfoDomain?.toApi(), - passphrase = passphrase + info = info.toApi(), + passphrase = passphrase ?: "" ) internal fun WifiInfoDomain.toApi() = WifiInfo( ssid = ssid, - band = bandDomain.toApi(), + band = band.toApi(), channel = channel, authMode = authModeDomain.toApi() ) internal fun ScanRecordDomain.toApi() = ScanRecord( - wifi = infoDomain?.toApi(), - rssi = rssi + wifi = wifiInfo?.toApi(), + rssi = rssi ?: 0 ) +@Suppress("unused") internal fun ScanResultsDomain.toApi() = ScanResults( results = results.map { it.toApi() } ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt index 0a2f7987..269f78b8 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -6,6 +6,11 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain internal fun AuthMode.toDomain() = when(this) { AuthMode.OPEN -> AuthModeDomain.OPEN @@ -18,7 +23,7 @@ internal fun AuthMode.toDomain() = when(this) { } internal fun Band.toDomain() = when(this) { - Band.BAND_UNSPECIFIED -> BandDomain.BAND_UNSPECIFIED + Band.BAND_UNSPECIFIED -> BandDomain.BAND_ANY Band.BAND_2_4_GHZ -> BandDomain.BAND_2_4_GH Band.BAND_5_GHZ -> BandDomain.BAND_5_GH Band.BAND_6_GHZ -> BandDomain.BAND_6_GH @@ -26,18 +31,22 @@ internal fun Band.toDomain() = when(this) { internal fun WifiInfo.toDomain() = WifiInfoDomain( ssid = ssid, - bandDomain = band.toDomain(), + band = band.toDomain(), channel = channel, - authModeDomain = authMode.toDomain() + authModeDomain = authMode.toDomain(), + bssid = "" ) +@Suppress("unused") internal fun WifiConfig.toDomain() = WifiConfigDomain( - wifiInfoDomain = info?.toDomain(), - passphrase = passphrase + info = info?.toDomain()!!, + passphrase = passphrase, + anyChannel = false, + volatileMemory = false ) internal fun ScanRecord.toDomain() = ScanRecordDomain( - infoDomain = wifi?.toDomain(), + wifiInfo = wifi?.toDomain(), rssi = rssi ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt deleted file mode 100644 index 0e928cd1..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.domain - -data class WifiConfigDomain( - val wifiInfoDomain: WifiInfoDomain?, - val passphrase: String -) \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt deleted file mode 100644 index 63bb2474..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiInfoDomain.kt +++ /dev/null @@ -1,8 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.domain - -data class WifiInfoDomain( - val ssid: String, - val bandDomain: BandDomain, - val channel: Int, - val authModeDomain: AuthModeDomain -) diff --git a/settings.gradle.kts b/settings.gradle.kts index 7257d56e..6828b692 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -59,9 +59,9 @@ include(":feature:ble") include(":feature:softap") include(":feature:ui") include(":feature:common") -include(":lib:ble:proto") include(":lib:ble:provisioner") include(":lib:softap:provisioner") +include(":lib:domain") //if (file('../Android-Common-Libraries').exists()) { // includeBuild('../Android-Common-Libraries') From 0c5f2202b14296fe83209bce3cad743def99d93e Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 19 Apr 2024 14:28:55 +0200 Subject: [PATCH 044/101] Includes the updated proto file to match the BLE schema and more improvements. --- app/build.gradle.kts | 3 +- feature/ble/build.gradle.kts | 1 + .../ProvisionerResourceRepository.kt | 6 +- .../provisioner/ble/sections/StatusSection.kt | 1 + .../provisioner/ble/sections/WifiSection.kt | 8 +- .../provisioner/ble/view/BleDestination.kt | 2 +- .../wifi/provisioner/ble/view/UiMapper.kt | 21 -- .../provisioner/ble/viewmodel/BleViewModel.kt | 12 +- .../ble/wifi/view/SelectChannelDialog.kt | 18 +- .../wifi/view/WiFiAccessPointListsScreen.kt | 16 +- .../ble/wifi/view/WifiScannerViewEntity.kt | 16 +- .../ble/wifi/viewmodel/WifiAggregator.kt | 14 +- .../wifi/viewmodel/WifiScannerViewModel.kt | 12 +- feature/common/build.gradle.kts | 8 +- .../provisioner/ExampleInstrumentedTest.kt | 24 -- .../common/WifiDataConfiguration.kt | 3 +- .../common/event/WifiScannerViewEvent.kt | 4 +- .../common/event/WifiSortOption.kt | 2 +- .../wifi/provisioner/ExampleUnitTest.kt | 17 -- .../softap/view/WifiAccessPointsScreen.kt | 237 ++++++++++++++++ .../softap/view/WifiScannerViewEntity.kt | 4 +- .../softap/src/main/res/values/strings.xml | 12 + feature/ui/build.gradle.kts | 1 + .../wifi/provisioner/ui/mapping/UiMapper.kt | 28 ++ .../wifi/provisioner/ui/view/WifiSortView.kt | 2 +- feature/ui/src/main/res/values/strings.xml | 4 + lib/ble/proto/.gitignore | 1 - lib/ble/proto/module-rules.pro | 21 -- lib/ble/proto/src/main/AndroidManifest.xml | 33 --- lib/ble/provisioner/build.gradle.kts | 9 + .../provisioner/ble/ProvisionerRepository.kt | 6 +- .../ble/ProvisionerRepositoryImpl.kt | 6 +- .../ble/domain/ScanParamsDomain.kt | 2 + .../provisioner/ble/domain/ToApiMapper.kt | 60 ++--- .../provisioner/ble/domain/ToDomainMapper.kt | 128 ++++----- .../ble}/domain/WifiConfigDomain.kt | 6 +- .../src/main/proto/common.proto | 252 +++++++++--------- .../src/main/proto/request.proto | 68 ++--- .../src/main/proto/response.proto | 88 +++--- .../src/main/proto/result.proto | 84 +++--- .../src/main/proto/version.proto | 20 +- lib/domain/build.gradle.kts | 23 +- .../wifi/provisioner/domain/BandDomain.kt | 3 +- .../wifi/provisioner/domain/WifiInfoDomain.kt | 5 +- lib/softap/provisioner/build.gradle.kts | 7 +- .../wifi/provisioner/softap/SoftApManager.kt | 2 +- .../provisioner/softap/domain/ToApiMapper.kt | 17 +- .../softap/domain/ToDomainMapper.kt | 29 +- .../softap/domain/WifiConfigDomain.kt} | 17 +- .../provisioner/src/main/proto/common.proto | 22 +- 50 files changed, 771 insertions(+), 614 deletions(-) delete mode 100644 feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt rename feature/common/src/main/java/no/nordicsemi/{android => kotlin}/wifi/provisioner/common/WifiDataConfiguration.kt (86%) rename feature/common/src/main/java/no/nordicsemi/{android => kotlin}/wifi/provisioner/common/event/WifiScannerViewEvent.kt (93%) rename feature/common/src/main/java/no/nordicsemi/{android => kotlin}/wifi/provisioner/common/event/WifiSortOption.kt (96%) delete mode 100644 feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt create mode 100644 feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt delete mode 100644 lib/ble/proto/.gitignore delete mode 100644 lib/ble/proto/module-rules.pro delete mode 100644 lib/ble/proto/src/main/AndroidManifest.xml rename lib/{domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner => ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/domain/WifiConfigDomain.kt (91%) rename lib/ble/{proto => provisioner}/src/main/proto/common.proto (96%) rename lib/ble/{proto => provisioner}/src/main/proto/request.proto (97%) rename lib/ble/{proto => provisioner}/src/main/proto/response.proto (96%) rename lib/ble/{proto => provisioner}/src/main/proto/result.proto (96%) rename lib/ble/{proto => provisioner}/src/main/proto/version.proto (96%) rename lib/{ble/proto/build.gradle.kts => softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt} (87%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4a7bc6b1..d0bb40e8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,10 +42,11 @@ android { } dependencies { - implementation(project(":lib:ble:provisioner")) implementation(project(":feature:ble")) implementation(project(":feature:softap")) implementation(project(":feature:common")) + implementation(project(":lib:ble:provisioner")) + implementation(project(":lib:softap:provisioner")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 57e331df..405068de 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(project(":feature:common")) implementation(project(":feature:ui")) implementation(project(":lib:ble:provisioner")) + implementation(project(":lib:domain")) implementation(libs.androidx.lifecycle.runtime.compose) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt index 60a7dbf9..f58a61b9 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt @@ -42,7 +42,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.Resource import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus @@ -62,7 +62,7 @@ class ProvisionerResourceRepository( return runTask { repository.getStatus() } } - fun startScan(): Flow> { + fun startScan(): Flow> { return repository.startScan() .map { Resource.createSuccess(it) } .onStart { emit(Resource.createLoading()) } @@ -76,7 +76,7 @@ class ProvisionerResourceRepository( repository.stopScan() } - fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow> { + fun setConfig(config: WifiConfigDomain): Flow> { return repository.setConfig(config) .map { Resource.createSuccess(it) } .onStart { emit(Resource.createLoading()) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt index 5329bc00..98712035 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt @@ -52,6 +52,7 @@ import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString @Composable internal fun StatusSection(status: Resource) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index 4be83c06..af33632e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -36,11 +36,11 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector @Composable internal fun WifiSection( @@ -63,10 +63,10 @@ internal fun WifiSection( } @Composable -private fun getDescription(record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain): String { +private fun getDescription(record: ScanRecordDomain): String { return StringBuilder() - .append(record.wifiInfo.ssid) + .append(record.wifiInfo?.ssid) .appendLine() - .append(stringResource(id = R.string.channel, record.wifiInfo.channel.toString())) + .append(stringResource(id = R.string.channel, record.wifiInfo?.channel.toString())) .toString() } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index d8c62e38..68d2a2cb 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -37,7 +37,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt index f1a3eb5a..7eefbb38 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt @@ -36,12 +36,9 @@ import androidx.compose.material.icons.filled.SignalWifi4Bar import androidx.compose.material.icons.filled.SignalWifiOff import androidx.compose.material.icons.filled.SignalWifiStatusbarConnectedNoInternet4 import androidx.compose.material.icons.filled.WifiFind -import androidx.compose.material.icons.outlined.SignalWifi4BarLock import androidx.compose.material.icons.outlined.SignalWifiStatusbarConnectedNoInternet4 -import androidx.compose.material.icons.outlined.Wifi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureReasonDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R @@ -67,24 +64,6 @@ internal fun WifiConnectionStateDomain?.toDisplayString() = when (this) { null -> R.string.wifi_status_unprovisioned }.let { stringResource(id = it) } -internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain?.toImageVector() = when (this) { - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN -> Icons.Outlined.Wifi - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP, - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK, - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK, - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK, - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE, - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK, - null -> Icons.Outlined.SignalWifi4BarLock -} - -@Composable -internal fun BandDomain.toDisplayString() = when (this) { - BandDomain.BAND_ANY -> R.string.any - BandDomain.BAND_2_4_GH -> R.string.band_2_4 - BandDomain.BAND_5_GH -> R.string.band_5 -}.let { stringResource(id = it) } - @Composable internal fun WifiConnectionFailureReasonDomain.toDisplayString() = when (this) { WifiConnectionFailureReasonDomain.AUTH_ERROR -> R.string.error_auth diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index cae7f69b..27947374 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -49,12 +49,12 @@ import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewMod import no.nordicsemi.android.kotlin.ble.core.RealServerDevice import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch +import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId -import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnHidePasswordDialog import no.nordicsemi.android.wifi.provisioner.ble.view.OnPasswordSelectedEvent @@ -68,7 +68,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEv import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData -import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import javax.inject.Inject @HiltViewModel @@ -93,7 +93,7 @@ class BleViewModel @Inject constructor( navigationManager.resultFrom(WiFiAccessPointsListId) .mapNotNull { it as? NavigationResult.Success } - .onEach { installWifi(it.value) } + .onEach { installWifi(it.value as WifiData) } .launchIn(viewModelScope) } @@ -233,11 +233,11 @@ class BleViewModel @Inject constructor( .let { pendingJobs.add(it) } } - private fun WifiData.toConfig(): no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain { + private fun WifiData.toConfig(): WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo val anyChannel = selectedChannel?.wifiInfo?.let { false } ?: true - return no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain( + return WifiConfigDomain( wifiInfo, state.password, !state.persistentMemory, diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt index f3a72f22..f14afd3e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt @@ -47,15 +47,15 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @Composable internal fun SelectChannelDialog( records: ScanRecordsForSsid, onDismiss: () -> Unit, - onRecordSelected: (no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain?) -> Unit + onRecordSelected: (ScanRecordDomain?) -> Unit ) { AlertDialog( onDismissRequest = { onDismiss() }, @@ -88,8 +88,8 @@ internal fun SelectChannelDialog( @Composable private fun ChannelListItem( - record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain, - onRecordSelected: (no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain) -> Unit + record: ScanRecordDomain, + onRecordSelected: (ScanRecordDomain) -> Unit ) { val wifi = record.wifiInfo @@ -101,18 +101,20 @@ private fun ChannelListItem( ) { Column(modifier = Modifier.weight(1f)) { Text( - text = stringResource(id = R.string.channel, wifi.channel.toString()), + text = stringResource(id = R.string.channel, wifi?.channel.toString()), style = MaterialTheme.typography.labelLarge ) - if (wifi.macAddress.isNotEmpty()) { + wifi?.macAddress?.takeIf { + it.isNotEmpty() + }?.let { Text( text = stringResource(id = R.string.bssid, wifi.macAddress), style = MaterialTheme.typography.bodySmall ) } - wifi.band?.toDisplayString()?.let { + wifi?.band?.toDisplayString()?.let { Text( text = stringResource(id = R.string.band, it), style = MaterialTheme.typography.bodySmall diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index 4ebc8eef..cbffdd0a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -63,17 +63,17 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes -import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector -import no.nordicsemi.android.wifi.provisioner.common.event.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioner.common.event.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioner.common.event.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortView +import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -142,7 +142,7 @@ private fun WifiList(viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerVie @Composable private fun WifiItem(records: ScanRecordsForSsid, onEvent: (WifiScannerViewEvent) -> Unit) { val wifiData = records.wifiData - val selectedScanRecord = remember { mutableStateOf(null) } + val selectedScanRecord = remember { mutableStateOf(null) } val scanRecord = selectedScanRecord.value val wifi = scanRecord?.wifiInfo diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt index 58d7b746..766985ae 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt @@ -31,10 +31,10 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.view -import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, @@ -50,18 +50,18 @@ data class WifiScannerViewEntity( data class ScanRecordsForSsid( val wifiData: WifiData, - val items: List = emptyList(), + val items: List = emptyList(), ) { val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } } data class WifiData( - val ssid: String, - val authMode: no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain, - val channelFallback: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain, //Needed for proto v1 - val selectedChannel: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain? = null + override val ssid: String, + override val authMode: AuthModeDomain, + val channelFallback: ScanRecordDomain, //Needed for proto v1 + val selectedChannel: ScanRecordDomain? = null ) : WifiDataConfiguration { fun isPasswordRequired(): Boolean { - return authMode != no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN + return authMode != AuthModeDomain.OPEN } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt index 20adcb56..18c0b59b 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt @@ -38,25 +38,25 @@ import javax.inject.Inject class WifiAggregator @Inject constructor() { - private val records = mutableMapOf>() + private val records = mutableMapOf>() - fun addWifi(record: no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain): List { - if (record.wifiInfo.authModeDomain == null) { + fun addWifi(record: ScanRecordDomain): List { + if (record.wifiInfo?.authModeDomain == null) { return createResult(records) } - val ssid = record.wifiInfo.ssid + val ssid = record.wifiInfo!!.ssid val ssidRecords = records[ssid]?.let { - (it + record).distinctBy { it.wifiInfo.channel }.sortedByDescending { it.rssi } + (it + record).distinctBy { it.wifiInfo?.channel }.sortedByDescending { it.rssi } } ?: listOf(record) this.records[ssid] = ssidRecords return createResult(records) } - private fun createResult(records: Map>): List { + private fun createResult(records: Map>): List { return records.map { ScanRecordsForSsid( - WifiData(it.key, it.value.first().wifiInfo.authModeDomain!!, it.value.first()), + WifiData(it.key, it.value.first().wifiInfo?.authModeDomain!!, it.value.first()), it.value ) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index 6c6e9ba3..28a373dd 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -40,18 +40,18 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioner.common.event.NavigateUpEvent -import no.nordicsemi.android.wifi.provisioner.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEntity -import no.nordicsemi.android.wifi.provisioner.common.event.WifiScannerViewEvent -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption import javax.inject.Inject @HiltViewModel diff --git a/feature/common/build.gradle.kts b/feature/common/build.gradle.kts index 5b64cc71..c8cae981 100644 --- a/feature/common/build.gradle.kts +++ b/feature/common/build.gradle.kts @@ -1,12 +1,12 @@ - plugins { alias(libs.plugins.nordic.library) + alias(libs.plugins.nordic.kotlin) } android { - namespace = "no.nordicsemi.android.wifi.provisioner.common" + namespace = "no.nordicsemi.wifi.provisioner.common" } -dependencies{ +dependencies { implementation(project(":lib:domain")) -} \ No newline at end of file +} diff --git a/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt b/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt deleted file mode 100644 index 25b90b6a..00000000 --- a/feature/common/src/androidTest/java/no/nordicsemi/android/wifi/provisioner/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("no.nordicsemi.android.wifi.provisioner.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt similarity index 86% rename from feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt index 8e2513f4..94fbbb9b 100644 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/WifiDataConfiguration.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt @@ -1,7 +1,8 @@ -package no.nordicsemi.android.wifi.provisioner.common +package no.nordicsemi.kotlin.wifi.provisioner.common import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain + /** * Common interface for the Wifi data configuration. * diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt similarity index 93% rename from feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt index 37fa3338..700f1968 100644 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiScannerViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.common.event +package no.nordicsemi.kotlin.wifi.provisioner.common.event -import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration sealed class WifiScannerViewEvent diff --git a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt similarity index 96% rename from feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt index 2fa30aaf..4cfbf040 100644 --- a/feature/common/src/main/java/no/nordicsemi/android/wifi/provisioner/common/event/WifiSortOption.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.common.event +package no.nordicsemi.kotlin.wifi.provisioner.common.event enum class WifiSortOption { NAME, RSSI diff --git a/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt b/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt deleted file mode 100644 index b6e89404..00000000 --- a/feature/common/src/test/java/no/nordicsemi/android/wifi/provisioner/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt new file mode 100644 index 00000000..1034bbe6 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.view + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.outlined.WarningAmber +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.common.theme.view.getWiFiRes +import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem +import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortView +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun WiFiAccessPointsScreen( + viewEntity: WifiScannerViewEntity, + onEvent: (WifiScannerViewEvent) -> Unit +) { + + Column(horizontalAlignment = Alignment.CenterHorizontally) { + NordicAppBar( + text = stringResource(id = R.string.wifi_access_points_title), + onNavigationButtonClick = { onEvent(NavigateUpEvent) } + ) + + if (viewEntity.isLoading) { + LoadingItem() + } else if (viewEntity.error != null) { + ErrorItem(viewEntity.error) + } else { + WifiList(viewEntity, onEvent) + } + } +} + +@Composable +private fun LoadingItem() { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(16.dp) + ) { + repeat(6) { + item { WifiLoadingItem() } + } + } +} + +@Composable +private fun ErrorItem(error: Throwable) { + Box(modifier = Modifier.padding(16.dp)) { + ErrorDataItem( + imageVector = Icons.Outlined.WarningAmber, + title = stringResource(id = R.string.wifi_scanning), + error = error + ) + } +} + +@Composable +private fun WifiList(viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerViewEvent) -> Unit) { + Column { + WifiSortView(viewEntity.sortOption) { + onEvent(OnSortOptionSelected(it)) + } + + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + contentPadding = PaddingValues(8.dp) + ) { + viewEntity.sortedItems.forEach { + item { WifiItem(records = it, onEvent = onEvent) } + } + } + } +} + +@Composable +private fun WifiItem(records: ScanRecordsForSsid, onEvent: (WifiScannerViewEvent) -> Unit) { + val wifiData = records.wifiData + val selectedScanRecord = remember { mutableStateOf(null) } + val scanRecord = selectedScanRecord.value + val wifi = scanRecord?.wifiInfo + + val showSelectChannelDialog = rememberSaveable { mutableStateOf(false) } + + if (showSelectChannelDialog.value) { + /*SelectChannelDialog( + records = records, + onDismiss = { showSelectChannelDialog.value = false } + ) { + selectedScanRecord.value = it + showSelectChannelDialog.value = false + }*/ + } + + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(10.dp)) + .clickable { onEvent(WifiSelectedEvent(wifiData.copy(selectedChannel = scanRecord))) } + .padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = wifiData.authMode.toImageVector(), + contentDescription = stringResource(id = R.string.cd_wifi_icon), + tint = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .background( + color = MaterialTheme.colorScheme.secondary, shape = CircleShape + ) + .padding(8.dp) + ) + + Spacer(modifier = Modifier.size(16.dp)) + + Column(modifier = Modifier.weight(1f)) { + Text( + text = wifiData.ssid, style = MaterialTheme.typography.labelLarge + ) + + if (wifi != null) { + if (wifi.macAddress.isNotEmpty()) { + Text( + text = stringResource(id = R.string.bssid, wifi.macAddress), + style = MaterialTheme.typography.bodySmall + ) + } + + if (wifi.band != null) { + Text( + text = stringResource( + id = R.string.band_and_channel, + wifi.band!!.toDisplayString(), + wifi.channel.toString() + ), + style = MaterialTheme.typography.bodySmall + ) + } else { + Text( + text = stringResource(id = R.string.channel, wifi.channel.toString()), + style = MaterialTheme.typography.bodySmall + ) + } + } else { + Text( + text = stringResource(id = R.string.channel, stringResource(id = R.string.any)), + style = MaterialTheme.typography.bodySmall + ) + } + } + + val displayRssi = scanRecord?.rssi ?: records.biggestRssi + + Row(modifier = Modifier + .clip(RoundedCornerShape(10.dp)) + .clickable { showSelectChannelDialog.value = true } + .border( + 1.dp, + MaterialTheme.colorScheme.onSurface, + RoundedCornerShape(10.dp) + ) + .padding(9.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(getWiFiRes(displayRssi), contentDescription = "") + + Icon(Icons.Default.ArrowDropDown, contentDescription = "") + } + } +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt index c19dee7c..b66a7ddb 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt @@ -31,8 +31,8 @@ package no.nordicsemi.android.wifi.provisioner.softap.view -import no.nordicsemi.android.wifi.provisioner.common.WifiDataConfiguration -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 0c61e709..c9a776d2 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -8,4 +8,16 @@ Confirm Wi-Fi Access Points Scanning error + + IPv4: %s + SSID: %s + BSSID: %s + Band: %s + Band: %s, Channel: %s + Channel: %s + 2.4 GHz + 5 GHz + Any + + Icon indicating wifi and it\'s authentication method. \ No newline at end of file diff --git a/feature/ui/build.gradle.kts b/feature/ui/build.gradle.kts index 33aa504a..072798c5 100644 --- a/feature/ui/build.gradle.kts +++ b/feature/ui/build.gradle.kts @@ -39,6 +39,7 @@ android { dependencies { implementation(project(":feature:common")) + implementation(project(":lib:domain")) implementation(libs.nordic.theme) diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt new file mode 100644 index 00000000..509beded --- /dev/null +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt @@ -0,0 +1,28 @@ +package no.nordicsemi.android.wifi.provisioner.ui.mapping + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.SignalWifi4BarLock +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain + +fun AuthModeDomain?.toImageVector() = when (this) { + AuthModeDomain.OPEN -> Icons.Outlined.Wifi + AuthModeDomain.WEP, + AuthModeDomain.WPA_PSK, + AuthModeDomain.WPA2_PSK, + AuthModeDomain.WPA_WPA2_PSK, + AuthModeDomain.WPA2_ENTERPRISE, + AuthModeDomain.WPA3_PSK, + null -> Icons.Outlined.SignalWifi4BarLock +} + +@Composable +fun BandDomain.toDisplayString() = when (this) { + BandDomain.BAND_ANY -> R.string.any + BandDomain.BAND_2_4_GH -> R.string.band_2_4 + BandDomain.BAND_5_GH -> R.string.band_5 +}.let { stringResource(id = it) } \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt index 749f3507..8f8653d1 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt @@ -52,7 +52,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.common.theme.R as themeR diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 4008f391..01666760 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -6,4 +6,8 @@ Sort by: Name RSSI + + 2.4 GHz + 5 GHz + Any \ No newline at end of file diff --git a/lib/ble/proto/.gitignore b/lib/ble/proto/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/lib/ble/proto/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/lib/ble/proto/module-rules.pro b/lib/ble/proto/module-rules.pro deleted file mode 100644 index ff59496d..00000000 --- a/lib/ble/proto/module-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/lib/ble/proto/src/main/AndroidManifest.xml b/lib/ble/proto/src/main/AndroidManifest.xml deleted file mode 100644 index d554f457..00000000 --- a/lib/ble/proto/src/main/AndroidManifest.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - \ No newline at end of file diff --git a/lib/ble/provisioner/build.gradle.kts b/lib/ble/provisioner/build.gradle.kts index 50a061fc..cce571af 100644 --- a/lib/ble/provisioner/build.gradle.kts +++ b/lib/ble/provisioner/build.gradle.kts @@ -32,6 +32,7 @@ plugins { alias(libs.plugins.nordic.library) alias(libs.plugins.nordic.kotlin) + alias(libs.plugins.wire) } android { @@ -41,4 +42,12 @@ android { dependencies { api(project(":lib:domain")) implementation(libs.nordic.ble.ktx) + implementation(libs.nordic.ble.common) + implementation(libs.nordic.uilogger) + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) } + +wire { + kotlin {} +} \ No newline at end of file diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt index 59b556c4..ccf99d6d 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt @@ -37,7 +37,7 @@ import android.content.Context import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.internal.ResponseErrorException @@ -97,7 +97,7 @@ interface ProvisionerRepository { * @throws [ResponseErrorException] when the IoT reports result different that success * @throws [NotificationTimeoutException] when the first result is not received before timeout time */ - fun startScan(): Flow + fun startScan(): Flow /** * Stop scanning for available Wi-Fi's. Should be called after [startScan]. @@ -112,7 +112,7 @@ interface ProvisionerRepository { * @throws [ResponseErrorException] when the IoT reports result different that success * @throws [NotificationTimeoutException] when the first result is not received before timeout time */ - fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow + fun setConfig(config: WifiConfigDomain): Flow /** * Unprovision the DK - forget slected SSID, password, etc. diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt index dcb333d9..4b972b1f 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt @@ -39,7 +39,7 @@ import kotlinx.coroutines.flow.map import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.toApi import no.nordicsemi.android.wifi.provisioner.ble.domain.toDomain @@ -67,7 +67,7 @@ class ProvisionerRepositoryImpl internal constructor( return status?.toDomain()!! } - override fun startScan(): Flow { + override fun startScan(): Flow { return manager?.startScan()!! .map { it.toDomain() } } @@ -76,7 +76,7 @@ class ProvisionerRepositoryImpl internal constructor( manager?.stopScan() } - override fun setConfig(config: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain): Flow { + override fun setConfig(config: WifiConfigDomain): Flow { return manager?.provision(config.toApi())!! .map { it.toDomain() } } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt index 677a708d..c71dce1e 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt @@ -31,6 +31,8 @@ package no.nordicsemi.android.wifi.provisioner.ble.domain +import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain + data class ScanParamsDomain( val band: BandDomain, val passive: Boolean, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt index 009f874d..2b52833c 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt @@ -35,43 +35,37 @@ import no.nordicsemi.android.wifi.provisioner.ble.proto.AuthMode import no.nordicsemi.android.wifi.provisioner.ble.proto.Band import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo +import no.nordicsemi.kotlin.wifi.provisioner.domain.* + import okio.ByteString.Companion.toByteString -internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain.toApi(): WifiConfig { - return WifiConfig( - wifi = info.toApi(), - passphrase = passphrase?.toByteArray()?.toByteString(), - volatileMemory = volatileMemory, - anyChannel = anyChannel - ) -} +internal fun WifiConfigDomain.toApi() = WifiConfig( + wifi = info?.toApi(), + passphrase = passphrase?.toByteArray()?.toByteString(), + volatileMemory = volatileMemory, + anyChannel = anyChannel +) -internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain.toApi(): WifiInfo { - return WifiInfo( - ssid = ssid.toByteArray().toByteString(), - bssid = bssid, - band = band?.toApi(), - channel = channel, - auth = authModeDomain?.toApi() - ) -} +internal fun WifiInfoDomain.toApi() = WifiInfo( + ssid = ssid.toByteArray().toByteString(), + bssid = bssid, + band = band?.toApi(), + channel = channel, + auth = authModeDomain?.toApi() +) -internal fun BandDomain.toApi(): Band { - return when (this) { - BandDomain.BAND_ANY -> Band.BAND_ANY - BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GH - BandDomain.BAND_5_GH -> Band.BAND_5_GH - } +internal fun BandDomain.toApi() = when (this) { + BandDomain.BAND_ANY -> Band.BAND_ANY + BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GH + BandDomain.BAND_5_GH -> Band.BAND_5_GH } -internal fun no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.toApi(): AuthMode { - return when (this) { - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN -> AuthMode.OPEN - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP -> AuthMode.WEP - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK -> AuthMode.WPA2_PSK - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK -> AuthMode.WPA_WPA2_PSK - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE -> AuthMode.WPA2_ENTERPRISE - no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK - } +internal fun AuthModeDomain.toApi(): AuthMode = when (this) { + AuthModeDomain.OPEN -> AuthMode.OPEN + AuthModeDomain.WEP -> AuthMode.WEP + AuthModeDomain.WPA_PSK -> AuthMode.WPA_PSK + AuthModeDomain.WPA2_PSK -> AuthMode.WPA2_PSK + AuthModeDomain.WPA_WPA2_PSK -> AuthMode.WPA_WPA2_PSK + AuthModeDomain.WPA2_ENTERPRISE -> AuthMode.WPA2_ENTERPRISE + AuthModeDomain.WPA3_PSK -> AuthMode.WPA3_PSK } diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt index b5719e5f..1e558443 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt @@ -31,7 +31,6 @@ package no.nordicsemi.android.wifi.provisioner.ble.domain -import android.util.Log import no.nordicsemi.android.wifi.provisioner.ble.proto.AuthMode import no.nordicsemi.android.wifi.provisioner.ble.proto.Band import no.nordicsemi.android.wifi.provisioner.ble.proto.ConnectionFailureReason @@ -41,92 +40,73 @@ import no.nordicsemi.android.wifi.provisioner.ble.proto.DeviceStatus import no.nordicsemi.android.wifi.provisioner.ble.proto.ScanParams import no.nordicsemi.android.wifi.provisioner.ble.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain import okio.ByteString -private const val TAG = "DOMAIN-MAPPER" +internal fun DeviceStatus.toDomain() = DeviceStatusDomain( + state?.toDomain(), + provisioning_info?.toDomain(), + connection_info?.toDomain(), + scan_info?.toDomain() +) -internal fun DeviceStatus.toDomain(): DeviceStatusDomain { - Log.d(TAG, "status: $this") - return DeviceStatusDomain( - state?.toDomain(), - provisioning_info?.toDomain(), - connection_info?.toDomain(), - scan_info?.toDomain() - ) -} - -internal fun ScanParams.toDomain(): ScanParamsDomain { - Log.d(TAG, "mapper: $this") - return ScanParamsDomain( - band!!.toDomain(), - passive!!, - period_ms!!, - group_channels!! - ) -} +internal fun ScanParams.toDomain() = ScanParamsDomain( + band!!.toDomain(), + passive!!, + period_ms!!, + group_channels!! +) -internal fun ConnectionInfo.toDomain(): ConnectionInfoDomain { - return ConnectionInfoDomain(ip4_addr!!.toIp()) -} +internal fun ConnectionInfo.toDomain() = + ConnectionInfoDomain(ip4_addr!!.toIp()) -internal fun ConnectionState.toDomain(): WifiConnectionStateDomain { - return when (this) { - ConnectionState.DISCONNECTED -> WifiConnectionStateDomain.DISCONNECTED - ConnectionState.AUTHENTICATION -> WifiConnectionStateDomain.AUTHENTICATION - ConnectionState.ASSOCIATION -> WifiConnectionStateDomain.ASSOCIATION - ConnectionState.OBTAINING_IP -> WifiConnectionStateDomain.OBTAINING_IP - ConnectionState.CONNECTED -> WifiConnectionStateDomain.CONNECTED - ConnectionState.CONNECTION_FAILED -> WifiConnectionStateDomain.CONNECTION_FAILED - } +internal fun ConnectionState.toDomain() = when (this) { + ConnectionState.DISCONNECTED -> WifiConnectionStateDomain.DISCONNECTED + ConnectionState.AUTHENTICATION -> WifiConnectionStateDomain.AUTHENTICATION + ConnectionState.ASSOCIATION -> WifiConnectionStateDomain.ASSOCIATION + ConnectionState.OBTAINING_IP -> WifiConnectionStateDomain.OBTAINING_IP + ConnectionState.CONNECTED -> WifiConnectionStateDomain.CONNECTED + ConnectionState.CONNECTION_FAILED -> WifiConnectionStateDomain.CONNECTION_FAILED } -internal fun AuthMode.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain { - return when (this) { - AuthMode.OPEN -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.OPEN - AuthMode.WEP -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WEP - AuthMode.WPA_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_PSK - AuthMode.WPA2_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_PSK - AuthMode.WPA_WPA2_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA_WPA2_PSK - AuthMode.WPA2_ENTERPRISE -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA2_ENTERPRISE - AuthMode.WPA3_PSK -> no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain.WPA3_PSK - } +internal fun AuthMode.toDomain() = when (this) { + AuthMode.OPEN -> AuthModeDomain.OPEN + AuthMode.WEP -> AuthModeDomain.WEP + AuthMode.WPA_PSK -> AuthModeDomain.WPA_PSK + AuthMode.WPA2_PSK -> AuthModeDomain.WPA2_PSK + AuthMode.WPA_WPA2_PSK -> AuthModeDomain.WPA_WPA2_PSK + AuthMode.WPA2_ENTERPRISE -> AuthModeDomain.WPA2_ENTERPRISE + AuthMode.WPA3_PSK -> AuthModeDomain.WPA3_PSK } -internal fun Band.toDomain(): BandDomain { - return when (this) { - Band.BAND_ANY -> BandDomain.BAND_ANY - Band.BAND_2_4_GH -> BandDomain.BAND_2_4_GH - Band.BAND_5_GH -> BandDomain.BAND_5_GH - } +internal fun Band.toDomain() = when (this) { + Band.BAND_ANY -> BandDomain.BAND_ANY + Band.BAND_2_4_GH -> BandDomain.BAND_2_4_GH + Band.BAND_5_GH -> BandDomain.BAND_5_GH } -internal fun ConnectionFailureReason.toDomain(): WifiConnectionFailureReasonDomain { - return when (this) { - ConnectionFailureReason.AUTH_ERROR -> WifiConnectionFailureReasonDomain.AUTH_ERROR - ConnectionFailureReason.NETWORK_NOT_FOUND -> WifiConnectionFailureReasonDomain.NETWORK_NOT_FOUND - ConnectionFailureReason.TIMEOUT -> WifiConnectionFailureReasonDomain.TIMEOUT - ConnectionFailureReason.FAIL_IP -> WifiConnectionFailureReasonDomain.FAIL_IP - ConnectionFailureReason.FAIL_CONN -> WifiConnectionFailureReasonDomain.FAIL_CONN - } +@Suppress("unused") +internal fun ConnectionFailureReason.toDomain() = when (this) { + ConnectionFailureReason.AUTH_ERROR -> WifiConnectionFailureReasonDomain.AUTH_ERROR + ConnectionFailureReason.NETWORK_NOT_FOUND -> WifiConnectionFailureReasonDomain.NETWORK_NOT_FOUND + ConnectionFailureReason.TIMEOUT -> WifiConnectionFailureReasonDomain.TIMEOUT + ConnectionFailureReason.FAIL_IP -> WifiConnectionFailureReasonDomain.FAIL_IP + ConnectionFailureReason.FAIL_CONN -> WifiConnectionFailureReasonDomain.FAIL_CONN } -internal fun WifiInfo.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain { - return no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain( - ssid.utf8(), - bssid, - band?.toDomain(), - channel, - auth?.toDomain() - ) -} +internal fun WifiInfo.toDomain() = WifiInfoDomain( + ssid.utf8(), + bssid, + band?.toDomain(), + channel, + auth?.toDomain() +) -internal fun ScanRecord.toDomain(): no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain { - Log.d(TAG, "mapper: $this") - return no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain(rssi, wifi!!.toDomain()) -} +internal fun ScanRecord.toDomain() = ScanRecordDomain(rssi = rssi, wifiInfo = wifi?.toDomain()) -internal fun ByteString.toIp(): String { - return toByteArray().joinToString(".") { - it.toUByte().toString() - } +internal fun ByteString.toIp() = toByteArray().joinToString(".") { + it.toUByte().toString() } diff --git a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt similarity index 91% rename from lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt rename to lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt index 2e104348..65028d5e 100644 --- a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConfigDomain.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt @@ -29,10 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.kotlin.wifi.provisioner.domain +package no.nordicsemi.android.wifi.provisioner.ble.domain + +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain data class WifiConfigDomain( - val info: WifiInfoDomain, + val info: WifiInfoDomain?, val passphrase: String?, val volatileMemory: Boolean, val anyChannel: Boolean diff --git a/lib/ble/proto/src/main/proto/common.proto b/lib/ble/provisioner/src/main/proto/common.proto similarity index 96% rename from lib/ble/proto/src/main/proto/common.proto rename to lib/ble/provisioner/src/main/proto/common.proto index 039f0a13..c02922f2 100644 --- a/lib/ble/proto/src/main/proto/common.proto +++ b/lib/ble/provisioner/src/main/proto/common.proto @@ -1,127 +1,127 @@ -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; - -// Common ENUMs - -/* The Op Code for requests. */ -enum OpCode { - // Cannot be used in request. - // In the response it means that decoding the Op Code - // in the request has failed. - RESERVED = 0; - - // Returns the device status. - // - // Request parameters: - // - none - // Response parameters: - // - DeviceStatus - GET_STATUS = 1; - - // Starts Wifi scan. - // - // Request parameters: - // - ScanParams - // Response parameters: - // - none - START_SCAN = 2; - - // Manually stops Wifi scan. - // - // Request parameters: - // - none - // Response parameters: - // - none - STOP_SCAN = 3; - - // Used to provision the Host to the given WiFi network. - // - // Request parameters: - // - WifiConfig - // Response parameters: - // - none - SET_CONFIG = 4; - - // Erases previously saved configuration. - // - // Request parameters: - // - none - // Response parameters: - // - none - FORGET_CONFIG = 5; -} - -/* Response status code. */ -enum Status { - // Returned when the request was successfully processed. - SUCCESS = 0; - // Returned when the request cannot be processed due to invalid arguments. - // For example, if the required argument is missing. - INVALID_ARGUMENT = 1; - // Returned when failed to decode the request. - INVALID_PROTO = 2; - // Returned in case of internal error. Hopefully never. - INTERNAL_ERROR = 3; -} - -/* The state of Wi-Fi station. */ -enum ConnectionState { - DISCONNECTED = 0; - AUTHENTICATION = 1; - ASSOCIATION = 2; - OBTAINING_IP = 3; - CONNECTED = 4; - CONNECTION_FAILED = 5; -} - -/* Connection failure reason. */ -enum ConnectionFailureReason { - // Authentication error. - AUTH_ERROR = 0; - // The specified network could not be find. - NETWORK_NOT_FOUND = 1; - // Timeout occurred. - TIMEOUT = 2; - // Could not obtain IP from provided provisioning information. - FAIL_IP = 3; - // Could not connect to provisioned network. - FAIL_CONN = 4; -} - -/* Wi-Fi Band. */ -enum Band { - BAND_ANY = 0; - BAND_2_4_GH = 1; - BAND_5_GH = 2; -} - -/* Wi-Fi Authentication Mode. */ -enum AuthMode { - OPEN = 0; - WEP = 1; - WPA_PSK = 2; - WPA2_PSK = 3; - WPA_WPA2_PSK = 4; - WPA2_ENTERPRISE = 5; - WPA3_PSK = 6; - // Note: More modes can be added in the future. -} - -/* Scanning parameters. */ -message ScanParams { - optional Band band = 1 [default = BAND_ANY]; - optional bool passive = 2 [default = false]; - optional uint32 period_ms = 3 [default = 0]; // 0 - no timeout - optional uint32 group_channels = 4; -} - -/* Wi-Fi details. */ -message WifiInfo { - required bytes ssid = 1; - required bytes bssid = 2; - optional Band band = 3; - required uint32 channel = 4; - optional AuthMode auth = 5; +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; + +// Common ENUMs + +/* The Op Code for requests. */ +enum OpCode { + // Cannot be used in request. + // In the response it means that decoding the Op Code + // in the request has failed. + RESERVED = 0; + + // Returns the device status. + // + // Request parameters: + // - none + // Response parameters: + // - DeviceStatus + GET_STATUS = 1; + + // Starts Wifi scan. + // + // Request parameters: + // - ScanParams + // Response parameters: + // - none + START_SCAN = 2; + + // Manually stops Wifi scan. + // + // Request parameters: + // - none + // Response parameters: + // - none + STOP_SCAN = 3; + + // Used to provision the Host to the given WiFi network. + // + // Request parameters: + // - WifiConfig + // Response parameters: + // - none + SET_CONFIG = 4; + + // Erases previously saved configuration. + // + // Request parameters: + // - none + // Response parameters: + // - none + FORGET_CONFIG = 5; +} + +/* Response status code. */ +enum Status { + // Returned when the request was successfully processed. + SUCCESS = 0; + // Returned when the request cannot be processed due to invalid arguments. + // For example, if the required argument is missing. + INVALID_ARGUMENT = 1; + // Returned when failed to decode the request. + INVALID_PROTO = 2; + // Returned in case of internal error. Hopefully never. + INTERNAL_ERROR = 3; +} + +/* The state of Wi-Fi station. */ +enum ConnectionState { + DISCONNECTED = 0; + AUTHENTICATION = 1; + ASSOCIATION = 2; + OBTAINING_IP = 3; + CONNECTED = 4; + CONNECTION_FAILED = 5; +} + +/* Connection failure reason. */ +enum ConnectionFailureReason { + // Authentication error. + AUTH_ERROR = 0; + // The specified network could not be find. + NETWORK_NOT_FOUND = 1; + // Timeout occurred. + TIMEOUT = 2; + // Could not obtain IP from provided provisioning information. + FAIL_IP = 3; + // Could not connect to provisioned network. + FAIL_CONN = 4; +} + +/* Wi-Fi Band. */ +enum Band { + BAND_ANY = 0; + BAND_2_4_GH = 1; + BAND_5_GH = 2; +} + +/* Wi-Fi Authentication Mode. */ +enum AuthMode { + OPEN = 0; + WEP = 1; + WPA_PSK = 2; + WPA2_PSK = 3; + WPA_WPA2_PSK = 4; + WPA2_ENTERPRISE = 5; + WPA3_PSK = 6; + // Note: More modes can be added in the future. +} + +/* Scanning parameters. */ +message ScanParams { + optional Band band = 1 [default = BAND_ANY]; + optional bool passive = 2 [default = false]; + optional uint32 period_ms = 3 [default = 0]; // 0 - no timeout + optional uint32 group_channels = 4; +} + +/* Wi-Fi details. */ +message WifiInfo { + required bytes ssid = 1; + required bytes bssid = 2; + optional Band band = 3; + required uint32 channel = 4; + optional AuthMode auth = 5; } \ No newline at end of file diff --git a/lib/ble/proto/src/main/proto/request.proto b/lib/ble/provisioner/src/main/proto/request.proto similarity index 97% rename from lib/ble/proto/src/main/proto/request.proto rename to lib/ble/provisioner/src/main/proto/request.proto index 6d0604d6..e654e8aa 100644 --- a/lib/ble/proto/src/main/proto/request.proto +++ b/lib/ble/provisioner/src/main/proto/request.proto @@ -1,34 +1,34 @@ -syntax = "proto2"; - -import "common.proto"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; - -// Requests - -/* Wi-Fi provisioning configuration for SET_CONFIG request. */ -message WifiConfig { - optional WifiInfo wifi = 1; - optional bytes passphrase = 2; // Default: empty string - // Should the Wi-Fi config be kept only in RAM and be removed after device reboot. - optional bool volatileMemory = 3; // Default: false - // When this flag is set to true, the WifiInfo parameters other than SSID should be - // ignored. - optional bool anyChannel = 4; -} - -/* The request type, sent to the device. */ -message Request { - // The op_code has to be optional, as new op codes may be added in the future. - // They would fail to be decoded in earlier versions, causing am error. - // With the optional modifier, they will be decoded as null. - optional OpCode op_code = 1; - - // Parameters: - - // The parameter for START_SCAN request. - optional ScanParams scan_params = 10; - // The parameter for SET_CONFIG request. - optional WifiConfig config = 11; -} +syntax = "proto2"; + +import "common.proto"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; + +// Requests + +/* Wi-Fi provisioning configuration for SET_CONFIG request. */ +message WifiConfig { + optional WifiInfo wifi = 1; + optional bytes passphrase = 2; // Default: empty string + // Should the Wi-Fi config be kept only in RAM and be removed after device reboot. + optional bool volatileMemory = 3; // Default: false + // When this flag is set to true, the WifiInfo parameters other than SSID should be + // ignored. + optional bool anyChannel = 4; +} + +/* The request type, sent to the device. */ +message Request { + // The op_code has to be optional, as new op codes may be added in the future. + // They would fail to be decoded in earlier versions, causing am error. + // With the optional modifier, they will be decoded as null. + optional OpCode op_code = 1; + + // Parameters: + + // The parameter for START_SCAN request. + optional ScanParams scan_params = 10; + // The parameter for SET_CONFIG request. + optional WifiConfig config = 11; +} diff --git a/lib/ble/proto/src/main/proto/response.proto b/lib/ble/provisioner/src/main/proto/response.proto similarity index 96% rename from lib/ble/proto/src/main/proto/response.proto rename to lib/ble/provisioner/src/main/proto/response.proto index 8d16f0fa..3bdbf738 100644 --- a/lib/ble/proto/src/main/proto/response.proto +++ b/lib/ble/provisioner/src/main/proto/response.proto @@ -1,44 +1,44 @@ -syntax = "proto2"; - -import "common.proto"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; - -// Responses - -/* Information about the Wi-Fi connected state. */ -message ConnectionInfo { - optional bytes ip4_addr = 1; -} - -/* Response payload for GET_STATUS request. */ -message DeviceStatus { - // The current state of the Wifi connection. - optional ConnectionState state = 1; - - // Parameters: - - // The network information if provisioned to a network. - // This can be set even if connection failed. - optional WifiInfo provisioning_info = 10; - // The connection info is set when the device is connected - // to the network and received the IP. - optional ConnectionInfo connection_info = 11; - // Set if the device is scanning. - // The period_ms contains remaining scanning period. - optional ScanParams scan_info = 12; -} - -/* A response type which is sent back from the device. */ -message Response { - // Request op code. - optional OpCode request_op_code = 1; - // Status of the operation. - optional Status status = 2; - - // Parameters: - - // The device status is set as a response to GET_STATUS. - optional DeviceStatus device_status = 10; -} +syntax = "proto2"; + +import "common.proto"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; + +// Responses + +/* Information about the Wi-Fi connected state. */ +message ConnectionInfo { + optional bytes ip4_addr = 1; +} + +/* Response payload for GET_STATUS request. */ +message DeviceStatus { + // The current state of the Wifi connection. + optional ConnectionState state = 1; + + // Parameters: + + // The network information if provisioned to a network. + // This can be set even if connection failed. + optional WifiInfo provisioning_info = 10; + // The connection info is set when the device is connected + // to the network and received the IP. + optional ConnectionInfo connection_info = 11; + // Set if the device is scanning. + // The period_ms contains remaining scanning period. + optional ScanParams scan_info = 12; +} + +/* A response type which is sent back from the device. */ +message Response { + // Request op code. + optional OpCode request_op_code = 1; + // Status of the operation. + optional Status status = 2; + + // Parameters: + + // The device status is set as a response to GET_STATUS. + optional DeviceStatus device_status = 10; +} diff --git a/lib/ble/proto/src/main/proto/result.proto b/lib/ble/provisioner/src/main/proto/result.proto similarity index 96% rename from lib/ble/proto/src/main/proto/result.proto rename to lib/ble/provisioner/src/main/proto/result.proto index e97b1952..d12fb75a 100644 --- a/lib/ble/proto/src/main/proto/result.proto +++ b/lib/ble/provisioner/src/main/proto/result.proto @@ -1,43 +1,43 @@ -syntax = "proto2"; - -import "common.proto"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; - -// States are sent over Data Out characteristic - -/* Single Wi-Fi scan result. */ -message ScanRecord { - optional WifiInfo wifi = 1; - optional int32 rssi = 2; -} - -/* - This type is returned by the Data Out characteristic using notifications. - Scan records are returned when WiFi scanning is enabled. - WiFi state is notified whenever connection state changes, or during provisioning. - */ -message Result { - optional ScanRecord scan_record = 1; - optional ConnectionState state = 2; - // The failure reason is set when the state is CONNECTION_FAILED. - optional ConnectionFailureReason reason = 3; -} - -/* -message Test { - message InnerTest { - required uint32 req_uint32 = 1; - optional uint32 opt_uint32 = 2; - } - required InnerTest req_inner_test = 1; - optional InnerTest opt_inner_test = 2; - optional AuthMode auto_mode = 3; - oneof either { - bool null = 4; - AuthMode am = 5; - InnerTest it = 6; - } -} +syntax = "proto2"; + +import "common.proto"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; + +// States are sent over Data Out characteristic + +/* Single Wi-Fi scan result. */ +message ScanRecord { + optional WifiInfo wifi = 1; + optional int32 rssi = 2; +} + +/* + This type is returned by the Data Out characteristic using notifications. + Scan records are returned when WiFi scanning is enabled. + WiFi state is notified whenever connection state changes, or during provisioning. + */ +message Result { + optional ScanRecord scan_record = 1; + optional ConnectionState state = 2; + // The failure reason is set when the state is CONNECTION_FAILED. + optional ConnectionFailureReason reason = 3; +} + +/* +message Test { + message InnerTest { + required uint32 req_uint32 = 1; + optional uint32 opt_uint32 = 2; + } + required InnerTest req_inner_test = 1; + optional InnerTest opt_inner_test = 2; + optional AuthMode auto_mode = 3; + oneof either { + bool null = 4; + AuthMode am = 5; + InnerTest it = 6; + } +} */ \ No newline at end of file diff --git a/lib/ble/proto/src/main/proto/version.proto b/lib/ble/provisioner/src/main/proto/version.proto similarity index 96% rename from lib/ble/proto/src/main/proto/version.proto rename to lib/ble/provisioner/src/main/proto/version.proto index 7e5e96f7..85beae1c 100644 --- a/lib/ble/proto/src/main/proto/version.proto +++ b/lib/ble/provisioner/src/main/proto/version.proto @@ -1,10 +1,10 @@ -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; - -/* Response payload for returned from Version characteristic. */ -message Info { - // The fw version as integer. - required uint32 version = 1; -} +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "no.nordicsemi.android.wifi.provisioner.ble.proto"; + +/* Response payload for returned from Version characteristic. */ +message Info { + // The fw version as integer. + required uint32 version = 1; +} diff --git a/lib/domain/build.gradle.kts b/lib/domain/build.gradle.kts index b0ca5924..4da6f641 100644 --- a/lib/domain/build.gradle.kts +++ b/lib/domain/build.gradle.kts @@ -1,9 +1,22 @@ plugins { - id("java-library") - id("org.jetbrains.kotlin.jvm") + alias(libs.plugins.nordic.library) + alias(libs.plugins.nordic.kotlin) + alias(libs.plugins.wire) } -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 +android { + namespace = "no.nordicsemi.wifi.provisioner.domain" +} + +dependencies{ + implementation(libs.androidx.core.ktx) + implementation(libs.nordic.ble.common) + implementation(libs.nordic.ble.ktx) + implementation(libs.nordic.uilogger) + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) +} + +wire { + kotlin {} } \ No newline at end of file diff --git a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt index 7bbe3943..dd498352 100644 --- a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt @@ -34,6 +34,5 @@ package no.nordicsemi.kotlin.wifi.provisioner.domain enum class BandDomain(val id: Int) { BAND_ANY(0), BAND_2_4_GH(1), - BAND_5_GH(2), - BAND_6_GH(3) + BAND_5_GH(2) } \ No newline at end of file diff --git a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt index 36c34f79..0b080577 100644 --- a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiInfoDomain.kt @@ -31,11 +31,12 @@ package no.nordicsemi.kotlin.wifi.provisioner.domain +import okio.ByteString data class WifiInfoDomain( val ssid: String, - internal val bssid: String, - val band: BandDomain, + val bssid: ByteString, + val band: BandDomain?, val channel: Int, val authModeDomain: AuthModeDomain? ) { diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 47deec62..89fea979 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -4,9 +4,6 @@ plugins { alias(libs.plugins.wire) } -wire { - kotlin {} -} android { namespace = "no.nordicsemi.android.wifi.provisioner.softap" } @@ -20,4 +17,8 @@ dependencies { implementation(libs.okhttp.logging) implementation("com.squareup.retrofit2:converter-wire:2.11.0") implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") +} + +wire { + kotlin {} } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 0d977fc8..e75dfbe2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -15,9 +15,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.withContext +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import javax.inject.Inject /** diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt index b5999dce..fecb97b4 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt @@ -9,8 +9,8 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain +import okio.ByteString.Companion.toByteString internal fun AuthModeDomain.toApi() = when(this) { AuthModeDomain.OPEN -> AuthMode.OPEN @@ -23,22 +23,23 @@ internal fun AuthModeDomain.toApi() = when(this) { } internal fun BandDomain.toApi() = when(this) { - BandDomain.BAND_ANY -> Band.BAND_UNSPECIFIED + BandDomain.BAND_ANY -> Band.BAND_ANY BandDomain.BAND_2_4_GH -> Band.BAND_2_4_GHZ BandDomain.BAND_5_GH -> Band.BAND_5_GHZ - BandDomain.BAND_6_GH -> Band.BAND_6_GHZ } +@Suppress("unused") internal fun WifiConfigDomain.toApi() = WifiConfig( - info = info.toApi(), - passphrase = passphrase ?: "" + wifi = info?.toApi(), + passphrase = passphrase?.toByteArray()?.toByteString(), ) internal fun WifiInfoDomain.toApi() = WifiInfo( - ssid = ssid, - band = band.toApi(), + ssid = ssid.toByteArray().toByteString(), + bssid = bssid, + band = band?.toApi(), channel = channel, - authMode = authModeDomain.toApi() + auth = authModeDomain?.toApi() ) internal fun ScanRecordDomain.toApi() = ScanRecord( diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt index 269f78b8..5e21c605 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt @@ -4,15 +4,13 @@ import no.nordicsemi.android.wifi.provisioner.softap.proto.AuthMode import no.nordicsemi.android.wifi.provisioner.softap.proto.Band import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.softap.proto.ScanResults -import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiConfig import no.nordicsemi.android.wifi.provisioner.softap.proto.WifiInfo import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConfigDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain -internal fun AuthMode.toDomain() = when(this) { +internal fun AuthMode.toDomain() = when (this) { AuthMode.OPEN -> AuthModeDomain.OPEN AuthMode.WEP -> AuthModeDomain.WEP AuthMode.WPA_PSK -> AuthModeDomain.WPA_PSK @@ -22,32 +20,23 @@ internal fun AuthMode.toDomain() = when(this) { AuthMode.WPA3_PSK -> AuthModeDomain.WPA3_PSK } -internal fun Band.toDomain() = when(this) { - Band.BAND_UNSPECIFIED -> BandDomain.BAND_ANY +internal fun Band.toDomain() = when (this) { + Band.BAND_ANY -> BandDomain.BAND_ANY Band.BAND_2_4_GHZ -> BandDomain.BAND_2_4_GH Band.BAND_5_GHZ -> BandDomain.BAND_5_GH - Band.BAND_6_GHZ -> BandDomain.BAND_6_GH } internal fun WifiInfo.toDomain() = WifiInfoDomain( - ssid = ssid, - band = band.toDomain(), + ssid = ssid.utf8(), + bssid = bssid, + band = band?.toDomain(), channel = channel, - authModeDomain = authMode.toDomain(), - bssid = "" -) - -@Suppress("unused") -internal fun WifiConfig.toDomain() = WifiConfigDomain( - info = info?.toDomain()!!, - passphrase = passphrase, - anyChannel = false, - volatileMemory = false + authModeDomain = auth?.toDomain() ) internal fun ScanRecord.toDomain() = ScanRecordDomain( - wifiInfo = wifi?.toDomain(), - rssi = rssi + rssi = rssi, + wifiInfo = wifi?.toDomain() ) internal fun ScanResults.toDomain() = ScanResultsDomain( diff --git a/lib/ble/proto/build.gradle.kts b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt similarity index 87% rename from lib/ble/proto/build.gradle.kts rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt index e1c8b51f..bfc73bb7 100644 --- a/lib/ble/proto/build.gradle.kts +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt @@ -29,16 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -plugins { - alias(libs.plugins.nordic.library) - alias(libs.plugins.nordic.kotlin) - alias(libs.plugins.wire) -} +package no.nordicsemi.android.wifi.provisioner.softap.domain -wire { - kotlin {} -} +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain -android { - namespace = "no.nordicsemi.android.wifi.provisioner.ble.proto" -} +data class WifiConfigDomain( + val info: WifiInfoDomain?, + val passphrase: String? +) diff --git a/lib/softap/provisioner/src/main/proto/common.proto b/lib/softap/provisioner/src/main/proto/common.proto index b352bc84..3a0bb470 100644 --- a/lib/softap/provisioner/src/main/proto/common.proto +++ b/lib/softap/provisioner/src/main/proto/common.proto @@ -1,14 +1,13 @@ -syntax = "proto3"; +syntax = "proto2"; option java_multiple_files = true; option java_package = "no.nordicsemi.android.wifi.provisioner.softap.proto"; // Common ENUMs enum Band { - BAND_UNSPECIFIED = 0; + BAND_ANY = 0; BAND_2_4_GHZ = 1; BAND_5_GHZ = 2; - BAND_6_GHZ = 3; } enum AuthMode { @@ -22,20 +21,21 @@ enum AuthMode { } message WifiInfo { - string ssid = 1; - Band band = 3; - uint32 channel = 4; - AuthMode authMode = 5; + required bytes ssid = 1; + required bytes bssid = 2; + optional Band band = 3; + required uint32 channel = 4; + optional AuthMode auth = 5; } message WifiConfig { - WifiInfo info = 1; - string passphrase = 2; + optional WifiInfo wifi = 1; + optional bytes passphrase = 2; } message ScanRecord { - WifiInfo wifi = 1; - int32 rssi = 2; + optional WifiInfo wifi = 1; + optional int32 rssi = 2; } message ScanResults { From 9de16e504f2d1fa5f795fb4e73442ba612d63b84 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 22 Apr 2024 11:50:13 +0200 Subject: [PATCH 045/101] WIP: Unifying BLE and Wifi provisioner UI --- .../provisioner/ble/sections/WifiSection.kt | 2 +- .../provisioner/ble/view/BleDestination.kt | 2 +- .../provisioner/ble/view/BleViewEntity.kt | 2 +- .../provisioner/ble/viewmodel/BleViewModel.kt | 2 +- .../wifi/view/WiFiAccessPointListsScreen.kt | 13 ++- .../ble/wifi/view/WifiScannerViewEntity.kt | 67 ------------- .../wifi/viewmodel/WifiScannerViewModel.kt | 61 ++++++------ feature/common/build.gradle.kts | 10 +- .../feature/common}/WifiAggregator.kt | 9 +- .../common/WifiDataConfiguration.kt | 2 +- .../feature/common}/WifiScannerViewEntity.kt | 5 +- .../common/event/WifiScannerViewEvent.kt | 4 +- .../common/event/WifiSortOption.kt | 2 +- .../viewmodel/GenericWifiScannerViewModel.kt | 39 ++++++++ .../softap/view/SoftApDestinations.kt | 21 ++++- .../softap/view/WifiAccessPointsScreen.kt | 18 ++-- .../softap/viewmodel/SoftApViewModel.kt | 29 +++--- .../softap/viewmodel/WifiScannerViewModel.kt | 94 +++++++++++++++++++ .../provisioner/ui}/SelectChannelDialog.kt | 6 +- .../wifi/provisioner/ui/view/WifiSortView.kt | 2 +- feature/ui/src/main/res/values/strings.xml | 11 +++ .../wifi/provisioner/softap/WifiService.kt | 4 +- 22 files changed, 261 insertions(+), 144 deletions(-) delete mode 100644 feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel => common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common}/WifiAggregator.kt (91%) rename feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/{ => feature}/common/WifiDataConfiguration.kt (84%) rename feature/{softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view => common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common}/WifiScannerViewEntity.kt (92%) rename feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/{ => feature}/common/event/WifiScannerViewEvent.kt (92%) rename feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/{ => feature}/common/event/WifiSortOption.kt (96%) create mode 100644 feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/SelectChannelDialog.kt (96%) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index af33632e..f6f0ccc7 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -37,7 +37,7 @@ import androidx.compose.ui.res.stringResource import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 68d2a2cb..3f83a3a8 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -37,7 +37,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt index e88ed8cf..391e98f2 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt @@ -38,7 +38,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData data class BleViewEntity( val device: ServerDevice? = null, diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 27947374..23180b21 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -67,7 +67,7 @@ import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import javax.inject.Inject diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt index cbffdd0a..73e20553 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt @@ -65,14 +65,17 @@ import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.SelectChannelDialog import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortView -import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiScannerViewEntity +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @OptIn(ExperimentalMaterial3Api::class) @@ -91,7 +94,7 @@ internal fun WiFiAccessPointListsScreen( if (viewEntity.isLoading) { LoadingItem() } else if (viewEntity.error != null) { - ErrorItem(viewEntity.error) + ErrorItem(viewEntity.error!!) } else { WifiList(viewEntity, onEvent) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt deleted file mode 100644 index 766985ae..00000000 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WifiScannerViewEntity.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.ble.wifi.view - -import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration -import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption - -data class WifiScannerViewEntity( - val isLoading: Boolean = true, - val error: Throwable? = null, - val sortOption: WifiSortOption = WifiSortOption.RSSI, - private val items: List = emptyList() -) { - val sortedItems: List = when (sortOption) { - WifiSortOption.NAME -> items.sortedBy { it.wifiData.ssid } - WifiSortOption.RSSI -> items.sortedByDescending { it.biggestRssi } - } -} - -data class ScanRecordsForSsid( - val wifiData: WifiData, - val items: List = emptyList(), -) { - val biggestRssi: Int = items.maxOf { it.rssi ?: 0 } -} - -data class WifiData( - override val ssid: String, - override val authMode: AuthModeDomain, - val channelFallback: ScanRecordDomain, //Needed for proto v1 - val selectedChannel: ScanRecordDomain? = null -) : WifiDataConfiguration { - fun isPasswordRequired(): Boolean { - return authMode != AuthModeDomain.OPEN - } -} diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index 28a373dd..1c179b5a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -31,52 +31,41 @@ package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository -import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiScannerViewEntity -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel import javax.inject.Inject @HiltViewModel internal class WifiScannerViewModel @Inject constructor( - private val navigationManager: Navigator, - private val wifiAggregator: WifiAggregator, + navigationManager: Navigator, + wifiAggregator: WifiAggregator, private val repository: ProvisionerResourceRepository -) : ViewModel() { - - private val _state = MutableStateFlow(WifiScannerViewEntity()) - val state = _state.asStateFlow() +) : GenericWifiScannerViewModel( + navigationManager = navigationManager, + wifiAggregator = wifiAggregator +) { init { - repository.startScan().onEach { - val state = _state.value - - _state.value = when (it) { - is Error -> state.copy(isLoading = false, error = it.error) - is Loading -> state.copy(isLoading = true) - is Success -> state.copy(isLoading = false, error = null, items = wifiAggregator.addWifi(it.data)) - } - }.launchIn(viewModelScope) + startScan() } - fun onEvent(event: WifiScannerViewEvent) { + override fun onEvent(event: WifiScannerViewEvent) { when (event) { NavigateUpEvent -> navigateUp() is WifiSelectedEvent -> navigateUp(event.wifiData) @@ -84,8 +73,20 @@ internal class WifiScannerViewModel @Inject constructor( } } - private fun onSortOptionSelected(sortOption: WifiSortOption) { - _state.value = _state.value.copy(sortOption = sortOption) + private fun startScan() { + repository.startScan().onEach { + val state = _state.value + + _state.value = when (it) { + is Error -> state.copy(isLoading = false, error = it.error) + is Loading -> state.copy(isLoading = true) + is Success -> state.copy( + isLoading = false, + error = null, + items = wifiAggregator.addWifi(it.data) + ) + } + }.launchIn(viewModelScope) } private suspend fun stopScanning() { @@ -96,14 +97,14 @@ internal class WifiScannerViewModel @Inject constructor( } } - private fun navigateUp() { + override fun navigateUp() { viewModelScope.launch { stopScanning() navigationManager.navigateUp() } } - private fun navigateUp(wifiData: WifiDataConfiguration) { + override fun navigateUp(wifiData: WifiDataConfiguration) { viewModelScope.launch { stopScanning() navigationManager.navigateUpWithResult(WiFiAccessPointsListId, wifiData) diff --git a/feature/common/build.gradle.kts b/feature/common/build.gradle.kts index c8cae981..7e53b85d 100644 --- a/feature/common/build.gradle.kts +++ b/feature/common/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - alias(libs.plugins.nordic.library) - alias(libs.plugins.nordic.kotlin) + alias(libs.plugins.nordic.feature) + alias(libs.plugins.nordic.hilt) } android { @@ -9,4 +9,10 @@ android { dependencies { implementation(project(":lib:domain")) + + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.hilt.navigation.compose) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.lifecycle.viewModel.compose) + implementation(libs.nordic.navigation) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiAggregator.kt similarity index 91% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiAggregator.kt index 18c0b59b..d5546917 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiAggregator.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiAggregator.kt @@ -29,10 +29,8 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel +package no.nordicsemi.kotlin.wifi.provisioner.feature.common -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.ScanRecordsForSsid -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WifiData import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import javax.inject.Inject @@ -53,6 +51,11 @@ class WifiAggregator @Inject constructor() { return createResult(records) } + fun addWifi(records: List): List { + records.forEach { addWifi(it) } + return createResult(this.records) + } + private fun createResult(records: Map>): List { return records.map { ScanRecordsForSsid( diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt similarity index 84% rename from feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt index 94fbbb9b..fea49018 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/WifiDataConfiguration.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.kotlin.wifi.provisioner.common +package no.nordicsemi.kotlin.wifi.provisioner.feature.common import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt similarity index 92% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt index b66a7ddb..8cd496f4 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiScannerViewEntity.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt @@ -29,12 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.softap.view +package no.nordicsemi.kotlin.wifi.provisioner.feature.common -import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSortOption data class WifiScannerViewEntity( val isLoading: Boolean = true, diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt similarity index 92% rename from feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt index 700f1968..8d6e21ca 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiScannerViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt @@ -29,9 +29,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.kotlin.wifi.provisioner.common.event +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event -import no.nordicsemi.kotlin.wifi.provisioner.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration sealed class WifiScannerViewEvent diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiSortOption.kt similarity index 96% rename from feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiSortOption.kt index 4cfbf040..2b31fc2a 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/common/event/WifiSortOption.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiSortOption.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.kotlin.wifi.provisioner.common.event +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event enum class WifiSortOption { NAME, RSSI diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt new file mode 100644 index 00000000..27769c88 --- /dev/null +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt @@ -0,0 +1,39 @@ +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel + +import androidx.lifecycle.ViewModel +import no.nordicsemi.android.common.navigation.Navigator +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiScannerViewEntity +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSortOption + +abstract class GenericWifiScannerViewModel( + protected val navigationManager: Navigator, + protected val wifiAggregator: WifiAggregator +) : ViewModel() { + + protected val _state = MutableStateFlow(WifiScannerViewEntity()) + val state = _state.asStateFlow() + + open fun onEvent(event: WifiScannerViewEvent) { + when (event) { + NavigateUpEvent -> navigateUp() + is WifiSelectedEvent -> navigateUp(event.wifiData) + is OnSortOptionSelected -> onSortOptionSelected(event.sortOption) + } + } + + protected fun onSortOptionSelected(sortOption: WifiSortOption) { + _state.value = _state.value.copy(sortOption = sortOption) + } + + protected abstract fun navigateUp() + + protected abstract fun navigateUp(wifiData: WifiDataConfiguration) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index e1a34750..5023ace2 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -1,14 +1,33 @@ package no.nordicsemi.android.wifi.provisioner.softap.view +import android.os.Build +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.WifiScannerViewModel +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration /** * Created by Roshan Rajaratnam on 14/02/2024. */ val SoftApProvisionerDestinationId = createSimpleDestination("softap-provider-destination") +val WiFiAccessPointsDestinationId = createDestination( + name = "wifi-access-points-destination1" +) val SoftApProvisionerDestinations = listOf( - defineDestination(SoftApProvisionerDestinationId) { SoftApProvisioningScreen() } + defineDestination(SoftApProvisionerDestinationId) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + SoftApProvisioningScreen() + } + }, + defineDestination(WiFiAccessPointsDestinationId) { + val viewModel = hiltViewModel() + val viewEntity by viewModel.state.collectAsStateWithLifecycle() + WiFiAccessPointsScreen(viewEntity, viewModel::onEvent) + } ) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt index 1034bbe6..b29d0944 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt @@ -64,16 +64,19 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.common.theme.view.getWiFiRes -import no.nordicsemi.kotlin.wifi.provisioner.common.event.NavigateUpEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.OnSortOptionSelected -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiScannerViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.feature.softap.R import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem +import no.nordicsemi.android.wifi.provisioner.ui.SelectChannelDialog import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.android.wifi.provisioner.ui.view.WifiLoadingItem import no.nordicsemi.android.wifi.provisioner.ui.view.WifiSortView +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiScannerViewEntity import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @OptIn(ExperimentalMaterial3Api::class) @@ -82,7 +85,6 @@ internal fun WiFiAccessPointsScreen( viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerViewEvent) -> Unit ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { NordicAppBar( text = stringResource(id = R.string.wifi_access_points_title), @@ -92,7 +94,7 @@ internal fun WiFiAccessPointsScreen( if (viewEntity.isLoading) { LoadingItem() } else if (viewEntity.error != null) { - ErrorItem(viewEntity.error) + ErrorItem(viewEntity.error!!) } else { WifiList(viewEntity, onEvent) } @@ -150,13 +152,13 @@ private fun WifiItem(records: ScanRecordsForSsid, onEvent: (WifiScannerViewEvent val showSelectChannelDialog = rememberSaveable { mutableStateOf(false) } if (showSelectChannelDialog.value) { - /*SelectChannelDialog( + SelectChannelDialog( records = records, onDismiss = { showSelectChannelDialog.value = false } ) { selectedScanRecord.value = it showSelectChannelDialog.value = false - }*/ + } } Row( diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index c4eb052a..84903df7 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -16,8 +16,8 @@ import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.wifi.provisioner.softap.ProvisioningState import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.domain.AuthModeDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.softap.view.WiFiAccessPointsDestinationId import okhttp3.OkHttpClient import javax.inject.Inject @@ -39,6 +39,7 @@ class SoftApViewModel @Inject constructor( ProvisioningState.Connected -> { discoverServices() } + ProvisioningState.Provisioning -> {} ProvisioningState.ProvisioningComplete -> {} } @@ -51,14 +52,14 @@ class SoftApViewModel @Inject constructor( } @RequiresApi(Build.VERSION_CODES.Q) - internal fun connect(ssid: String = "mobileappsrules", password: String) { + internal fun connect(ssid: String = "0018F0-nrf-wifiprov", password: String) { softApManager.connect(ssid = ssid, password = password) } private fun discoverServices() { viewModelScope.launch { softApManager.discoverServices() - listSsids() + navigateTo(WiFiAccessPointsDestinationId) } } @@ -68,14 +69,20 @@ class SoftApViewModel @Inject constructor( } viewModelScope.launch(handler) { val result = softApManager.listSsids() - Log.d("AAAA", "Results: $result") - if (result.wifiScanResults.isNotEmpty()) { - val wifConfig = WifiConfigDomain( - ssid = "", - passphrase = "", - authModeDomain = AuthModeDomain.WPA3_PSK, - ) - provision(wifConfig) + Log.d("AAAA", "Results: ${result.results}") + result.results.forEach { + it.wifiInfo?.takeIf { wifiInfo -> + wifiInfo.ssid == "OnHub" + }?.let { wifiInfo -> + Log.d("AAAA", "Found the device!") + val wifiConfig = WifiConfigDomain( + info = wifiInfo, + passphrase = "newbird379", + ) + Log.d("AAAA", "WifiConfig: $wifiConfig") + provision(wifiConfig) + return@forEach + } } } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt new file mode 100644 index 00000000..71e9b42c --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.viewmodel + +import android.util.Log +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.launch +import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel +import javax.inject.Inject + +@HiltViewModel +internal class WifiScannerViewModel @Inject constructor( + navigationManager: Navigator, + wifiAggregator: WifiAggregator, + private val softApManager: SoftApManager +) : GenericWifiScannerViewModel( + navigationManager = navigationManager, + wifiAggregator = wifiAggregator +) { + + init { + listSsids() + } + + override fun onEvent(event: WifiScannerViewEvent) { + when (event) { + NavigateUpEvent -> navigateUp() + is WifiSelectedEvent -> navigateUp(event.wifiData) + is OnSortOptionSelected -> onSortOptionSelected(event.sortOption) + } + } + + private fun listSsids() { + val handler = CoroutineExceptionHandler { _, throwable -> + Log.e("AAAA", "$throwable") + } + viewModelScope.launch(handler) { + val ssids = softApManager.listSsids() + val state = _state.value + _state.value = state.copy( + isLoading = false, error = null, + items = wifiAggregator.addWifi( + ssids.results + ), + ) + } + } + override fun navigateUp() { + navigationManager.navigateUp() + } + + override fun navigateUp(wifiData: WifiDataConfiguration) { + // navigationManager.navigate(WiFiAccessPointsListId, wifiData) + } +} diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/SelectChannelDialog.kt similarity index 96% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/SelectChannelDialog.kt index f14afd3e..77354ca0 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/SelectChannelDialog.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/SelectChannelDialog.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.wifi.view +package no.nordicsemi.android.wifi.provisioner.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -47,12 +47,12 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.RssiIcon -import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @Composable -internal fun SelectChannelDialog( +fun SelectChannelDialog( records: ScanRecordsForSsid, onDismiss: () -> Unit, onRecordSelected: (ScanRecordDomain?) -> Unit diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt index 8f8653d1..29960bee 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/WifiSortView.kt @@ -52,7 +52,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.kotlin.wifi.provisioner.common.event.WifiSortOption +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSortOption import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.common.theme.R as themeR diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 01666760..8edaba99 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -7,6 +7,17 @@ Name RSSI + Select Wi-Fi + Clear + Dismiss + + + IPv4: %s + SSID: %s + BSSID: %s + Band: %s + Band: %s, Channel: %s + Channel: %s 2.4 GHz 5 GHz Any diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt index 373bd8a5..86fe72a2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt @@ -14,11 +14,11 @@ import retrofit2.http.POST */ interface WifiService { - @Headers("Content-Type: text/plain") + @Headers("Content-Type: application/x-protobuf") @GET("prov/networks") suspend fun listSsids(): ScanResults - @Headers("Content-Type: text/plain") + @Headers("Content-Type: application/x-protobuf") @POST("prov/configure") suspend fun provision(@Body config: WifiConfig): Response } \ No newline at end of file From 0bd97bc43b1d125b48a418e8f1de73264d067c32 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 22 Apr 2024 13:32:59 +0200 Subject: [PATCH 046/101] WIP: Unifying BLE and Wifi provisioner UI --- .../provisioner/ble/view/BleDestination.kt | 4 ++-- .../wifi/viewmodel/WifiScannerViewModel.kt | 18 +++--------------- .../feature/common/WifiDataConfiguration.kt | 15 --------------- .../feature/common/WifiScannerViewEntity.kt | 6 +++--- .../common/event/WifiScannerViewEvent.kt | 4 ++-- .../viewmodel/GenericWifiScannerViewModel.kt | 8 ++++---- .../softap/view/SoftApDestinations.kt | 4 ++-- .../softap/viewmodel/WifiScannerViewModel.kt | 19 ++++--------------- 8 files changed, 20 insertions(+), 58 deletions(-) delete mode 100644 feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 3f83a3a8..4442a6b2 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -37,13 +37,13 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData val BleProvisioningDestinationId = createSimpleDestination("ble-provisioning-destination") -val WiFiAccessPointsListId = createDestination( +val WiFiAccessPointsListId = createDestination( name = "wifi-access-points-destination" ) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt index 1c179b5a..0a3111fe 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt @@ -37,17 +37,13 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration -import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent import no.nordicsemi.android.wifi.provisioner.ble.Error import no.nordicsemi.android.wifi.provisioner.ble.Loading import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel import javax.inject.Inject @@ -65,14 +61,6 @@ internal class WifiScannerViewModel @Inject constructor( startScan() } - override fun onEvent(event: WifiScannerViewEvent) { - when (event) { - NavigateUpEvent -> navigateUp() - is WifiSelectedEvent -> navigateUp(event.wifiData) - is OnSortOptionSelected -> onSortOptionSelected(event.sortOption) - } - } - private fun startScan() { repository.startScan().onEach { val state = _state.value @@ -104,7 +92,7 @@ internal class WifiScannerViewModel @Inject constructor( } } - override fun navigateUp(wifiData: WifiDataConfiguration) { + override fun navigateUp(wifiData: WifiData) { viewModelScope.launch { stopScanning() navigationManager.navigateUpWithResult(WiFiAccessPointsListId, wifiData) diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt deleted file mode 100644 index fea49018..00000000 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiDataConfiguration.kt +++ /dev/null @@ -1,15 +0,0 @@ -package no.nordicsemi.kotlin.wifi.provisioner.feature.common - -import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain - - -/** - * Common interface for the Wifi data configuration. - * - * @property ssid SSID of the network. - * @property authMode Authentication mode used for provisioning. - */ -interface WifiDataConfiguration { - val ssid: String - val authMode: AuthModeDomain -} \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt index 8cd496f4..59d3481a 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/WifiScannerViewEntity.kt @@ -55,11 +55,11 @@ data class ScanRecordsForSsid( } data class WifiData( - override val ssid: String, - override val authMode: AuthModeDomain, + val ssid: String, + val authMode: AuthModeDomain, val channelFallback: ScanRecordDomain, //Needed for proto v1 val selectedChannel: ScanRecordDomain? = null -) : WifiDataConfiguration { +) { fun isPasswordRequired(): Boolean { return authMode != AuthModeDomain.OPEN } diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt index 8d6e21ca..7802e2a9 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/WifiScannerViewEvent.kt @@ -31,12 +31,12 @@ package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData sealed class WifiScannerViewEvent data object NavigateUpEvent : WifiScannerViewEvent() -data class WifiSelectedEvent(val wifiData: WifiDataConfiguration) : WifiScannerViewEvent() +data class WifiSelectedEvent(val wifiData: WifiData) : WifiScannerViewEvent() data class OnSortOptionSelected(val sortOption: WifiSortOption) : WifiScannerViewEvent() diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt index 27769c88..80398b70 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/viewmodel/GenericWifiScannerViewModel.kt @@ -5,7 +5,7 @@ import no.nordicsemi.android.common.navigation.Navigator import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiScannerViewEntity import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected @@ -21,7 +21,7 @@ abstract class GenericWifiScannerViewModel( protected val _state = MutableStateFlow(WifiScannerViewEntity()) val state = _state.asStateFlow() - open fun onEvent(event: WifiScannerViewEvent) { + fun onEvent(event: WifiScannerViewEvent) { when (event) { NavigateUpEvent -> navigateUp() is WifiSelectedEvent -> navigateUp(event.wifiData) @@ -29,11 +29,11 @@ abstract class GenericWifiScannerViewModel( } } - protected fun onSortOptionSelected(sortOption: WifiSortOption) { + private fun onSortOptionSelected(sortOption: WifiSortOption) { _state.value = _state.value.copy(sortOption = sortOption) } protected abstract fun navigateUp() - protected abstract fun navigateUp(wifiData: WifiDataConfiguration) + protected abstract fun navigateUp(wifiData: WifiData) } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 5023ace2..9b434cf0 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -8,14 +8,14 @@ import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.WifiScannerViewModel -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData /** * Created by Roshan Rajaratnam on 14/02/2024. */ val SoftApProvisionerDestinationId = createSimpleDestination("softap-provider-destination") -val WiFiAccessPointsDestinationId = createDestination( +val WiFiAccessPointsDestinationId = createDestination( name = "wifi-access-points-destination1" ) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt index 71e9b42c..64f839a0 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt @@ -38,12 +38,9 @@ import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.view.WiFiAccessPointsDestinationId import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiDataConfiguration -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.NavigateUpEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSortOptionSelected -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel import javax.inject.Inject @@ -61,14 +58,6 @@ internal class WifiScannerViewModel @Inject constructor( listSsids() } - override fun onEvent(event: WifiScannerViewEvent) { - when (event) { - NavigateUpEvent -> navigateUp() - is WifiSelectedEvent -> navigateUp(event.wifiData) - is OnSortOptionSelected -> onSortOptionSelected(event.sortOption) - } - } - private fun listSsids() { val handler = CoroutineExceptionHandler { _, throwable -> Log.e("AAAA", "$throwable") @@ -88,7 +77,7 @@ internal class WifiScannerViewModel @Inject constructor( navigationManager.navigateUp() } - override fun navigateUp(wifiData: WifiDataConfiguration) { - // navigationManager.navigate(WiFiAccessPointsListId, wifiData) + override fun navigateUp(wifiData: WifiData) { + navigationManager.navigateUpWithResult(WiFiAccessPointsDestinationId, wifiData) } } From 8e8bd5c171724655b05f586fc11f24f880eb8387 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 01:15:46 +0200 Subject: [PATCH 047/101] WIP: Unifying BLE and Wifi provisioner UI --- .../android/wifi/provisioner/HomeScreen.kt | 8 +- .../ProvisionerResourceRepository.kt | 6 +- .../ble/sections/ActionButtonSection.kt | 19 +- .../provisioner/ble/sections/StatusSection.kt | 14 +- .../ble/sections/VersionSection.kt | 10 +- .../ble/sections/VolatileMemorySwitch.kt | 6 +- .../provisioner/ble/view/BleDestination.kt | 20 +- .../ble/view/BleProvisioningScreen.kt | 40 ++-- .../provisioner/ble/view/BleViewEntity.kt | 32 +-- .../provisioner/ble/viewmodel/BleViewModel.kt | 38 ++-- ...ListsScreen.kt => BleWifiScannerScreen.kt} | 2 +- ...iewModel.kt => BleWifiScannerViewModel.kt} | 12 +- .../common/event}/BleScreenViewEvent.kt | 26 +-- .../common/event}/PasswordDialogEvent.kt | 2 +- .../feature/common/event/ViewEvent.kt | 3 + .../feature/common/view/ViewEntity.kt | 23 ++ .../softap/sections/ActionButtonSection.kt | 88 ++++++++ .../softap/view/SoftApConnectorScreen.kt | 135 +++++++++++ .../softap/view/SoftApDestinations.kt | 29 ++- .../softap/view/SoftApProvisioningScreen.kt | 195 +++++++--------- ...tsScreen.kt => SoftApWifiScannerScreen.kt} | 2 +- .../softap/view/entity/SoftApViewEntity.kt | 25 +++ .../viewmodel/SoftApConnectorViewModel.kt | 36 +++ .../viewmodel/SoftApProvisioningViewModel.kt | 212 ++++++++++++++++++ .../softap/viewmodel/SoftApViewModel.kt | 114 ---------- ...Model.kt => SoftApWifiScannerViewModel.kt} | 7 +- .../softap/src/main/res/values/strings.xml | 5 + .../wifi/provisioner/ui}/PasswordDialog.kt | 8 +- .../wifi/provisioner/ui}/view/UiMapper.kt | 15 +- .../ui/view/section}/DeviceSection.kt | 50 +++-- .../view/section}/DisconnectedDeviceStatus.kt | 4 +- .../ui/view/section}/PasswordSection.kt | 10 +- .../ui/view/section}/ProvisioningSection.kt | 18 +- .../ui/view/section}/UnprovisioningSection.kt | 14 +- .../ui/view/section}/WifiSection.kt | 12 +- .../src/main/res/drawable/ic_upload_wifi.xml | 0 feature/ui/src/main/res/values/strings.xml | 81 ++++++- .../provisioner/ble/ProvisionerRepository.kt | 4 +- .../ble/ProvisionerRepositoryImpl.kt | 4 +- .../provisioner/ble/domain/ToDomainMapper.kt | 5 + .../domain/ConnectionInfoDomain.kt | 2 +- .../provisioner}/domain/DeviceStatusDomain.kt | 4 +- .../provisioner}/domain/ScanParamsDomain.kt | 4 +- .../WifiConnectionFailureReasonDomain.kt | 2 +- .../domain/WifiConnectionStateDomain.kt | 2 +- .../provisioner/domain/resource}/Resource.kt | 2 +- .../softap/NetworkServiceDiscoveryListener.kt | 2 + .../android/wifi/provisioner/softap/SoftAp.kt | 13 ++ .../wifi/provisioner/softap/SoftApManager.kt | 19 +- 49 files changed, 958 insertions(+), 426 deletions(-) rename feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/{WiFiAccessPointListsScreen.kt => BleWifiScannerScreen.kt} (99%) rename feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/{WifiScannerViewModel.kt => BleWifiScannerViewModel.kt} (89%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view => common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event}/BleScreenViewEvent.kt (66%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password => common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event}/PasswordDialogEvent.kt (96%) create mode 100644 feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt create mode 100644 feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt rename feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/{WifiAccessPointsScreen.kt => SoftApWifiScannerScreen.kt} (99%) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt rename feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/{WifiScannerViewModel.kt => SoftApWifiScannerViewModel.kt} (92%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/PasswordDialog.kt (93%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui}/view/UiMapper.kt (87%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/DeviceSection.kt (71%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/DisconnectedDeviceStatus.kt (94%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/PasswordSection.kt (85%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/ProvisioningSection.kt (93%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/UnprovisioningSection.kt (86%) rename feature/{ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections => ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section}/WifiSection.kt (89%) rename feature/{ble => ui}/src/main/res/drawable/ic_upload_wifi.xml (100%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/ConnectionInfoDomain.kt (96%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/DeviceStatusDomain.kt (92%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/ScanParamsDomain.kt (93%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/WifiConnectionFailureReasonDomain.kt (96%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner}/domain/WifiConnectionStateDomain.kt (96%) rename lib/{ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble => domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/resource}/Resource.kt (96%) create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 9107cce8..ce1c2c43 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -58,8 +58,8 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.wifi.provisioner.app.R -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestinationId -import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestinationId +import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestination @Composable fun HomeScreen() { @@ -95,10 +95,10 @@ fun HomeScreen() { ) } Row(modifier = Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) { - Button(onClick = { vm.navigateTo(BleProvisioningDestinationId) }) { + Button(onClick = { vm.navigateTo(BleProvisioningDestination) }) { Text(text = "Provision over BLE") } - Button(onClick = { vm.navigateTo(SoftApProvisionerDestinationId) }) { + Button(onClick = { vm.navigateTo(SoftApProvisionerDestination) }) { Text(text = "Provision over Wi-Fi") } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt index f58a61b9..98b4fd7f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/ProvisionerResourceRepository.kt @@ -38,12 +38,12 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus class ProvisionerResourceRepository( diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index eaaedfed..79de6fff 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -42,18 +42,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity -import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity @Composable -fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (BleProvisioningViewEvent) -> Unit) { +fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { if (viewEntity.isRunning()) { return } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt index 98712035..314196d9 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt @@ -41,18 +41,18 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector -import no.nordicsemi.android.wifi.provisioner.ble.Error -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.Success -import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ui.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ui.view.toImageVector +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success @Composable internal fun StatusSection(status: Resource) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt index 4c88b75d..d3ccd3c6 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VersionSection.kt @@ -35,18 +35,18 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Code import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.Error -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error @Composable -internal fun VersionSection(version: Resource) { +fun VersionSection(version: Resource) { when (version) { is Error -> ErrorSection(version.error) is Loading -> LoadingItem() diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt index 99f3ed2f..6597ffcd 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt @@ -46,15 +46,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable fun VolatileMemorySwitch( volatileMemory: Boolean, enabled: Boolean, - onEvent: (BleProvisioningViewEvent) -> Unit + onEvent: (ProvisioningViewEvent) -> Unit ) { Row( modifier = Modifier diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 4442a6b2..3dbac42a 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -38,20 +38,22 @@ import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination -import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.WiFiAccessPointListsScreen -import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.WifiScannerViewModel +import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.BleWifiScannerScreen +import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.BleWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -val BleProvisioningDestinationId = createSimpleDestination("ble-provisioning-destination") -val WiFiAccessPointsListId = createDestination( - name = "wifi-access-points-destination" +val BleProvisioningDestination = createSimpleDestination("ble-provisioning-destination") +val BleWifiScannerDestination = createDestination( + name = "wifi-access-points-ble-destination" ) val BleProvisioningDestinations = listOf( - defineDestination(BleProvisioningDestinationId) { BleProvisioningScreen() }, - defineDestination(WiFiAccessPointsListId) { - val viewModel = hiltViewModel() + defineDestination(BleProvisioningDestination) { + BleProvisioningScreen() + }, + defineDestination(BleWifiScannerDestination) { + val viewModel = hiltViewModel() val viewEntity by viewModel.state.collectAsStateWithLifecycle() - WiFiAccessPointListsScreen(viewEntity = viewEntity, onEvent = viewModel::onEvent) + BleWifiScannerScreen(viewEntity = viewEntity, onEvent = viewModel::onEvent) } ) + BleScannerDestination diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index a91a4073..e3106ccf 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -50,20 +50,25 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent import no.nordicsemi.android.wifi.provisioner.ble.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioner.ble.sections.DeviceSection -import no.nordicsemi.android.wifi.provisioner.ble.sections.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioner.ble.sections.PasswordSection -import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection import no.nordicsemi.android.wifi.provisioner.ble.sections.StatusSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.UnprovisioningSection import no.nordicsemi.android.wifi.provisioner.ble.sections.VersionSection import no.nordicsemi.android.wifi.provisioner.ble.sections.VolatileMemorySwitch -import no.nordicsemi.android.wifi.provisioner.ble.sections.WifiSection import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.sections.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioner.ble.password.PasswordDialog -import no.nordicsemi.android.wifi.provisioner.ble.password.PasswordSetDialogEvent +import no.nordicsemi.android.wifi.provisioner.ui.view.section.BluetoothDevice +import no.nordicsemi.android.wifi.provisioner.ui.view.section.DeviceNotSelectedSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -71,7 +76,7 @@ fun BleProvisioningScreen() { val viewModel = hiltViewModel() val state by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (BleProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } + val onEvent: (ProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } Column { NordicAppBar( text = stringResource(id = R.string.label_ble_provisioner), @@ -91,15 +96,17 @@ fun BleProvisioningScreen() { } if (state.showPasswordDialog == true) { - PasswordDialog { - (it as? PasswordSetDialogEvent)?.let { onEvent(OnPasswordSelectedEvent(it.password)) } + PasswordDialog { event -> + (event as? PasswordSetDialogEvent)?.let { + onEvent(OnPasswordSelectedEvent(it.password)) + } onEvent(OnHidePasswordDialog) } } } @Composable -private fun Content(state: BleViewEntity, onEvent: (BleProvisioningViewEvent) -> Unit) { +private fun Content(state: BleViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { Column( modifier = Modifier .verticalScroll(rememberScrollState()) @@ -107,7 +114,14 @@ private fun Content(state: BleViewEntity, onEvent: (BleProvisioningViewEvent) -> ) { Spacer(modifier = Modifier.size(12.dp)) - DeviceSection(state.device, !state.isRunning(), onEvent) + if (state.device == null) { + DeviceNotSelectedSection(onEvent) + } else { + BluetoothDevice(state.device.name, state.device.address, !state.isRunning(), onEvent) + } + /*state.device?.let { + BluetoothDevice(it.name , it.address, !state.isRunning(), onEvent) + } ?: DeviceNotSelectedSection(onEvent)*/ Spacer(modifier = Modifier.size(12.dp)) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt index 391e98f2..2eb663af 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt @@ -32,26 +32,28 @@ package no.nordicsemi.android.wifi.provisioner.ble.view import no.nordicsemi.android.kotlin.ble.core.ServerDevice -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.Success -import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity data class BleViewEntity( val device: ServerDevice? = null, val version: Resource? = null, val status: Resource? = null, - val network: WifiData? = null, - val password: String? = null, + override val network: WifiData? = null, + override val password: String? = null, val persistentMemory: Boolean = true, - val showPasswordDialog: Boolean? = null, - val provisioningStatus: Resource? = null, + override val showPasswordDialog: Boolean? = null, + override val provisioningStatus: Resource? = null, val unprovisioningStatus: Resource? = null, - val isConnected: Boolean = true -) { + override val isConnected: Boolean = true +) : ViewEntity { + fun isStatusSuccess(): Boolean { return device != null && version is Success && status is Success } @@ -65,7 +67,11 @@ data class BleViewEntity( } fun isRunning(): Boolean { - return device != null && version == null || version is Loading || status is Loading || provisioningStatus is Loading || unprovisioningStatus is Loading + return device != null && version == null + || version is Loading + || status is Loading + || provisioningStatus is Loading + || unprovisioningStatus is Loading } fun hasFinished(): Boolean { @@ -76,7 +82,7 @@ data class BleViewEntity( || unprovisioningStatus is Success } - fun hasFinishedWithSuccess(): Boolean { + override fun hasFinishedWithSuccess(): Boolean { val status = (provisioningStatus as? Success)?.data return isConnected && (status == WifiConnectionStateDomain.CONNECTED diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 23180b21..9cd0a247 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -47,26 +47,26 @@ import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.kotlin.ble.core.RealServerDevice -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity -import no.nordicsemi.android.wifi.provisioner.ble.view.OnFinishedEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnHidePasswordDialog -import no.nordicsemi.android.wifi.provisioner.ble.view.OnPasswordSelectedEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionClickEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.BleWifiScannerDestination import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import javax.inject.Inject @@ -91,13 +91,13 @@ class BleViewModel @Inject constructor( .onEach { installBluetoothDevice(it.value as RealServerDevice) } .launchIn(viewModelScope) - navigationManager.resultFrom(WiFiAccessPointsListId) + navigationManager.resultFrom(BleWifiScannerDestination) .mapNotNull { it as? NavigationResult.Success } - .onEach { installWifi(it.value as WifiData) } + .onEach { installWifi(it.value) } .launchIn(viewModelScope) } - fun onEvent(event: BleProvisioningViewEvent) { + fun onEvent(event: ProvisioningViewEvent) { if (event != OpenLoggerEvent) { cancelPendingJobs() } @@ -105,7 +105,7 @@ class BleViewModel @Inject constructor( OnFinishedEvent -> finish() is OnPasswordSelectedEvent -> onPasswordSelected(event.password) OnSelectDeviceClickEvent -> requestBluetoothDevice() - OnSelectWifiEvent -> navigationManager.navigateTo(WiFiAccessPointsListId) + OnSelectWifiEvent -> navigationManager.navigateTo(BleWifiScannerDestination) OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() OnShowPasswordDialog -> showPasswordDialog() diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/BleWifiScannerScreen.kt similarity index 99% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/BleWifiScannerScreen.kt index 73e20553..f06feace 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/WiFiAccessPointListsScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/view/BleWifiScannerScreen.kt @@ -80,7 +80,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun WiFiAccessPointListsScreen( +internal fun BleWifiScannerScreen( viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerViewEvent) -> Unit ) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/BleWifiScannerViewModel.kt similarity index 89% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/BleWifiScannerViewModel.kt index 0a3111fe..ad37ab7c 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/WifiScannerViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/wifi/viewmodel/BleWifiScannerViewModel.kt @@ -37,18 +37,18 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.wifi.provisioner.ble.Error -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Success +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository -import no.nordicsemi.android.wifi.provisioner.ble.view.WiFiAccessPointsListId +import no.nordicsemi.android.wifi.provisioner.ble.view.BleWifiScannerDestination import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel import javax.inject.Inject @HiltViewModel -internal class WifiScannerViewModel @Inject constructor( +internal class BleWifiScannerViewModel @Inject constructor( navigationManager: Navigator, wifiAggregator: WifiAggregator, private val repository: ProvisionerResourceRepository @@ -95,7 +95,7 @@ internal class WifiScannerViewModel @Inject constructor( override fun navigateUp(wifiData: WifiData) { viewModelScope.launch { stopScanning() - navigationManager.navigateUpWithResult(WiFiAccessPointsListId, wifiData) + navigationManager.navigateUpWithResult(BleWifiScannerDestination, wifiData) } } } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt similarity index 66% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt index 7973c2f8..324361b8 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleScreenViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt @@ -29,28 +29,28 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.view +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event -sealed interface BleProvisioningViewEvent +sealed interface ProvisioningViewEvent -data object OnSelectDeviceClickEvent : BleProvisioningViewEvent +data object OnSelectDeviceClickEvent : ProvisioningViewEvent -data object OnFinishedEvent : BleProvisioningViewEvent +data object OnFinishedEvent : ProvisioningViewEvent -data object OnProvisionNextDeviceEvent : BleProvisioningViewEvent +data object OnProvisionNextDeviceEvent : ProvisioningViewEvent -data object OnSelectWifiEvent : BleProvisioningViewEvent +data object OnSelectWifiEvent : ProvisioningViewEvent -data object OnShowPasswordDialog : BleProvisioningViewEvent +data object OnShowPasswordDialog : ProvisioningViewEvent -data object OnHidePasswordDialog : BleProvisioningViewEvent +data object OnHidePasswordDialog : ProvisioningViewEvent -data class OnPasswordSelectedEvent(val password: String) : BleProvisioningViewEvent +data class OnPasswordSelectedEvent(val password: String) : ProvisioningViewEvent -data object OnProvisionClickEvent : BleProvisioningViewEvent +data object OnProvisionClickEvent : ProvisioningViewEvent -data object OpenLoggerEvent : BleProvisioningViewEvent +data object OpenLoggerEvent : ProvisioningViewEvent -data object OnUnprovisionEvent : BleProvisioningViewEvent +data object OnUnprovisionEvent : ProvisioningViewEvent -data object OnVolatileMemoryChangedEvent : BleProvisioningViewEvent +data object OnVolatileMemoryChangedEvent : ProvisioningViewEvent diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt similarity index 96% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt index 463c5d33..0097f679 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialogEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.password +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event sealed interface PasswordDialogEvent diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt new file mode 100644 index 00000000..b75d1cbe --- /dev/null +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt @@ -0,0 +1,3 @@ +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event + +interface ViewEvent \ No newline at end of file diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt new file mode 100644 index 00000000..af0ca72b --- /dev/null +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt @@ -0,0 +1,23 @@ +package no.nordicsemi.kotlin.wifi.provisioner.feature.common.view + +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData + +/** + * ViewEntity is an interface that represents the view state of the application + * + * @property network Network data + * @property password Password of the network + * @property showPasswordDialog Show password dialog + * @property isConnected Is connected to the network + **/ +interface ViewEntity { + val network: WifiData? + val password: String? + val showPasswordDialog: Boolean? + val provisioningStatus: Resource? + val isConnected: Boolean + + fun hasFinishedWithSuccess(): Boolean +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt new file mode 100644 index 00000000..12e64c64 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.sections + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog + +@Composable +fun ActionButtonSection(viewEntity: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { + if (viewEntity.device == null) { + ActionButton(stringResource(id = R.string.start)) { + onEvent(OnProvisionNextDeviceEvent) + } + } else if(viewEntity.network == null) { + ActionButton(stringResource(id = R.string.select_wifi)) { + onEvent(OnSelectWifiEvent) + } + } else if(viewEntity.password == null) { + onEvent(OnShowPasswordDialog) + } else if(viewEntity.hasFinishedWithSuccess()) { + ActionButton(stringResource(id = R.string.next_device)) { + onEvent(OnProvisionNextDeviceEvent) + } + } else { + ActionButton(stringResource(id = R.string.provision)) { + onEvent(OnProvisionClickEvent) + } + } +} + +@Composable +private fun ActionButton(text: String, onClick: () -> Unit) { + Box(modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)) { + Button( + onClick = onClick, + modifier = Modifier + .align(Alignment.Center) + .widthIn(min = 100.dp) + ) { + Text(text = text) + } + } +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt new file mode 100644 index 00000000..2178f173 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.view + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApConnectorViewModel + +@RequiresApi(Build.VERSION_CODES.Q) +@Composable +fun SoftApConnectorScreen() { + val viewModel = hiltViewModel() + var ssid by rememberSaveable { mutableStateOf("00189C-nrf-wifiprov") } + var password by rememberSaveable { mutableStateOf("") } + var showPassword by rememberSaveable { mutableStateOf(true) } + + AlertDialog( + onDismissRequest = { }, + icon = { + Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) + }, + title = { + Text( + text = stringResource(id = R.string.setup_wifi), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + Column { + Text( + text = stringResource(id = R.string.setup_wifi_rationale), + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.size(size = 16.dp)) + OutlinedTextField(value = ssid, onValueChange = { ssid = it }) + Spacer(modifier = Modifier.size(size = 8.dp)) + OutlinedTextField( + value = password, + onValueChange = { password = it }, + visualTransformation = if (showPassword) + VisualTransformation.None + else + PasswordVisualTransformation(), + trailingIcon = { + IconButton(onClick = { showPassword = !showPassword }) { + Icon( + imageVector = if (!showPassword) + Icons.Outlined.Visibility + else Icons.Outlined.VisibilityOff, + contentDescription = null + ) + } + } + ) + } + }, + dismissButton = { + TextButton( + onClick = { + viewModel.navigateUp() + } + ) { Text(text = "Cancel") } + }, + confirmButton = { + TextButton( + onClick = { + viewModel.connect( + ssid = ssid, + password = password + ) + } + ) { Text(text = "Confirm") } + } + ) +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 9b434cf0..08d5a21d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -1,33 +1,44 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.WifiScannerViewModel +import no.nordicsemi.android.common.navigation.defineDialogDestination +import no.nordicsemi.android.wifi.provisioner.softap.SoftAp +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent /** * Created by Roshan Rajaratnam on 14/02/2024. */ - -val SoftApProvisionerDestinationId = createSimpleDestination("softap-provider-destination") -val WiFiAccessPointsDestinationId = createDestination( - name = "wifi-access-points-destination1" +val SoftApProvisionerDestination = createSimpleDestination("softap-provisioner-destination") +val SoftApConnectorDestination = createDestination( + "softap-connector-destination" +) +val SoftApWifiScannerDestination = createDestination( + name = "wifi-access-points-softap-destination" ) +@RequiresApi(Build.VERSION_CODES.Q) val SoftApProvisionerDestinations = listOf( - defineDestination(SoftApProvisionerDestinationId) { + defineDestination(SoftApProvisionerDestination) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { SoftApProvisioningScreen() } }, - defineDestination(WiFiAccessPointsDestinationId) { - val viewModel = hiltViewModel() + defineDialogDestination(SoftApConnectorDestination) { + SoftApConnectorScreen() + }, + defineDestination(SoftApWifiScannerDestination) { + val viewModel = hiltViewModel() val viewEntity by viewModel.state.collectAsStateWithLifecycle() - WiFiAccessPointsScreen(viewEntity, viewModel::onEvent) + val onEvent: (WifiScannerViewEvent) -> Unit = { viewModel.onEvent(it) } + SoftApWifiScannerScreen(viewEntity, onEvent) } ) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 140b11e9..3a89dfb1 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -31,153 +31,124 @@ package no.nordicsemi.android.wifi.provisioner.softap.view -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Visibility -import androidx.compose.material.icons.outlined.VisibilityOff -import androidx.compose.material.icons.outlined.Wifi -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Button +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.softap.sections.WifiDeviceNotSelected -import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApViewModel +import no.nordicsemi.android.wifi.provisioner.softap.sections.ActionButtonSection +import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApProvisioningViewModel +import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog +import no.nordicsemi.android.wifi.provisioner.ui.view.section.DeviceNotSelectedSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice +import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent -@RequiresApi(Build.VERSION_CODES.Q) @OptIn(ExperimentalMaterial3Api::class) @Composable fun SoftApProvisioningScreen() { - val viewModel = hiltViewModel() - LocalContext.current + val viewModel = hiltViewModel() - var ssid by rememberSaveable { mutableStateOf("0018F0-nrf-wifiprov") } - var password by rememberSaveable { mutableStateOf("") } - var showDialog by rememberSaveable { mutableStateOf(false) } - var showPassword by rememberSaveable { mutableStateOf(false) } - - Column( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 56.dp) - ) { + val state by viewModel.state.collectAsStateWithLifecycle() + val onEvent: (ProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } + Column { NordicAppBar( text = stringResource(id = R.string.label_wifi_provisioner), actions = { LoggerAppBarIcon( - onClick = { /*TODO*/ } + onClick = { viewModel.onEvent(OpenLoggerEvent) } ) }, showBackButton = true, onNavigationButtonClick = viewModel::navigateUp ) - Column( - modifier = Modifier - .weight(1f) - .padding(horizontal = 16.dp) - ) { - Spacer(modifier = Modifier.size(12.dp)) - WifiDeviceNotSelected { showDialog = true } - Spacer(modifier = Modifier.size(12.dp)) + Box(modifier = Modifier.weight(1f)) { + Content(state) { viewModel.onEvent(it) } } - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { - Button(onClick = { showDialog = true }) { - Text(text = stringResource(id = R.string.setup_wifi)) + ActionButtonSection(state, onEvent) + Spacer(modifier = Modifier.size(16.dp)) + } + + if (state.showPasswordDialog == true) { + PasswordDialog { event -> + (event as? PasswordSetDialogEvent)?.let { + onEvent(OnPasswordSelectedEvent(it.password)) } + onEvent(OnHidePasswordDialog) } } +} - if (showDialog) { - AlertDialog( - onDismissRequest = { showDialog = false }, - icon = { - Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) - }, - title = { - Text( - text = stringResource(id = R.string.setup_wifi), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.titleLarge - ) - }, - text = { - Column { - Text( - text = stringResource(id = R.string.setup_wifi_rationale), - modifier = Modifier.fillMaxWidth(), - style = MaterialTheme.typography.bodyMedium - ) - Spacer(modifier = Modifier.size(size = 16.dp)) - OutlinedTextField(value = ssid, onValueChange = { ssid = it }) - Spacer(modifier = Modifier.size(size = 8.dp)) - OutlinedTextField( - value = password, - onValueChange = { password = it }, - visualTransformation = if(showPassword) - VisualTransformation.None - else - PasswordVisualTransformation(), - trailingIcon = { - IconButton(onClick = { showPassword = !showPassword }) { - Icon( - imageVector = if (!showPassword) - Icons.Outlined.Visibility - else Icons.Outlined.VisibilityOff, - contentDescription = null - ) - } - } - ) - } - }, - dismissButton = { - TextButton( - onClick = { - showDialog = false - } - ) { Text(text = "Cancel") } - }, - confirmButton = { - TextButton( - onClick = { - showDialog = false - viewModel.connect( - ssid = ssid, - password = password - ) - } - ) { Text(text = "Confirm") } +@Composable +private fun Content(state: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(horizontal = 16.dp) + ) { + Spacer(modifier = Modifier.size(12.dp)) + + state.device?.let { + SoftApDevice(it.ssid , it.connectionInfoDomain!!.ipv4Address, true, onEvent) + } ?: DeviceNotSelectedSection(onEvent) + + Spacer(modifier = Modifier.size(12.dp)) + + if (!state.isConnected && state.device != null) { + DisconnectedDeviceStatus() + } else { + + Spacer(modifier = Modifier.size(12.dp)) + + // state.status?.let { StatusSection(it) } + + state.network?.let { + Spacer(modifier = Modifier.size(12.dp)) + + SectionTitle(text = stringResource(id = R.string.section_provisioning)) + + Spacer(modifier = Modifier.size(12.dp)) + + WifiSection(it, false, onEvent) } - ) + + state.password?.let { + Spacer(modifier = Modifier.size(10.dp)) + + PasswordSection(false, onEvent) + } + } } } + + +@Composable +private fun SectionTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApWifiScannerScreen.kt similarity index 99% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt rename to feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApWifiScannerScreen.kt index b29d0944..11b3123a 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/WifiAccessPointsScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApWifiScannerScreen.kt @@ -81,7 +81,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun WiFiAccessPointsScreen( +internal fun SoftApWifiScannerScreen( viewEntity: WifiScannerViewEntity, onEvent: (WifiScannerViewEvent) -> Unit ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt new file mode 100644 index 00000000..09e70bdd --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt @@ -0,0 +1,25 @@ +package no.nordicsemi.android.wifi.provisioner.softap.view.entity + +import no.nordicsemi.android.wifi.provisioner.softap.SoftAp +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity + +data class SoftApViewEntity( + val device: SoftAp? = null, + override val network: WifiData? = null, + override val password: String? = null, + override val showPasswordDialog: Boolean? = null, + override val provisioningStatus: Resource? = null, + override val isConnected: Boolean = true, +) : ViewEntity { + + override fun hasFinishedWithSuccess(): Boolean { + val status = (provisioningStatus as? Success)?.data + return (isConnected + && status == WifiConnectionStateDomain.CONNECTED) + || status == WifiConnectionStateDomain.CONNECTION_FAILED + } +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt new file mode 100644 index 00000000..851b7e82 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt @@ -0,0 +1,36 @@ +@file:Suppress("unused") + +package no.nordicsemi.android.wifi.provisioner.softap.viewmodel + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApConnectorDestination +import javax.inject.Inject + +/** + * Created by Roshan Rajaratnam on 15/02/2024. + */ +@HiltViewModel +class SoftApConnectorViewModel @Inject constructor( + navigationManager: Navigator, + savedStateHandle: SavedStateHandle, + private val softApManager: SoftApManager +) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle = savedStateHandle) { + + @RequiresApi(Build.VERSION_CODES.Q) + internal fun connect(ssid: String = "0018F0-nrf-wifiprov", password: String) { + viewModelScope.launch { + softApManager.connect(ssid = ssid, password = password)?.let { + navigateUpWithResult(SoftApConnectorDestination, it) + } + } + } +} + diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt new file mode 100644 index 00000000..13d46dde --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.viewmodel + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import no.nordicsemi.android.common.navigation.NavigationResult +import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.wifi.provisioner.softap.SoftAp +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApConnectorDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import javax.inject.Inject + +@HiltViewModel +class SoftApProvisioningViewModel @Inject constructor( + private val softApManager: SoftApManager, + private val navigationManager: Navigator, + savedStateHandle: SavedStateHandle, +) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { + + private val _state = MutableStateFlow(SoftApViewEntity()) + val state = _state.asStateFlow() + + init { + navigationManager.resultFrom(SoftApConnectorDestination) + .mapNotNull { it as? NavigationResult.Success } + .onEach { result -> + result.value?.let { + installSoftApDevice(it) + } + } + .launchIn(viewModelScope) + navigationManager.resultFrom(SoftApWifiScannerDestination) + .mapNotNull { it as? NavigationResult.Success } + .onEach { installWifi(it.value) } + .launchIn(viewModelScope) + } + + fun onEvent(event: ProvisioningViewEvent) { + when (event) { + OnFinishedEvent -> finish() + is OnPasswordSelectedEvent -> onPasswordSelected(event.password) + OnSelectDeviceClickEvent -> requestWifiDevice() + OnSelectWifiEvent -> navigationManager.navigateTo(SoftApWifiScannerDestination) + OnProvisionClickEvent -> provision() + OnHidePasswordDialog -> hidePasswordDialog() + OnShowPasswordDialog -> showPasswordDialog() + OpenLoggerEvent -> {}//repository.openLogger() + OnUnprovisionEvent -> cancelConfig() + OnProvisionNextDeviceEvent -> provisionNextDevice() + OnVolatileMemoryChangedEvent -> {} + } + } + + private fun provisionNextDevice() { + viewModelScope.launch { + launch { release() } + requestSoftApDevice() + delay(500) //nasty delay to prevent screen change before navigation + _state.value = SoftApViewEntity() + } + } + + private fun cancelConfig() { + + } + + private fun showPasswordDialog() { + _state.value = _state.value.copy(showPasswordDialog = true) + } + + private fun hidePasswordDialog() { + _state.value = _state.value.copy(showPasswordDialog = false) + } + + private fun finish() { + viewModelScope.launch { + release() + _state.value = SoftApViewEntity() + } + } + + private fun release() { + try { + _state.value.device?.let { + softApManager.disconnect() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun requestSoftApDevice() { + navigationManager.navigateTo(SoftApConnectorDestination) + } + + private fun requestWifiDevice() { + release() + navigationManager.navigateTo(SoftApConnectorDestination) + } + + private fun installWifi(wifiData: WifiData) { + _state.value = _state.value.copy( + network = wifiData, + password = null, + showPasswordDialog = wifiData.isPasswordRequired() + ) + } + + private fun installSoftApDevice(device: SoftAp) { + _state.value = SoftApViewEntity(device = device) + } + + private fun onPasswordSelected(password: String) { + _state.value = _state.value.copy(password = password) + } + + private fun provision() { + viewModelScope.launch { + val state = _state.value + val network = state.network + network?.let { + softApManager.provision(it.toConfig()).also { response -> + if (response.isSuccessful) { + val nsdServiceInfo = softApManager.discoverServices() + _state.value = state.copy( + device = state.device?.apply { + connectionInfoDomain = connectionInfoDomain?.copy( + ipv4Address = nsdServiceInfo.host.toString() + ) + }, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.CONNECTED + ) + ) + } else { + _state.value = state.copy( + provisioningStatus = Resource.createError( + Throwable("Provisioning failed") + ) + ) + } + } + } + } + } + + private fun WifiData.toConfig(): WifiConfigDomain { + val state = _state.value + val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo + return WifiConfigDomain( + wifiInfo, + state.password + ) + } +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt deleted file mode 100644 index 84903df7..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ /dev/null @@ -1,114 +0,0 @@ -@file:Suppress("unused") - -package no.nordicsemi.android.wifi.provisioner.softap.viewmodel - -import android.os.Build -import android.util.Log -import androidx.annotation.RequiresApi -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch -import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel -import no.nordicsemi.android.wifi.provisioner.softap.ProvisioningState -import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.softap.view.WiFiAccessPointsDestinationId -import okhttp3.OkHttpClient -import javax.inject.Inject - -/** - * Created by Roshan Rajaratnam on 15/02/2024. - */ -@HiltViewModel -class SoftApViewModel @Inject constructor( - navigator: Navigator, - savedStateHandle: SavedStateHandle, - private val softApManager: SoftApManager, - private val okHttpClient: OkHttpClient -) : SimpleNavigationViewModel(navigator = navigator, savedStateHandle = savedStateHandle) { - init { - softApManager.provisioningState.onEach { - when (it) { - ProvisioningState.Disconnected -> {} - ProvisioningState.Connecting -> {} - ProvisioningState.Connected -> { - discoverServices() - } - - ProvisioningState.Provisioning -> {} - ProvisioningState.ProvisioningComplete -> {} - } - }.launchIn(viewModelScope) - } - - override fun onCleared() { - super.onCleared() - softApManager.disconnect() - } - - @RequiresApi(Build.VERSION_CODES.Q) - internal fun connect(ssid: String = "0018F0-nrf-wifiprov", password: String) { - softApManager.connect(ssid = ssid, password = password) - } - - private fun discoverServices() { - viewModelScope.launch { - softApManager.discoverServices() - navigateTo(WiFiAccessPointsDestinationId) - } - } - - private fun listSsids() { - val handler = CoroutineExceptionHandler { _, t -> - Log.e("AAAA", "$t") - } - viewModelScope.launch(handler) { - val result = softApManager.listSsids() - Log.d("AAAA", "Results: ${result.results}") - result.results.forEach { - it.wifiInfo?.takeIf { wifiInfo -> - wifiInfo.ssid == "OnHub" - }?.let { wifiInfo -> - Log.d("AAAA", "Found the device!") - val wifiConfig = WifiConfigDomain( - info = wifiInfo, - passphrase = "newbird379", - ) - Log.d("AAAA", "WifiConfig: $wifiConfig") - provision(wifiConfig) - return@forEach - } - } - } - } - - private fun provision(config: WifiConfigDomain) { - - val handler = CoroutineExceptionHandler { _, t -> - Log.e("AAAA", "$t") - } - viewModelScope.launch(handler) { - try { - softApManager.provision(config = config).also { response -> - if (response.isSuccessful) { - softApManager.disconnect() - softApManager.discoverServices() - } - } - } catch (exception: Exception) { - // TODO This workaround was added to start the service discovery again once the - // provisioning is completed. This has to be cleaned up once the fw disconnects - // gracefully. - Log.e("AAAA", "Error: $exception") - softApManager.disconnect() - softApManager.discoverServices() - } - } - } -} - diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt similarity index 92% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt rename to feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt index 64f839a0..87f839a9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/WifiScannerViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt @@ -38,14 +38,14 @@ import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.view.WiFiAccessPointsDestinationId +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel import javax.inject.Inject @HiltViewModel -internal class WifiScannerViewModel @Inject constructor( +internal class SoftApWifiScannerViewModel @Inject constructor( navigationManager: Navigator, wifiAggregator: WifiAggregator, private val softApManager: SoftApManager @@ -62,6 +62,7 @@ internal class WifiScannerViewModel @Inject constructor( val handler = CoroutineExceptionHandler { _, throwable -> Log.e("AAAA", "$throwable") } + viewModelScope.launch(handler) { val ssids = softApManager.listSsids() val state = _state.value @@ -78,6 +79,6 @@ internal class WifiScannerViewModel @Inject constructor( } override fun navigateUp(wifiData: WifiData) { - navigationManager.navigateUpWithResult(WiFiAccessPointsDestinationId, wifiData) + navigationManager.navigateUpWithResult(SoftApWifiScannerDestination, wifiData) } } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index c9a776d2..ebd89a9e 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -20,4 +20,9 @@ Any Icon indicating wifi and it\'s authentication method. + + Device status + Provisioning data + Upload status + \ No newline at end of file diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt similarity index 93% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt index 937b5d1e..70b9be67 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/password/PasswordDialog.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt @@ -29,13 +29,12 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.password +package no.nordicsemi.android.wifi.provisioner.ui import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField @@ -47,9 +46,10 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation -import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.DismissEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordDialogEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent -@OptIn(ExperimentalMaterial3Api::class) @Composable fun PasswordDialog(onEvent: (PasswordDialogEvent) -> Unit) { val passwordField = rememberSaveable { mutableStateOf("") } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt similarity index 87% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt index 7eefbb38..6024bacf 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.view +package no.nordicsemi.android.wifi.provisioner.ui.view import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.SignalWifi4Bar @@ -39,11 +39,12 @@ import androidx.compose.material.icons.filled.WifiFind import androidx.compose.material.icons.outlined.SignalWifiStatusbarConnectedNoInternet4 import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionFailureReasonDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain -import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionFailureReasonDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain +import no.nordicsemi.android.wifi.provisioner.ui.R -internal fun WifiConnectionStateDomain?.toImageVector() = when (this) { +@Composable +fun WifiConnectionStateDomain?.toImageVector() = when (this) { WifiConnectionStateDomain.DISCONNECTED -> Icons.Outlined.SignalWifiStatusbarConnectedNoInternet4 WifiConnectionStateDomain.AUTHENTICATION, WifiConnectionStateDomain.ASSOCIATION, @@ -54,7 +55,7 @@ internal fun WifiConnectionStateDomain?.toImageVector() = when (this) { } @Composable -internal fun WifiConnectionStateDomain?.toDisplayString() = when (this) { +fun WifiConnectionStateDomain?.toDisplayString() = when (this) { WifiConnectionStateDomain.DISCONNECTED -> R.string.wifi_status_disconnected WifiConnectionStateDomain.AUTHENTICATION -> R.string.wifi_status_authentication WifiConnectionStateDomain.ASSOCIATION -> R.string.wifi_status_association @@ -65,7 +66,7 @@ internal fun WifiConnectionStateDomain?.toDisplayString() = when (this) { }.let { stringResource(id = it) } @Composable -internal fun WifiConnectionFailureReasonDomain.toDisplayString() = when (this) { +fun WifiConnectionFailureReasonDomain.toDisplayString() = when (this) { WifiConnectionFailureReasonDomain.AUTH_ERROR -> R.string.error_auth WifiConnectionFailureReasonDomain.NETWORK_NOT_FOUND -> R.string.error_network_not_found WifiConnectionFailureReasonDomain.TIMEOUT -> R.string.error_timeout diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt similarity index 71% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt index 18c662a7..eb380eae 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt @@ -29,53 +29,59 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.PhoneAndroid +import androidx.compose.material.icons.outlined.Router import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import no.nordicsemi.android.common.theme.NordicTheme -import no.nordicsemi.android.kotlin.ble.core.ServerDevice -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnProvisionNextDeviceEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectDeviceClickEvent -import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @Composable -internal fun DeviceSection( - device: ServerDevice?, +fun BluetoothDevice( + name: String?, + address: String, isEditable: Boolean = false, - onEvent: (BleProvisioningViewEvent) -> Unit + onEvent: (ProvisioningViewEvent) -> Unit ) { - if (device == null) { - DeviceNotSelectedSection(onEvent) - } else { - BluetoothDevice(device, isEditable, onEvent) - } + ClickableDataItem( + imageVector = Icons.Outlined.PhoneAndroid, + title = name ?: address, + isEditable = isEditable, + description = address, + onClick = { onEvent(OnSelectDeviceClickEvent) }, + buttonText = stringResource(id = R.string.change_device) + ) } + @Composable -private fun BluetoothDevice( - device: ServerDevice, +fun SoftApDevice( + name: String?, + address: String, isEditable: Boolean = false, - onEvent: (BleProvisioningViewEvent) -> Unit + onEvent: (ProvisioningViewEvent) -> Unit ) { ClickableDataItem( - imageVector = Icons.Outlined.PhoneAndroid, - title = device.name ?: device.address, + imageVector = Icons.Outlined.Router, + title = name ?: address, isEditable = isEditable, - description = device.address, + description = address, onClick = { onEvent(OnSelectDeviceClickEvent) }, buttonText = stringResource(id = R.string.change_device) ) } @Composable -private fun DeviceNotSelectedSection( - onEvent: (BleProvisioningViewEvent) -> Unit +fun DeviceNotSelectedSection( + onEvent: (ProvisioningViewEvent) -> Unit ) { ClickableDataItem( imageVector = Icons.Outlined.PhoneAndroid, diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt similarity index 94% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt index 0979d298..956dea96 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt @@ -29,14 +29,14 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.LinkOff import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.DataItem +import no.nordicsemi.android.wifi.provisioner.ui.R @Composable fun DisconnectedDeviceStatus() { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt similarity index 85% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt index 85ae6237..3b0e344e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt @@ -29,19 +29,19 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Password import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.R @Composable -internal fun PasswordSection(isEditable: Boolean = false, onEvent: (BleProvisioningViewEvent) -> Unit) { +fun PasswordSection(isEditable: Boolean = false, onEvent: (ProvisioningViewEvent) -> Unit) { ClickableDataItem( imageVector = Icons.Outlined.Password, title = stringResource(id = R.string.password), diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt similarity index 93% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt index d723a6e5..3706003e 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -46,18 +46,18 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.common.theme.view.ProgressItem import no.nordicsemi.android.common.theme.view.ProgressItemStatus -import no.nordicsemi.android.wifi.provisioner.ble.Error -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.Success -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain -import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.android.wifi.provisioner.ui.view.toDisplayString +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success @Composable -internal fun ProvisioningSection(status: Resource) { +fun ProvisioningSection(status: Resource) { val lastStatus = rememberSaveable { mutableStateOf(WifiConnectionStateDomain.DISCONNECTED) } when (status) { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt similarity index 86% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt index 4782bcb5..c948025f 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons @@ -38,17 +38,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.feature.ble.R -import no.nordicsemi.android.wifi.provisioner.ble.Error -import no.nordicsemi.android.wifi.provisioner.ble.Loading -import no.nordicsemi.android.wifi.provisioner.ble.Resource -import no.nordicsemi.android.wifi.provisioner.ble.Success import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem +import no.nordicsemi.android.wifi.provisioner.ui.R +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error @Composable -internal fun UnprovisioningSection(status: Resource) { +fun UnprovisioningSection(status: Resource) { when (status) { is Error -> ErrorItem(status.error) is Loading -> LoadingItem(modifier = Modifier.padding(vertical = 8.dp)) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt similarity index 89% rename from feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt rename to feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt index f6f0ccc7..d2f8b6d7 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt @@ -29,24 +29,24 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.sections +package no.nordicsemi.android.wifi.provisioner.ui.view.section import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningViewEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnSelectWifiEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem +import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector @Composable -internal fun WifiSection( +fun WifiSection( record: WifiData, isEditable: Boolean = false, - onEvent: (BleProvisioningViewEvent) -> Unit + onEvent: (ProvisioningViewEvent) -> Unit ) { Column { ClickableDataItem( diff --git a/feature/ble/src/main/res/drawable/ic_upload_wifi.xml b/feature/ui/src/main/res/drawable/ic_upload_wifi.xml similarity index 100% rename from feature/ble/src/main/res/drawable/ic_upload_wifi.xml rename to feature/ui/src/main/res/drawable/ic_upload_wifi.xml diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 8edaba99..bc4cecfb 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -1,16 +1,58 @@ - Icon representing data available in the section. - Unknown Error + Change Sort by: Name RSSI - Select Wi-Fi - Clear + Device status + Provisioning data + Upload status + + Unknown error + + 1. Make sure the device is turned on and is connected to a power source. + + Unprovisioned + Start + Select device + Next device + Finish + Set password + Password + **** **** Dismiss + Accept + Clear + + Device status + Disconnected + Wi-Fi status + Selected Wi-Fi + Start provisioning + Version + Scanning error + Unprovision + Select password + Provision + Provisioning status + Unrovisioning status + Success + + Icon representing data available in the section. + Connecting + Authentication + Association + Obtaining IP + Connected + Disconnected + Unprovisioned + Error occurred during provisioning. + Icon indicating wifi and it\'s authentication method. + + Wi-Fi IPv4: %s SSID: %s @@ -21,4 +63,35 @@ 2.4 GHz 5 GHz Any + + Authentication error. + The specified network could not be find. + Timeout occurred. + Could not obtain IP from provided provisioning information. + Could not connect to provisioned network. + + Connection info + Wi-Fi info + + Scan params + Passive: %s + Period: %s [ms] + Group channels: %s + + Hide password + Show password + Version: %s (%s) + + Disconnected + Authentication + Association + Obtaining IP + Result + Connected + Connection failed + + V %d + Select Wi-Fi + + Persistent storage \ No newline at end of file diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt index ccf99d6d..56f44281 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt @@ -34,11 +34,11 @@ package no.nordicsemi.android.wifi.provisioner.ble import android.annotation.SuppressLint import android.bluetooth.BluetoothDevice import android.content.Context -import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.internal.ResponseErrorException import no.nordicsemi.android.wifi.provisioner.ble.internal.NotificationTimeoutException diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt index 4b972b1f..6274c5d0 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt @@ -36,11 +36,11 @@ import android.bluetooth.BluetoothDevice import android.content.Context import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import no.nordicsemi.android.wifi.provisioner.ble.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.VersionDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConnectionStateDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ble.domain.toApi import no.nordicsemi.android.wifi.provisioner.ble.domain.toDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt index 1e558443..3e9697ac 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt +++ b/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt @@ -42,7 +42,12 @@ import no.nordicsemi.android.wifi.provisioner.ble.proto.ScanRecord import no.nordicsemi.android.wifi.provisioner.ble.proto.WifiInfo import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanParamsDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionFailureReasonDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain import okio.ByteString diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ConnectionInfoDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ConnectionInfoDomain.kt index f9a363ee..f67567d0 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ConnectionInfoDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ConnectionInfoDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain data class ConnectionInfoDomain( val ipv4Address: String diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/DeviceStatusDomain.kt similarity index 92% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/DeviceStatusDomain.kt index 1ae4f08f..573256f1 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/DeviceStatusDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/DeviceStatusDomain.kt @@ -29,11 +29,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain data class DeviceStatusDomain( val wifiState: WifiConnectionStateDomain?, - val wifiInfo: no.nordicsemi.kotlin.wifi.provisioner.domain.WifiInfoDomain?, + val wifiInfo: WifiInfoDomain?, val connectionInfo: ConnectionInfoDomain?, val scanParams: ScanParamsDomain? ) { diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanParamsDomain.kt similarity index 93% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanParamsDomain.kt index c71dce1e..881a2549 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ScanParamsDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/ScanParamsDomain.kt @@ -29,9 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain - -import no.nordicsemi.kotlin.wifi.provisioner.domain.BandDomain +package no.nordicsemi.kotlin.wifi.provisioner.domain data class ScanParamsDomain( val band: BandDomain, diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionFailureReasonDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionFailureReasonDomain.kt index 1163eea9..89bd1dab 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionFailureReasonDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionFailureReasonDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain enum class WifiConnectionFailureReasonDomain(val id: Int) { AUTH_ERROR(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionStateDomain.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionStateDomain.kt index 3f337734..af39fcfc 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConnectionStateDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/WifiConnectionStateDomain.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble.domain +package no.nordicsemi.kotlin.wifi.provisioner.domain enum class WifiConnectionStateDomain(val id: Int) { DISCONNECTED(0), diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/resource/Resource.kt similarity index 96% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt rename to lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/resource/Resource.kt index 9d498a73..40c95b7f 100644 --- a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Resource.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/resource/Resource.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ble +package no.nordicsemi.kotlin.wifi.provisioner.domain.resource sealed interface Resource { diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 291d9cff..b92837b1 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -107,6 +107,8 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage */ internal fun stopDiscovery() { nsdManager.stopServiceDiscovery(nsdListener) + if(mutex.isLocked) + mutex.unlock() } internal companion object { diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt new file mode 100644 index 00000000..ef7fdf44 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt @@ -0,0 +1,13 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain + +/** + * WifiDevice class represents a Wi-Fi network that the device should connect to. + */ +data class SoftAp( + val ssid: String, + val password: String? +) { + var connectionInfoDomain: ConnectionInfoDomain? = null +} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index e75dfbe2..36625700 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -14,10 +14,12 @@ import androidx.annotation.RequiresApi import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain +import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain import javax.inject.Inject /** @@ -43,6 +45,8 @@ class SoftApManager @Inject constructor( private val _discoveredServices = mutableListOf() private var discoveredService: NsdServiceInfo? = null + private val mutex = Mutex(true) + private var isConnected = false private val networkCallback = object : ConnectivityManager.NetworkCallback() { @@ -52,22 +56,27 @@ class SoftApManager @Inject constructor( // do success processing here.. try { if (connectivityManager.bindProcessToNetwork(network)) { + isConnected = true Log.d( "AAAA", "Link properties ${ connectivityManager.getLinkProperties(network)?.toString() }" ) - _provisioningState.value = ProvisioningState.Connected + // _provisioningState.value = ProvisioningState.Connected() } else { disconnect() } } catch (e: Exception) { + disconnect() Log.e("AAAA", "Error: $e") + } finally { + mutex.unlock() } } override fun onUnavailable() { // do failure processing here.. + mutex.unlock() Log.d("AAAA", "Something went wrong!") } } @@ -80,7 +89,8 @@ class SoftApManager @Inject constructor( * the SSID or the passphrase of the network that the device must be provisioned into. */ @RequiresApi(Build.VERSION_CODES.Q) - fun connect(ssid: String, password: String = "") { + suspend fun connect(ssid: String, password: String = ""): SoftAp? { + isConnected = false _provisioningState.value = ProvisioningState.Connecting val specifier = WifiNetworkSpecifier.Builder() .setSsid(ssid) @@ -93,6 +103,11 @@ class SoftApManager @Inject constructor( .setNetworkSpecifier(specifier) .build() connectivityManager.requestNetwork(request, networkCallback) + mutex.lock() + val service = discoverServices() + return if (isConnected) SoftAp(ssid = ssid, password = password).apply { + connectionInfoDomain = ConnectionInfoDomain(ipv4Address = service.host.toString()) + } else null } /** From 558734da19dfcc5ff1f8113439fb23ad44b82e76 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 01:16:50 +0200 Subject: [PATCH 048/101] WIP: Unifying BLE and Wifi provisioner UI --- .../wifi/provisioner/ble/sections/ActionButtonSection.kt | 3 +-- .../kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index 79de6fff..2f64d84c 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -43,7 +43,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent @@ -51,7 +50,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNex import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @Composable fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt deleted file mode 100644 index b75d1cbe..00000000 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event - -interface ViewEvent \ No newline at end of file From 8a513e00adf07d48b9c301cfc70962d09b0acdd6 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 13:12:50 +0200 Subject: [PATCH 049/101] WIP: Unifying BLE and Wifi provisioner UI --- .../feature/common/view/ViewEntity.kt | 3 ++ .../softap/view/entity/SoftApViewEntity.kt | 4 +++ .../provisioner/softap/ProvisioningState.kt | 34 ------------------- .../wifi/provisioner/softap/SoftApManager.kt | 8 ----- 4 files changed, 7 insertions(+), 42 deletions(-) delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt index af0ca72b..c4493e3e 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt @@ -19,5 +19,8 @@ interface ViewEntity { val provisioningStatus: Resource? val isConnected: Boolean + /** + * Check if the provisioning has finished successfully. + */ fun hasFinishedWithSuccess(): Boolean } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt index 09e70bdd..c481b40b 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt @@ -7,6 +7,9 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity +/** + * SoftApViewEntity is a data class that represents the view state of the SoftAp provisioning screen + */ data class SoftApViewEntity( val device: SoftAp? = null, override val network: WifiData? = null, @@ -14,6 +17,7 @@ data class SoftApViewEntity( override val showPasswordDialog: Boolean? = null, override val provisioningStatus: Resource? = null, override val isConnected: Boolean = true, + val isAuthorized: Boolean = false, ) : ViewEntity { override fun hasFinishedWithSuccess(): Boolean { diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt deleted file mode 100644 index de7f1ab2..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/ProvisioningState.kt +++ /dev/null @@ -1,34 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap - -/** - * Created by Roshan Rajaratnam on 23/02/2024. - * - * Defines the WifiNetworkState - */ -sealed class ProvisioningState { - - /** - * State when connected to a Unprovisioned Wifi Node. - */ - data object Disconnected : ProvisioningState() - - /** - * State when connected to a Unprovisioned Wifi Node. - */ - data object Connecting : ProvisioningState() - - /** - * State when connected to a Unprovisioned Wifi Node. - */ - data object Connected : ProvisioningState() - - /** - * State when connected to a Unprovisioned Wifi Node - */ - data object Provisioning : ProvisioningState() - - /** - * State when Disconnected from an Unprovisioned Wifi Node - */ - data object ProvisioningComplete : ProvisioningState() -} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 36625700..157bae59 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -30,7 +30,6 @@ import javax.inject.Inject * @property nsdListener Network service discovery listener. * @property wifiService WifiServer api. * @property coroutineDispatcher Coroutine dispatcher. - * @property provisioningState Provisioning state. * @constructor Create empty SoftApManager. */ class SoftApManager @Inject constructor( @@ -39,10 +38,6 @@ class SoftApManager @Inject constructor( private val wifiService: WifiService, private val coroutineDispatcher: CoroutineDispatcher ) { - private var _provisioningState = - MutableStateFlow(ProvisioningState.Disconnected) - val provisioningState = _provisioningState.asStateFlow() - private val _discoveredServices = mutableListOf() private var discoveredService: NsdServiceInfo? = null private val mutex = Mutex(true) @@ -62,7 +57,6 @@ class SoftApManager @Inject constructor( connectivityManager.getLinkProperties(network)?.toString() }" ) - // _provisioningState.value = ProvisioningState.Connected() } else { disconnect() } @@ -91,7 +85,6 @@ class SoftApManager @Inject constructor( @RequiresApi(Build.VERSION_CODES.Q) suspend fun connect(ssid: String, password: String = ""): SoftAp? { isConnected = false - _provisioningState.value = ProvisioningState.Connecting val specifier = WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(password) @@ -118,7 +111,6 @@ class SoftApManager @Inject constructor( connectivityManager.bindProcessToNetwork(null) } connectivityManager.unregisterNetworkCallback(networkCallback) - _provisioningState.value = ProvisioningState.Disconnected } /** From 7e6d09ced315b23a6491510287c14955eadba285 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 13:13:28 +0200 Subject: [PATCH 050/101] WIP: Unifying BLE and Wifi provisioner UI, fix imports --- .../nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 157bae59..924b4b72 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -12,8 +12,6 @@ import android.os.Build import android.util.Log import androidx.annotation.RequiresApi import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain From 2d422964c37b6729d74a8f7a8261a3661ffab2a4 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 13:52:17 +0200 Subject: [PATCH 051/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../ble/sections/ActionButtonSection.kt | 2 +- .../ble/sections/VolatileMemorySwitch.kt | 2 +- .../ble/view/BleProvisioningScreen.kt | 13 ++++++------- .../ble/view/BleProvisioningViewEvent.kt | 9 +++++++++ .../provisioner/ble/viewmodel/BleViewModel.kt | 6 +++--- .../{BleScreenViewEvent.kt => ViewEvent.kt} | 9 +-------- .../softap/view/SoftApProvisioningScreen.kt | 8 +++++--- .../viewmodel/SoftApProvisioningViewModel.kt | 10 ---------- .../ui/view/section/DeviceSection.kt | 17 +++++++++++++++-- 9 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningViewEvent.kt rename feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/{BleScreenViewEvent.kt => ViewEvent.kt} (90%) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index 2f64d84c..1bb89a43 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -43,13 +43,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity +import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent import no.nordicsemi.android.wifi.provisioner.ui.R import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt index 6597ffcd..ec1a7348 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/VolatileMemorySwitch.kt @@ -46,8 +46,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent import no.nordicsemi.android.wifi.provisioner.feature.ble.R @Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index e3106ccf..27fc4fc0 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -50,24 +50,23 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar -import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent import no.nordicsemi.android.wifi.provisioner.ble.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection import no.nordicsemi.android.wifi.provisioner.ble.sections.StatusSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.UnprovisioningSection import no.nordicsemi.android.wifi.provisioner.ble.sections.VersionSection import no.nordicsemi.android.wifi.provisioner.ble.sections.VolatileMemorySwitch import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.view.section.BluetoothDevice -import no.nordicsemi.android.wifi.provisioner.ui.view.section.DeviceNotSelectedSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.BluetoothDeviceNotSelected import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.UnprovisioningSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @OptIn(ExperimentalMaterial3Api::class) @@ -115,7 +114,7 @@ private fun Content(state: BleViewEntity, onEvent: (ProvisioningViewEvent) -> Un Spacer(modifier = Modifier.size(12.dp)) if (state.device == null) { - DeviceNotSelectedSection(onEvent) + BluetoothDeviceNotSelected(onEvent = onEvent) } else { BluetoothDevice(state.device.name, state.device.address, !state.isRunning(), onEvent) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningViewEvent.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningViewEvent.kt new file mode 100644 index 00000000..ccd0538b --- /dev/null +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningViewEvent.kt @@ -0,0 +1,9 @@ +package no.nordicsemi.android.wifi.provisioner.ble.view + +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent + +data object OpenLoggerEvent : ProvisioningViewEvent + +data object OnUnprovisionEvent : ProvisioningViewEvent + +data object OnVolatileMemoryChangedEvent : ProvisioningViewEvent \ No newline at end of file diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 9cd0a247..236724fe 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -63,12 +63,12 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNex import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent import no.nordicsemi.android.wifi.provisioner.ble.view.BleWifiScannerDestination import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent import javax.inject.Inject @HiltViewModel diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt similarity index 90% rename from feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt rename to feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt index 324361b8..bfa023ad 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/BleScreenViewEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/ViewEvent.kt @@ -30,8 +30,7 @@ */ package no.nordicsemi.kotlin.wifi.provisioner.feature.common.event - -sealed interface ProvisioningViewEvent +interface ProvisioningViewEvent data object OnSelectDeviceClickEvent : ProvisioningViewEvent @@ -48,9 +47,3 @@ data object OnHidePasswordDialog : ProvisioningViewEvent data class OnPasswordSelectedEvent(val password: String) : ProvisioningViewEvent data object OnProvisionClickEvent : ProvisioningViewEvent - -data object OpenLoggerEvent : ProvisioningViewEvent - -data object OnUnprovisionEvent : ProvisioningViewEvent - -data object OnVolatileMemoryChangedEvent : ProvisioningViewEvent diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 3a89dfb1..b059b3b7 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -38,6 +38,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Router import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -55,10 +57,10 @@ import no.nordicsemi.android.wifi.provisioner.softap.sections.ActionButtonSectio import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApProvisioningViewModel import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog -import no.nordicsemi.android.wifi.provisioner.ui.view.section.DeviceNotSelectedSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice +import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSelected import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent @@ -111,8 +113,8 @@ private fun Content(state: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Spacer(modifier = Modifier.size(12.dp)) state.device?.let { - SoftApDevice(it.ssid , it.connectionInfoDomain!!.ipv4Address, true, onEvent) - } ?: DeviceNotSelectedSection(onEvent) + SoftApDevice(it.ssid, it.connectionInfoDomain!!.ipv4Address, true, onEvent) + } ?: SoftApDeviceNotSelected(onEvent = onEvent) Spacer(modifier = Modifier.size(12.dp)) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 13d46dde..61d9e06d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -61,9 +61,6 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNex import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnUnprovisionEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnVolatileMemoryChangedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent import javax.inject.Inject @@ -101,10 +98,7 @@ class SoftApProvisioningViewModel @Inject constructor( OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() OnShowPasswordDialog -> showPasswordDialog() - OpenLoggerEvent -> {}//repository.openLogger() - OnUnprovisionEvent -> cancelConfig() OnProvisionNextDeviceEvent -> provisionNextDevice() - OnVolatileMemoryChangedEvent -> {} } } @@ -117,10 +111,6 @@ class SoftApProvisioningViewModel @Inject constructor( } } - private fun cancelConfig() { - - } - private fun showPasswordDialog() { _state.value = _state.value.copy(showPasswordDialog = true) } diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt index eb380eae..1a97914c 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt @@ -35,6 +35,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.PhoneAndroid import androidx.compose.material.icons.outlined.Router import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import no.nordicsemi.android.common.theme.NordicTheme @@ -80,11 +81,23 @@ fun SoftApDevice( } @Composable -fun DeviceNotSelectedSection( +fun SoftApDeviceNotSelected(onEvent: (ProvisioningViewEvent) -> Unit) { + DeviceNotSelectedSection(imageVector = Icons.Outlined.Router, onEvent = onEvent) +} + +@Composable +fun BluetoothDeviceNotSelected(onEvent: (ProvisioningViewEvent) -> Unit) { + DeviceNotSelectedSection(imageVector = Icons.Outlined.PhoneAndroid, onEvent = onEvent) +} + + +@Composable +private fun DeviceNotSelectedSection( + imageVector: ImageVector = Icons.Outlined.PhoneAndroid, onEvent: (ProvisioningViewEvent) -> Unit ) { ClickableDataItem( - imageVector = Icons.Outlined.PhoneAndroid, + imageVector = imageVector, title = "Not selected", isEditable = false, description = "Please select a device to provision", From ef6d5abde81f36274d468685e6289b4bcabe0672 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 25 Apr 2024 13:58:29 +0200 Subject: [PATCH 052/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../wifi/provisioner/softap/view/SoftApProvisioningScreen.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index b059b3b7..c2653fbf 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -38,8 +38,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Router import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -64,7 +62,6 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSel import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OpenLoggerEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent @@ -80,7 +77,7 @@ fun SoftApProvisioningScreen() { text = stringResource(id = R.string.label_wifi_provisioner), actions = { LoggerAppBarIcon( - onClick = { viewModel.onEvent(OpenLoggerEvent) } + onClick = { } ) }, showBackButton = true, From 148f72e365fa4669f6fa75bde32fcb995452c81e Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 13:52:22 +0200 Subject: [PATCH 053/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../provisioner/ble/view/BleViewEntity.kt | 2 +- .../common/event/PasswordDialogEvent.kt | 2 +- .../feature/common/view/ViewEntity.kt | 2 + .../softap/di/SoftApManagerModule.kt | 22 ++ .../softap/sections/ActionButtonSection.kt | 6 +- .../softap/sections/WifiSection.kt | 2 +- .../softap/view/SoftApConnectorDialog.kt | 137 ++++++++++++ .../softap/view/SoftApConnectorScreen.kt | 135 ----------- .../softap/view/SoftApDestinations.kt | 6 - .../softap/view/SoftApProvisioningScreen.kt | 43 +++- .../view/SoftApProvisioningViewEvent.kt | 10 + .../softap/view/entity/SoftApViewEntity.kt | 11 +- .../viewmodel/SoftApConnectorViewModel.kt | 36 --- .../viewmodel/SoftApProvisioningViewModel.kt | 90 ++++---- .../softap/src/main/res/values/strings.xml | 4 +- lib/softap/provisioner/build.gradle.kts | 5 +- .../wifi/provisioner/softap/HostName.kt | 34 +++ .../softap/NetworkServiceDiscoveryListener.kt | 138 +++++------- .../softap/PassphraseConfiguration.kt | 9 + .../android/wifi/provisioner/softap/SoftAp.kt | 13 +- .../wifi/provisioner/softap/SoftApManager.kt | 209 +++++++++++------- ...ervice.kt => SoftApProvisioningService.kt} | 2 +- .../softap/di/DispatchersModule.kt | 37 ---- .../softap/di/SoftApManagerModule.kt | 34 --- .../softap/di/WifiServiceModule.kt | 108 --------- 25 files changed, 536 insertions(+), 561 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt rename lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/{WifiService.kt => SoftApProvisioningService.kt} (94%) delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt delete mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt index 2eb663af..1caf63cf 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleViewEntity.kt @@ -74,7 +74,7 @@ data class BleViewEntity( || unprovisioningStatus is Loading } - fun hasFinished(): Boolean { + override fun hasFinished(): Boolean { val status = (provisioningStatus as? Success)?.data return !isConnected || status == WifiConnectionStateDomain.CONNECTED diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt index 0097f679..f5a4ad8d 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/event/PasswordDialogEvent.kt @@ -35,4 +35,4 @@ sealed interface PasswordDialogEvent data class PasswordSetDialogEvent(val password: String) : PasswordDialogEvent -object DismissEvent : PasswordDialogEvent +data object DismissEvent : PasswordDialogEvent diff --git a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt index c4493e3e..351e552b 100644 --- a/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt +++ b/feature/common/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/feature/common/view/ViewEntity.kt @@ -19,6 +19,8 @@ interface ViewEntity { val provisioningStatus: Resource? val isConnected: Boolean + fun hasFinished(): Boolean + /** * Check if the provisioning has finished successfully. */ diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt new file mode 100644 index 00000000..12ab482b --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt @@ -0,0 +1,22 @@ +package no.nordicsemi.android.wifi.provisioner.softap.di + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import javax.inject.Singleton + +/** + * Created by Roshan Rajaratnam on 22/02/2024. + */ +@Module +@InstallIn(SingletonComponent::class) +object SoftApManagerModule { + + @Provides + @Singleton + fun provideSoftApManager(@ApplicationContext context: Context) = SoftApManager(context = context) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt index 12e64c64..4982c5ae 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt @@ -61,8 +61,10 @@ fun ActionButtonSection(viewEntity: SoftApViewEntity, onEvent: (ProvisioningView onEvent(OnSelectWifiEvent) } } else if(viewEntity.password == null) { - onEvent(OnShowPasswordDialog) - } else if(viewEntity.hasFinishedWithSuccess()) { + ActionButton( stringResource(id = R.string.password_select)) { + onEvent(OnShowPasswordDialog) + } + } else if(viewEntity.hasFinished()) { ActionButton(stringResource(id = R.string.next_device)) { onEvent(OnProvisionNextDeviceEvent) } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt index 49db0149..aa43bf22 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt @@ -20,6 +20,6 @@ private fun WifiNotSelectedSection( isEditable = false, description = "Please select a device to provision", onClick = onClick, - buttonText = stringResource(id = R.string.setup_wifi) + buttonText = stringResource(id = R.string.soft_ap) ) } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt new file mode 100644 index 00000000..d1f9d62e --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -0,0 +1,137 @@ +package no.nordicsemi.android.wifi.provisioner.softap.view + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration + + +@Composable +internal fun SoftApConnectorDialog( + isNetworkServiceDiscoveryCompleted: Boolean?, + connect: (String, PassphraseConfiguration) -> Unit, + dismiss: () -> Unit +) { + var ssid by rememberSaveable { mutableStateOf("nrf-wifiprov") } + var password by rememberSaveable { mutableStateOf("") } + var showButtons by rememberSaveable { + mutableStateOf(true) + } + + AlertDialog( + onDismissRequest = dismiss, + icon = { Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) }, + title = { + Text( + text = stringResource(id = R.string.soft_ap), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + if (isNetworkServiceDiscoveryCompleted == null) { + showButtons = true + SoftApConnectorContent( + ssid = ssid, + password = password, + onSsidChange = { ssid = it }, + onPasswordChange = { password = it }, + onShowPassword = {} + ) + } else if (!isNetworkServiceDiscoveryCompleted) { + showButtons = false + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator() + } + } else { + showButtons = true + } + }, + dismissButton = { + if(showButtons) { + TextButton(onClick = dismiss) { + Text(text = "Cancel") + } + } + }, + confirmButton = { + if(showButtons) { + TextButton(onClick = { connect(ssid, Open) }) { + Text(text = "Confirm") + } + } + } + ) +} + +@Composable +private fun SoftApConnectorContent( + ssid: String, + password: String, + onSsidChange: (String) -> Unit, + onPasswordChange: (String) -> Unit, + onShowPassword: () -> Unit +) { + var showPassword by rememberSaveable { mutableStateOf(true) } + Column { + Text( + text = stringResource(id = R.string.softap_rationale), + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.size(size = 16.dp)) + OutlinedTextField(value = ssid, onValueChange = onSsidChange) + Spacer(modifier = Modifier.size(size = 8.dp)) + OutlinedTextField( + value = password, + onValueChange = onPasswordChange, + visualTransformation = if (showPassword) + VisualTransformation.None + else + PasswordVisualTransformation(), + trailingIcon = { + IconButton(onClick = { showPassword = !showPassword }) { + Icon( + imageVector = if (!showPassword) + Icons.Outlined.Visibility + else Icons.Outlined.VisibilityOff, + contentDescription = null + ) + } + } + ) + } +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt deleted file mode 100644 index 2178f173..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorScreen.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.view - -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Visibility -import androidx.compose.material.icons.outlined.VisibilityOff -import androidx.compose.material.icons.outlined.Wifi -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApConnectorViewModel - -@RequiresApi(Build.VERSION_CODES.Q) -@Composable -fun SoftApConnectorScreen() { - val viewModel = hiltViewModel() - var ssid by rememberSaveable { mutableStateOf("00189C-nrf-wifiprov") } - var password by rememberSaveable { mutableStateOf("") } - var showPassword by rememberSaveable { mutableStateOf(true) } - - AlertDialog( - onDismissRequest = { }, - icon = { - Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) - }, - title = { - Text( - text = stringResource(id = R.string.setup_wifi), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.titleLarge - ) - }, - text = { - Column { - Text( - text = stringResource(id = R.string.setup_wifi_rationale), - modifier = Modifier.fillMaxWidth(), - style = MaterialTheme.typography.bodyMedium - ) - Spacer(modifier = Modifier.size(size = 16.dp)) - OutlinedTextField(value = ssid, onValueChange = { ssid = it }) - Spacer(modifier = Modifier.size(size = 8.dp)) - OutlinedTextField( - value = password, - onValueChange = { password = it }, - visualTransformation = if (showPassword) - VisualTransformation.None - else - PasswordVisualTransformation(), - trailingIcon = { - IconButton(onClick = { showPassword = !showPassword }) { - Icon( - imageVector = if (!showPassword) - Icons.Outlined.Visibility - else Icons.Outlined.VisibilityOff, - contentDescription = null - ) - } - } - ) - } - }, - dismissButton = { - TextButton( - onClick = { - viewModel.navigateUp() - } - ) { Text(text = "Cancel") } - }, - confirmButton = { - TextButton( - onClick = { - viewModel.connect( - ssid = ssid, - password = password - ) - } - ) { Text(text = "Confirm") } - } - ) -} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 08d5a21d..a1bc2676 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -18,9 +18,6 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerVie * Created by Roshan Rajaratnam on 14/02/2024. */ val SoftApProvisionerDestination = createSimpleDestination("softap-provisioner-destination") -val SoftApConnectorDestination = createDestination( - "softap-connector-destination" -) val SoftApWifiScannerDestination = createDestination( name = "wifi-access-points-softap-destination" ) @@ -32,9 +29,6 @@ val SoftApProvisionerDestinations = listOf( SoftApProvisioningScreen() } }, - defineDialogDestination(SoftApConnectorDestination) { - SoftApConnectorScreen() - }, defineDestination(SoftApWifiScannerDestination) { val viewModel = hiltViewModel() val viewEntity by viewModel.state.collectAsStateWithLifecycle() diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index c2653fbf..913e6efd 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -34,29 +34,48 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff +import androidx.compose.material.icons.outlined.Wifi +import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.softap.sections.ActionButtonSection import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApProvisioningViewModel import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSelected import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection @@ -90,6 +109,17 @@ fun SoftApProvisioningScreen() { Spacer(modifier = Modifier.size(16.dp)) } + if (state.showSoftApDialog) { + SoftApConnectorDialog( + isNetworkServiceDiscoveryCompleted = state.isNetworkServiceDiscoveryCompleted, + connect = { ssid, passphrase -> + onEvent(OnSoftApConnectEvent(ssid, passphrase)) + }, dismiss = { + onEvent(OnHidePasswordDialog) + } + ) + } + if (state.showPasswordDialog == true) { PasswordDialog { event -> (event as? PasswordSetDialogEvent)?.let { @@ -130,14 +160,23 @@ private fun Content(state: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Spacer(modifier = Modifier.size(12.dp)) - WifiSection(it, false, onEvent) + WifiSection(it, true, onEvent) } state.password?.let { Spacer(modifier = Modifier.size(10.dp)) - PasswordSection(false, onEvent) + PasswordSection(true, onEvent) } + + // TODO verification + /*state.provisioningStatus?.let { + SectionTitle(text = stringResource(id = R.string.section_status)) + + Spacer(modifier = Modifier.size(8.dp)) + + ProvisioningSection(it) + }*/ } } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt new file mode 100644 index 00000000..21c1e7d4 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt @@ -0,0 +1,10 @@ +package no.nordicsemi.android.wifi.provisioner.softap.view + +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent + +data class OnSoftApConnectEvent( + val ssid: String, + val passphraseConfiguration: PassphraseConfiguration = Open +) : ProvisioningViewEvent \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt index c481b40b..2d7d2140 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt @@ -18,12 +18,17 @@ data class SoftApViewEntity( override val provisioningStatus: Resource? = null, override val isConnected: Boolean = true, val isAuthorized: Boolean = false, + val showSoftApDialog: Boolean = false, + val isNetworkServiceDiscoveryCompleted: Boolean? = null ) : ViewEntity { + override fun hasFinished(): Boolean { + val status = (provisioningStatus as? Success)?.data + return status == WifiConnectionStateDomain.DISCONNECTED + } + override fun hasFinishedWithSuccess(): Boolean { val status = (provisioningStatus as? Success)?.data - return (isConnected - && status == WifiConnectionStateDomain.CONNECTED) - || status == WifiConnectionStateDomain.CONNECTION_FAILED + return status == WifiConnectionStateDomain.CONNECTED } } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt deleted file mode 100644 index 851b7e82..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApConnectorViewModel.kt +++ /dev/null @@ -1,36 +0,0 @@ -@file:Suppress("unused") - -package no.nordicsemi.android.wifi.provisioner.softap.viewmodel - -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.launch -import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel -import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApConnectorDestination -import javax.inject.Inject - -/** - * Created by Roshan Rajaratnam on 15/02/2024. - */ -@HiltViewModel -class SoftApConnectorViewModel @Inject constructor( - navigationManager: Navigator, - savedStateHandle: SavedStateHandle, - private val softApManager: SoftApManager -) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle = savedStateHandle) { - - @RequiresApi(Build.VERSION_CODES.Q) - internal fun connect(ssid: String = "0018F0-nrf-wifiprov", password: String) { - viewModelScope.launch { - softApManager.connect(ssid = ssid, password = password)?.let { - navigateUpWithResult(SoftApConnectorDestination, it) - } - } - } -} - diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 61d9e06d..e618adf0 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -31,9 +31,14 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel +import android.net.nsd.NsdServiceInfo +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -44,10 +49,12 @@ import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.softap.SoftAp import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApConnectorDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.OnSoftApConnectEvent import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain @@ -73,16 +80,12 @@ class SoftApProvisioningViewModel @Inject constructor( private val _state = MutableStateFlow(SoftApViewEntity()) val state = _state.asStateFlow() + private val nsdServiceInfo = NsdServiceInfo().apply { + serviceName = "wifiprov" + serviceType = "_http._tcp." + } init { - navigationManager.resultFrom(SoftApConnectorDestination) - .mapNotNull { it as? NavigationResult.Success } - .onEach { result -> - result.value?.let { - installSoftApDevice(it) - } - } - .launchIn(viewModelScope) navigationManager.resultFrom(SoftApWifiScannerDestination) .mapNotNull { it as? NavigationResult.Success } .onEach { installWifi(it.value) } @@ -93,7 +96,11 @@ class SoftApProvisioningViewModel @Inject constructor( when (event) { OnFinishedEvent -> finish() is OnPasswordSelectedEvent -> onPasswordSelected(event.password) - OnSelectDeviceClickEvent -> requestWifiDevice() + OnSelectDeviceClickEvent -> provisionNextDevice() + is OnSoftApConnectEvent -> + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ + connect(ssid = event.ssid, passphraseConfiguration = event.passphraseConfiguration) + } OnSelectWifiEvent -> navigationManager.navigateTo(SoftApWifiScannerDestination) OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() @@ -103,12 +110,7 @@ class SoftApProvisioningViewModel @Inject constructor( } private fun provisionNextDevice() { - viewModelScope.launch { - launch { release() } - requestSoftApDevice() - delay(500) //nasty delay to prevent screen change before navigation - _state.value = SoftApViewEntity() - } + requestSoftApDevice() } private fun showPasswordDialog() { @@ -129,7 +131,9 @@ class SoftApProvisioningViewModel @Inject constructor( private fun release() { try { _state.value.device?.let { - softApManager.disconnect() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + softApManager.disconnect() + } } } catch (e: Exception) { e.printStackTrace() @@ -137,12 +141,8 @@ class SoftApProvisioningViewModel @Inject constructor( } private fun requestSoftApDevice() { - navigationManager.navigateTo(SoftApConnectorDestination) - } - - private fun requestWifiDevice() { release() - navigationManager.navigateTo(SoftApConnectorDestination) + _state.value = SoftApViewEntity(showSoftApDialog = true) } private fun installWifi(wifiData: WifiData) { @@ -161,22 +161,39 @@ class SoftApProvisioningViewModel @Inject constructor( _state.value = _state.value.copy(password = password) } - private fun provision() { + @RequiresApi(Build.VERSION_CODES.Q) + private fun connect( + ssid: String = "0018F0-nrf-wifiprov", + passphraseConfiguration: PassphraseConfiguration = Open + ) { viewModelScope.launch { - val state = _state.value - val network = state.network - network?.let { - softApManager.provision(it.toConfig()).also { response -> + softApManager.run { + connect(ssid = ssid, passphraseConfiguration = passphraseConfiguration) + _state.value = _state.value.copy(isNetworkServiceDiscoveryCompleted = false) + discoverServices() + _state.value = SoftApViewEntity(device = softAp, isNetworkServiceDiscoveryCompleted = true) + } + } + } + + private fun provision() { + val state = _state.value + val device = state.device ?: return + val network = state.network ?: return + val handler = CoroutineExceptionHandler { _, throwable -> + Log.d("AAAA", "Provisioning failed $throwable") + _state.value = state.copy( + provisioningStatus = Resource.createError(throwable) + ) + } + viewModelScope.launch(handler) { + softApManager.run { + provision(config = network.toConfig()).also { response -> if (response.isSuccessful) { - val nsdServiceInfo = softApManager.discoverServices() _state.value = state.copy( - device = state.device?.apply { - connectionInfoDomain = connectionInfoDomain?.copy( - ipv4Address = nsdServiceInfo.host.toString() - ) - }, + device = softApManager.softAp, provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.CONNECTED + data = WifiConnectionStateDomain.DISCONNECTED ) ) } else { @@ -194,9 +211,6 @@ class SoftApProvisioningViewModel @Inject constructor( private fun WifiData.toConfig(): WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo - return WifiConfigDomain( - wifiInfo, - state.password - ) + return WifiConfigDomain(info = wifiInfo, passphrase = state.password) } } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index ebd89a9e..63a17548 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -1,8 +1,8 @@ "Wi-Fi Provisioner " - Setup Wi-Fi - Please provide the Wi-Fi SSID and the Password + Soft AP + Enter the SSID and password of the SoftAp you want to connect to. Change Wi-Fi Dismiss Confirm diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 89fea979..6659556b 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -1,6 +1,6 @@ plugins { alias(libs.plugins.nordic.library) - alias(libs.plugins.nordic.hilt) + alias(libs.plugins.nordic.kotlin) alias(libs.plugins.wire) } @@ -10,6 +10,9 @@ android { dependencies { api(project(":lib:domain")) + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.annotation) + implementation(libs.nordic.core) implementation(libs.retrofit.core) implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.converter.scalars) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt new file mode 100644 index 00000000..68ded82f --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt @@ -0,0 +1,34 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +import okhttp3.tls.HandshakeCertificates +import okhttp3.tls.decodeCertificatePem + +/** + * Host name configuration contains the hostname of the SoftAP provisioning service. + * + * @property hostName The hostname of the SoftAP provisioning service. + */ +data class HostNameConfiguration( + val serviceName: String = "wifiprov", + val hostName: String = "https://wifiprov.local/", + val certificate: String = CERTIFICATE +) { + val handshakeCertificates = HandshakeCertificates.Builder() + .addTrustedCertificate(certificate.decodeCertificatePem()) + .build() +} + + +private const val CERTIFICATE = "" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + + "YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxGjAY\n" + + "BgNVBAoMEVRlc3QgT3JnYW5pemF0aW9uMRcwFQYDVQQDDA53aWZpcHJvdi5sb2Nh\n" + + "bDAeFw0yNDAzMjYxMzI4MzNaFw0yNTAzMjYxMzI4MzNaMGAxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRowGAYDVQQKDBFUZXN0IE9y\n" + + "Z2FuaXphdGlvbjEXMBUGA1UEAwwOd2lmaXByb3YubG9jYWwwWTATBgcqhkjOPQIB\n" + + "BggqhkjOPQMBBwNCAAR6COfDiVYhNJkqCe3COkrN/Y9U8LPSDElE+mDk0ri7Ivb8\n" + + "LefdeYP3HgoTEEgem5eDNy10UZlf6+q6VUWyCH8toxMwETAPBgNVHRMBAf8EBTAD\n" + + "AQH/MAoGCCqGSM49BAMCA0kAMEYCIQDmEcPlg4GuPIAE9xvpW8t8LGit/+eDWCqE\n" + + "3ADi/H6f0QIhALUgBnN1+7awE7M1FvSnizX3b5ff7BfzltskPYnpjxqS\n" + + "-----END CERTIFICATE-----\n" \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index b92837b1..2e1f4b38 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -3,8 +3,10 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.util.Log -import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.suspendCancellableCoroutine import java.net.InetAddress +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException /** * NetworkServiceDiscoveryListener that would listen to the network service discovery events. @@ -13,106 +15,88 @@ import java.net.InetAddress * @property discoveredIps List of discovered IP addresses of the network services. Note that this * list could be empty if no services are discovered. */ -class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager) { - private val mutex = Mutex(true) +class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager, private val serviceName: String) { private val _discoveredIps = mutableListOf() val discoveredIps: List get() = _discoveredIps - private var _serviceInfo: NsdServiceInfo? = null - - /** - * Callback used to listen for service discovery. + * Discovers the network services. + * + * @return NsdServiceInfo instance. */ - private val nsdListener = object : NsdManager.DiscoveryListener { + internal suspend fun discoverServices( + nsdServiceInfo: NsdServiceInfo + ): NsdServiceInfo = suspendCancellableCoroutine { continuation -> - // Called as soon as service discovery begins. - override fun onDiscoveryStarted(regType: String) { - Log.d("AAAA", "Service discovery started $regType") - } + lateinit var nsdListener: NsdManager.DiscoveryListener - override fun onServiceFound(service: NsdServiceInfo) { - // A service was found! Do something with it. - Log.d("AAAA", "Service discovered $service") - if (service.serviceName == SERVICE_NAME) { - Log.d("AAAA", "Resolving service $service") - nsdManager.resolveService(service, resolveListener) + val resolveListener = object : NsdManager.ResolveListener { + override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { + // Called when the resolve fails. Use the error code to debug. + Log.e("AAAA", "Resolve failed: $errorCode") } - } - override fun onServiceLost(service: NsdServiceInfo) { - // When the network service is no longer available. - // Internal bookkeeping code goes here. - Log.e("AAAA", "service lost: $service") + override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { + Log.d("AAAA", "Resolve success: $serviceInfo") + serviceInfo?.let { + Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") + _discoveredIps.add(it.host) + continuation.resume(it) + nsdManager.stopServiceDiscovery(nsdListener) + } + } } + nsdListener = object : NsdManager.DiscoveryListener { - override fun onDiscoveryStopped(serviceType: String) { - Log.i("AAAA", "Discovery stopped: $serviceType") - } + // Called as soon as service discovery begins. + override fun onDiscoveryStarted(regType: String) { + Log.d("AAAA", "Service discovery started $regType") + } - override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { - try { - Log.e("AAAA", "Discovery failed: Error code:$errorCode") - // nsdManager.stopServiceDiscovery(this) - } catch (e: Exception) { - Log.e("AAAA", "error on start discovery failed: $e") - } finally { - nsdManager.stopServiceDiscovery(this) + override fun onServiceFound(service: NsdServiceInfo) { + // A service was found! Do something with it. + Log.d("AAAA", "Service discovered $service") + if (service.serviceName == serviceName) { + Log.d("AAAA", "Resolving service $service") + nsdManager.resolveService(service, resolveListener) + } } - } - override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e("AAAA", "Discovery failed: Error code:$errorCode") - nsdManager.stopServiceDiscovery(this) - } - } + override fun onServiceLost(service: NsdServiceInfo) { + // When the network service is no longer available. + // Internal bookkeeping code goes here. + Log.e("AAAA", "service lost: $service") + } - /** - * Callback used to listen for service resolution. - */ - private val resolveListener = object : NsdManager.ResolveListener { - override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { - // Called when the resolve fails. Use the error code to debug. - Log.e("AAAA", "Resolve failed: $errorCode") - } + override fun onDiscoveryStopped(serviceType: String) { + Log.i("AAAA", "Discovery stopped: $serviceType") + } - override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { - Log.d("AAAA", "Resolve success: $serviceInfo") - serviceInfo?.let { - _serviceInfo = it - _discoveredIps.add(it.host) - mutex.unlock() + override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { + Log.e("AAAA", "error on starting service discovery for " + + "$serviceType failed: $errorCode") + continuation.resumeWithException( + Throwable("Discovery failed: Error code:$errorCode") + ) + } + + override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { + Log.e("AAAA", "Discovery failed: Error code:$errorCode") + continuation.resumeWithException( + Throwable("Discovery failed: Error code:$errorCode") + ) } } - } - /** - * Discovers the network services. - * - * @return NsdServiceInfo instance. - */ - internal suspend fun discoverServices(): NsdServiceInfo? { nsdManager.discoverServices( - SERVICE_TYPE, + nsdServiceInfo.serviceType, NsdManager.PROTOCOL_DNS_SD, nsdListener ) - mutex.lock() - return _serviceInfo!! - } - - /** - * Stops the network service discovery. - */ - internal fun stopDiscovery() { - nsdManager.stopServiceDiscovery(nsdListener) - if(mutex.isLocked) - mutex.unlock() - } - internal companion object { - const val SERVICE_NAME = "wifiprov" - private const val SERVICE_TYPE = "_http._tcp." + continuation.invokeOnCancellation { + nsdManager.stopServiceDiscovery(nsdListener) + } } } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt new file mode 100644 index 00000000..365a4d96 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt @@ -0,0 +1,9 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +sealed class PassphraseConfiguration(open val passphrase : String) + +data object Open : PassphraseConfiguration("") + +data class Wpa2Passphrase(override val passphrase: String) : PassphraseConfiguration(passphrase) + +data class Wpa3Passphrase(override val passphrase: String) : PassphraseConfiguration(passphrase) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt index ef7fdf44..623248cf 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt @@ -1,13 +1,24 @@ package no.nordicsemi.android.wifi.provisioner.softap +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain /** * WifiDevice class represents a Wi-Fi network that the device should connect to. + * + * @property ssid SSID of the network. + * @property passphraseConfiguration Passphrase configuration of the network. + * @property macAddress MAC address of the device. + * @property connectionInfoDomain Connection info of the device. */ data class SoftAp( val ssid: String, - val password: String? + val passphraseConfiguration: PassphraseConfiguration ) { + var macAddress: String? = null + internal set var connectionInfoDomain: ConnectionInfoDomain? = null + internal set + var wifiConfigDomain: WifiConfigDomain? = null + internal set } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 924b4b72..8c3c4536 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -2,77 +2,91 @@ package no.nordicsemi.android.wifi.provisioner.softap +import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest +import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.net.wifi.WifiNetworkSpecifier import android.os.Build -import android.util.Log import androidx.annotation.RequiresApi -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.withContext +import kotlinx.coroutines.suspendCancellableCoroutine +import no.nordicsemi.android.wifi.provisioner.softap.Open.passphrase import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain -import javax.inject.Inject +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.wire.WireConverterFactory +import java.util.concurrent.TimeUnit +import javax.net.ssl.HostnameVerifier +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException /** * Created by Roshan Rajaratnam on 23/02/2024. * * Entry point to the SoftApManager - * @property connectivityManager Android's connectivity manager. - * @property nsdListener Network service discovery listener. - * @property wifiService WifiServer api. - * @property coroutineDispatcher Coroutine dispatcher. + * * @constructor Create empty SoftApManager. */ -class SoftApManager @Inject constructor( - private val connectivityManager: ConnectivityManager, - private val nsdListener: NetworkServiceDiscoveryListener, - private val wifiService: WifiService, - private val coroutineDispatcher: CoroutineDispatcher +class SoftApManager( + context: Context, + hostNameConfiguration: HostNameConfiguration = HostNameConfiguration(), ) { + var softAp: SoftAp? = null + private set + private val _discoveredServices = mutableListOf() private var discoveredService: NsdServiceInfo? = null - private val mutex = Mutex(true) private var isConnected = false - private val networkCallback = object : ConnectivityManager.NetworkCallback() { + private val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager + private val nsdListener = NetworkServiceDiscoveryListener(nsdManager, serviceName = hostNameConfiguration.serviceName) - @RequiresApi(Build.VERSION_CODES.M) - override fun onAvailable(network: Network) { - super.onAvailable(network) - // do success processing here.. - try { - if (connectivityManager.bindProcessToNetwork(network)) { - isConnected = true - Log.d( - "AAAA", "Link properties ${ - connectivityManager.getLinkProperties(network)?.toString() - }" - ) - } else { - disconnect() - } - } catch (e: Exception) { - disconnect() - Log.e("AAAA", "Error: $e") - } finally { - mutex.unlock() - } + private val interceptor = HttpLoggingInterceptor().apply { + level = when { + BuildConfig.DEBUG -> HttpLoggingInterceptor.Level.BODY + else -> HttpLoggingInterceptor.Level.NONE } + } - override fun onUnavailable() { - // do failure processing here.. - mutex.unlock() - Log.d("AAAA", "Something went wrong!") - } + private val hostNameVerifier = HostnameVerifier { hostname, _ -> + hostname.contains(hostNameConfiguration.serviceName) } + private val client = OkHttpClient.Builder() + .sslSocketFactory( + hostNameConfiguration.handshakeCertificates.sslSocketFactory(), + hostNameConfiguration.handshakeCertificates.trustManager + ) + .addInterceptor(interceptor) + .hostnameVerifier { hostname, _ -> + hostname.contains(hostNameConfiguration.serviceName) + } + .followRedirects(false) + .dns { + nsdListener.discoveredIps + } + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + + private val softApProvisioningService = Retrofit.Builder() + .baseUrl(hostNameConfiguration.hostName) + .client(client) + .addConverterFactory(WireConverterFactory.create()) + .build() + .create(SoftApProvisioningService::class.java) + + private lateinit var networkCallback: ConnectivityManager.NetworkCallback + /** * Connects to an unprovisioned wifi device by establishing a temporary wifi network connection * with the given ssid and the password. @@ -81,65 +95,110 @@ class SoftApManager @Inject constructor( * the SSID or the passphrase of the network that the device must be provisioned into. */ @RequiresApi(Build.VERSION_CODES.Q) - suspend fun connect(ssid: String, password: String = ""): SoftAp? { - isConnected = false - val specifier = WifiNetworkSpecifier.Builder() + suspend fun connect( + ssid: String, + passphraseConfiguration: PassphraseConfiguration, + ): Unit = suspendCancellableCoroutine { continuation -> + networkCallback = object : ConnectivityManager.NetworkCallback() { + + @RequiresApi(Build.VERSION_CODES.Q) + override fun onAvailable(network: Network) { + // do success processing here..\ + if (connectivityManager.bindProcessToNetwork(network)) { + isConnected = true + softAp = SoftAp( + ssid = ssid, + passphraseConfiguration = passphraseConfiguration + ) + continuation.resume(Unit) + } else { + disconnect() + continuation.resumeWithException( + exception = IllegalStateException("Failed to bind to the network.") + ) + } + } + + override fun onUnavailable() { + // do failure processing here.. + disconnect() + continuation.resumeWithException( + exception = IllegalStateException("Failed to bind to the network.") + ) + } + } + + val wifNetworkBuilder = WifiNetworkSpecifier.Builder() .setSsid(ssid) - .setWpa2Passphrase(password) - .build() + + val networkSpecifier = when (passphraseConfiguration) { + is Open -> wifNetworkBuilder.setWpa2Passphrase(passphrase) + is Wpa2Passphrase -> wifNetworkBuilder.setWpa2Passphrase(passphrase) + is Wpa3Passphrase -> wifNetworkBuilder.setWpa3Passphrase(passphrase) + }.build() val request = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .setNetworkSpecifier(specifier) + .setNetworkSpecifier(networkSpecifier) .build() + connectivityManager.requestNetwork(request, networkCallback) - mutex.lock() - val service = discoverServices() - return if (isConnected) SoftAp(ssid = ssid, password = password).apply { - connectionInfoDomain = ConnectionInfoDomain(ipv4Address = service.host.toString()) - } else null + + // Invoked if the coroutine calling this suspend function is cancelled. + continuation.invokeOnCancellation { + connectivityManager.unregisterNetworkCallback(networkCallback) + } } /** - * Disconnects from an unprovisioned or a newly provisioned device. + * Discover services on the network. + * + * @param nsdServiceInfo NsdServiceInfo instance. */ - fun disconnect() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - connectivityManager.bindProcessToNetwork(null) + suspend fun discoverServices( + nsdServiceInfo: NsdServiceInfo = NsdServiceInfo() + .apply { + serviceName = "wifiprov" + serviceType = "_http._tcp." + } + ) { + val serviceInfo = nsdListener + .discoverServices(nsdServiceInfo = nsdServiceInfo) + softAp?.apply { + connectionInfoDomain = ConnectionInfoDomain(ipv4Address = serviceInfo.host.toString()) } - connectivityManager.unregisterNetworkCallback(networkCallback) } /** - * Discover services on the network. + * Lists the SSIDs scanned by the nRF7002 device */ - suspend fun discoverServices(): NsdServiceInfo { - val serviceInfo = nsdListener.discoverServices() - nsdListener.stopDiscovery() - return serviceInfo!! - } + suspend fun listSsids() = softApProvisioningService.listSsids().toDomain() /** - * Stops the network service discovery. + * Provisions the nRF7002 device a wifi network with the given credentials. + * + * @param config Credentials of the wifi network. */ - private fun stopDiscovery() { - nsdListener.stopDiscovery() - } + suspend fun provision(config: WifiConfigDomain) = + softApProvisioningService.provision(config.toApi()) /** - * Lists the SSIDs scanned by the nRF7002 device + * Disconnects from an unprovisioned or a newly provisioned device. */ - suspend fun listSsids() = withContext(coroutineDispatcher) { - wifiService.listSsids().toDomain() + @RequiresApi(Build.VERSION_CODES.Q) + fun disconnect() { + isConnected = false + connectivityManager.bindProcessToNetwork(null) + connectivityManager.unregisterNetworkCallback(networkCallback) } /** - * Provisions the nRF7002 device a wifi network with the given credentials. + * Did provisioning complete. * - * @param config Credentials of the wifi network. + * @param nsdServiceInfo NsdServiceInfo instance. */ - suspend fun provision(config: WifiConfigDomain) = withContext(coroutineDispatcher) { - wifiService.provision(config.toApi()) + suspend fun verify(nsdServiceInfo: NsdServiceInfo) { + discoverServices(nsdServiceInfo = nsdServiceInfo) } } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt similarity index 94% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt rename to lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt index 86fe72a2..3d9e5605 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/WifiService.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt @@ -12,7 +12,7 @@ import retrofit2.http.POST /** * Created by Roshan Rajaratnam on 19/02/2024. */ -interface WifiService { +interface SoftApProvisioningService { @Headers("Content-Type: application/x-protobuf") @GET("prov/networks") diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt deleted file mode 100644 index 8c035bdc..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/DispatchersModule.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * * Copyright (c) 2022, Nordic Semiconductor - * * - * * SPDX-License-Identifier: Apache-2.0 - * - */ - -package no.nordicsemi.android.wifi.provisioner.softap.di - -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import javax.inject.Qualifier - -@Module -@InstallIn(SingletonComponent::class) -class DispatchersModule { - @Provides - @DefaultDispatcher - fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default - - @Provides - @IODispatcher - fun provideIODispatcher(): CoroutineDispatcher = Dispatchers.IO -} - -@Retention(AnnotationRetention.BINARY) -@Qualifier -annotation class DefaultDispatcher - -@Retention(AnnotationRetention.BINARY) -@Qualifier -annotation class IODispatcher \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt deleted file mode 100644 index c773365f..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/SoftApManagerModule.kt +++ /dev/null @@ -1,34 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.di - -import android.net.ConnectivityManager -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineDispatcher -import no.nordicsemi.android.wifi.provisioner.softap.NetworkServiceDiscoveryListener -import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.WifiService -import javax.inject.Singleton - -/** - * Created by Roshan Rajaratnam on 22/02/2024. - */ -@Module -@InstallIn(SingletonComponent::class) -object SoftApManagerModule { - - @Provides - @Singleton - fun provideSoftApManager( - connectivityManager: ConnectivityManager, - nsdListener: NetworkServiceDiscoveryListener, - wifiService: WifiService, - @IODispatcher coroutineDispatcher: CoroutineDispatcher - ) = SoftApManager( - connectivityManager = connectivityManager, - nsdListener = nsdListener, - wifiService = wifiService, - coroutineDispatcher = coroutineDispatcher - ) -} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt deleted file mode 100644 index ccee931b..00000000 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiServiceModule.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * * Copyright (c) 2022, Nordic Semiconductor - * * - * * SPDX-License-Identifier: Apache-2.0 - * - */ - -package no.nordicsemi.android.wifi.provisioner.softap.di - -import android.content.Context -import android.net.ConnectivityManager -import android.net.nsd.NsdManager -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import no.nordicsemi.android.wifi.provisioner.softap.BuildConfig -import no.nordicsemi.android.wifi.provisioner.softap.NetworkServiceDiscoveryListener -import no.nordicsemi.android.wifi.provisioner.softap.WifiService -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import okhttp3.logging.HttpLoggingInterceptor.Level -import okhttp3.tls.HandshakeCertificates -import okhttp3.tls.decodeCertificatePem -import retrofit2.Retrofit -import retrofit2.converter.wire.WireConverterFactory -import retrofit2.create -import java.util.concurrent.TimeUnit -import javax.inject.Singleton -import javax.net.ssl.HostnameVerifier - - -/** - * Created by Roshan Rajaratnam on 19/02/2024. - */ -@Module -@InstallIn(SingletonComponent::class) -object WifiServiceModule { - - @Provides - @Singleton - fun provideConnectivityManager(@ApplicationContext context: Context): ConnectivityManager { - return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - } - - @Provides - @Singleton - fun provideNetworkServiceDiscoveryListener(@ApplicationContext context : Context): NetworkServiceDiscoveryListener { - val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager - return NetworkServiceDiscoveryListener(nsdManager) - } - - @Provides - @Singleton - fun provideOkHttpClient(nsdListener: NetworkServiceDiscoveryListener): OkHttpClient { - val interceptor = HttpLoggingInterceptor().apply { - level = when { - BuildConfig.DEBUG -> Level.BODY - else -> Level.NONE - } - } - val certificate = HandshakeCertificates.Builder() - .addTrustedCertificate(CERTIFICATE.decodeCertificatePem()) - .build() - - // This is a work around to avoid unknown host exception - val hostNameVerifier = HostnameVerifier { hostname, _ -> - hostname.contains(NetworkServiceDiscoveryListener.SERVICE_NAME) - } - - return OkHttpClient.Builder() - .sslSocketFactory(certificate.sslSocketFactory(), certificate.trustManager) - .addInterceptor(interceptor) - .hostnameVerifier(hostNameVerifier) - .followRedirects(false) - .dns { - nsdListener.discoveredIps - } - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - } - - @Provides - @Singleton - fun provideService(client: OkHttpClient): WifiService = Retrofit.Builder() - .baseUrl("https://${NetworkServiceDiscoveryListener.SERVICE_NAME}.local/") - .client(client) - .addConverterFactory(WireConverterFactory.create()) - .build() - .create() - - private const val CERTIFICATE = "" + - "-----BEGIN CERTIFICATE-----\n" + - "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + - "YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxGjAY\n" + - "BgNVBAoMEVRlc3QgT3JnYW5pemF0aW9uMRcwFQYDVQQDDA53aWZpcHJvdi5sb2Nh\n" + - "bDAeFw0yNDAzMjYxMzI4MzNaFw0yNTAzMjYxMzI4MzNaMGAxCzAJBgNVBAYTAlVT\n" + - "MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRowGAYDVQQKDBFUZXN0IE9y\n" + - "Z2FuaXphdGlvbjEXMBUGA1UEAwwOd2lmaXByb3YubG9jYWwwWTATBgcqhkjOPQIB\n" + - "BggqhkjOPQMBBwNCAAR6COfDiVYhNJkqCe3COkrN/Y9U8LPSDElE+mDk0ri7Ivb8\n" + - "LefdeYP3HgoTEEgem5eDNy10UZlf6+q6VUWyCH8toxMwETAPBgNVHRMBAf8EBTAD\n" + - "AQH/MAoGCCqGSM49BAMCA0kAMEYCIQDmEcPlg4GuPIAE9xvpW8t8LGit/+eDWCqE\n" + - "3ADi/H6f0QIhALUgBnN1+7awE7M1FvSnizX3b5ff7BfzltskPYnpjxqS\n" + - "-----END CERTIFICATE-----\n" -} \ No newline at end of file From d380a6ef1d367395bf8b5ef4bf07c43508890466 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 13:53:22 +0200 Subject: [PATCH 054/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../softap/view/SoftApDestinations.kt | 2 -- .../softap/view/SoftApProvisioningScreen.kt | 19 ------------------- .../viewmodel/SoftApProvisioningViewModel.kt | 2 -- 3 files changed, 23 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index a1bc2676..be6739ef 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -8,8 +8,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination -import no.nordicsemi.android.common.navigation.defineDialogDestination -import no.nordicsemi.android.wifi.provisioner.softap.SoftAp import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 913e6efd..65d25340 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -34,48 +34,29 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Visibility -import androidx.compose.material.icons.outlined.VisibilityOff -import androidx.compose.material.icons.outlined.Wifi -import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.softap.Open -import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.softap.sections.ActionButtonSection import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApProvisioningViewModel import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSelected import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index e618adf0..c6c0684b 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -39,7 +39,6 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -178,7 +177,6 @@ class SoftApProvisioningViewModel @Inject constructor( private fun provision() { val state = _state.value - val device = state.device ?: return val network = state.network ?: return val handler = CoroutineExceptionHandler { _, throwable -> Log.d("AAAA", "Provisioning failed $throwable") From 9f6e0084a9dd812caac94eba38fa72c62ef00a41 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 14:01:32 +0200 Subject: [PATCH 055/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../softap/viewmodel/SoftApProvisioningViewModel.kt | 4 ---- .../provisioner/softap/NetworkServiceDiscoveryListener.kt | 4 ++-- .../android/wifi/provisioner/softap/SoftApManager.kt | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index c6c0684b..334d9667 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -79,10 +79,6 @@ class SoftApProvisioningViewModel @Inject constructor( private val _state = MutableStateFlow(SoftApViewEntity()) val state = _state.asStateFlow() - private val nsdServiceInfo = NsdServiceInfo().apply { - serviceName = "wifiprov" - serviceType = "_http._tcp." - } init { navigationManager.resultFrom(SoftApWifiScannerDestination) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 2e1f4b38..587a5f7f 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -15,7 +15,7 @@ import kotlin.coroutines.resumeWithException * @property discoveredIps List of discovered IP addresses of the network services. Note that this * list could be empty if no services are discovered. */ -class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager, private val serviceName: String) { +class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager) { private val _discoveredIps = mutableListOf() val discoveredIps: List get() = _discoveredIps @@ -57,7 +57,7 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceFound(service: NsdServiceInfo) { // A service was found! Do something with it. Log.d("AAAA", "Service discovered $service") - if (service.serviceName == serviceName) { + if (service.serviceName == nsdServiceInfo.serviceName) { Log.d("AAAA", "Resolving service $service") nsdManager.resolveService(service, resolveListener) } diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 8c3c4536..642acd7d 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -48,7 +48,7 @@ class SoftApManager( private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager - private val nsdListener = NetworkServiceDiscoveryListener(nsdManager, serviceName = hostNameConfiguration.serviceName) + private val nsdListener = NetworkServiceDiscoveryListener(nsdManager) private val interceptor = HttpLoggingInterceptor().apply { level = when { From bbda74fe1df21148ba212e17aab048f7c5960b0d Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 14:02:05 +0200 Subject: [PATCH 056/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../softap/viewmodel/SoftApProvisioningViewModel.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 334d9667..24fa2c02 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -31,7 +31,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel -import android.net.nsd.NsdServiceInfo import android.os.Build import android.util.Log import androidx.annotation.RequiresApi @@ -148,10 +147,6 @@ class SoftApProvisioningViewModel @Inject constructor( ) } - private fun installSoftApDevice(device: SoftAp) { - _state.value = SoftApViewEntity(device = device) - } - private fun onPasswordSelected(password: String) { _state.value = _state.value.copy(password = password) } From 3fb39ff106d64f5ee2ff408d62401c4697773155 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 14:12:22 +0200 Subject: [PATCH 057/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../wifi/provisioner/softap/view/SoftApConnectorDialog.kt | 5 +++++ .../provisioner/softap/view/SoftApProvisioningScreen.kt | 3 ++- feature/softap/src/main/res/values/strings.xml | 3 ++- .../android/wifi/provisioner/softap/SoftApManager.kt | 6 +++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index d1f9d62e..cdc5c29d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -75,6 +75,11 @@ internal fun SoftApConnectorDialog( horizontalAlignment = Alignment.CenterHorizontally ) { CircularProgressIndicator() + Text( + text = stringResource(id = R.string.softap_rationale), + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.bodyMedium + ) } } else { showButtons = true diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 65d25340..4a0e6474 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -60,6 +60,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSelected import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent @@ -96,7 +97,7 @@ fun SoftApProvisioningScreen() { connect = { ssid, passphrase -> onEvent(OnSoftApConnectEvent(ssid, passphrase)) }, dismiss = { - onEvent(OnHidePasswordDialog) + onEvent(OnFinishedEvent) } ) } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 63a17548..651bb51c 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -2,7 +2,8 @@ "Wi-Fi Provisioner " Soft AP - Enter the SSID and password of the SoftAp you want to connect to. + Enter the SSID and password of the Soft AP you want to connect to. + Connecting to Soft AP… Change Wi-Fi Dismiss Confirm diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 642acd7d..eb44a5bc 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -181,7 +181,11 @@ class SoftApManager( * @param config Credentials of the wifi network. */ suspend fun provision(config: WifiConfigDomain) = - softApProvisioningService.provision(config.toApi()) + softApProvisioningService.provision(config.toApi()).also { + if(it.isSuccessful){ + softAp?.wifiConfigDomain = config + } + } /** * Disconnects from an unprovisioned or a newly provisioned device. From 25fd4cc7c13366e876ea0b7236d75f5669031649 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 30 Apr 2024 14:22:31 +0200 Subject: [PATCH 058/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../wifi/provisioner/softap/view/SoftApConnectorDialog.kt | 2 +- feature/softap/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index cdc5c29d..0b1928ae 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -76,7 +76,7 @@ internal fun SoftApConnectorDialog( ) { CircularProgressIndicator() Text( - text = stringResource(id = R.string.softap_rationale), + text = stringResource(id = R.string.discovering_services), modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyMedium ) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 651bb51c..94c8db68 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -3,7 +3,7 @@ "Wi-Fi Provisioner " Soft AP Enter the SSID and password of the Soft AP you want to connect to. - Connecting to Soft AP… + Discovering services… Change Wi-Fi Dismiss Confirm From 1bbe487f403e6609369227f2420e1db854ac1052 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 2 May 2024 08:44:04 +0200 Subject: [PATCH 059/101] WIP: Unifying BLE and Wifi provisioner UI. --- app/build.gradle.kts | 1 + .../android/wifi/provisioner/HomeScreen.kt | 70 ++++++++++--------- .../wifi/provisioner/ui/WelcomeSection.kt | 52 ++++++++++++++ .../ui/view/section/SectionTitle.kt | 15 ++++ feature/ui/src/main/res/values/strings.xml | 11 +++ 5 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt create mode 100644 feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/SectionTitle.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d0bb40e8..59b06b13 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,6 +45,7 @@ dependencies { implementation(project(":feature:ble")) implementation(project(":feature:softap")) implementation(project(":feature:common")) + implementation(project(":feature:ui")) implementation(project(":lib:ble:provisioner")) implementation(project(":lib:softap:provisioner")) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index ce1c2c43..7a5e69f4 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -42,7 +42,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.Button +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -50,7 +50,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -60,58 +59,63 @@ import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewMod import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestination import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestination +import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverBle +import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverWifi @Composable fun HomeScreen() { val vm: SimpleNavigationViewModel = hiltViewModel() - Scaffold( - containerColor = colorResource(id = no.nordicsemi.android.common.theme.R.color.appBarColor), - ) { innerPadding -> + Scaffold(containerColor = MaterialTheme.colorScheme.background) { innerPadding -> Column( modifier = Modifier .fillMaxSize() .padding(paddingValues = innerPadding), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { + Spacer(modifier = Modifier.size(16.dp)) Text( text = stringResource(id = R.string.label_ble_provisioner), style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.ExtraBold ) - Row( + Column( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .weight(weight = 1f), - horizontalArrangement = Arrangement.Center + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceEvenly ) { - Image( - painter = painterResource(id = R.drawable.ic_nrf70), - contentDescription = stringResource(id = R.string.ic_nrf70), + + Row( modifier = Modifier - .widthIn(max = 200.dp) - .padding(8.dp) - .background(Color.White) - ) - } - Row(modifier = Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) { - Button(onClick = { vm.navigateTo(BleProvisioningDestination) }) { - Text(text = "Provision over BLE") + .fillMaxWidth() + /*.weight(weight = 1f)*/, + horizontalArrangement = Arrangement.Center + ) { + Image( + painter = painterResource(id = R.drawable.ic_nrf70), + contentDescription = stringResource(id = R.string.ic_nrf70), + modifier = Modifier + .widthIn(max = 200.dp) + .padding(8.dp) + .background(Color.White) + ) } - Button(onClick = { vm.navigateTo(SoftApProvisionerDestination) }) { - Text(text = "Provision over Wi-Fi") + LazyColumn { + item { + ProvisionOverBle { + vm.navigateTo(BleProvisioningDestination) + } + } + item { + ProvisionOverWifi { + vm.navigateTo(SoftApProvisionerDestination) + } + } } + Spacer(modifier = Modifier.size(16.dp)) } - Spacer(modifier = Modifier.size(16.dp)) } } -} - -@Composable -private fun SectionTitle(text: String) { - Text( - text = text, - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) -} +} \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt new file mode 100644 index 00000000..9c7c34ff --- /dev/null +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt @@ -0,0 +1,52 @@ +package no.nordicsemi.android.wifi.provisioner.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle + + +@Composable +fun ProvisionOverBle(onClick: () -> Unit) { + OutlinedCard( + modifier = Modifier + .padding(all = 8.dp) + .clickable(onClick = onClick) + ) { + Column(modifier = Modifier.padding(all = 16.dp)) { + SectionTitle(text = stringResource(R.string.provision_over_ble)) + Spacer(modifier = Modifier.size(8.dp)) + Text( + text = stringResource(R.string.provision_over_ble_rationale), + style = MaterialTheme.typography.bodyMedium + ) + } + } +} + +@Composable +fun ProvisionOverWifi(onClick: () -> Unit) { + OutlinedCard( + modifier = Modifier + .padding(all = 8.dp) + .clickable(onClick = onClick) + ) { + Column(modifier = Modifier.padding(all = 16.dp)) { + SectionTitle(text = stringResource(R.string.provision_over_wi_fi)) + Spacer(modifier = Modifier.size(8.dp)) + Text( + text = stringResource(R.string.provision_over_wifi_rationale), + style = MaterialTheme.typography.bodyMedium + ) + } + } +} \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/SectionTitle.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/SectionTitle.kt new file mode 100644 index 00000000..243e396f --- /dev/null +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/SectionTitle.kt @@ -0,0 +1,15 @@ +package no.nordicsemi.android.wifi.provisioner.ui.view.section + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + + +@Composable +fun SectionTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.secondary + ) +} \ No newline at end of file diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index bc4cecfb..9c297487 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -94,4 +94,15 @@ Select Wi-Fi Persistent storage + + Provision over BLE + This mode allows provisioning a nRF700x device to a + Wi-Fi network by providing the Wi-Fi credentials over BLE, by directly connecting to the + device using BLE + + Provision over Wi-Fi + This mode allows provisioning a nRF700x device to a + Wi-Fi network by providing the Wi-Fi credentials over Wi-Fi by directly connecting to the + Soft AP advertised by the device. + \ No newline at end of file From b3b0957f6e24094de21c17e38e67dd301e797ada Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 2 May 2024 11:06:40 +0200 Subject: [PATCH 060/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../android/wifi/provisioner/HomeScreen.kt | 78 ++++++++++--------- .../android/wifi/provisioner/MainActivity.kt | 2 - .../softap/view/SoftApDestinations.kt | 2 - feature/ui/src/main/res/values/strings.xml | 6 +- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 7a5e69f4..89cf8265 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -34,59 +34,60 @@ package no.nordicsemi.android.wifi.provisioner import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestination import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestination import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverBle import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverWifi +@OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeScreen() { val vm: SimpleNavigationViewModel = hiltViewModel() - - Scaffold(containerColor = MaterialTheme.colorScheme.background) { innerPadding -> - Column( + Scaffold( + contentWindowInsets = WindowInsets(0, 0, 0, 0), + topBar = { + NordicAppBar( + text = stringResource(id = R.string.label_ble_provisioner) + ) + }, + ) { innerPadding -> + LazyColumn( modifier = Modifier .fillMaxSize() - .padding(paddingValues = innerPadding), - horizontalAlignment = Alignment.CenterHorizontally, + .padding(innerPadding) + .consumeWindowInsets(innerPadding) + .windowInsetsPadding( + WindowInsets.safeDrawing.only( + WindowInsetsSides.Horizontal, + ), + ), + verticalArrangement = Arrangement.SpaceEvenly ) { - Spacer(modifier = Modifier.size(16.dp)) - Text( - text = stringResource(id = R.string.label_ble_provisioner), - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.ExtraBold - ) - Column( - modifier = Modifier - .fillMaxSize() - .weight(weight = 1f), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceEvenly - ) { - + item { Row( modifier = Modifier .fillMaxWidth() @@ -102,19 +103,20 @@ fun HomeScreen() { .background(Color.White) ) } - LazyColumn { - item { - ProvisionOverBle { - vm.navigateTo(BleProvisioningDestination) - } - } - item { - ProvisionOverWifi { - vm.navigateTo(SoftApProvisionerDestination) - } - } + } + /*item { + NordicText( + text = stringResource(id = R.string.app_info), + style = MaterialTheme.typography.bodyMedium + ) + }*/ + item { + ProvisionOverBle { + vm.navigateTo(BleProvisioningDestination) + } + ProvisionOverWifi { + vm.navigateTo(SoftApProvisionerDestination) } - Spacer(modifier = Modifier.size(16.dp)) } } } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt index 14643c85..14ee05db 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt @@ -49,9 +49,7 @@ class MainActivity : NordicActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { NordicTheme { Surface(modifier = Modifier.fillMaxSize()) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index be6739ef..5ef13ba9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -1,7 +1,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -20,7 +19,6 @@ val SoftApWifiScannerDestination = createDestination( name = "wifi-access-points-softap-destination" ) -@RequiresApi(Build.VERSION_CODES.Q) val SoftApProvisionerDestinations = listOf( defineDestination(SoftApProvisionerDestination) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 9c297487..5e56cfcd 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -95,10 +95,10 @@ Persistent storage - Provision over BLE + Provision over Bluetooth LE This mode allows provisioning a nRF700x device to a - Wi-Fi network by providing the Wi-Fi credentials over BLE, by directly connecting to the - device using BLE + Wi-Fi network by providing the Wi-Fi credentials, directly connecting to the + device using Bluetooth LE Provision over Wi-Fi This mode allows provisioning a nRF700x device to a From c1449e1f3512afaf4866baa32e92df000248ac03 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 3 May 2024 10:27:30 +0200 Subject: [PATCH 061/101] WIP: Unifying BLE and Wifi provisioner UI. --- .../softap/viewmodel/SoftApProvisioningViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 24fa2c02..b14de38c 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -93,7 +93,10 @@ class SoftApProvisioningViewModel @Inject constructor( OnSelectDeviceClickEvent -> provisionNextDevice() is OnSoftApConnectEvent -> if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ - connect(ssid = event.ssid, passphraseConfiguration = event.passphraseConfiguration) + connect( + ssid = event.ssid, + passphraseConfiguration = event.passphraseConfiguration + ) } OnSelectWifiEvent -> navigationManager.navigateTo(SoftApWifiScannerDestination) OnProvisionClickEvent -> provision() From c0abcbeee0cf484989e9e5d934fd3f916e4242c5 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 3 May 2024 10:29:16 +0200 Subject: [PATCH 062/101] clean up --- .../provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index b14de38c..7d111c44 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -49,7 +49,6 @@ import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration -import no.nordicsemi.android.wifi.provisioner.softap.SoftAp import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.view.OnSoftApConnectEvent From dff23852434bf8112298c78a62c692ef12aa625b Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 3 May 2024 10:30:47 +0200 Subject: [PATCH 063/101] Improvements : error handling --- .../provisioner/softap/SoftApException.kt | 21 +++++++ .../wifi/provisioner/softap/SoftApManager.kt | 62 +++++++++++++++---- 2 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt new file mode 100644 index 00000000..29ad3464 --- /dev/null +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt @@ -0,0 +1,21 @@ +package no.nordicsemi.android.wifi.provisioner.softap + +/** + * An exception that is thrown when the SoftAP provisioning fails. + */ +sealed class SoftApException : Exception() + +/** + * An exception that is thrown when the WiFi is not enabled. + */ +data object WifiNotEnabledException : SoftApException() { + private fun readResolve(): Any = WifiNotEnabledException +} + +/** + * An exception that is thrown when the SoftAp manager fails to bind to the connected SoftAP + * network. + */ +data object FailedToBindToNetwork : SoftApException() { + private fun readResolve(): Any = WifiNotEnabledException +} \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index eb44a5bc..75f06d8b 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -9,17 +9,21 @@ import android.net.NetworkCapabilities import android.net.NetworkRequest import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo +import android.net.wifi.WifiManager import android.net.wifi.WifiNetworkSpecifier import android.os.Build import androidx.annotation.RequiresApi import kotlinx.coroutines.suspendCancellableCoroutine import no.nordicsemi.android.wifi.provisioner.softap.Open.passphrase +import no.nordicsemi.android.wifi.provisioner.softap.domain.ScanResultsDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain import okhttp3.OkHttpClient +import okhttp3.ResponseBody import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.wire.WireConverterFactory import java.util.concurrent.TimeUnit @@ -43,8 +47,10 @@ class SoftApManager( private val _discoveredServices = mutableListOf() private var discoveredService: NsdServiceInfo? = null - private var isConnected = false + private var isBoundToNetwork = false + private val wifiManager = + context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager @@ -93,19 +99,29 @@ class SoftApManager( * * Note: The SSID and the password are the ones used to connect to the unprovisioned device, not * the SSID or the passphrase of the network that the device must be provisioned into. + * + * @throws WifiNotEnabledException if the wifi is not enabled. + * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. + * Call [connect] to connect to the softap and bind to the network. */ @RequiresApi(Build.VERSION_CODES.Q) + @Throws(WifiNotEnabledException::class, FailedToBindToNetwork::class) suspend fun connect( ssid: String, passphraseConfiguration: PassphraseConfiguration, ): Unit = suspendCancellableCoroutine { continuation -> + if (!wifiManager.isWifiEnabled) + continuation.resumeWithException( + exception = WifiNotEnabledException + ) + networkCallback = object : ConnectivityManager.NetworkCallback() { @RequiresApi(Build.VERSION_CODES.Q) override fun onAvailable(network: Network) { // do success processing here..\ if (connectivityManager.bindProcessToNetwork(network)) { - isConnected = true + isBoundToNetwork = true softAp = SoftAp( ssid = ssid, passphraseConfiguration = passphraseConfiguration @@ -114,7 +130,7 @@ class SoftApManager( } else { disconnect() continuation.resumeWithException( - exception = IllegalStateException("Failed to bind to the network.") + exception = FailedToBindToNetwork ) } } @@ -127,7 +143,6 @@ class SoftApManager( ) } } - val wifNetworkBuilder = WifiNetworkSpecifier.Builder() .setSsid(ssid) @@ -155,6 +170,9 @@ class SoftApManager( * Discover services on the network. * * @param nsdServiceInfo NsdServiceInfo instance. + * @throws WifiNotEnabledException if the wifi is not enabled. + * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. + * Call [connect] to connect to the softap and bind to the network. */ suspend fun discoverServices( nsdServiceInfo: NsdServiceInfo = NsdServiceInfo() @@ -163,6 +181,8 @@ class SoftApManager( serviceType = "_http._tcp." } ) { + require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isBoundToNetwork) { throw FailedToBindToNetwork } val serviceInfo = nsdListener .discoverServices(nsdServiceInfo = nsdServiceInfo) softAp?.apply { @@ -171,34 +191,54 @@ class SoftApManager( } /** - * Lists the SSIDs scanned by the nRF7002 device + * Lists the SSIDs scanned by the nRF700x device + * + * @return ScanResultsDomain containing the list of SSIDs. + * @throws WifiNotEnabledException if the wifi is not enabled. + * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. + * Call [connect] to connect to the softap and bind to the network. */ - suspend fun listSsids() = softApProvisioningService.listSsids().toDomain() + suspend fun listSsids(): ScanResultsDomain { + require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isBoundToNetwork) { throw FailedToBindToNetwork } + return softApProvisioningService.listSsids().toDomain() + } /** * Provisions the nRF7002 device a wifi network with the given credentials. * * @param config Credentials of the wifi network. + * @return Response received from the device. + * @throws WifiNotEnabledException if the wifi is not enabled. + * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. + * Call [connect] to connect to the softap and bind to the network. */ - suspend fun provision(config: WifiConfigDomain) = - softApProvisioningService.provision(config.toApi()).also { - if(it.isSuccessful){ + suspend fun provision(config: WifiConfigDomain): Response { + require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isBoundToNetwork) { throw FailedToBindToNetwork } + return softApProvisioningService.provision(config.toApi()).also { + if (it.isSuccessful) { softAp?.wifiConfigDomain = config } } + } /** * Disconnects from an unprovisioned or a newly provisioned device. + * @throws WifiNotEnabledException if the wifi is not enabled. + * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. + * Call [connect] to connect to the softap and bind to the network. */ @RequiresApi(Build.VERSION_CODES.Q) fun disconnect() { - isConnected = false + isBoundToNetwork = false connectivityManager.bindProcessToNetwork(null) connectivityManager.unregisterNetworkCallback(networkCallback) } /** - * Did provisioning complete. + * Verifies if the provisioning completed successfully. Note for this to work, both the devices + * and provisioning app has to be connected to the same network. * * @param nsdServiceInfo NsdServiceInfo instance. */ From b5204f78bb05d23412b6ff465dd213c4451916ae Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 6 May 2024 15:00:06 +0200 Subject: [PATCH 064/101] Improvements to the API --- feature/softap/src/main/AndroidManifest.xml | 1 + .../softap/di/SoftApManagerModule.kt | 3 +- .../softap/di/WifiManagerModule.kt | 24 ++++++ .../softap/view/SoftApConnectorDialog.kt | 2 +- .../softap/view/SoftApDestinations.kt | 4 +- .../softap/view/SoftApProvisioningScreen.kt | 2 +- .../viewmodel/SoftApProvisioningViewModel.kt | 47 +++++++---- .../softap/NetworkServiceDiscoveryListener.kt | 44 +++++++++-- .../android/wifi/provisioner/softap/SoftAp.kt | 13 ++- .../wifi/provisioner/softap/SoftApManager.kt | 79 +++++++++++++++---- 10 files changed, 172 insertions(+), 47 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiManagerModule.kt diff --git a/feature/softap/src/main/AndroidManifest.xml b/feature/softap/src/main/AndroidManifest.xml index 4d74c6ed..ae3c65d7 100644 --- a/feature/softap/src/main/AndroidManifest.xml +++ b/feature/softap/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + ( val SoftApProvisionerDestinations = listOf( defineDestination(SoftApProvisionerDestination) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - SoftApProvisioningScreen() - } + SoftApProvisioningScreen() }, defineDestination(SoftApWifiScannerDestination) { val viewModel = hiltViewModel() diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index 4a0e6474..af4daced 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -122,7 +122,7 @@ private fun Content(state: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Spacer(modifier = Modifier.size(12.dp)) state.device?.let { - SoftApDevice(it.ssid, it.connectionInfoDomain!!.ipv4Address, true, onEvent) + SoftApDevice(it.name, it.connectionInfoDomain!!.ipv4Address, true, onEvent) } ?: SoftApDeviceNotSelected(onEvent = onEvent) Spacer(modifier = Modifier.size(12.dp)) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 7d111c44..75a84849 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -31,13 +31,15 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel +import android.net.wifi.WifiManager import android.os.Build import android.util.Log -import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -66,11 +68,13 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDevice import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +import java.net.SocketTimeoutException import javax.inject.Inject @HiltViewModel class SoftApProvisioningViewModel @Inject constructor( private val softApManager: SoftApManager, + private val wifiManager: WifiManager, private val navigationManager: Navigator, savedStateHandle: SavedStateHandle, ) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { @@ -85,18 +89,23 @@ class SoftApProvisioningViewModel @Inject constructor( .launchIn(viewModelScope) } + override fun onCleared() { + super.onCleared() + softApManager.disconnect() + } + fun onEvent(event: ProvisioningViewEvent) { when (event) { OnFinishedEvent -> finish() is OnPasswordSelectedEvent -> onPasswordSelected(event.password) OnSelectDeviceClickEvent -> provisionNextDevice() - is OnSoftApConnectEvent -> - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ - connect( - ssid = event.ssid, - passphraseConfiguration = event.passphraseConfiguration - ) - } + is OnSoftApConnectEvent -> { + connect( + ssid = event.ssid, + passphraseConfiguration = event.passphraseConfiguration + ) + } + OnSelectWifiEvent -> navigationManager.navigateTo(SoftApWifiScannerDestination) OnProvisionClickEvent -> provision() OnHidePasswordDialog -> hidePasswordDialog() @@ -153,7 +162,6 @@ class SoftApProvisioningViewModel @Inject constructor( _state.value = _state.value.copy(password = password) } - @RequiresApi(Build.VERSION_CODES.Q) private fun connect( ssid: String = "0018F0-nrf-wifiprov", passphraseConfiguration: PassphraseConfiguration = Open @@ -163,7 +171,8 @@ class SoftApProvisioningViewModel @Inject constructor( connect(ssid = ssid, passphraseConfiguration = passphraseConfiguration) _state.value = _state.value.copy(isNetworkServiceDiscoveryCompleted = false) discoverServices() - _state.value = SoftApViewEntity(device = softAp, isNetworkServiceDiscoveryCompleted = true) + _state.value = + SoftApViewEntity(device = softAp, isNetworkServiceDiscoveryCompleted = true) } } } @@ -173,11 +182,16 @@ class SoftApProvisioningViewModel @Inject constructor( val network = state.network ?: return val handler = CoroutineExceptionHandler { _, throwable -> Log.d("AAAA", "Provisioning failed $throwable") - _state.value = state.copy( - provisioningStatus = Resource.createError(throwable) - ) + if (throwable is SocketTimeoutException) { + _state.value = state.copy( + device = softApManager.softAp, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.DISCONNECTED + ) + ) + } } - viewModelScope.launch(handler) { + viewModelScope.launch(Dispatchers.IO + handler) { softApManager.run { provision(config = network.toConfig()).also { response -> if (response.isSuccessful) { @@ -187,6 +201,8 @@ class SoftApProvisioningViewModel @Inject constructor( data = WifiConnectionStateDomain.DISCONNECTED ) ) + // discoverServices() + verify() } else { _state.value = state.copy( provisioningStatus = Resource.createError( @@ -199,6 +215,9 @@ class SoftApProvisioningViewModel @Inject constructor( } } + private fun isConnectedToTheSameNetwork() { + } + private fun WifiData.toConfig(): WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 587a5f7f..6abd64ed 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -4,6 +4,8 @@ import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.util.Log import kotlinx.coroutines.suspendCancellableCoroutine +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager.Companion.KEY_LINK_ADDR +import okio.ByteString.Companion.toByteString import java.net.InetAddress import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -26,9 +28,10 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage * @return NsdServiceInfo instance. */ internal suspend fun discoverServices( + macAddress: String? = null, nsdServiceInfo: NsdServiceInfo ): NsdServiceInfo = suspendCancellableCoroutine { continuation -> - + _discoveredIps.clear() lateinit var nsdListener: NsdManager.DiscoveryListener val resolveListener = object : NsdManager.ResolveListener { @@ -40,13 +43,32 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { Log.d("AAAA", "Resolve success: $serviceInfo") serviceInfo?.let { - Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") - _discoveredIps.add(it.host) - continuation.resume(it) - nsdManager.stopServiceDiscovery(nsdListener) + if (macAddress == null) { + Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") + stopDiscovery(it) + } else { + val mac = serviceInfo.attributes?.get(KEY_LINK_ADDR)?.toByteString()?.utf8() + if (mac == macAddress) { + stopDiscovery(it) + } + } + /*if(nsdServiceInfo.attributes.isEmpty() || nsdServiceInfo.attributes == serviceInfo.attributes){ + Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") + _discoveredIps.add(it.host) + continuation.resume(it) + nsdManager.stopServiceDiscovery(nsdListener) + }*/ } } + + private fun stopDiscovery(serviceInfo: NsdServiceInfo) { + Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") + _discoveredIps.add(serviceInfo.host) + continuation.resume(serviceInfo) + nsdManager.stopServiceDiscovery(nsdListener) + } } + nsdListener = object : NsdManager.DiscoveryListener { // Called as soon as service discovery begins. @@ -55,8 +77,12 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage } override fun onServiceFound(service: NsdServiceInfo) { - // A service was found! Do something with it. Log.d("AAAA", "Service discovered $service") + // Check if the service name found matches the service name we are looking for. + // Service attributes could be null if the service is not yet resolved, so if both [service] and [nsdServiceInfo] + // may be have null attributes, we can assume that this device and its services has not been discovered yet. + // In the case of [nsdServiceInfo] having attributes, we can assume that the device has been discovered and we can + // compare the link address to see if the service is the one we are looking for. if (service.serviceName == nsdServiceInfo.serviceName) { Log.d("AAAA", "Resolving service $service") nsdManager.resolveService(service, resolveListener) @@ -74,8 +100,10 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage } override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e("AAAA", "error on starting service discovery for " + - "$serviceType failed: $errorCode") + Log.e( + "AAAA", "error on starting service discovery for " + + "$serviceType failed: $errorCode" + ) continuation.resumeWithException( Throwable("Discovery failed: Error code:$errorCode") ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt index 623248cf..0fa208bf 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt @@ -1,7 +1,10 @@ package no.nordicsemi.android.wifi.provisioner.softap +import android.net.nsd.NsdServiceInfo +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager.Companion.KEY_LINK_ADDR import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain +import okio.ByteString.Companion.toByteString /** * WifiDevice class represents a Wi-Fi network that the device should connect to. @@ -15,10 +18,16 @@ data class SoftAp( val ssid: String, val passphraseConfiguration: PassphraseConfiguration ) { + val name: String + get() = ssid + + internal var serviceInfo: NsdServiceInfo? = null var macAddress: String? = null - internal set + get() = serviceInfo?.attributes?.get(KEY_LINK_ADDR)?.toByteString()?.utf8() + private set var connectionInfoDomain: ConnectionInfoDomain? = null - internal set + get() = ConnectionInfoDomain(ipv4Address = serviceInfo?.host.toString()) + private set var wifiConfigDomain: WifiConfigDomain? = null internal set } \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 75f06d8b..fd350ed0 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -4,6 +4,7 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.content.Context import android.net.ConnectivityManager +import android.net.LinkAddress import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest @@ -23,6 +24,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain import okhttp3.OkHttpClient import okhttp3.ResponseBody import okhttp3.logging.HttpLoggingInterceptor +import okio.ByteString.Companion.toByteString import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.wire.WireConverterFactory @@ -31,6 +33,7 @@ import javax.net.ssl.HostnameVerifier import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException + /** * Created by Roshan Rajaratnam on 23/02/2024. * @@ -48,6 +51,7 @@ class SoftApManager( private val _discoveredServices = mutableListOf() private var discoveredService: NsdServiceInfo? = null private var isBoundToNetwork = false + private var isConnected = false private val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager @@ -114,13 +118,25 @@ class SoftApManager( continuation.resumeWithException( exception = WifiNotEnabledException ) - + /* + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + wifiManager.isWifiEnabled = true + val wifiConfiguration = WifiConfiguration() + wifiConfiguration.SSID = String.format("\"%s\"", ssid) + wifiConfiguration.preSharedKey = String.format("\"%s\"", passphraseConfiguration.passphrase) + val wifiID = wifiManager.addNetwork(wifiConfiguration) + Log.d("AAAA", "wifiID: $wifiID") + wifiConfiguration.networkId = wifiID + wifiManager.enableNetwork(wifiID, true) + } else { + }*/ networkCallback = object : ConnectivityManager.NetworkCallback() { @RequiresApi(Build.VERSION_CODES.Q) override fun onAvailable(network: Network) { // do success processing here..\ if (connectivityManager.bindProcessToNetwork(network)) { + isConnected = true isBoundToNetwork = true softAp = SoftAp( ssid = ssid, @@ -167,12 +183,13 @@ class SoftApManager( } /** - * Discover services on the network. + * Discovers and resolves the mDNS services on the network. * - * @param nsdServiceInfo NsdServiceInfo instance. + * Note: If the mDNS service on the Soft AP is to be discovered make sure to call [connect] + * before calling this method. + * + * @param nsdServiceInfo NsdServiceInfo to be discovered. * @throws WifiNotEnabledException if the wifi is not enabled. - * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. - * Call [connect] to connect to the softap and bind to the network. */ suspend fun discoverServices( nsdServiceInfo: NsdServiceInfo = NsdServiceInfo() @@ -182,14 +199,24 @@ class SoftApManager( } ) { require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } - require(isBoundToNetwork) { throw FailedToBindToNetwork } - val serviceInfo = nsdListener - .discoverServices(nsdServiceInfo = nsdServiceInfo) + val serviceInfo = discoverNetworkServices(nsdServiceInfo = nsdServiceInfo) softAp?.apply { - connectionInfoDomain = ConnectionInfoDomain(ipv4Address = serviceInfo.host.toString()) + this.serviceInfo = serviceInfo } } + private suspend fun discoverNetworkServices( + macAddress: String? = null, + nsdServiceInfo: NsdServiceInfo + ): NsdServiceInfo { + val serviceInfo = nsdListener + .discoverServices( + macAddress = macAddress, + nsdServiceInfo = nsdServiceInfo + ) + return serviceInfo + } + /** * Lists the SSIDs scanned by the nRF700x device * @@ -231,18 +258,36 @@ class SoftApManager( */ @RequiresApi(Build.VERSION_CODES.Q) fun disconnect() { - isBoundToNetwork = false - connectivityManager.bindProcessToNetwork(null) - connectivityManager.unregisterNetworkCallback(networkCallback) + if (isConnected) { + isConnected = false + isBoundToNetwork = false + connectivityManager.bindProcessToNetwork(null) + connectivityManager.unregisterNetworkCallback(networkCallback) + } } /** - * Verifies if the provisioning completed successfully. Note for this to work, both the devices - * and provisioning app has to be connected to the same network. + * Verifies if the provisioning completed successfully. * - * @param nsdServiceInfo NsdServiceInfo instance. + * Note: Before calling this ensure that both the phone and the provisioned soft ap device are + * on the same wifi network. */ - suspend fun verify(nsdServiceInfo: NsdServiceInfo) { - discoverServices(nsdServiceInfo = nsdServiceInfo) + suspend fun verify() = softAp?.takeIf { + it.serviceInfo != null + }?.let { + val serviceInfo = discoverNetworkServices( + macAddress = it.macAddress, + nsdServiceInfo = NsdServiceInfo().apply { + serviceName = "wifiprov" + serviceType = "_http._tcp." + } + ) + val mac = serviceInfo.attributes[KEY_LINK_ADDR]?.toByteString()?.utf8() + mac == it.macAddress + } ?: false + + + companion object { + const val KEY_LINK_ADDR = "linkaddr" } } \ No newline at end of file From d0104137bb4b4e9da129e55189455aacd96c6c25 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 6 May 2024 15:03:34 +0200 Subject: [PATCH 065/101] Improvements to the API --- .../android/wifi/provisioner/softap/SoftApManager.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index fd350ed0..07074b1e 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -4,7 +4,6 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.content.Context import android.net.ConnectivityManager -import android.net.LinkAddress import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest @@ -20,7 +19,6 @@ import no.nordicsemi.android.wifi.provisioner.softap.domain.ScanResultsDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.domain.toApi import no.nordicsemi.android.wifi.provisioner.softap.domain.toDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.ConnectionInfoDomain import okhttp3.OkHttpClient import okhttp3.ResponseBody import okhttp3.logging.HttpLoggingInterceptor @@ -262,8 +260,8 @@ class SoftApManager( isConnected = false isBoundToNetwork = false connectivityManager.bindProcessToNetwork(null) - connectivityManager.unregisterNetworkCallback(networkCallback) } + connectivityManager.unregisterNetworkCallback(networkCallback) } /** From f398e58dd5d82d4109446ea209452f5efd3135d8 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 7 May 2024 13:07:53 +0200 Subject: [PATCH 066/101] Minor improvements --- .../ble/sections/ActionButtonSection.kt | 20 +++++++---- ...Module.kt => ConnectivityManagerModule.kt} | 9 +++-- .../softap/view/SoftApConnectorDialog.kt | 35 +++++++++++-------- .../viewmodel/SoftApProvisioningViewModel.kt | 11 +++++- .../softap/src/main/res/values/strings.xml | 4 ++- .../softap/NetworkServiceDiscoveryListener.kt | 31 ++++++---------- .../wifi/provisioner/softap/SoftApManager.kt | 31 ++++++---------- 7 files changed, 75 insertions(+), 66 deletions(-) rename feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/{WifiManagerModule.kt => ConnectivityManagerModule.kt} (70%) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt index 1bb89a43..82ac4a99 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ActionButtonSection.kt @@ -31,14 +31,14 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.Button +import androidx.compose.material3.ElevatedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -80,7 +80,7 @@ fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (ProvisioningViewEve onEvent(OnSelectWifiEvent) } } else if (viewEntity.network!!.isPasswordRequired() && viewEntity.password == null) { - ActionButton( stringResource(id = R.string.password_select)) { + ActionButton(stringResource(id = R.string.password_select)) { onEvent(OnShowPasswordDialog) } } else { @@ -92,11 +92,17 @@ fun ActionButtonSection(viewEntity: BleViewEntity, onEvent: (ProvisioningViewEve @Composable private fun ActionButton(text: String, onClick: () -> Unit) { - Box(modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)) { - Button( + Row( + modifier = Modifier + .fillMaxWidth() + .padding(all = 16.dp), + horizontalArrangement = Arrangement.Center + ) { + ElevatedButton( onClick = onClick, modifier = Modifier - .align(Alignment.Center) + .padding(all = 16.dp) + //.align(Alignment.Center) .widthIn(min = 100.dp) ) { Text(text = text) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiManagerModule.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/ConnectivityManagerModule.kt similarity index 70% rename from feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiManagerModule.kt rename to feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/ConnectivityManagerModule.kt index 51e4b137..013807e7 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/WifiManagerModule.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/di/ConnectivityManagerModule.kt @@ -1,13 +1,13 @@ package no.nordicsemi.android.wifi.provisioner.softap.di import android.content.Context +import android.net.ConnectivityManager import android.net.wifi.WifiManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager import javax.inject.Singleton /** @@ -15,10 +15,15 @@ import javax.inject.Singleton */ @Module @InstallIn(SingletonComponent::class) -object WifiManagerModule { +object ConnectivityManagerModule { @Provides @Singleton fun provideWifiManager(@ApplicationContext context: Context) = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + + @Provides + @Singleton + fun provideConnectivityManager(@ApplicationContext context: Context) = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index 28b1a956..0d1c3d3f 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -69,31 +69,22 @@ internal fun SoftApConnectorDialog( ) } else if (!isNetworkServiceDiscoveryCompleted) { showButtons = false - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - CircularProgressIndicator() - Spacer(modifier = Modifier.size(16.dp)) - Text( - text = stringResource(id = R.string.discovering_services), - style = MaterialTheme.typography.bodyMedium - ) - } + CircularProgressIndicatorContent( + text = stringResource(id = R.string.discovering_services) + ) } else { showButtons = true } }, dismissButton = { - if(showButtons) { + if (showButtons) { TextButton(onClick = dismiss) { Text(text = "Cancel") } } }, confirmButton = { - if(showButtons) { + if (showButtons) { TextButton(onClick = { connect(ssid, Open) }) { Text(text = "Confirm") } @@ -139,4 +130,20 @@ private fun SoftApConnectorContent( } ) } +} + +@Composable +fun CircularProgressIndicatorContent(text: String) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator() + Spacer(modifier = Modifier.size(16.dp)) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium + ) + } } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 75a84849..8939ad94 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -31,6 +31,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel +import android.net.ConnectivityManager import android.net.wifi.WifiManager import android.os.Build import android.util.Log @@ -202,7 +203,15 @@ class SoftApProvisioningViewModel @Inject constructor( ) ) // discoverServices() - verify() + if(verify()){ + // wifiManager.network + _state.value = state.copy( + device = softApManager.softAp, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.CONNECTED + ) + ) + } } else { _state.value = state.copy( provisioningStatus = Resource.createError( diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 94c8db68..a9393693 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -2,7 +2,9 @@ "Wi-Fi Provisioner " Soft AP - Enter the SSID and password of the Soft AP you want to connect to. + Enter the SSID and passphrase of the Soft AP you want to connect to. + \n\nNote: Make sure the nRF 700x device is powered on. + Discovering services… Change Wi-Fi Dismiss diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 6abd64ed..13b849fc 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -37,14 +37,13 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage val resolveListener = object : NsdManager.ResolveListener { override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { // Called when the resolve fails. Use the error code to debug. - Log.e("AAAA", "Resolve failed: $errorCode") + Log.e("AAA", "Resolve failed: $errorCode") } override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { - Log.d("AAAA", "Resolve success: $serviceInfo") + Log.d("AAA", "Resolve success: $serviceInfo") serviceInfo?.let { if (macAddress == null) { - Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") stopDiscovery(it) } else { val mac = serviceInfo.attributes?.get(KEY_LINK_ADDR)?.toByteString()?.utf8() @@ -52,17 +51,11 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage stopDiscovery(it) } } - /*if(nsdServiceInfo.attributes.isEmpty() || nsdServiceInfo.attributes == serviceInfo.attributes){ - Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") - _discoveredIps.add(it.host) - continuation.resume(it) - nsdManager.stopServiceDiscovery(nsdListener) - }*/ } } private fun stopDiscovery(serviceInfo: NsdServiceInfo) { - Log.d("AAAA", "Service attributes: ${serviceInfo.attributes}") + Log.d("AAA", "Service attributes: ${serviceInfo.attributes}") _discoveredIps.add(serviceInfo.host) continuation.resume(serviceInfo) nsdManager.stopServiceDiscovery(nsdListener) @@ -73,18 +66,14 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage // Called as soon as service discovery begins. override fun onDiscoveryStarted(regType: String) { - Log.d("AAAA", "Service discovery started $regType") + Log.d("AAA", "Service discovery started $regType") } override fun onServiceFound(service: NsdServiceInfo) { - Log.d("AAAA", "Service discovered $service") + Log.d("AAA", "Service discovered $service") // Check if the service name found matches the service name we are looking for. - // Service attributes could be null if the service is not yet resolved, so if both [service] and [nsdServiceInfo] - // may be have null attributes, we can assume that this device and its services has not been discovered yet. - // In the case of [nsdServiceInfo] having attributes, we can assume that the device has been discovered and we can - // compare the link address to see if the service is the one we are looking for. if (service.serviceName == nsdServiceInfo.serviceName) { - Log.d("AAAA", "Resolving service $service") + Log.d("AAA", "Resolving service $service") nsdManager.resolveService(service, resolveListener) } } @@ -92,16 +81,16 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceLost(service: NsdServiceInfo) { // When the network service is no longer available. // Internal bookkeeping code goes here. - Log.e("AAAA", "service lost: $service") + Log.e("AAA", "service lost: $service") } override fun onDiscoveryStopped(serviceType: String) { - Log.i("AAAA", "Discovery stopped: $serviceType") + Log.i("AAA", "Discovery stopped: $serviceType") } override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { Log.e( - "AAAA", "error on starting service discovery for " + + "AAA", "error on starting service discovery for " + "$serviceType failed: $errorCode" ) continuation.resumeWithException( @@ -110,7 +99,7 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage } override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e("AAAA", "Discovery failed: Error code:$errorCode") + Log.e("AAA", "Discovery failed: Error code:$errorCode") continuation.resumeWithException( Throwable("Discovery failed: Error code:$errorCode") ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 07074b1e..3537e5c2 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -93,7 +93,7 @@ class SoftApManager( .build() .create(SoftApProvisioningService::class.java) - private lateinit var networkCallback: ConnectivityManager.NetworkCallback + private var networkCallback: ConnectivityManager.NetworkCallback? = null /** * Connects to an unprovisioned wifi device by establishing a temporary wifi network connection @@ -112,22 +112,10 @@ class SoftApManager( ssid: String, passphraseConfiguration: PassphraseConfiguration, ): Unit = suspendCancellableCoroutine { continuation -> - if (!wifiManager.isWifiEnabled) - continuation.resumeWithException( - exception = WifiNotEnabledException - ) - /* - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - wifiManager.isWifiEnabled = true - val wifiConfiguration = WifiConfiguration() - wifiConfiguration.SSID = String.format("\"%s\"", ssid) - wifiConfiguration.preSharedKey = String.format("\"%s\"", passphraseConfiguration.passphrase) - val wifiID = wifiManager.addNetwork(wifiConfiguration) - Log.d("AAAA", "wifiID: $wifiID") - wifiConfiguration.networkId = wifiID - wifiManager.enableNetwork(wifiID, true) - } else { - }*/ + if (!wifiManager.isWifiEnabled) { + continuation.resumeWithException(exception = WifiNotEnabledException) + } + networkCallback = object : ConnectivityManager.NetworkCallback() { @RequiresApi(Build.VERSION_CODES.Q) @@ -172,11 +160,11 @@ class SoftApManager( .setNetworkSpecifier(networkSpecifier) .build() - connectivityManager.requestNetwork(request, networkCallback) + connectivityManager.requestNetwork(request, networkCallback!!) // Invoked if the coroutine calling this suspend function is cancelled. continuation.invokeOnCancellation { - connectivityManager.unregisterNetworkCallback(networkCallback) + connectivityManager.unregisterNetworkCallback(networkCallback!!) } } @@ -261,7 +249,10 @@ class SoftApManager( isBoundToNetwork = false connectivityManager.bindProcessToNetwork(null) } - connectivityManager.unregisterNetworkCallback(networkCallback) + + networkCallback?.let { + connectivityManager.unregisterNetworkCallback(it) + } } /** From 70fa063d0aea29ec2ab519f06ff5892639bc955a Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 13 May 2024 11:05:58 +0200 Subject: [PATCH 067/101] Add missing API version checks --- .../nordicsemi/android/wifi/provisioner/HomeScreen.kt | 7 +++++-- .../provisioner/softap/view/SoftApDestinations.kt | 4 +++- .../softap/view/SoftApProvisioningScreen.kt | 3 +++ .../softap/viewmodel/SoftApProvisioningViewModel.kt | 11 ++++------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 89cf8265..8a2e60e3 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -31,6 +31,7 @@ package no.nordicsemi.android.wifi.provisioner +import android.os.Build import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -114,8 +115,10 @@ fun HomeScreen() { ProvisionOverBle { vm.navigateTo(BleProvisioningDestination) } - ProvisionOverWifi { - vm.navigateTo(SoftApProvisionerDestination) + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + ProvisionOverWifi { + vm.navigateTo(SoftApProvisionerDestination) + } } } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index e7fb3557..5ef13ba9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -21,7 +21,9 @@ val SoftApWifiScannerDestination = createDestination( val SoftApProvisionerDestinations = listOf( defineDestination(SoftApProvisionerDestination) { - SoftApProvisioningScreen() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + SoftApProvisioningScreen() + } }, defineDestination(SoftApWifiScannerDestination) { val viewModel = hiltViewModel() diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index af4daced..edfd17cd 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -31,6 +31,8 @@ package no.nordicsemi.android.wifi.provisioner.softap.view +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -66,6 +68,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSele import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent +@RequiresApi(Build.VERSION_CODES.Q) @OptIn(ExperimentalMaterial3Api::class) @Composable fun SoftApProvisioningScreen() { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 8939ad94..257f04dc 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -31,16 +31,14 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel -import android.net.ConnectivityManager -import android.net.wifi.WifiManager import android.os.Build import android.util.Log +import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -75,7 +73,6 @@ import javax.inject.Inject @HiltViewModel class SoftApProvisioningViewModel @Inject constructor( private val softApManager: SoftApManager, - private val wifiManager: WifiManager, private val navigationManager: Navigator, savedStateHandle: SavedStateHandle, ) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { @@ -90,11 +87,13 @@ class SoftApProvisioningViewModel @Inject constructor( .launchIn(viewModelScope) } + @RequiresApi(Build.VERSION_CODES.Q) override fun onCleared() { super.onCleared() softApManager.disconnect() } + @RequiresApi(Build.VERSION_CODES.Q) fun onEvent(event: ProvisioningViewEvent) { when (event) { OnFinishedEvent -> finish() @@ -163,6 +162,7 @@ class SoftApProvisioningViewModel @Inject constructor( _state.value = _state.value.copy(password = password) } + @RequiresApi(Build.VERSION_CODES.Q) private fun connect( ssid: String = "0018F0-nrf-wifiprov", passphraseConfiguration: PassphraseConfiguration = Open @@ -224,9 +224,6 @@ class SoftApProvisioningViewModel @Inject constructor( } } - private fun isConnectedToTheSameNetwork() { - } - private fun WifiData.toConfig(): WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo From b17d809ce054e307d216519c0e7e69c643a4ce31 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 08:51:05 +0200 Subject: [PATCH 068/101] Adds API checks and some improvements --- .../android/wifi/provisioner/HomeScreen.kt | 23 ++++++++- app/src/main/res/values/strings.xml | 1 + .../softap/view/entity/SoftApViewEntity.kt | 3 +- .../viewmodel/SoftApProvisioningViewModel.kt | 48 ++++++++++--------- feature/ui/src/main/res/values/strings.xml | 10 ++-- 5 files changed, 53 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 8a2e60e3..65ee1e0d 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -49,13 +49,19 @@ import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.app.R @@ -68,6 +74,9 @@ import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverWifi @Composable fun HomeScreen() { val vm: SimpleNavigationViewModel = hiltViewModel() + val context = LocalContext.current + val scope = rememberCoroutineScope() + val snackbarHostState = remember { SnackbarHostState() } Scaffold( contentWindowInsets = WindowInsets(0, 0, 0, 0), topBar = { @@ -75,6 +84,9 @@ fun HomeScreen() { text = stringResource(id = R.string.label_ble_provisioner) ) }, + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + }, ) { innerPadding -> LazyColumn( modifier = Modifier @@ -115,9 +127,16 @@ fun HomeScreen() { ProvisionOverBle { vm.navigateTo(BleProvisioningDestination) } - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - ProvisionOverWifi { + ProvisionOverWifi { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { vm.navigateTo(SoftApProvisionerDestination) + } else { + scope.launch { + snackbarHostState.showSnackbar( + message = context.getString(R.string.error_softap_not_supported), + actionLabel = context.getString(R.string.dismiss) + ) + } } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9b34b9ef..9605dba3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -139,4 +139,5 @@ Sort by: Name RSSI + This feature requires an Android device running Android 10 or above. \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt index 2d7d2140..17cccd92 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt @@ -24,7 +24,8 @@ data class SoftApViewEntity( override fun hasFinished(): Boolean { val status = (provisioningStatus as? Success)?.data - return status == WifiConnectionStateDomain.DISCONNECTED + return status == WifiConnectionStateDomain.DISCONNECTED || + status == WifiConnectionStateDomain.CONNECTED } override fun hasFinishedWithSuccess(): Boolean { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 257f04dc..c5cc8c53 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -36,6 +36,7 @@ import android.util.Log import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers @@ -182,36 +183,18 @@ class SoftApProvisioningViewModel @Inject constructor( val state = _state.value val network = state.network ?: return val handler = CoroutineExceptionHandler { _, throwable -> - Log.d("AAAA", "Provisioning failed $throwable") + // There is always chance that a socket timeout is thrown from the DK during + // provisioning due to timing constraints. In such cases, we can ignore the response + // and assume that the provisioning was successful. if (throwable is SocketTimeoutException) { - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.DISCONNECTED - ) - ) + handleResponse(state) } } viewModelScope.launch(Dispatchers.IO + handler) { softApManager.run { provision(config = network.toConfig()).also { response -> if (response.isSuccessful) { - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.DISCONNECTED - ) - ) - // discoverServices() - if(verify()){ - // wifiManager.network - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.CONNECTED - ) - ) - } + handleResponse(state) } else { _state.value = state.copy( provisioningStatus = Resource.createError( @@ -224,6 +207,25 @@ class SoftApProvisioningViewModel @Inject constructor( } } + private fun handleResponse(state : SoftApViewEntity){ + viewModelScope.launch { + _state.value = state.copy( + device = softApManager.softAp, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.DISCONNECTED + ) + ) + if(softApManager.verify()){ + _state.value = state.copy( + device = softApManager.softAp, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.CONNECTED + ) + ) + } + } + } + private fun WifiData.toConfig(): WifiConfigDomain { val state = _state.value val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 5e56cfcd..20bb1382 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -96,13 +96,11 @@ Persistent storage Provision over Bluetooth LE - This mode allows provisioning a nRF700x device to a - Wi-Fi network by providing the Wi-Fi credentials, directly connecting to the - device using Bluetooth LE + This mode uses secure Bluetooth LE link to transfer + Wi-Fi credentials to the provisionee and verify provisioning status. Provision over Wi-Fi - This mode allows provisioning a nRF700x device to a - Wi-Fi network by providing the Wi-Fi credentials over Wi-Fi by directly connecting to the - Soft AP advertised by the device. + This mode uses temporary a Wi-Fi network (Soft AP) + created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. \ No newline at end of file From 7133b6c329ec7e43e485d9271eb2d38e07fb9639 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 09:37:51 +0200 Subject: [PATCH 069/101] Adds a progress dialog as provisioning may take a few seconds to complete. --- .../softap/view/SoftApConnectorDialog.kt | 20 +--------- .../softap/view/SoftApProvisioningDialog.kt | 40 +++++++++++++++++++ .../softap/view/SoftApProvisioningScreen.kt | 8 +++- .../softap/view/entity/SoftApViewEntity.kt | 1 + .../viewmodel/SoftApProvisioningViewModel.kt | 19 +++++++-- .../softap/src/main/res/values/strings.xml | 3 ++ .../ui/CircularProgressIndicatorContent.kt | 30 ++++++++++++++ 7 files changed, 97 insertions(+), 24 deletions(-) create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt create mode 100644 feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/CircularProgressIndicatorContent.kt diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index 0d1c3d3f..3ae8dab8 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -1,6 +1,5 @@ package no.nordicsemi.android.wifi.provisioner.softap.view -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -10,7 +9,6 @@ import androidx.compose.material.icons.outlined.Visibility import androidx.compose.material.icons.outlined.VisibilityOff import androidx.compose.material.icons.outlined.Wifi import androidx.compose.material3.AlertDialog -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -22,7 +20,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation @@ -32,6 +29,7 @@ import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.feature.softap.R import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration +import no.nordicsemi.android.wifi.provisioner.ui.CircularProgressIndicatorContent @Composable @@ -130,20 +128,4 @@ private fun SoftApConnectorContent( } ) } -} - -@Composable -fun CircularProgressIndicatorContent(text: String) { - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - CircularProgressIndicator() - Spacer(modifier = Modifier.size(16.dp)) - Text( - text = text, - style = MaterialTheme.typography.bodyMedium - ) - } } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt new file mode 100644 index 00000000..085c7f8b --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt @@ -0,0 +1,40 @@ +package no.nordicsemi.android.wifi.provisioner.softap.view + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.ui.CircularProgressIndicatorContent + + +@Composable +internal fun SoftApProvisioningDialog(dismiss: () -> Unit) { + + AlertDialog( + onDismissRequest = dismiss, + icon = { Icon(imageVector = Icons.Outlined.Settings, contentDescription = null) }, + title = { + Text( + text = stringResource(id = R.string.provisioning), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + CircularProgressIndicatorContent( + text = stringResource(id = R.string.provisioning_device_rationale) + ) + }, + dismissButton = {}, + confirmButton = {} + ) +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index edfd17cd..bfb0d01e 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -75,7 +75,7 @@ fun SoftApProvisioningScreen() { val viewModel = hiltViewModel() val state by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (ProvisioningViewEvent) -> Unit = { viewModel.onEvent(it) } + val onEvent: (ProvisioningViewEvent) -> Unit = viewModel::onEvent Column { NordicAppBar( text = stringResource(id = R.string.label_wifi_provisioner), @@ -113,6 +113,12 @@ fun SoftApProvisioningScreen() { onEvent(OnHidePasswordDialog) } } + + if(state.showProvisioningDialog){ + SoftApProvisioningDialog{ + onEvent(OnFinishedEvent) + } + } } @Composable diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt index 17cccd92..76d9c9f9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt @@ -19,6 +19,7 @@ data class SoftApViewEntity( override val isConnected: Boolean = true, val isAuthorized: Boolean = false, val showSoftApDialog: Boolean = false, + val showProvisioningDialog: Boolean = false, val isNetworkServiceDiscoveryCompleted: Boolean? = null ) : ViewEntity { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index c5cc8c53..9e6747d7 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -97,7 +97,10 @@ class SoftApProvisioningViewModel @Inject constructor( @RequiresApi(Build.VERSION_CODES.Q) fun onEvent(event: ProvisioningViewEvent) { when (event) { - OnFinishedEvent -> finish() + OnFinishedEvent -> { + _state.value = _state.value.copy(showProvisioningDialog = false) + finish() + } is OnPasswordSelectedEvent -> onPasswordSelected(event.password) OnSelectDeviceClickEvent -> provisionNextDevice() is OnSoftApConnectEvent -> { @@ -180,6 +183,7 @@ class SoftApProvisioningViewModel @Inject constructor( } private fun provision() { + _state.value = _state.value.copy(showProvisioningDialog = true) val state = _state.value val network = state.network ?: return val handler = CoroutineExceptionHandler { _, throwable -> @@ -187,7 +191,13 @@ class SoftApProvisioningViewModel @Inject constructor( // provisioning due to timing constraints. In such cases, we can ignore the response // and assume that the provisioning was successful. if (throwable is SocketTimeoutException) { - handleResponse(state) + _state.value = state.copy( + device = softApManager.softAp, + provisioningStatus = Resource.createSuccess( + data = WifiConnectionStateDomain.CONNECTED, + ), + showProvisioningDialog = false + ) } } viewModelScope.launch(Dispatchers.IO + handler) { @@ -219,8 +229,9 @@ class SoftApProvisioningViewModel @Inject constructor( _state.value = state.copy( device = softApManager.softAp, provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.CONNECTED - ) + data = WifiConnectionStateDomain.CONNECTED, + ), + showProvisioningDialog = false ) } } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index a9393693..453630a7 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -27,5 +27,8 @@ Device status Provisioning data Upload status + Provisioning + Please wait while the device is being provisioned. + This may take around 5-10 seconds to complete. \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/CircularProgressIndicatorContent.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/CircularProgressIndicatorContent.kt new file mode 100644 index 00000000..1022e20d --- /dev/null +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/CircularProgressIndicatorContent.kt @@ -0,0 +1,30 @@ +package no.nordicsemi.android.wifi.provisioner.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun CircularProgressIndicatorContent(text: String) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator() + Spacer(modifier = Modifier.size(16.dp)) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium + ) + } +} \ No newline at end of file From c09e00f953864417bb23a724421d801da5fa0bd6 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 14:07:25 +0200 Subject: [PATCH 070/101] Improvements from UX dry run --- app/src/main/res/values/strings.xml | 2 +- feature/ble/src/main/res/values/strings.xml | 2 +- .../softap/sections/ActionButtonSection.kt | 6 ++--- .../softap/view/SoftApConnectorDialog.kt | 4 ++-- .../softap/view/SoftApProvisioningDialog.kt | 24 +++++++++++++------ .../softap/view/SoftApProvisioningScreen.kt | 2 +- .../viewmodel/SoftApProvisioningViewModel.kt | 15 +++++------- .../softap/src/main/res/values/strings.xml | 6 +++-- .../ui/view/section/DeviceSection.kt | 6 ++--- .../ui/view/section/PasswordSection.kt | 2 +- .../ui/view/section/WifiSection.kt | 2 +- feature/ui/src/main/res/values/strings.xml | 2 +- 12 files changed, 40 insertions(+), 33 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9605dba3..a91058a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -32,7 +32,7 @@ nRF Wi-Fi Provisioner - Change + Change An icon of nRF70 Series The nRF Wi-Fi Provisioner app allows provisioning nRF 700x devices to Wi-Fi networks over Bluetooth LE.\n\n diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml index 1c1f78e5..53ff3662 100644 --- a/feature/ble/src/main/res/values/strings.xml +++ b/feature/ble/src/main/res/values/strings.xml @@ -32,7 +32,7 @@ Bluetooth LE - Change + Change An icon of nRF70 Series The nRF Wi-Fi Provisioner app allows provisioning nRF 700x devices to Wi-Fi networks over Bluetooth LE.\n\n diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt index 4982c5ae..ca972aee 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt @@ -64,10 +64,8 @@ fun ActionButtonSection(viewEntity: SoftApViewEntity, onEvent: (ProvisioningView ActionButton( stringResource(id = R.string.password_select)) { onEvent(OnShowPasswordDialog) } - } else if(viewEntity.hasFinished()) { - ActionButton(stringResource(id = R.string.next_device)) { - onEvent(OnProvisionNextDeviceEvent) - } + } else if(viewEntity.hasFinished() || viewEntity.hasFinishedWithSuccess()) { + } else { ActionButton(stringResource(id = R.string.provision)) { onEvent(OnProvisionClickEvent) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index 3ae8dab8..fa70ce2e 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -108,7 +108,7 @@ private fun SoftApConnectorContent( ) Spacer(modifier = Modifier.size(size = 16.dp)) OutlinedTextField(value = ssid, onValueChange = onSsidChange) - Spacer(modifier = Modifier.size(size = 8.dp)) + /*Spacer(modifier = Modifier.size(size = 8.dp)) OutlinedTextField( value = password, onValueChange = onPasswordChange, @@ -126,6 +126,6 @@ private fun SoftApConnectorContent( ) } } - ) + )*/ } } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt index 085c7f8b..70d4c3ab 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt @@ -7,17 +7,18 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity import no.nordicsemi.android.wifi.provisioner.ui.CircularProgressIndicatorContent @Composable -internal fun SoftApProvisioningDialog(dismiss: () -> Unit) { - +internal fun SoftApProvisioningDialog(state: SoftApViewEntity, dismiss: () -> Unit) { AlertDialog( onDismissRequest = dismiss, icon = { Icon(imageVector = Icons.Outlined.Settings, contentDescription = null) }, @@ -30,11 +31,20 @@ internal fun SoftApProvisioningDialog(dismiss: () -> Unit) { ) }, text = { - CircularProgressIndicatorContent( - text = stringResource(id = R.string.provisioning_device_rationale) - ) + if (state.hasFinished() || state.hasFinishedWithSuccess()) { + Text(text = stringResource(id = R.string.provisioning_device_success)) + } else { + CircularProgressIndicatorContent( + text = stringResource(id = R.string.provisioning_device_rationale) + ) + } }, - dismissButton = {}, - confirmButton = {} + confirmButton = { + if (state.hasFinished()) { + TextButton(onClick = dismiss) { + Text(text = stringResource(id = R.string.ok)) + } + } + } ) } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt index bfb0d01e..98c904db 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt @@ -115,7 +115,7 @@ fun SoftApProvisioningScreen() { } if(state.showProvisioningDialog){ - SoftApProvisioningDialog{ + SoftApProvisioningDialog(state){ onEvent(OnFinishedEvent) } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt index 9e6747d7..4edf6dfa 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt @@ -131,10 +131,9 @@ class SoftApProvisioningViewModel @Inject constructor( } private fun finish() { - viewModelScope.launch { - release() - _state.value = SoftApViewEntity() - } + release() + _state.value = SoftApViewEntity() + navigateUp() } private fun release() { @@ -168,7 +167,7 @@ class SoftApProvisioningViewModel @Inject constructor( @RequiresApi(Build.VERSION_CODES.Q) private fun connect( - ssid: String = "0018F0-nrf-wifiprov", + ssid: String = "nrf-wifiprov", passphraseConfiguration: PassphraseConfiguration = Open ) { viewModelScope.launch { @@ -195,8 +194,7 @@ class SoftApProvisioningViewModel @Inject constructor( device = softApManager.softAp, provisioningStatus = Resource.createSuccess( data = WifiConnectionStateDomain.CONNECTED, - ), - showProvisioningDialog = false + ) ) } } @@ -230,8 +228,7 @@ class SoftApProvisioningViewModel @Inject constructor( device = softApManager.softAp, provisioningStatus = Resource.createSuccess( data = WifiConnectionStateDomain.CONNECTED, - ), - showProvisioningDialog = false + ) ) } } diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 453630a7..de87bcf3 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -2,8 +2,8 @@ "Wi-Fi Provisioner " Soft AP - Enter the SSID and passphrase of the Soft AP you want to connect to. - \n\nNote: Make sure the nRF 700x device is powered on. + Enter the SSID of the nRF700x device you want to connect to. + \n\nNote: Make sure the nRF 700x device is powered on and in range. Discovering services… Change Wi-Fi @@ -30,5 +30,7 @@ Provisioning Please wait while the device is being provisioned. This may take around 5-10 seconds to complete. + OK + Provisioning completed. \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt index 1a97914c..ae596fd0 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt @@ -58,7 +58,7 @@ fun BluetoothDevice( isEditable = isEditable, description = address, onClick = { onEvent(OnSelectDeviceClickEvent) }, - buttonText = stringResource(id = R.string.change_device) + buttonText = stringResource(id = R.string.change) ) } @@ -76,7 +76,7 @@ fun SoftApDevice( isEditable = isEditable, description = address, onClick = { onEvent(OnSelectDeviceClickEvent) }, - buttonText = stringResource(id = R.string.change_device) + buttonText = stringResource(id = R.string.change) ) } @@ -102,7 +102,7 @@ private fun DeviceNotSelectedSection( isEditable = false, description = "Please select a device to provision", onClick = { onEvent(OnProvisionNextDeviceEvent) }, - buttonText = stringResource(id = R.string.change_device) + buttonText = stringResource(id = R.string.change) ) } diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt index 3b0e344e..6b8f95d4 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt @@ -50,6 +50,6 @@ fun PasswordSection(isEditable: Boolean = false, onEvent: (ProvisioningViewEvent onClick = { onEvent(OnShowPasswordDialog) }, - buttonText = stringResource(id = R.string.set_password) + buttonText = stringResource(id = R.string.change) ) } diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt index d2f8b6d7..2d28d242 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt @@ -57,7 +57,7 @@ fun WifiSection( onClick = { onEvent(OnSelectWifiEvent) }, - buttonText = stringResource(id = R.string.change_device) + buttonText = stringResource(id = R.string.change) ) } } diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 20bb1382..131714f6 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Change + Change Sort by: Name From a7ca9f59b8c48a3d9f6f9d90cd8aa37be77d90e5 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 14:14:52 +0200 Subject: [PATCH 071/101] Improvements from UX dry run --- feature/softap/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index de87bcf3..4a2d57b2 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -1,8 +1,8 @@ "Wi-Fi Provisioner " - Soft AP - Enter the SSID of the nRF700x device you want to connect to. + Connect to Device + Enter the SSID of the Soft AP you want to connect to. \n\nNote: Make sure the nRF 700x device is powered on and in range. Discovering services… From d549085720032654e7c77cf761c063d2d02dd5d8 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 14:20:38 +0200 Subject: [PATCH 072/101] Improvements from UX dry run --- .../android/wifi/provisioner/HomeScreen.kt | 3 --- .../main/res/drawable-night-xxhdpi/ic_nrf70.png | Bin 0 -> 13182 bytes 2 files changed, 3 deletions(-) create mode 100644 feature/ui/src/main/res/drawable-night-xxhdpi/ic_nrf70.png diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 65ee1e0d..2a8d0d14 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -33,7 +33,6 @@ package no.nordicsemi.android.wifi.provisioner import android.os.Build import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets @@ -55,7 +54,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -113,7 +111,6 @@ fun HomeScreen() { modifier = Modifier .widthIn(max = 200.dp) .padding(8.dp) - .background(Color.White) ) } } diff --git a/feature/ui/src/main/res/drawable-night-xxhdpi/ic_nrf70.png b/feature/ui/src/main/res/drawable-night-xxhdpi/ic_nrf70.png new file mode 100644 index 0000000000000000000000000000000000000000..c673dbc9dc4ce7ed477bb5ed8d7b7877dd9bb203 GIT binary patch literal 13182 zcmeHtcT|(v)^{ihO104hq&T9~&>;{&I!YTlh(ZVW!yQv&J(j~fhanIMi-Eqj z83aPJ489{64}z82OqKiKM`MVE4b}`1DB$boR6B60!Wa*nb}{JoRIXiY?^MtnKpvv@a>Uq>b>0lbP z#!88%Xfj2ZS7O#wz0&~evqe@Wu6DTYA)YmVtWQ!7rW;IvSj&FlQXYu;C=*8h=yCee z$6B~V9m9=L+nY2Ud1PSQO*btqQv)rnKg|I~q~h+w^&2&Kn;gt9>g4j}3yj^%gniS| z;q^Fi*EF-|Z~-jIe)E74&x7NfdiC!{Mp~SD>ziz?8LZE7ko^=9I4QR}He4H-;F)%`99Y{X$cAtKSbv7Rnz zN}A%2D{bbTtQ0K9+{Ru$bAKfD-QG&c=c-kne_xGA1ma~zfj9;~arS}DhofEWf?4s0 zbBo!tEQOo2qgRjd?;dGMKl8+}@GzG$hv|*OpB8TH)l+j3D(M}pL| zd|K&llxYkn6EB6H%3;%ZTzP>6VYpQnbmw(He27FO5o^%{J39~^sNbWziR(W>+J(4* z^s+HBgdu&rBoWR&PAJJBFJF*%5QwUJkS_x1fx-$nq0nyLa3M-nt&o75GhE18-Uw>s ztA%oP(+}}OnTHr#AVWNm%FaUSYKK*WV1R)a3X2d3^78b?z=GgH`+Q;Gcj~f~kib3( z)&nkNV`M6z<>QAEkdu^?gi7cHxdq4wsT~$j^>cQCnQ80(!2*1O3%O#kzA!1Nz`#Js zKv_v2KeUvzva+%iR7OfhMgmYsV1m7|h#(1Xj4+kOFCN+`4ARfd7whKZEkNaoaPslT z!i9vubAdng^YS$^`is3c<_|9be@F!(e5Ir%p;BI6Qh(op!RiD6CVwdOzwW?TfKw`E zhQj#x`yo*}0Vr>*@ZVYJ85o)V#er%P+Re*%-zea`e+Y9%{zd2O@8`KsmRyNpX{6ScSV4>zxe-y`cK>Ui2;?75lq_$=}#4EpbZzI>I-xB zLAp7^_J38Bc2aghC_72W$V)3p$RU)ZC7k4C5E6=V3JP-a^3qU6CF#GhGVsP=5#C4? zl@(wv=?3^HBA`g563R(JUd~xwLQW1PC!ypljg&x1BV>?BCwV0$7sbD^F!6H(S&8uc zyH-?I&Qw-V8EFMs1sMrhC21K6IVUBA1Oh6nAR#X=FDt7gBdsjw0^MgtjRWkwsR3L_ zM)Gefrk)6_i;tfdT*wH46fiOW7p;Yx7s?!qpn6SOQCeP6QC>z_Rz^l%Mq1`yL{=z2 z49GYtQ)#HAtit{iXCzD)utb2&aq~i;QBuC%==}%OxWIrlz_SQyq5{tQ>%bV8mLCd% z_3^Xt@$rNUQI!>-vi$3@5jaoI2rNPyfkgpnP#HNGR30WRZy_xQ1OMe^#h@}U=-=pl zoZVc4|6kP9(<7kzE9Uxc7$84*f9cneGDltg_376~Pq+QEBp|SVDqslYFB33`0F?8- zo`Bb{M@UzMHyQ=t{e1=mA^9}@$K6@tdsouxH6VslqRh<21QKTbml(yB!3BCM2ZA}jBZ zwno=}zpvDJGmWM)bhkFQ0N3&6K|PCX{~&w~dl5+dPkv?iha(vwBju8hXAI3&XZPe4 zwxuh!&}jLSEDEubk*p9`$>LiNHYH!~Nx0bvm*c!n7Yx?c!ncMuJmo%aU>UKHx`cXC zAOik)IVZ33R%Gp56w|s-VXni1!HZD`=JTn!uh(mjRWHxGM~FOGUMr-X#D?Y_i*0(B zop2~DAC33+sV`HRgb?h5YW?>*gtk3mYg5i;6bpBLF~e2Mc-bU2HCsX=3_`%R!EUYD z6YHlJAq)m8XWPDcCmPOZF(HQ0W_&Tky zY0XqoUV7NiyRWhhEIF)!$PQnDYwW}AXD*xGxuLp?C6xZ@xgfSsWlvR(!N<+r_OFNf#aD(Dj^YQB9bZmQN}6swGDm z-kWka6LOxFeeyODWy#?HBMs4M(Ol;h=sZ$($$%a<9li0qRP5lCgp2eCoM^Mn z9o^kqcNciHB%=i(2oON%^t@8U4lQ*@%>bi`x#F98K?Mk)012(OAi?_LQl5 z@6|0;_!oP4LZ4Q?s zJbck)%F)~49)r6{JaM9(}-7A;w z_C&2mm3FJ_z=!naH7VvNOB=9AMW4y(VDW3Ys*f@AD@>eLr}AD0iA=q}<4(d~dcm-r z7yBFB3Uy>h)B2p{@-mq|rNG(?3vcYKGDbW<%~AR6-24wQLJ^BaY?WB;7E&&j z-mG9)&exHq3YuPtyid`wSv~Zvru5QT^-3nl@RDz>OXLWyCV(7H3%@Twu|_StoXA;u zA^DZ~Gi(-L3O}$P^lFvNCHr6-@~4t**yomkp-br@H9gPc_m&%4lB$LeEk|5oQJeN% zyL!uu(La#wu8xzb$j2?twiWA=lXfrFxWdua1r+~XBJ#ps&l@)S5PC%Tq}Ur0F1ZKy zYN2Xx;^en!=&1{KF;A0C35m9GOa+*P7jMiJ)ZOAsVVr^wy&{*o84A6# zz-yF|-t4V+c6*XZtFsb1EMF_=NZ{yO^dH|iJALcm(0uETxmeF3Ebr3AlZywKihYty zxbK{`q4mz1dnmPaMb0@lkT|E?MFA%S9M@3cslacip5yc~kPf!_ah#z+Z7oa+&}S5M9<9zVjkL~nb2wMZDxwpQs2fGOCLLyS<{W^<&SN9M;a(q9RzEj_vZynF7) zeA?%y(-K!Vw`m2Vpy|20&y@3_PXdxm4lTK&^pw&Hsuj~!!vpRw-qOz4ll{Clq(<;! z`l|g>k8je_mYKATc_tlZD_S`{2oJe< zenf?7BsBg`F5wQitGv|sVUBM1_XX8ZxMfmznruz9LG*@qI(^?6*C$jD>qJvA;x#=svjkQdtN*f+S7-vu#v3rBQL;9Ol`WeKUe|?%gyEp9${9RD@jB*ii5TgxZm<6OQTt*LM7GuC2yth;){uZ+PUX2o69A z+IlLh=*!aGW|<<@;_{J05CZ<@&*KwhW~~Qb51t4$^6F3W9_B)?$_)1lc1HGJJ~Hvi zirjy}^MJNK%>E(qL(l^GGQLXZeHa})ml#P8i^rKM&0s?VnRS3%i|XeQM+$4<5#g`N zqDg&}m>;_ps51h&8f0ZGZ(Ce;6{O$2R(aHedX6sn#Z{3pQA#8WSf((#jiq!|&3PK{^>_KSe`_x0>gx{6#@3*P^3^c3Y8qCT!MeF=!vc+yF2c+)VtHOYbsTNp z)-7wHS3Jd;6FwZ7)Ym*_PAMxqc4EPTj4Ki44d+kGGcF6XlKrYUV4PU%<{pCzEZUpp zB)P{jHX9@Tzn zQ)wn;zrJ()Vr@g%h!yIp$g7T?jbhOlk5Xt{jy{^Pn7kp_zuGr=S%88To-(rJSR1~a z)RB_RlA)-zYo`x@<9#&{X#nKDab_NZJmzg~gx(k@08bq*uai6PuDUnTzEd3PoNQ zy+3eGLr>ef%CI_Tj!z46GeI&??!>eawi-QPT^!$Dz22M7)rv_UsqMA0fsV(W z`iE)x82q#5s{8Vr)2{+nw zHW{N_Bv*^twH+li*b`XLb|_6}m(O)2Gi4#xS82 zDG1#<{xfu3NMe`3P7f;%^iR9fd@k?({FSc^%{=p4xM-$*LMV#y<*eOoB$b~9l;o|* zw!L$e4Id-JKIwWR=0}JSEVDiFGJTxIpjHIw%!FRAMh2Y)*&^Vp9h6?6^S-8knn5!3 z=$TB##*$b{c+LLe^>bQ|y26$`N!|>R@u#Uwk&KMkYZ@(|zA#(2UAJsHS|LiEfoK`A zruZ^z@pfONT5iA8XD(XM-dDpYF)m7Z?VfT;vdj=h>`lj3_M{^dhc2f|1A#|y_dD2= zzA!(D_hF`C#C}NmPDDSH)or-xq6DFbT|Y0I$|u%HqjWbyntol!e~5F9P@v!>&Hc8V z{bj4u?84Hw$i40FWe3i5E{NT%Akh)TZ(tb6FOY~D0v0S=VSfjSOL~V+OeB`d?xj&QZ6%Akyq_Eo=AH`ct8o z9mncgeSsD9zvH`^tqG}ufR8Y}Tw^aI=9j1!0AW4@NBPR+|A@~y?NBKDg&Cbl(7kb> z@!HLI1>a;vI?wwL8LQ?-XZu%Hi|Gn_8di)~00%3e8G))wIJX*m6CK%9<r&LqOQOpG*LS7N93t z{Gw^VXZH8VeU*Twx2IK)oh-5W!ps16Ltik{^eSJID_-`fT9~aMr3z}KSfHd6AHAC_ zdJp-xLF~Qthr0;3$w~V>GJ^mukH=r{Ug{(#3K{b z3^C7^rFStbqXX%o@c_8F1wcYR*FmZaG(bWm0!Of;lMMU zL(o$fH**=c5^QYFT$XG6*3M0vQQ>Y){MJyi6|wUwVs-WVgWZ6=Didll)AMi8X!$aqD4R%oQ*E zt>8D(W^~1yDz2dXR;SB}P2cM%8+OEVtKzE*IhrO#FhVTD5s=u^^yAuH)ya6i&!=&P ztxked??I!@V*O+7!pq>K!|-~5OrHUn=V(yT+@qCD@0GaUaQ-YFMpi!z;D@v`a?s$c z0v9+kEg@3_HwTOxO+4QB=ZnUGA$s_MRz{9RG6;{@XLQ#24k+Y&^af__@r7#9n2Xkl z3FbShjLUC3nbCT(yd#|V%<uQ?w5jJrb=Br^#0)~(PZWFcO;~De*O8@)cisP0p^*-9~plGfl{hc)`A3ClDjpA zItng*nApkdiFhgpRBFMh6i4_E zSqCLFU$H=ybgia^< zh)WTttF3LS#e-wX47BiY!!lw?kJt#>bGte*TM^7|(`c2KAl$b=QzJPQ$JA|JiJ|zP zAl}l-(2I2`x8ndZwlJi*$1ZOY^I9W<-&e51Enkx7anu|+TV{Hu^Hm2CoQt}I=Rsff zLnz1Y&7%n>7Ku_$yVn?(gYuSY0Gthc*1e(J2npgo8IE@Ow%BuEMmqk>WS$=_oW(r4 zE*8qrpx(FpOmwXg>2ZW}iaC*7tI*~?x$)nRY?YcKkG(t?lekx>wHY&*0 zqcK$@ArFQI;fyPfpdLtpGw$J$QKdmiaR*QC!{ly<4XWc&PCv{R0 zjG;G})`p5G@dCL3ey5+x(o^B%noBtk!uZ#LK29~edyb0O_rACJpGh9gU;O4;?8pUq zd*EWN89wK(UhlQ;P1D3CVseD;#KuyYrLCNQ%A9!)G3D5#YbyY=6j}N@0~Bm`=$KK5 zYxo_nx~G0@??5}31G1MFAT5n6$Q*mm4^AM_e_`6wZ0Y|CXdv_<+b@_SzwOtH@#W`K zI8g=BOGWJ04+__x<>ncT@IhDH3fve50UdwADL4ZVkYcK#-ip6!L{zQ^1h#NEs&Id1g`q4>ie1XHCcjp)SF{Y35h2y?4ATDsW`?Y<(-tzn_TZS2=Hd~Q)2wU?XU6Mw*VT$n zR!ZEbp@m!i3cVzkSoFw~@`8i3_-S4#kP6blEnvS%8H`Zwu1MU68TMEy=K3NrY~W`) z`jEQ}O8cC3&7&cL8=P95_P^RV&c{*N3CxXGTDIjIe?9~Es%q-P>Oa%>K;P(as<&;$ zMy~N`;|-Vck)Oe{+#2BCZpBkhpeJHpVNqQjW>}$k!-eW(+QtKqhgZTrClpsW(bK~Q zX})l-b>+K8Gxc8={91IuI=f6{uwq8`lwf4M2uMt^#;6!kT*Q<6R+VLowLUDg@Hrv8 zAT*0x(tenWRw^Bt90DeZoa4guu-#zOSkPScf)pwivaL&J(;9g$H6Wf5bzO0w1RW8&Wk|#26$Q zqQ5nI$~o#4{gj^bR#&8#-sm9W+PM^#DXKkRj)SaUJCOQjK}M9A1!Ud^k# zzM=$a7BKXnf$Pv-IbRQ9X!(kG#X%IcWbN&DofvuY`qV2OYXjee8KtM30aRJp^5mBR zPOYRdgK=>wOipGU21>U2J+&`72I*+`;dV6Cq+Ip5P$=xEb7I zx%mj8bYVr!h0C!Cj#bZRw$5UAWPH|y1M`9jtL0tLW!_%C0N|}N0LBH*p?aChk+man z0I%(rgJ7WVdI*4tBoZyKtBDr`h;%%6$xtp2bgWM_lYOk$+PDu1*kdawPp7E8tK6|I zS78B5+u1Z`t_z!GyBo*N3g^ZnDzYteh!?|qwP7_2Qi z96S9Gd(I7)zjiU>7MV}Wu^AhBy`qDC#I|nr9VyvgdNxow|PM1&7;uUkCUnaMeQs-<~X2 zfJ-!3Z)Me4rRKLm)XBDX#Hk|f<v0^Xz+MRM%y{96`4L!yoS#z z6H}VG_sRL^Ww)zZQn|zZzf7&puZG2iLv$=35ps@A4rg)~K0W{>+6TZ_53-@v^9GeSi~_*yDokhft*OB}RJ z_%o4jIaff{Pd)U zrD~{`U2XSV`;R^CgC|1X8r0Y)P!R_7Zsl>8l0r6micXTqRsKYJ# z4N>0-rKGxc1zVldd~~vgd|(Fdk$zohD#nNw7XvK|^}XCtS9pPdqKNDAM5cu*G#ZrZ zjaj7?X=RjUf}wPl42qEYp_PiD#mx4|`4g%0SLNH_9>Z=sdm+2qNg4^~{v47kbkB~U zGs7k4bIN+lgb$FfXHvV-R~=V*2TfYk#McNI!ih=7Yr*fRwzJm> z_mH10;WhS@XQFK$PX{M0W|S#(UX~raH{NkNhnqFpwDuUD;9c$JaB%jbG}0D&yg&Y+#<~<#)8y)D{yCW9c`i@~DmB=uKwL>dRp_ z3LFxfunE(Hb~d*2>08EgQchd<2JAAy3?ob(w=;(%n_C*aFT2*R566*5<1RhH`82=U zne-MbmGAs^yJ`NI7DTf;F-)wlCc9|Z$JcCs5DfkHWUy3K(j&OQrv#@_z_bi%gZa&^ z!Gl6zv;mhgH$%jBQ0sWZF7P^UW*<|69xb2hC8{?rs)?I#eZkKR*icm%-)>_c(a7u& z_8QH5bFZiHUhXAB+ZV(fSjU76{pKM3*ktOBN29bR?uRBm zDyAX7>y+{OH}S9+^`yu7kEc}!j2!HaO@e~*fS^mK;8b6t3GWZkdZL_lB-?yNWfr_B zc(ocjV-4+Ndtr0}*6wRTzAe(DSZF(MZ&-iJ>bcZu65j@jJnz5eFGlPdN=cGBO*}qn z&Z@Ij|ABo(yIw7@7iRu*)OV5{0-@uf{w)9^YP0u<`olOv{g0!@H&JAcMTKFG_e&1SG!b(zl>a?i`&O8(S<7mu`wU-R%fW%8V+kJ2#ds5}y2ce0Z3 zoef?vQ2JomAyBXs)~qQBUVP8A5aq-+6iEkW94yE|G~IKzC6WrI9?z(FQGOhqjkK6M z{Jm5^hgenED%9VtHe0o|{3#!E&oc^?SqX4g^HZhq+UA$xRIvPt;cJ7}_F`43$IUm3ye~WHsyF8^ zZnB*!IMnXz>d~u)jjGc&NwE4oQ&{wzTB*Vhq&$*{iwmQqxH4vIGC;LHs^bsE1{3&}zi7um8zEGlBeE+@o1WH&k1<*SS#z N8R!^m7iv0Q|3A(NA>;r6 literal 0 HcmV?d00001 From 5f4d18f80a4920e77b52cb8ae886c21ada71f8c4 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 15 May 2024 14:22:54 +0200 Subject: [PATCH 073/101] Improvements from UX dry run --- feature/softap/src/main/res/values/strings.xml | 2 +- feature/ui/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 4a2d57b2..0d62d062 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -2,7 +2,7 @@ "Wi-Fi Provisioner " Connect to Device - Enter the SSID of the Soft AP you want to connect to. + Enter the SSID of the SoftAP you want to connect to. \n\nNote: Make sure the nRF 700x device is powered on and in range. Discovering services… diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index 131714f6..ebacf75a 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -100,7 +100,7 @@ Wi-Fi credentials to the provisionee and verify provisioning status. Provision over Wi-Fi - This mode uses temporary a Wi-Fi network (Soft AP) + This mode uses temporary a Wi-Fi network (SoftAP) created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. \ No newline at end of file From fc45548c6d37cded1e36aac7d5c9fd054a28abef Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Wed, 22 May 2024 14:51:19 +0200 Subject: [PATCH 074/101] Introduces new UI based on UX Tests --- .../provisioner/WifiProvisionerApplication.kt | 1 + app/src/main/res/values/strings.xml | 2 +- feature/softap/build.gradle.kts | 7 +- .../softap/sections/ActionButtonSection.kt | 88 --- .../softap/sections/WifiDeviceSection.kt | 24 - .../softap/sections/WifiSection.kt | 25 - .../softap/view/SoftApConnectorDialog.kt | 71 ++- .../softap/view/SoftApDestinations.kt | 27 +- .../softap/view/SoftApProvisioningDialog.kt | 50 -- .../softap/view/SoftApProvisioningScreen.kt | 183 ------- .../view/SoftApProvisioningViewEvent.kt | 10 - .../provisioner/softap/view/SoftApScreen.kt | 507 ++++++++++++++++++ .../viewmodel/SoftApProvisioningViewModel.kt | 242 --------- .../softap/viewmodel/SoftApViewModel.kt | 211 ++++++++ .../viewmodel/SoftApWifiScannerViewModel.kt | 5 +- .../softap/src/main/res/values/strings.xml | 33 +- .../wifi/provisioner/ui/PasswordDialog.kt | 62 +++ .../ui/view/section/WifiSection.kt | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- .../wifi/provisioner/domain/BandDomain.kt | 2 +- lib/softap/provisioner/build.gradle.kts | 3 +- .../softap/NetworkServiceDiscoveryListener.kt | 30 +- .../provisioner/softap/SoftApException.kt | 18 +- .../wifi/provisioner/softap/SoftApManager.kt | 8 +- 24 files changed, 934 insertions(+), 681 deletions(-) delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt create mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt index c84b00ed..1522b532 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt @@ -34,5 +34,6 @@ package no.nordicsemi.android.wifi.provisioner import android.app.Application import dagger.hilt.android.HiltAndroidApp + @HiltAndroidApp class WifiProvisionerApplication : Application() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a91058a3..6dee071d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,7 +71,7 @@ Device status Disconnected Wi-Fi status - Selected Wi-Fi + Selected Wi-Fi Start provisioning Version Scanning error diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index a03ce7e1..f461b39f 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -60,6 +60,7 @@ dependencies { implementation(libs.nordic.theme) implementation(libs.nordic.navigation) implementation(libs.nordic.uilogger) + implementation(libs.nordic.logger) implementation(libs.accompanist.placeholder) @@ -70,6 +71,8 @@ dependencies { implementation(libs.retrofit.converter.gson) implementation(libs.okhttp) implementation(libs.okhttp.logging) - implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") - implementation("com.squareup.retrofit2:converter-scalars:2.9.0") + + // Timber & SLF4J + implementation ("com.arcao:slf4j-timber:3.1") + implementation ("no.nordicsemi.android:log-timber:2.3.0") } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt deleted file mode 100644 index ca972aee..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/ActionButtonSection.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.sections - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.Button -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent -import no.nordicsemi.android.wifi.provisioner.ui.R -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog - -@Composable -fun ActionButtonSection(viewEntity: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { - if (viewEntity.device == null) { - ActionButton(stringResource(id = R.string.start)) { - onEvent(OnProvisionNextDeviceEvent) - } - } else if(viewEntity.network == null) { - ActionButton(stringResource(id = R.string.select_wifi)) { - onEvent(OnSelectWifiEvent) - } - } else if(viewEntity.password == null) { - ActionButton( stringResource(id = R.string.password_select)) { - onEvent(OnShowPasswordDialog) - } - } else if(viewEntity.hasFinished() || viewEntity.hasFinishedWithSuccess()) { - - } else { - ActionButton(stringResource(id = R.string.provision)) { - onEvent(OnProvisionClickEvent) - } - } -} - -@Composable -private fun ActionButton(text: String, onClick: () -> Unit) { - Box(modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)) { - Button( - onClick = onClick, - modifier = Modifier - .align(Alignment.Center) - .widthIn(min = 100.dp) - ) { - Text(text = text) - } - } -} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt deleted file mode 100644 index 98e3d188..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiDeviceSection.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.sections - -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Wifi -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem - -/** - * Created by Roshan Rajaratnam on 19/02/2024. - */ - -@Composable -fun WifiDeviceNotSelected(onClick: () -> Unit) { - ClickableDataItem( - imageVector = Icons.Outlined.Wifi, - title = "Not selected", - isEditable = false, - description = "Please setup the Wi-Fi network", - onClick = onClick, - buttonText = stringResource(id = R.string.change_wifi) - ) -} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt deleted file mode 100644 index aa43bf22..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/sections/WifiSection.kt +++ /dev/null @@ -1,25 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.sections - -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.SignalWifiConnectedNoInternet4 -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.ui.ClickableDataItem - -/** - * Created by Roshan Rajaratnam on 16/02/2024. - */ -@Composable -private fun WifiNotSelectedSection( - onClick: () -> Unit -) { - ClickableDataItem( - imageVector = Icons.Outlined.SignalWifiConnectedNoInternet4, - title = "Not selected", - isEditable = false, - description = "Please select a device to provision", - onClick = onClick, - buttonText = stringResource(id = R.string.soft_ap) - ) -} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index fa70ce2e..35811cb0 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -5,12 +5,9 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Visibility -import androidx.compose.material.icons.outlined.VisibilityOff import androidx.compose.material.icons.outlined.Wifi import androidx.compose.material3.AlertDialog import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text @@ -22,8 +19,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import no.nordicsemi.android.wifi.provisioner.feature.softap.R @@ -31,7 +26,6 @@ import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.ui.CircularProgressIndicatorContent - @Composable internal fun SoftApConnectorDialog( isNetworkServiceDiscoveryCompleted: Boolean?, @@ -91,6 +85,51 @@ internal fun SoftApConnectorDialog( ) } + + + +@Composable +internal fun EditSsidDialog( + ssidName: String = "nrf-wifiprov", + onSsidChange: (String) -> Unit, + dismiss: () -> Unit, +) { + var ssid by rememberSaveable { mutableStateOf(ssidName) } + var password by rememberSaveable { mutableStateOf("") } + + AlertDialog( + onDismissRequest = dismiss, + icon = { Icon(imageVector = Icons.Outlined.Wifi, contentDescription = null) }, + title = { + Text( + text = stringResource(id = R.string.soft_ap), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + SoftApConnectorContent( + ssid = ssid, + password = password, + onSsidChange = { ssid = it }, + onPasswordChange = { password = it }, + onShowPassword = {} + ) + }, + dismissButton = { + TextButton(onClick = dismiss) { + Text(text = "Cancel") + } + }, + confirmButton = { + TextButton(onClick = { onSsidChange(ssid) }) { + Text(text = "Confirm") + } + } + ) +} + @Composable private fun SoftApConnectorContent( ssid: String, @@ -99,7 +138,6 @@ private fun SoftApConnectorContent( onPasswordChange: (String) -> Unit, onShowPassword: () -> Unit ) { - var showPassword by rememberSaveable { mutableStateOf(true) } Column { Text( text = stringResource(id = R.string.softap_rationale), @@ -108,24 +146,5 @@ private fun SoftApConnectorContent( ) Spacer(modifier = Modifier.size(size = 16.dp)) OutlinedTextField(value = ssid, onValueChange = onSsidChange) - /*Spacer(modifier = Modifier.size(size = 8.dp)) - OutlinedTextField( - value = password, - onValueChange = onPasswordChange, - visualTransformation = if (showPassword) - VisualTransformation.None - else - PasswordVisualTransformation(), - trailingIcon = { - IconButton(onClick = { showPassword = !showPassword }) { - Icon( - imageVector = if (!showPassword) - Icons.Outlined.Visibility - else Icons.Outlined.VisibilityOff, - contentDescription = null - ) - } - } - )*/ } } \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 5ef13ba9..49a463a2 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -2,11 +2,13 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import android.os.Build import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApViewModel import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent @@ -22,7 +24,30 @@ val SoftApWifiScannerDestination = createDestination( val SoftApProvisionerDestinations = listOf( defineDestination(SoftApProvisionerDestination) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - SoftApProvisioningScreen() + val viewModel = hiltViewModel() + val state by viewModel.state.collectAsStateWithLifecycle() + val context = LocalContext.current + // SoftApProvisioningScreen() + SoftApScreen( + state = state, + onLoggerAppBarIconPressed = { + viewModel.onLoggerAppBarIconPressed(context) + }, + start = { ssid, configuration -> + viewModel.start( + context = context, + ssid = ssid, + passphraseConfiguration = configuration + ) + }, + onSelectWifiPressed = viewModel::onSelectWifiPressed, + onPasswordEntered = { + viewModel.onPasswordEntered(it) + }, + onProvisionPressed = viewModel::onProvisionPressed, + verify = viewModel::verify, + navigateUp = viewModel::navigateUp + ) } }, defineDestination(SoftApWifiScannerDestination) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt deleted file mode 100644 index 70d4c3ab..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningDialog.kt +++ /dev/null @@ -1,50 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.view - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Settings -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity -import no.nordicsemi.android.wifi.provisioner.ui.CircularProgressIndicatorContent - - -@Composable -internal fun SoftApProvisioningDialog(state: SoftApViewEntity, dismiss: () -> Unit) { - AlertDialog( - onDismissRequest = dismiss, - icon = { Icon(imageVector = Icons.Outlined.Settings, contentDescription = null) }, - title = { - Text( - text = stringResource(id = R.string.provisioning), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.titleLarge - ) - }, - text = { - if (state.hasFinished() || state.hasFinishedWithSuccess()) { - Text(text = stringResource(id = R.string.provisioning_device_success)) - } else { - CircularProgressIndicatorContent( - text = stringResource(id = R.string.provisioning_device_rationale) - ) - } - }, - confirmButton = { - if (state.hasFinished()) { - TextButton(onClick = dismiss) { - Text(text = stringResource(id = R.string.ok)) - } - } - } - ) -} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt deleted file mode 100644 index 98c904db..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningScreen.kt +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.view - -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon -import no.nordicsemi.android.common.theme.view.NordicAppBar -import no.nordicsemi.android.wifi.provisioner.feature.softap.R -import no.nordicsemi.android.wifi.provisioner.softap.sections.ActionButtonSection -import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity -import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApProvisioningViewModel -import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog -import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDevice -import no.nordicsemi.android.wifi.provisioner.ui.view.section.SoftApDeviceNotSelected -import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent - -@RequiresApi(Build.VERSION_CODES.Q) -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SoftApProvisioningScreen() { - val viewModel = hiltViewModel() - - val state by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (ProvisioningViewEvent) -> Unit = viewModel::onEvent - Column { - NordicAppBar( - text = stringResource(id = R.string.label_wifi_provisioner), - actions = { - LoggerAppBarIcon( - onClick = { } - ) - }, - showBackButton = true, - onNavigationButtonClick = viewModel::navigateUp - ) - Box(modifier = Modifier.weight(1f)) { - Content(state) { viewModel.onEvent(it) } - } - ActionButtonSection(state, onEvent) - Spacer(modifier = Modifier.size(16.dp)) - } - - if (state.showSoftApDialog) { - SoftApConnectorDialog( - isNetworkServiceDiscoveryCompleted = state.isNetworkServiceDiscoveryCompleted, - connect = { ssid, passphrase -> - onEvent(OnSoftApConnectEvent(ssid, passphrase)) - }, dismiss = { - onEvent(OnFinishedEvent) - } - ) - } - - if (state.showPasswordDialog == true) { - PasswordDialog { event -> - (event as? PasswordSetDialogEvent)?.let { - onEvent(OnPasswordSelectedEvent(it.password)) - } - onEvent(OnHidePasswordDialog) - } - } - - if(state.showProvisioningDialog){ - SoftApProvisioningDialog(state){ - onEvent(OnFinishedEvent) - } - } -} - -@Composable -private fun Content(state: SoftApViewEntity, onEvent: (ProvisioningViewEvent) -> Unit) { - Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .padding(horizontal = 16.dp) - ) { - Spacer(modifier = Modifier.size(12.dp)) - - state.device?.let { - SoftApDevice(it.name, it.connectionInfoDomain!!.ipv4Address, true, onEvent) - } ?: SoftApDeviceNotSelected(onEvent = onEvent) - - Spacer(modifier = Modifier.size(12.dp)) - - if (!state.isConnected && state.device != null) { - DisconnectedDeviceStatus() - } else { - - Spacer(modifier = Modifier.size(12.dp)) - - // state.status?.let { StatusSection(it) } - - state.network?.let { - Spacer(modifier = Modifier.size(12.dp)) - - SectionTitle(text = stringResource(id = R.string.section_provisioning)) - - Spacer(modifier = Modifier.size(12.dp)) - - WifiSection(it, true, onEvent) - } - - state.password?.let { - Spacer(modifier = Modifier.size(10.dp)) - - PasswordSection(true, onEvent) - } - - // TODO verification - /*state.provisioningStatus?.let { - SectionTitle(text = stringResource(id = R.string.section_status)) - - Spacer(modifier = Modifier.size(8.dp)) - - ProvisioningSection(it) - }*/ - } - } -} - - -@Composable -private fun SectionTitle(text: String) { - Text( - text = text, - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) -} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt deleted file mode 100644 index 21c1e7d4..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApProvisioningViewEvent.kt +++ /dev/null @@ -1,10 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.view - -import no.nordicsemi.android.wifi.provisioner.softap.Open -import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent - -data class OnSoftApConnectEvent( - val ssid: String, - val passphraseConfiguration: PassphraseConfiguration = Open -) : ProvisioningViewEvent \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt new file mode 100644 index 00000000..73d414b6 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -0,0 +1,507 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + +package no.nordicsemi.android.wifi.provisioner.softap.view + +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.PermDataSetting +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.filled.Verified +import androidx.compose.material.icons.filled.Wifi +import androidx.compose.material.icons.filled.WifiFind +import androidx.compose.material.icons.filled.WifiPassword +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon +import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.common.theme.view.ProgressItem +import no.nordicsemi.android.common.theme.view.ProgressItemStatus +import no.nordicsemi.android.common.theme.view.WizardStepAction +import no.nordicsemi.android.common.theme.view.WizardStepComponent +import no.nordicsemi.android.common.theme.view.WizardStepState +import no.nordicsemi.android.common.theme.view.getWiFiRes +import no.nordicsemi.android.wifi.provisioner.feature.softap.R +import no.nordicsemi.android.wifi.provisioner.softap.FailedToBindToNetwork +import no.nordicsemi.android.wifi.provisioner.softap.OnConnectionLost +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration +import no.nordicsemi.android.wifi.provisioner.softap.UnableToConnectToNetwork +import no.nordicsemi.android.wifi.provisioner.softap.WifiNotEnabledException +import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApScreenState +import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog +import no.nordicsemi.android.wifi.provisioner.ui.SelectChannelDialog +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData + +@Composable +fun SoftApScreen( + state: SoftApScreenState, + onLoggerAppBarIconPressed: () -> Unit, + start: (String, PassphraseConfiguration) -> Unit, + onSelectWifiPressed: () -> Unit, + onPasswordEntered: (String) -> Unit, + onProvisionPressed: () -> Unit, + verify: () -> Unit, + navigateUp: (() -> Unit) +) { + var ssidName by rememberSaveable { mutableStateOf("nrf-wifiprov") } + val snackbarHostState = remember { SnackbarHostState() } + val scope = rememberCoroutineScope() + Column { + NordicAppBar( + text = stringResource(id = R.string.label_wifi_provisioner), + actions = { + LoggerAppBarIcon( + onClick = onLoggerAppBarIconPressed + ) + }, + showBackButton = true, + onNavigationButtonClick = navigateUp + ) + OutlinedCard( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(vertical = 16.dp, horizontal = 8.dp), + ) { + runCatching { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + ) { + ConfigureSoftAp( + configureState = state.configureState, + connectionState = state.connectionState, + ssidName = ssidName, + onSsidChange = { ssidName = it } + ) + ConnectToSoftAp( + connectionState = state.connectionState, + serviceDiscoveryState = state.discoveringServicesState, + ssidName = ssidName, + start = { start(ssidName, Open) } + ) + SelectWifi( + provisioningState = state.provisionState, + selectWifiState = state.selectWifiState, + wifiData = state.selectedWifi, + onSelectWifiPressed = onSelectWifiPressed, + onPasswordEntered = onPasswordEntered, + ) + SetPassphrase( + provisioningState = state.provisionState, + providePasswordState = state.providePasswordState, + password = state.password, + onPasswordEntered = onPasswordEntered + ) + Provisioning( + passwordState = state.providePasswordState, + provisioningState = state.provisionState, + onProvisionPressed = onProvisionPressed + ) + Verify( + provisioningState = state.provisionState, + verificationState = state.verifyState, + verify = verify + ) + } + }.onFailure { + showSnackBar(scope, snackbarHostState, it) + } + } + } +} + +private fun showSnackBar( + scope: CoroutineScope, + snackbarHostState: SnackbarHostState, + throwable: Throwable +) { + scope.launch { + val message = when (throwable) { + is WifiNotEnabledException -> "Please enable Wi-Fi!" + is FailedToBindToNetwork -> "Failed to bind to network!" + is UnableToConnectToNetwork -> "Unable to connect to network!" + is OnConnectionLost -> "Connection lost!" + else -> "${throwable::class.simpleName}: ${throwable.message}" + } + snackbarHostState.showSnackbar(message = message) + } +} + + +@Composable +private fun ConfigureSoftAp( + configureState: WizardStepState, + connectionState: WizardStepState, + ssidName: String, + onSsidChange: (String) -> Unit, +) { + var showDialog by rememberSaveable { mutableStateOf(false) } + WizardStepComponent( + icon = Icons.Default.Settings, + title = stringResource(R.string.configure), + state = configureState, + decor = if ((connectionState == WizardStepState.CURRENT || + connectionState == WizardStepState.COMPLETED) + && configureState == WizardStepState.COMPLETED + ) { + null + } else if (configureState != WizardStepState.INACTIVE) WizardStepAction.Action( + text = stringResource(id = R.string.edit_ssid), + onClick = { + showDialog = true + } + ) else null, + showVerticalDivider = true + ) { + Text(text = "SSID: $ssidName") + } + if (showDialog) { + EditSsidDialog( + ssidName = ssidName, + onSsidChange = { + onSsidChange(it) + showDialog = false + }, + dismiss = { + showDialog = false + } + ) + } +} + +@Composable +private fun ConnectToSoftAp( + connectionState: WizardStepState, + serviceDiscoveryState: WizardStepState, + ssidName: String, + start: () -> Unit, +) { + WizardStepComponent( + icon = Icons.Default.Wifi, + title = stringResource(id = R.string.connect), + state = connectionState, + decor = if (connectionState == WizardStepState.COMPLETED && + serviceDiscoveryState == WizardStepState.COMPLETED + ) { + null + } else WizardStepAction.Action( + text = stringResource(id = R.string.start), + onClick = { + start() + } + ), + showVerticalDivider = false, + ) { + ProgressItem( + text = when (connectionState) { + WizardStepState.CURRENT -> stringResource(id = R.string.connecting) + WizardStepState.COMPLETED -> stringResource(id = R.string.connected) + else -> stringResource(id = R.string.connect) + }, + status = when (connectionState) { + WizardStepState.CURRENT -> ProgressItemStatus.WORKING + WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + else -> ProgressItemStatus.DISABLED + }, + iconRightPadding = 24.dp, + ) + ProgressItem( + text = when (serviceDiscoveryState) { + WizardStepState.INACTIVE -> stringResource(id = R.string.discover_services) + WizardStepState.CURRENT -> stringResource(id = R.string.discovering_services) + else -> stringResource(id = R.string.discovered_services) + }, + status = when (serviceDiscoveryState) { + WizardStepState.CURRENT -> ProgressItemStatus.WORKING + WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + else -> ProgressItemStatus.DISABLED + }, + iconRightPadding = 24.dp, + ) + } +} + +@Composable +private fun SelectWifi( + provisioningState: WizardStepState, + selectWifiState: WizardStepState, + wifiData: WifiData?, + onSelectWifiPressed: () -> Unit, + onPasswordEntered: (String) -> Unit, +) { + WizardStepComponent( + icon = Icons.Default.WifiFind, + title = stringResource(id = R.string.select_wifi), + state = selectWifiState, + decor = if (selectWifiState == WizardStepState.INACTIVE) null + else if ((provisioningState == WizardStepState.CURRENT + && selectWifiState == WizardStepState.COMPLETED) + || (provisioningState == WizardStepState.COMPLETED + && selectWifiState == WizardStepState.COMPLETED) + ) { + null + } else WizardStepAction.Action( + text = stringResource(id = R.string.select), + onClick = onSelectWifiPressed + ), + showVerticalDivider = true + ) { + if (wifiData != null && selectWifiState != WizardStepState.INACTIVE) { + Text(text = "SSID: ${wifiData.ssid}, band: ${wifiData.channelFallback.wifiInfo?.band?.toDisplayString()}") + } else { + Text(text = stringResource(R.string.select_wifi_rationale)) + } + } +} + +@Composable +private fun SetPassphrase( + providePasswordState: WizardStepState, + provisioningState: WizardStepState, + password: String? = null, + onPasswordEntered: (String) -> Unit, +) { + var showDialog by rememberSaveable { mutableStateOf(false) } + WizardStepComponent( + icon = Icons.Default.WifiPassword, + title = stringResource(id = R.string.set_passphrase), + state = providePasswordState, + decor = if (providePasswordState == WizardStepState.INACTIVE) { + null + } else if ((provisioningState == WizardStepState.CURRENT + && providePasswordState == WizardStepState.COMPLETED) + || (provisioningState == WizardStepState.COMPLETED + && providePasswordState == WizardStepState.COMPLETED) + ) { + null + } else if (providePasswordState == WizardStepState.CURRENT) WizardStepAction.Action( + text = stringResource(id = R.string.set), + onClick = { showDialog = true } + ) else WizardStepAction.Action( + text = stringResource(id = R.string.set), + onClick = { showDialog = true } + ), + showVerticalDivider = true + ) { + if (password == null) { + Text(text = stringResource(R.string.set_passphrase_rationale)) + } else { + Text(text = stringResource(R.string.set_passphrase_value, password.toPassphrase())) + } + if (showDialog) { + PasswordDialog( + onConfirmPressed = { + onPasswordEntered(it) + showDialog = false + }, + onDismiss = { showDialog = false } + ) + } + } +} + +@Composable +private fun Provisioning( + passwordState: WizardStepState, + provisioningState: WizardStepState, + onProvisionPressed: () -> Unit +) { + WizardStepComponent( + icon = Icons.Default.PermDataSetting, + title = stringResource(id = R.string.provision), + state = provisioningState, + decor = if (passwordState == WizardStepState.COMPLETED && + provisioningState == WizardStepState.INACTIVE + ) { + WizardStepAction.Action( + text = stringResource(id = R.string.provision), + onClick = onProvisionPressed + ) + } else if (provisioningState == WizardStepState.CURRENT) { + WizardStepAction.ProgressIndicator + } else if (passwordState == WizardStepState.COMPLETED && + provisioningState == WizardStepState.COMPLETED + ) { + null + } else null, + showVerticalDivider = false + ) { + ProgressItem( + text = when (provisioningState) { + WizardStepState.INACTIVE -> stringResource(R.string.provisioning_rationale) + WizardStepState.CURRENT -> stringResource(R.string.provisioning_device_to_your_network) + WizardStepState.COMPLETED -> stringResource(R.string.provisioning_completed) + }, + status = when (provisioningState) { + WizardStepState.CURRENT -> ProgressItemStatus.WORKING + WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + else -> ProgressItemStatus.DISABLED + }, + iconRightPadding = 24.dp, + ) + } +} + +@Composable +private fun Verify( + provisioningState: WizardStepState, + verificationState: WizardStepState, + verify: () -> Unit +) { + WizardStepComponent( + icon = Icons.Default.Verified, + title = stringResource(id = R.string.verify), + state = verificationState, + decor = if (verificationState == WizardStepState.INACTIVE && + provisioningState == WizardStepState.COMPLETED + ) { + WizardStepAction.Action( + text = stringResource(id = R.string.verify), + onClick = verify + ) + } else if (verificationState == WizardStepState.CURRENT) { + WizardStepAction.ProgressIndicator + } else null, + showVerticalDivider = false + ) { + ProgressItem( + text = when (verificationState) { + WizardStepState.INACTIVE -> stringResource(R.string.optional_verification_rationale) + WizardStepState.CURRENT -> "Locating provisioned device..." + WizardStepState.COMPLETED -> "Verification completed." + }, + status = when (verificationState) { + WizardStepState.CURRENT -> ProgressItemStatus.WORKING + WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + else -> ProgressItemStatus.DISABLED + }, + iconRightPadding = 24.dp, + ) + } +} + + +@Composable +private fun WifiItem( + record: ScanRecordsForSsid, + onWifiSelected: (ScanRecordsForSsid) -> Unit = {} +) { + val wifiData = record.wifiData + val selectedScanRecord = remember { mutableStateOf(null) } + val scanRecord = selectedScanRecord.value + val wifi = scanRecord?.wifiInfo + + val showSelectChannelDialog = rememberSaveable { mutableStateOf(false) } + + if (showSelectChannelDialog.value) { + SelectChannelDialog( + records = record, + onDismiss = { showSelectChannelDialog.value = false } + ) { + selectedScanRecord.value = it + showSelectChannelDialog.value = false + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(10.dp)) + .clickable { + onWifiSelected(record) + } + .padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text(text = wifiData.ssid, style = MaterialTheme.typography.labelLarge) + + if (wifi != null) { + if (wifi.macAddress.isNotEmpty()) { + Text( + text = stringResource(id = R.string.bssid, wifi.macAddress), + style = MaterialTheme.typography.bodySmall + ) + } + + if (wifi.band != null) { + Text( + text = stringResource( + id = R.string.band_and_channel, + wifi.band!!.toDisplayString(), + wifi.channel.toString() + ), + style = MaterialTheme.typography.bodySmall + ) + } else { + Text( + text = stringResource(id = R.string.channel, wifi.channel.toString()), + style = MaterialTheme.typography.bodySmall + ) + } + } else { + Text( + text = stringResource(id = R.string.channel, stringResource(id = R.string.any)), + style = MaterialTheme.typography.bodySmall + ) + } + } + + val displayRssi = scanRecord?.rssi ?: record.biggestRssi + + Row(modifier = Modifier + .clip(RoundedCornerShape(10.dp)) + .clickable { showSelectChannelDialog.value = true } + .border( + 1.dp, + MaterialTheme.colorScheme.onSurface, + RoundedCornerShape(10.dp) + ) + .padding(9.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(getWiFiRes(displayRssi), contentDescription = "") + + Icon(Icons.Default.ArrowDropDown, contentDescription = "") + } + } +} + +private fun String.toPassphrase(): String { + var password = "" + repeat(length) { + password += '*' + } + return password +} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt deleted file mode 100644 index 4edf6dfa..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApProvisioningViewModel.kt +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2022, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.wifi.provisioner.softap.viewmodel - -import android.os.Build -import android.util.Log -import androidx.annotation.RequiresApi -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.compose.viewModel -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.mapNotNull -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch -import no.nordicsemi.android.common.navigation.NavigationResult -import no.nordicsemi.android.common.navigation.Navigator -import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel -import no.nordicsemi.android.wifi.provisioner.softap.Open -import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration -import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager -import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.softap.view.OnSoftApConnectEvent -import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination -import no.nordicsemi.android.wifi.provisioner.softap.view.entity.SoftApViewEntity -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionClickEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNextDeviceEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent -import java.net.SocketTimeoutException -import javax.inject.Inject - -@HiltViewModel -class SoftApProvisioningViewModel @Inject constructor( - private val softApManager: SoftApManager, - private val navigationManager: Navigator, - savedStateHandle: SavedStateHandle, -) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { - - private val _state = MutableStateFlow(SoftApViewEntity()) - val state = _state.asStateFlow() - - init { - navigationManager.resultFrom(SoftApWifiScannerDestination) - .mapNotNull { it as? NavigationResult.Success } - .onEach { installWifi(it.value) } - .launchIn(viewModelScope) - } - - @RequiresApi(Build.VERSION_CODES.Q) - override fun onCleared() { - super.onCleared() - softApManager.disconnect() - } - - @RequiresApi(Build.VERSION_CODES.Q) - fun onEvent(event: ProvisioningViewEvent) { - when (event) { - OnFinishedEvent -> { - _state.value = _state.value.copy(showProvisioningDialog = false) - finish() - } - is OnPasswordSelectedEvent -> onPasswordSelected(event.password) - OnSelectDeviceClickEvent -> provisionNextDevice() - is OnSoftApConnectEvent -> { - connect( - ssid = event.ssid, - passphraseConfiguration = event.passphraseConfiguration - ) - } - - OnSelectWifiEvent -> navigationManager.navigateTo(SoftApWifiScannerDestination) - OnProvisionClickEvent -> provision() - OnHidePasswordDialog -> hidePasswordDialog() - OnShowPasswordDialog -> showPasswordDialog() - OnProvisionNextDeviceEvent -> provisionNextDevice() - } - } - - private fun provisionNextDevice() { - requestSoftApDevice() - } - - private fun showPasswordDialog() { - _state.value = _state.value.copy(showPasswordDialog = true) - } - - private fun hidePasswordDialog() { - _state.value = _state.value.copy(showPasswordDialog = false) - } - - private fun finish() { - release() - _state.value = SoftApViewEntity() - navigateUp() - } - - private fun release() { - try { - _state.value.device?.let { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - softApManager.disconnect() - } - } - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun requestSoftApDevice() { - release() - _state.value = SoftApViewEntity(showSoftApDialog = true) - } - - private fun installWifi(wifiData: WifiData) { - _state.value = _state.value.copy( - network = wifiData, - password = null, - showPasswordDialog = wifiData.isPasswordRequired() - ) - } - - private fun onPasswordSelected(password: String) { - _state.value = _state.value.copy(password = password) - } - - @RequiresApi(Build.VERSION_CODES.Q) - private fun connect( - ssid: String = "nrf-wifiprov", - passphraseConfiguration: PassphraseConfiguration = Open - ) { - viewModelScope.launch { - softApManager.run { - connect(ssid = ssid, passphraseConfiguration = passphraseConfiguration) - _state.value = _state.value.copy(isNetworkServiceDiscoveryCompleted = false) - discoverServices() - _state.value = - SoftApViewEntity(device = softAp, isNetworkServiceDiscoveryCompleted = true) - } - } - } - - private fun provision() { - _state.value = _state.value.copy(showProvisioningDialog = true) - val state = _state.value - val network = state.network ?: return - val handler = CoroutineExceptionHandler { _, throwable -> - // There is always chance that a socket timeout is thrown from the DK during - // provisioning due to timing constraints. In such cases, we can ignore the response - // and assume that the provisioning was successful. - if (throwable is SocketTimeoutException) { - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.CONNECTED, - ) - ) - } - } - viewModelScope.launch(Dispatchers.IO + handler) { - softApManager.run { - provision(config = network.toConfig()).also { response -> - if (response.isSuccessful) { - handleResponse(state) - } else { - _state.value = state.copy( - provisioningStatus = Resource.createError( - Throwable("Provisioning failed") - ) - ) - } - } - } - } - } - - private fun handleResponse(state : SoftApViewEntity){ - viewModelScope.launch { - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.DISCONNECTED - ) - ) - if(softApManager.verify()){ - _state.value = state.copy( - device = softApManager.softAp, - provisioningStatus = Resource.createSuccess( - data = WifiConnectionStateDomain.CONNECTED, - ) - ) - } - } - } - - private fun WifiData.toConfig(): WifiConfigDomain { - val state = _state.value - val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo - return WifiConfigDomain(info = wifiInfo, passphrase = state.password) - } -} diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt new file mode 100644 index 00000000..42beaa63 --- /dev/null +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2022, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.wifi.provisioner.softap.viewmodel + +import android.content.Context +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import no.nordicsemi.android.common.logger.LoggerLauncher +import no.nordicsemi.android.common.navigation.NavigationResult +import no.nordicsemi.android.common.navigation.Navigator +import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel +import no.nordicsemi.android.common.theme.view.WizardStepState +import no.nordicsemi.android.log.timber.nRFLoggerTree +import no.nordicsemi.android.wifi.provisioner.softap.Open +import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration +import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import timber.log.Timber +import java.net.SocketTimeoutException +import javax.inject.Inject + + +@HiltViewModel +class SoftApViewModel @Inject constructor( + private val softApManager: SoftApManager, + navigationManager: Navigator, + savedStateHandle: SavedStateHandle, +) : SimpleNavigationViewModel(navigator = navigationManager, savedStateHandle) { + + private val _state = MutableStateFlow(SoftApScreenState()) + val state = _state.asStateFlow() + + private var wifiConfigDomain: WifiConfigDomain? = null + private var logger: Timber.Tree? = null + + + init { + Timber.plant(Timber.DebugTree()) + navigationManager.resultFrom(SoftApWifiScannerDestination) + .mapNotNull { it as? NavigationResult.Success } + .onEach { + onWifiSelected(it.value) + } + .launchIn(viewModelScope) + } + + @RequiresApi(Build.VERSION_CODES.Q) + override fun onCleared() { + super.onCleared() + softApManager.disconnect() + } + + fun onLoggerAppBarIconPressed(context: Context) { + context.packageManager + .getLaunchIntentForPackage("no.nordicsemi.android.log") + ?.let { launchIntent -> + context.startActivity(launchIntent) + } ?: run { + LoggerLauncher.launch(context) + } + } + + fun start( + context: Context, + ssid: String = "nrf-wifiprov", + passphraseConfiguration: PassphraseConfiguration = Open + ) { + if (logger != null) { + Timber.uproot(logger!!) + logger = null + } + Timber.plant(nRFLoggerTree(context, "SoftAP Manager", ssid).also { + logger = it + }) + + viewModelScope.launch { + connect(ssid, passphraseConfiguration) + discoverServices() + // listSsids() + // provision() + } + } + + private suspend fun connect( + ssid: String = "nrf-wifiprov", + passphraseConfiguration: PassphraseConfiguration = Open + ) { + _state.value = _state.value.copy(connectionState = WizardStepState.CURRENT) + softApManager.connect(ssid = ssid, passphraseConfiguration = passphraseConfiguration) + _state.value = _state.value.copy(configureState = WizardStepState.COMPLETED) + _state.value = _state.value.copy(connectionState = WizardStepState.COMPLETED) + } + + private suspend fun discoverServices() { + _state.value = _state.value.copy(discoveringServicesState = WizardStepState.CURRENT) + softApManager.discoverServices() + _state.value = _state.value.copy(discoveringServicesState = WizardStepState.COMPLETED) + _state.value = _state.value.copy(selectWifiState = WizardStepState.CURRENT) + } + + fun onSelectWifiPressed() { + navigateTo(SoftApWifiScannerDestination) + } + + private fun onWifiSelected(record: WifiData) { + _state.value = _state.value.copy( + selectedWifi = record, + selectWifiState = WizardStepState.COMPLETED, + providePasswordState = WizardStepState.CURRENT + ) + } + + fun onPasswordEntered(password: String) { + val selectedWifi = _state.value.selectedWifi + selectedWifi?.let { wifiData -> + wifiConfigDomain = wifiData.toConfig(password) + _state.value = _state.value.copy( + providePasswordState = WizardStepState.COMPLETED, + password = password + ) + } + } + + fun onProvisionPressed() { + viewModelScope.launch { + wifiConfigDomain?.let { + try { + _state.value = _state.value.copy(provisionState = WizardStepState.CURRENT) + softApManager.provision(it) + } catch (e: SocketTimeoutException) { + // There is always chance that a socket timeout is thrown from the DK during + // provisioning due to timing constraints. In such cases, we can ignore the response + // and assume that the provisioning was successful. + Timber.log(Log.WARN, e, "Provisioning succeeded due to timeout") + } catch (e: Exception) { + + } finally { + _state.value = _state.value.copy(provisionState = WizardStepState.COMPLETED) + } + } + } + } + + fun verify() { + viewModelScope.launch { + _state.value = _state.value.copy(verifyState = WizardStepState.CURRENT) + val verified = softApManager.verify() + if (verified) { + _state.value = _state.value.copy(verifyState = WizardStepState.COMPLETED) + } + } + } + + private fun WifiData.toConfig(password: String): WifiConfigDomain { + val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo + return WifiConfigDomain(info = wifiInfo, passphrase = password) + } +} + +data class SoftApScreenState( + val configureState: WizardStepState = WizardStepState.COMPLETED, + val connectionState: WizardStepState = WizardStepState.INACTIVE, + val discoveringServicesState: WizardStepState = WizardStepState.INACTIVE, + val selectWifiState: WizardStepState = WizardStepState.INACTIVE, + val selectedWifi: WifiData? = null, + val password: String? = null, + val providePasswordState: WizardStepState = WizardStepState.INACTIVE, + val provisionState: WizardStepState = WizardStepState.INACTIVE, + val verifyState: WizardStepState = WizardStepState.INACTIVE, +) \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt index 87f839a9..a76db6e5 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApWifiScannerViewModel.kt @@ -31,7 +31,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.viewmodel -import android.util.Log import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler @@ -42,6 +41,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDesti import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiAggregator import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.viewmodel.GenericWifiScannerViewModel +import org.slf4j.LoggerFactory import javax.inject.Inject @HiltViewModel @@ -54,13 +54,14 @@ internal class SoftApWifiScannerViewModel @Inject constructor( wifiAggregator = wifiAggregator ) { + private val logger = LoggerFactory.getLogger(SoftApWifiScannerViewModel::class.java) init { listSsids() } private fun listSsids() { val handler = CoroutineExceptionHandler { _, throwable -> - Log.e("AAAA", "$throwable") + logger.error("Error while listing SSIDs: {}", throwable.message) } viewModelScope.launch(handler) { diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 0d62d062..4f034e53 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -5,7 +5,10 @@ Enter the SSID of the SoftAP you want to connect to. \n\nNote: Make sure the nRF 700x device is powered on and in range. - Discovering services… + Discover services + Services discovered. + Discovering services + Resolving IP Address… Change Wi-Fi Dismiss Confirm @@ -27,10 +30,38 @@ Device status Provisioning data Upload status + Provision Provisioning + Provisioned + Verify + Verifying + Verified Please wait while the device is being provisioned. This may take around 5-10 seconds to complete. OK Provisioning completed. + Connect to Device + Connect + Connecting… + Connected + Change + Select Wi-Fi + Select a Wi-Fi Network + Edit + Start + Listing Wi-Fi networks + Edit SSID + Select + Set Passphrase + Set + Configure + Selected Wi-Fi: %s + Select a Wi-Fi Network to provision the nRF 700x device to + Please set the passphrase for the selected Wi-Fi Network. + Passphrase: %s + Provisioning device to your network… + Provisioning completed. + Provides the Wi-Fi credentials to the device. + Optionally verify if provisioning succeeded. \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt index 70b9be67..e15aae38 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/PasswordDialog.kt @@ -113,3 +113,65 @@ fun PasswordDialog(onEvent: (PasswordDialogEvent) -> Unit) { } ) } + + +@Composable +fun PasswordDialog( + onConfirmPressed: (String) -> Unit, + onDismiss: () -> Unit +) { + val passwordField = rememberSaveable { mutableStateOf("") } + val passwordVisible = rememberSaveable { mutableStateOf(false) } + + val visualTransformation = if (passwordVisible.value) { + VisualTransformation.None + } else { + PasswordVisualTransformation() + } + + val image = if (passwordVisible.value) { + Icons.Filled.Visibility + } else { + Icons.Filled.VisibilityOff + } + + val description = if (passwordVisible.value) { + stringResource(id = R.string.hide_password) + } else { + stringResource(id = R.string.show_password) + } + + AlertDialog( + onDismissRequest = onDismiss, + title = { Text(stringResource(id = R.string.set_password)) }, + text = { + OutlinedTextField( + value = passwordField.value, + label = { Text(text = stringResource(id = R.string.password)) }, + visualTransformation = visualTransformation, + onValueChange = { + passwordField.value = it + }, + trailingIcon = { + IconButton(onClick = { passwordVisible.value = !passwordVisible.value }) { + Icon(imageVector = image, description) + } + } + ) + }, + confirmButton = { + TextButton(onClick = { + passwordField.value.let { + onConfirmPressed(passwordField.value) + } + }) { + Text(stringResource(id = R.string.accept)) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(stringResource(id = R.string.dismiss)) + } + } + ) +} diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt index 2d28d242..21479fab 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt @@ -63,7 +63,7 @@ fun WifiSection( } @Composable -private fun getDescription(record: ScanRecordDomain): String { +fun getDescription(record: ScanRecordDomain): String { return StringBuilder() .append(record.wifiInfo?.ssid) .appendLine() diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f33bad43..728c1225 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Feb 12 16:06:22 CET 2024 +#Wed May 15 21:08:23 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt index dd498352..bacf8f08 100644 --- a/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt +++ b/lib/domain/src/main/java/no/nordicsemi/kotlin/wifi/provisioner/domain/BandDomain.kt @@ -34,5 +34,5 @@ package no.nordicsemi.kotlin.wifi.provisioner.domain enum class BandDomain(val id: Int) { BAND_ANY(0), BAND_2_4_GH(1), - BAND_5_GH(2) + BAND_5_GH(2); } \ No newline at end of file diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 6659556b..60079bca 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -18,8 +18,9 @@ dependencies { implementation(libs.retrofit.converter.scalars) implementation(libs.okhttp) implementation(libs.okhttp.logging) - implementation("com.squareup.retrofit2:converter-wire:2.11.0") + implementation(libs.retrofit.converter.wire) implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") + implementation("org.slf4j:slf4j-api:1.7.36") } wire { diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index 13b849fc..dbe6e71f 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -2,10 +2,10 @@ package no.nordicsemi.android.wifi.provisioner.softap import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo -import android.util.Log import kotlinx.coroutines.suspendCancellableCoroutine import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager.Companion.KEY_LINK_ADDR import okio.ByteString.Companion.toByteString +import org.slf4j.LoggerFactory import java.net.InetAddress import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -18,6 +18,7 @@ import kotlin.coroutines.resumeWithException * list could be empty if no services are discovered. */ class NetworkServiceDiscoveryListener internal constructor(private val nsdManager: NsdManager) { + private val logger = LoggerFactory.getLogger(NetworkServiceDiscoveryListener::class.java) private val _discoveredIps = mutableListOf() val discoveredIps: List get() = _discoveredIps @@ -37,11 +38,11 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage val resolveListener = object : NsdManager.ResolveListener { override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) { // Called when the resolve fails. Use the error code to debug. - Log.e("AAA", "Resolve failed: $errorCode") + logger.error("Resolve failed: {}", errorCode) } override fun onServiceResolved(serviceInfo: NsdServiceInfo?) { - Log.d("AAA", "Resolve success: $serviceInfo") + logger.info("Resolve success: {}", serviceInfo) serviceInfo?.let { if (macAddress == null) { stopDiscovery(it) @@ -55,7 +56,6 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage } private fun stopDiscovery(serviceInfo: NsdServiceInfo) { - Log.d("AAA", "Service attributes: ${serviceInfo.attributes}") _discoveredIps.add(serviceInfo.host) continuation.resume(serviceInfo) nsdManager.stopServiceDiscovery(nsdListener) @@ -66,14 +66,14 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage // Called as soon as service discovery begins. override fun onDiscoveryStarted(regType: String) { - Log.d("AAA", "Service discovery started $regType") + logger.trace("Service discovery started for {}", regType) } override fun onServiceFound(service: NsdServiceInfo) { - Log.d("AAA", "Service discovered $service") + logger.info("Service discovered: {}", service) // Check if the service name found matches the service name we are looking for. if (service.serviceName == nsdServiceInfo.serviceName) { - Log.d("AAA", "Resolving service $service") + logger.info("Resolving service...") nsdManager.resolveService(service, resolveListener) } } @@ -81,17 +81,17 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage override fun onServiceLost(service: NsdServiceInfo) { // When the network service is no longer available. // Internal bookkeeping code goes here. - Log.e("AAA", "service lost: $service") } override fun onDiscoveryStopped(serviceType: String) { - Log.i("AAA", "Discovery stopped: $serviceType") + logger.trace("Discovery stopped: {}", serviceType) } override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e( - "AAA", "error on starting service discovery for " + - "$serviceType failed: $errorCode" + logger.error( + "Error while starting service discovery for {} failed: {}", + serviceType, + errorCode ) continuation.resumeWithException( Throwable("Discovery failed: Error code:$errorCode") @@ -99,7 +99,11 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage } override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) { - Log.e("AAA", "Discovery failed: Error code:$errorCode") + logger.error( + "Error while stopping service discovery for {} failed: {}", + serviceType, + errorCode + ) continuation.resumeWithException( Throwable("Discovery failed: Error code:$errorCode") ) diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt index 29ad3464..014e3980 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt @@ -12,10 +12,24 @@ data object WifiNotEnabledException : SoftApException() { private fun readResolve(): Any = WifiNotEnabledException } +/** + * An exception that is thrown when the SoftAp manager fails to connect to the SoftAP network. + */ +data object UnableToConnectToNetwork : SoftApException() { + private fun readResolve(): Any = UnableToConnectToNetwork +} + /** * An exception that is thrown when the SoftAp manager fails to bind to the connected SoftAP * network. */ data object FailedToBindToNetwork : SoftApException() { - private fun readResolve(): Any = WifiNotEnabledException -} \ No newline at end of file + private fun readResolve(): Any = FailedToBindToNetwork +} + +/** + * An exception that is thrown when the SoftAp manager loses connectivity from the SoftAP. + */ +data object OnConnectionLost : SoftApException() { + private fun readResolve(): Any = OnConnectionLost +} diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 3537e5c2..991e1d08 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -131,18 +131,14 @@ class SoftApManager( continuation.resume(Unit) } else { disconnect() - continuation.resumeWithException( - exception = FailedToBindToNetwork - ) + continuation.resumeWithException(exception = FailedToBindToNetwork) } } override fun onUnavailable() { // do failure processing here.. disconnect() - continuation.resumeWithException( - exception = IllegalStateException("Failed to bind to the network.") - ) + continuation.resumeWithException(exception = UnableToConnectToNetwork) } } val wifNetworkBuilder = WifiNetworkSpecifier.Builder() From 6a99e614b09e1a3525c255a672d69c748cc2cc71 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 23 May 2024 13:47:37 +0200 Subject: [PATCH 075/101] Improvements --- .../android/wifi/provisioner/HomeScreen.kt | 8 +- .../ble/sections/ProvisionOverBleSection.kt | 37 +++++++++ feature/ble/src/main/res/values/strings.xml | 5 ++ .../softap/view/ProvisionOverWifiSection.kt} | 25 +----- .../softap/view/SoftApDestinations.kt | 3 +- .../provisioner/softap/view/SoftApScreen.kt | 83 +++++++++++++------ .../softap/viewmodel/SoftApViewModel.kt | 22 ++++- .../softap/src/main/res/values/strings.xml | 6 +- feature/ui/src/main/res/values/strings.xml | 9 -- .../wifi/provisioner/softap/HostName.kt | 31 ++++--- .../wifi/provisioner/softap/SoftApManager.kt | 17 +++- 11 files changed, 165 insertions(+), 81 deletions(-) create mode 100644 feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt => softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt} (62%) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 2a8d0d14..52dc02f4 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -63,10 +63,10 @@ import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.app.R +import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisionOverBleSection import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.ProvisionOverWifiSection import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestination -import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverBle -import no.nordicsemi.android.wifi.provisioner.ui.ProvisionOverWifi @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -121,10 +121,10 @@ fun HomeScreen() { ) }*/ item { - ProvisionOverBle { + ProvisionOverBleSection { vm.navigateTo(BleProvisioningDestination) } - ProvisionOverWifi { + ProvisionOverWifiSection { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { vm.navigateTo(SoftApProvisionerDestination) } else { diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt new file mode 100644 index 00000000..efa468df --- /dev/null +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt @@ -0,0 +1,37 @@ +package no.nordicsemi.android.wifi.provisioner.ble.sections + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.feature.ble.R +import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle + + +@Composable +fun ProvisionOverBleSection(onClick: () -> Unit) { + OutlinedCard( + modifier = Modifier + .padding(all = 8.dp) + .clickable(onClick = onClick) + ) { + Column(modifier = Modifier.padding(all = 16.dp)) { + SectionTitle(text = stringResource( + R.string.provision_over_ble) + ) + Spacer(modifier = Modifier.size(8.dp)) + Text( + text = stringResource(R.string.provision_over_ble_rationale), + style = MaterialTheme.typography.bodyMedium + ) + } + } +} \ No newline at end of file diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml index 53ff3662..b72a0190 100644 --- a/feature/ble/src/main/res/values/strings.xml +++ b/feature/ble/src/main/res/values/strings.xml @@ -136,4 +136,9 @@ Select Wi-Fi Persistent storage + + Provision over Bluetooth LE + This mode uses secure Bluetooth LE link to transfer + Wi-Fi credentials to the provisionee and verify provisioning status. + \ No newline at end of file diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt similarity index 62% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt rename to feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt index 9c7c34ff..194a7aed 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/WelcomeSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.wifi.provisioner.ui +package no.nordicsemi.android.wifi.provisioner.softap.view import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -12,36 +12,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import no.nordicsemi.android.wifi.provisioner.feature.softap.R import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle @Composable -fun ProvisionOverBle(onClick: () -> Unit) { +fun ProvisionOverWifiSection(onClick: () -> Unit) { OutlinedCard( modifier = Modifier .padding(all = 8.dp) .clickable(onClick = onClick) ) { Column(modifier = Modifier.padding(all = 16.dp)) { - SectionTitle(text = stringResource(R.string.provision_over_ble)) - Spacer(modifier = Modifier.size(8.dp)) - Text( - text = stringResource(R.string.provision_over_ble_rationale), - style = MaterialTheme.typography.bodyMedium - ) - } - } -} - -@Composable -fun ProvisionOverWifi(onClick: () -> Unit) { - OutlinedCard( - modifier = Modifier - .padding(all = 8.dp) - .clickable(onClick = onClick) - ) { - Column(modifier = Modifier.padding(all = 16.dp)) { - SectionTitle(text = stringResource(R.string.provision_over_wi_fi)) + SectionTitle(text = stringResource(R.string.provision_over_wifi)) Spacer(modifier = Modifier.size(8.dp)) Text( text = stringResource(R.string.provision_over_wifi_rationale), diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 49a463a2..beb2f715 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -46,7 +46,8 @@ val SoftApProvisionerDestinations = listOf( }, onProvisionPressed = viewModel::onProvisionPressed, verify = viewModel::verify, - navigateUp = viewModel::navigateUp + navigateUp = viewModel::navigateUp, + resetError = viewModel::onSnackBarDismissed, ) } }, diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index 73d414b6..d85be4bf 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -1,11 +1,10 @@ -@file:OptIn(ExperimentalMaterial3Api::class) - package no.nordicsemi.android.wifi.provisioner.softap.view import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState @@ -23,7 +22,10 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -62,6 +64,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +@OptIn(ExperimentalMaterial3Api::class) @Composable fun SoftApScreen( state: SoftApScreenState, @@ -71,28 +74,39 @@ fun SoftApScreen( onPasswordEntered: (String) -> Unit, onProvisionPressed: () -> Unit, verify: () -> Unit, - navigateUp: (() -> Unit) + navigateUp: (() -> Unit), + resetError: () -> Unit ) { var ssidName by rememberSaveable { mutableStateOf("nrf-wifiprov") } val snackbarHostState = remember { SnackbarHostState() } val scope = rememberCoroutineScope() - Column { - NordicAppBar( - text = stringResource(id = R.string.label_wifi_provisioner), - actions = { - LoggerAppBarIcon( - onClick = onLoggerAppBarIconPressed - ) - }, - showBackButton = true, - onNavigationButtonClick = navigateUp - ) - OutlinedCard( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .padding(vertical = 16.dp, horizontal = 8.dp), - ) { - runCatching { + if (state.error != null) { + showSnackBar(scope, snackbarHostState, state.error) { + resetError() + } + } + Scaffold( + contentWindowInsets = WindowInsets(0, 0, 0, 0), + topBar = { + NordicAppBar( + text = stringResource(id = R.string.provision_over_wifi), + actions = { + LoggerAppBarIcon(onClick = onLoggerAppBarIconPressed) + }, + showBackButton = true, + onNavigationButtonClick = navigateUp + ) + }, + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + }, + ) { innerPadding -> + Column(modifier = Modifier.padding(innerPadding)) { + OutlinedCard( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(vertical = 16.dp, horizontal = 8.dp), + ) { Column( modifier = Modifier .fillMaxWidth() @@ -108,7 +122,9 @@ fun SoftApScreen( connectionState = state.connectionState, serviceDiscoveryState = state.discoveringServicesState, ssidName = ssidName, - start = { start(ssidName, Open) } + start = { + start(ssidName, Open) + } ) SelectWifi( provisioningState = state.provisionState, @@ -134,8 +150,6 @@ fun SoftApScreen( verify = verify ) } - }.onFailure { - showSnackBar(scope, snackbarHostState, it) } } } @@ -144,7 +158,8 @@ fun SoftApScreen( private fun showSnackBar( scope: CoroutineScope, snackbarHostState: SnackbarHostState, - throwable: Throwable + throwable: Throwable, + onDismissed: () -> Unit ) { scope.launch { val message = when (throwable) { @@ -154,7 +169,14 @@ private fun showSnackBar( is OnConnectionLost -> "Connection lost!" else -> "${throwable::class.simpleName}: ${throwable.message}" } - snackbarHostState.showSnackbar(message = message) + val result = snackbarHostState.showSnackbar(message = message) + when (result) { + SnackbarResult.Dismissed -> { + onDismissed() + } + + SnackbarResult.ActionPerformed -> {} + } } } @@ -278,7 +300,16 @@ private fun SelectWifi( showVerticalDivider = true ) { if (wifiData != null && selectWifiState != WizardStepState.INACTIVE) { - Text(text = "SSID: ${wifiData.ssid}, band: ${wifiData.channelFallback.wifiInfo?.band?.toDisplayString()}") + Text( + text = "SSID: ${wifiData.ssid}, band: " + + "${ + wifiData + .let { + it.selectedChannel?.wifiInfo?.band?.toDisplayString() + ?: it.channelFallback.wifiInfo?.band?.toDisplayString() + } + }" + ) } else { Text(text = stringResource(R.string.select_wifi_rationale)) } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 42beaa63..9ee621ae 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -38,6 +38,7 @@ import androidx.annotation.RequiresApi import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -53,6 +54,7 @@ import no.nordicsemi.android.log.timber.nRFLoggerTree import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.WifiNotEnabledException import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData @@ -113,12 +115,12 @@ class SoftApViewModel @Inject constructor( Timber.plant(nRFLoggerTree(context, "SoftAP Manager", ssid).also { logger = it }) - - viewModelScope.launch { + val handler = CoroutineExceptionHandler() { _, throwable -> + _state.value = _state.value.copy(error = throwable) + } + viewModelScope.launch(handler) { connect(ssid, passphraseConfiguration) discoverServices() - // listSsids() - // provision() } } @@ -126,6 +128,9 @@ class SoftApViewModel @Inject constructor( ssid: String = "nrf-wifiprov", passphraseConfiguration: PassphraseConfiguration = Open ) { + require(softApManager.isWifiEnabled) { + throw WifiNotEnabledException + } _state.value = _state.value.copy(connectionState = WizardStepState.CURRENT) softApManager.connect(ssid = ssid, passphraseConfiguration = passphraseConfiguration) _state.value = _state.value.copy(configureState = WizardStepState.COMPLETED) @@ -133,6 +138,9 @@ class SoftApViewModel @Inject constructor( } private suspend fun discoverServices() { + require(softApManager.isWifiEnabled) { + throw WifiNotEnabledException + } _state.value = _state.value.copy(discoveringServicesState = WizardStepState.CURRENT) softApManager.discoverServices() _state.value = _state.value.copy(discoveringServicesState = WizardStepState.COMPLETED) @@ -173,6 +181,7 @@ class SoftApViewModel @Inject constructor( // provisioning due to timing constraints. In such cases, we can ignore the response // and assume that the provisioning was successful. Timber.log(Log.WARN, e, "Provisioning succeeded due to timeout") + _state.value = _state.value.copy(error = e) } catch (e: Exception) { } finally { @@ -196,6 +205,10 @@ class SoftApViewModel @Inject constructor( val wifiInfo = selectedChannel?.wifiInfo ?: channelFallback.wifiInfo return WifiConfigDomain(info = wifiInfo, passphrase = password) } + + fun onSnackBarDismissed() { + _state.value = _state.value.copy(error = null) + } } data class SoftApScreenState( @@ -208,4 +221,5 @@ data class SoftApScreenState( val providePasswordState: WizardStepState = WizardStepState.INACTIVE, val provisionState: WizardStepState = WizardStepState.INACTIVE, val verifyState: WizardStepState = WizardStepState.INACTIVE, + val error: Throwable? = null ) \ No newline at end of file diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 4f034e53..deac2c81 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ - "Wi-Fi Provisioner " + "Wi-Fi Provisioner" + "Provision over Wi-Fi" Connect to Device Enter the SSID of the SoftAP you want to connect to. \n\nNote: Make sure the nRF 700x device is powered on and in range. @@ -63,5 +64,8 @@ Provisioning completed. Provides the Wi-Fi credentials to the device. Optionally verify if provisioning succeeded. + This mode uses temporary a Wi-Fi network (SoftAP) + created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. + \ No newline at end of file diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index ebacf75a..ddf147df 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -94,13 +94,4 @@ Select Wi-Fi Persistent storage - - Provision over Bluetooth LE - This mode uses secure Bluetooth LE link to transfer - Wi-Fi credentials to the provisionee and verify provisioning status. - - Provision over Wi-Fi - This mode uses temporary a Wi-Fi network (SoftAP) - created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. - \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt index 68ded82f..e0a889ba 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt @@ -6,7 +6,10 @@ import okhttp3.tls.decodeCertificatePem /** * Host name configuration contains the hostname of the SoftAP provisioning service. * - * @property hostName The hostname of the SoftAP provisioning service. + * @property serviceName Service name of the SoftAP provisioning service. + * @property hostName Hostname of the SoftAP provisioning service. + * @property certificate The certificate of the SoftAP provisioning service. + * @property handshakeCertificates The handshake certificates for the SoftAP provisioning service. */ data class HostNameConfiguration( val serviceName: String = "wifiprov", @@ -21,14 +24,20 @@ data class HostNameConfiguration( private const val CERTIFICATE = "" + "-----BEGIN CERTIFICATE-----\n" + - "MIIB1jCCAXugAwIBAgIUbOY1v8ubBZy6qIsZXelxvLy5l+QwCgYIKoZIzj0EAwIw\n" + - "YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxGjAY\n" + - "BgNVBAoMEVRlc3QgT3JnYW5pemF0aW9uMRcwFQYDVQQDDA53aWZpcHJvdi5sb2Nh\n" + - "bDAeFw0yNDAzMjYxMzI4MzNaFw0yNTAzMjYxMzI4MzNaMGAxCzAJBgNVBAYTAlVT\n" + - "MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRowGAYDVQQKDBFUZXN0IE9y\n" + - "Z2FuaXphdGlvbjEXMBUGA1UEAwwOd2lmaXByb3YubG9jYWwwWTATBgcqhkjOPQIB\n" + - "BggqhkjOPQMBBwNCAAR6COfDiVYhNJkqCe3COkrN/Y9U8LPSDElE+mDk0ri7Ivb8\n" + - "LefdeYP3HgoTEEgem5eDNy10UZlf6+q6VUWyCH8toxMwETAPBgNVHRMBAf8EBTAD\n" + - "AQH/MAoGCCqGSM49BAMCA0kAMEYCIQDmEcPlg4GuPIAE9xvpW8t8LGit/+eDWCqE\n" + - "3ADi/H6f0QIhALUgBnN1+7awE7M1FvSnizX3b5ff7BfzltskPYnpjxqS\n" + + "MIICzTCCAnOgAwIBAgIUF3C1+U4KvWOYM85tZRg5/wmWMKIwCgYIKoZIzj0EAwIw\n" + + "gbAxCzAJBgNVBAYTAlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlv\n" + + "dXJDaXR5MRkwFwYDVQQKDBBZb3VyT3JnYW5pemF0aW9uMR8wHQYDVQQLDBZZb3Vy\n" + + "T3JnYW5pemF0aW9uYWxVbml0MSUwIwYJKoZIhvcNAQkBFhZ5b3VyLmVtYWlsQGV4\n" + + "YW1wbGUuY29tMRcwFQYDVQQDDA53aWZpcHJvdi5sb2NhbDAeFw0yNDA1MjIwODUx\n" + + "MTJaFw0zNDA1MjAwODUxMTJaMIGwMQswCQYDVQQGEwJVUzESMBAGA1UECAwJWW91\n" + + "clN0YXRlMREwDwYDVQQHDAhZb3VyQ2l0eTEZMBcGA1UECgwQWW91ck9yZ2FuaXph\n" + + "dGlvbjEfMB0GA1UECwwWWW91ck9yZ2FuaXphdGlvbmFsVW5pdDElMCMGCSqGSIb3\n" + + "DQEJARYWeW91ci5lbWFpbEBleGFtcGxlLmNvbTEXMBUGA1UEAwwOd2lmaXByb3Yu\n" + + "bG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ7TywX0D1gDuNOB9QJxJtU\n" + + "g9wKnBsgiajKCcpEKQzNyoYVtF6i4He//Oi01BvAiN5Wh636dzoXKsoP9y0yzx/a\n" + + "o2kwZzArBgNVHREEJDAigg53aWZpcHJvdi5sb2NhbIIQKi53aWZpcHJvdi5sb2Nh\n" + + "bDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBpjAdBgNVHQ4EFgQUMbOrGx0KVcEJ\n" + + "rEgRTGzoJOavreowCgYIKoZIzj0EAwIDSAAwRQIhAK1vHxEUMD/i3RzEnLPDxmqV\n" + + "jNCb+C26GeHMp1IqwzeuAiA6+H3OiqFpssvXsVjWEEQxicNpAKL8ZCqL384+rjix\n" + + "5Q==\n" + "-----END CERTIFICATE-----\n" \ No newline at end of file diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 991e1d08..e3496d0f 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -13,6 +13,7 @@ import android.net.wifi.WifiManager import android.net.wifi.WifiNetworkSpecifier import android.os.Build import androidx.annotation.RequiresApi +import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine import no.nordicsemi.android.wifi.provisioner.softap.Open.passphrase import no.nordicsemi.android.wifi.provisioner.softap.domain.ScanResultsDomain @@ -37,6 +38,8 @@ import kotlin.coroutines.resumeWithException * * Entry point to the SoftApManager * + * @param context Context of the application. + * @param hostNameConfiguration HostNameConfiguration to be used for the SoftApManager. * @constructor Create empty SoftApManager. */ class SoftApManager( @@ -53,6 +56,10 @@ class SoftApManager( private val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + + val isWifiEnabled: Boolean + get() = wifiManager.isWifiEnabled + private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager private val nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager @@ -106,14 +113,16 @@ class SoftApManager( * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. * Call [connect] to connect to the softap and bind to the network. */ + @OptIn(InternalCoroutinesApi::class) @RequiresApi(Build.VERSION_CODES.Q) @Throws(WifiNotEnabledException::class, FailedToBindToNetwork::class) suspend fun connect( ssid: String, passphraseConfiguration: PassphraseConfiguration, ): Unit = suspendCancellableCoroutine { continuation -> - if (!wifiManager.isWifiEnabled) { + if (!isWifiEnabled) { continuation.resumeWithException(exception = WifiNotEnabledException) + return@suspendCancellableCoroutine } networkCallback = object : ConnectivityManager.NetworkCallback() { @@ -180,7 +189,7 @@ class SoftApManager( serviceType = "_http._tcp." } ) { - require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isWifiEnabled) { throw WifiNotEnabledException } val serviceInfo = discoverNetworkServices(nsdServiceInfo = nsdServiceInfo) softAp?.apply { this.serviceInfo = serviceInfo @@ -208,7 +217,7 @@ class SoftApManager( * Call [connect] to connect to the softap and bind to the network. */ suspend fun listSsids(): ScanResultsDomain { - require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isWifiEnabled) { throw WifiNotEnabledException } require(isBoundToNetwork) { throw FailedToBindToNetwork } return softApProvisioningService.listSsids().toDomain() } @@ -223,7 +232,7 @@ class SoftApManager( * Call [connect] to connect to the softap and bind to the network. */ suspend fun provision(config: WifiConfigDomain): Response { - require(wifiManager.isWifiEnabled) { throw WifiNotEnabledException } + require(isWifiEnabled) { throw WifiNotEnabledException } require(isBoundToNetwork) { throw FailedToBindToNetwork } return softApProvisioningService.provision(config.toApi()).also { if (it.isSuccessful) { From 34b262f15e9ee5f70a75422cf1206b644e9b8672 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 23 May 2024 14:13:05 +0200 Subject: [PATCH 076/101] Minor improvements --- .../android/wifi/provisioner/softap/view/SoftApScreen.kt | 1 + .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 6 +++--- .../provisioner/softap/NetworkServiceDiscoveryListener.kt | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index d85be4bf..5dacaa07 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -63,6 +63,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +import java.net.SocketTimeoutException @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 9ee621ae..e8979ae1 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -180,10 +180,10 @@ class SoftApViewModel @Inject constructor( // There is always chance that a socket timeout is thrown from the DK during // provisioning due to timing constraints. In such cases, we can ignore the response // and assume that the provisioning was successful. - Timber.log(Log.WARN, e, "Provisioning succeeded due to timeout") - _state.value = _state.value.copy(error = e) + Timber.log(Log.WARN, e, "Connection timed out, provisioning succeeded!") } catch (e: Exception) { - + Timber.log(Log.WARN, e, "Error, provisioning succeeded!") + _state.value = _state.value.copy(error = e) } finally { _state.value = _state.value.copy(provisionState = WizardStepState.COMPLETED) } diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt index dbe6e71f..5381242f 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt @@ -109,7 +109,6 @@ class NetworkServiceDiscoveryListener internal constructor(private val nsdManage ) } } - nsdManager.discoverServices( nsdServiceInfo.serviceType, NsdManager.PROTOCOL_DNS_SD, From f084c992f9b933189dcbf5e967fc9bc26b23f08c Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 23 May 2024 14:14:12 +0200 Subject: [PATCH 077/101] Removes unused resources --- app/src/main/res/values/strings.xml | 21 -- .../src/main/res/drawable/ic_disconnected.xml | 40 ---- .../res/drawable/ic_launcher_background.xml | 201 ------------------ .../res/drawable/ic_launcher_foreground.xml | 54 ----- .../ble/src/main/res/drawable/ic_no_phone.xml | 40 ---- .../ble/src/main/res/drawable/ic_password.xml | 40 ---- .../src/main/res/drawable/ic_wifi_loading.xml | 40 ---- .../src/main/res/drawable/ic_wifi_lock.xml | 40 ---- .../ble/src/main/res/drawable/ic_wifi_ok.xml | 40 ---- .../src/main/res/drawable/ic_wifi_open.xml | 40 ---- feature/ble/src/main/res/values/strings.xml | 20 -- .../softap/src/main/res/values/strings.xml | 17 -- .../src/main/res/drawable/ic_disconnected.xml | 40 ---- .../res/drawable/ic_launcher_background.xml | 201 ------------------ .../res/drawable/ic_launcher_foreground.xml | 54 ----- feature/ui/src/main/res/values/strings.xml | 7 - 16 files changed, 895 deletions(-) delete mode 100644 feature/ble/src/main/res/drawable/ic_disconnected.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_no_phone.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_password.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_wifi_loading.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_wifi_lock.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_wifi_ok.xml delete mode 100644 feature/ble/src/main/res/drawable/ic_wifi_open.xml delete mode 100644 feature/ui/src/main/res/drawable/ic_disconnected.xml delete mode 100644 feature/ui/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 feature/ui/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6dee071d..4f27ed94 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,19 +34,6 @@ Change An icon of nRF70 Series - The nRF Wi-Fi Provisioner app allows provisioning nRF 700x devices to - Wi-Fi networks over Bluetooth LE.\n\n - - ### Key features:\n - * Provisioning nRF 700x devices to Wi-Fi networks.\n - * Displaying connection status of provisioned devices.\n - * Re-provisioning already provisioned devices to alternate networks.\n\n - - ### Requirements:\n - * [nRF700x DK](https://www.nordicsemi.com/News/2022/08/Nordic-Semiconductor-announces-its-first-WiFi-chip).\n - * Wi-Fi Provisioning Service sample programmed.\n\n - - Make sure the device is powered ON and in range. Device status Provisioning data @@ -54,11 +41,7 @@ Unknown error - 1. Make sure the device is turned on and is connected to a power source. - - Unprovisioned Start - Select device Next device Finish Set password @@ -71,7 +54,6 @@ Device status Disconnected Wi-Fi status - Selected Wi-Fi Start provisioning Version Scanning error @@ -83,7 +65,6 @@ Success - Connecting Authentication Association Obtaining IP @@ -121,9 +102,7 @@ Hide password Show password - Version: %s (%s) - Disconnected Authentication Association Obtaining IP diff --git a/feature/ble/src/main/res/drawable/ic_disconnected.xml b/feature/ble/src/main/res/drawable/ic_disconnected.xml deleted file mode 100644 index e7b219f4..00000000 --- a/feature/ble/src/main/res/drawable/ic_disconnected.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_launcher_background.xml b/feature/ble/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 59b53bf6..00000000 --- a/feature/ble/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_launcher_foreground.xml b/feature/ble/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 8e36a423..00000000 --- a/feature/ble/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_no_phone.xml b/feature/ble/src/main/res/drawable/ic_no_phone.xml deleted file mode 100644 index f891c885..00000000 --- a/feature/ble/src/main/res/drawable/ic_no_phone.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_password.xml b/feature/ble/src/main/res/drawable/ic_password.xml deleted file mode 100644 index 272fa039..00000000 --- a/feature/ble/src/main/res/drawable/ic_password.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_wifi_loading.xml b/feature/ble/src/main/res/drawable/ic_wifi_loading.xml deleted file mode 100644 index 4fa2c00f..00000000 --- a/feature/ble/src/main/res/drawable/ic_wifi_loading.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_wifi_lock.xml b/feature/ble/src/main/res/drawable/ic_wifi_lock.xml deleted file mode 100644 index 3c6d7c52..00000000 --- a/feature/ble/src/main/res/drawable/ic_wifi_lock.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_wifi_ok.xml b/feature/ble/src/main/res/drawable/ic_wifi_ok.xml deleted file mode 100644 index 2501e12b..00000000 --- a/feature/ble/src/main/res/drawable/ic_wifi_ok.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/drawable/ic_wifi_open.xml b/feature/ble/src/main/res/drawable/ic_wifi_open.xml deleted file mode 100644 index 9ccdc926..00000000 --- a/feature/ble/src/main/res/drawable/ic_wifi_open.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ble/src/main/res/values/strings.xml b/feature/ble/src/main/res/values/strings.xml index b72a0190..da9c95d7 100644 --- a/feature/ble/src/main/res/values/strings.xml +++ b/feature/ble/src/main/res/values/strings.xml @@ -34,19 +34,6 @@ Change An icon of nRF70 Series - The nRF Wi-Fi Provisioner app allows provisioning nRF 700x devices to - Wi-Fi networks over Bluetooth LE.\n\n - - ### Key features:\n - * Provisioning nRF 700x devices to Wi-Fi networks.\n - * Displaying connection status of provisioned devices.\n - * Re-provisioning already provisioned devices to alternate networks.\n\n - - ### Requirements:\n - * [nRF700x DK](https://www.nordicsemi.com/News/2022/08/Nordic-Semiconductor-announces-its-first-WiFi-chip).\n - * Wi-Fi Provisioning Service sample programmed.\n\n - - Make sure the device is powered ON and in range. Device status Provisioning data @@ -54,11 +41,7 @@ Unknown error - 1. Make sure the device is turned on and is connected to a power source. - - Unprovisioned Start - Select device Next device Finish Set password @@ -84,7 +67,6 @@ Icon representing data available in the section. - Connecting Authentication Association Obtaining IP @@ -122,9 +104,7 @@ Hide password Show password - Version: %s (%s) - Disconnected Authentication Association Obtaining IP diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index deac2c81..ce54373e 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -1,6 +1,5 @@ - "Wi-Fi Provisioner" "Provision over Wi-Fi" Connect to Device Enter the SSID of the SoftAP you want to connect to. @@ -9,10 +8,7 @@ Discover services Services discovered. Discovering services - Resolving IP Address… - Change Wi-Fi Dismiss - Confirm Wi-Fi Access Points Scanning error @@ -32,31 +28,18 @@ Provisioning data Upload status Provision - Provisioning - Provisioned Verify - Verifying - Verified - Please wait while the device is being provisioned. - This may take around 5-10 seconds to complete. - OK - Provisioning completed. - Connect to Device Connect Connecting… Connected Change Select Wi-Fi - Select a Wi-Fi Network - Edit Start - Listing Wi-Fi networks Edit SSID Select Set Passphrase Set Configure - Selected Wi-Fi: %s Select a Wi-Fi Network to provision the nRF 700x device to Please set the passphrase for the selected Wi-Fi Network. Passphrase: %s diff --git a/feature/ui/src/main/res/drawable/ic_disconnected.xml b/feature/ui/src/main/res/drawable/ic_disconnected.xml deleted file mode 100644 index e7b219f4..00000000 --- a/feature/ui/src/main/res/drawable/ic_disconnected.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/feature/ui/src/main/res/drawable/ic_launcher_background.xml b/feature/ui/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 59b53bf6..00000000 --- a/feature/ui/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml b/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 8e36a423..00000000 --- a/feature/ui/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - diff --git a/feature/ui/src/main/res/values/strings.xml b/feature/ui/src/main/res/values/strings.xml index ddf147df..f53f1fd5 100644 --- a/feature/ui/src/main/res/values/strings.xml +++ b/feature/ui/src/main/res/values/strings.xml @@ -12,11 +12,7 @@ Unknown error - 1. Make sure the device is turned on and is connected to a power source. - - Unprovisioned Start - Select device Next device Finish Set password @@ -42,7 +38,6 @@ Icon representing data available in the section. - Connecting Authentication Association Obtaining IP @@ -80,9 +75,7 @@ Hide password Show password - Version: %s (%s) - Disconnected Authentication Association Obtaining IP From edbe7ce405aac9fa11cee1b7bef88b5979cbafa0 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 30 Sep 2022 23:00:38 +0200 Subject: [PATCH 078/101] Readme update --- README.md | 74 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 8778a9ab..51000f47 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,73 @@ -# Android-nRF-Wi-Fi-Provisioner +# nRF Wi-Fi Provisioner for Android -An Android library and app for provisioning [nRF 7 devices](https://www.nordicsemi.com/Products/nRF7002) to a Wi-Fi network. +An Android library and a sample app for provisioning [nRF 7002 devices](https://www.nordicsemi.com/Products/nRF7002) to a Wi-Fi network. ## Application Get it on Google Play -### Flow -The application allows to communicate with a nRF 7 series device. -The main job of the phone is to get status from the device and initiate provisioning or unprovisioning process. +The application requires nRF700x Wi-Fi device with a nRF5x companion chip with firmware allowing provisioning over Bluetooth LE as a transport. + +### Features +- Obtaining device status +- Provisioning to Wi-Fi network +- Unprovisioning See this [User Guide](doc/UserGuide.pdf) with the nice presentation about how to use the application. #### Obtaining status -1. The phone connects to the selected IoT device and initialise pairing. -2. After successful pairing it downloads current version and status. +1. The phone connects to the selected device advertising Wi-Fi Provisioning Service UUID and initialise pairing. +2. After successful pairing, it requests the firmware version and device status. 3. Based on status - provisioning or unprovisioning process can be initiated. #### Provisioning -1. The phone send START_SCAN command to the IoT device and waits for the result. -2. The phone displays the list with result. An user can select Wi-Fi. If Wi-Fi item provides such an option, then there is a possibility to select a specific channel to connect. -3. After selecting interesting Wi-Fi the phone should send STOP_SCAN command. -4. The user needs to provide a password if the selected Wi-Fi is protected. -5. The user selects if the Wi-Fi should be stored in persistent memory which means that Wi-Fi credentials should survive restarting process. -6. Then the user clicks "Provision" button which sends credential to the IoT device and receive connectivity changes from it. -7. When the IoT device is provisioned then the process is finished and a next device can be provisioned. + +1. The phone sends `START_SCAN` command and waits for the result. +2. The phone displays the list with available Wi-Fi networks received from the device. +3. User can select a Wi-Fi. In case of multiple Access Points with the same SSID, user may select specific Wi-Fi channel. +4. After selecting the Wi-Fi, the phone should send `STOP_SCAN` command. +5. User provides a password if the selected Wi-Fi network is protected. +7. User selects, whether the Wi-Fi should be stored in persistent memory which means that Wi-Fi credentials should survive power cycle. Disabling this option may be desired during testing. +8. User clicks the "Provision" button which sends credential to the device and receives provisioniong status updates. +9. When the device is provisioned, the process is complete and a next device can be selected. #### Unprovisioning -1. The phone sends FORGET_CONFIG command and receive success/error result. +1. The phone sends `FORGET_CONFIG` command and receive success/error result. + +## Provisioning Protocol + +The protocol uses Bluetooth LE as transport. + +### Bluetooth LE Advertising + +The device should advertise: +* *Service UUID* - Wi-Fi Provisioning Service UUID +* *Service Data* + * UUID: Wi-Fi Provisioning Service UUID + * Data: + - version (uint8) + - flags (uint16) + - rssi (uint8) +* *Complete Local Name* - device name ### Bluetooth LE Service -Application depends on one service which should be implemented by an IoT device: -```14387800-130c-49e7-b877-2881c89cb258``` + +| UUID | Name | +| ---- | ---- | +| 1438**7800**-130c-49e7-b877-2881c89cb258 | Wi-Fi Provisioning Service | #### Characteristics -The service contains 3 characteristics. -1. ```14387801-130c-49e7-b877-2881c89cb258``` - Unprotected version characteristic which return version number. It is reserved for checking supporting version before actual start of work. -2. ```14387802-130c-49e7-b877-2881c89cb258``` - Protected with pairing control-point characteristic. It is used by the phone to send commands. In indication the command result status is obtained in asynchronous manner. -3. ```14387803-130c-49e7-b877-2881c89cb258``` - Protected with pairing data-out characteristic. In notification the IoT device sends available Wi-Fi items and connectivity status updates. -### Proto files -The communication with the IoT device is handled with the usage of [Proto files](lib_proto/src/main/proto). +| UUID | Name | Security | Properties | Notes | +| ---- | ---- | -------- | ---------- | ----- | +| 1438**7801**-130c-49e7-b877-2881c89cb258 | Version | Unprotected | Read | Firmware version number | +| 1438**7802**-130c-49e7-b877-2881c89cb258 | Control Point | Encrypted | Write, Indicate | Commands and statuses | +| 1438**7803**-130c-49e7-b877-2881c89cb258 | Data Out | Encrypted | Notify | Scan resutls and provisioning statueses | + +### Encoding + +The commands and parameters are encoded using [Protobuf](lib_proto/src/main/proto). + +Read more about Protobuf at https://developers.google.com/protocol-buffers From 41ce02f78d4efa3b12dd09705d8b4459df302661 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 23 May 2024 15:05:40 +0200 Subject: [PATCH 079/101] add proguard rules --- app/proguard-rules.pro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 01639a19..a972830a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,6 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation +-keep class no.nordicsemi.android.wifi.** { *; } \ No newline at end of file From 643aab2f2f8db879823365a101f20a817f621889 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Thu, 23 May 2024 18:37:24 +0200 Subject: [PATCH 080/101] adds missing proguard rules --- app/proguard-rules.pro | 3 ++- lib/domain/build.gradle.kts | 7 +------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index a972830a..1373a054 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,4 +20,5 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation --keep class no.nordicsemi.android.wifi.** { *; } \ No newline at end of file +-keep class no.nordicsemi.android.wifi.** { *; } +-keep class no.nordicsemi.kotlin.wifi.** { *; } \ No newline at end of file diff --git a/lib/domain/build.gradle.kts b/lib/domain/build.gradle.kts index 4da6f641..1b975301 100644 --- a/lib/domain/build.gradle.kts +++ b/lib/domain/build.gradle.kts @@ -5,16 +5,11 @@ plugins { } android { - namespace = "no.nordicsemi.wifi.provisioner.domain" + namespace = "no.nordicsemi.kotlin.wifi.provisioner.domain" } dependencies{ implementation(libs.androidx.core.ktx) - implementation(libs.nordic.ble.common) - implementation(libs.nordic.ble.ktx) - implementation(libs.nordic.uilogger) - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) } wire { From 2bc2d8d323379720b2f14673b12d5054ad7a7a21 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 24 May 2024 08:34:21 +0200 Subject: [PATCH 081/101] adds missing proguard rules --- lib/softap/provisioner/proguard-rules.pro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/softap/provisioner/proguard-rules.pro b/lib/softap/provisioner/proguard-rules.pro index 481bb434..3bdead4a 100644 --- a/lib/softap/provisioner/proguard-rules.pro +++ b/lib/softap/provisioner/proguard-rules.pro @@ -18,4 +18,6 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile +-keep class retrofit2.** { *; } +-keep interface retrofit2.** { *; } \ No newline at end of file From 114b93577eeea9540c845df9855316af3ebca2fe Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 24 May 2024 08:45:25 +0200 Subject: [PATCH 082/101] Recommended proguard rules by square/retrofit --- lib/softap/provisioner/proguard-rules.pro | 73 ++++++++++++++++------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/lib/softap/provisioner/proguard-rules.pro b/lib/softap/provisioner/proguard-rules.pro index 3bdead4a..f8a63525 100644 --- a/lib/softap/provisioner/proguard-rules.pro +++ b/lib/softap/provisioner/proguard-rules.pro @@ -1,23 +1,50 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile --keep class retrofit2.** { *; } --keep interface retrofit2.** { *; } \ No newline at end of file +# Recommended ProGuard rules for Retrofit 2. +# https://github.com/square/retrofit/blob/trunk/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro +# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and +# EnclosingMethod is required to use InnerClasses. +-keepattributes Signature, InnerClasses, EnclosingMethod + +# Retrofit does reflection on method and parameter annotations. +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations + +# Keep annotation default values (e.g., retrofit2.http.Field.encoded). +-keepattributes AnnotationDefault + +# Retain service method parameters when optimizing. +-keepclassmembers,allowshrinking,allowobfuscation interface * { + @retrofit2.http.* ; +} + +# Ignore annotation used for build tooling. +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement + +# Ignore JSR 305 annotations for embedding nullability information. +-dontwarn javax.annotation.** + +# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath. +-dontwarn kotlin.Unit + +# Top-level functions that can only be used by Kotlin. +-dontwarn retrofit2.KotlinExtensions +-dontwarn retrofit2.KotlinExtensions$* + +# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy +# and replaces all potential values with null. Explicitly keeping the interfaces prevents this. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface <1> + +# Keep inherited services. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface * extends <1> + +# With R8 full mode generic signatures are stripped for classes that are not +# kept. Suspend functions are wrapped in continuations where the type argument +# is used. +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation + +# R8 full mode strips generic signatures from return types if not kept. +-if interface * { @retrofit2.http.* public *** *(...); } +-keep,allowoptimization,allowshrinking,allowobfuscation class <3> + +# With R8 full mode generic signatures are stripped for classes that are not kept. +-keep,allowobfuscation,allowshrinking class retrofit2.Response \ No newline at end of file From 03c5b3fd68221f6fe9c7786760eb88e23b2589c9 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 24 May 2024 09:09:01 +0200 Subject: [PATCH 083/101] Recommended proguard rules by square/retrofit --- feature/softap/proguard-rules.pro | 71 ++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/feature/softap/proguard-rules.pro b/feature/softap/proguard-rules.pro index 481bb434..f8a63525 100644 --- a/feature/softap/proguard-rules.pro +++ b/feature/softap/proguard-rules.pro @@ -1,21 +1,50 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +# Recommended ProGuard rules for Retrofit 2. +# https://github.com/square/retrofit/blob/trunk/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro +# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and +# EnclosingMethod is required to use InnerClasses. +-keepattributes Signature, InnerClasses, EnclosingMethod + +# Retrofit does reflection on method and parameter annotations. +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations + +# Keep annotation default values (e.g., retrofit2.http.Field.encoded). +-keepattributes AnnotationDefault + +# Retain service method parameters when optimizing. +-keepclassmembers,allowshrinking,allowobfuscation interface * { + @retrofit2.http.* ; +} + +# Ignore annotation used for build tooling. +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement + +# Ignore JSR 305 annotations for embedding nullability information. +-dontwarn javax.annotation.** + +# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath. +-dontwarn kotlin.Unit + +# Top-level functions that can only be used by Kotlin. +-dontwarn retrofit2.KotlinExtensions +-dontwarn retrofit2.KotlinExtensions$* + +# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy +# and replaces all potential values with null. Explicitly keeping the interfaces prevents this. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface <1> + +# Keep inherited services. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface * extends <1> + +# With R8 full mode generic signatures are stripped for classes that are not +# kept. Suspend functions are wrapped in continuations where the type argument +# is used. +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation + +# R8 full mode strips generic signatures from return types if not kept. +-if interface * { @retrofit2.http.* public *** *(...); } +-keep,allowoptimization,allowshrinking,allowobfuscation class <3> + +# With R8 full mode generic signatures are stripped for classes that are not kept. +-keep,allowobfuscation,allowshrinking class retrofit2.Response \ No newline at end of file From ffa0d8b3a67b210f0471f30015df1db6fcf53e21 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Fri, 24 May 2024 09:54:45 +0200 Subject: [PATCH 084/101] Clean up proguard files. --- app/proguard-rules.pro | 5 +---- feature/ble/consumer-rules.pro | 0 feature/ble/proguard-rules.pro | 21 ------------------- feature/common/consumer-rules.pro | 0 feature/common/proguard-rules.pro | 21 ------------------- feature/softap/consumer-rules.pro | 0 .../{proguard-rules.pro => module-rules.pro} | 0 feature/ui/consumer-rules.pro | 0 .../domain/module-rules.pro | 5 +++-- lib/softap/provisioner/consumer-rules.pro | 0 .../{proguard-rules.pro => module-rules.pro} | 0 11 files changed, 4 insertions(+), 48 deletions(-) delete mode 100644 feature/ble/consumer-rules.pro delete mode 100644 feature/ble/proguard-rules.pro delete mode 100644 feature/common/consumer-rules.pro delete mode 100644 feature/common/proguard-rules.pro delete mode 100644 feature/softap/consumer-rules.pro rename feature/softap/{proguard-rules.pro => module-rules.pro} (100%) delete mode 100644 feature/ui/consumer-rules.pro rename feature/ui/proguard-rules.pro => lib/domain/module-rules.pro (82%) delete mode 100644 lib/softap/provisioner/consumer-rules.pro rename lib/softap/provisioner/{proguard-rules.pro => module-rules.pro} (100%) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 1373a054..01639a19 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,7 +18,4 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile --keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation --keep class no.nordicsemi.android.wifi.** { *; } --keep class no.nordicsemi.kotlin.wifi.** { *; } \ No newline at end of file +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/ble/consumer-rules.pro b/feature/ble/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/ble/proguard-rules.pro b/feature/ble/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/feature/ble/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/common/consumer-rules.pro b/feature/common/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/common/proguard-rules.pro b/feature/common/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/feature/common/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/softap/consumer-rules.pro b/feature/softap/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/softap/proguard-rules.pro b/feature/softap/module-rules.pro similarity index 100% rename from feature/softap/proguard-rules.pro rename to feature/softap/module-rules.pro diff --git a/feature/ui/consumer-rules.pro b/feature/ui/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/ui/proguard-rules.pro b/lib/domain/module-rules.pro similarity index 82% rename from feature/ui/proguard-rules.pro rename to lib/domain/module-rules.pro index 481bb434..206b9cdc 100644 --- a/feature/ui/proguard-rules.pro +++ b/lib/domain/module-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts.kts.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html @@ -18,4 +18,5 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile +-keep class no.nordicsemi.kotlin.wifi.** { *; } \ No newline at end of file diff --git a/lib/softap/provisioner/consumer-rules.pro b/lib/softap/provisioner/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/softap/provisioner/proguard-rules.pro b/lib/softap/provisioner/module-rules.pro similarity index 100% rename from lib/softap/provisioner/proguard-rules.pro rename to lib/softap/provisioner/module-rules.pro From 195e4db3a5eba6695ca0900d4b2a988ebfa672f6 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 24 May 2024 14:25:00 +0200 Subject: [PATCH 085/101] Fixing dependencies --- app/build.gradle.kts | 18 +---- .../android/wifi/provisioner/HomeScreen.kt | 8 +- .../android/wifi/provisioner/MainActivity.kt | 19 ++++- .../provisioner/WifiProvisionerApplication.kt | 10 ++- feature/ble/build.gradle.kts | 22 +---- .../ble/repository/RepositoryModule.kt | 3 +- .../ble/scanner/ProvisioningData.kt | 2 +- .../provisioner/ble/view/BleDestination.kt | 4 +- .../provisioner/ble/viewmodel/BleViewModel.kt | 18 ++--- feature/common/build.gradle.kts | 5 -- feature/softap/build.gradle.kts | 25 +----- feature/softap/module-rules.pro | 50 ------------ .../softap/view/SoftApConnectorDialog.kt | 3 - .../softap/view/SoftApDestinations.kt | 80 ++++++++++--------- .../provisioner/softap/view/SoftApScreen.kt | 4 +- .../softap/view/entity/SoftApViewEntity.kt | 36 --------- .../softap/viewmodel/SoftApViewModel.kt | 13 +-- feature/ui/build.gradle.kts | 4 - lib/ble/provisioner/build.gradle.kts | 5 +- lib/domain/build.gradle.kts | 4 - lib/domain/module-rules.pro | 2 +- lib/softap/provisioner/build.gradle.kts | 7 +- .../wifi/provisioner/softap/SoftApManager.kt | 2 - settings.gradle.kts | 2 +- 24 files changed, 104 insertions(+), 242 deletions(-) delete mode 100644 feature/softap/module-rules.pro delete mode 100644 feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 59b06b13..72f038a2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -49,29 +49,13 @@ dependencies { implementation(project(":lib:ble:provisioner")) implementation(project(":lib:softap:provisioner")) - implementation(libs.androidx.lifecycle.runtime.compose) - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.foundation) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.hilt.navigation.compose) - implementation(libs.nordic.scanner) implementation(libs.androidx.activity.compose) - implementation(libs.androidx.lifecycle.viewModel.compose) - implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) - implementation(libs.nordic.uilogger) - implementation(libs.nordic.blek.uiscanner) - implementation(libs.nordic.permissions.ble) - - implementation(libs.accompanist.placeholder) - - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) + implementation(libs.timber) } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 52dc02f4..66893cec 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -64,9 +64,9 @@ import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewMod import no.nordicsemi.android.common.theme.view.NordicAppBar import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisionOverBleSection -import no.nordicsemi.android.wifi.provisioner.ble.view.BleProvisioningDestination +import no.nordicsemi.android.wifi.provisioner.ble.view.BleDestination import no.nordicsemi.android.wifi.provisioner.softap.view.ProvisionOverWifiSection -import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApProvisionerDestination +import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApDestination @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -122,11 +122,11 @@ fun HomeScreen() { }*/ item { ProvisionOverBleSection { - vm.navigateTo(BleProvisioningDestination) + vm.navigateTo(BleDestination) } ProvisionOverWifiSection { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - vm.navigateTo(SoftApProvisionerDestination) + vm.navigateTo(SoftApDestination) } else { scope.launch { snackbarHostState.showSnackbar( diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt index 14ee05db..c840937f 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/MainActivity.kt @@ -31,7 +31,10 @@ package no.nordicsemi.android.wifi.provisioner +import android.graphics.Color +import android.os.Build import android.os.Bundle +import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.fillMaxSize @@ -49,14 +52,22 @@ class MainActivity : NordicActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() + + enableEdgeToEdge(statusBarStyle = SystemBarStyle.dark(Color.TRANSPARENT)) + setContent { NordicTheme { Surface(modifier = Modifier.fillMaxSize()) { NavigationView( - destinations = HomeDestination + - BleProvisioningDestinations + - SoftApProvisionerDestinations + destinations = (HomeDestination + + BleProvisioningDestinations).run { + // Soft AP is available on Android 10 and newer. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + this + SoftApProvisionerDestinations + } else { + this + } + } ) } } diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt index 1522b532..033127a3 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/WifiProvisionerApplication.kt @@ -33,7 +33,15 @@ package no.nordicsemi.android.wifi.provisioner import android.app.Application import dagger.hilt.android.HiltAndroidApp +import timber.log.Timber @HiltAndroidApp -class WifiProvisionerApplication : Application() +class WifiProvisionerApplication : Application() { + + override fun onCreate() { + super.onCreate() + + Timber.plant(Timber.DebugTree()) + } +} diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 405068de..6b86c53a 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -31,7 +31,6 @@ plugins { alias(libs.plugins.nordic.feature) - alias(libs.plugins.nordic.hilt) } android { @@ -44,30 +43,11 @@ dependencies { implementation(project(":lib:ble:provisioner")) implementation(project(":lib:domain")) - implementation(libs.androidx.lifecycle.runtime.compose) - - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.foundation) - implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material.iconsExtended) - implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.hilt.navigation.compose) - implementation(libs.nordic.scanner) - implementation(libs.androidx.activity.compose) - implementation(libs.androidx.lifecycle.viewModel.compose) - - implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) implementation(libs.nordic.logger) - implementation(libs.nordic.uilogger) - implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.permissions.ble) - - implementation(libs.accompanist.placeholder) - - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) + implementation(libs.nordic.blek.uiscanner) } diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt index 998a449f..27e9b357 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/repository/RepositoryModule.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.repository +package no.nordicsemi.android.wifi.provisioner.ble.repository import android.content.Context import dagger.Module @@ -38,7 +38,6 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import no.nordicsemi.android.wifi.provisioner.ble.ProvisionerRepository -import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository @Module @InstallIn(SingletonComponent::class) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt index f6c58e27..b29684e9 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/scanner/ProvisioningData.kt @@ -32,7 +32,7 @@ package no.nordicsemi.android.wifi.provisioner.ble.scanner import android.os.ParcelUuid -import no.nordicsemi.android.common.core.DataByteArray +import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResultData import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResults import java.util.UUID diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt index 3dbac42a..1f93d643 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleDestination.kt @@ -37,17 +37,19 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.common.navigation.with import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestination import no.nordicsemi.android.wifi.provisioner.ble.wifi.view.BleWifiScannerScreen import no.nordicsemi.android.wifi.provisioner.ble.wifi.viewmodel.BleWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData +val BleDestination = createSimpleDestination("ble") val BleProvisioningDestination = createSimpleDestination("ble-provisioning-destination") val BleWifiScannerDestination = createDestination( name = "wifi-access-points-ble-destination" ) -val BleProvisioningDestinations = listOf( +val BleProvisioningDestinations = BleDestination with listOf( defineDestination(BleProvisioningDestination) { BleProvisioningScreen() }, diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt index 236724fe..86d53cf9 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/viewmodel/BleViewModel.kt @@ -47,14 +47,19 @@ import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.kotlin.ble.core.RealServerDevice -import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading -import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.ble.internal.ConnectionStatus import no.nordicsemi.android.wifi.provisioner.ble.launchWithCatch import no.nordicsemi.android.wifi.provisioner.ble.repository.ProvisionerResourceRepository import no.nordicsemi.android.wifi.provisioner.ble.scanner.BleScannerDestinationId -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent import no.nordicsemi.android.wifi.provisioner.ble.view.BleViewEntity +import no.nordicsemi.android.wifi.provisioner.ble.view.BleWifiScannerDestination +import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent +import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading +import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnFinishedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent @@ -63,12 +68,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnProvisionNex import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectDeviceClickEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnSelectWifiEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnShowPasswordDialog -import no.nordicsemi.android.wifi.provisioner.ble.view.BleWifiScannerDestination -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -import no.nordicsemi.android.wifi.provisioner.ble.domain.WifiConfigDomain -import no.nordicsemi.android.wifi.provisioner.ble.view.OnUnprovisionEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OnVolatileMemoryChangedEvent -import no.nordicsemi.android.wifi.provisioner.ble.view.OpenLoggerEvent +import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.ProvisioningViewEvent import javax.inject.Inject @HiltViewModel diff --git a/feature/common/build.gradle.kts b/feature/common/build.gradle.kts index 7e53b85d..d91ee168 100644 --- a/feature/common/build.gradle.kts +++ b/feature/common/build.gradle.kts @@ -1,6 +1,5 @@ plugins { alias(libs.plugins.nordic.feature) - alias(libs.plugins.nordic.hilt) } android { @@ -10,9 +9,5 @@ android { dependencies { implementation(project(":lib:domain")) - implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.hilt.navigation.compose) - implementation(libs.androidx.activity.compose) - implementation(libs.androidx.lifecycle.viewModel.compose) implementation(libs.nordic.navigation) } diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index f461b39f..78a62bb2 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -31,7 +31,6 @@ plugins { alias(libs.plugins.nordic.feature) - alias(libs.plugins.nordic.hilt) } android { @@ -39,33 +38,15 @@ android { } dependencies { - implementation(project(":feature:common")) implementation(project(":feature:ui")) implementation(project(":lib:softap:provisioner")) - implementation(libs.androidx.lifecycle.runtime.compose) - - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.foundation) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.material.iconsExtended) - implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.hilt.navigation.compose) - implementation(libs.androidx.activity.compose) - implementation(libs.androidx.lifecycle.viewModel.compose) - - implementation(libs.nordic.core) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) - implementation(libs.nordic.uilogger) implementation(libs.nordic.logger) - implementation(libs.accompanist.placeholder) - - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) + implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.retrofit.core) implementation(libs.retrofit.converter.gson) @@ -73,6 +54,6 @@ dependencies { implementation(libs.okhttp.logging) // Timber & SLF4J - implementation ("com.arcao:slf4j-timber:3.1") - implementation ("no.nordicsemi.android:log-timber:2.3.0") + implementation (libs.slf4j.timber) + implementation(libs.nordic.log.timber) } diff --git a/feature/softap/module-rules.pro b/feature/softap/module-rules.pro deleted file mode 100644 index f8a63525..00000000 --- a/feature/softap/module-rules.pro +++ /dev/null @@ -1,50 +0,0 @@ -# Recommended ProGuard rules for Retrofit 2. -# https://github.com/square/retrofit/blob/trunk/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro -# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and -# EnclosingMethod is required to use InnerClasses. --keepattributes Signature, InnerClasses, EnclosingMethod - -# Retrofit does reflection on method and parameter annotations. --keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations - -# Keep annotation default values (e.g., retrofit2.http.Field.encoded). --keepattributes AnnotationDefault - -# Retain service method parameters when optimizing. --keepclassmembers,allowshrinking,allowobfuscation interface * { - @retrofit2.http.* ; -} - -# Ignore annotation used for build tooling. --dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement - -# Ignore JSR 305 annotations for embedding nullability information. --dontwarn javax.annotation.** - -# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath. --dontwarn kotlin.Unit - -# Top-level functions that can only be used by Kotlin. --dontwarn retrofit2.KotlinExtensions --dontwarn retrofit2.KotlinExtensions$* - -# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy -# and replaces all potential values with null. Explicitly keeping the interfaces prevents this. --if interface * { @retrofit2.http.* ; } --keep,allowobfuscation interface <1> - -# Keep inherited services. --if interface * { @retrofit2.http.* ; } --keep,allowobfuscation interface * extends <1> - -# With R8 full mode generic signatures are stripped for classes that are not -# kept. Suspend functions are wrapped in continuations where the type argument -# is used. --keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation - -# R8 full mode strips generic signatures from return types if not kept. --if interface * { @retrofit2.http.* public *** *(...); } --keep,allowoptimization,allowshrinking,allowobfuscation class <3> - -# With R8 full mode generic signatures are stripped for classes that are not kept. --keep,allowobfuscation,allowshrinking class retrofit2.Response \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt index 35811cb0..56cf7e68 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApConnectorDialog.kt @@ -85,9 +85,6 @@ internal fun SoftApConnectorDialog( ) } - - - @Composable internal fun EditSsidDialog( ssidName: String = "nrf-wifiprov", diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index beb2f715..02b34983 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -1,6 +1,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext import androidx.hilt.navigation.compose.hiltViewModel @@ -8,53 +9,56 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import no.nordicsemi.android.common.navigation.createDestination import no.nordicsemi.android.common.navigation.createSimpleDestination import no.nordicsemi.android.common.navigation.defineDestination +import no.nordicsemi.android.common.navigation.with import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApViewModel import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApWifiScannerViewModel import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.WifiScannerViewEvent -/** - * Created by Roshan Rajaratnam on 14/02/2024. - */ +val SoftApDestination = createSimpleDestination("softap") val SoftApProvisionerDestination = createSimpleDestination("softap-provisioner-destination") val SoftApWifiScannerDestination = createDestination( name = "wifi-access-points-softap-destination" ) -val SoftApProvisionerDestinations = listOf( - defineDestination(SoftApProvisionerDestination) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - val viewModel = hiltViewModel() - val state by viewModel.state.collectAsStateWithLifecycle() - val context = LocalContext.current - // SoftApProvisioningScreen() - SoftApScreen( - state = state, - onLoggerAppBarIconPressed = { - viewModel.onLoggerAppBarIconPressed(context) - }, - start = { ssid, configuration -> - viewModel.start( - context = context, - ssid = ssid, - passphraseConfiguration = configuration - ) - }, - onSelectWifiPressed = viewModel::onSelectWifiPressed, - onPasswordEntered = { - viewModel.onPasswordEntered(it) - }, - onProvisionPressed = viewModel::onProvisionPressed, - verify = viewModel::verify, - navigateUp = viewModel::navigateUp, - resetError = viewModel::onSnackBarDismissed, +@RequiresApi(Build.VERSION_CODES.Q) +private val softApProvisionerDestination = defineDestination(SoftApProvisionerDestination) { + val viewModel = hiltViewModel() + val state by viewModel.state.collectAsStateWithLifecycle() + val context = LocalContext.current + + SoftApScreen( + state = state, + onLoggerAppBarIconPressed = { + viewModel.onLoggerAppBarIconPressed(context) + }, + start = { ssid, configuration -> + viewModel.start( + context = context, + ssid = ssid, + passphraseConfiguration = configuration ) - } - }, - defineDestination(SoftApWifiScannerDestination) { - val viewModel = hiltViewModel() - val viewEntity by viewModel.state.collectAsStateWithLifecycle() - val onEvent: (WifiScannerViewEvent) -> Unit = { viewModel.onEvent(it) } - SoftApWifiScannerScreen(viewEntity, onEvent) - } + }, + onSelectWifiPressed = viewModel::onSelectWifiPressed, + onPasswordEntered = { + viewModel.onPasswordEntered(it) + }, + onProvisionPressed = viewModel::onProvisionPressed, + verify = viewModel::verify, + navigateUp = viewModel::navigateUp, + resetError = viewModel::onSnackBarDismissed, + ) +} + +private val softApWifiScannerDestination = defineDestination(SoftApWifiScannerDestination) { + val viewModel = hiltViewModel() + val viewEntity by viewModel.state.collectAsStateWithLifecycle() + val onEvent: (WifiScannerViewEvent) -> Unit = { viewModel.onEvent(it) } + SoftApWifiScannerScreen(viewEntity, onEvent) +} + +@RequiresApi(Build.VERSION_CODES.Q) +val SoftApProvisionerDestinations = SoftApDestination with listOf( + softApProvisionerDestination, + softApWifiScannerDestination, ) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index 5dacaa07..ff562ef9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -240,9 +240,7 @@ private fun ConnectToSoftAp( null } else WizardStepAction.Action( text = stringResource(id = R.string.start), - onClick = { - start() - } + onClick = start, ), showVerticalDivider = false, ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt deleted file mode 100644 index 76d9c9f9..00000000 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/entity/SoftApViewEntity.kt +++ /dev/null @@ -1,36 +0,0 @@ -package no.nordicsemi.android.wifi.provisioner.softap.view.entity - -import no.nordicsemi.android.wifi.provisioner.softap.SoftAp -import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain -import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource -import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Success -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -import no.nordicsemi.kotlin.wifi.provisioner.feature.common.view.ViewEntity - -/** - * SoftApViewEntity is a data class that represents the view state of the SoftAp provisioning screen - */ -data class SoftApViewEntity( - val device: SoftAp? = null, - override val network: WifiData? = null, - override val password: String? = null, - override val showPasswordDialog: Boolean? = null, - override val provisioningStatus: Resource? = null, - override val isConnected: Boolean = true, - val isAuthorized: Boolean = false, - val showSoftApDialog: Boolean = false, - val showProvisioningDialog: Boolean = false, - val isNetworkServiceDiscoveryCompleted: Boolean? = null -) : ViewEntity { - - override fun hasFinished(): Boolean { - val status = (provisioningStatus as? Success)?.data - return status == WifiConnectionStateDomain.DISCONNECTED || - status == WifiConnectionStateDomain.CONNECTED - } - - override fun hasFinishedWithSuccess(): Boolean { - val status = (provisioningStatus as? Success)?.data - return status == WifiConnectionStateDomain.CONNECTED - } -} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index e8979ae1..22da34f9 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -50,6 +50,7 @@ import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.common.theme.view.WizardStepState +import no.nordicsemi.android.log.LogSession import no.nordicsemi.android.log.timber.nRFLoggerTree import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration @@ -74,11 +75,9 @@ class SoftApViewModel @Inject constructor( val state = _state.asStateFlow() private var wifiConfigDomain: WifiConfigDomain? = null - private var logger: Timber.Tree? = null - + private var logger: nRFLoggerTree? = null init { - Timber.plant(Timber.DebugTree()) navigationManager.resultFrom(SoftApWifiScannerDestination) .mapNotNull { it as? NavigationResult.Success } .onEach { @@ -99,10 +98,11 @@ class SoftApViewModel @Inject constructor( ?.let { launchIntent -> context.startActivity(launchIntent) } ?: run { - LoggerLauncher.launch(context) - } + LoggerLauncher.launch(context, logger?.session as LogSession) + } } + @RequiresApi(Build.VERSION_CODES.Q) fun start( context: Context, ssid: String = "nrf-wifiprov", @@ -115,7 +115,7 @@ class SoftApViewModel @Inject constructor( Timber.plant(nRFLoggerTree(context, "SoftAP Manager", ssid).also { logger = it }) - val handler = CoroutineExceptionHandler() { _, throwable -> + val handler = CoroutineExceptionHandler { _, throwable -> _state.value = _state.value.copy(error = throwable) } viewModelScope.launch(handler) { @@ -124,6 +124,7 @@ class SoftApViewModel @Inject constructor( } } + @RequiresApi(Build.VERSION_CODES.Q) private suspend fun connect( ssid: String = "nrf-wifiprov", passphraseConfiguration: PassphraseConfiguration = Open diff --git a/feature/ui/build.gradle.kts b/feature/ui/build.gradle.kts index 072798c5..edac5181 100644 --- a/feature/ui/build.gradle.kts +++ b/feature/ui/build.gradle.kts @@ -43,10 +43,6 @@ dependencies { implementation(libs.nordic.theme) - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.foundation) - implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.accompanist.placeholder) diff --git a/lib/ble/provisioner/build.gradle.kts b/lib/ble/provisioner/build.gradle.kts index cce571af..f82b4ac4 100644 --- a/lib/ble/provisioner/build.gradle.kts +++ b/lib/ble/provisioner/build.gradle.kts @@ -41,11 +41,8 @@ android { dependencies { api(project(":lib:domain")) + implementation(libs.nordic.ble.ktx) - implementation(libs.nordic.ble.common) - implementation(libs.nordic.uilogger) - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) } wire { diff --git a/lib/domain/build.gradle.kts b/lib/domain/build.gradle.kts index 1b975301..e6347f44 100644 --- a/lib/domain/build.gradle.kts +++ b/lib/domain/build.gradle.kts @@ -8,10 +8,6 @@ android { namespace = "no.nordicsemi.kotlin.wifi.provisioner.domain" } -dependencies{ - implementation(libs.androidx.core.ktx) -} - wire { kotlin {} } \ No newline at end of file diff --git a/lib/domain/module-rules.pro b/lib/domain/module-rules.pro index 206b9cdc..c3d6cb63 100644 --- a/lib/domain/module-rules.pro +++ b/lib/domain/module-rules.pro @@ -19,4 +19,4 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile --keep class no.nordicsemi.kotlin.wifi.** { *; } \ No newline at end of file +-keep,allowshrinking,allowobfuscation class no.nordicsemi.kotlin.wifi.** { *; } \ No newline at end of file diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/provisioner/build.gradle.kts index 60079bca..9f39058a 100644 --- a/lib/softap/provisioner/build.gradle.kts +++ b/lib/softap/provisioner/build.gradle.kts @@ -10,17 +10,18 @@ android { dependencies { api(project(":lib:domain")) + implementation(libs.androidx.core.ktx) implementation(libs.androidx.annotation) - implementation(libs.nordic.core) + implementation(libs.retrofit.core) implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.converter.scalars) + implementation(libs.retrofit.converter.wire) implementation(libs.okhttp) implementation(libs.okhttp.logging) - implementation(libs.retrofit.converter.wire) implementation("com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.12") - implementation("org.slf4j:slf4j-api:1.7.36") + implementation("org.slf4j:slf4j-api:1.7.36") // TODO replace with libs } wire { diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index e3496d0f..730de80c 100644 --- a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -13,7 +13,6 @@ import android.net.wifi.WifiManager import android.net.wifi.WifiNetworkSpecifier import android.os.Build import androidx.annotation.RequiresApi -import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine import no.nordicsemi.android.wifi.provisioner.softap.Open.passphrase import no.nordicsemi.android.wifi.provisioner.softap.domain.ScanResultsDomain @@ -113,7 +112,6 @@ class SoftApManager( * @throws FailedToBindToNetwork if the device failed to bind to the connected wifi network. * Call [connect] to connect to the softap and bind to the network. */ - @OptIn(InternalCoroutinesApi::class) @RequiresApi(Build.VERSION_CODES.Q) @Throws(WifiNotEnabledException::class, FailedToBindToNetwork::class) suspend fun connect( diff --git a/settings.gradle.kts b/settings.gradle.kts index 6828b692..504f03ed 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,7 +48,7 @@ dependencyResolutionManagement { } versionCatalogs { create("libs") { - from("no.nordicsemi.android.gradle:version-catalog:1.11.4") + from("no.nordicsemi.android.gradle:version-catalog:1.11.8") } } } From d15676fa21d5ae7b4cb107547722110054cc84bd Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 24 May 2024 15:07:47 +0200 Subject: [PATCH 086/101] Moving ble and softap modules one level up --- app/build.gradle.kts | 4 ++-- feature/ble/build.gradle.kts | 2 +- feature/softap/build.gradle.kts | 2 +- lib/ble/{provisioner => }/.gitignore | 0 lib/ble/{provisioner => }/build.gradle.kts | 0 lib/ble/{provisioner => }/module-rules.pro | 0 lib/ble/{provisioner => }/src/main/AndroidManifest.xml | 0 .../java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt | 0 .../android/wifi/provisioner/ble/ProvisionerRepository.kt | 0 .../android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt | 0 .../android/wifi/provisioner/ble/domain/ToApiMapper.kt | 0 .../android/wifi/provisioner/ble/domain/ToDomainMapper.kt | 0 .../android/wifi/provisioner/ble/domain/VersionDomain.kt | 0 .../android/wifi/provisioner/ble/domain/WifiConfigDomain.kt | 0 .../android/wifi/provisioner/ble/internal/BleManagerStatus.kt | 0 .../wifi/provisioner/ble/internal/ByteArrayReadResponse.kt | 0 .../provisioner/ble/internal/ConnectionObserverAdapter.kt | 0 .../provisioner/ble/internal/NotificationTimeoutException.kt | 0 .../wifi/provisioner/ble/internal/ProvisionerBleManager.kt | 0 .../wifi/provisioner/ble/internal/ResponseErrorException.kt | 0 lib/ble/{provisioner => }/src/main/proto/common.proto | 0 lib/ble/{provisioner => }/src/main/proto/request.proto | 0 lib/ble/{provisioner => }/src/main/proto/response.proto | 0 lib/ble/{provisioner => }/src/main/proto/result.proto | 0 lib/ble/{provisioner => }/src/main/proto/version.proto | 0 lib/softap/{provisioner => }/.gitignore | 0 lib/softap/{provisioner => }/build.gradle.kts | 0 lib/softap/{provisioner => }/module-rules.pro | 0 lib/softap/{provisioner => }/src/main/AndroidManifest.xml | 0 .../no/nordicsemi/android/wifi/provisioner/softap/HostName.kt | 0 .../provisioner/softap/NetworkServiceDiscoveryListener.kt | 0 .../wifi/provisioner/softap/PassphraseConfiguration.kt | 0 .../no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt | 0 .../android/wifi/provisioner/softap/SoftApException.kt | 0 .../android/wifi/provisioner/softap/SoftApManager.kt | 0 .../wifi/provisioner/softap/SoftApProvisioningService.kt | 0 .../wifi/provisioner/softap/credentials/Credentials.kt | 0 .../wifi/provisioner/softap/domain/ScanResultsDomain.kt | 0 .../android/wifi/provisioner/softap/domain/ToApiMapper.kt | 0 .../android/wifi/provisioner/softap/domain/ToDomainMapper.kt | 0 .../wifi/provisioner/softap/domain/WifiConfigDomain.kt | 0 lib/softap/{provisioner => }/src/main/proto/common.proto | 0 settings.gradle.kts | 4 ++-- 43 files changed, 6 insertions(+), 6 deletions(-) rename lib/ble/{provisioner => }/.gitignore (100%) rename lib/ble/{provisioner => }/build.gradle.kts (100%) rename lib/ble/{provisioner => }/module-rules.pro (100%) rename lib/ble/{provisioner => }/src/main/AndroidManifest.xml (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt (100%) rename lib/ble/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt (100%) rename lib/ble/{provisioner => }/src/main/proto/common.proto (100%) rename lib/ble/{provisioner => }/src/main/proto/request.proto (100%) rename lib/ble/{provisioner => }/src/main/proto/response.proto (100%) rename lib/ble/{provisioner => }/src/main/proto/result.proto (100%) rename lib/ble/{provisioner => }/src/main/proto/version.proto (100%) rename lib/softap/{provisioner => }/.gitignore (100%) rename lib/softap/{provisioner => }/build.gradle.kts (100%) rename lib/softap/{provisioner => }/module-rules.pro (100%) rename lib/softap/{provisioner => }/src/main/AndroidManifest.xml (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt (100%) rename lib/softap/{provisioner => }/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt (100%) rename lib/softap/{provisioner => }/src/main/proto/common.proto (100%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 72f038a2..6dff163d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -46,8 +46,8 @@ dependencies { implementation(project(":feature:softap")) implementation(project(":feature:common")) implementation(project(":feature:ui")) - implementation(project(":lib:ble:provisioner")) - implementation(project(":lib:softap:provisioner")) + implementation(project(":lib:ble")) + implementation(project(":lib:softap")) implementation(libs.androidx.compose.ui) diff --git a/feature/ble/build.gradle.kts b/feature/ble/build.gradle.kts index 6b86c53a..eeeec341 100644 --- a/feature/ble/build.gradle.kts +++ b/feature/ble/build.gradle.kts @@ -40,7 +40,7 @@ android { dependencies { implementation(project(":feature:common")) implementation(project(":feature:ui")) - implementation(project(":lib:ble:provisioner")) + implementation(project(":lib:ble")) implementation(project(":lib:domain")) implementation(libs.androidx.compose.material.iconsExtended) diff --git a/feature/softap/build.gradle.kts b/feature/softap/build.gradle.kts index 78a62bb2..5a5bd8d6 100644 --- a/feature/softap/build.gradle.kts +++ b/feature/softap/build.gradle.kts @@ -40,7 +40,7 @@ android { dependencies { implementation(project(":feature:common")) implementation(project(":feature:ui")) - implementation(project(":lib:softap:provisioner")) + implementation(project(":lib:softap")) implementation(libs.nordic.theme) implementation(libs.nordic.navigation) diff --git a/lib/ble/provisioner/.gitignore b/lib/ble/.gitignore similarity index 100% rename from lib/ble/provisioner/.gitignore rename to lib/ble/.gitignore diff --git a/lib/ble/provisioner/build.gradle.kts b/lib/ble/build.gradle.kts similarity index 100% rename from lib/ble/provisioner/build.gradle.kts rename to lib/ble/build.gradle.kts diff --git a/lib/ble/provisioner/module-rules.pro b/lib/ble/module-rules.pro similarity index 100% rename from lib/ble/provisioner/module-rules.pro rename to lib/ble/module-rules.pro diff --git a/lib/ble/provisioner/src/main/AndroidManifest.xml b/lib/ble/src/main/AndroidManifest.xml similarity index 100% rename from lib/ble/provisioner/src/main/AndroidManifest.xml rename to lib/ble/src/main/AndroidManifest.xml diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/Ext.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepository.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/ProvisionerRepositoryImpl.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToApiMapper.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/ToDomainMapper.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/VersionDomain.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/domain/WifiConfigDomain.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/BleManagerStatus.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ByteArrayReadResponse.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ConnectionObserverAdapter.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/NotificationTimeoutException.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ProvisionerBleManager.kt diff --git a/lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt b/lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt similarity index 100% rename from lib/ble/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt rename to lib/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/internal/ResponseErrorException.kt diff --git a/lib/ble/provisioner/src/main/proto/common.proto b/lib/ble/src/main/proto/common.proto similarity index 100% rename from lib/ble/provisioner/src/main/proto/common.proto rename to lib/ble/src/main/proto/common.proto diff --git a/lib/ble/provisioner/src/main/proto/request.proto b/lib/ble/src/main/proto/request.proto similarity index 100% rename from lib/ble/provisioner/src/main/proto/request.proto rename to lib/ble/src/main/proto/request.proto diff --git a/lib/ble/provisioner/src/main/proto/response.proto b/lib/ble/src/main/proto/response.proto similarity index 100% rename from lib/ble/provisioner/src/main/proto/response.proto rename to lib/ble/src/main/proto/response.proto diff --git a/lib/ble/provisioner/src/main/proto/result.proto b/lib/ble/src/main/proto/result.proto similarity index 100% rename from lib/ble/provisioner/src/main/proto/result.proto rename to lib/ble/src/main/proto/result.proto diff --git a/lib/ble/provisioner/src/main/proto/version.proto b/lib/ble/src/main/proto/version.proto similarity index 100% rename from lib/ble/provisioner/src/main/proto/version.proto rename to lib/ble/src/main/proto/version.proto diff --git a/lib/softap/provisioner/.gitignore b/lib/softap/.gitignore similarity index 100% rename from lib/softap/provisioner/.gitignore rename to lib/softap/.gitignore diff --git a/lib/softap/provisioner/build.gradle.kts b/lib/softap/build.gradle.kts similarity index 100% rename from lib/softap/provisioner/build.gradle.kts rename to lib/softap/build.gradle.kts diff --git a/lib/softap/provisioner/module-rules.pro b/lib/softap/module-rules.pro similarity index 100% rename from lib/softap/provisioner/module-rules.pro rename to lib/softap/module-rules.pro diff --git a/lib/softap/provisioner/src/main/AndroidManifest.xml b/lib/softap/src/main/AndroidManifest.xml similarity index 100% rename from lib/softap/provisioner/src/main/AndroidManifest.xml rename to lib/softap/src/main/AndroidManifest.xml diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/HostName.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/NetworkServiceDiscoveryListener.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/PassphraseConfiguration.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftAp.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApException.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApProvisioningService.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/credentials/Credentials.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ScanResultsDomain.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToApiMapper.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/ToDomainMapper.kt diff --git a/lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt similarity index 100% rename from lib/softap/provisioner/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt rename to lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/domain/WifiConfigDomain.kt diff --git a/lib/softap/provisioner/src/main/proto/common.proto b/lib/softap/src/main/proto/common.proto similarity index 100% rename from lib/softap/provisioner/src/main/proto/common.proto rename to lib/softap/src/main/proto/common.proto diff --git a/settings.gradle.kts b/settings.gradle.kts index 504f03ed..fcd7a520 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -59,8 +59,8 @@ include(":feature:ble") include(":feature:softap") include(":feature:ui") include(":feature:common") -include(":lib:ble:provisioner") -include(":lib:softap:provisioner") +include(":lib:ble") +include(":lib:softap") include(":lib:domain") //if (file('../Android-Common-Libraries').exists()) { From 51a541f7465dbd16bd0c30e4a31e3bd5114b3c97 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 01:43:15 +0200 Subject: [PATCH 087/101] Minor improvements --- .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 22da34f9..41190a3d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -176,14 +176,17 @@ class SoftApViewModel @Inject constructor( wifiConfigDomain?.let { try { _state.value = _state.value.copy(provisionState = WizardStepState.CURRENT) - softApManager.provision(it) + val response = softApManager.provision(it) + if(response.isSuccessful) { + Timber.log(Log.INFO, "Provisioning succeeded: $response") + } } catch (e: SocketTimeoutException) { // There is always chance that a socket timeout is thrown from the DK during // provisioning due to timing constraints. In such cases, we can ignore the response // and assume that the provisioning was successful. Timber.log(Log.WARN, e, "Connection timed out, provisioning succeeded!") } catch (e: Exception) { - Timber.log(Log.WARN, e, "Error, provisioning succeeded!") + Timber.log(Log.WARN, e, "Error occurred, provisioning may have succeeded!") _state.value = _state.value.copy(error = e) } finally { _state.value = _state.value.copy(provisionState = WizardStepState.COMPLETED) From e661ceec7d7b4794b495d974d02264863a6579ec Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 01:47:13 +0200 Subject: [PATCH 088/101] Separates SSID and Band --- .../wifi/provisioner/softap/view/SoftApScreen.kt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index ff562ef9..fe2c74b6 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -299,16 +299,14 @@ private fun SelectWifi( showVerticalDivider = true ) { if (wifiData != null && selectWifiState != WizardStepState.INACTIVE) { + Text(text = "SSID: ${wifiData.ssid}") Text( - text = "SSID: ${wifiData.ssid}, band: " + - "${ - wifiData - .let { - it.selectedChannel?.wifiInfo?.band?.toDisplayString() - ?: it.channelFallback.wifiInfo?.band?.toDisplayString() - } - }" - ) + text = "Band: ${ + wifiData.let { + it.selectedChannel?.wifiInfo?.band?.toDisplayString() + ?: it.channelFallback.wifiInfo?.band?.toDisplayString() + } + }") } else { Text(text = stringResource(R.string.select_wifi_rationale)) } From 170410ef377bacc01d34dd9a27e199793032771a Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 01:53:58 +0200 Subject: [PATCH 089/101] Add a check if request succeeded. --- .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 41190a3d..a3e23bb5 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -177,7 +177,7 @@ class SoftApViewModel @Inject constructor( try { _state.value = _state.value.copy(provisionState = WizardStepState.CURRENT) val response = softApManager.provision(it) - if(response.isSuccessful) { + if (response.isSuccessful) { Timber.log(Log.INFO, "Provisioning succeeded: $response") } } catch (e: SocketTimeoutException) { From 106dab091badba322e86ee7f015c5b601555353c Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 01:57:03 +0200 Subject: [PATCH 090/101] Mark password state as completed in case the network is open. --- .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index a3e23bb5..db9b93b0 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -156,7 +156,9 @@ class SoftApViewModel @Inject constructor( _state.value = _state.value.copy( selectedWifi = record, selectWifiState = WizardStepState.COMPLETED, - providePasswordState = WizardStepState.CURRENT + providePasswordState = if (record.authMode == AuthModeDomain.OPEN) + WizardStepState.COMPLETED + else WizardStepState.CURRENT ) } From 7e73db534a8a99e1031f4aecaf2968a8aa1d724a Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 03:06:23 +0200 Subject: [PATCH 091/101] Fix strings --- feature/softap/src/main/res/values/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index ce54373e..654b33a8 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -6,7 +6,7 @@ \n\nNote: Make sure the nRF 700x device is powered on and in range. Discover services - Services discovered. + Services discovered Discovering services Dismiss Wi-Fi Access Points @@ -41,12 +41,12 @@ Set Configure Select a Wi-Fi Network to provision the nRF 700x device to - Please set the passphrase for the selected Wi-Fi Network. + Set the passphrase for the selected Wi-Fi Network Passphrase: %s Provisioning device to your network… Provisioning completed. - Provides the Wi-Fi credentials to the device. - Optionally verify if provisioning succeeded. + Provides the Wi-Fi credentials to the device + Optionally verify provisioning state This mode uses temporary a Wi-Fi network (SoftAP) created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. From 5ac3a83c234ca7d22512387c7449826d824ffabf Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Sat, 25 May 2024 03:07:45 +0200 Subject: [PATCH 092/101] ADd timeout for verification --- .../provisioner/softap/view/SoftApScreen.kt | 28 +++++++++++++------ .../softap/viewmodel/SoftApViewModel.kt | 19 ++++++++++--- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index fe2c74b6..a40c1eea 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -28,6 +28,7 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -40,6 +41,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar @@ -63,7 +65,6 @@ import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData -import java.net.SocketTimeoutException @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -407,16 +408,18 @@ private fun Verify( verificationState: WizardStepState, verify: () -> Unit ) { + var isVerifyClicked by remember { mutableStateOf(false) } WizardStepComponent( icon = Icons.Default.Verified, title = stringResource(id = R.string.verify), state = verificationState, - decor = if (verificationState == WizardStepState.INACTIVE && - provisioningState == WizardStepState.COMPLETED - ) { + decor = if (provisioningState == WizardStepState.COMPLETED && !isVerifyClicked && verificationState == WizardStepState.CURRENT) { WizardStepAction.Action( text = stringResource(id = R.string.verify), - onClick = verify + onClick = { + isVerifyClicked = true + verify() + } ) } else if (verificationState == WizardStepState.CURRENT) { WizardStepAction.ProgressIndicator @@ -424,10 +427,11 @@ private fun Verify( showVerticalDivider = false ) { ProgressItem( - text = when (verificationState) { - WizardStepState.INACTIVE -> stringResource(R.string.optional_verification_rationale) - WizardStepState.CURRENT -> "Locating provisioned device..." - WizardStepState.COMPLETED -> "Verification completed." + text = when { + !isVerifyClicked -> stringResource(R.string.optional_verification_rationale) + verificationState == WizardStepState.CURRENT -> "Locating provisioned device..." + verificationState == WizardStepState.COMPLETED -> "Verification completed." + else -> {""} }, status = when (verificationState) { WizardStepState.CURRENT -> ProgressItemStatus.WORKING @@ -437,6 +441,12 @@ private fun Verify( iconRightPadding = 24.dp, ) } + LaunchedEffect(isVerifyClicked) { + if(isVerifyClicked) { + delay(5000L) + isVerifyClicked = false + } + } } diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index db9b93b0..4cddce1d 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -45,6 +45,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import kotlinx.coroutines.withTimeout import no.nordicsemi.android.common.logger.LoggerLauncher import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.Navigator @@ -58,6 +59,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager import no.nordicsemi.android.wifi.provisioner.softap.WifiNotEnabledException import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData import timber.log.Timber import java.net.SocketTimeoutException @@ -160,6 +162,9 @@ class SoftApViewModel @Inject constructor( WizardStepState.COMPLETED else WizardStepState.CURRENT ) + if(record.authMode == AuthModeDomain.OPEN) { + onPasswordEntered("") + } } fun onPasswordEntered(password: String) { @@ -192,6 +197,7 @@ class SoftApViewModel @Inject constructor( _state.value = _state.value.copy(error = e) } finally { _state.value = _state.value.copy(provisionState = WizardStepState.COMPLETED) + _state.value = _state.value.copy(verifyState = WizardStepState.CURRENT) } } } @@ -200,9 +206,14 @@ class SoftApViewModel @Inject constructor( fun verify() { viewModelScope.launch { _state.value = _state.value.copy(verifyState = WizardStepState.CURRENT) - val verified = softApManager.verify() - if (verified) { - _state.value = _state.value.copy(verifyState = WizardStepState.COMPLETED) + try { + withTimeout(5000L) { + val verified = softApManager.verify() + if (verified) { + _state.value = _state.value.copy(verifyState = WizardStepState.COMPLETED) + } + } + } catch (e: Exception) { } } } @@ -219,7 +230,7 @@ class SoftApViewModel @Inject constructor( data class SoftApScreenState( val configureState: WizardStepState = WizardStepState.COMPLETED, - val connectionState: WizardStepState = WizardStepState.INACTIVE, + val connectionState: WizardStepState = WizardStepState.CURRENT, val discoveringServicesState: WizardStepState = WizardStepState.INACTIVE, val selectWifiState: WizardStepState = WizardStepState.INACTIVE, val selectedWifi: WifiData? = null, From 92092d55654008c70a2fda1ee3a5ae8bc4fe29dc Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 27 May 2024 13:54:41 +0200 Subject: [PATCH 093/101] ADds timeout for verification and many other ui improvements --- .../softap/view/SoftApDestinations.kt | 1 + .../provisioner/softap/view/SoftApScreen.kt | 106 ++++++++++-------- .../softap/viewmodel/SoftApViewModel.kt | 32 ++++-- .../softap/src/main/res/values/strings.xml | 9 +- .../wifi/provisioner/softap/SoftApManager.kt | 2 +- 5 files changed, 91 insertions(+), 59 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt index 02b34983..d549d1a2 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApDestinations.kt @@ -28,6 +28,7 @@ private val softApProvisionerDestination = defineDestination(SoftApProvisionerDe val context = LocalContext.current SoftApScreen( + context = context, state = state, onLoggerAppBarIconPressed = { viewModel.onLoggerAppBarIconPressed(context) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index a40c1eea..7ce66143 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -1,5 +1,6 @@ package no.nordicsemi.android.wifi.provisioner.softap.view +import android.content.Context import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -12,12 +13,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material.icons.filled.PermDataSetting import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Verified import androidx.compose.material.icons.filled.Wifi import androidx.compose.material.icons.filled.WifiFind import androidx.compose.material.icons.filled.WifiPassword +import androidx.compose.material.icons.outlined.NetworkCheck import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -28,7 +29,6 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -41,7 +41,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay +import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.launch import no.nordicsemi.android.common.logger.view.LoggerAppBarIcon import no.nordicsemi.android.common.theme.view.NordicAppBar @@ -62,6 +62,7 @@ import no.nordicsemi.android.wifi.provisioner.softap.viewmodel.SoftApScreenState import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.SelectChannelDialog import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData @@ -69,6 +70,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData @OptIn(ExperimentalMaterial3Api::class) @Composable fun SoftApScreen( + context: Context, state: SoftApScreenState, onLoggerAppBarIconPressed: () -> Unit, start: (String, PassphraseConfiguration) -> Unit, @@ -83,7 +85,12 @@ fun SoftApScreen( val snackbarHostState = remember { SnackbarHostState() } val scope = rememberCoroutineScope() if (state.error != null) { - showSnackBar(scope, snackbarHostState, state.error) { + showSnackBar( + context = context, + scope = scope, + snackbarHostState = snackbarHostState, + throwable = state.error + ) { resetError() } } @@ -123,6 +130,7 @@ fun SoftApScreen( ConnectToSoftAp( connectionState = state.connectionState, serviceDiscoveryState = state.discoveringServicesState, + isConnectionRequested = state.isConnectionRequested, ssidName = ssidName, start = { start(ssidName, Open) @@ -138,17 +146,20 @@ fun SoftApScreen( SetPassphrase( provisioningState = state.provisionState, providePasswordState = state.providePasswordState, + wifiData = state.selectedWifi, password = state.password, onPasswordEntered = onPasswordEntered ) Provisioning( passwordState = state.providePasswordState, provisioningState = state.provisionState, + isProvisioningRequested = state.isProvisioningRequested, onProvisionPressed = onProvisionPressed ) Verify( provisioningState = state.provisionState, verificationState = state.verifyState, + isVerificationRequested = state.isVerificationRequested, verify = verify ) } @@ -158,6 +169,7 @@ fun SoftApScreen( } private fun showSnackBar( + context: Context, scope: CoroutineScope, snackbarHostState: SnackbarHostState, throwable: Throwable, @@ -165,20 +177,15 @@ private fun showSnackBar( ) { scope.launch { val message = when (throwable) { - is WifiNotEnabledException -> "Please enable Wi-Fi!" + is WifiNotEnabledException -> context.getString(R.string.please_enable_wi_fi) is FailedToBindToNetwork -> "Failed to bind to network!" is UnableToConnectToNetwork -> "Unable to connect to network!" is OnConnectionLost -> "Connection lost!" + is TimeoutCancellationException -> "Verification timed out, please retry!" else -> "${throwable::class.simpleName}: ${throwable.message}" } val result = snackbarHostState.showSnackbar(message = message) - when (result) { - SnackbarResult.Dismissed -> { - onDismissed() - } - - SnackbarResult.ActionPerformed -> {} - } + if (result == SnackbarResult.Dismissed) onDismissed() } } @@ -227,6 +234,7 @@ private fun ConfigureSoftAp( @Composable private fun ConnectToSoftAp( connectionState: WizardStepState, + isConnectionRequested: Boolean, serviceDiscoveryState: WizardStepState, ssidName: String, start: () -> Unit, @@ -246,14 +254,17 @@ private fun ConnectToSoftAp( showVerticalDivider = false, ) { ProgressItem( - text = when (connectionState) { - WizardStepState.CURRENT -> stringResource(id = R.string.connecting) - WizardStepState.COMPLETED -> stringResource(id = R.string.connected) + text = when { + isConnectionRequested && connectionState == WizardStepState.CURRENT -> stringResource( + id = R.string.connecting + ) + + connectionState == WizardStepState.COMPLETED -> stringResource(id = R.string.connected) else -> stringResource(id = R.string.connect) }, - status = when (connectionState) { - WizardStepState.CURRENT -> ProgressItemStatus.WORKING - WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + status = when { + isConnectionRequested && connectionState == WizardStepState.CURRENT -> ProgressItemStatus.WORKING + connectionState == WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS else -> ProgressItemStatus.DISABLED }, iconRightPadding = 24.dp, @@ -308,6 +319,7 @@ private fun SelectWifi( ?: it.channelFallback.wifiInfo?.band?.toDisplayString() } }") + Text(text = "Security: ${wifiData.authMode.toDisplayString()}") } else { Text(text = stringResource(R.string.select_wifi_rationale)) } @@ -318,12 +330,13 @@ private fun SelectWifi( private fun SetPassphrase( providePasswordState: WizardStepState, provisioningState: WizardStepState, + wifiData: WifiData?, password: String? = null, onPasswordEntered: (String) -> Unit, ) { var showDialog by rememberSaveable { mutableStateOf(false) } WizardStepComponent( - icon = Icons.Default.WifiPassword, + icon = wifiData?.authMode?.toImageVector() ?: Icons.Default.WifiPassword, title = stringResource(id = R.string.set_passphrase), state = providePasswordState, decor = if (providePasswordState == WizardStepState.INACTIVE) { @@ -364,21 +377,22 @@ private fun SetPassphrase( private fun Provisioning( passwordState: WizardStepState, provisioningState: WizardStepState, + isProvisioningRequested: Boolean, onProvisionPressed: () -> Unit ) { WizardStepComponent( - icon = Icons.Default.PermDataSetting, + icon = Icons.Outlined.NetworkCheck, title = stringResource(id = R.string.provision), state = provisioningState, - decor = if (passwordState == WizardStepState.COMPLETED && - provisioningState == WizardStepState.INACTIVE + decor = if (isProvisioningRequested && provisioningState == WizardStepState.CURRENT) { + WizardStepAction.ProgressIndicator + } else if (passwordState == WizardStepState.COMPLETED && + provisioningState == WizardStepState.CURRENT ) { WizardStepAction.Action( text = stringResource(id = R.string.provision), onClick = onProvisionPressed ) - } else if (provisioningState == WizardStepState.CURRENT) { - WizardStepAction.ProgressIndicator } else if (passwordState == WizardStepState.COMPLETED && provisioningState == WizardStepState.COMPLETED ) { @@ -387,14 +401,15 @@ private fun Provisioning( showVerticalDivider = false ) { ProgressItem( - text = when (provisioningState) { - WizardStepState.INACTIVE -> stringResource(R.string.provisioning_rationale) - WizardStepState.CURRENT -> stringResource(R.string.provisioning_device_to_your_network) - WizardStepState.COMPLETED -> stringResource(R.string.provisioning_completed) + text = when { + isProvisioningRequested && provisioningState == WizardStepState.CURRENT -> stringResource(R.string.provisioning_device_to_your_network) + provisioningState == WizardStepState.COMPLETED -> stringResource(R.string.provisioning_completed) + provisioningState == WizardStepState.INACTIVE -> stringResource(R.string.provisioning_rationale) + else -> stringResource(R.string.provisioning_rationale) }, - status = when (provisioningState) { - WizardStepState.CURRENT -> ProgressItemStatus.WORKING - WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + status = when { + isProvisioningRequested && provisioningState == WizardStepState.CURRENT -> ProgressItemStatus.WORKING + provisioningState == WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS else -> ProgressItemStatus.DISABLED }, iconRightPadding = 24.dp, @@ -406,18 +421,17 @@ private fun Provisioning( private fun Verify( provisioningState: WizardStepState, verificationState: WizardStepState, + isVerificationRequested: Boolean, verify: () -> Unit ) { - var isVerifyClicked by remember { mutableStateOf(false) } WizardStepComponent( icon = Icons.Default.Verified, title = stringResource(id = R.string.verify), state = verificationState, - decor = if (provisioningState == WizardStepState.COMPLETED && !isVerifyClicked && verificationState == WizardStepState.CURRENT) { + decor = if (provisioningState == WizardStepState.COMPLETED && !isVerificationRequested && verificationState == WizardStepState.CURRENT) { WizardStepAction.Action( text = stringResource(id = R.string.verify), onClick = { - isVerifyClicked = true verify() } ) @@ -428,25 +442,21 @@ private fun Verify( ) { ProgressItem( text = when { - !isVerifyClicked -> stringResource(R.string.optional_verification_rationale) - verificationState == WizardStepState.CURRENT -> "Locating provisioned device..." - verificationState == WizardStepState.COMPLETED -> "Verification completed." - else -> {""} + isVerificationRequested && verificationState == WizardStepState.CURRENT -> + stringResource(R.string.locating_provisioned_device) + + verificationState == WizardStepState.CURRENT -> stringResource(R.string.optional_verification_rationale) + verificationState == WizardStepState.COMPLETED -> stringResource(R.string.verification_completed) + else -> stringResource(R.string.optional_verification_rationale) }, - status = when (verificationState) { - WizardStepState.CURRENT -> ProgressItemStatus.WORKING - WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS + status = when { + isVerificationRequested && verificationState == WizardStepState.CURRENT -> ProgressItemStatus.WORKING + verificationState == WizardStepState.COMPLETED -> ProgressItemStatus.SUCCESS else -> ProgressItemStatus.DISABLED }, iconRightPadding = 24.dp, ) } - LaunchedEffect(isVerifyClicked) { - if(isVerifyClicked) { - delay(5000L) - isVerifyClicked = false - } - } } @@ -542,4 +552,4 @@ private fun String.toPassphrase(): String { password += '*' } return password -} +} \ No newline at end of file diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 4cddce1d..354eb665 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -39,6 +39,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -56,6 +57,7 @@ import no.nordicsemi.android.log.timber.nRFLoggerTree import no.nordicsemi.android.wifi.provisioner.softap.Open import no.nordicsemi.android.wifi.provisioner.softap.PassphraseConfiguration import no.nordicsemi.android.wifi.provisioner.softap.SoftApManager +import no.nordicsemi.android.wifi.provisioner.softap.UnableToConnectToNetwork import no.nordicsemi.android.wifi.provisioner.softap.WifiNotEnabledException import no.nordicsemi.android.wifi.provisioner.softap.domain.WifiConfigDomain import no.nordicsemi.android.wifi.provisioner.softap.view.SoftApWifiScannerDestination @@ -100,8 +102,8 @@ class SoftApViewModel @Inject constructor( ?.let { launchIntent -> context.startActivity(launchIntent) } ?: run { - LoggerLauncher.launch(context, logger?.session as LogSession) - } + LoggerLauncher.launch(context, logger?.session as LogSession) + } } @RequiresApi(Build.VERSION_CODES.Q) @@ -118,6 +120,9 @@ class SoftApViewModel @Inject constructor( logger = it }) val handler = CoroutineExceptionHandler { _, throwable -> + if (throwable is UnableToConnectToNetwork) { + _state.value = _state.value.copy(isConnectionRequested = false) + } _state.value = _state.value.copy(error = throwable) } viewModelScope.launch(handler) { @@ -162,7 +167,7 @@ class SoftApViewModel @Inject constructor( WizardStepState.COMPLETED else WizardStepState.CURRENT ) - if(record.authMode == AuthModeDomain.OPEN) { + if (record.authMode == AuthModeDomain.OPEN) { onPasswordEntered("") } } @@ -173,7 +178,8 @@ class SoftApViewModel @Inject constructor( wifiConfigDomain = wifiData.toConfig(password) _state.value = _state.value.copy( providePasswordState = WizardStepState.COMPLETED, - password = password + password = password, + provisionState = WizardStepState.CURRENT ) } } @@ -182,7 +188,10 @@ class SoftApViewModel @Inject constructor( viewModelScope.launch { wifiConfigDomain?.let { try { - _state.value = _state.value.copy(provisionState = WizardStepState.CURRENT) + _state.value = _state.value.copy( + isProvisioningRequested = true, + provisionState = WizardStepState.CURRENT + ) val response = softApManager.provision(it) if (response.isSuccessful) { Timber.log(Log.INFO, "Provisioning succeeded: $response") @@ -196,6 +205,7 @@ class SoftApViewModel @Inject constructor( Timber.log(Log.WARN, e, "Error occurred, provisioning may have succeeded!") _state.value = _state.value.copy(error = e) } finally { + softApManager.disconnect() _state.value = _state.value.copy(provisionState = WizardStepState.COMPLETED) _state.value = _state.value.copy(verifyState = WizardStepState.CURRENT) } @@ -205,15 +215,20 @@ class SoftApViewModel @Inject constructor( fun verify() { viewModelScope.launch { - _state.value = _state.value.copy(verifyState = WizardStepState.CURRENT) + _state.value = _state.value.copy(isVerificationRequested = true) try { - withTimeout(5000L) { + withTimeout(10000L) { val verified = softApManager.verify() if (verified) { _state.value = _state.value.copy(verifyState = WizardStepState.COMPLETED) } } + } catch (e: TimeoutCancellationException) { + Timber.log(Log.WARN, e, "Verification timed out!") + _state.value = _state.value.copy(error = e, isVerificationRequested = false) } catch (e: Exception) { + Timber.log(Log.WARN, e, "Unknown error occurred!") + _state.value = _state.value.copy(error = e, isVerificationRequested = false) } } } @@ -231,12 +246,15 @@ class SoftApViewModel @Inject constructor( data class SoftApScreenState( val configureState: WizardStepState = WizardStepState.COMPLETED, val connectionState: WizardStepState = WizardStepState.CURRENT, + val isConnectionRequested: Boolean = false, val discoveringServicesState: WizardStepState = WizardStepState.INACTIVE, val selectWifiState: WizardStepState = WizardStepState.INACTIVE, val selectedWifi: WifiData? = null, val password: String? = null, val providePasswordState: WizardStepState = WizardStepState.INACTIVE, val provisionState: WizardStepState = WizardStepState.INACTIVE, + val isProvisioningRequested: Boolean = false, val verifyState: WizardStepState = WizardStepState.INACTIVE, + val isVerificationRequested: Boolean = false, val error: Throwable? = null ) \ No newline at end of file diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 654b33a8..085d63b7 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -43,12 +43,15 @@ Select a Wi-Fi Network to provision the nRF 700x device to Set the passphrase for the selected Wi-Fi Network Passphrase: %s - Provisioning device to your network… - Provisioning completed. - Provides the Wi-Fi credentials to the device + Sending Wi-Fi credentials… + Wi-Fi credentials sent + Send Wi-Fi credentials Optionally verify provisioning state This mode uses temporary a Wi-Fi network (SoftAP) created by the provisionee to send Wi-Fi credentials. Communication is encrypted using TLS. + Locating provisioned device… + Verification completed + Please enable Wi-Fi! \ No newline at end of file diff --git a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt index 730de80c..d9e69d7b 100644 --- a/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt +++ b/lib/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/SoftApManager.kt @@ -279,7 +279,7 @@ class SoftApManager( } ?: false - companion object { + internal companion object { const val KEY_LINK_ADDR = "linkaddr" } } \ No newline at end of file From f2f284da06954b3e5bbf1ca8d38d8f9da991d0ce Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 27 May 2024 14:11:26 +0200 Subject: [PATCH 094/101] Revert unified BLE provisioning UI --- .../ble/sections}/DeviceSection.kt | 26 +------------------ .../ble/sections}/DisconnectedDeviceStatus.kt | 2 +- .../ble/sections}/PasswordSection.kt | 2 +- .../ble/sections}/ProvisioningSection.kt | 4 +-- .../provisioner/ble/sections/StatusSection.kt | 4 +-- .../ble/sections}/UnprovisioningSection.kt | 2 +- .../provisioner/ble/sections}/WifiSection.kt | 2 +- .../ble/view/BleProvisioningScreen.kt | 14 +++++----- .../wifi/provisioner/ble}/view/UiMapper.kt | 2 +- .../wifi/provisioner/ui/mapping/UiMapper.kt | 10 +++++++ 10 files changed, 27 insertions(+), 41 deletions(-) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/DeviceSection.kt (82%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/DisconnectedDeviceStatus.kt (97%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/PasswordSection.kt (97%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/ProvisioningSection.kt (98%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/UnprovisioningSection.kt (98%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections}/WifiSection.kt (97%) rename feature/{ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui => ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble}/view/UiMapper.kt (98%) diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt similarity index 82% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt index ae596fd0..335d8165 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DeviceSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DeviceSection.kt @@ -29,11 +29,10 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.PhoneAndroid -import androidx.compose.material.icons.outlined.Router import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource @@ -62,29 +61,6 @@ fun BluetoothDevice( ) } - -@Composable -fun SoftApDevice( - name: String?, - address: String, - isEditable: Boolean = false, - onEvent: (ProvisioningViewEvent) -> Unit -) { - ClickableDataItem( - imageVector = Icons.Outlined.Router, - title = name ?: address, - isEditable = isEditable, - description = address, - onClick = { onEvent(OnSelectDeviceClickEvent) }, - buttonText = stringResource(id = R.string.change) - ) -} - -@Composable -fun SoftApDeviceNotSelected(onEvent: (ProvisioningViewEvent) -> Unit) { - DeviceNotSelectedSection(imageVector = Icons.Outlined.Router, onEvent = onEvent) -} - @Composable fun BluetoothDeviceNotSelected(onEvent: (ProvisioningViewEvent) -> Unit) { DeviceNotSelectedSection(imageVector = Icons.Outlined.PhoneAndroid, onEvent = onEvent) diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt similarity index 97% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt index 956dea96..c385c7e6 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/DisconnectedDeviceStatus.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/DisconnectedDeviceStatus.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.LinkOff diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt similarity index 97% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt index 6b8f95d4..bea0d990 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/PasswordSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/PasswordSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Password diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt similarity index 98% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt index 3706003e..7032c474 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/ProvisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -50,7 +50,7 @@ import no.nordicsemi.kotlin.wifi.provisioner.domain.WifiConnectionStateDomain import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem import no.nordicsemi.android.wifi.provisioner.ui.R -import no.nordicsemi.android.wifi.provisioner.ui.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Resource diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt index 314196d9..9a7b3e56 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/StatusSection.kt @@ -46,8 +46,8 @@ import no.nordicsemi.android.wifi.provisioner.ui.DataItem import no.nordicsemi.android.wifi.provisioner.ui.ErrorDataItem import no.nordicsemi.android.wifi.provisioner.ui.LoadingItem import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ui.view.toDisplayString -import no.nordicsemi.android.wifi.provisioner.ui.view.toImageVector +import no.nordicsemi.android.wifi.provisioner.ble.view.toDisplayString +import no.nordicsemi.android.wifi.provisioner.ble.view.toImageVector import no.nordicsemi.kotlin.wifi.provisioner.domain.DeviceStatusDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Error import no.nordicsemi.kotlin.wifi.provisioner.domain.resource.Loading diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt similarity index 98% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt index c948025f..6c1a450e 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/UnprovisioningSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/UnprovisioningSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt similarity index 97% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt index 21479fab..2eaf412f 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/section/WifiSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/WifiSection.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view.section +package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt index 27fc4fc0..6df3c2d4 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/BleProvisioningScreen.kt @@ -57,13 +57,13 @@ import no.nordicsemi.android.wifi.provisioner.ble.sections.VolatileMemorySwitch import no.nordicsemi.android.wifi.provisioner.ble.viewmodel.BleViewModel import no.nordicsemi.android.wifi.provisioner.feature.ble.R import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog -import no.nordicsemi.android.wifi.provisioner.ui.view.section.BluetoothDevice -import no.nordicsemi.android.wifi.provisioner.ui.view.section.BluetoothDeviceNotSelected -import no.nordicsemi.android.wifi.provisioner.ui.view.section.DisconnectedDeviceStatus -import no.nordicsemi.android.wifi.provisioner.ui.view.section.PasswordSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.ProvisioningSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.UnprovisioningSection -import no.nordicsemi.android.wifi.provisioner.ui.view.section.WifiSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.BluetoothDevice +import no.nordicsemi.android.wifi.provisioner.ble.sections.BluetoothDeviceNotSelected +import no.nordicsemi.android.wifi.provisioner.ble.sections.DisconnectedDeviceStatus +import no.nordicsemi.android.wifi.provisioner.ble.sections.PasswordSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisioningSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.UnprovisioningSection +import no.nordicsemi.android.wifi.provisioner.ble.sections.WifiSection import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnHidePasswordDialog import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.OnPasswordSelectedEvent import no.nordicsemi.kotlin.wifi.provisioner.feature.common.event.PasswordSetDialogEvent diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt similarity index 98% rename from feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt rename to feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt index 6024bacf..36cfe829 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/view/UiMapper.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/view/UiMapper.kt @@ -29,7 +29,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.wifi.provisioner.ui.view +package no.nordicsemi.android.wifi.provisioner.ble.view import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.SignalWifi4Bar diff --git a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt index 509beded..4334702a 100644 --- a/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt +++ b/feature/ui/src/main/java/no/nordicsemi/android/wifi/provisioner/ui/mapping/UiMapper.kt @@ -20,6 +20,16 @@ fun AuthModeDomain?.toImageVector() = when (this) { null -> Icons.Outlined.SignalWifi4BarLock } +fun AuthModeDomain.toDisplayString(): String = when(this){ + AuthModeDomain.OPEN -> "Open" + AuthModeDomain.WEP -> "WEP" + AuthModeDomain.WPA_PSK -> "WPA PSK" + AuthModeDomain.WPA2_PSK -> "WPA2 PSK" + AuthModeDomain.WPA_WPA2_PSK -> "WPA/WPA2 PSK" + AuthModeDomain.WPA2_ENTERPRISE -> "WPA2 Enterprise" + AuthModeDomain.WPA3_PSK -> "WPA3 PSK" +} + @Composable fun BandDomain.toDisplayString() = when (this) { BandDomain.BAND_ANY -> R.string.any From 11fbec9f62531f67dc5b1f02b60c58ae9ca8e4e8 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 27 May 2024 14:17:44 +0200 Subject: [PATCH 095/101] minor clean up --- .../wifi/provisioner/softap/viewmodel/SoftApViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt index 354eb665..9f184b92 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/viewmodel/SoftApViewModel.kt @@ -69,7 +69,7 @@ import javax.inject.Inject @HiltViewModel -class SoftApViewModel @Inject constructor( +internal class SoftApViewModel @Inject constructor( private val softApManager: SoftApManager, navigationManager: Navigator, savedStateHandle: SavedStateHandle, From 7819910a10ee8736b53160ff8520427cda923620 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 27 May 2024 14:25:59 +0200 Subject: [PATCH 096/101] Add seperate string for Open networks. --- .../wifi/provisioner/softap/view/SoftApScreen.kt | 11 +++++++++-- feature/softap/src/main/res/values/strings.xml | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index 7ce66143..8b17b192 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -63,6 +63,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.PasswordDialog import no.nordicsemi.android.wifi.provisioner.ui.SelectChannelDialog import no.nordicsemi.android.wifi.provisioner.ui.mapping.toDisplayString import no.nordicsemi.android.wifi.provisioner.ui.mapping.toImageVector +import no.nordicsemi.kotlin.wifi.provisioner.domain.AuthModeDomain import no.nordicsemi.kotlin.wifi.provisioner.domain.ScanRecordDomain import no.nordicsemi.kotlin.wifi.provisioner.feature.common.ScanRecordsForSsid import no.nordicsemi.kotlin.wifi.provisioner.feature.common.WifiData @@ -359,7 +360,10 @@ private fun SetPassphrase( if (password == null) { Text(text = stringResource(R.string.set_passphrase_rationale)) } else { - Text(text = stringResource(R.string.set_passphrase_value, password.toPassphrase())) + if (wifiData?.authMode == AuthModeDomain.OPEN) { + Text(text = stringResource(R.string.emptu_passwphrase_rationale)) + } else + Text(text = stringResource(R.string.set_passphrase_value, password.toPassphrase())) } if (showDialog) { PasswordDialog( @@ -402,7 +406,10 @@ private fun Provisioning( ) { ProgressItem( text = when { - isProvisioningRequested && provisioningState == WizardStepState.CURRENT -> stringResource(R.string.provisioning_device_to_your_network) + isProvisioningRequested && provisioningState == WizardStepState.CURRENT -> stringResource( + R.string.provisioning_device_to_your_network + ) + provisioningState == WizardStepState.COMPLETED -> stringResource(R.string.provisioning_completed) provisioningState == WizardStepState.INACTIVE -> stringResource(R.string.provisioning_rationale) else -> stringResource(R.string.provisioning_rationale) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 085d63b7..7ed8bea7 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -53,5 +53,6 @@ Locating provisioned device… Verification completed Please enable Wi-Fi! + Passphrase not required \ No newline at end of file From 7999ad4e86a1335187a7cf0972ce3fe3bb3538ec Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 28 May 2024 08:10:06 +0200 Subject: [PATCH 097/101] Fix padding for both tablet and phone UI. --- .../ble/sections/ProvisionOverBleSection.kt | 2 + .../softap/view/ProvisionOverWifiSection.kt | 2 + .../provisioner/softap/view/SoftApScreen.kt | 90 ++++++++++--------- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt index efa468df..690871c4 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt @@ -3,6 +3,7 @@ package no.nordicsemi.android.wifi.provisioner.ble.sections import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.MaterialTheme @@ -20,6 +21,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle fun ProvisionOverBleSection(onClick: () -> Unit) { OutlinedCard( modifier = Modifier + .fillMaxWidth() .padding(all = 8.dp) .clickable(onClick = onClick) ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt index 194a7aed..acd6d7ce 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt @@ -3,6 +3,7 @@ package no.nordicsemi.android.wifi.provisioner.softap.view import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.MaterialTheme @@ -20,6 +21,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle fun ProvisionOverWifiSection(onClick: () -> Unit) { OutlinedCard( modifier = Modifier + .fillMaxWidth() .padding(all = 8.dp) .clickable(onClick = onClick) ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index 8b17b192..fd9b8332 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -115,55 +115,55 @@ fun SoftApScreen( OutlinedCard( modifier = Modifier .verticalScroll(rememberScrollState()) - .padding(vertical = 16.dp, horizontal = 8.dp), + .padding(vertical = 16.dp, horizontal = 16.dp), ) { Column( modifier = Modifier .fillMaxWidth() .padding(16.dp), ) { - ConfigureSoftAp( - configureState = state.configureState, - connectionState = state.connectionState, - ssidName = ssidName, - onSsidChange = { ssidName = it } - ) - ConnectToSoftAp( - connectionState = state.connectionState, - serviceDiscoveryState = state.discoveringServicesState, - isConnectionRequested = state.isConnectionRequested, - ssidName = ssidName, - start = { - start(ssidName, Open) - } - ) - SelectWifi( - provisioningState = state.provisionState, - selectWifiState = state.selectWifiState, - wifiData = state.selectedWifi, - onSelectWifiPressed = onSelectWifiPressed, - onPasswordEntered = onPasswordEntered, - ) - SetPassphrase( - provisioningState = state.provisionState, - providePasswordState = state.providePasswordState, - wifiData = state.selectedWifi, - password = state.password, - onPasswordEntered = onPasswordEntered - ) - Provisioning( - passwordState = state.providePasswordState, - provisioningState = state.provisionState, - isProvisioningRequested = state.isProvisioningRequested, - onProvisionPressed = onProvisionPressed - ) - Verify( - provisioningState = state.provisionState, - verificationState = state.verifyState, - isVerificationRequested = state.isVerificationRequested, - verify = verify - ) } + ConfigureSoftAp( + configureState = state.configureState, + connectionState = state.connectionState, + ssidName = ssidName, + onSsidChange = { ssidName = it } + ) + ConnectToSoftAp( + connectionState = state.connectionState, + serviceDiscoveryState = state.discoveringServicesState, + isConnectionRequested = state.isConnectionRequested, + ssidName = ssidName, + start = { + start(ssidName, Open) + } + ) + SelectWifi( + provisioningState = state.provisionState, + selectWifiState = state.selectWifiState, + wifiData = state.selectedWifi, + onSelectWifiPressed = onSelectWifiPressed, + onPasswordEntered = onPasswordEntered, + ) + SetPassphrase( + provisioningState = state.provisionState, + providePasswordState = state.providePasswordState, + wifiData = state.selectedWifi, + password = state.password, + onPasswordEntered = onPasswordEntered + ) + Provisioning( + passwordState = state.providePasswordState, + provisioningState = state.provisionState, + isProvisioningRequested = state.isProvisioningRequested, + onProvisionPressed = onProvisionPressed + ) + Verify( + provisioningState = state.provisionState, + verificationState = state.verifyState, + isVerificationRequested = state.isVerificationRequested, + verify = verify + ) } } } @@ -200,6 +200,7 @@ private fun ConfigureSoftAp( ) { var showDialog by rememberSaveable { mutableStateOf(false) } WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Settings, title = stringResource(R.string.configure), state = configureState, @@ -241,6 +242,7 @@ private fun ConnectToSoftAp( start: () -> Unit, ) { WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Wifi, title = stringResource(id = R.string.connect), state = connectionState, @@ -295,6 +297,7 @@ private fun SelectWifi( onPasswordEntered: (String) -> Unit, ) { WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.WifiFind, title = stringResource(id = R.string.select_wifi), state = selectWifiState, @@ -337,6 +340,7 @@ private fun SetPassphrase( ) { var showDialog by rememberSaveable { mutableStateOf(false) } WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = wifiData?.authMode?.toImageVector() ?: Icons.Default.WifiPassword, title = stringResource(id = R.string.set_passphrase), state = providePasswordState, @@ -385,6 +389,7 @@ private fun Provisioning( onProvisionPressed: () -> Unit ) { WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Outlined.NetworkCheck, title = stringResource(id = R.string.provision), state = provisioningState, @@ -432,6 +437,7 @@ private fun Verify( verify: () -> Unit ) { WizardStepComponent( + modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Verified, title = stringResource(id = R.string.verify), state = verificationState, From fdd08cf8b9d03ddb36baddfe696eb6d53926c6e7 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 28 May 2024 08:23:39 +0200 Subject: [PATCH 098/101] Display app version --- .../android/wifi/provisioner/HomeScreen.kt | 22 ++++++++++++++----- app/src/main/res/values/strings.xml | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index 66893cec..d5dea183 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -47,9 +47,11 @@ import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -57,11 +59,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import kotlinx.coroutines.launch import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel import no.nordicsemi.android.common.theme.view.NordicAppBar +import no.nordicsemi.android.wifi.provisioner.app.BuildConfig import no.nordicsemi.android.wifi.provisioner.app.R import no.nordicsemi.android.wifi.provisioner.ble.sections.ProvisionOverBleSection import no.nordicsemi.android.wifi.provisioner.ble.view.BleDestination @@ -114,12 +118,6 @@ fun HomeScreen() { ) } } - /*item { - NordicText( - text = stringResource(id = R.string.app_info), - style = MaterialTheme.typography.bodyMedium - ) - }*/ item { ProvisionOverBleSection { vm.navigateTo(BleDestination) @@ -137,6 +135,18 @@ fun HomeScreen() { } } } + item { + Text( + text = stringResource( + id = R.string.app_version, + BuildConfig.VERSION_NAME, + BuildConfig.VERSION_CODE + ), + modifier = Modifier.fillMaxWidth().padding(end = 16.dp), + textAlign = TextAlign.End, + style = MaterialTheme.typography.labelMedium + ) + } } } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4f27ed94..76368232 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -119,4 +119,5 @@ Name RSSI This feature requires an Android device running Android 10 or above. + Version: %s (%s) \ No newline at end of file From dcb00b479c2de75bbb6cc8f05861c39906ae41b7 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Tue, 28 May 2024 10:32:48 +0200 Subject: [PATCH 099/101] UI Improvements --- .../android/wifi/provisioner/HomeScreen.kt | 50 ++++++++----- .../ble/sections/ProvisionOverBleSection.kt | 3 +- .../softap/view/ProvisionOverWifiSection.kt | 4 +- .../provisioner/softap/view/SoftApScreen.kt | 75 ++++++++++++------- .../softap/src/main/res/values/strings.xml | 4 + 5 files changed, 86 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt index d5dea183..953339a7 100644 --- a/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt +++ b/app/src/main/java/no/nordicsemi/android/wifi/provisioner/HomeScreen.kt @@ -34,6 +34,7 @@ package no.nordicsemi.android.wifi.provisioner import android.os.Build import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides @@ -55,6 +56,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -90,7 +92,7 @@ fun HomeScreen() { SnackbarHost(hostState = snackbarHostState) }, ) { innerPadding -> - LazyColumn( + Column( modifier = Modifier .fillMaxSize() .padding(innerPadding) @@ -100,30 +102,35 @@ fun HomeScreen() { WindowInsetsSides.Horizontal, ), ), - verticalArrangement = Arrangement.SpaceEvenly + horizontalAlignment = Alignment.CenterHorizontally ) { - item { - Row( + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.4f, true), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = painterResource(id = R.drawable.ic_nrf70), + contentDescription = stringResource(id = R.string.ic_nrf70), modifier = Modifier - .fillMaxWidth() - /*.weight(weight = 1f)*/, - horizontalArrangement = Arrangement.Center - ) { - Image( - painter = painterResource(id = R.drawable.ic_nrf70), - contentDescription = stringResource(id = R.string.ic_nrf70), - modifier = Modifier - .widthIn(max = 200.dp) - .padding(8.dp) - ) - } + .widthIn(max = 200.dp) + .padding(8.dp) + ) } - item { + Column( + modifier = Modifier + .fillMaxWidth() + .weight(0.4f, true), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { ProvisionOverBleSection { vm.navigateTo(BleDestination) } ProvisionOverWifiSection { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { vm.navigateTo(SoftApDestination) } else { scope.launch { @@ -135,14 +142,17 @@ fun HomeScreen() { } } } - item { + Row( + modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Center, + ) { Text( text = stringResource( id = R.string.app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE ), - modifier = Modifier.fillMaxWidth().padding(end = 16.dp), + modifier = Modifier.padding(bottom = 48.dp), textAlign = TextAlign.End, style = MaterialTheme.typography.labelMedium ) diff --git a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt index 690871c4..d60c62f8 100644 --- a/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt +++ b/feature/ble/src/main/java/no/nordicsemi/android/wifi/provisioner/ble/sections/ProvisionOverBleSection.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.widthIn import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text @@ -21,7 +22,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle fun ProvisionOverBleSection(onClick: () -> Unit) { OutlinedCard( modifier = Modifier - .fillMaxWidth() + .widthIn(max = 600.dp) .padding(all = 8.dp) .clickable(onClick = onClick) ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt index acd6d7ce..5812bafa 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/ProvisionOverWifiSection.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text @@ -21,7 +23,7 @@ import no.nordicsemi.android.wifi.provisioner.ui.view.section.SectionTitle fun ProvisionOverWifiSection(onClick: () -> Unit) { OutlinedCard( modifier = Modifier - .fillMaxWidth() + .widthIn(max = 600.dp) .padding(all = 8.dp) .clickable(onClick = onClick) ) { diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index fd9b8332..efe1c1dd 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -117,12 +118,7 @@ fun SoftApScreen( .verticalScroll(rememberScrollState()) .padding(vertical = 16.dp, horizontal = 16.dp), ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - ) { - } + Spacer(modifier = Modifier.padding(16.dp)) ConfigureSoftAp( configureState = state.configureState, connectionState = state.connectionState, @@ -179,10 +175,10 @@ private fun showSnackBar( scope.launch { val message = when (throwable) { is WifiNotEnabledException -> context.getString(R.string.please_enable_wi_fi) - is FailedToBindToNetwork -> "Failed to bind to network!" - is UnableToConnectToNetwork -> "Unable to connect to network!" - is OnConnectionLost -> "Connection lost!" - is TimeoutCancellationException -> "Verification timed out, please retry!" + is FailedToBindToNetwork -> context.getString(R.string.failed_to_bind_to_network) + is UnableToConnectToNetwork -> context.getString(R.string.unable_to_connect_to_network) + is OnConnectionLost -> context.getString(R.string.connection_lost) + is TimeoutCancellationException -> context.getString(R.string.verification_timed_out_please_retry) else -> "${throwable::class.simpleName}: ${throwable.message}" } val result = snackbarHostState.showSnackbar(message = message) @@ -204,8 +200,7 @@ private fun ConfigureSoftAp( icon = Icons.Default.Settings, title = stringResource(R.string.configure), state = configureState, - decor = if ((connectionState == WizardStepState.CURRENT || - connectionState == WizardStepState.COMPLETED) + decor = if (connectionState == WizardStepState.COMPLETED && configureState == WizardStepState.COMPLETED ) { null @@ -217,7 +212,7 @@ private fun ConfigureSoftAp( ) else null, showVerticalDivider = true ) { - Text(text = "SSID: $ssidName") + Text(style = MaterialTheme.typography.bodyMedium, text = "SSID: $ssidName") } if (showDialog) { EditSsidDialog( @@ -258,11 +253,12 @@ private fun ConnectToSoftAp( ) { ProgressItem( text = when { - isConnectionRequested && connectionState == WizardStepState.CURRENT -> stringResource( - id = R.string.connecting - ) + isConnectionRequested && connectionState == WizardStepState.CURRENT -> + stringResource(id = R.string.connecting) + + connectionState == WizardStepState.COMPLETED -> + stringResource(id = R.string.connected) - connectionState == WizardStepState.COMPLETED -> stringResource(id = R.string.connected) else -> stringResource(id = R.string.connect) }, status = when { @@ -315,17 +311,20 @@ private fun SelectWifi( showVerticalDivider = true ) { if (wifiData != null && selectWifiState != WizardStepState.INACTIVE) { - Text(text = "SSID: ${wifiData.ssid}") - Text( + Text(style = MaterialTheme.typography.bodyMedium, text = "SSID: ${wifiData.ssid}") + Text(style = MaterialTheme.typography.bodyMedium, text = "Band: ${ wifiData.let { it.selectedChannel?.wifiInfo?.band?.toDisplayString() ?: it.channelFallback.wifiInfo?.band?.toDisplayString() } - }") - Text(text = "Security: ${wifiData.authMode.toDisplayString()}") + }" + ) } else { - Text(text = stringResource(R.string.select_wifi_rationale)) + Text( + style = MaterialTheme.typography.bodyMedium, + text = stringResource(R.string.select_wifi_rationale) + ) } } } @@ -361,13 +360,33 @@ private fun SetPassphrase( ), showVerticalDivider = true ) { - if (password == null) { - Text(text = stringResource(R.string.set_passphrase_rationale)) - } else { - if (wifiData?.authMode == AuthModeDomain.OPEN) { - Text(text = stringResource(R.string.emptu_passwphrase_rationale)) + + if (wifiData != null) { + Text( + style = MaterialTheme.typography.bodyMedium, + text = "Security: ${wifiData.authMode.toDisplayString()}" + ) + + if (wifiData.authMode == AuthModeDomain.OPEN) { + Text( + style = MaterialTheme.typography.bodyMedium, + text = stringResource(R.string.emptu_passwphrase_rationale) + ) } else - Text(text = stringResource(R.string.set_passphrase_value, password.toPassphrase())) + if (password != null) { + Text( + style = MaterialTheme.typography.bodyMedium, + text = stringResource( + R.string.set_passphrase_value, + password.toPassphrase() + ) + ) + } + } else { + Text( + style = MaterialTheme.typography.bodyMedium, + text = stringResource(R.string.set_passphrase_rationale) + ) } if (showDialog) { PasswordDialog( diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index 7ed8bea7..c80fac60 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -54,5 +54,9 @@ Verification completed Please enable Wi-Fi! Passphrase not required + Failed to bind to network! + Unable to connect to network! + Connection lost! + Verification timed out, please retry! \ No newline at end of file From 2b3a7ff8aee5e5a06449c120e1ad430ea39f3f73 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 3 Jun 2024 14:14:16 +0200 Subject: [PATCH 100/101] Minor improvements --- app/src/main/res/values/strings.xml | 1 - .../provisioner/softap/view/SoftApScreen.kt | 102 +++++++++--------- .../softap/src/main/res/values/strings.xml | 6 +- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 76368232..48f49967 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -111,7 +111,6 @@ Connection failed V %d - Select Wi-Fi Persistent storage diff --git a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt index efe1c1dd..c213f278 100644 --- a/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt +++ b/feature/softap/src/main/java/no/nordicsemi/android/wifi/provisioner/softap/view/SoftApScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -118,48 +117,49 @@ fun SoftApScreen( .verticalScroll(rememberScrollState()) .padding(vertical = 16.dp, horizontal = 16.dp), ) { - Spacer(modifier = Modifier.padding(16.dp)) - ConfigureSoftAp( - configureState = state.configureState, - connectionState = state.connectionState, - ssidName = ssidName, - onSsidChange = { ssidName = it } - ) - ConnectToSoftAp( - connectionState = state.connectionState, - serviceDiscoveryState = state.discoveringServicesState, - isConnectionRequested = state.isConnectionRequested, - ssidName = ssidName, - start = { - start(ssidName, Open) - } - ) - SelectWifi( - provisioningState = state.provisionState, - selectWifiState = state.selectWifiState, - wifiData = state.selectedWifi, - onSelectWifiPressed = onSelectWifiPressed, - onPasswordEntered = onPasswordEntered, - ) - SetPassphrase( - provisioningState = state.provisionState, - providePasswordState = state.providePasswordState, - wifiData = state.selectedWifi, - password = state.password, - onPasswordEntered = onPasswordEntered - ) - Provisioning( - passwordState = state.providePasswordState, - provisioningState = state.provisionState, - isProvisioningRequested = state.isProvisioningRequested, - onProvisionPressed = onProvisionPressed - ) - Verify( - provisioningState = state.provisionState, - verificationState = state.verifyState, - isVerificationRequested = state.isVerificationRequested, - verify = verify - ) + Column(modifier = Modifier.padding(16.dp)) { + ConfigureSoftAp( + configureState = state.configureState, + connectionState = state.connectionState, + ssidName = ssidName, + onSsidChange = { ssidName = it } + ) + ConnectToSoftAp( + connectionState = state.connectionState, + serviceDiscoveryState = state.discoveringServicesState, + isConnectionRequested = state.isConnectionRequested, + ssidName = ssidName, + start = { + start(ssidName, Open) + } + ) + SelectWifi( + provisioningState = state.provisionState, + selectWifiState = state.selectWifiState, + wifiData = state.selectedWifi, + onSelectWifiPressed = onSelectWifiPressed, + onPasswordEntered = onPasswordEntered, + ) + SetPassphrase( + provisioningState = state.provisionState, + providePasswordState = state.providePasswordState, + wifiData = state.selectedWifi, + password = state.password, + onPasswordEntered = onPasswordEntered + ) + Provisioning( + passwordState = state.providePasswordState, + provisioningState = state.provisionState, + isProvisioningRequested = state.isProvisioningRequested, + onProvisionPressed = onProvisionPressed + ) + Verify( + provisioningState = state.provisionState, + verificationState = state.verifyState, + isVerificationRequested = state.isVerificationRequested, + verify = verify + ) + } } } } @@ -196,7 +196,6 @@ private fun ConfigureSoftAp( ) { var showDialog by rememberSaveable { mutableStateOf(false) } WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Settings, title = stringResource(R.string.configure), state = configureState, @@ -237,7 +236,6 @@ private fun ConnectToSoftAp( start: () -> Unit, ) { WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Wifi, title = stringResource(id = R.string.connect), state = connectionState, @@ -293,9 +291,8 @@ private fun SelectWifi( onPasswordEntered: (String) -> Unit, ) { WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.WifiFind, - title = stringResource(id = R.string.select_wifi), + title = stringResource(id = R.string.wifi_network), state = selectWifiState, decor = if (selectWifiState == WizardStepState.INACTIVE) null else if ((provisioningState == WizardStepState.CURRENT @@ -323,7 +320,7 @@ private fun SelectWifi( } else { Text( style = MaterialTheme.typography.bodyMedium, - text = stringResource(R.string.select_wifi_rationale) + text = stringResource(R.string.select_wifi) ) } } @@ -339,9 +336,8 @@ private fun SetPassphrase( ) { var showDialog by rememberSaveable { mutableStateOf(false) } WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = wifiData?.authMode?.toImageVector() ?: Icons.Default.WifiPassword, - title = stringResource(id = R.string.set_passphrase), + title = stringResource(id = R.string.security), state = providePasswordState, decor = if (providePasswordState == WizardStepState.INACTIVE) { null @@ -370,7 +366,7 @@ private fun SetPassphrase( if (wifiData.authMode == AuthModeDomain.OPEN) { Text( style = MaterialTheme.typography.bodyMedium, - text = stringResource(R.string.emptu_passwphrase_rationale) + text = stringResource(R.string.empty_passphrase_rationale) ) } else if (password != null) { @@ -385,7 +381,7 @@ private fun SetPassphrase( } else { Text( style = MaterialTheme.typography.bodyMedium, - text = stringResource(R.string.set_passphrase_rationale) + text = stringResource(R.string.se_wifi_passphrase) ) } if (showDialog) { @@ -408,7 +404,6 @@ private fun Provisioning( onProvisionPressed: () -> Unit ) { WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Outlined.NetworkCheck, title = stringResource(id = R.string.provision), state = provisioningState, @@ -456,7 +451,6 @@ private fun Verify( verify: () -> Unit ) { WizardStepComponent( - modifier = Modifier.padding(horizontal = 16.dp), icon = Icons.Default.Verified, title = stringResource(id = R.string.verify), state = verificationState, diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index c80fac60..f2649a45 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -33,11 +33,13 @@ Connecting… Connected Change + Wi-Fi Network Select Wi-Fi Start Edit SSID Select - Set Passphrase + Security + Set Wi-Fi passphrase Set Configure Select a Wi-Fi Network to provision the nRF 700x device to @@ -53,7 +55,7 @@ Locating provisioned device… Verification completed Please enable Wi-Fi! - Passphrase not required + Passphrase not required Failed to bind to network! Unable to connect to network! Connection lost! From 62e270e77264c1cac1cb60588d64683ba8515ff7 Mon Sep 17 00:00:00 2001 From: roshanrajaratnam Date: Mon, 3 Jun 2024 14:19:13 +0200 Subject: [PATCH 101/101] Removes unused resources. --- feature/softap/src/main/res/values/strings.xml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/feature/softap/src/main/res/values/strings.xml b/feature/softap/src/main/res/values/strings.xml index f2649a45..e914b1a7 100644 --- a/feature/softap/src/main/res/values/strings.xml +++ b/feature/softap/src/main/res/values/strings.xml @@ -12,8 +12,6 @@ Wi-Fi Access Points Scanning error - IPv4: %s - SSID: %s BSSID: %s Band: %s Band: %s, Channel: %s @@ -22,17 +20,13 @@ 5 GHz Any - Icon indicating wifi and it\'s authentication method. + Icon indicating wifi and it\'s authentication method.= - Device status - Provisioning data - Upload status Provision Verify Connect Connecting… Connected - Change Wi-Fi Network Select Wi-Fi Start @@ -42,8 +36,6 @@ Set Wi-Fi passphrase Set Configure - Select a Wi-Fi Network to provision the nRF 700x device to - Set the passphrase for the selected Wi-Fi Network Passphrase: %s Sending Wi-Fi credentials… Wi-Fi credentials sent