From af5a67502da115a1cc5711d24a1c00345da91fad Mon Sep 17 00:00:00 2001 From: sakumar3 Date: Fri, 26 Jul 2024 12:39:46 +0530 Subject: [PATCH] Release-v2.9.1 package --- .gitignore | 1 + README.md | 1 + build.gradle.kts | 2 +- gradle.properties | 7 +- gradle/wrapper/gradle-wrapper.properties | 4 +- mobile/build.gradle.kts | 75 +- mobile/src/main/AndroidManifest.xml | 29 +- .../bledemo/Base/activities/BaseActivity.kt | 2 +- .../Base/viewmodels/ScannerViewModel.kt | 6 +- .../Bluetooth/Services/BluetoothService.kt | 10 +- .../advertiser/services/AdvertiserService.kt | 12 +- .../demo/devkitsensor917/APIClient.kt | 15 + .../activities/DevKitSensor917Activity.kt | 104 ++ .../devkitsensor917/interface/APIInterface.kt | 70 ++ .../model/AccelerometerGyroScopeResponse.kt | 7 + .../model/AmbientLightResponse.kt | 6 + .../devkitsensor917/model/HumidityResponse.kt | 5 + .../demo/devkitsensor917/model/LEDResponse.kt | 7 + .../model/LEDStatusResponse.kt | 5 + .../model/MicrophoneResponse.kt | 5 + .../model/ProvisionResponse.kt | 5 + .../devkitsensor917/model/ScanResponse.kt | 3 + .../devkitsensor917/model/StatusResponse.kt | 6 + .../devkitsensor917/model/TempResponse.kt | 5 + .../demo/devkitsensor917/model/UserData.kt | 9 + .../utils/DevKitSensorChecker.kt | 28 + .../utils/DevKitSensorControl.kt | 908 ++++++++++++++++++ .../utils/DevKitSesnorControl.kt | 4 + .../adapters/MatterScannedResultAdapter.kt | 9 +- .../fragments/MatterScannerFragment.kt | 4 +- .../MatterTemperatureSensorFragment.kt | 1 + .../MatterWifiInputDialogFragment.kt | 3 +- .../utils/MatterDialogDeviceInfoFragment.kt | 93 ++ .../activities/RangeTestActivity.kt | 28 +- .../demo/range_test/models/RangeTestValues.kt | 31 +- .../demo/throughput/views/SpeedView.kt | 4 +- .../base/models/ThunderBoardDevice.kt | 10 +- .../activities/BlinkyThunderboardActivity.kt | 157 ++- .../demos/motion/activities/MotionActivity.kt | 8 +- .../demos/motion/adapters/GdxAdapter.kt | 4 +- .../activities/WifiCommissioningActivity.kt | 145 ++- .../iop_test/activities/IOPTestActivity.kt | 214 +++-- .../iop_test/models/DemoItemProvider.kt | 1 + .../iop_test/models/SiliconLabsTestInfo.kt | 18 +- .../activities/DeviceServicesActivity.kt | 2 + .../scan/browser/services/ShareLogServices.kt | 3 +- .../home_screen/dialogs/SelectDeviceDialog.kt | 12 +- .../home_screen/fragments/DemoFragment.kt | 202 ++-- .../home_screen/fragments/ScanFragment.kt | 2 +- .../menu_items/DevKitSensorDemo.kt | 8 + .../viewmodels/ScanFragmentViewModel.kt | 5 +- .../viewmodels/SelectDeviceViewModel.kt | 59 +- .../home_screen/views/BluetoothEnableBar.kt | 17 +- .../main/res/drawable/btn_rounded_black.xml | 20 + .../main/res/drawable/btn_rounded_blue.xml | 20 + .../res/drawable/btn_rounded_blue_dev.xml | 20 + .../res/drawable/btn_rounded_dark_blue.xml | 20 + .../main/res/drawable/btn_rounded_green.xml | 20 + .../src/main/res/drawable/btn_rounded_red.xml | 20 + .../drawable/button_background_blue_box.xml | 6 + .../drawable/button_background_green_box.xml | 6 + .../drawable/button_background_grey_box.xml | 6 + .../drawable/button_background_red_box.xml | 6 + .../button_background_soft_black_box.xml | 6 + .../main/res/drawable/icon_dks_917_led.xml | 19 + .../main/res/drawable/icon_dks_917_motion.xml | 19 + .../main/res/drawable/motion_rounded_bg.xml | 4 +- .../res/drawable/redesign_ic_demo_dks_917.xml | 20 + .../activity_917_dev_kit_sensor_layout.xml | 58 ++ .../main/res/layout/activity_matter_demo.xml | 1 - .../dev_kit_sensor_917_dialog_layout.xml | 81 ++ ...t_sesnor_917_led_control_dialog_layout.xml | 154 +++ ...esnor_917_motion_control_dialog_layout.xml | 217 +++++ .../main/res/layout/dialog_share_iop_log.xml | 86 ++ ...ragment_dev_kit_sensor_917_home_layout.xml | 21 + .../src/main/res/layout/fragment_settings.xml | 5 + .../main/res/layout/sensor_demo_grid_item.xml | 48 + mobile/src/main/res/values-sw600dp/dimens.xml | 1 + mobile/src/main/res/values/colors.xml | 14 + mobile/src/main/res/values/dimens.xml | 7 +- mobile/src/main/res/values/strings.xml | 36 +- mobile/src/main/res/values/styles.xml | 58 +- .../src/main/si_launcher_playstore-icon.png | Bin 0 -> 159437 bytes 83 files changed, 2971 insertions(+), 409 deletions(-) create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/APIClient.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/activities/DevKitSensor917Activity.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/interface/APIInterface.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AccelerometerGyroScopeResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AmbientLightResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/HumidityResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDStatusResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/MicrophoneResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ProvisionResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ScanResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/StatusResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/TempResponse.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/UserData.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorChecker.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorControl.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSesnorControl.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/MatterDialogDeviceInfoFragment.kt create mode 100644 mobile/src/main/java/com/siliconlabs/bledemo/home_screen/menu_items/DevKitSensorDemo.kt create mode 100644 mobile/src/main/res/drawable/btn_rounded_black.xml create mode 100644 mobile/src/main/res/drawable/btn_rounded_blue.xml create mode 100644 mobile/src/main/res/drawable/btn_rounded_blue_dev.xml create mode 100644 mobile/src/main/res/drawable/btn_rounded_dark_blue.xml create mode 100644 mobile/src/main/res/drawable/btn_rounded_green.xml create mode 100644 mobile/src/main/res/drawable/btn_rounded_red.xml create mode 100644 mobile/src/main/res/drawable/button_background_blue_box.xml create mode 100644 mobile/src/main/res/drawable/button_background_green_box.xml create mode 100644 mobile/src/main/res/drawable/button_background_grey_box.xml create mode 100644 mobile/src/main/res/drawable/button_background_red_box.xml create mode 100644 mobile/src/main/res/drawable/button_background_soft_black_box.xml create mode 100644 mobile/src/main/res/drawable/icon_dks_917_led.xml create mode 100644 mobile/src/main/res/drawable/icon_dks_917_motion.xml create mode 100644 mobile/src/main/res/drawable/redesign_ic_demo_dks_917.xml create mode 100644 mobile/src/main/res/layout/activity_917_dev_kit_sensor_layout.xml create mode 100644 mobile/src/main/res/layout/dev_kit_sensor_917_dialog_layout.xml create mode 100644 mobile/src/main/res/layout/dev_kit_sesnor_917_led_control_dialog_layout.xml create mode 100644 mobile/src/main/res/layout/dev_kit_sesnor_917_motion_control_dialog_layout.xml create mode 100644 mobile/src/main/res/layout/dialog_share_iop_log.xml create mode 100644 mobile/src/main/res/layout/fragment_dev_kit_sensor_917_home_layout.xml create mode 100644 mobile/src/main/res/layout/sensor_demo_grid_item.xml create mode 100644 mobile/src/main/si_launcher_playstore-icon.png diff --git a/.gitignore b/.gitignore index 8d6f5252..6c4c3f0c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ Builds .idea/ *.iml /local.properties +*.apk *.DS_Store diff --git a/README.md b/README.md index d1a562f9..d6f64ad5 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Simplicity Connect includes many demos to test sample apps in the Silicon Labs G - **Bluetooth Electronic Shelf Labels (ESL)**: Adds and commissions ESL tags to the system network by scanning the tag's QR code with the mobile device's camera and provides the user a UI to view the list commissioned tags and control them. - **Matter**: Commission and control of the Matter devices over Thread and Wi-Fi. - **Wi-Fi OTA Firmware Update**: The Wi-Fi OTA firmware update demo demonstrates how to update the SiWx91x user application firmware over Wi-Fi connection, by downloading the image from the mobile phone. +- **Wi-Fi 917 Sensors**: The Wi-Fi 917 Sensor demo demonstrates to read and display sensor data from 917 Dev Kit. ## Development Features Simplicity Connect helps developers create and troubleshoot Bluetooth applications running on Silicon Labs’ BLE hardware. Here’s a rundown of some example functionalities. diff --git a/build.gradle.kts b/build.gradle.kts index 407be4a7..f65e0f89 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "7.4.2" apply false + id("com.android.application") version "8.4.1" apply false id("org.jetbrains.kotlin.android") version "1.7.21" apply false id("org.jetbrains.kotlin.android.extensions") version "1.7.21" apply false id("org.jetbrains.kotlin.kapt") version "1.7.21" apply false diff --git a/gradle.properties b/gradle.properties index c02c9517..9a84b0ad 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,6 +15,9 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true +org.gradle.parallel=true android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 079fca27..d96216a6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Oct 20 13:32:19 CEST 2020 +#Thu Oct 26 16:56:57 EEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip diff --git a/mobile/build.gradle.kts b/mobile/build.gradle.kts index f738a9f0..83e8abe7 100644 --- a/mobile/build.gradle.kts +++ b/mobile/build.gradle.kts @@ -1,3 +1,5 @@ +import com.android.build.api.variant.Packaging + plugins { id("com.android.application") id("org.jetbrains.kotlin.android") @@ -13,12 +15,12 @@ repositories { } android { - compileSdk = 33 + compileSdk = 34 namespace = "com.siliconlabs.bledemo" defaultConfig { minSdk = 29 - targetSdk = 33 + targetSdk = 34 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -58,8 +60,8 @@ android { create("blueGecko") { dimension = versionDim applicationId = "com.siliconlabs.bledemo" - versionCode = 49 - versionName = "2.9.0" + versionCode = 53 + versionName = "2.9.1" } } @@ -74,27 +76,40 @@ android { buildFeatures { viewBinding = true + buildConfig = true } } dependencies { implementation(fileTree(mapOf("include" to listOf("*.jar", "*.so"), "dir" to "libs"))) + // This dependency is downloaded from the Google’s Maven repository. + // Make sure you also include that repository in your project's build.gradle file. + implementation("com.google.android.play:feature-delivery:2.1.0") + implementation("com.google.android.play:review:2.0.1") + implementation("com.google.android.play:app-update:2.1.0") + + + // For Kotlin users, also import the Kotlin extensions library for Play Feature Delivery: + implementation("com.google.android.play:feature-delivery-ktx:2.1.0") + implementation("com.google.android.play:review-ktx:2.0.1") + implementation("com.google.android.play:app-update-ktx:2.1.0") // androidx - implementation("androidx.core:core-ktx:1.10.0") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("androidx.fragment:fragment:1.5.6") - implementation("androidx.core:core-splashscreen:1.0.0") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1") - implementation("androidx.activity:activity-ktx:1.6.0") - implementation("com.google.android.material:material:1.9.0") + implementation("androidx.core:core-ktx:1.13.1") + implementation("androidx.appcompat:appcompat:1.7.0") + implementation("androidx.fragment:fragment:1.8.1") + implementation("androidx.core:core-splashscreen:1.0.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.2") + implementation("androidx.activity:activity-ktx:1.9.0") + implementation("com.google.android.material:material:1.12.0") // Coroutines - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // UI components implementation("androidx.cardview:cardview:1.0.0") - implementation("androidx.recyclerview:recyclerview:1.3.0") + implementation("androidx.recyclerview:recyclerview:1.3.2") implementation("androidx.gridlayout:gridlayout:1.0.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") @@ -106,12 +121,12 @@ dependencies { //implementation("com.github.PhilJay:MPAndroidChart:v3.0.3") // Navigation - implementation("androidx.navigation:navigation-fragment-ktx:2.5.3") - implementation("androidx.navigation:navigation-ui-ktx:2.5.3") - implementation("androidx.navigation:navigation-dynamic-features-fragment:2.5.3") + implementation("androidx.navigation:navigation-fragment-ktx:2.7.7") + implementation("androidx.navigation:navigation-ui-ktx:2.7.7") + implementation("androidx.navigation:navigation-dynamic-features-fragment:2.7.7") // Dependency injection - implementation("com.google.dagger:hilt-android:2.45") + implementation("com.google.dagger:hilt-android:2.46.1") kapt("com.google.dagger:hilt-android-compiler:2.45") // View binding @@ -123,7 +138,7 @@ dependencies { // Parsing implementation("com.google.code.gson:gson:2.10.1") implementation("com.opencsv:opencsv:5.6") - implementation("androidx.activity:activity:1.6.0-alpha05") + implementation("androidx.activity:activity:1.9.0") // Only used for Int.pow() method in a couple of places implementation("com.google.guava:guava:29.0-android") @@ -135,16 +150,22 @@ dependencies { // instrumented tests testImplementation("junit:junit:4.13.2") - androidTestUtil("androidx.test:orchestrator:1.4.2") - androidTestImplementation("androidx.test:runner:1.5.2") - androidTestImplementation("androidx.test:rules:1.5.0") - androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestUtil("androidx.test:orchestrator:1.5.0") + androidTestImplementation("androidx.test:runner:1.6.1") + androidTestImplementation("androidx.test:rules:1.6.1") + androidTestImplementation("androidx.test.ext:junit:1.2.1") //Matter - implementation("androidx.camera:camera-core:1.1.0") - implementation("androidx.camera:camera-camera2:1.1.0") - implementation("androidx.camera:camera-lifecycle:1.1.0") - implementation("androidx.camera:camera-view:1.1.0") - implementation("com.google.mlkit:barcode-scanning:17.0.2") + implementation("androidx.camera:camera-core:1.3.4") + implementation("androidx.camera:camera-camera2:1.3.4") + implementation("androidx.camera:camera-lifecycle:1.3.4") + implementation("androidx.camera:camera-view:1.3.4") + implementation("com.google.mlkit:barcode-scanning:17.2.0") implementation("com.daimajia.swipelayout:library:1.2.0@aar") + + //DevKitSensor917 Demo + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0") + } diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index bae93deb..1a5ef942 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -18,10 +18,12 @@ - - - - + + + + + + @@ -33,13 +35,14 @@ + android:theme="@style/MainAppTheme" + android:usesCleartextTraffic="true" + tools:replace="android:allowBackup"> + android:screenOrientation="portrait" + android:theme="@style/matter_theme" /> + = _isScanningOn - abstract fun handleScanResult(result: ScanResultCompat) + abstract fun handleScanResult(result: ScanResultCompat, + connectType: BluetoothService.GattConnectType?, + context: Context?) fun toggleScanningState() { diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Services/BluetoothService.kt b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Services/BluetoothService.kt index 3facdbc0..8537a0ae 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Services/BluetoothService.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/Bluetooth/Services/BluetoothService.kt @@ -80,7 +80,8 @@ class BluetoothService : LocalService() { IOP_TEST, ESL_DEMO, MATTER_DEMO, - WIFI_OTA_UPDATE + WIFI_OTA_UPDATE, + DEV_KIT_SENSOR } interface ScanListener { @@ -280,7 +281,12 @@ class BluetoothService : LocalService() { addAction(ACTION_GATT_SERVER_DEBUG_CONNECTION) addAction(ACTION_GATT_SERVER_REMOVE_NOTIFICATION) } - registerReceiver(gattServerBroadcastReceiver, filter) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(gattServerBroadcastReceiver, filter, RECEIVER_EXPORTED) + }else { + registerReceiver(gattServerBroadcastReceiver, filter) + } } diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/services/AdvertiserService.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/services/AdvertiserService.kt index 7f80ce33..6d6a01d9 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/services/AdvertiserService.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/configure/advertiser/services/AdvertiserService.kt @@ -6,6 +6,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE import android.os.Build import android.os.IBinder import androidx.core.content.ContextCompat @@ -39,11 +40,16 @@ class AdvertiserService : Service() { val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) registerReceiver(receiver, filter) + } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val notification = prepareNotification() - startForeground(1, notification) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + startForeground(1, notification, FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE) + } else { + startForeground(1, notification) + } return START_STICKY } @@ -67,9 +73,9 @@ class AdvertiserService : Service() { this, ADVERTISER_NOTIFICATION_REQUEST_CODE, notificationIntent, PendingIntent.FLAG_IMMUTABLE) return Notification.Builder(this, CHANNEL_ID).apply { - setContentTitle("EFR Connect") + setContentTitle("Si Connect") setContentText("Advertiser is running...") - setSmallIcon(R.mipmap.efr_redesign_launcher) + setSmallIcon(R.mipmap.si_launcher) setContentIntent(pendingIntent) setShowWhen(false) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/APIClient.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/APIClient.kt new file mode 100644 index 00000000..914da777 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/APIClient.kt @@ -0,0 +1,15 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917 + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + + +object APIClient { + val baseURL = "http://192.168.10.10" + + fun getInstance(): Retrofit { + return Retrofit.Builder().baseUrl(baseURL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/activities/DevKitSensor917Activity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/activities/DevKitSensor917Activity.kt new file mode 100644 index 00000000..ae628d0e --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/activities/DevKitSensor917Activity.kt @@ -0,0 +1,104 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.activities + +import android.os.Bundle +import android.view.MenuItem +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.siliconlabs.bledemo.R +import com.siliconlabs.bledemo.databinding.Activity917DevKitSensorLayoutBinding +import com.siliconlabs.bledemo.features.demo.devkitsensor917.utils.DevKitSensorChecker +import com.siliconlabs.bledemo.features.demo.devkitsensor917.utils.DevKitSensorControl + +class DevKitSensor917Activity : AppCompatActivity() { + + private lateinit var binding: Activity917DevKitSensorLayoutBinding + private var currentFragment: Fragment? = null + private val devKitSensorChecker = DevKitSensorChecker() + private val controls = + mutableMapOf() + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = Activity917DevKitSensorLayoutBinding.inflate(layoutInflater) + setSupportActionBar(binding.toolbar) + setContentView(binding.root) + val actionBar = supportActionBar + actionBar!!.setHomeAsUpIndicator(R.drawable.matter_back) + actionBar.setDisplayHomeAsUpEnabled(true) + initGrid() + } +// +// override fun onBackPressed() { +// if (getFragmentManager().getBackStackEntryCount() > 0) +// getFragmentManager().popBackStack(); +// else +// super.onBackPressed(); +// } + + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + this.finish() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + private fun initGrid() { + binding.envGrid.apply { + devKitSensorChecker.devKitSensors.filter { + it.value == DevKitSensorChecker.DevkitSensorState.WORKING + }.forEach { + controls[it.key] = DevKitSensorControl( + this.context, + getString(getTileDescription(it.key)), + ContextCompat.getDrawable(this.context, getTileIcon(it.key)) + ).also { + + addView(it) + it.setListener(it.tag) + + } + } + } + } + + + @StringRes + private fun getTileDescription(sensor: DevKitSensorChecker.DevkitSensor917BoardSensor): Int { + return when (sensor) { + DevKitSensorChecker.DevkitSensor917BoardSensor.Temperature -> R.string.environment_temp + DevKitSensorChecker.DevkitSensor917BoardSensor.Humidity -> R.string.environment_humidity + DevKitSensorChecker.DevkitSensor917BoardSensor.AmbientLight -> R.string.environment_ambient + DevKitSensorChecker.DevkitSensor917BoardSensor.Motion -> R.string.dev_kit_sensor_917_motion + DevKitSensorChecker.DevkitSensor917BoardSensor.LED -> R.string.dev_kit_sensor_917_led +// DevKitSensorChecker.DevkitSensor917BoardSensor.Microphone -> R.string.dev_kit_sensor_917_microphone + + else -> 0 + } + } + + @DrawableRes + private fun getTileIcon(sensor: DevKitSensorChecker.DevkitSensor917BoardSensor): Int { + return when (sensor) { + DevKitSensorChecker.DevkitSensor917BoardSensor.Temperature -> R.drawable.icon_temp + DevKitSensorChecker.DevkitSensor917BoardSensor.Humidity -> R.drawable.icon_environment + DevKitSensorChecker.DevkitSensor917BoardSensor.AmbientLight -> R.drawable.icon_light + DevKitSensorChecker.DevkitSensor917BoardSensor.Motion -> R.drawable.icon_dks_917_motion + DevKitSensorChecker.DevkitSensor917BoardSensor.LED -> R.drawable.icon_dks_917_led +// DevKitSensorChecker.DevkitSensor917BoardSensor.Microphone -> R.drawable.icon_sound + + else -> 0 + } + } + + +} + diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/interface/APIInterface.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/interface/APIInterface.kt new file mode 100644 index 00000000..d4982169 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/interface/APIInterface.kt @@ -0,0 +1,70 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917 + + +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.AccelerometerGyroScopeResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.AmbientLightResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.HumidityResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.LEDResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.LEDStatusResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.MicrophoneResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.ProvisionResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.ScanResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.StatusResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.TempResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.Call + +interface APIInterface { + @GET("/led") + suspend fun getLedStatus(): Response + + @GET("/temperature") + suspend fun getTempStatus(): Response + + @GET("/light") + suspend fun getAmbitStatus(): Response + + @GET("/humidity") + suspend fun getHumidityStatus(): Response + + @GET("/accelerometer") + suspend fun getAccelerometerStatus(): Response + + @GET("/gyroscope") + suspend fun getGyroscopeStatus(): Response + + @GET("/microphone") + suspend fun getMicrophoneStatus(): Response + + @GET("/provisioning") + suspend fun getProvisioningStatus():Response + + @GET("/scan") + suspend fun getScanStatus(): Response + + @GET("/Status") + suspend fun getStatus():Response + + @POST("/led") + fun setAllLEdsOnOff(@Body body: Map): Call + + @POST("/led") + fun setRedLEDOn(@Body body: Map): Call + + @POST("/led") + fun setGreenLEDOn(@Body body: Map): Call + + @POST("/led") + fun setBlueLEDOn(@Body body: Map): Call + + @GET("/status_led") + suspend fun getLedSwitchStatus(): Response + + @POST("/status_led") + fun setLEDStatusOff(@Body body: Map): Call + + +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AccelerometerGyroScopeResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AccelerometerGyroScopeResponse.kt new file mode 100644 index 00000000..9f437257 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AccelerometerGyroScopeResponse.kt @@ -0,0 +1,7 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class AccelerometerGyroScopeResponse( + val x: String, + val y: String, + val z: String +) \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AmbientLightResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AmbientLightResponse.kt new file mode 100644 index 00000000..6cac65cd --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/AmbientLightResponse.kt @@ -0,0 +1,6 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class AmbientLightResponse( + val ambient_light_lux:String, + val white_light_lux:String +) \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/HumidityResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/HumidityResponse.kt new file mode 100644 index 00000000..4341115e --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/HumidityResponse.kt @@ -0,0 +1,5 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class HumidityResponse( + val humidity_percentage: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDResponse.kt new file mode 100644 index 00000000..ba8c1d42 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDResponse.kt @@ -0,0 +1,7 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class LEDResponse( + var red: String, + var green: String, + var blue: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDStatusResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDStatusResponse.kt new file mode 100644 index 00000000..f1681536 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/LEDStatusResponse.kt @@ -0,0 +1,5 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class LEDStatusResponse( + var status_led: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/MicrophoneResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/MicrophoneResponse.kt new file mode 100644 index 00000000..bb292a76 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/MicrophoneResponse.kt @@ -0,0 +1,5 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class MicrophoneResponse( + val microphone_decibel: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ProvisionResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ProvisionResponse.kt new file mode 100644 index 00000000..240eb1ab --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ProvisionResponse.kt @@ -0,0 +1,5 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class ProvisionResponse( + val status: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ScanResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ScanResponse.kt new file mode 100644 index 00000000..694cc762 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/ScanResponse.kt @@ -0,0 +1,3 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class ScanResponse(val count: String) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/StatusResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/StatusResponse.kt new file mode 100644 index 00000000..2eb151bb --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/StatusResponse.kt @@ -0,0 +1,6 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class StatusResponse( + val status: String, + val provisioned: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/TempResponse.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/TempResponse.kt new file mode 100644 index 00000000..dbe3e675 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/TempResponse.kt @@ -0,0 +1,5 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +data class TempResponse( + val temperature_celcius: String +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/UserData.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/UserData.kt new file mode 100644 index 00000000..aaee88e5 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/model/UserData.kt @@ -0,0 +1,9 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.model + +import com.google.gson.annotations.SerializedName + +data class UserData( + @SerializedName("red") val red: String?, + @SerializedName("green") val green: String?, + @SerializedName("blue") val blue: String? +) diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorChecker.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorChecker.kt new file mode 100644 index 00000000..70993980 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorChecker.kt @@ -0,0 +1,28 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.utils + +class DevKitSensorChecker { + val devKitSensors = mutableMapOf( + DevkitSensor917BoardSensor.Temperature to DevkitSensorState.WORKING, + DevkitSensor917BoardSensor.Humidity to DevkitSensorState.WORKING, + DevkitSensor917BoardSensor.AmbientLight to DevkitSensorState.WORKING, + DevkitSensor917BoardSensor.Motion to DevkitSensorState.WORKING, + DevkitSensor917BoardSensor.LED to DevkitSensorState.WORKING, +// DevkitSensor917BoardSensor.Microphone to DevkitSensorState.WORKING, + + ) + + enum class DevkitSensor917BoardSensor(val broken: Long?) { + Temperature(0x7fff), + Humidity(0xffff), + AmbientLight(0xffffffff), + Motion(0xffff), + LED(0xffffff), +// Microphone(0xffff) + } + + enum class DevkitSensorState { + WORKING, + MISSING, + BROKEN + } +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorControl.kt new file mode 100644 index 00000000..bf7d2faf --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSensorControl.kt @@ -0,0 +1,908 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.utils + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.Context +import android.graphics.drawable.Drawable +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import android.widget.Toast +import androidx.core.content.ContextCompat +import androidx.gridlayout.widget.GridLayout +import com.siliconlabs.bledemo.R +import com.siliconlabs.bledemo.features.demo.devkitsensor917.APIClient +import com.siliconlabs.bledemo.features.demo.devkitsensor917.APIInterface +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.LEDResponse +import com.siliconlabs.bledemo.features.demo.devkitsensor917.model.LEDStatusResponse +import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.environment.model.TemperatureScale +import kotlinx.android.synthetic.main.environmentdemo_tile.view.env_description +import kotlinx.android.synthetic.main.environmentdemo_tile.view.env_icon +import kotlinx.android.synthetic.main.environmentdemo_tile.view.env_value +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import timber.log.Timber + +open class DevKitSensorControl( + context: Context, + description: String?, + icon: Drawable? +) : LinearLayout(context, null, 0) { + private var btnRedStatus = false + private var btnGreenStatus = false + private var btnBlueStatus = false + private lateinit var ledImageStatus: ImageView + private lateinit var onLEDBtn : Button + private lateinit var offLEDBtn : Button + private lateinit var redLEDBtn : Button + private lateinit var greenLEDBtn : Button + private lateinit var blueLEDBtn : Button + constructor(context: Context) : this(context, null, null) + + private val tileView: View = inflate(context, R.layout.sensor_demo_grid_item,this) + + fun setListener(tag: Any) { + val code = tag.toString() + tileView.setOnClickListener { + when (code) { + temperature -> showTemperatureDialog(code) + humidity -> showHumidityDialog(code) + ambientLight -> showAmbientLightDialog(code) + microphone -> showMicrophoneDialog(code) + LED -> showLEDControlDialog(code) + motion -> showMotionDialog(code) + } + + + } + } + + fun setTemperature(temperature: Float, temperatureType: Int) { + tileView.env_value.text = String.format( + if (temperatureType == TemperatureScale.FAHRENHEIT) context.getString(R.string.environment_temp_f) else context.getString( + R.string.environment_temp_c + ), + if (temperatureType == TemperatureScale.FAHRENHEIT) temperature * 1.8f + 32f else temperature + ) + } + + fun setHumidity(humidity: Int) { + tileView.env_value.text = + String.format(context.getString(R.string.environment_humidity_measure), humidity) + } + + fun setAmbientLight(ambientLight: Float) { + tileView.env_value.text = + String.format(context.getString(R.string.devkit_ambient_lx), ambientLight) + } + + fun setMicrophone(microphone: Float) { + tileView.env_value.text = + String.format(context.getString(R.string.devkit_ambient_lx), microphone) + } + + private fun showMotionDialog(title: String) { + var apiJob: Job? = null + val devkitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devkitSensorDialog.setContentView(R.layout.dev_kit_sesnor_917_motion_control_dialog_layout) + devkitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val header = devkitSensorDialog.findViewById(R.id.header) as TextView + val yesBtn = devkitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devkitSensorDialog.findViewById(R.id.no_opt) as TextView + val orientationX = devkitSensorDialog.findViewById(R.id.orient_x) as TextView + val orientationY = devkitSensorDialog.findViewById(R.id.orientation_y) as TextView + val orientationZ = devkitSensorDialog.findViewById(R.id.orientation_z) as TextView + val degreeString = context.getString(R.string.motion_orientation_degree) + val acceloX = devkitSensorDialog.findViewById(R.id.accelo_x) as TextView + val acceloY = devkitSensorDialog.findViewById(R.id.accelo_y) as TextView + val acceloZ = devkitSensorDialog.findViewById(R.id.accelo_z) as TextView + orientationX.text = String.format(degreeString, 00f) + orientationY.text = String.format(degreeString, 00f) + orientationZ.text = String.format(degreeString, 00f) + + val accelerationString = context.getString(R.string.motion_acceleration_g) + acceloX.text = String.format(accelerationString, 00F) + acceloY.text = String.format(accelerationString, 00F) + acceloZ.text = String.format(accelerationString, 00F) + + yesBtn.setOnClickListener { + GlobalScope.launch(Dispatchers.IO) { + doInMotionOrientationBackground(orientationX, orientationY, orientationZ) + doInMotionAccelometerBackground(acceloX, acceloY, acceloZ) + } + } + noBtn.setOnClickListener { + devkitSensorDialog.dismiss() + if (apiJob != null) { + apiJob?.cancel() + } + } + header.text = title + space + context.getString(R.string.title_sensor) + devkitSensorDialog.show() + apiJob = GlobalScope.launch { + while (true) { + doInMotionOrientationBackground(orientationX, orientationY, orientationZ) + doInMotionAccelometerBackground(acceloX, acceloY, acceloZ) + delay(TIME_OUT) + } + } + } + + private suspend fun doInMotionAccelometerBackground( + viewX: TextView, + viewY: TextView, + viewZ: TextView + ) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getAccelerometerStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + val accelerationString = context.getString(R.string.motion_acceleration_g) + viewX.text = String.format(accelerationString, data.x.toFloat()) + viewY.text = String.format(accelerationString, data.y.toFloat()) + viewZ.text = String.format(accelerationString, data.z.toFloat()) + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred" + e.message) + } + } + } + + + private suspend fun doInMotionOrientationBackground( + viewX: TextView, + viewY: TextView, + viewZ: TextView + ) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getGyroscopeStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + val degreeString = context.getString(R.string.motion_orientation_degree) + viewX.text = String.format(degreeString, data.x.toFloat()) + viewY.text = String.format(degreeString, data.y.toFloat()) + viewZ.text = String.format(degreeString, data.z.toFloat()) + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred" + e.message) + } + } + } + + private fun showTemperatureDialog(title: String) { + var apiJob: Job? = null + val devKitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devKitSensorDialog.setContentView(R.layout.dev_kit_sensor_917_dialog_layout) + devKitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + //devKitSensorDialog.window?.setBackgroundDrawable(ColorDrawable(android.graphics.Color.TRANSPARENT)) + val header = devKitSensorDialog.findViewById(R.id.header) as TextView + val subTitle = devKitSensorDialog.findViewById(R.id.subTitle) as TextView + val yesBtn = devKitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devKitSensorDialog.findViewById(R.id.no_opt) as TextView + val image = devKitSensorDialog.findViewById(R.id.image) as ImageView + val dataHolder = devKitSensorDialog.findViewById(R.id.txt_value) as TextView + dataHolder.text = context.getString(R.string.matter_init_value) + image.setImageResource(R.drawable.icon_temp) + header.text = title + space + context.getString(R.string.title_sensor) + subTitle.text = title + yesBtn.setOnClickListener { + GlobalScope.launch(Dispatchers.IO) { + doInTempBackground(dataHolder) + } + } + noBtn.setOnClickListener { + devKitSensorDialog.dismiss() + if (apiJob != null) { + apiJob?.cancel() + } + } + devKitSensorDialog.show() + + apiJob = GlobalScope.launch { + while (true) { + doInTempBackground(dataHolder) + delay(TIME_OUT) + } + } + + } + + private suspend fun doInAmbientBackground(view: TextView) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getAmbitStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + view.text = data.ambient_light_lux + " lx" + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + + @SuppressLint("SetTextI18n") + private suspend fun doInMicroPhoneBackground(view: TextView) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getMicrophoneStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + view.text = data.microphone_decibel + " dB" + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + + + @SuppressLint("SetTextI18n") + private suspend fun doInHumidityBackground(view: TextView) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getHumidityStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + view.text = data.humidity_percentage + " %" + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + + @SuppressLint("SetTextI18n") + private suspend fun doInTempBackground(view: TextView) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getTempStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + view.text = data.temperature_celcius + " ℃" + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + + init { + tileView.setTag(description) + tileView.apply { + env_description.text = description +// env_value.text = context.getString(R.string.environment_not_initialized) + env_icon.setImageDrawable(icon) +// env_value.visibility = View.INVISIBLE + } + layoutParams = GridLayout.LayoutParams( + GridLayout.spec(GridLayout.UNDEFINED, 1f), + GridLayout.spec(GridLayout.UNDEFINED, 1f) + ).apply { + width = 0 + } + } + + private fun showMicrophoneDialog(title: String) { + var apiJob: Job? = null + val devKitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devKitSensorDialog.setContentView(R.layout.dev_kit_sensor_917_dialog_layout) + devKitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val header = devKitSensorDialog.findViewById(R.id.header) as TextView + val subTitle = devKitSensorDialog.findViewById(R.id.subTitle) as TextView + val yesBtn = devKitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devKitSensorDialog.findViewById(R.id.no_opt) as TextView + val image = devKitSensorDialog.findViewById(R.id.image) as ImageView + val microphoneHolder = devKitSensorDialog.findViewById(R.id.txt_value) as TextView + microphoneHolder.text = context.getString(R.string.dev_kit_sensor_micro_init_value) + image.setImageResource(R.drawable.icon_sound) + header.text = title + space + context.getString(R.string.title_sensor) + subTitle.text = title + yesBtn.setOnClickListener { + GlobalScope.launch(Dispatchers.IO) { + doInMicroPhoneBackground(microphoneHolder) + } + } + noBtn.setOnClickListener { + devKitSensorDialog.dismiss() + if (apiJob != null) { + apiJob?.cancel() + } + } + devKitSensorDialog.show() + + apiJob = GlobalScope.launch { + while (true) { + doInMicroPhoneBackground(microphoneHolder) + delay(TIME_OUT) + } + } + + } + + private fun showAmbientLightDialog(title: String) { + var apiJob: Job? = null + val devKitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devKitSensorDialog.setContentView(R.layout.dev_kit_sensor_917_dialog_layout) + devKitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val header = devKitSensorDialog.findViewById(R.id.header) as TextView + val subTitle = devKitSensorDialog.findViewById(R.id.subTitle) as TextView + val yesBtn = devKitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devKitSensorDialog.findViewById(R.id.no_opt) as TextView + val image = devKitSensorDialog.findViewById(R.id.image) as ImageView + val abiHolder = devKitSensorDialog.findViewById(R.id.txt_value) as TextView + + abiHolder.text = context.getString(R.string.dev_kit_sensor_ambient_init_value) + abiHolder.textSize = 50F + image.setImageResource(R.drawable.icon_light) + header.text = title + space + context.getString(R.string.title_sensor) + subTitle.text = title + + yesBtn.setOnClickListener { + GlobalScope.launch(Dispatchers.IO) { + doInAmbientBackground(abiHolder) + } + } + noBtn.setOnClickListener { + devKitSensorDialog.dismiss() + if (apiJob != null) { + apiJob?.cancel() + } + } + devKitSensorDialog.show() + + apiJob = GlobalScope.launch { + while (true) { + doInAmbientBackground(abiHolder) + delay(TIME_OUT) + } + } + + } + + + /* LED functionality Implementation */ + private fun imageForLightOn(view: ImageView, red: Boolean, blue: Boolean, green: Boolean) { + + view.setImageResource(R.drawable.light_on) + var idColor = 0 + if (red && blue && green) { + idColor = R.color.silabs_yellow + } else if (red && blue) { + idColor = R.color.silabs_magenta + } else if (blue && green) { + idColor = R.color.silabs_cyan_led + } else if (green && red) { + idColor = R.color.silabs_yellow_led + } else if (blue) { + idColor = R.color.silabs_blue + } else if (red) { + idColor = R.color.silabs_red + } else if (green) { + idColor = R.color.silabs_green + } else { + idColor = R.color.grey + } + view.setColorFilter( + ContextCompat.getColor(context, idColor), + android.graphics.PorterDuff.Mode.SRC_IN + ) + } + + private fun showLEDControlDialog(title: String) { + val apiJob: Job? = null + val devKitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devKitSensorDialog.setContentView( + R.layout.dev_kit_sesnor_917_led_control_dialog_layout + ) + devKitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val header = devKitSensorDialog.findViewById(R.id.header) as TextView + val subTitle = devKitSensorDialog.findViewById(R.id.subTitle) as TextView + val yesBtn = devKitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devKitSensorDialog.findViewById(R.id.no_opt) as TextView + onLEDBtn = devKitSensorDialog.findViewById(R.id.onButton) as Button + offLEDBtn = devKitSensorDialog.findViewById(R.id.offButton) as Button + redLEDBtn = devKitSensorDialog.findViewById(R.id.redButton) as Button + greenLEDBtn = devKitSensorDialog.findViewById(R.id.greenButton) as Button + blueLEDBtn = devKitSensorDialog.findViewById(R.id.blueButton) as Button + ledImageStatus = devKitSensorDialog.findViewById(R.id.imageLight) as ImageView + + header.text = title + space + context.getString(R.string.title_control) + subTitle.text = title + subTitle.visibility = View.GONE + + //LED Switch Off condition + imageForLightOn(view = ledImageStatus, red = false, blue = false, green = false) +// switchOffLEDStatusOff() + GlobalScope.launch { + getLedSwitchStatus() + } + + yesBtn.setOnClickListener { + refreshLEDStatus() + } + noBtn.setOnClickListener { + devKitSensorDialog.dismiss() + if (apiJob != null) { + apiJob.cancel() + } + } + onLEDBtn.setOnClickListener { + GlobalScope.launch { + setAllLEDOn(ledImageStatus) + } + } + + offLEDBtn.setOnClickListener { + GlobalScope.launch { + setAllLEDOff(ledImageStatus) + } + } + + redLEDBtn.setOnClickListener { + btnRedStatus = !btnRedStatus + setLEDControl() + } + greenLEDBtn.setOnClickListener { + btnGreenStatus = !btnGreenStatus + setLEDControl() + } + + blueLEDBtn.setOnClickListener { + btnBlueStatus = !btnBlueStatus + setLEDControl() + } + + devKitSensorDialog.setCanceledOnTouchOutside(false) + devKitSensorDialog.show() + } + + private fun switchOffLEDStatusOff() { + GlobalScope.launch { + setLEDStatusOff(ledImageStatus) + } + } + + private fun setOnBtnBackground() { + onLEDBtn.setBackgroundResource(R.drawable.button_background_soft_black_box) + offLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + redLEDBtn.setBackgroundResource(R.drawable.button_background_red_box) + greenLEDBtn.setBackgroundResource(R.drawable.button_background_green_box) + blueLEDBtn.setBackgroundResource(R.drawable.button_background_blue_box) + } + + private fun setOffBtnBackground() { + onLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + offLEDBtn.setBackgroundResource(R.drawable.button_background_soft_black_box) + redLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + greenLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + blueLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + } + + private fun refreshLEDStatus() { + GlobalScope.launch(Dispatchers.IO) { + getAllLEDStatus(ledImageStatus) + } + } + + private fun setBtnColorBackground() { + if(btnRedStatus) + redLEDBtn.setBackgroundResource(R.drawable.button_background_red_box) + else + redLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + + if(btnGreenStatus) + greenLEDBtn.setBackgroundResource(R.drawable.button_background_green_box) + else + greenLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + + if(btnBlueStatus) + blueLEDBtn.setBackgroundResource(R.drawable.button_background_blue_box) + else + blueLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + + if(btnRedStatus && btnGreenStatus && btnBlueStatus) { + onLEDBtn.setBackgroundResource(R.drawable.button_background_soft_black_box) + offLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + } else { + onLEDBtn.setBackgroundResource(R.drawable.button_background_grey_box) + offLEDBtn.setBackgroundResource(R.drawable.button_background_soft_black_box) + } + + } + + private fun setLEDControl(){ + GlobalScope.launch { + setLEDCtrl( + ledImageStatus, + btnRedStatus, + btnGreenStatus, + btnBlueStatus + ) + } + } + + private suspend fun setLEDCtrl(view: ImageView, red: Boolean, green: Boolean, blue: Boolean) { + withContext(Dispatchers.Default) { + val ledStatus = APIClient.getInstance().create(APIInterface::class.java) + val params: MutableMap = HashMap() + var statusRed: String = OFF + if (red) { + statusRed = ON + } + params.put(RED, statusRed) + var statusGreen = OFF + if (green) { + statusGreen = ON + } + params.put(GREEN, statusGreen) + var statusBlue = OFF + if (blue) { + statusBlue = ON + } + params.put(BLUE, statusBlue) + + ledStatus.setRedLEDOn(params).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + if (data.red.equals(OFF) && data.green.equals(OFF) + && data.blue.equals(OFF) + ) { + imageForLightOn(view, false, false, false) + } else { + imageForLightOn(view, red, blue, green) + } + setBtnColorBackground() + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, false, false, false) + Toast.makeText( + context, + "Failed to connect. Check your Wi-Fi connection", + Toast.LENGTH_SHORT + ).show() + } + + }) + } + } + + private suspend fun setAllLEDOff(view: ImageView) { + withContext(Dispatchers.Default) { + val ledStatus = APIClient.getInstance().create(APIInterface::class.java) + val body = mapOf( + RED to OFF, + GREEN to OFF, + BLUE to OFF + ) + ledStatus.setAllLEdsOnOff(body).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + if (data.red.equals(OFF) && data.green.equals(OFF) + && data.blue.equals(OFF) + ) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, btnRedStatus, btnBlueStatus, btnGreenStatus) + } else { + imageForLightOn(view, false, false, false) + setOffBtnBackground() + } + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, false, false, false) + Toast.makeText( + context, + "Failed to connect. Check your Wi-Fi connection", + Toast.LENGTH_SHORT + ).show() + } + + }) + + } + } + + private suspend fun setAllLEDOn(view: ImageView) { + withContext(Dispatchers.Default) { + val ledStatus = APIClient.getInstance().create(APIInterface::class.java) + val body = mapOf( + RED to ON, + GREEN to ON, + BLUE to ON + ) + ledStatus.setAllLEdsOnOff(body).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + if (data.red.equals(OFF) && data.green.equals(OFF) + && data.blue.equals(OFF) + ) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, btnRedStatus, btnBlueStatus, btnGreenStatus) + } else { + btnRedStatus = true + btnBlueStatus = true + btnGreenStatus = true + setOnBtnBackground() + imageForLightOn(view, btnRedStatus, btnBlueStatus, btnGreenStatus) + } + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, false, false, false) + Toast.makeText( + context, + "Failed to connect. Check your Wi-Fi connection", + Toast.LENGTH_SHORT + ).show() + } + + }) + } + } + + private suspend fun getLedSwitchStatus() { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getLedSwitchStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + if(data.status_led == ON) + switchOffLEDStatusOff() + else + refreshLEDStatus() + } + } else { + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + private suspend fun setLEDStatusOff(view: ImageView) { + withContext(Dispatchers.Default) { + val ledStatus = APIClient.getInstance().create(APIInterface::class.java) + val body = mapOf( + STATUS_LED to OFF + ) + ledStatus.setLEDStatusOff(body).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + //refresh the current LED status + refreshLEDStatus() + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + btnRedStatus = false + btnBlueStatus = false + btnGreenStatus = false + setOffBtnBackground() + imageForLightOn(view, false, false, false) + Toast.makeText( + context, + "Failed to connect. Check your Wi-Fi connection", + Toast.LENGTH_SHORT + ).show() + } + + }) + } + } + private suspend fun getAllLEDStatus(view: ImageView) { + withContext(Dispatchers.Default) { + try { + val apiService = APIClient.getInstance().create(APIInterface::class.java) + val response = apiService.getLedStatus() + println("Response: $response") + if (response.isSuccessful) { + val data = response.body() + println("data: $data") + if (data != null) { + btnRedStatus = data.red == ON + btnGreenStatus = data.green == ON + btnBlueStatus = data.blue == ON + imageForLightOn(view, btnRedStatus, btnBlueStatus, btnGreenStatus) + setBtnColorBackground() + } + } else { + //df + Timber.tag(TAG).e("Response failed:") + } + } catch (e: Exception) { + // Handle the exception + Timber.tag(TAG).e("Exception occurred") + } + } + } + + private fun showHumidityDialog(title: String) { + var apiJob: Job? = null + val devKitSensorDialog = Dialog(context, R.style.Style_Dialog_Rounded_Corner) + devKitSensorDialog.setContentView( + R.layout.dev_kit_sensor_917_dialog_layout + ) + devKitSensorDialog.window?.setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + val header = devKitSensorDialog.findViewById(R.id.header) as TextView + val subTitle = devKitSensorDialog.findViewById(R.id.subTitle) as TextView + val yesBtn = devKitSensorDialog.findViewById(R.id.yes_opt) as TextView + val noBtn = devKitSensorDialog.findViewById(R.id.no_opt) as TextView + val image = devKitSensorDialog.findViewById(R.id.image) as ImageView + val humidityHolder = devKitSensorDialog.findViewById(R.id.txt_value) as TextView + humidityHolder.text = context.getString(R.string.dev_kit_sensor_humidity_init_value) + image.setImageResource(R.drawable.icon_environment) + header.text = title + space + context.getString(R.string.title_sensor) + subTitle.text = title + yesBtn.setOnClickListener { + GlobalScope.launch(Dispatchers.IO) { + doInHumidityBackground(humidityHolder) + } + } + noBtn.setOnClickListener { + devKitSensorDialog.dismiss() + if (apiJob != null) { + apiJob?.cancel() + } + } + devKitSensorDialog.show() + + apiJob = GlobalScope.launch { + while (true) { + doInHumidityBackground(humidityHolder) + delay(TIME_OUT) + } + } + + } + + + companion object { + const val space = " " + const val temperature = "Temperature" + const val humidity = "Humidity" + const val ambientLight = "Ambient Light" + const val microphone = "Microphone" + const val LED = "LED" + const val motion = "Motion" + const val TIME_OUT = 3000L + const val OFF = "off" + const val ON = "on" + const val RED = "red" + const val GREEN = "green" + const val BLUE = "blue" + const val STATUS_LED = "status_led" + private val TAG = DevKitSensorControl.javaClass.simpleName.toString() + } +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSesnorControl.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSesnorControl.kt new file mode 100644 index 00000000..8b93f622 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/devkitsensor917/utils/DevKitSesnorControl.kt @@ -0,0 +1,4 @@ +package com.siliconlabs.bledemo.features.demo.devkitsensor917.utils + +class DevKitSesnorControl { +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/adapters/MatterScannedResultAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/adapters/MatterScannedResultAdapter.kt index 687dba52..9d129467 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/adapters/MatterScannedResultAdapter.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/adapters/MatterScannedResultAdapter.kt @@ -1,10 +1,12 @@ package com.siliconlabs.bledemo.features.demo.matter_demo.adapters import android.content.Context +import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView +import com.daimajia.swipe.SimpleSwipeListener import com.daimajia.swipe.SwipeLayout import com.siliconlabs.bledemo.R import com.siliconlabs.bledemo.databinding.MatterScannedListItemBinding @@ -18,8 +20,6 @@ class MatterScannedResultAdapter( ) : RecyclerView.Adapter() { private lateinit var context: Context private var onClickListener: OnClickListener? = null - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MatterItemViewModel { val binding = MatterScannedListItemBinding.inflate( @@ -61,10 +61,8 @@ class MatterScannedResultAdapter( holder.binding.swipe.findViewById(R.id.bottom_wrapper) ) //viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper)); - - - holder.binding.textViewHeader.setOnClickListener { + runBlocking { if (onClickListener != null) { onClickListener!!.onClick(position, matterInfo) @@ -81,7 +79,6 @@ class MatterScannedResultAdapter( } } - override fun getItemCount(): Int { return matterList.size } diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannerFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannerFragment.kt index 48142f0c..93c046fc 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannerFragment.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterScannerFragment.kt @@ -82,7 +82,6 @@ class MatterScannerFragment : Fragment() { println("Input MT : ${qrCodeManualInput}") handleManualInput(qrCodeManualInput) } - } override fun onResume() { @@ -293,7 +292,7 @@ class MatterScannerFragment : Fragment() { Timber.e("Unrecognized QR Exception") } } catch (e: Exception) { - Timber.e("Unrecognized QR Exception " + e) + Timber.e("Unrecognized QR Exception $e" ) } } @@ -372,6 +371,7 @@ class MatterScannerFragment : Fragment() { return locationPermissionGranted && bleScanPermissionGranted } + @Deprecated("Deprecated in Java") override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterTemperatureSensorFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterTemperatureSensorFragment.kt index b6df6e59..4bf3fa9b 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterTemperatureSensorFragment.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterTemperatureSensorFragment.kt @@ -56,6 +56,7 @@ class MatterTemperatureSensorFragment : Fragment() { private var endpointId: Int = ON_OFF_CLUSTER_ENDPOINT private lateinit var model: MatterScannedResultModel private var customProgressDialog: CustomProgressDialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mPrefs = requireContext().getSharedPreferences( diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWifiInputDialogFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWifiInputDialogFragment.kt index 46f6ce5f..8bc81c87 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWifiInputDialogFragment.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/fragments/MatterWifiInputDialogFragment.kt @@ -73,8 +73,7 @@ class MatterWifiInputDialogFragment : DialogFragment() { } if (!FragmentUtils.isPasswordValid(wifiPassword)) { Toast.makeText(requireContext(), - getString(R.string.password_must_be_min_8_characters), Toast.LENGTH_SHORT) - .show() + getString(R.string.password_must_be_min_8_characters), Toast.LENGTH_SHORT).show() return@setOnClickListener } val intent = Intent() diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/MatterDialogDeviceInfoFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/MatterDialogDeviceInfoFragment.kt new file mode 100644 index 00000000..522a05e5 --- /dev/null +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/matter_demo/utils/MatterDialogDeviceInfoFragment.kt @@ -0,0 +1,93 @@ +package com.siliconlabs.bledemo.features.demo.matter_demo.utils + +import android.content.DialogInterface +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import com.siliconlabs.bledemo.databinding.DialogDeviceInfoLayoutBinding +import com.siliconlabs.bledemo.features.iop_test.utils.DialogDeviceInfoFragment +import kotlinx.android.synthetic.main.adapter_scanned_device.title + +class MatterDialogDeviceInfoFragment: DialogFragment() { + private var title: String? = null + private var message: String? = null + private var positiveButtonText: String? = null + private var negativeButtonText: String? = null + private var positiveClickListener: DialogInterface.OnClickListener? = null + private var negativeClickListener: DialogInterface.OnClickListener? = null + private lateinit var binding: DialogDeviceInfoLayoutBinding + + private var dialogShowing = false + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = DialogDeviceInfoLayoutBinding.inflate(inflater, container, false) + return binding.root + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + + // Set title and message + binding.dialogTitle.text = title + binding.dialogMessage.text = message + + // Set positive button click listener + binding.btnPositive.setOnClickListener { + positiveClickListener?.onClick(dialog, DialogInterface.BUTTON_POSITIVE) + dismiss() + } + + // Set negative button click listener + binding.btnNegative.setOnClickListener { + negativeClickListener?.onClick(dialog, DialogInterface.BUTTON_NEGATIVE) + dismiss() + } + + // Set button texts + binding.btnPositive.text = positiveButtonText + binding.btnNegative.text = negativeButtonText + + } + + + // Builder pattern for setting dialog properties + class Builder { + private val fragment = DialogDeviceInfoFragment() + + fun setTitle(title: String?): Builder { + fragment.title = title + return this + } + + fun setMessage(message: String?): Builder { + fragment.message = message + return this + } + + fun setPositiveButton(text: String?, listener: DialogInterface.OnClickListener?): Builder { + fragment.positiveButtonText = text + fragment.positiveClickListener = listener + return this + } + + fun setNegativeButton(text: String?, listener: DialogInterface.OnClickListener?): Builder { + fragment.negativeButtonText = text + fragment.negativeClickListener = listener + return this + } + + fun build(): DialogDeviceInfoFragment { + return fragment + } + } + + fun isShowing(): Boolean { + return dialogShowing + } +} \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt index c0293ef7..91eb1c00 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/activities/RangeTestActivity.kt @@ -39,10 +39,9 @@ import kotlin.math.abs @SuppressLint("MissingPermission") class RangeTestActivity : BaseDemoActivity(), Controller { - private var lowerLimit: Int = 0 + private var lowerLimit: Int = 0 private var upperLimit: Int = 0 private var descriptor2906: BluetoothGattDescriptor? = null - private var activeDeviceId = 1 private var advertisementHandler: RangeTestAdvertisementHandler? = null @@ -192,8 +191,8 @@ class RangeTestActivity : BaseDemoActivity(), Controller { } }) }.also { - it.show(supportFragmentManager, "select_device_dialog") - } + it.show(supportFragmentManager, "select_device_dialog") + } } else { showRangeTestFragment(presenter.getMode()) } @@ -785,11 +784,11 @@ class RangeTestActivity : BaseDemoActivity(), Controller { status: Int ) { super.onCharacteristicRead(gatt, characteristic, status) - val descriptorUuid = UUID.fromString("00002906-0000-1000-8000-00805f9b34fb") - if (characteristic != null) { - descriptor2906 = characteristic.getDescriptor(descriptorUuid) - } + val descriptorUuid=UUID.fromString("00002906-0000-1000-8000-00805f9b34fb") + if(characteristic!=null){ + descriptor2906=characteristic.getDescriptor(descriptorUuid) + } if (status != BluetoothGatt.GATT_SUCCESS) { handleConnectionError() return @@ -802,16 +801,14 @@ class RangeTestActivity : BaseDemoActivity(), Controller { if (gattCharacteristic != null) { updatePresenter(gatt, characteristic, gattCharacteristic) - if (gattCharacteristic === GattCharacteristic.RangeTestTxPower - || gattCharacteristic === GattCharacteristic.RangeTestPayload - || gattCharacteristic === GattCharacteristic.RangeTestMaSize - ) { + if (gattCharacteristic === GattCharacteristic.RangeTestTxPower || gattCharacteristic === GattCharacteristic.RangeTestPayload || gattCharacteristic === GattCharacteristic.RangeTestMaSize) { val descriptors = characteristic.descriptors if (descriptors.size > 1) { queueReadDescriptor(gatt, characteristic, descriptors[descriptors.size - 1]) } - } else { - if (gattCharacteristic === GattCharacteristic.RangeTestChannel) { + } + else{ + if (gattCharacteristic===GattCharacteristic.RangeTestChannel){ val descriptors = characteristic.descriptors if (descriptors.size > 1) { descriptor2906?.let { queueReadDescriptor(gatt, characteristic, it) } @@ -1247,7 +1244,7 @@ class RangeTestActivity : BaseDemoActivity(), Controller { android.R.id.home -> { service?.disconnectAllGatts() gatt?.disconnect() - Handler(Looper.getMainLooper()).postDelayed({ onBackPressed() }, 500) + Handler(Looper.getMainLooper()).postDelayed({ onBackPressed() },500) true } @@ -1259,4 +1256,5 @@ class RangeTestActivity : BaseDemoActivity(), Controller { private const val RECONNECTION_RETRIES = 3 private const val TRANSMISSION_INTERVAL: Long = 1000 / 13 } + } diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt index 46b79532..b54d5250 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/range_test/models/RangeTestValues.kt @@ -1,11 +1,13 @@ package com.siliconlabs.bledemo.features.demo.range_test.models +import com.siliconlabs.bledemo.features.demo.range_test.activities.RangeTestActivity import java.util.* /** * @author Comarch S.A. */ class RangeTestValues { + companion object { const val PACKET_COUNT_REPEAT = 65535 @@ -21,6 +23,19 @@ class RangeTestValues { private const val ID_MIN = 0 private const val ID_MAX = 32 + fun setChannelsMinMax(min: Int, max: Int) { + CHANNELS_MIN = min + CHANNELS_MAX = max + updateChannelLookup() + } + private fun updateChannelLookup() { + val channelsLookupSize = CHANNELS_MAX - CHANNELS_MIN + 1 + val channelsLookup: ArrayList = ArrayList(channelsLookupSize) + for (i in 0 until channelsLookupSize) { + channelsLookup.add(CHANNELS_MIN + i) + } + CHANNEL_LOOKUP = Collections.unmodifiableList(channelsLookup) + } init { val channelsLookupSize = CHANNELS_MAX - CHANNELS_MIN + 1 val channelsLookup: ArrayList = ArrayList(channelsLookupSize) @@ -39,20 +54,6 @@ class RangeTestValues { ID_LOOKUP = Collections.unmodifiableList(idLookup) } - - fun setChannelsMinMax(min: Int, max: Int) { - CHANNELS_MIN = min - CHANNELS_MAX = max - updateChannelLookup() - } - - private fun updateChannelLookup() { - val channelsLookupSize = CHANNELS_MAX - CHANNELS_MIN + 1 - val channelsLookup: ArrayList = ArrayList(channelsLookupSize) - for (i in 0 until channelsLookupSize) { - channelsLookup.add(CHANNELS_MIN + i) - } - CHANNEL_LOOKUP = Collections.unmodifiableList(channelsLookup) - } } + } \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/throughput/views/SpeedView.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/throughput/views/SpeedView.kt index 6b037020..4b71567b 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/throughput/views/SpeedView.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/throughput/views/SpeedView.kt @@ -135,7 +135,8 @@ class SpeedView(context: Context, attributeSet: AttributeSet? = null) : View(con this.unitsArray = array } - override fun onDraw(canvas: Canvas?) { + + override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val startAngle = (135f + (progress / 100.0) * 270).toFloat() @@ -157,6 +158,7 @@ class SpeedView(context: Context, attributeSet: AttributeSet? = null) : View(con drawUnits(this) drawSpeed(this) } + } private fun drawUnits(canvas: Canvas) { diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt index 9b6fdee1..e8cb36ac 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/base/models/ThunderBoardDevice.kt @@ -19,11 +19,9 @@ class ThunderBoardDevice(device: BluetoothDevice) { THUNDERBOARD_MODEL_SENSE -> Type.THUNDERBOARD_SENSE THUNDERBOARD_MODEL_BLUE_V1, THUNDERBOARD_MODEL_BLUE_V2 -> Type.THUNDERBOARD_BLUE - + THUNDERBOARD_MODEL_DEV_KIT_V3, THUNDERBOARD_MODEL_DEV_KIT_V1, - THUNDERBOARD_MODEL_DEV_KIT_V2, - THUNDERBOARD_MODEL_DEV_KIT_V3 -> Type.THUNDERBOARD_DEV_KIT - + THUNDERBOARD_MODEL_DEV_KIT_V2 -> Type.THUNDERBOARD_DEV_KIT else -> Type.UNKNOWN } @@ -33,9 +31,9 @@ class ThunderBoardDevice(device: BluetoothDevice) { UNKNOWN(0); companion object { - fun fromInt(code: Int): PowerSource { + fun fromInt(code: Int) : PowerSource { for (source in values()) { - if (source.value == code) return source + if (source.value == code ) return source } return UNKNOWN } diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt index 5d83a02c..fbc1114b 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/blinky_thunderboard/activities/BlinkyThunderboardActivity.kt @@ -34,17 +34,12 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val view = - LayoutInflater.from(this).inflate(R.layout.activity_blinky_thunderboard, null, false) - colorLEDControl = - view.findViewById(R.id.color_led_control) // make the view gone (if necessary) before it can be showed + val view = LayoutInflater.from(this).inflate(R.layout.activity_blinky_thunderboard, null, false) + colorLEDControl = view.findViewById(R.id.color_led_control) // make the view gone (if necessary) before it can be showed ledsControl = view.findViewById(R.id.leds_control) val powerSourceIntent = intent.getIntExtra(SelectDeviceDialog.POWER_SOURCE_EXTRA, 0) val modelNumberIntent = intent.getStringExtra(SelectDeviceDialog.MODEL_TYPE_EXTRA) - setControlsVisibility( - ThunderBoardDevice.PowerSource.fromInt(powerSourceIntent), - modelNumberIntent - ) + setControlsVisibility(ThunderBoardDevice.PowerSource.fromInt(powerSourceIntent), modelNumberIntent) mainSection?.addView(view) @@ -82,17 +77,15 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen viewModel.button0.observe(this, Observer { switch_0.setChecked(it) }) viewModel.button1.observe(this, Observer { switch_1.setChecked(it) }) viewModel.led0.observe(this, Observer { - if (it != led_0.isChecked) led_0.isChecked = it - }) + if (it != led_0.isChecked) led_0.isChecked = it }) viewModel.led1.observe(this, Observer { - if (it != led_1.isChecked) led_1.isChecked = it - }) + if (it != led_1.isChecked) led_1.isChecked = it }) when (modelNumber) { + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3, ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE, ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> { + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 -> { viewModel.colorLed.observe(this, Observer { colorLEDControl.setColorLEDsUI(it) }) @@ -107,10 +100,10 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen private fun sendColorLedCommand(rgbState: LedRGBState) { val data = byteArrayOf( - (if (rgbState.on) viewModel.rgbLedMask.value!! else 0x00).toByte(), - (rgbState.red and 0xff).toByte(), - (rgbState.green and 0xff).toByte(), - (rgbState.blue and 0xff).toByte() + (if (rgbState.on) viewModel.rgbLedMask.value!! else 0x00).toByte(), + (rgbState.red and 0xff).toByte(), + (rgbState.green and 0xff).toByte(), + (rgbState.blue and 0xff).toByte() ) getRgbLedCharacteristic()?.apply { @@ -119,28 +112,24 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen } } - private fun setControlsVisibility( - powerSource: ThunderBoardDevice.PowerSource, - modelNumber: String? - ) { + private fun setControlsVisibility(powerSource: ThunderBoardDevice.PowerSource, modelNumber: String?) { if (modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1 || - modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 - ) { + modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2) { ledsControl.visibility = View.GONE } if (modelNumber == ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE && - powerSource == ThunderBoardDevice.PowerSource.COIN_CELL - ) { + powerSource == ThunderBoardDevice.PowerSource.COIN_CELL) { colorLEDControl.visibility = View.GONE } } @SuppressLint("MissingPermission") private fun initControls() { - if (statusFragment.viewModel.thunderboardDevice.value?.boardType != ThunderBoardDevice.Type.THUNDERBOARD_SENSE && - statusFragment.viewModel.thunderboardDevice.value?.boardType != ThunderBoardDevice.Type.THUNDERBOARD_DEV_KIT - ) { + if (statusFragment.viewModel.thunderboardDevice.value?. + boardType != ThunderBoardDevice.Type.THUNDERBOARD_SENSE && + statusFragment.viewModel.thunderboardDevice.value?. + boardType != ThunderBoardDevice.Type.THUNDERBOARD_DEV_KIT) { runOnUiThread { colorLEDControl.visibility = View.GONE } } @@ -158,31 +147,30 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen gattQueue.clearAllButLast() // prevent from queueing more gatt commands } - private fun getDigitalWriteCharacteristic(): BluetoothGattCharacteristic? { + private fun getDigitalWriteCharacteristic() : BluetoothGattCharacteristic? { return gatt?.getService( - GattService.AutomationIo.number - )?.characteristics - ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two - ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0 } + GattService.AutomationIo.number)?.characteristics + ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two + ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0 } } - private fun getDigitalNotifyCharacteristic(): BluetoothGattCharacteristic? { + private fun getDigitalNotifyCharacteristic() : BluetoothGattCharacteristic? { return gatt?.getService( - GattService.AutomationIo.number - )?.characteristics - ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two - ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0 } + GattService.AutomationIo.number)?.characteristics + ?.filter { it.uuid == GattCharacteristic.Digital.uuid } // there are two + ?.first { it.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0 } } - private fun getRgbLedCharacteristic(): BluetoothGattCharacteristic? { - return gatt?.getService(GattService.UserInterface.number) - ?.getCharacteristic(GattCharacteristic.RgbLeds.uuid) + private fun getRgbLedCharacteristic() : BluetoothGattCharacteristic? { + return gatt?.getService(GattService.UserInterface.number)?. + getCharacteristic(GattCharacteristic.RgbLeds.uuid) } - private fun getRgbLedMaskDescriptor(): BluetoothGattDescriptor? { - return gatt?.getService(GattService.UserInterface.number) - ?.getCharacteristic(GattCharacteristic.RgbLeds.uuid)?.getDescriptor(LED_MASK_DESCRIPTOR) + private fun getRgbLedMaskDescriptor() : BluetoothGattDescriptor? { + return gatt?.getService(GattService.UserInterface.number)?. + getCharacteristic(GattCharacteristic.RgbLeds.uuid)?. + getDescriptor(LED_MASK_DESCRIPTOR) } override val gattCallback: TimeoutGattCallback = object : TimeoutGattCallback() { @@ -200,11 +188,9 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen queueReadingDeviceCharacteristics() } - override fun onCharacteristicRead( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - status: Int - ) { + override fun onCharacteristicRead(gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + status: Int) { super.onCharacteristicRead(gatt, characteristic, status) gattQueue.handleCommandProcessed() if (status != BluetoothGatt.GATT_SUCCESS) return @@ -216,9 +202,7 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen GattCharacteristic.ModelNumberString, GattCharacteristic.BatteryLevel, GattCharacteristic.PowerSource, - GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic( - characteristic - ) + GattCharacteristic.FirmwareRevision -> statusFragment.handleBaseCharacteristic(characteristic) GattCharacteristic.RgbLeds -> { val on = characteristic.getIntValue(gattCharacteristic.format, 0) @@ -226,24 +210,21 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen val green = characteristic.getIntValue(gattCharacteristic.format, 2) val blue = characteristic.getIntValue(gattCharacteristic.format, 3) val ledState = LedRGBState( - on != null && on != 0, - red ?: 0, - green ?: 0, - blue ?: 0 + on != null && on != 0, + red ?: 0, + green ?: 0, + blue ?: 0 ) viewModel.colorLed.postValue(ledState) } - - else -> {} + else -> { } } } - override fun onCharacteristicWrite( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - status: Int - ) { + override fun onCharacteristicWrite(gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + status: Int) { super.onCharacteristicWrite(gatt, characteristic, status) gattQueue.handleCommandProcessed() if (status != BluetoothGatt.GATT_SUCCESS) return @@ -253,63 +234,54 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen when (gattCharacteristic) { GattCharacteristic.Digital -> { val led0State = - (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_0_ON) != 0 + (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_0_ON) != 0 val led1State = - (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_1_ON) != 0 + (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.LED_1_ON) != 0 viewModel.led0.postValue(led0State) viewModel.led1.postValue(led1State) } - GattCharacteristic.RgbLeds -> { val on = characteristic.getIntValue(gattCharacteristic.format, 0) val red = characteristic.getIntValue(gattCharacteristic.format, 1) val green = characteristic.getIntValue(gattCharacteristic.format, 2) val blue = characteristic.getIntValue(gattCharacteristic.format, 3) val ledState = LedRGBState( - on != null && on != 0, - red ?: 0, - green ?: 0, - blue ?: 0 + on != null && on != 0, + red ?: 0, + green ?: 0, + blue ?: 0 ) viewModel.colorLed.postValue(ledState) } - else -> { } } } - override fun onCharacteristicChanged( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic - ) { + override fun onCharacteristicChanged(gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic) { super.onCharacteristicChanged(gatt, characteristic) val gattCharacteristic = GattCharacteristic.fromUuid(characteristic.uuid) when (gattCharacteristic) { GattCharacteristic.BatteryLevel, - GattCharacteristic.PowerSource -> statusFragment.handleBaseCharacteristic( - characteristic - ) + GattCharacteristic.PowerSource -> statusFragment.handleBaseCharacteristic(characteristic) GattCharacteristic.Digital -> { val button0State = - (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_0_ON) != 0 + (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_0_ON) != 0 val button1State = - (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_1_ON) != 0 + (characteristic.value[0].toInt() and BlinkyThunderboardViewModel.BUTTON_1_ON) != 0 viewModel.button0.postValue(button0State) viewModel.button1.postValue(button1State) } - - else -> {} + else -> { } } } - override fun onDescriptorRead( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, - status: Int - ) { + override fun onDescriptorRead(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, + status: Int) { super.onDescriptorRead(gatt, descriptor, status) if (descriptor?.uuid == LED_MASK_DESCRIPTOR) { @@ -318,23 +290,20 @@ class BlinkyThunderboardActivity : ThunderboardActivity(), ColorLEDControlListen } - override fun onDescriptorWrite( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, - status: Int - ) { + override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, + status: Int) { super.onDescriptorWrite(gatt, descriptor, status) gattQueue.handleCommandProcessed() if (status != BluetoothGatt.GATT_SUCCESS) return when (descriptor.characteristic.uuid) { GattCharacteristic.BatteryLevel.uuid -> initControls() - else -> {} + else -> { } } } } companion object { - private val LED_MASK_DESCRIPTOR: UUID? = - UUID.fromString("1c694489-8825-45cc-8720-28b54b1fbf00") + private val LED_MASK_DESCRIPTOR: UUID? = UUID.fromString("1c694489-8825-45cc-8720-28b54b1fbf00") } } \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/activities/MotionActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/activities/MotionActivity.kt index 3bea9c70..d48a0ed8 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/activities/MotionActivity.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/activities/MotionActivity.kt @@ -15,15 +15,15 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration -import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog +import com.siliconlabs.bledemo.R import com.siliconlabs.bledemo.bluetooth.ble.GattCharacteristic import com.siliconlabs.bledemo.bluetooth.ble.GattService import com.siliconlabs.bledemo.bluetooth.ble.TimeoutGattCallback -import com.siliconlabs.bledemo.R -import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.motion.viewmodels.MotionViewModel -import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.motion.adapters.GdxAdapter import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker import com.siliconlabs.bledemo.features.demo.thunderboard_demos.base.utils.SensorChecker.ThunderboardSensor +import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.motion.adapters.GdxAdapter +import com.siliconlabs.bledemo.features.demo.thunderboard_demos.demos.motion.viewmodels.MotionViewModel +import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog import kotlinx.android.synthetic.main.activity_motion.* import kotlinx.android.synthetic.main.motiondemo_acceleration.* import kotlinx.android.synthetic.main.motiondemo_orientation.* diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt index 9b89b0ec..7a0964d0 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/thunderboard_demos/demos/motion/adapters/GdxAdapter.kt @@ -261,10 +261,10 @@ class GdxAdapter(private val backgroundColor: Int, modelType: String?) : when (modelType) { ThunderBoardDevice.THUNDERBOARD_MODEL_BLUE_V1, ThunderBoardDevice.THUNDERBOARD_MODEL_BLUE_V2 -> this.modelType = ModelType.BLUE + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3, ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE, ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> this.modelType = ModelType.SENSE + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 -> this.modelType = ModelType.SENSE else -> this.modelType = ModelType.SENSE } } diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/activities/WifiCommissioningActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/activities/WifiCommissioningActivity.kt index f5dbaf8e..d4a0e67e 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/activities/WifiCommissioningActivity.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/demo/wifi_commissioning/activities/WifiCommissioningActivity.kt @@ -6,6 +6,7 @@ import android.app.ProgressDialog import android.bluetooth.* import android.content.* import android.os.Bundle +import android.util.Log import android.view.View import android.widget.* import androidx.recyclerview.widget.LinearLayoutManager @@ -20,6 +21,7 @@ import com.siliconlabs.bledemo.features.demo.wifi_commissioning.adapters.AccessP import com.siliconlabs.bledemo.features.demo.wifi_commissioning.models.AccessPoint import com.siliconlabs.bledemo.features.demo.wifi_commissioning.models.BoardCommand import com.siliconlabs.bledemo.features.demo.wifi_commissioning.models.SecurityMode +import com.siliconlabs.bledemo.utils.Constants import timber.log.Timber import java.util.* @@ -69,11 +71,12 @@ class WifiCommissioningActivity : BaseDemoActivity() { } private fun setupRecyclerView() { - accessPointsAdapter = AccessPointsAdapter(accessPoints, object : AccessPointsAdapter.OnItemClickListener { - override fun onItemClick(itemView: View?, position: Int) { - onAccessPointClicked(position) - } - }) + accessPointsAdapter = + AccessPointsAdapter(accessPoints, object : AccessPointsAdapter.OnItemClickListener { + override fun onItemClick(itemView: View?, position: Int) { + onAccessPointClicked(position) + } + }) _binding.wifiAccessPtsList.apply { adapter = accessPointsAdapter layoutManager = LinearLayoutManager(context) @@ -87,7 +90,8 @@ class WifiCommissioningActivity : BaseDemoActivity() { private fun showProgressDialog(message: String) { runOnUiThread { progressDialog?.dismiss() - progressDialog = ProgressDialog.show(this, getString(R.string.empty_description), message) + progressDialog = + ProgressDialog.show(this, getString(R.string.empty_description), message) } } @@ -164,15 +168,17 @@ class WifiCommissioningActivity : BaseDemoActivity() { private fun toggleMainView(isAccessPointConnected: Boolean) { runOnUiThread { - _binding.apConnectedLayout.visibility = if (isAccessPointConnected) View.VISIBLE else View.GONE - _binding.wifiAccessPtsList.visibility = if (isAccessPointConnected) View.GONE else View.VISIBLE + _binding.apConnectedLayout.visibility = + if (isAccessPointConnected) View.VISIBLE else View.GONE + _binding.wifiAccessPtsList.visibility = + if (isAccessPointConnected) View.GONE else View.VISIBLE } } private fun showDisconnectionDialog() { val dialogMessage = - if (connectedAccessPoint?.name == clickedAccessPoint?.name) getString(R.string.disconnect_title) - else getString(R.string.another_ap_connected) + if (connectedAccessPoint?.name == clickedAccessPoint?.name) getString(R.string.disconnect_title) + else getString(R.string.another_ap_connected) AlertDialog.Builder(this).apply { setCancelable(false) @@ -244,31 +250,40 @@ class WifiCommissioningActivity : BaseDemoActivity() { Timber.d("onServicesDiscovered; status = $status") gatt.getService(GattService.WifiCommissioningService.number)?.let { - characteristicWrite = it.getCharacteristic(GattCharacteristic.WifiCommissioningWrite.uuid) - characteristicRead = it.getCharacteristic(GattCharacteristic.WifiCommissioningRead.uuid) - characteristicNotification = it.getCharacteristic(GattCharacteristic.WifiCommissioningNotify.uuid) + characteristicWrite = + it.getCharacteristic(GattCharacteristic.WifiCommissioningWrite.uuid) + characteristicRead = + it.getCharacteristic(GattCharacteristic.WifiCommissioningRead.uuid) + characteristicNotification = + it.getCharacteristic(GattCharacteristic.WifiCommissioningNotify.uuid) } if (gatt.setCharacteristicNotification(characteristicNotification, true)) { Timber.d("Notifications enabled for ${characteristicNotification?.uuid}") - characteristicNotification?.getDescriptor(UUID.fromString(clientCharacteristicConfig))?.let { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - gatt.writeDescriptor(it) - } + characteristicNotification?.getDescriptor(UUID.fromString(clientCharacteristicConfig)) + ?.let { + it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE + gatt.writeDescriptor(it) + } } writeCommand(BoardCommand.Send.GET_FIRMWARE_VERSION) } - override fun onCharacteristicWrite(gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - status: Int) { + override fun onCharacteristicWrite( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + status: Int + ) { Timber.d("onCharacteristicWrite; characteristic = ${characteristic.uuid}, sendCommand = $sendCommand, status = $status") Timber.d("Raw data = ${Arrays.toString(characteristic.value)}") if (status == BluetoothGatt.GATT_SUCCESS) { when (sendCommand) { BoardCommand.Send.SSID -> writeCommand( - BoardCommand.Send.SECURITY_TYPE, clickedAccessPoint?.securityMode?.value?.toString()!!) + BoardCommand.Send.SECURITY_TYPE, + clickedAccessPoint?.securityMode?.value?.toString()!! + ) + BoardCommand.Send.DISCONNECTION -> readOperation() BoardCommand.Send.SECURITY_TYPE -> { if (clickedAccessPoint?.password!!.isNotEmpty()) { @@ -278,33 +293,40 @@ class WifiCommissioningActivity : BaseDemoActivity() { readOperation() } } + BoardCommand.Send.PASSWORD -> { sendCommand = BoardCommand.Send.SSID readOperation() } + BoardCommand.Send.CHECK_CONNECTION -> { sendCommand = BoardCommand.Send.CHECK_CONNECTION readOperation() } + BoardCommand.Send.GET_FIRMWARE_VERSION -> { sendCommand = BoardCommand.Send.GET_FIRMWARE_VERSION readOperation() } - else -> { } + + else -> {} } } } - override fun onCharacteristicRead(gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - status: Int) { + override fun onCharacteristicRead( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + status: Int + ) { Timber.d("onCharacteristicRead; characteristic = ${characteristic.uuid}, readCommand = $readCommand, status = $status") Timber.d("Raw data = ${Arrays.toString(characteristic.value)}") if (status == BluetoothGatt.GATT_SUCCESS) { readCommand = BoardCommand.Response.fromInt( - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) ) - val statusBit = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1) + val statusBit = + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1) if (readCommand.value != sendCommand.value) { readOperation() @@ -312,21 +334,49 @@ class WifiCommissioningActivity : BaseDemoActivity() { when (readCommand) { BoardCommand.Response.CONNECTION -> { if (statusBit == 1) { - clickedAccessPoint?.macAddress = convertMacAddressToString(characteristic.value.copyOfRange(3, 9)) - clickedAccessPoint?.ipAddress = convertIpAddressToString(characteristic.value.copyOfRange(10, 14)) + clickedAccessPoint?.macAddress = convertMacAddressToString( + characteristic.value.copyOfRange( + 3, + 9 + ) + ) + clickedAccessPoint?.ipAddress = convertIpAddressToString( + characteristic.value.copyOfRange( + 10, + 14 + ) + ) onAccessPointConnection(true) } else { onAccessPointConnection(false) } } + BoardCommand.Response.DISCONNECTION -> onAccessPointDisconnection(statusBit == 1) BoardCommand.Response.CHECK_CONNECTION -> isAccessPointConnected(statusBit == 1) BoardCommand.Response.FIRMWARE_VERSION -> { + + val bytes: ByteArray = characteristic.value if (statusBit > 0) { - val rawString = characteristic.getStringValue(2) - onFirmwareVersionReceived(rawString.replace(unprintableCharsRegex, "")) + val firmareVersionString = buildString { + for ((index, byte) in bytes.sliceArray(FIRMWARE_BYTE_START_INDEX until FIRMWARE_BYTE_END_INDEX) + .withIndex()) { + if (index < 2) { + append( + byte.toUByte().toString(RADIX_HEX) + .padStart(PADDING_LENGTH, '0') + ) // Convert byte to hexadecimal string + } else if (index != 7) { + append(".${byte.toUByte()}") // Append byte value with a dot separator + } + } + } + onFirmwareVersionReceived(firmareVersionString) } + + } + BoardCommand.Response.UNKNOWN -> { if (sendCommand != BoardCommand.Send.SSID) readOperation() } @@ -335,20 +385,26 @@ class WifiCommissioningActivity : BaseDemoActivity() { } } - override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { + override fun onCharacteristicChanged( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic + ) { Timber.d("onCharacteristicChanged; characteristic = ${characteristic.uuid}") Timber.d("Raw data = ${Arrays.toString(characteristic.value)}") if (characteristic.uuid == GattCharacteristic.WifiCommissioningNotify.uuid) { /* Scanned access point info. */ val rawName = characteristic.getStringValue(2) - val rawSecurityMode = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + val rawSecurityMode = + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) Timber.d("Raw access point name = $rawName") - onAccessPointScanned(AccessPoint( + onAccessPointScanned( + AccessPoint( name = rawName.replace(unprintableCharsRegex, ""), - securityMode = SecurityMode.fromInt(rawSecurityMode) - )) + securityMode = SecurityMode.fromInt(rawSecurityMode) + ) + ) } } } @@ -382,7 +438,11 @@ class WifiCommissioningActivity : BaseDemoActivity() { }.start() } - private fun writeToCharacteristic(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, data: String): Boolean { + private fun writeToCharacteristic( + gatt: BluetoothGatt?, + characteristic: BluetoothGattCharacteristic?, + data: String + ): Boolean { return if (gatt != null && characteristic != null) { Timber.d("Data to write = $data") if (data.length > 100) { @@ -404,7 +464,7 @@ class WifiCommissioningActivity : BaseDemoActivity() { }.start() } - private fun convertMacAddressToString(rawData: ByteArray) : String { + private fun convertMacAddressToString(rawData: ByteArray): String { return StringBuilder().apply { rawData.forEachIndexed { index, byte -> val hexValue = Integer.toHexString(Converters.getIntFromTwosComplement(byte)) @@ -416,7 +476,7 @@ class WifiCommissioningActivity : BaseDemoActivity() { }.toString() } - private fun convertIpAddressToString(rawData: ByteArray) : String { + private fun convertIpAddressToString(rawData: ByteArray): String { return StringBuilder().apply { rawData.forEachIndexed { index, byte -> append(Converters.getIntFromTwosComplement(byte)) @@ -424,5 +484,12 @@ class WifiCommissioningActivity : BaseDemoActivity() { } }.toString() } + + companion object { + private const val RADIX_HEX = 16 + private const val PADDING_LENGTH = 2 + private const val FIRMWARE_BYTE_START_INDEX = 2 + private const val FIRMWARE_BYTE_END_INDEX = 11 + } } \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt index 76c8b342..49ed5d65 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/activities/IOPTestActivity.kt @@ -17,6 +17,7 @@ package com.siliconlabs.bledemo.features.iop_test.activities import android.annotation.SuppressLint +import android.app.Activity import android.app.Dialog import android.bluetooth.* import android.bluetooth.le.BluetoothLeScanner @@ -27,6 +28,9 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.net.Uri import android.os.* import android.text.TextUtils import android.util.Log @@ -40,12 +44,14 @@ import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.startActivity import androidx.core.content.FileProvider import androidx.core.view.get +import androidx.lifecycle.lifecycleScope +import com.siliconlabs.bledemo.R import com.siliconlabs.bledemo.bluetooth.ble.GattCharacteristic import com.siliconlabs.bledemo.bluetooth.ble.GattService import com.siliconlabs.bledemo.bluetooth.ble.TimeoutGattCallback import com.siliconlabs.bledemo.bluetooth.services.BluetoothService +import com.siliconlabs.bledemo.databinding.DialogShareIopLogBinding import com.siliconlabs.bledemo.features.scan.browser.dialogs.OtaLoadingDialog -import com.siliconlabs.bledemo.R import com.siliconlabs.bledemo.features.iop_test.fragments.IOPTestFragment import com.siliconlabs.bledemo.features.iop_test.fragments.IOPTestFragment.Companion.newInstance import com.siliconlabs.bledemo.features.iop_test.models.* @@ -63,6 +69,11 @@ import com.siliconlabs.bledemo.utils.Converters import com.siliconlabs.bledemo.utils.Notifications import com.siliconlabs.bledemo.utils.UuidConsts import kotlinx.android.synthetic.main.activity_iop_test.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber import java.io.* import java.text.SimpleDateFormat @@ -73,6 +84,10 @@ import kotlin.math.floor @SuppressLint("LogNotTimber", "MissingPermission") class IOPTestActivity : AppCompatActivity() { + private val SAVE_LOG_REQUEST_CODE = 123 + private var isLogcatData: Boolean = false + private var logs: String = "" + private var reconnectTimer: Timer? = Timer() private var handler: Handler? = null @@ -803,15 +818,18 @@ class IOPTestActivity : AppCompatActivity() { mBluetoothBinding?.bind() } - private fun saveLogFile() { - Executors.newSingleThreadExecutor().execute { - val file = saveDataTestToFile(getPathOfLogFile()) - handler?.post { - shareLogDataTestByEmail(file.absolutePath) - } + + private fun saveLogcatFile() { + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = "text/plain" // MIME type of the file you want to save + putExtra(Intent.EXTRA_TITLE, getPathOfLogFile()) } + startActivityForResult(intent, SAVE_LOG_REQUEST_CODE) } + + private fun startTest() { isTestRunning = true isTestFinished = false @@ -855,7 +873,6 @@ class IOPTestActivity : AppCompatActivity() { shareMenuItem?.isVisible = false } } - private fun removeBond(device: BluetoothDevice): Boolean { return try { return device::class.java.getMethod("removeBond").invoke(device) as Boolean @@ -865,6 +882,7 @@ class IOPTestActivity : AppCompatActivity() { } + /** * Show information device test and progress test item */ @@ -968,6 +986,29 @@ class IOPTestActivity : AppCompatActivity() { checkBluetoothExtendedSettings() registerBroadcastReceivers() handleClickEvents() + startLogCapture() + } + + private fun startLogCapture() { + lifecycleScope.launch(Dispatchers.IO) { + captureContinuousLogcat("IOPTest").collect { logLine -> + withContext(Dispatchers.Main) { + logs += logLine + "\n" + } + } + } + + } + + fun captureContinuousLogcat(tag: String): Flow = flow { + val process = Runtime.getRuntime().exec("logcat -s $tag") + val bufferedReader = BufferedReader(InputStreamReader(process.inputStream)) + + bufferedReader.useLines { lines -> + lines.forEach { line -> + emit(line) + } + } } private fun checkIfBluetoothIsSupported() { @@ -988,11 +1029,36 @@ class IOPTestActivity : AppCompatActivity() { } return true } + private fun showCustomDialog() { + val dialog = Dialog(this) + val dialogBinding: DialogShareIopLogBinding = DialogShareIopLogBinding.inflate(layoutInflater) + dialog.setContentView(dialogBinding.root) + dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + dialog.setCancelable(true) + + dialogBinding.tvTestLog.setOnClickListener { + isLogcatData = false + //saveLogFile() + saveLogcatFile() + dialog.dismiss() + } + + dialogBinding.tvAppLog.setOnClickListener { + isLogcatData = true + saveLogcatFile() + dialog.dismiss() + } + + dialogBinding.shareLogCancel.setOnClickListener { + dialog.dismiss() + } + dialog.show() + } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.iop_share -> { - saveLogFile() + showCustomDialog() true } @@ -1139,8 +1205,45 @@ class IOPTestActivity : AppCompatActivity() { Toast.LENGTH_SHORT ).show() } + + SAVE_LOG_REQUEST_CODE -> { + if (resultCode == Activity.RESULT_OK) { + intent?.data?.let { uri -> + Executors.newSingleThreadExecutor().execute { + val file = saveDataLogcatDataToFile(uri) + handler?.post { + shareLogDataTestByEmail(uri) + } + } + } ?: run { + Toast.makeText(this, getString(R.string.chosen_file_not_found), Toast.LENGTH_SHORT).show() + } + } + } } } + /** + * Save log data into File + */ + private fun saveDataLogcatDataToFile(uri: Uri): File { + val contentResolver = applicationContext.contentResolver + val outputStream = contentResolver.openOutputStream(uri) + outputStream?.use { fOut -> + OutputStreamWriter(fOut).use { myOutWriter -> + if (isLogcatData){ + myOutWriter.write(logs + "\n" + getDataLog()) + }else{ + myOutWriter.write( getDataLog()) + } + + + } + } ?: throw IOException("Failed to open output stream") + + return File(uri.path ?: throw IOException("File path not available from URI")) + + + } /** * Enable indicate by characteristics @@ -1585,56 +1688,22 @@ class IOPTestActivity : AppCompatActivity() { val boardName = getSiliconLabsTestInfo().iopBoard.icName.text val pathFile = getSiliconLabsTestInfo().phoneName pathFile.replace(" ", "") - return pathFile + "_" + boardName + "_" + getDate() + ".txt" - } + if (isLogcatData) { + return "logcat"+"_" + getDate("EEE MMM dd HH_mm_ss z yyyy") + ".txt" - /** - * Save log data into File - */ - private fun saveDataTestToFile(pathFileOfLog: String?): File { - val path = getExternalFilesDir(null)?.absolutePath + File.separator + FOLDER_NAME - val folder = File(path) - if (!folder.exists()) { - folder.mkdirs() - } - val file = File(folder, pathFileOfLog) - if (file.exists()) { - file.delete() - } - try { - file.createNewFile() - var fOut: FileOutputStream? = null - try { - fOut = FileOutputStream(file) - var myOutWriter: OutputStreamWriter? = null - try { - myOutWriter = OutputStreamWriter(fOut) - myOutWriter.write(getDataLog()) - } catch (e: Exception) { - Log.e( - TAG, - e.localizedMessage ?: "saveDataTestToFile(), OutputStreamWriter exception" - ) - } finally { - myOutWriter?.close() - } - fOut.flush() - } catch (e: Exception) { - Log.e(TAG, e.localizedMessage ?: "saveDataTestToFile(), FileOutputStream exception") - } finally { - fOut?.close() - } - } catch (e: IOException) { - Log.e("Exception", "File write failed: $e") + } else { + return pathFile + "_" + boardName + "_" + getDate("yyyy_MM_dd_HH_mm_ss") + ".txt" } - return file } + + + /** * Get Date currently */ - private fun getDate(): String { - return SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.getDefault()).format(Date()) + private fun getDate(format: String): String { + return SimpleDateFormat(format, Locale.getDefault()).format(Date()) } /** @@ -1643,18 +1712,17 @@ class IOPTestActivity : AppCompatActivity() { private fun getDataLog(): String { return getSiliconLabsTestInfo().toString() } - - private fun shareLogDataTestByEmail(fileLocation: String) { + private fun shareLogDataTestByEmail(uri: Uri) { try { - val uri = FileProvider.getUriForFile( - this, - applicationContext.packageName + ".provider", - File(fileLocation) - ) val message = "Please check the attachment to get the log file." val intent = Intent(Intent.ACTION_SEND).apply { type = "text/plain" - putExtra(Intent.EXTRA_SUBJECT, "[Silabs] Test log") + if (isLogcatData){ + putExtra(Intent.EXTRA_SUBJECT, "[Silabs] Application Debug log") + }else{ + putExtra(Intent.EXTRA_SUBJECT, "[Silabs] Test log") + } + putExtra(Intent.EXTRA_STREAM, uri) putExtra(Intent.EXTRA_TEXT, message) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) @@ -1666,6 +1734,8 @@ class IOPTestActivity : AppCompatActivity() { } } + + /** * Perform the test by item test case */ @@ -2010,6 +2080,7 @@ class IOPTestActivity : AppCompatActivity() { when (step) { // write CCCD to different value from the default 3 -> { + Log.d(TAG,"CASE 3: iopPhase3RunTestCaseBonding"+ "Write value 0x00 to CCCD") CCCD_value[0] = 1 iopPhase3ExtraDescriptor?.setValue(CCCD_value) mBluetoothGatt?.writeDescriptor(iopPhase3ExtraDescriptor) @@ -2020,25 +2091,21 @@ class IOPTestActivity : AppCompatActivity() { // disconnect 4 -> { + Log.d(TAG,"CASE 4: iopPhase3RunTestCaseBonding"+ "disconnect") disconnectGatt(mBluetoothGatt) - // reconnect(4000) - //connectToDevice(mBluetoothDevice) - /* writeValueToCharacteristic( - characteristicIOPPhase3Control, - null, - iopPhase3WriteControlBytes(0, 4, 0)) - Log.d("iopPhase3RunTestCaseBonding", "Set Control Characteristic for Security")*/ - } + } 6 -> { mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor) - Log.d("CASE 6: iopPhase3RunTestCaseBonding", "read CCCD:" + read_CCCD_value[0]) + Log.d(TAG,"CASE 6: iopPhase3RunTestCaseBonding"+ "read CCCD:" + read_CCCD_value[0]) // Mobile read CCCD. (Pass: if the CCCD value is the same as the value written before bond ). if (read_CCCD_value[0].toInt() == 1) { + isCCCDPass=true } else { - updateDataTestFailed(POSITION_TEST_IOP3_SECURITY) isCCCDPass = false + updateDataTestFailed(POSITION_TEST_IOP3_SECURITY) + finishItemTest( POSITION_TEST_IOP3_SECURITY, getSiliconLabsTestInfo().listItemTest[POSITION_TEST_IOP3_SECURITY] @@ -2048,7 +2115,7 @@ class IOPTestActivity : AppCompatActivity() { // Mobile write value 0xBB (0xBB or 0x00) to CCCD. (Pass: if the CCCD value was written in last step). 7 -> { - Log.d("CASE 7: iopPhase3RunTestCaseBonding", "Write value 0x00 to CCCD") + Log.d(TAG,"CASE 7: iopPhase3RunTestCaseBonding"+ "Write value 0x00 to CCCD") CCCD_value[0] = 0 iopPhase3ExtraDescriptor?.setValue(CCCD_value) mBluetoothGatt?.writeDescriptor(iopPhase3ExtraDescriptor) @@ -2057,9 +2124,10 @@ class IOPTestActivity : AppCompatActivity() { 8 -> { mBluetoothGatt?.readDescriptor(iopPhase3ExtraDescriptor) read_CCCD_value = iopPhase3ExtraDescriptor?.getValue()!!.copyOf() - Log.d("CASE 8: iopPhase3RunTestCaseBonding", "read CCCD:" + read_CCCD_value[0]) + Log.d(TAG,"CASE 8: iopPhase3RunTestCaseBonding"+ "read CCCD:" + read_CCCD_value[0]) // Mobile read CCCD. (Pass: if the CCCD value is the same as the value written before bond ). if (read_CCCD_value[0].toInt() == 0) { + isCCCDPass = true } else { isCCCDPass = false updateDataTestFailed(POSITION_TEST_IOP3_SECURITY) @@ -2327,6 +2395,8 @@ class IOPTestActivity : AppCompatActivity() { } + + private val iopCachingRunnable = Runnable { Log.d(TAG, "iopCachingRunnable") iopCachingFailed() diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt index bb604e32..82126dc5 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/DemoItemProvider.kt @@ -16,6 +16,7 @@ class DemoItemProvider { add(ItemTestCaseInfo(7, "Throughput", "Throughput-GATT Notification.", null, Common.IOP3_TC_STATUS_WAITING)) add(ItemTestCaseInfo(8, "Security and Encryption", "Security and Encryption.", dataChildrenSecurity(), Common.IOP3_TC_STATUS_WAITING)) add(ItemTestCaseInfo(9, "LE Privacy", "LE Privacy.",null, Common.IOP3_TC_STATUS_WAITING)) + /* This test should remain hidden for now due to investigation being underway. It may return later. add(ItemTestCaseInfo(9, "GATT Caching", "GATT Caching.", dataChildrenCaching(), Common.IOP3_TC_STATUS_WAITING)) */ diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt index 299bc1e7..ff7749bc 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/features/iop_test/models/SiliconLabsTestInfo.kt @@ -46,7 +46,6 @@ class SiliconLabsTestInfo(var fwName: String, val listItemTest: ArrayList= 11 -> append(itemTest.idTest + 1) itemTest.idTest == 8 -> append(7) - itemTest.idTest == 9 -> append(7) else -> append(itemTest.idTest) } append(".") @@ -75,7 +74,7 @@ class SiliconLabsTestInfo(var fwName: String, val listItemTest: ArrayList launchDemo(characteristic.getStringValue(0)) GattConnectType.BLINKY -> { when (characteristic.getStringValue(0)) { + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3, ThunderBoardDevice.THUNDERBOARD_MODEL_SENSE, ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V1, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2, - ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V3 -> { + ThunderBoardDevice.THUNDERBOARD_MODEL_DEV_KIT_V2 -> { connectType = GattConnectType.BLINKY_THUNDERBOARD cachedBoardType = characteristic.getStringValue(0) gatt?.readCharacteristic(getPowerSourceCharacteristic(gatt)) @@ -158,7 +158,7 @@ class SelectDeviceDialog( when (connectType) { GattConnectType.MOTION -> setReadingDialogMsgAndDiscoverServices(gatt) GattConnectType.BLINKY -> { - if (gatt.device.name == getString(R.string.blinky_service_name)) launchDemo() + if (gatt.device.name.startsWith(getString(R.string.blinky_service_name))) launchDemo() else setReadingDialogMsgAndDiscoverServices(gatt) } @@ -436,10 +436,10 @@ class SelectDeviceDialog( add(buildFilter(GattService.RangeTestService)) } - GattConnectType.BLINKY -> { + /*GattConnectType.BLINKY -> { add(buildFilter(BuildFilterName.BLINKY)) add(buildFilter(manufacturerDataFilter)) - } + }*/ GattConnectType.THROUGHPUT_TEST -> { add(buildFilter(BuildFilterName.THROUGHPUT_TEST)) @@ -535,7 +535,7 @@ class SelectDeviceDialog( } override fun handleScanResult(scanResult: ScanResultCompat) { - viewModel.handleScanResult(scanResult) + viewModel.handleScanResult(scanResult,connectType,context) } override fun onDiscoveryFailed() { diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/DemoFragment.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/DemoFragment.kt index f3b3546d..9828a242 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/DemoFragment.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/fragments/DemoFragment.kt @@ -19,6 +19,7 @@ import by.kirich1409.viewbindingdelegate.viewBinding import com.siliconlabs.bledemo.R import com.siliconlabs.bledemo.bluetooth.services.BluetoothService import com.siliconlabs.bledemo.databinding.FragmentDemoBinding +import com.siliconlabs.bledemo.features.demo.devkitsensor917.activities.DevKitSensor917Activity import com.siliconlabs.bledemo.features.demo.matter_demo.activities.MatterDemoActivity import com.siliconlabs.bledemo.features.demo.range_test.activities.RangeTestActivity import com.siliconlabs.bledemo.features.demo.wifi_ota_update.AlertErrorDialog @@ -33,6 +34,7 @@ import com.siliconlabs.bledemo.home_screen.dialogs.SelectDeviceDialog import com.siliconlabs.bledemo.home_screen.menu_items.Blinky import com.siliconlabs.bledemo.home_screen.menu_items.ConnectedLighting import com.siliconlabs.bledemo.home_screen.menu_items.DemoMenuItem +import com.siliconlabs.bledemo.home_screen.menu_items.DevKitSensorDemo import com.siliconlabs.bledemo.home_screen.menu_items.Environment import com.siliconlabs.bledemo.home_screen.menu_items.EslDemo import com.siliconlabs.bledemo.home_screen.menu_items.HealthThermometer @@ -70,8 +72,8 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI private var otaFileSelectionDialog: WiFiOtaFileSelectionDialog? = null private var otaFileManager: WiFiOtaFileManager? = null private var otaFilePath: Uri? = null - private var socket : Socket? = null - private var serverSocket : ServerSocket? = null + private var socket: Socket? = null + private var serverSocket: ServerSocket? = null private var portId = 8080 private var isClientConnected = false private val kBits = "%.2f Kbit/s" @@ -158,7 +160,14 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI OTADemo( R.drawable.redesign_ic_demo_ota, getString(R.string.ota_demo_title), - getString(R.string.ota_demo_desc) + getString(R.string.ota_demo_title_desc) + ) + ) + add( + DevKitSensorDemo( + R.drawable.redesign_ic_demo_dks_917, + getString(R.string.dev_kit_sensor_917_title), + getString(R.string.dev_kit_sensor_917_desc) ) ) } @@ -230,28 +239,45 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI } override fun onDemoItemClicked(demoItem: DemoMenuItem) { - if (demoItem.connectType == BluetoothService.GattConnectType.MATTER_DEMO) { + if (demoItem.connectType == BluetoothService.GattConnectType.DEV_KIT_SENSOR) { + if (isNetworkAvailable(context)) { + requireContext().startActivity( + Intent( + requireContext(), + DevKitSensor917Activity::class.java + ) + ) + }else{ + Toast.makeText( + requireContext(), + getString(R.string.turn_on_wifi), + Toast.LENGTH_SHORT + ).show() + } + } else if (demoItem.connectType == BluetoothService.GattConnectType.MATTER_DEMO) { requireContext().startActivity(Intent(requireContext(), MatterDemoActivity::class.java)) } else if (demoItem.connectType == BluetoothService.GattConnectType.RANGE_TEST) { startActivity(Intent(requireContext(), RangeTestActivity::class.java)) } else if (demoItem.connectType == BluetoothService.GattConnectType.WIFI_OTA_UPDATE) { - if (isNetworkAvailable(context)) { - otaFileSelectionDialog = WiFiOtaFileSelectionDialog(object : WiFiOtaFileSelectionDialog.CancelCallback { + if (isNetworkAvailable(context)) { + otaFileSelectionDialog = WiFiOtaFileSelectionDialog( + object : WiFiOtaFileSelectionDialog.CancelCallback { override fun onDismiss() { otaFileSelectionDialog?.dismiss() - }}, - listener = fileSelectionListener, - getLocalIpAddress() - ).also { - it.show(childFragmentManager, "ota_file_selection_dialog") - } - } else { - Toast.makeText( - requireContext(), - getString(R.string.turn_on_wifi), - Toast.LENGTH_SHORT - ).show() + } + }, + listener = fileSelectionListener, + getLocalIpAddress() + ).also { + it.show(childFragmentManager, "ota_file_selection_dialog") } + } else { + Toast.makeText( + requireContext(), + getString(R.string.turn_on_wifi), + Toast.LENGTH_SHORT + ).show() + } } else { selectDeviceDialog = SelectDeviceDialog.newDialog(demoItem.connectType) selectDeviceDialog?.show(childFragmentManager, "select_device_dialog") @@ -275,9 +301,11 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI private fun isNetworkAvailable(context: Context?): Boolean { if (context == null) return false - val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + val capabilities = + connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) if (capabilities != null) { when { capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> { @@ -293,28 +321,46 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI } return false } + private val fileSelectionListener = object : WiFiOtaFileSelectionDialog.FileSelectionListener { override fun onSelectFileButtonClicked() { otaFileSelectionDialog?.disableUploadButton() Intent(Intent.ACTION_GET_CONTENT) .apply { type = "*/*" } - .also { startActivityForResult(Intent.createChooser(it, - getString(R.string.ota_choose_file)), - RPS_FILE_CHOICE_REQUEST_CODE - ) } + .also { + startActivityForResult( + Intent.createChooser( + it, + getString(R.string.ota_choose_file) + ), + RPS_FILE_CHOICE_REQUEST_CODE + ) + } } override fun onOtaButtonClicked() { - if(otaFileSelectionDialog?.checkPortNumberValid() == true){ + if (otaFileSelectionDialog?.checkPortNumberValid() == true) { otaFileManager?.otaFile?.let { startOtaProcess() } ?: if (otaFileManager?.otaFilename != null) { - Toast.makeText(requireContext(), getString(R.string.incorrect_file), Toast.LENGTH_SHORT).show() + Toast.makeText( + requireContext(), + getString(R.string.incorrect_file), + Toast.LENGTH_SHORT + ).show() } else { - Toast.makeText(requireContext(), getString(R.string.no_file_chosen), Toast.LENGTH_SHORT).show() + Toast.makeText( + requireContext(), + getString(R.string.no_file_chosen), + Toast.LENGTH_SHORT + ).show() } } else { - Toast.makeText(requireContext(), getString(R.string.port_id_validation), Toast.LENGTH_SHORT).show() + Toast.makeText( + requireContext(), + getString(R.string.port_id_validation), + Toast.LENGTH_SHORT + ).show() } } @@ -349,10 +395,20 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI otaProgressDialog?.steps?.visibility = View.INVISIBLE otaProgressDialog?.uploadImage?.visibility = View.VISIBLE // otaProgressDialog?.btnOtaEnd?.isEnabled = false - otaProgressDialog?.btnOtaEnd?.setBackgroundColor(getColor(requireContext(),R.color.silabs_red)) + otaProgressDialog?.btnOtaEnd?.setBackgroundColor( + getColor( + requireContext(), + R.color.silabs_red + ) + ) otaProgressDialog?.btnOtaEnd?.text = getString(R.string.button_cancel) otaProgressDialog?.firmwareStatus?.text = getString(R.string.waiting_for_client_to_connect) - otaProgressDialog?.firmwareStatus?.setTextColor(getColor(requireContext(),R.color.silabs_dark_blue)) + otaProgressDialog?.firmwareStatus?.setTextColor( + getColor( + requireContext(), + R.color.silabs_dark_blue + ) + ) } private fun showOtaProgressDialog() { @@ -362,8 +418,13 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI private fun startOtaProcess() { activity?.runOnUiThread { showOtaProgressDialog() - portId = Integer.parseInt(otaFileSelectionDialog?.getPortId()) - otaProgressDialog?.setProgressInfo(otaFileManager?.otaFilename, otaFileManager?.otaFile?.size, getLocalIpAddress() ,portId.toString()) + portId = Integer.parseInt(otaFileSelectionDialog?.getPortId()) + otaProgressDialog?.setProgressInfo( + otaFileManager?.otaFilename, + otaFileManager?.otaFile?.size, + getLocalIpAddress(), + portId.toString() + ) animateLoading() } @@ -403,14 +464,14 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI private fun showTimeOutAlertDialog() { activity?.runOnUiThread { - alertErrorDialog = AlertErrorDialog( object : AlertErrorDialog.OtaErrorCallback { - override fun onDismiss() { - initializeToDefaultValues() - otaProgressDialog?.dismiss() - socket?.close() - serverSocket?.close() - } - }) + alertErrorDialog = AlertErrorDialog(object : AlertErrorDialog.OtaErrorCallback { + override fun onDismiss() { + initializeToDefaultValues() + otaProgressDialog?.dismiss() + socket?.close() + serverSocket?.close() + } + }) alertErrorDialog?.show(childFragmentManager, "error_dialog") } @@ -468,7 +529,8 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI var length = 0 val outputStream = socket!!.getOutputStream() val inputStream = socket!!.getInputStream() - val totalPackets = Integer.parseInt(otaFileManager?.otaFile?.size?.div(1024).toString())+1 + val totalPackets = + Integer.parseInt(otaFileManager?.otaFile?.size?.div(1024).toString()) + 1 while (true) { retLen = inputStream.read(data, 0, 3) if (retLen > 0) { @@ -513,7 +575,7 @@ class DemoFragment : BaseServiceDependentMainMenuFragment(), DemoAdapter.OnDemoI //Update the Progress Dialog UI updateProgressDialog(ctr++, totalPackets) packetCount = ctr - if(ctr> = MutableLiveData(mutableMapOf()) + private val _scannedDevices: MutableLiveData> = + MutableLiveData(mutableMapOf()) val scannedDevices: LiveData> = _scannedDevices private val _deviceToInsert: MutableLiveData = MutableLiveData() val deviceToInsert: LiveData = _deviceToInsert private val _numberOfDevices: MutableLiveData = MutableLiveData(0) val numberOfDevices: LiveData = _numberOfDevices - override fun handleScanResult(result: ScanResultCompat) { + override fun handleScanResult( + result: ScanResultCompat, + connectType: BluetoothService.GattConnectType?, + context: Context? + ) { + val manufacturerDataFilter = ManufacturerDataFilter( + id = 71, + data = byteArrayOf(2, 0) + ) + synchronized(_scannedDevices) { - _scannedDevices.value?.apply { - val address = result.device?.address!! - val isNewDevice = !keys.contains(address) + val deviceName = result.device?.name + var shouldAddDevice = true + if (deviceName == null) { + shouldAddDevice = false + } - getOrPut(address, { BluetoothDeviceInfo(result.device!!)}).also { - updateScanInfo(it, result) + if (connectType != null && connectType == BluetoothService.GattConnectType.BLINKY) { + if (deviceName != null) { + if (context != null) { + if (!deviceName.startsWith(context.getString(R.string.blinky_service_name),ignoreCase = true) + && !matchesManufacturerData(result, manufacturerDataFilter)) { + shouldAddDevice = false + } + } } + } + if (shouldAddDevice) { + _scannedDevices.value?.apply { + val address = result.device?.address!! + val isNewDevice = !keys.contains(address) + + getOrPut(address, { BluetoothDeviceInfo(result.device!!) }).also { + updateScanInfo(it, result) + } - if (isNewDevice) { - _deviceToInsert.value = this[address] - _numberOfDevices.value = size + if (isNewDevice) { + _deviceToInsert.value = this[address] + _numberOfDevices.value = size + } } } _isAnyDeviceDiscovered.value = _scannedDevices.value?.isNotEmpty() ?: false } + + } fun clearDevices() { @@ -44,4 +78,9 @@ class SelectDeviceViewModel : ScannerViewModel() { return _scannedDevices.value?.values?.toList() ?: listOf() } + fun matchesManufacturerData(result: ScanResultCompat, filter: ManufacturerDataFilter): Boolean { + val manufacturerData = result.scanRecord?.getManufacturerSpecificData(filter.id) + return manufacturerData != null && manufacturerData.contentEquals(filter.data) + } + } \ No newline at end of file diff --git a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/BluetoothEnableBar.kt b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/BluetoothEnableBar.kt index d6ea833f..df421a54 100644 --- a/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/BluetoothEnableBar.kt +++ b/mobile/src/main/java/com/siliconlabs/bledemo/home_screen/views/BluetoothEnableBar.kt @@ -1,14 +1,18 @@ package com.siliconlabs.bledemo.home_screen.views import android.annotation.SuppressLint +import android.app.Activity import android.bluetooth.BluetoothAdapter import android.content.Context import android.content.Intent -import android.os.Handler -import android.os.Looper +import android.provider.Settings import android.util.AttributeSet import android.view.View +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import com.siliconlabs.bledemo.R +import android.os.Handler +import android.os.Looper class BluetoothEnableBar(context: Context, attrs: AttributeSet?) : NoServiceWarningBar(context, attrs) { @@ -45,8 +49,7 @@ class BluetoothEnableBar(context: Context, attrs: AttributeSet?) : val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() // Add a delay to check if Bluetooth is on after enabling Handler(Looper.getMainLooper()).postDelayed({ - warningBarMessage.text = - context.getString(R.string.bluetooth_adapter_bar_turning_on) + warningBarMessage.text = context.getString(R.string.bluetooth_adapter_bar_turning_on) if (bluetoothAdapter.isEnabled) { // Bluetooth is on // Display message or perform actions here @@ -58,8 +61,7 @@ class BluetoothEnableBar(context: Context, attrs: AttributeSet?) : // Bluetooth is still off // Display message or perform actions here _binding.apply { - warningBarMessage.text = - context.getString(R.string.bluetooth_adapter_bar_disabled) + warningBarMessage.text = context.getString(R.string.bluetooth_adapter_bar_disabled) warningBarActionButton.visibility = View.VISIBLE } } @@ -67,7 +69,8 @@ class BluetoothEnableBar(context: Context, attrs: AttributeSet?) : } } - companion object { + companion object{ private const val DELAY_CHECK_BLUETOOTH = 5000L } + } \ No newline at end of file diff --git a/mobile/src/main/res/drawable/btn_rounded_black.xml b/mobile/src/main/res/drawable/btn_rounded_black.xml new file mode 100644 index 00000000..c10f5cd3 --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_black.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/btn_rounded_blue.xml b/mobile/src/main/res/drawable/btn_rounded_blue.xml new file mode 100644 index 00000000..56cd2399 --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_blue.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/btn_rounded_blue_dev.xml b/mobile/src/main/res/drawable/btn_rounded_blue_dev.xml new file mode 100644 index 00000000..56cd2399 --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_blue_dev.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/btn_rounded_dark_blue.xml b/mobile/src/main/res/drawable/btn_rounded_dark_blue.xml new file mode 100644 index 00000000..f612da56 --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_dark_blue.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/btn_rounded_green.xml b/mobile/src/main/res/drawable/btn_rounded_green.xml new file mode 100644 index 00000000..4a6a835a --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_green.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/btn_rounded_red.xml b/mobile/src/main/res/drawable/btn_rounded_red.xml new file mode 100644 index 00000000..ca9749e0 --- /dev/null +++ b/mobile/src/main/res/drawable/btn_rounded_red.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/main/res/drawable/button_background_blue_box.xml b/mobile/src/main/res/drawable/button_background_blue_box.xml new file mode 100644 index 00000000..198fdf97 --- /dev/null +++ b/mobile/src/main/res/drawable/button_background_blue_box.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/button_background_green_box.xml b/mobile/src/main/res/drawable/button_background_green_box.xml new file mode 100644 index 00000000..ca5b3df2 --- /dev/null +++ b/mobile/src/main/res/drawable/button_background_green_box.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/button_background_grey_box.xml b/mobile/src/main/res/drawable/button_background_grey_box.xml new file mode 100644 index 00000000..5bd4cf46 --- /dev/null +++ b/mobile/src/main/res/drawable/button_background_grey_box.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/button_background_red_box.xml b/mobile/src/main/res/drawable/button_background_red_box.xml new file mode 100644 index 00000000..c5d44785 --- /dev/null +++ b/mobile/src/main/res/drawable/button_background_red_box.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/button_background_soft_black_box.xml b/mobile/src/main/res/drawable/button_background_soft_black_box.xml new file mode 100644 index 00000000..f65c2422 --- /dev/null +++ b/mobile/src/main/res/drawable/button_background_soft_black_box.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/icon_dks_917_led.xml b/mobile/src/main/res/drawable/icon_dks_917_led.xml new file mode 100644 index 00000000..69df3484 --- /dev/null +++ b/mobile/src/main/res/drawable/icon_dks_917_led.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/mobile/src/main/res/drawable/icon_dks_917_motion.xml b/mobile/src/main/res/drawable/icon_dks_917_motion.xml new file mode 100644 index 00000000..6277eca5 --- /dev/null +++ b/mobile/src/main/res/drawable/icon_dks_917_motion.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/mobile/src/main/res/drawable/motion_rounded_bg.xml b/mobile/src/main/res/drawable/motion_rounded_bg.xml index 79d4b70d..80e42592 100644 --- a/mobile/src/main/res/drawable/motion_rounded_bg.xml +++ b/mobile/src/main/res/drawable/motion_rounded_bg.xml @@ -3,10 +3,10 @@ - + - + diff --git a/mobile/src/main/res/drawable/redesign_ic_demo_dks_917.xml b/mobile/src/main/res/drawable/redesign_ic_demo_dks_917.xml new file mode 100644 index 00000000..92608658 --- /dev/null +++ b/mobile/src/main/res/drawable/redesign_ic_demo_dks_917.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/mobile/src/main/res/layout/activity_917_dev_kit_sensor_layout.xml b/mobile/src/main/res/layout/activity_917_dev_kit_sensor_layout.xml new file mode 100644 index 00000000..38e22c19 --- /dev/null +++ b/mobile/src/main/res/layout/activity_917_dev_kit_sensor_layout.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/layout/activity_matter_demo.xml b/mobile/src/main/res/layout/activity_matter_demo.xml index 35d6d6d7..427006b7 100644 --- a/mobile/src/main/res/layout/activity_matter_demo.xml +++ b/mobile/src/main/res/layout/activity_matter_demo.xml @@ -45,7 +45,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/layout/dev_kit_sesnor_917_led_control_dialog_layout.xml b/mobile/src/main/res/layout/dev_kit_sesnor_917_led_control_dialog_layout.xml new file mode 100644 index 00000000..67753a0e --- /dev/null +++ b/mobile/src/main/res/layout/dev_kit_sesnor_917_led_control_dialog_layout.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + +